diff options
Diffstat (limited to 'extensions/git/src/repository.ts')
-rw-r--r-- | extensions/git/src/repository.ts | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 92c78a44969..76c30e5c1d4 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -5,7 +5,7 @@ import * as fs from 'fs'; import * as path from 'path'; -import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab, TabKindTextDiff, TabKindNotebookDiff } from 'vscode'; +import { CancellationToken, Command, Disposable, Event, EventEmitter, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, FileDecoration, commands, Tab, TabInputTextDiff, TabInputNotebookDiff, RelativePattern } from 'vscode'; import TelemetryReporter from '@vscode/extension-telemetry'; import * as nls from 'vscode-nls'; import { Branch, Change, ForcePushMode, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status, CommitOptions, BranchQuery, FetchOptions } from './api/git'; @@ -541,10 +541,12 @@ class DotGitWatcher implements IFileWatcher { private repository: Repository, private outputChannel: OutputChannel ) { - const rootWatcher = watch(repository.dotGit); + const rootWatcher = watch(repository.dotGit.path); this.disposables.push(rootWatcher); - const filteredRootWatcher = filterEvent(rootWatcher.event, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path)); + // Ignore changes to the "index.lock" file, and watchman fsmonitor hook (https://git-scm.com/docs/githooks#_fsmonitor_watchman) cookie files. + // Watchman creates a cookie file inside the git directory whenever a query is run (https://facebook.github.io/watchman/docs/cookies.html). + const filteredRootWatcher = filterEvent(rootWatcher.event, uri => !/\/\.git(\/index\.lock)?$|\/\.watchman-cookie-/.test(uri.path)); this.event = anyEvent(filteredRootWatcher, this.emitter.event); repository.onDidRunGitStatus(this.updateTransientWatchers, this, this.disposables); @@ -561,7 +563,7 @@ class DotGitWatcher implements IFileWatcher { this.transientDisposables = dispose(this.transientDisposables); const { name, remote } = this.repository.HEAD.upstream; - const upstreamPath = path.join(this.repository.dotGit, 'refs', 'remotes', remote, name); + const upstreamPath = path.join(this.repository.dotGit.commonPath ?? this.repository.dotGit.path, 'refs', 'remotes', remote, name); try { const upstreamWatcher = watch(upstreamPath); @@ -840,7 +842,7 @@ export class Repository implements Disposable { return this.repository.root; } - get dotGit(): string { + get dotGit(): { path: string; commonPath?: string } { return this.repository.dotGit; } @@ -858,37 +860,36 @@ export class Repository implements Disposable { outputChannel: OutputChannel, private telemetryReporter: TelemetryReporter ) { - const workspaceWatcher = workspace.createFileSystemWatcher('**'); - this.disposables.push(workspaceWatcher); + const repositoryWatcher = workspace.createFileSystemWatcher(new RelativePattern(Uri.file(repository.root), '**')); + this.disposables.push(repositoryWatcher); - const onWorkspaceFileChange = anyEvent(workspaceWatcher.onDidChange, workspaceWatcher.onDidCreate, workspaceWatcher.onDidDelete); - const onWorkspaceRepositoryFileChange = filterEvent(onWorkspaceFileChange, uri => isDescendant(repository.root, uri.fsPath)); - const onWorkspaceWorkingTreeFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => !/\/\.git($|\/)/.test(uri.path)); + const onRepositoryFileChange = anyEvent(repositoryWatcher.onDidChange, repositoryWatcher.onDidCreate, repositoryWatcher.onDidDelete); + const onRepositoryWorkingTreeFileChange = filterEvent(onRepositoryFileChange, uri => !/\.git($|\/)/.test(relativePath(repository.root, uri.fsPath))); - let onDotGitFileChange: Event<Uri>; + let onRepositoryDotGitFileChange: Event<Uri>; try { const dotGitFileWatcher = new DotGitWatcher(this, outputChannel); - onDotGitFileChange = dotGitFileWatcher.event; + onRepositoryDotGitFileChange = dotGitFileWatcher.event; this.disposables.push(dotGitFileWatcher); } catch (err) { if (Log.logLevel <= LogLevel.Error) { - outputChannel.appendLine(`${logTimestamp()} Failed to watch '${this.dotGit}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`); + outputChannel.appendLine(`${logTimestamp()} Failed to watch path:'${this.dotGit.path}' or commonPath:'${this.dotGit.commonPath}', reverting to legacy API file watched. Some events might be lost.\n${err.stack || err}`); } - onDotGitFileChange = filterEvent(onWorkspaceRepositoryFileChange, uri => /\/\.git($|\/)/.test(uri.path)); + onRepositoryDotGitFileChange = filterEvent(onRepositoryFileChange, uri => /\.git($|\/)/.test(uri.path)); } // FS changes should trigger `git status`: // - any change inside the repository working tree // - any change whithin the first level of the `.git` folder, except the folder itself and `index.lock` - const onFileChange = anyEvent(onWorkspaceWorkingTreeFileChange, onDotGitFileChange); + const onFileChange = anyEvent(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange); onFileChange(this.onFileChange, this, this.disposables); // Relevate repository changes should trigger virtual document change events - onDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables); + onRepositoryDotGitFileChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables); - this.disposables.push(new FileEventLogger(onWorkspaceWorkingTreeFileChange, onDotGitFileChange, outputChannel)); + this.disposables.push(new FileEventLogger(onRepositoryWorkingTreeFileChange, onRepositoryDotGitFileChange, outputChannel)); const root = Uri.file(repository.root); this._sourceControl = scm.createSourceControl('git', 'Git', root); @@ -1272,14 +1273,14 @@ export class Repository implements Disposable { const diffEditorTabsToClose: Tab[] = []; - for (const tab of window.tabGroups.groups.map(g => g.tabs).flat()) { - const { kind } = tab; - if (kind instanceof TabKindTextDiff || kind instanceof TabKindNotebookDiff) { - if (kind.modified.scheme === 'git' && indexResources.some(r => pathEquals(r, kind.modified.fsPath))) { + for (const tab of window.tabGroups.all.map(g => g.tabs).flat()) { + const { input } = tab; + if (input instanceof TabInputTextDiff || input instanceof TabInputNotebookDiff) { + if (input.modified.scheme === 'git' && indexResources.some(r => pathEquals(r, input.modified.fsPath))) { // Index diffEditorTabsToClose.push(tab); } - if (kind.modified.scheme === 'file' && kind.original.scheme === 'git' && workingTreeResources.some(r => pathEquals(r, kind.modified.fsPath))) { + if (input.modified.scheme === 'file' && input.original.scheme === 'git' && workingTreeResources.some(r => pathEquals(r, input.modified.fsPath))) { // Working Tree diffEditorTabsToClose.push(tab); } |