Skip to content

Commit 13d0dad

Browse files
committed
1 parent 622f083 commit 13d0dad

3 files changed

Lines changed: 35 additions & 27 deletions

File tree

extensions/git/src/git.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ export class Git {
329329
this.env = options.env || {};
330330
}
331331

332-
open(repository: string): Repository {
333-
return new Repository(this, repository);
332+
open(repository: string, dotGit: string): Repository {
333+
return new Repository(this, repository, dotGit);
334334
}
335335

336336
async init(repository: string): Promise<void> {
@@ -370,6 +370,11 @@ export class Git {
370370
return path.normalize(result.stdout.trim());
371371
}
372372

373+
async getRepositoryDotGit(repositoryPath: string): Promise<string> {
374+
const result = await this.exec(repositoryPath, ['rev-parse', '--absolute-git-dir']);
375+
return path.normalize(result.stdout.trim());
376+
}
377+
373378
async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
374379
options = assign({ cwd }, options || {});
375380
return await this._exec(args, options);
@@ -649,7 +654,8 @@ export class Repository {
649654

650655
constructor(
651656
private _git: Git,
652-
private repositoryRoot: string
657+
private repositoryRoot: string,
658+
readonly dotGit: string
653659
) { }
654660

655661
get git(): Git {

extensions/git/src/model.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class Model {
7878
this.disposables.push(fsWatcher);
7979

8080
const onWorkspaceChange = anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate, fsWatcher.onDidDelete);
81-
const onGitRepositoryChange = filterEvent(onWorkspaceChange, uri => /\/\.git\//.test(uri.path));
81+
const onGitRepositoryChange = filterEvent(onWorkspaceChange, uri => /\/\.git/.test(uri.path));
8282
const onPossibleGitRepositoryChange = filterEvent(onGitRepositoryChange, uri => !this.getRepository(uri));
8383
onPossibleGitRepositoryChange(this.onPossibleGitRepositoryChange, this, this.disposables);
8484

@@ -232,7 +232,8 @@ export class Model {
232232
return;
233233
}
234234

235-
const repository = new Repository(this.git.open(repositoryRoot), this.globalState);
235+
const dotGit = await this.git.getRepositoryDotGit(repositoryRoot);
236+
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this.globalState);
236237

237238
this.open(repository);
238239
} catch (err) {

extensions/git/src/repository.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode';
77
import { Repository as BaseRepository, Commit, Stash, GitError, Submodule, CommitOptions, ForcePushMode } from './git';
8-
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util';
8+
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent, toDisposable } from './util';
99
import { memoize, throttle, debounce } from './decorators';
1010
import { toGitUri } from './uri';
1111
import { AutoFetcher } from './autofetch';
@@ -553,27 +553,28 @@ export class Repository implements Disposable {
553553
private readonly repository: BaseRepository,
554554
globalState: Memento
555555
) {
556-
const fsWatcher = workspace.createFileSystemWatcher('**');
557-
this.disposables.push(fsWatcher);
558-
559-
const workspaceFilter = (uri: Uri) => isDescendant(repository.root, uri.fsPath);
560-
const onWorkspaceDelete = filterEvent(fsWatcher.onDidDelete, workspaceFilter);
561-
const onWorkspaceChange = filterEvent(anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate), workspaceFilter);
562-
const onRepositoryDotGitDelete = filterEvent(onWorkspaceDelete, uri => /\/\.git$/.test(uri.path));
563-
const onRepositoryChange = anyEvent(onWorkspaceDelete, onWorkspaceChange);
564-
565-
// relevant repository changes are:
566-
// - DELETE .git folder
567-
// - ANY CHANGE within .git folder except .git itself and .git/index.lock
568-
const onRelevantRepositoryChange = anyEvent(
569-
onRepositoryDotGitDelete,
570-
filterEvent(onRepositoryChange, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path))
571-
);
572-
573-
onRelevantRepositoryChange(this.onFSChange, this, this.disposables);
574-
575-
const onRelevantGitChange = filterEvent(onRelevantRepositoryChange, uri => /\/\.git\//.test(uri.path));
576-
onRelevantGitChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
556+
const workspaceWatcher = workspace.createFileSystemWatcher('**');
557+
this.disposables.push(workspaceWatcher);
558+
559+
const onWorkspaceFileChanges = anyEvent(workspaceWatcher.onDidChange, workspaceWatcher.onDidCreate, workspaceWatcher.onDidDelete);
560+
const onWorkspaceRepositoryFileChanges = filterEvent(onWorkspaceFileChanges, uri => isDescendant(repository.root, uri.fsPath));
561+
const onWorkspaceWorkingTreeFileChanges = filterEvent(onWorkspaceRepositoryFileChanges, uri => !/\/\.git($|\/)/.test(uri.path));
562+
563+
const dotGitWatcher = fs.watch(repository.dotGit);
564+
const onRepositoryFileEmitter = new EventEmitter<Uri>();
565+
dotGitWatcher.on('change', (_, e) => onRepositoryFileEmitter.fire(Uri.file(path.join(repository.dotGit, e as string))));
566+
dotGitWatcher.on('error', err => console.error(err));
567+
this.disposables.push(toDisposable(() => dotGitWatcher.close()));
568+
const onRelevantRepositoryChanges = filterEvent(onRepositoryFileEmitter.event, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path));
569+
570+
// FS changes should trigger `git status`:
571+
// - any change inside the repository working tree
572+
// - any change whithin the first level of the `.git` folder, except the folder itself and `index.lock`
573+
const onFSChange = anyEvent(onWorkspaceWorkingTreeFileChanges, onRelevantRepositoryChanges);
574+
onFSChange(this.onFSChange, this, this.disposables);
575+
576+
// Relevate repository changes should trigger virtual document change events
577+
onRelevantRepositoryChanges(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
577578

578579
const root = Uri.file(repository.root);
579580
this._sourceControl = scm.createSourceControl('git', 'Git', root);

0 commit comments

Comments
 (0)