diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 0212f1cbec107a913328ecbb0687a119c87f7204..3eaa99748b3c113c3d3b24ce5d04aa29d0f85baf 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -6,7 +6,7 @@ 'use strict'; import { Uri, commands, scm, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn } from 'vscode'; -import { Ref, RefType, Git, GitErrorCodes } from './git'; +import { Ref, RefType, Git, GitErrorCodes, Branch } from './git'; import { Model, Resource, Status, CommitOptions, WorkingTreeGroup, IndexGroup, MergeGroup } from './model'; import { toGitUri, fromGitUri } from './uri'; import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange } from './staging'; @@ -85,7 +85,7 @@ class MergeItem implements QuickPickItem { constructor(protected ref: Ref) { } async run(model: Model): Promise { - await model.merge(this.ref.name); + await model.merge(this.ref.name! || this.ref.commit!); } } @@ -783,10 +783,12 @@ export class CommandCenter { const includeRemotes = checkoutType === 'all' || checkoutType === 'remote'; const heads = this.model.refs.filter(ref => ref.type === RefType.Head) - .map(ref => new MergeItem(ref)); + .filter(ref => ref.name || ref.commit) + .map(ref => new MergeItem(ref as Branch)); const remoteHeads = (includeRemotes ? this.model.refs.filter(ref => ref.type === RefType.RemoteHead) : []) - .map(ref => new MergeItem(ref)); + .filter(ref => ref.name || ref.commit) + .map(ref => new MergeItem(ref as Branch)); const picks = [...heads, ...remoteHeads]; const placeHolder = localize('select a branch to merge from', 'Select a branch to merge from'); @@ -796,7 +798,16 @@ export class CommandCenter { return; } - await choice.run(this.model); + try { + await choice.run(this.model); + } catch (err) { + if (err.gitErrorCode !== GitErrorCodes.Conflict) { + throw err; + } + + const message = localize('merge conflicts', "There are merge conflicts. Resolve them before committing."); + await window.showWarningMessage(message); + } } @command('git.pull') diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 865fd06e18d8a47fc4fb27f33c3ca608046e98cc..28e918ef536ac599cfcd73a855015a19c49bfaaf 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -654,9 +654,18 @@ export class Repository { await this.run(args); } - async merge(name: string): Promise { - const args = ['merge', name]; - await this.run(args); + async merge(ref: string): Promise { + const args = ['merge', ref]; + + try { + await this.run(args); + } catch (err) { + if (/^CONFLICT /m.test(err.stdout || '')) { + err.gitErrorCode = GitErrorCodes.Conflict; + } + + throw err; + } } async clean(paths: string[]): Promise { diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index f213b6151c709b7ae2093c3e028f23a547d58197..073cb39fc8fd4c15d28eaa83b8a5e7ce34b42c39 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -461,8 +461,8 @@ export class Model implements Disposable { await this.run(Operation.DeleteBranch, () => this.repository.deleteBranch(name, force)); } - async merge(name: string): Promise { - await this.run(Operation.Merge, () => this.repository.merge(name)); + async merge(ref: string): Promise { + await this.run(Operation.Merge, () => this.repository.merge(ref)); } async checkout(treeish: string): Promise {