From 64c8bd46c9035f003c6d9b85455f816a46e9acf0 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 11 Jan 2018 18:56:18 -0500 Subject: [PATCH] Fixes versioned files not working --- src/commands/common.ts | 2 +- src/git/gitUri.ts | 25 +++++++++++++++++++------ src/gitService.ts | 22 ++++++++++++++-------- src/trackers/documentTracker.ts | 34 ++++++++++++++++++++++------------ 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/commands/common.ts b/src/commands/common.ts index 4d394f4..f4f4216 100644 --- a/src/commands/common.ts +++ b/src/commands/common.ts @@ -295,7 +295,7 @@ export async function openEditor(uri: Uri, options: TextDocumentShowOptions & { const { rethrow, ...opts } = options; try { if (uri instanceof GitUri) { - uri = uri.fileUri(false); + uri = uri.fileUri({ noSha: true }); } const document = await workspace.openTextDocument(uri); diff --git a/src/git/gitUri.ts b/src/git/gitUri.ts index 5384b35..f9aa84f 100644 --- a/src/git/gitUri.ts +++ b/src/git/gitUri.ts @@ -10,6 +10,7 @@ export interface IGitCommitInfo { fileName?: string; repoPath: string; sha?: string; + versionedPath?: string; } // Taken from https://github.com/Microsoft/vscode/blob/master/src/vs/base/common/uri.ts#L331-L337 @@ -30,8 +31,10 @@ interface UriEx { export class GitUri extends ((Uri as any) as UriEx) { - repoPath?: string | undefined; - sha?: string | undefined; + repoPath?: string; + sha?: string; + + versionedPath?: string; constructor(uri?: Uri) constructor(uri: Uri, commit: IGitCommitInfo); @@ -75,6 +78,7 @@ export class GitUri extends ((Uri as any) as UriEx) { super({ scheme: uri.scheme, authority: authority, path: fsPath, query: uri.query, fragment: uri.fragment }); this.repoPath = commitOrRepoPath.repoPath; + this.versionedPath = commitOrRepoPath.versionedPath; if (GitService.isStagedUncommitted(commitOrRepoPath.sha) || !GitService.isUncommitted(commitOrRepoPath.sha)) { this.sha = commitOrRepoPath.sha; } @@ -84,8 +88,10 @@ export class GitUri extends ((Uri as any) as UriEx) { return this.sha && GitService.shortenSha(this.sha); } - fileUri(useSha: boolean = true) { - return Uri.file(useSha && this.sha ? this.path : this.fsPath); + fileUri(options: { noSha?: boolean, useVersionedPath?: boolean } = {}) { + if (options.useVersionedPath && this.versionedPath !== undefined) return Uri.file(this.versionedPath); + + return Uri.file(!options.noSha && this.sha ? this.path : this.fsPath); } getFormattedPath(separator: string = Strings.pad(GlyphChars.Dot, 2, 2), relativeTo?: string): string { @@ -190,8 +196,8 @@ export class GitUri extends ((Uri as any) as UriEx) { } as IGitCommitInfo); } - const gitUri = await Container.git.getGitUri(uri); - if (gitUri !== undefined) return gitUri; + const versionedUri = await Container.git.getVersionedUri(uri); + if (versionedUri !== undefined) return versionedUri; return new GitUri(uri, await Container.git.getRepoPath(uri)); } @@ -240,6 +246,13 @@ export class GitUri extends ((Uri as any) as UriEx) { return Strings.normalizePath(relativePath); } + static toKey(fileName: string): string; + static toKey(uri: Uri): string; + static toKey(fileNameOrUri: string | Uri): string; + static toKey(fileNameOrUri: string | Uri): string { + return Strings.normalizePath(typeof fileNameOrUri === 'string' ? fileNameOrUri : fileNameOrUri.fsPath).toLowerCase(); + } + static toRevisionUri(uri: GitUri): Uri; static toRevisionUri(sha: string, fileName: string, repoPath: string): Uri; static toRevisionUri(sha: string, status: IGitStatusFile, repoPath: string): Uri; diff --git a/src/gitService.ts b/src/gitService.ts index c4fc31b..f499de4 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -4,7 +4,7 @@ import { ConfigurationChangeEvent, Disposable, Event, EventEmitter, Range, TextE import { configuration, IRemotesConfig } from './configuration'; import { CommandContext, DocumentSchemes, setCommandContext } from './constants'; import { Container } from './container'; -import { CachedBlame, CachedDiff, CachedLog, DocumentTracker, GitDocumentState, TrackedDocument } from './trackers/documentTracker'; +import { CachedBlame, CachedDiff, CachedLog, GitDocumentState, TrackedDocument } from './trackers/documentTracker'; import { RemoteProviderFactory, RemoteProviderMap } from './git/remotes/factory'; import { CommitFormatting, Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitCommitType, GitDiff, GitDiffChunkLine, GitDiffParser, GitDiffShortStat, GitLog, GitLogCommit, GitLogParser, GitRemote, GitRemoteParser, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, GitTag, GitTagParser, IGit, Repository } from './git/git'; import { GitUri, IGitCommitInfo } from './git/gitUri'; @@ -45,12 +45,14 @@ export class GitService extends Disposable { private _repositoriesLoadingPromise: Promise | undefined; private _suspended: boolean = false; private readonly _trackedCache: Map>; + private _versionedUriCache: Map; constructor() { super(() => this.dispose()); this._repositoryTree = TernarySearchTree.forPaths(); this._trackedCache = new Map(); + this._versionedUriCache = new Map(); this._disposable = Disposable.from( window.onDidChangeWindowState(this.onWindowStateChanged, this), @@ -65,6 +67,7 @@ export class GitService extends Disposable { dispose() { this._repositoryTree.forEach(r => r.dispose()); this._trackedCache.clear(); + this._versionedUriCache.clear(); this._disposable && this._disposable.dispose(); } @@ -684,11 +687,6 @@ export class GitService extends Disposable { return await Git.config_get(key, repoPath); } - async getGitUri(uri: Uri) { - const doc = await Container.tracker.get(uri); - return doc !== undefined ? doc.uri : undefined; - } - async getDiffForFile(uri: GitUri, sha1?: string, sha2?: string): Promise { if (sha1 !== undefined && sha2 === undefined && uri.sha !== undefined) { sha2 = uri.sha; @@ -1201,6 +1199,10 @@ export class GitService extends Disposable { } const file = await Git.getVersionedFile(repoPath, fileName, sha); + if (file === undefined) return undefined; + + this._versionedUriCache.set(GitUri.toKey(file), new GitUri(Uri.file(fileName), { sha: sha, repoPath: repoPath!, versionedPath: file })); + return file; } @@ -1210,6 +1212,10 @@ export class GitService extends Disposable { return Git.show(repoPath, fileName, sha, { encoding: GitService.getEncoding(repoPath, fileName) }); } + getVersionedUri(uri: Uri) { + return this._versionedUriCache.get(GitUri.toKey(uri)); + } + isTrackable(scheme: string): boolean; isTrackable(uri: Uri): boolean; isTrackable(schemeOruri: string | Uri): boolean { @@ -1233,7 +1239,7 @@ export class GitService extends Disposable { let fileName: string; if (typeof fileNameOrUri === 'string') { [fileName, repoPath] = Git.splitPath(fileNameOrUri, repoPath); - cacheKey = DocumentTracker.toStateKey(fileNameOrUri); + cacheKey = GitUri.toKey(fileNameOrUri); } else { if (!this.isTrackable(fileNameOrUri)) return false; @@ -1241,7 +1247,7 @@ export class GitService extends Disposable { fileName = fileNameOrUri.fsPath; repoPath = fileNameOrUri.repoPath; sha = fileNameOrUri.sha; - cacheKey = DocumentTracker.toStateKey(fileName); + cacheKey = GitUri.toKey(fileName); } if (sha !== undefined) { diff --git a/src/trackers/documentTracker.ts b/src/trackers/documentTracker.ts index bce145c..ae7bf62 100644 --- a/src/trackers/documentTracker.ts +++ b/src/trackers/documentTracker.ts @@ -1,8 +1,9 @@ 'use strict'; -import { Functions, IDeferrable, Strings } from './../system'; +import { Functions, IDeferrable } from './../system'; import { ConfigurationChangeEvent, Disposable, Event, EventEmitter, TextDocument, TextDocumentChangeEvent, TextEditor, Uri, window, workspace } from 'vscode'; import { configuration } from './../configuration'; import { CommandContext, DocumentSchemes, isActiveDocument, isTextEditor, setCommandContext } from './../constants'; +import { GitUri } from '../gitService'; import { DocumentBlameStateChangeEvent, TrackedDocument } from './trackedDocument'; export { CachedBlame, CachedDiff, CachedLog, GitDocumentState } from './gitDocumentState'; @@ -47,6 +48,7 @@ export class DocumentTracker extends Disposable { this._disposable = Disposable.from( configuration.onDidChange(this.onConfigurationChanged, this), window.onDidChangeActiveTextEditor(Functions.debounce(this.onActiveTextEditorChanged, 0), this), + // window.onDidChangeVisibleTextEditors(Functions.debounce(this.onVisibleEditorsChanged, 5000), this), workspace.onDidChangeTextDocument(Functions.debounce(this.onTextDocumentChanged, 50), this), workspace.onDidCloseTextDocument(this.onTextDocumentClosed, this), workspace.onDidSaveTextDocument(this.onTextDocumentSaved, this) @@ -159,6 +161,15 @@ export class DocumentTracker extends Disposable { } } + // private onVisibleEditorsChanged(editors: TextEditor[]) { + // if (this._documentMap.size === 0) return; + + // // If we have no visible editors, or no "real" visible editors reset our cache + // if (editors.length === 0 || editors.every(e => !isTextEditor(e))) { + // this.clear(); + // } + // } + async add(fileName: string): Promise>; async add(document: TextDocument): Promise>; async add(uri: Uri): Promise>; @@ -193,7 +204,7 @@ export class DocumentTracker extends Disposable { has(uri: Uri): boolean; has(key: string | TextDocument | Uri): boolean { if (typeof key === 'string' || key instanceof Uri) { - key = DocumentTracker.toStateKey(key); + key = GitUri.toKey(key); } return this._documentMap.has(key); } @@ -202,6 +213,9 @@ export class DocumentTracker extends Disposable { if (typeof documentOrId === 'string') { documentOrId = await workspace.openTextDocument(documentOrId); } + else if (documentOrId instanceof GitUri) { + documentOrId = await workspace.openTextDocument(documentOrId.fileUri({ useVersionedPath: true })); + } else if (documentOrId instanceof Uri) { documentOrId = await workspace.openTextDocument(documentOrId); } @@ -213,8 +227,11 @@ export class DocumentTracker extends Disposable { } private async _get(documentOrId: string | TextDocument | Uri) { - if (typeof documentOrId === 'string' || documentOrId instanceof Uri) { - documentOrId = DocumentTracker.toStateKey(documentOrId); + if (documentOrId instanceof GitUri) { + documentOrId = GitUri.toKey(documentOrId.fileUri({ useVersionedPath: true })); + } + else if (typeof documentOrId === 'string' || documentOrId instanceof Uri) { + documentOrId = GitUri.toKey(documentOrId); } const doc = this._documentMap.get(documentOrId); @@ -225,7 +242,7 @@ export class DocumentTracker extends Disposable { } private addCore(document: TextDocument): TrackedDocument { - const key = DocumentTracker.toStateKey(document.uri); + const key = GitUri.toKey(document.uri); // Always start out false, so we will fire the event if needed const doc = new TrackedDocument(document, key, false, { @@ -281,11 +298,4 @@ export class DocumentTracker extends Disposable { this._dirtyStateChangedDebounced(e); } - - static toStateKey(fileName: string): string; - static toStateKey(uri: Uri): string; - static toStateKey(fileNameOrUri: string | Uri): string; - static toStateKey(fileNameOrUri: string | Uri): string { - return Strings.normalizePath(typeof fileNameOrUri === 'string' ? fileNameOrUri : fileNameOrUri.fsPath).toLowerCase(); - } }