From bd05cf149e803508405e26a3b335ab2595fea86d Mon Sep 17 00:00:00 2001 From: netcon Date: Wed, 12 Aug 2026 02:37:40 +0800 Subject: [PATCH] feat: fit resourceLabelFormatters (#716) --- .gitignore | 1 + extensions/github1s/package.json | 12 +++++----- .../github1s/src/providers/file-search.ts | 4 ++-- .../src/providers/file-system/index.ts | 6 ++--- extensions/github1s/src/router/authority.ts | 24 +++++++++++++++++++ extensions/github1s/src/router/index.ts | 10 ++++---- 6 files changed, 41 insertions(+), 16 deletions(-) create mode 100644 extensions/github1s/src/router/authority.ts diff --git a/.gitignore b/.gitignore index 9a28bffee..7f61e2ee3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ lib dist out node_modules +.worktrees/ diff --git a/extensions/github1s/package.json b/extensions/github1s/package.json index 927bdf563..6b1b26fcc 100644 --- a/extensions/github1s/package.json +++ b/extensions/github1s/package.json @@ -29,25 +29,25 @@ "resourceLabelFormatters": [ { "scheme": "github1s", - "authority": "**/*+?*", + "authority": "?*/**", "formatting": { - "label": "${path} (${authoritySuffix:7})", + "label": "${path} (${authoritySuffix})", "separator": "/" } }, { "scheme": "gitlab1s", - "authority": "**/*+?*", + "authority": "?*/**", "formatting": { - "label": "${path} (${authoritySuffix:7})", + "label": "${path} (${authoritySuffix})", "separator": "/" } }, { "scheme": "bitbucket1s", - "authority": "**/*+?*", + "authority": "?*/**", "formatting": { - "label": "${path} (${authoritySuffix:7})", + "label": "${path} (${authoritySuffix})", "separator": "/" } } diff --git a/extensions/github1s/src/providers/file-search.ts b/extensions/github1s/src/providers/file-search.ts index fd3ae75fa..2e651f109 100644 --- a/extensions/github1s/src/providers/file-search.ts +++ b/extensions/github1s/src/providers/file-search.ts @@ -57,7 +57,7 @@ export class GitHub1sFileSearchProvider implements FileSearchProvider, Disposabl */ getFileUris = reuseable(async (): Promise => { const { repo, ref } = router.getState(); - const cacheKey = `${repo}+${ref}`; + const cacheKey = `${repo}@${ref}`; if (this.fileUrisMap.has(cacheKey)) { return this.fileUrisMap.get(cacheKey)!; @@ -65,7 +65,7 @@ export class GitHub1sFileSearchProvider implements FileSearchProvider, Disposabl const dataSource = await getAdapter().resolveDataSource(); const rootDirectoryData = await dataSource.provideDirectory(repo, ref, '/', true); - const rootDirectoryUri = router.buildUri({ repo, ref, path: '/' }); + const rootDirectoryUri = router.buildUri({ path: '/' }); // the number of items in the tree array maybe exceeded maximum limit, only // insert the data to fileSystemProvider's cache if `treeData.truncated` is false diff --git a/extensions/github1s/src/providers/file-system/index.ts b/extensions/github1s/src/providers/file-system/index.ts index 508dc2f24..eb3f29f08 100644 --- a/extensions/github1s/src/providers/file-system/index.ts +++ b/extensions/github1s/src/providers/file-system/index.ts @@ -86,7 +86,7 @@ export class GitHub1sFileSystemProvider implements FileSystemProvider, Disposabl public async lookup(uri: Uri, silent: boolean): Promise { const parts = uri.path.split('/').filter(Boolean); const { scheme, repo, ref } = router.parseUri(uri); - const lookupKey = `${scheme}:${repo}+${ref}`; + const lookupKey = `${scheme}:${repo}@${ref}`; if (!this.root.has(lookupKey)) { this.root.set(lookupKey, createEntry(adapterTypes.FileType.Directory, uri.with({ path: '/' }), '')); } @@ -172,7 +172,7 @@ export class GitHub1sFileSystemProvider implements FileSystemProvider, Disposabl } const subRef = directory.sha || 'HEAD'; const [subScheme, subRepo] = await parseSubmoduleUrl(gitmoduleData.url); - const lookupKey = `${subScheme}:${subRepo}+${subRef}`; + const lookupKey = `${subScheme}:${subRepo}@${subRef}`; directory.name = ''; // update the name field to '' to indicated it is an root directory // update the uri field to indicated it is belong the `submodule repository` directory.uri = router.buildUri({ scheme: subScheme, repo: subRepo, ref: subRef, path: '/' }); @@ -215,7 +215,7 @@ export class GitHub1sFileSystemProvider implements FileSystemProvider, Disposabl uri = Uri.joinPath(file.uri, file.name); } const { scheme, repo, ref, path } = router.parseUri(uri); - const cacheKey = `${scheme}:${repo}+${ref}${path}`; + const cacheKey = `${scheme}:${repo}@${ref}${path}`; if (!this.contentCache.has(cacheKey)) { const dataSource = await getAdapter(scheme).resolveDataSource(); const data = await dataSource.provideFile(repo, ref, path); diff --git a/extensions/github1s/src/router/authority.ts b/extensions/github1s/src/router/authority.ts new file mode 100644 index 000000000..9472c0468 --- /dev/null +++ b/extensions/github1s/src/router/authority.ts @@ -0,0 +1,24 @@ +/** + * @file URI authority helpers + * @author netcon + */ + +export const buildAuthority = (repo: string, ref: string): string => { + // label is using for display in resourceLabelFormatters + const label = ref.length >= 32 ? ref.slice(0, 7) : ref; + return repo && ref ? `${repo}@${ref}+${label}` : ''; +}; + +export const parseAuthority = (authority: string): { repo: string; ref: string } | undefined => { + // repo name may starts with @, so we skip the first character + const atIndex = authority.slice(1).indexOf('@') + 1; + if (atIndex <= 0) { + // compatible with old format, remove in the future + const [repo, ref] = authority.split('+'); + return repo && ref ? { repo, ref } : undefined; + } + const repo = authority.slice(0, atIndex); + const plusIndex = authority.lastIndexOf('+'); + const ref = plusIndex > 0 ? authority.slice(atIndex + 1, plusIndex) : ''; + return repo && ref ? { repo, ref } : undefined; +}; diff --git a/extensions/github1s/src/router/index.ts b/extensions/github1s/src/router/index.ts index 9062c360f..432e9b342 100644 --- a/extensions/github1s/src/router/index.ts +++ b/extensions/github1s/src/router/index.ts @@ -7,6 +7,7 @@ import * as vscode from 'vscode'; import { getAdapter } from '@/adapters'; import { History, createMemoryHistory, parsePath, Action } from 'history'; import { RouterParser, RouterState } from '@/adapters/types'; +import { buildAuthority, parseAuthority } from './authority'; import { EventEmitter } from './events'; export interface UrlManager { @@ -93,9 +94,8 @@ export class Router extends EventEmitter { } public parseUri(uri: vscode.Uri): UriState { - const scheme = uri.scheme; - const [repo, ref] = uri.authority ? uri.authority.split('+') : [this._state!.repo, this._state!.ref]; - return { scheme, repo, ref, path: uri.path || '/' }; + const { repo, ref } = parseAuthority(uri.authority) || this._state!; + return { scheme: uri.scheme, repo, ref, path: uri.path || '/' }; } public buildUri(state?: Partial, base?: vscode.Uri): vscode.Uri { @@ -108,8 +108,8 @@ export class Router extends EventEmitter { throw new Error('ref is required when repo is provided'); } if (state?.hasOwnProperty('ref')) { - const repo = state.repo || base?.authority.split('+')[0] || this._state!.repo; - mergedState.authority = repo && state.ref ? `${repo}+${state.ref}` : ''; + const repo = state.repo || parseAuthority(base?.authority || '')?.repo || this._state!.repo; + mergedState.authority = buildAuthority(repo, state.ref || ''); } if (state?.hasOwnProperty('path')) { mergedState.path = `/${state.path?.split('/').filter(Boolean).join('/') || ''}`;