Skip to content

Commit bcb3e0d

Browse files
committed
detect conflict markers when staging
fixes microsoft#33983
1 parent 25a8ce9 commit bcb3e0d

4 files changed

Lines changed: 41 additions & 11 deletions

File tree

extensions/git/npm-shrinkwrap.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/git/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@
806806
}
807807
},
808808
"dependencies": {
809+
"byline": "^5.0.0",
809810
"iconv-lite": "0.4.15",
810811
"vscode-extension-telemetry": "0.0.8",
811812
"vscode-nls": "2.0.2"

extensions/git/src/commands.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Ref, RefType, Git, GitErrorCodes, Branch } from './git';
1010
import { Repository, Resource, Status, CommitOptions, ResourceGroupType } from './repository';
1111
import { Model } from './model';
1212
import { toGitUri, fromGitUri } from './uri';
13+
import { grep } from './util';
1314
import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange } from './staging';
1415
import * as path from 'path';
1516
import * as os from 'os';
@@ -486,12 +487,20 @@ export class CommandCenter {
486487
}
487488

488489
const selection = resourceStates.filter(s => s instanceof Resource) as Resource[];
489-
const mergeConflicts = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
490-
491-
if (mergeConflicts.length > 0) {
492-
const message = mergeConflicts.length > 1
493-
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", mergeConflicts.length)
494-
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(mergeConflicts[0].resourceUri.fsPath));
490+
const merge = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
491+
const bothModified = merge.filter(s => s.type === Status.BOTH_MODIFIED);
492+
const promises = bothModified.map(s => grep(s.resourceUri.fsPath, /^<{7}|^={7}|^>{7}/));
493+
const unresolvedBothModified = await Promise.all<boolean>(promises);
494+
const resolvedConflicts = bothModified.filter((s, i) => !unresolvedBothModified[i]);
495+
const unresolvedConflicts = [
496+
...merge.filter(s => s.type !== Status.BOTH_MODIFIED),
497+
...bothModified.filter((s, i) => unresolvedBothModified[i])
498+
];
499+
500+
if (unresolvedConflicts.length > 0) {
501+
const message = unresolvedConflicts.length > 1
502+
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", unresolvedConflicts.length)
503+
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(unresolvedConflicts[0].resourceUri.fsPath));
495504

496505
const yes = localize('yes', "Yes");
497506
const pick = await window.showWarningMessage(message, { modal: true }, yes);
@@ -501,10 +510,8 @@ export class CommandCenter {
501510
}
502511
}
503512

504-
const workingTree = selection
505-
.filter(s => s.resourceGroupType === ResourceGroupType.WorkingTree);
506-
507-
const scmResources = [...workingTree, ...mergeConflicts];
513+
const workingTree = selection.filter(s => s.resourceGroupType === ResourceGroupType.WorkingTree);
514+
const scmResources = [...workingTree, ...resolvedConflicts, ...unresolvedConflicts];
508515

509516
if (!scmResources.length) {
510517
return;

extensions/git/src/util.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { Event } from 'vscode';
99
import { dirname } from 'path';
1010
import * as fs from 'fs';
11+
import * as byline from 'byline';
1112

1213
export function log(...args: any[]): void {
1314
console.log.apply(console, ['git:', ...args]);
@@ -188,4 +189,20 @@ export function find<T>(array: T[], fn: (t: T) => boolean): T | undefined {
188189
});
189190

190191
return result;
192+
}
193+
194+
export async function grep(filename: string, pattern: RegExp): Promise<boolean> {
195+
return new Promise<boolean>((c, e) => {
196+
const fileStream = fs.createReadStream(filename, { encoding: 'utf8' });
197+
const stream = byline(fileStream);
198+
stream.on('data', (line: string) => {
199+
if (pattern.test(line)) {
200+
fileStream.close();
201+
c(true);
202+
}
203+
});
204+
205+
stream.on('error', e);
206+
stream.on('end', () => c(false));
207+
});
191208
}

0 commit comments

Comments
 (0)