Skip to content

Commit 7cd0eb5

Browse files
committed
Fixes errors with renamed/deleted files
Adds a new "missing" document to allow the tracker to track these files
1 parent 6ae9d0e commit 7cd0eb5

File tree

3 files changed

+95
-24
lines changed

3 files changed

+95
-24
lines changed

src/gitService.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ export class GitService extends Disposable {
936936
key += `:n${options.maxCount}`;
937937
}
938938

939-
const doc = await Container.tracker.getOrAdd(fileName);
939+
const doc = await Container.tracker.getOrAdd(new GitUri(Uri.file(fileName), { repoPath: repoPath!, sha: options.ref }));
940940
if (this.UseCaching && options.range === undefined && !options.reverse) {
941941
if (doc.state !== undefined) {
942942
const cachedLog = doc.state.get<CachedLog>(key);
@@ -1089,13 +1089,13 @@ export class GitService extends Disposable {
10891089
}
10901090
}
10911091

1092-
async getRepoPath(filePath: string): Promise<string | undefined>;
1093-
async getRepoPath(uri: Uri | undefined): Promise<string | undefined>;
1094-
async getRepoPath(filePathOrUri: string | Uri | undefined): Promise<string | undefined> {
1092+
async getRepoPath(filePath: string, options?: { ref?: string, skipTrackingCheck?: boolean }): Promise<string | undefined>;
1093+
async getRepoPath(uri: Uri | undefined, options?: { ref?: string, skipTrackingCheck?: boolean }): Promise<string | undefined>;
1094+
async getRepoPath(filePathOrUri: string | Uri | undefined, options: { ref?: string, skipTrackingCheck?: boolean } = {}): Promise<string | undefined> {
10951095
if (filePathOrUri === undefined) return await this.getActiveRepoPath();
10961096
if (filePathOrUri instanceof GitUri) return filePathOrUri.repoPath;
10971097

1098-
const repo = await this.getRepository(filePathOrUri);
1098+
const repo = await this.getRepository(filePathOrUri, options);
10991099
if (repo !== undefined) return repo.path;
11001100

11011101
const rp = await this.getRepoPathCore(typeof filePathOrUri === 'string' ? filePathOrUri : filePathOrUri.fsPath, false);
@@ -1149,10 +1149,10 @@ export class GitService extends Disposable {
11491149
return this._repositoryTree;
11501150
}
11511151

1152-
async getRepository(repoPath: string): Promise<Repository | undefined>;
1153-
async getRepository(uri: Uri): Promise<Repository | undefined>;
1154-
async getRepository(repoPathOrUri: string | Uri): Promise<Repository | undefined>;
1155-
async getRepository(repoPathOrUri: string | Uri): Promise<Repository | undefined> {
1152+
async getRepository(repoPath: string, options?: { ref?: string, skipTrackingCheck?: boolean }): Promise<Repository | undefined>;
1153+
async getRepository(uri: Uri, options?: { ref?: string, skipTrackingCheck?: boolean }): Promise<Repository | undefined>;
1154+
async getRepository(repoPathOrUri: string | Uri, options?: { ref?: string, skipTrackingCheck?: boolean }): Promise<Repository | undefined>;
1155+
async getRepository(repoPathOrUri: string | Uri, options: { ref?: string, skipTrackingCheck?: boolean } = {}): Promise<Repository | undefined> {
11561156
const repositoryTree = await this.getRepositoryTree();
11571157

11581158
let path: string;
@@ -1179,8 +1179,10 @@ export class GitService extends Disposable {
11791179
const repo = repositoryTree.findSubstr(path);
11801180
if (repo === undefined) return undefined;
11811181

1182-
// Make sure the file is tracked in that repo, before returning
1183-
if (!await this.isTrackedCore(repo.path, path)) return undefined;
1182+
if (!options.skipTrackingCheck) {
1183+
// Make sure the file is tracked in that repo, before returning
1184+
if (!await this.isTrackedCore(repo.path, path, options.ref)) return undefined;
1185+
}
11841186
return repo;
11851187
}
11861188

src/trackers/documentTracker.ts

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22
import { Functions, IDeferrable } from './../system';
3-
import { ConfigurationChangeEvent, Disposable, Event, EventEmitter, TextDocument, TextDocumentChangeEvent, TextEditor, Uri, window, workspace } from 'vscode';
3+
import { ConfigurationChangeEvent, Disposable, EndOfLine, Event, EventEmitter, Position, Range, TextDocument, TextDocumentChangeEvent, TextEditor, TextLine, Uri, window, workspace } from 'vscode';
44
import { configuration } from './../configuration';
55
import { CommandContext, DocumentSchemes, isActiveDocument, isTextEditor, setCommandContext } from './../constants';
66
import { GitUri } from '../gitService';
@@ -174,10 +174,9 @@ export class DocumentTracker<T> extends Disposable {
174174
// }
175175
// }
176176

177-
async add(fileName: string): Promise<TrackedDocument<T>>;
178177
async add(document: TextDocument): Promise<TrackedDocument<T>>;
179178
async add(uri: Uri): Promise<TrackedDocument<T>>;
180-
async add(documentOrId: string | TextDocument | Uri): Promise<TrackedDocument<T>> {
179+
async add(documentOrId: TextDocument | Uri): Promise<TrackedDocument<T>> {
181180
return this._add(documentOrId);
182181
}
183182

@@ -196,10 +195,9 @@ export class DocumentTracker<T> extends Disposable {
196195
return await this._get(documentOrId);
197196
}
198197

199-
async getOrAdd(fileName: string): Promise<TrackedDocument<T>>;
200198
async getOrAdd(document: TextDocument): Promise<TrackedDocument<T>>;
201199
async getOrAdd(uri: Uri): Promise<TrackedDocument<T>>;
202-
async getOrAdd(documentOrId: string | TextDocument | Uri): Promise<TrackedDocument<T>> {
200+
async getOrAdd(documentOrId: TextDocument | Uri): Promise<TrackedDocument<T>> {
203201
return await this._get(documentOrId) || await this._add(documentOrId);
204202
}
205203

@@ -213,12 +211,22 @@ export class DocumentTracker<T> extends Disposable {
213211
return this._documentMap.has(key);
214212
}
215213

216-
private async _add(documentOrId: string | TextDocument | Uri): Promise<TrackedDocument<T>> {
217-
if (typeof documentOrId === 'string') {
218-
documentOrId = await workspace.openTextDocument(documentOrId);
219-
}
220-
else if (documentOrId instanceof GitUri) {
221-
documentOrId = await workspace.openTextDocument(documentOrId.fileUri({ useVersionedPath: true }));
214+
private async _add(documentOrId: TextDocument | Uri): Promise<TrackedDocument<T>> {
215+
if (documentOrId instanceof GitUri) {
216+
try {
217+
documentOrId = await workspace.openTextDocument(documentOrId.fileUri({ useVersionedPath: true }));
218+
}
219+
catch (ex) {
220+
if (!ex.toString().includes('File not found')) throw ex;
221+
222+
// If we can't find the file, assume it is because the file has been renamed or deleted at some point
223+
documentOrId = new MissingRevisionTextDocument(documentOrId);
224+
225+
// const [fileName, repoPath] = await Container.git.findWorkingFileName(documentOrId, undefined, ref);
226+
// if (fileName === undefined) throw new Error(`Failed to add tracking for document: ${documentOrId}`);
227+
228+
// documentOrId = await workspace.openTextDocument(path.resolve(repoPath!, fileName));
229+
}
222230
}
223231
else if (documentOrId instanceof Uri) {
224232
documentOrId = await workspace.openTextDocument(documentOrId);
@@ -303,3 +311,64 @@ export class DocumentTracker<T> extends Disposable {
303311
this._dirtyStateChangedDebounced(e);
304312
}
305313
}
314+
315+
class MissingRevisionTextDocument implements TextDocument {
316+
317+
readonly eol: EndOfLine;
318+
readonly fileName: string;
319+
readonly isClosed: boolean;
320+
readonly isDirty: boolean;
321+
readonly isUntitled: boolean;
322+
readonly languageId: string;
323+
readonly lineCount: number;
324+
readonly uri: Uri;
325+
readonly version: number;
326+
327+
constructor(
328+
public readonly gitUri: GitUri
329+
) {
330+
this.uri = gitUri.fileUri({ useVersionedPath: true });
331+
332+
this.eol = EndOfLine.LF;
333+
this.fileName = this.uri.fsPath;
334+
this.isClosed = false;
335+
this.isDirty = false;
336+
this.isUntitled = false;
337+
this.lineCount = 0;
338+
this.version = 0;
339+
}
340+
341+
getText(range?: Range | undefined): string {
342+
throw new Error('Method not supported.');
343+
}
344+
345+
getWordRangeAtPosition(position: Position, regex?: RegExp | undefined): Range | undefined {
346+
throw new Error('Method not supported.');
347+
}
348+
349+
lineAt(line: number): TextLine;
350+
lineAt(position: Position): TextLine;
351+
lineAt(position: any): TextLine {
352+
throw new Error('Method not supported.');
353+
}
354+
355+
offsetAt(position: Position): number {
356+
throw new Error('Method not supported.');
357+
}
358+
359+
positionAt(offset: number): Position {
360+
throw new Error('Method not supported.');
361+
}
362+
363+
save(): Thenable<boolean> {
364+
throw new Error('Method not supported.');
365+
}
366+
367+
validatePosition(position: Position): Position {
368+
throw new Error('Method not supported.');
369+
}
370+
371+
validateRange(range: Range): Range {
372+
throw new Error('Method not supported.');
373+
}
374+
}

src/trackers/trackedDocument.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export class TrackedDocument<T> extends Disposable {
145145

146146
this._blameFailed = true;
147147

148-
if (wasBlameable && isActiveDocument(this.document)) {
148+
if (wasBlameable && isActiveDocument(this._document)) {
149149
this.update({ forceBlameChange: true});
150150
}
151151
}
@@ -168,7 +168,7 @@ export class TrackedDocument<T> extends Disposable {
168168

169169
this._isDirtyIdle = false;
170170

171-
const active = getEditorIfActive(this.document);
171+
const active = getEditorIfActive(this._document);
172172
const wasBlameable = options.forceBlameChange ? undefined : this.isBlameable;
173173

174174
this._isTracked = await Container.git.isTracked(this._uri);

0 commit comments

Comments
 (0)