- import type { Uri } from 'vscode';
- import { isLinux } from '@env/platform';
- import { Schemes } from './constants';
- import type { Repository } from './git/models/repository';
- import { addVslsPrefixIfNeeded, normalizePath } from './system/path';
- import { UriTrie } from './system/trie';
- // TODO@eamodio don't import from string here since it will break the tests because of ESM dependencies
- // import { CharCode } from './string';
-
- const slash = 47; //CharCode.Slash;
-
- export type RepoComparisonKey = string & { __type__: 'RepoComparisonKey' };
-
- export function asRepoComparisonKey(uri: Uri): RepoComparisonKey {
- const { path } = normalizeRepoUri(uri);
- return path as RepoComparisonKey;
- }
-
- export function normalizeRepoUri(uri: Uri): { path: string; ignoreCase: boolean } {
- let path;
- switch (uri.scheme.toLowerCase()) {
- case Schemes.File:
- path = normalizePath(uri.fsPath);
- return { path: path, ignoreCase: !isLinux };
-
- case Schemes.Git:
- case Schemes.GitLens:
- path = uri.path;
- if (path.charCodeAt(path.length - 1) === slash) {
- path = path.slice(1, -1);
- } else {
- path = path.slice(1);
- }
- return { path: path, ignoreCase: !isLinux };
-
- case Schemes.Virtual:
- case Schemes.GitHub: {
- path = uri.path;
- if (path.charCodeAt(path.length - 1) === slash) {
- path = path.slice(1, -1);
- } else {
- path = path.slice(1);
- }
-
- // TODO@eamodio Revisit this, as we can't strip off the authority details (e.g. metadata) ultimately (since you in theory could have a workspace with more than 1 virtual repo which are the same except for the authority)
- const authority = uri.authority?.split('+', 1)[0];
- return { path: authority ? `${authority}/${path}` : path, ignoreCase: false };
- }
- case Schemes.Vsls:
- case Schemes.VslsScc:
- // Check if this is a root live share folder, if so add the required prefix (required to match repos correctly)
- path = addVslsPrefixIfNeeded(uri.path);
- if (path.charCodeAt(path.length - 1) === slash) {
- path = path.slice(1, -1);
- } else {
- path = path.slice(1);
- }
-
- return { path: path, ignoreCase: false };
-
- case Schemes.PRs: {
- path = uri.path;
- if (path.charCodeAt(path.length - 1) === slash) {
- path = path.slice(1, -1);
- } else {
- path = path.slice(1);
- }
-
- const authority = uri.authority?.split('+', 1)[0];
- if (authority === Schemes.GitHub) {
- return { path: authority ? `${authority}/${path}` : path, ignoreCase: false };
- }
-
- return { path: path, ignoreCase: !isLinux };
- }
- default:
- path = uri.path;
- if (path.charCodeAt(path.length - 1) === slash) {
- path = path.slice(1, -1);
- } else {
- path = path.slice(1);
- }
- return { path: path, ignoreCase: false };
- }
- }
-
- export class Repositories {
- private readonly _trie: UriTrie<Repository>;
- private _count: number = 0;
-
- constructor() {
- this._trie = new UriTrie<Repository>(normalizeRepoUri);
- }
-
- get count(): number {
- return this._count;
- }
-
- add(repository: Repository): boolean {
- const added = this._trie.set(repository.uri, repository);
- if (added) {
- this._count++;
- }
- return added;
- }
-
- clear(): void {
- this._count = 0;
- this._trie.clear();
- }
-
- forEach(fn: (repository: Repository) => void, thisArg?: unknown): void {
- for (const value of this._trie.getDescendants()) {
- fn.call(thisArg, value);
- }
- }
-
- get(uri: Uri): Repository | undefined {
- return this._trie.get(uri);
- }
-
- getClosest(uri: Uri): Repository | undefined {
- return this._trie.getClosest(uri);
- }
-
- has(uri: Uri): boolean {
- return this._trie.has(uri);
- }
-
- remove(uri: Uri, dispose: boolean = true): boolean {
- const deleted = this._trie.delete(uri, dispose);
- if (deleted) {
- this._count--;
- }
- return deleted;
- }
-
- values(): IterableIterator<Repository> {
- return this._trie.getDescendants();
- }
- }
|