From ae2d0cd96f9f5712bf0662e4d59f96bfc4fbf9f7 Mon Sep 17 00:00:00 2001 From: Vladimir Kotikov Date: Tue, 2 Oct 2018 22:17:53 +0300 Subject: [PATCH] Add option to automatically stash changes before performing `git pull` --- extensions/git/package.json | 6 +++ extensions/git/package.nls.json | 3 +- extensions/git/src/repository.ts | 77 ++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index 59e4100e4e7..121b3a6c5ec 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1175,6 +1175,12 @@ "default": false, "description": "%config.fetchOnPull%" }, + "git.autoStash": { + "type": "boolean", + "scope": "resource", + "default": false, + "description": "%config.autoStash%" + }, "git.allowForcePush": { "type": "boolean", "default": false, diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 4d73891f818..35483856770 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -102,6 +102,7 @@ "config.rebaseWhenSync": "Force git to use rebase when running the sync command.", "config.confirmEmptyCommits": "Always confirm the creation of empty commits.", "config.fetchOnPull": "Fetch all branches when pulling or just the current one.", + "config.autoStash": "Stash any changes before pulling and restore them after successful pull.", "config.allowForcePush": "Controls whether force push (with or without lease) is enabled.", "config.useForcePushWithLease": "Controls whether force pushing uses the safer force-with-lease variant.", "config.confirmForcePush": "Controls whether to ask for confirmation before force-pushing.", @@ -112,4 +113,4 @@ "colors.ignored": "Color for ignored resources.", "colors.conflict": "Color for resources with conflicts.", "colors.submodule": "Color for submodule resources." -} \ No newline at end of file +} diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index c10865fae54..afc998a0817 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -559,6 +559,11 @@ export class Repository implements Disposable { private isFreshRepository: boolean | undefined = undefined; private disposables: Disposable[] = []; + private _trackedCount: number = 0; + public get trackedCount(): number { + return this._trackedCount; + } + constructor( private readonly repository: BaseRepository, globalState: Memento @@ -926,14 +931,7 @@ export class Repository implements Disposable { branch = `${head.upstream.name}`; } - const config = workspace.getConfiguration('git', Uri.file(this.root)); - const fetchOnPull = config.get('fetchOnPull'); - - if (fetchOnPull) { - await this.run(Operation.Pull, () => this.repository.pull(true)); - } else { - await this.run(Operation.Pull, () => this.repository.pull(true, remote, branch)); - } + return this.pullFrom(true, remote, branch); } @throttle @@ -946,25 +944,32 @@ export class Repository implements Disposable { branch = `${head.upstream.name}`; } - const config = workspace.getConfiguration('git', Uri.file(this.root)); - const fetchOnPull = config.get('fetchOnPull'); - - if (fetchOnPull) { - await this.run(Operation.Pull, () => this.repository.pull(false)); - } else { - await this.run(Operation.Pull, () => this.repository.pull(false, remote, branch)); - } + return this.pullFrom(false, remote, branch); } async pullFrom(rebase?: boolean, remote?: string, branch?: string): Promise { const config = workspace.getConfiguration('git', Uri.file(this.root)); const fetchOnPull = config.get('fetchOnPull'); + const autoStash = config.get('autoStash'); - if (fetchOnPull) { - await this.run(Operation.Pull, () => this.repository.pull(rebase)); - } else { - await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, branch)); - } + + await this.run(Operation.Pull, async () => { + const doStash = autoStash && this.trackedCount > 0; + + if (doStash) { + await this.repository.createStash(); + } + + if (fetchOnPull) { + await this.run(Operation.Pull, () => this.repository.pull(rebase)); + } else { + await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, branch)); + } + + if (doStash) { + await this.repository.popStash(); + } + }); } @throttle @@ -1009,9 +1014,16 @@ export class Repository implements Disposable { pushBranch = `${head.name}:${head.upstream.name}`; } + const config = workspace.getConfiguration('git', Uri.file(this.root)); + const fetchOnPull = config.get('fetchOnPull'); + const autoStash = config.get('autoStash'); + await this.run(Operation.Sync, async () => { - const config = workspace.getConfiguration('git', Uri.file(this.root)); - const fetchOnPull = config.get('fetchOnPull'); + const doStash = autoStash && this.trackedCount > 0; + + if (doStash) { + await this.repository.createStash(); + } if (fetchOnPull) { await this.repository.pull(rebase); @@ -1019,6 +1031,10 @@ export class Repository implements Disposable { await this.repository.pull(rebase, remoteName, pullBranch); } + if (doStash) { + await this.repository.popStash(); + } + const remote = this.remotes.find(r => r.name === remoteName); if (remote && remote.isReadOnly) { @@ -1299,17 +1315,20 @@ export class Repository implements Disposable { this.indexGroup.resourceStates = index; this.workingTreeGroup.resourceStates = workingTree; + let totalCount = merge.length + index.length + workingTree.length; + this._trackedCount = totalCount - workingTree.filter(r => + r.type === Status.UNTRACKED || + r.type === Status.IGNORED + ).length; + // set count badge const countBadge = workspace.getConfiguration('git').get('countBadge'); - let count = merge.length + index.length + workingTree.length; - switch (countBadge) { - case 'off': count = 0; break; - case 'tracked': count = count - workingTree.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED).length; break; + case 'off': this._sourceControl.count = 0; break; + case 'all': this._sourceControl.count = totalCount; break; + case 'tracked': this._sourceControl.count = this._trackedCount; break; } - this._sourceControl.count = count; - // Disable `Discard All Changes` for "fresh" repositories // https://github.com/Microsoft/vscode/issues/43066 const isFreshRepository = !this._HEAD || !this._HEAD.commit;