mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-18 23:59:43 +01:00
Update git clone to use new repo cache (#272276)
This commit is contained in:
@@ -4,9 +4,21 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { LogOutputChannel, Memento, workspace } from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { LRUCache } from './cache';
|
||||
import { Remote } from './api/git';
|
||||
import { isDescendant } from './util';
|
||||
|
||||
export interface RepositoryCacheInfo {
|
||||
workspacePath: string; // path of the workspace folder or workspace file
|
||||
}
|
||||
|
||||
function isRepositoryCacheInfo(obj: unknown): obj is RepositoryCacheInfo {
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
return false;
|
||||
}
|
||||
const rec = obj as Record<string, unknown>;
|
||||
return typeof rec.workspacePath === 'string';
|
||||
}
|
||||
|
||||
export class RepositoryCache {
|
||||
|
||||
@@ -14,8 +26,8 @@ export class RepositoryCache {
|
||||
private static readonly MAX_REPO_ENTRIES = 30; // Max repositories tracked
|
||||
private static readonly MAX_FOLDER_ENTRIES = 10; // Max folders per repository
|
||||
|
||||
// Outer LRU: repoUrl -> inner LRU (folderPathOrWorkspaceFile -> true). Only keys matter.
|
||||
private readonly lru = new LRUCache<string, LRUCache<string, true>>(RepositoryCache.MAX_REPO_ENTRIES);
|
||||
// Outer LRU: repoUrl -> inner LRU (folderPathOrWorkspaceFile -> RepositoryCacheInfo).
|
||||
private readonly lru = new LRUCache<string, LRUCache<string, RepositoryCacheInfo>>(RepositoryCache.MAX_REPO_ENTRIES);
|
||||
|
||||
constructor(public readonly _globalState: Memento, private readonly _logger: LogOutputChannel) {
|
||||
this.load();
|
||||
@@ -40,14 +52,16 @@ export class RepositoryCache {
|
||||
set(repoUrl: string, rootPath: string): void {
|
||||
let foldersLru = this.lru.get(repoUrl);
|
||||
if (!foldersLru) {
|
||||
foldersLru = new LRUCache<string, true>(RepositoryCache.MAX_FOLDER_ENTRIES);
|
||||
foldersLru = new LRUCache<string, RepositoryCacheInfo>(RepositoryCache.MAX_FOLDER_ENTRIES);
|
||||
}
|
||||
const folderPathOrWorkspaceFile: string | undefined = this._findWorkspaceForRepo(rootPath);
|
||||
if (!folderPathOrWorkspaceFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
foldersLru.set(folderPathOrWorkspaceFile, true); // touch entry
|
||||
foldersLru.set(folderPathOrWorkspaceFile, {
|
||||
workspacePath: folderPathOrWorkspaceFile
|
||||
}); // touch entry
|
||||
this.lru.set(repoUrl, foldersLru);
|
||||
this.save();
|
||||
}
|
||||
@@ -62,13 +76,7 @@ export class RepositoryCache {
|
||||
const sorted = [...this._workspaceFolders].sort((a, b) => b.uri.fsPath.length - a.uri.fsPath.length);
|
||||
for (const folder of sorted) {
|
||||
const folderPath = folder.uri.fsPath;
|
||||
const relToFolder = path.relative(folderPath, rootPath);
|
||||
if (relToFolder === '' || (!relToFolder.startsWith('..') && !path.isAbsolute(relToFolder))) {
|
||||
folderPathOrWorkspaceFile = folderPath;
|
||||
break;
|
||||
}
|
||||
const relFromFolder = path.relative(rootPath, folderPath);
|
||||
if (relFromFolder === '' || (!relFromFolder.startsWith('..') && !path.isAbsolute(relFromFolder))) {
|
||||
if (isDescendant(folderPath, rootPath) || isDescendant(rootPath, folderPath)) {
|
||||
folderPathOrWorkspaceFile = folderPath;
|
||||
break;
|
||||
}
|
||||
@@ -105,9 +113,9 @@ export class RepositoryCache {
|
||||
/**
|
||||
* We should possibly support converting between ssh remotes and http remotes.
|
||||
*/
|
||||
get(repoUrl: string): string[] | undefined {
|
||||
get(repoUrl: string): RepositoryCacheInfo[] | undefined {
|
||||
const inner = this.lru.get(repoUrl);
|
||||
return inner ? Array.from(inner.keys()) : undefined;
|
||||
return inner ? Array.from(inner.values()) : undefined;
|
||||
}
|
||||
|
||||
delete(repoUrl: string, folderPathOrWorkspaceFile: string) {
|
||||
@@ -129,42 +137,43 @@ export class RepositoryCache {
|
||||
|
||||
private load(): void {
|
||||
try {
|
||||
const raw = this._globalState.get<[string, [string, true][]][]>(RepositoryCache.STORAGE_KEY);
|
||||
if (Array.isArray(raw)) {
|
||||
for (const [repo, storedFolders] of raw) {
|
||||
if (typeof repo !== 'string' || !Array.isArray(storedFolders)) {
|
||||
const raw = this._globalState.get<[string, [string, RepositoryCacheInfo][]][]>(RepositoryCache.STORAGE_KEY);
|
||||
if (!Array.isArray(raw)) {
|
||||
return;
|
||||
}
|
||||
for (const [repo, storedFolders] of raw) {
|
||||
if (typeof repo !== 'string' || !Array.isArray(storedFolders)) {
|
||||
continue;
|
||||
}
|
||||
const inner = new LRUCache<string, RepositoryCacheInfo>(RepositoryCache.MAX_FOLDER_ENTRIES);
|
||||
for (const entry of storedFolders) {
|
||||
if (!Array.isArray(entry) || entry.length !== 2) {
|
||||
continue;
|
||||
}
|
||||
const inner = new LRUCache<string, true>(RepositoryCache.MAX_FOLDER_ENTRIES);
|
||||
for (const entry of storedFolders) {
|
||||
let folderPath: string | undefined;
|
||||
if (Array.isArray(entry) && entry.length === 2) {
|
||||
const [workspaceFolder, _] = entry;
|
||||
if (typeof workspaceFolder === 'string') {
|
||||
folderPath = workspaceFolder;
|
||||
}
|
||||
}
|
||||
if (folderPath) {
|
||||
inner.set(folderPath, true);
|
||||
}
|
||||
}
|
||||
if (inner.size) {
|
||||
this.lru.set(repo, inner);
|
||||
const [folderPath, info] = entry;
|
||||
if (typeof folderPath !== 'string' || !isRepositoryCacheInfo(info)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inner.set(folderPath, info);
|
||||
}
|
||||
if (inner.size) {
|
||||
this.lru.set(repo, inner);
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
this._logger.warn('[CachedRepositories][load] Failed to load cached repositories from global state.');
|
||||
}
|
||||
}
|
||||
|
||||
private save(): void {
|
||||
// Serialize as [repoUrl, [folderPathOrWorkspaceFile, true][]] preserving outer LRU order.
|
||||
const serialized: [string, [string, true][]][] = [];
|
||||
// Serialize as [repoUrl, [folderPathOrWorkspaceFile, RepositoryCacheInfo][]] preserving outer LRU order.
|
||||
const serialized: [string, [string, RepositoryCacheInfo][]][] = [];
|
||||
for (const [repo, inner] of this.lru) {
|
||||
const folders: [string, true][] = [];
|
||||
for (const [folder, _] of inner) {
|
||||
folders.push([folder, true]);
|
||||
const folders: [string, RepositoryCacheInfo][] = [];
|
||||
for (const [folder, info] of inner) {
|
||||
folders.push([folder, info]);
|
||||
}
|
||||
serialized.push([repo, folders]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user