Skip to content

Commit 670212b

Browse files
committed
Fixes #756 - use --first-parent for merge commits
Fixes issue with --numstat changes Fixes issue with walking back too far
1 parent 39af556 commit 670212b

File tree

5 files changed

+52
-42
lines changed

5 files changed

+52
-42
lines changed

src/commands/diffLineWithPrevious.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class DiffLineWithPreviousCommand extends ActiveEditorCommand {
6262
Logger.error(
6363
ex,
6464
'DiffLineWithPreviousCommand',
65-
`getPreviousDiffUris(${gitUri.repoPath}, ${gitUri.fsPath}, ${gitUri.sha})`
65+
`getPreviousLineDiffUris(${gitUri.repoPath}, ${gitUri.fsPath}, ${gitUri.sha})`
6666
);
6767
return Messages.showGenericErrorMessage('Unable to open compare');
6868
}

src/commands/diffWithPrevious.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22
import { commands, TextDocumentShowOptions, TextEditor, Uri } from 'vscode';
33
import { Container } from '../container';
4-
import { GitCommit, GitService, GitUri } from '../git/gitService';
4+
import { GitCommit, GitLogCommit, GitService, GitUri } from '../git/gitService';
55
import { Logger } from '../logger';
66
import { Messages } from '../messages';
77
import { ActiveEditorCommand, command, CommandContext, Commands, getCommandUri, openEditor } from './common';
@@ -57,7 +57,9 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
5757
gitUri,
5858
gitUri.sha,
5959
// If we are in a diff editor, assume we are on the right side, and need to skip back 1 more revisions
60-
args.inDiffEditor ? 1 : 0
60+
args.inDiffEditor ? 1 : 0,
61+
// If this is a merge commit, walk back using the first parent only
62+
args.commit && (args.commit as GitLogCommit).isMerge
6163
);
6264

