This commit is contained in:
Joao Moreno 2019-06-06 15:57:21 +02:00
parent 622f08313b
commit 13d0dad699
3 changed files with 31 additions and 23 deletions

View file

@ -329,8 +329,8 @@ export class Git {
this.env = options.env || {};
}
open(repository: string): Repository {
return new Repository(this, repository);
open(repository: string, dotGit: string): Repository {
return new Repository(this, repository, dotGit);
}
async init(repository: string): Promise<void> {
@ -370,6 +370,11 @@ export class Git {
return path.normalize(result.stdout.trim());
}
async getRepositoryDotGit(repositoryPath: string): Promise<string> {
const result = await this.exec(repositoryPath, ['rev-parse', '--absolute-git-dir']);
return path.normalize(result.stdout.trim());
}
async exec(cwd: string, args: string[], options: SpawnOptions = {}): Promise<IExecutionResult<string>> {
options = assign({ cwd }, options || {});
return await this._exec(args, options);
@ -649,7 +654,8 @@ export class Repository {
constructor(
private _git: Git,
private repositoryRoot: string
private repositoryRoot: string,
readonly dotGit: string
) { }
get git(): Git {

View file

@ -78,7 +78,7 @@ export class Model {
this.disposables.push(fsWatcher);
const onWorkspaceChange = anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate, fsWatcher.onDidDelete);
const onGitRepositoryChange = filterEvent(onWorkspaceChange, uri => /\/\.git\//.test(uri.path));
const onGitRepositoryChange = filterEvent(onWorkspaceChange, uri => /\/\.git/.test(uri.path));
const onPossibleGitRepositoryChange = filterEvent(onGitRepositoryChange, uri => !this.getRepository(uri));
onPossibleGitRepositoryChange(this.onPossibleGitRepositoryChange, this, this.disposables);
@ -232,7 +232,8 @@ export class Model {
return;
}
const repository = new Repository(this.git.open(repositoryRoot), this.globalState);
const dotGit = await this.git.getRepositoryDotGit(repositoryRoot);
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this.globalState);
this.open(repository);
} catch (err) {

View file

@ -5,7 +5,7 @@
import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode';
import { Repository as BaseRepository, Commit, Stash, GitError, Submodule, CommitOptions, ForcePushMode } from './git';
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util';
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent, toDisposable } from './util';
import { memoize, throttle, debounce } from './decorators';
import { toGitUri } from './uri';
import { AutoFetcher } from './autofetch';
@ -553,27 +553,28 @@ export class Repository implements Disposable {
private readonly repository: BaseRepository,
globalState: Memento
) {
const fsWatcher = workspace.createFileSystemWatcher('**');
this.disposables.push(fsWatcher);
const workspaceWatcher = workspace.createFileSystemWatcher('**');
this.disposables.push(workspaceWatcher);
const workspaceFilter = (uri: Uri) => isDescendant(repository.root, uri.fsPath);
const onWorkspaceDelete = filterEvent(fsWatcher.onDidDelete, workspaceFilter);
const onWorkspaceChange = filterEvent(anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate), workspaceFilter);
const onRepositoryDotGitDelete = filterEvent(onWorkspaceDelete, uri => /\/\.git$/.test(uri.path));
const onRepositoryChange = anyEvent(onWorkspaceDelete, onWorkspaceChange);
const onWorkspaceFileChanges = anyEvent(workspaceWatcher.onDidChange, workspaceWatcher.onDidCreate, workspaceWatcher.onDidDelete);
const onWorkspaceRepositoryFileChanges = filterEvent(onWorkspaceFileChanges, uri => isDescendant(repository.root, uri.fsPath));
const onWorkspaceWorkingTreeFileChanges = filterEvent(onWorkspaceRepositoryFileChanges, uri => !/\/\.git($|\/)/.test(uri.path));
// relevant repository changes are:
// - DELETE .git folder
// - ANY CHANGE within .git folder except .git itself and .git/index.lock
const onRelevantRepositoryChange = anyEvent(
onRepositoryDotGitDelete,
filterEvent(onRepositoryChange, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path))
);
const dotGitWatcher = fs.watch(repository.dotGit);
const onRepositoryFileEmitter = new EventEmitter<Uri>();
dotGitWatcher.on('change', (_, e) => onRepositoryFileEmitter.fire(Uri.file(path.join(repository.dotGit, e as string))));
dotGitWatcher.on('error', err => console.error(err));
this.disposables.push(toDisposable(() => dotGitWatcher.close()));
const onRelevantRepositoryChanges = filterEvent(onRepositoryFileEmitter.event, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path));
onRelevantRepositoryChange(this.onFSChange, this, this.disposables);
// 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 onFSChange = anyEvent(onWorkspaceWorkingTreeFileChanges, onRelevantRepositoryChanges);
onFSChange(this.onFSChange, this, this.disposables);
const onRelevantGitChange = filterEvent(onRelevantRepositoryChange, uri => /\/\.git\//.test(uri.path));
onRelevantGitChange(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
// Relevate repository changes should trigger virtual document change events
onRelevantRepositoryChanges(this._onDidChangeRepository.fire, this._onDidChangeRepository, this.disposables);
const root = Uri.file(repository.root);
this._sourceControl = scm.createSourceControl('git', 'Git', root);