From c889303366fa7d8f1ecf8afed164fa9ff32dfddd Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 2 Mar 2018 17:31:37 +0100 Subject: [PATCH] fixes #44802 --- extensions/git/src/commands.ts | 16 ++++----- extensions/git/src/git.ts | 19 ++++++++--- extensions/git/src/repository.ts | 56 +++++++++++++++++++++++--------- 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 8ce710d56b4..2284e266bf7 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1333,7 +1333,7 @@ export class CommandCenter { const remoteCharCnt = remotePick.label.length; - repository.pull(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1)); + repository.pullFrom(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1)); } @command('git.pull', { repository: true }) @@ -1345,7 +1345,7 @@ export class CommandCenter { return; } - await repository.pull(); + await repository.pull(repository.HEAD && repository.HEAD.upstream); } @command('git.pullRebase', { repository: true }) @@ -1357,7 +1357,7 @@ export class CommandCenter { return; } - await repository.pullWithRebase(); + await repository.pullWithRebase(repository.HEAD && repository.HEAD.upstream); } @command('git.push', { repository: true }) @@ -1375,7 +1375,7 @@ export class CommandCenter { } try { - await repository.push(); + await repository.push(repository.HEAD.upstream); } catch (err) { if (err.gitErrorCode !== GitErrorCodes.NoUpstreamBranch) { throw err; @@ -1443,7 +1443,7 @@ export class CommandCenter { const shouldPrompt = config.get('confirmSync') === true; if (shouldPrompt) { - const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}'.", HEAD.upstream); + const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}/{1}'.", HEAD.upstream.remote, HEAD.upstream.name); const yes = localize('ok', "OK"); const neverAgain = localize('never again', "OK, Don't Show Again"); const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain); @@ -1456,9 +1456,9 @@ export class CommandCenter { } if (rebase) { - await repository.syncRebase(); + await repository.syncRebase(HEAD.upstream); } else { - await repository.sync(); + await repository.sync(HEAD.upstream); } } @@ -1476,7 +1476,7 @@ export class CommandCenter { return; } - await repository.sync(); + await repository.sync(HEAD.upstream); })); } diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index bc1a6cf494f..094bf3fe577 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -53,8 +53,13 @@ export interface Ref { remote?: string; } +export interface UpstreamRef { + remote: string; + name: string; +} + export interface Branch extends Ref { - upstream?: string; + upstream?: UpstreamRef; ahead?: number; behind?: number; } @@ -1218,10 +1223,16 @@ export class Repository { const commit = result.stdout.trim(); try { - const res2 = await this.run(['rev-parse', '--symbolic-full-name', '--abbrev-ref', name + '@{u}']); - const upstream = res2.stdout.trim(); + const res2 = await this.run(['rev-parse', '--symbolic-full-name', name + '@{u}']); + const fullUpstream = res2.stdout.trim(); + const match = /^refs\/remotes\/([^/]+)\/(.+)$/.exec(fullUpstream); - const res3 = await this.run(['rev-list', '--left-right', name + '...' + upstream]); + if (!match) { + throw new Error(`Could not parse upstream branch: ${fullUpstream}`); + } + + const upstream = { remote: match[1], name: match[2] }; + const res3 = await this.run(['rev-list', '--left-right', name + '...' + fullUpstream]); let ahead = 0, behind = 0; let i = 0; diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 66782db8f26..a0145ad226b 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -6,7 +6,7 @@ 'use strict'; 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, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError, Submodule, DiffOptions } from './git'; +import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError, Submodule, DiffOptions, UpstreamRef } from './git'; import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util'; import { memoize, throttle, debounce } from './decorators'; import { toGitUri } from './uri'; @@ -728,24 +728,48 @@ export class Repository implements Disposable { } @throttle - async pullWithRebase(): Promise { - await this.run(Operation.Pull, () => this.repository.pull(true)); + async pullWithRebase(upstream?: UpstreamRef): Promise { + let remote: string | undefined; + let branch: string | undefined; + + if (upstream) { + remote = upstream.remote; + branch = upstream.name; + } + + await this.run(Operation.Pull, () => this.repository.pull(true, remote, branch)); } @throttle - async pull(rebase?: boolean, remote?: string, name?: string): Promise { - await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, name)); - } + async pull(upstream?: UpstreamRef): Promise { + let remote: string | undefined; + let branch: string | undefined; - @throttle - async push(): Promise { - await this.run(Operation.Push, () => this.repository.push()); + if (upstream) { + remote = upstream.remote; + branch = upstream.name; + } + + await this.run(Operation.Pull, () => this.repository.pull(false, remote, branch)); } async pullFrom(rebase?: boolean, remote?: string, branch?: string): Promise { await this.run(Operation.Pull, () => this.repository.pull(rebase, remote, branch)); } + @throttle + async push(upstream?: UpstreamRef): Promise { + let remote: string | undefined; + let branch: string | undefined; + + if (upstream) { + remote = upstream.remote; + branch = upstream.name; + } + + await this.run(Operation.Push, () => this.repository.push(remote, branch)); + } + async pushTo(remote?: string, name?: string, setUpstream: boolean = false): Promise { await this.run(Operation.Push, () => this.repository.push(remote, name, setUpstream)); } @@ -754,26 +778,26 @@ export class Repository implements Disposable { await this.run(Operation.Push, () => this.repository.push(remote, undefined, false, true)); } - private async _sync(rebase: boolean): Promise { + private async _sync(upstream: UpstreamRef, rebase: boolean): Promise { await this.run(Operation.Sync, async () => { - await this.repository.pull(rebase); + await this.repository.pull(rebase, upstream.remote, upstream.name); const shouldPush = this.HEAD && typeof this.HEAD.ahead === 'number' ? this.HEAD.ahead > 0 : true; if (shouldPush) { - await this.repository.push(); + await this.repository.push(upstream.remote, upstream.name); } }); } @throttle - sync(): Promise { - return this._sync(false); + sync(upstream: UpstreamRef): Promise { + return this._sync(upstream, false); } @throttle - async syncRebase(): Promise { - return this._sync(true); + async syncRebase(upstream: UpstreamRef): Promise { + return this._sync(upstream, true); } async show(ref: string, filePath: string): Promise {