6365
if (diffUris === undefined || diffUris.previous === undefined) {

src/git/git.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -667,25 +667,27 @@ export class Git {
667667
ref: string | undefined,
668668
{
669669
filters,
670-
format = GitLogParser.defaultFormat,
671670
maxCount,
671+
firstParent = false,
672672
renames = true,
673673
reverse = false,
674+
simple = false,
674675
startLine,
675676
endLine
676677
}: {
677678
filters?: GitLogDiffFilter[];
678-
format?: string;
679679
maxCount?: number;
680+
firstParent?: boolean;
680681
renames?: boolean;
681682
reverse?: boolean;
683+
simple?: boolean;
682684
startLine?: number;
683685
endLine?: number;
684686
} = {}
685687
) {
686688
const [file, root] = Git.splitPath(fileName, repoPath);
687689

688-
const params = ['log', `--format=${format}`];
690+
const params = ['log', `--format=${simple ? GitLogParser.simpleFormat : GitLogParser.defaultFormat}`];
689691

690692
if (maxCount && !reverse) {
691693
params.push(`-n${maxCount}`);
@@ -696,8 +698,17 @@ export class Git {
696698
params.push(`--diff-filter=${filters.join(emptyStr)}`);
697699
}
698700

701+
if (firstParent) {
702+
params.push('--first-parent');
703+
}
704+
699705
if (startLine == null) {
700-
params.push('--numstat', '--summary');
706+
if (simple) {
707+
params.push('--name-status');
708+
}
709+
else {
710+
params.push('--numstat', '--summary');
711+
}
701712
}
702713
else {
703714
// Don't include --name-status or -s because Git won't honor it

src/git/gitService.ts

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,10 +1678,10 @@ export class GitService implements Disposable {
16781678
const fileName = GitUri.relativeTo(uri, repoPath);
16791679
let data = await Git.log__file(repoPath, fileName, ref, {
16801680
filters: filters,
1681-
format: GitLogParser.simpleFormat,
16821681
maxCount: skip + 1,
16831682
// startLine: editorLine !== undefined ? editorLine + 1 : undefined,
1684-
reverse: true
1683+
reverse: true,
1684+
simple: true
16851685
});
16861686
if (data == null || data.length === 0) return undefined;
16871687

@@ -1690,9 +1690,9 @@ export class GitService implements Disposable {
16901690
if (status === 'D') {
16911691
data = await Git.log__file(repoPath, '.', nextRef, {
16921692
filters: ['R'],
1693-
format: GitLogParser.simpleFormat,
1694-
maxCount: 1
1693+
maxCount: 1,
16951694
// startLine: editorLine !== undefined ? editorLine + 1 : undefined
1695+
simple: true
16961696
});
16971697
if (data == null || data.length === 0) {
16981698
return GitUri.fromFile(file || fileName, repoPath, nextRef);
@@ -1714,7 +1714,8 @@ export class GitService implements Disposable {
17141714
repoPath: string,
17151715
uri: Uri,
17161716
ref: string | undefined,
1717-
skip: number = 0
1717+
skip: number = 0,
1718+
firstParent: boolean = false
17181719
): Promise<{ current: GitUri; previous: GitUri | undefined } | undefined> {
17191720
if (ref === GitService.deletedOrMissingSha) return undefined;
17201721

@@ -1744,14 +1745,14 @@ export class GitService implements Disposable {
17441745
return {
17451746
// Diff staged with HEAD (or prior if more skips)
17461747
current: GitUri.fromFile(fileName, repoPath, GitService.uncommittedStagedSha),
1747-
previous: await this.getPreviousUri(repoPath, uri, ref, skip - 1)
1748+
previous: await this.getPreviousUri(repoPath, uri, ref, skip - 1, undefined, firstParent)
17481749
};
17491750
}
17501751
else if (status.workingTreeStatus !== undefined) {
17511752
if (skip === 0) {
17521753
return {
17531754
current: GitUri.fromFile(fileName, repoPath, undefined),
1754-
previous: await this.getPreviousUri(repoPath, uri, undefined, skip)
1755+
previous: await this.getPreviousUri(repoPath, uri, undefined, skip, undefined, firstParent)
17551756
};
17561757
}
17571758
}
@@ -1765,25 +1766,25 @@ export class GitService implements Disposable {
17651766
const current =
17661767
skip === 0
17671768
? GitUri.fromFile(fileName, repoPath, ref)
1768-
: (await this.getPreviousUri(repoPath, uri, undefined, skip - 1))!;
1769+
: (await this.getPreviousUri(repoPath, uri, undefined, skip - 1, undefined, firstParent))!;
17691770
if (current === undefined || current.sha === GitService.deletedOrMissingSha) return undefined;
17701771

17711772
return {
17721773
current: current,
1773-
previous: await this.getPreviousUri(repoPath, uri, undefined, skip)
1774+
previous: await this.getPreviousUri(repoPath, uri, undefined, skip, undefined, firstParent)
17741775
};
17751776
}
17761777

17771778
// If we are at a commit, diff commit with previous
17781779
const current =
17791780
skip === 0
17801781
? GitUri.fromFile(fileName, repoPath, ref)
1781-
: (await this.getPreviousUri(repoPath, uri, ref, skip - 1))!;
1782+
: (await this.getPreviousUri(repoPath, uri, ref, skip - 1, undefined, firstParent))!;
17821783
if (current === undefined || current.sha === GitService.deletedOrMissingSha) return undefined;
17831784

17841785
return {
17851786
current: current,
1786-
previous: await this.getPreviousUri(repoPath, uri, ref, skip)
1787+
previous: await this.getPreviousUri(repoPath, uri, ref, skip, undefined, firstParent)
17871788
};
17881789
}
17891790

@@ -1904,7 +1905,8 @@ export class GitService implements Disposable {
19041905
uri: Uri,
19051906
ref?: string,
19061907
skip: number = 0,
1907-
editorLine?: number
1908+
editorLine?: number,
1909+
firstParent: boolean = false
19081910
): Promise<GitUri | undefined> {
19091911
if (ref === GitService.deletedOrMissingSha) return undefined;
19101912

@@ -1914,17 +1916,14 @@ export class GitService implements Disposable {
19141916
ref = undefined;
19151917
}
19161918

1917-
if (ref !== undefined) {
1918-
skip++;
1919-
}
1920-
19211919
const fileName = GitUri.relativeTo(uri, repoPath);
19221920
// TODO: Add caching
19231921
let data;
19241922
try {
19251923
data = await Git.log__file(repoPath, fileName, ref, {
1926-
format: GitLogParser.simpleFormat,
1927-
maxCount: skip + 1,
1924+
maxCount: skip + 2,
1925+
firstParent: firstParent,
1926+
simple: true,
19281927
startLine: editorLine !== undefined ? editorLine + 1 : undefined
19291928
});
19301929
}
@@ -1950,7 +1949,7 @@ export class GitService implements Disposable {
19501949
}
19511950
if (data == null || data.length === 0) return undefined;
19521951

1953-
const [previousRef, file] = GitLogParser.parseSimple(data, skip, editorLine !== undefined ? ref : undefined);
1952+
const [previousRef, file] = GitLogParser.parseSimple(data, skip, ref);
19541953
// If the previous ref matches the ref we asked for assume we are at the end of the history
19551954
if (ref !== undefined && ref === previousRef) return undefined;
19561955

@@ -2343,8 +2342,8 @@ export class GitService implements Disposable {
23432342
// Now check if that commit had any renames
23442343
data = await Git.log__file(repoPath, '.', ref, {
23452344
filters: ['R'],
2346-
format: GitLogParser.simpleFormat,
2347-
maxCount: 1
2345+
maxCount: 1,
2346+
simple: true
23482347
});
23492348
if (data == null || data.length === 0) {
23502349
return GitUri.resolveToUri(fileName, repoPath);

src/git/parsers/logParser.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,8 @@ export class GitLogParser {
460460
static parseSimple(
461461
data: string,
462462
skip: number,
463-
lineRef?: string
463+
skipRef?: string
464464
): [string | undefined, string | undefined, GitFileStatus | undefined] {
465-
// Don't skip 1 extra for line-based previous, as we will be skipping the line ref as needed
466-
if (lineRef !== undefined) {
467-
skip--;
468-
}
469-
470465
let ref;
471466
let diffFile;
472467
let diffRenamed;
@@ -479,16 +474,11 @@ export class GitLogParser {
479474
match = logFileSimpleRegex.exec(data);
480475
if (match == null) break;
481476

477+
if (match[1] === skipRef) continue;
482478
if (skip-- > 0) continue;
483479

484480
[, ref, diffFile, diffRenamed, status, file, renamed] = match;
485481

486-
if (lineRef === ref) {
487-
skip++;
488-
489-
continue;
490-
}
491-
492482
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
493483
file = ` ${diffRenamed || diffFile || renamed || file}`.substr(1);
494484
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
@@ -499,7 +489,11 @@ export class GitLogParser {
499489
logFileSimpleRegex.lastIndex = 0;
500490

501491
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
502-
return [` ${ref}`.substr(1), file, status as GitFileStatus | undefined];
492+
return [
493+
ref == null || ref.length === 0 ? undefined : ` ${ref}`.substr(1),
494+
file,
495+
status as GitFileStatus | undefined
496+
];
503497
}
504498

505499
@debug({ args: false })
@@ -536,6 +530,10 @@ export class GitLogParser {
536530
logFileSimpleRenamedFilesRegex.lastIndex = 0;
537531

538532
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
539-
return [` ${ref}`.substr(1), file, status as GitFileStatus | undefined];
533+
return [
534+
ref == null || ref.length === 0 ? undefined : ` ${ref}`.substr(1),
535+
file,
536+
status as GitFileStatus | undefined
537+
];
540538
}
541539
}

0 commit comments

Comments
 (0)