Browse Source

Adds merge conflict parsing to status

main
Eric Amodio 4 years ago
parent
commit
f2d885b2d8
14 changed files with 323 additions and 94 deletions
  1. +16
    -3
      package.json
  2. +4
    -1
      src/git/formatters/commitFormatter.ts
  3. +2
    -2
      src/git/git.ts
  4. +4
    -0
      src/git/models/commit.ts
  5. +58
    -19
      src/git/models/file.ts
  6. +5
    -0
      src/git/models/logCommit.ts
  7. +9
    -3
      src/git/models/stashCommit.ts
  8. +184
    -26
      src/git/models/status.ts
  9. +1
    -0
      src/git/parsers/diffParser.ts
  10. +15
    -15
      src/git/parsers/logParser.ts
  11. +3
    -3
      src/git/parsers/stashParser.ts
  12. +9
    -15
      src/git/parsers/statusParser.ts
  13. +5
    -1
      src/views/nodes/fileRevisionAsCommitNode.ts
  14. +8
    -6
      src/views/nodes/lineHistoryNode.ts

+ 16
- 3
package.json View File

@ -3705,7 +3705,8 @@
{
"command": "gitlens.views.openChanges",
"title": "Open Changes",
"category": "GitLens"
"category": "GitLens",
"icon": "$(compare-changes)"
},
{
"command": "gitlens.views.openChangesWithWorking",
@ -7184,7 +7185,7 @@
},
{
"command": "gitlens.views.selectFileForCompare",
"when": "viewItem =~ /gitlens:file\\b/",
"when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/",
"group": "4_gitlens_compare@99"
},
{
@ -7348,8 +7349,18 @@
"alt": "gitlens.views.openFile"
},
{
"command": "gitlens.views.openChanges",
"when": "view =~ /gitlens\\.views\\.(?!fileHistory|lineHistory)\\b/ && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+conflicted\\b)/",
"group": "inline@96"
},
{
"command": "gitlens.views.openFile",
"when": "view =~ /gitlens\\.views\\.(fileHistory|lineHistory)\\b/ && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+conflicted\\b)/",
"group": "inline@96"
},
{
"command": "gitlens.views.openChangesWithWorking",
"when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+unstaged\\b)/",
"when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+(conflicted|unstaged)\\b)/",
"group": "inline@96"
},
{
@ -8115,10 +8126,12 @@
"gitlens/commit/file/openChanges": [
{
"command": "gitlens.externalDiff",
"when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/",
"group": "1_gitlens@1"
},
{
"command": "gitlens.views.openChangesWithWorking",
"whsen": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/",
"group": "1_gitlens@2"
},
{

+ 4
- 1
src/git/formatters/commitFormatter.ts View File

@ -414,12 +414,15 @@ export class CommitFormatter extends Formatter {
get message(): string {
if (this._item.isUncommitted) {
const confliced = this._item.hasConflicts;
const staged =
this._item.isUncommittedStaged ||
(this._options.previousLineDiffUris?.current?.isUncommittedStaged ?? false);
return this._padOrTruncate(
`${this._options.markdown ? '\n> ' : ''}${staged ? 'Staged' : 'Uncommitted'} changes`,
`${this._options.markdown ? '\n> ' : ''}${
confliced ? 'Merge' : staged ? 'Staged' : 'Uncommitted'
} changes`,
this._options.tokenOptions.message,
);
}

+ 2
- 2
src/git/git.ts View File

@ -10,7 +10,7 @@ import { Objects, Strings } from '../system';
import { findGitPath, GitLocation } from './locator';
import { fsExists, run, RunError, RunOptions } from './shell';
import { GitBranchParser, GitLogParser, GitReflogParser, GitStashParser, GitTagParser } from './parsers/parsers';
import { GitFileStatus, GitRevision } from './models/models';
import { GitRevision } from './models/models';
export * from './models/models';
export * from './parsers/parsers';
@ -19,7 +19,7 @@ export * from './remotes/provider';
export * from './search';
export { RunError } from './shell';
export type GitDiffFilter = Exclude<GitFileStatus, '!' | '?'>;;
export type GitDiffFilter = 'A' | 'C' | 'D' | 'M' | 'R' | 'T' | 'U' | 'X' | 'B' | '*';;
const emptyArray = (Object.freeze([]) as any) as any[];
const emptyObj = Object.freeze({});

+ 4
- 0
src/git/models/commit.ts View File

@ -69,6 +69,10 @@ export abstract class GitCommit implements GitRevisionReference {
this._fileName = fileName || '';
}
get hasConflicts(): boolean {
return false;
}
get ref() {
return this.sha;
}

+ 58
- 19
src/git/models/file.ts View File

@ -4,13 +4,40 @@ import { Strings } from '../../system';
import { GitUri } from '../gitUri';
import { GitLogCommit } from './logCommit';
export declare type GitFileStatus = '!' | '?' | 'A' | 'C' | 'D' | 'M' | 'R' | 'T' | 'U' | 'X' | 'B';
export declare type GitFileStatus = GitFileConflictStatus | GitFileIndexStatus | GitFileWorkingTreeStatus;
export enum GitFileConflictStatus {
AddedByBoth = 'AA',
AddedByUs = 'AU',
AddedByThem = 'UA',
DeletedByBoth = 'DD',
DeletedByUs = 'DU',
DeletedByThem = 'UD',
ModifiedByBoth = 'UU',
}
export enum GitFileIndexStatus {
Added = 'A',
Deleted = 'D',
Modified = 'M',
Renamed = 'R',
Copied = 'C',
}
export enum GitFileWorkingTreeStatus {
Added = 'A',
Deleted = 'D',
Modified = 'M',
Untracked = '?',
Ignored = '!',
}
export interface GitFile {
status: GitFileStatus;
status: GitFileConflictStatus | GitFileIndexStatus | GitFileWorkingTreeStatus;
readonly repoPath?: string;
readonly indexStatus?: GitFileStatus;
readonly workingTreeStatus?: GitFileStatus;
readonly conflictStatus?: GitFileConflictStatus;
readonly indexStatus?: GitFileIndexStatus;
readonly workingTreeStatus?: GitFileWorkingTreeStatus;
readonly fileName: string;
readonly originalFileName?: string;
}
@ -63,53 +90,65 @@ export namespace GitFile {
'!': 'icon-status-ignored.svg',
'?': 'icon-status-untracked.svg',
A: 'icon-status-added.svg',
C: 'icon-status-copied.svg',
D: 'icon-status-deleted.svg',
M: 'icon-status-modified.svg',
R: 'icon-status-renamed.svg',
C: 'icon-status-copied.svg',
AA: 'icon-status-conflict.svg',
AU: 'icon-status-conflict.svg',
UA: 'icon-status-conflict.svg',
DD: 'icon-status-conflict.svg',
DU: 'icon-status-conflict.svg',
UD: 'icon-status-conflict.svg',
UU: 'icon-status-conflict.svg',
T: 'icon-status-modified.svg',
U: 'icon-status-conflict.svg',
X: 'icon-status-unknown.svg',
B: 'icon-status-unknown.svg',
};
export function getStatusIcon(status: GitFileStatus): string {
return statusIconsMap[status] || statusIconsMap['X'];
return statusIconsMap[status] ?? 'icon-status-unknown.svg';
}
const statusCodiconsMap = {
'!': '$(diff-ignored)',
'?': '$(diff-added)',
A: '$(diff-added)',
C: '$(diff-added)',
D: '$(diff-removed)',
M: '$(diff-modified)',
R: '$(diff-renamed)',
C: '$(diff-added)',
AA: '$(warning)',
AU: '$(warning)',
UA: '$(warning)',
DD: '$(warning)',
DU: '$(warning)',
UD: '$(warning)',
UU: '$(warning)',
T: '$(diff-modified)',
U: '$(alert)',
X: '$(question)',
B: '$(question)',
};
export function getStatusCodicon(status: GitFileStatus, missing: string = GlyphChars.Space.repeat(4)): string {
return statusCodiconsMap[status] || missing;
return statusCodiconsMap[status] ?? missing;
}
const statusTextMap = {
'!': 'Ignored',
'?': 'Untracked',
A: 'Added',
C: 'Copied',
D: 'Deleted',
M: 'Modified',
R: 'Renamed',
C: 'Copied',
AA: 'Conflict',
AU: 'Conflict',
UA: 'Conflict',
DD: 'Conflict',
DU: 'Conflict',
UD: 'Conflict',
UU: 'Conflict',
T: 'Modified',
U: 'Conflict',
X: 'Unknown',
B: 'Unknown',
};
export function getStatusText(status: GitFileStatus): string {
return statusTextMap[status] || statusTextMap['X'];
return statusTextMap[status] ?? 'Unknown';
}
}

+ 5
- 0
src/git/models/logCommit.ts View File

@ -80,6 +80,11 @@ export class GitLogCommit extends GitCommit {
);
}
@memoize()
get hasConflicts() {
return this.files.some(f => f.conflictStatus != null);
}
get isMerge() {
return this.parentShas != null && this.parentShas.length > 1;
}

+ 9
- 3
src/git/models/stashCommit.ts View File

@ -1,7 +1,7 @@
'use strict';
import { GitCommitType } from './commit';
import { Container } from '../../container';
import { GitFile } from './file';
import { GitFile, GitFileWorkingTreeStatus } from './file';
import { GitLogCommit } from './logCommit';
import { GitReference } from './models';
import { gate, memoize } from '../../system';
@ -61,9 +61,15 @@ export class GitStashCommit extends GitLogCommit {
const commit = await Container.git.getCommit(this.repoPath, `${this.stashName}^3`);
if (commit != null && commit.files.length !== 0) {
// Since these files are untracked -- make them look that way
commit.files.forEach(s => (s.status = '?'));
const files = commit.files.map(s => ({
...s,
status: GitFileWorkingTreeStatus.Untracked,
conflictStatus: undefined,
indexStatus: undefined,
workingTreeStatus: GitFileWorkingTreeStatus.Untracked,
}));
this.files.push(...commit.files);
this.files.push(...files);
}
}
}

+ 184
- 26
src/git/models/status.ts View File

@ -3,7 +3,7 @@ import { Uri } from 'vscode';
import { GitBranch, GitTrackingState } from './branch';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { GitFile, GitFileStatus } from './file';
import { GitFile, GitFileConflictStatus, GitFileIndexStatus, GitFileStatus, GitFileWorkingTreeStatus } from './file';
import { GitUri } from '../gitUri';
import { GitCommitType, GitLogCommit, GitRemote, GitRevision } from './models';
import { memoize, Strings } from '../../system';
@ -16,6 +16,10 @@ export interface ComputedWorkingTreeGitStatus {
unstaged: number;
unstagedAddsAndChanges: GitStatusFile[];
unstagedStatus: string;
conflicted: number;
conflictedAddsAndChanges: GitStatusFile[];
conflictedStatus: string;
}
export class GitStatus {
@ -35,12 +39,25 @@ export class GitStatus {
}
}
@memoize()
get conflicts() {
return this.files.filter(f => f.conflicted);
}
@memoize()
get hasConflicts() {
return this.files.some(f => f.conflicted);
}
get ref() {
return this.detached ? this.sha : this.branch;
}
@memoize()
computeWorkingTreeStatus(): ComputedWorkingTreeGitStatus {
let conflictedAdds = 0;
let conflictedDeletes = 0;
let conflictedChanges = 0;
let stagedAdds = 0;
let unstagedAdds = 0;
let stagedChanges = 0;
@ -48,24 +65,47 @@ export class GitStatus {
let stagedDeletes = 0;
let unstagedDeletes = 0;
const conflictedAddsAndChanges: GitStatusFile[] = [];
const stagedAddsAndChanges: GitStatusFile[] = [];
const unstagedAddsAndChanges: GitStatusFile[] = [];
for (const f of this.files) {
switch (f.indexStatus) {
case 'A':
case '?':
stagedAdds++;
switch (f.conflictStatus) {
case undefined:
break;
case GitFileConflictStatus.AddedByBoth:
case GitFileConflictStatus.AddedByUs:
case GitFileConflictStatus.AddedByThem:
conflictedAdds++;
stagedAddsAndChanges.push(f);
break;
case 'D':
stagedDeletes++;
case GitFileConflictStatus.DeletedByBoth:
case GitFileConflictStatus.DeletedByUs:
case GitFileConflictStatus.DeletedByThem:
conflictedDeletes++;
break;
default:
conflictedChanges++;
conflictedAddsAndChanges.push(f);
break;
}
switch (f.indexStatus) {
case undefined:
break;
case GitFileIndexStatus.Added:
stagedAdds++;
stagedAddsAndChanges.push(f);
break;
case GitFileIndexStatus.Deleted:
stagedDeletes++;
break;
default:
stagedChanges++;
stagedAddsAndChanges.push(f);
@ -73,19 +113,20 @@ export class GitStatus {
}
switch (f.workingTreeStatus) {
case 'A':
case '?':
case undefined:
case GitFileWorkingTreeStatus.Ignored:
break;
case GitFileWorkingTreeStatus.Added:
case GitFileWorkingTreeStatus.Untracked:
unstagedAdds++;
unstagedAddsAndChanges.push(f);
break;
case 'D':
case GitFileWorkingTreeStatus.Deleted:
unstagedDeletes++;
break;
case undefined:
break;
default:
unstagedChanges++;
unstagedAddsAndChanges.push(f);
@ -93,10 +134,14 @@ export class GitStatus {
}
}
const conflicted = conflictedAdds + conflictedChanges + conflictedDeletes;
const staged = stagedAdds + stagedChanges + stagedDeletes;
const unstaged = unstagedAdds + unstagedChanges + unstagedDeletes;
return {
conflicted: conflicted,
conflictedAddsAndChanges: conflictedAddsAndChanges,
conflictedStatus: conflicted > 0 ? `+${conflictedAdds} ~${conflictedChanges} -${conflictedDeletes}` : '',
staged: staged,
stagedStatus: staged > 0 ? `+${stagedAdds} ~${stagedChanges} -${stagedDeletes}` : '',
stagedAddsAndChanges: stagedAddsAndChanges,
@ -244,26 +289,98 @@ export class GitStatus {
}
export class GitStatusFile implements GitFile {
public readonly conflictStatus: GitFileConflictStatus | undefined;
public readonly indexStatus: GitFileIndexStatus | undefined;
public readonly workingTreeStatus: GitFileWorkingTreeStatus | undefined;
constructor(
public readonly repoPath: string,
public readonly indexStatus: GitFileStatus | undefined,
public readonly workingTreeStatus: GitFileStatus | undefined,
x: string | undefined,
y: string | undefined,
public readonly fileName: string,
public readonly originalFileName?: string,
) {}
) {
if (x != null && y != null) {
switch (x + y) {
case '??':
this.workingTreeStatus = GitFileWorkingTreeStatus.Untracked;
break;
case '!!':
this.workingTreeStatus = GitFileWorkingTreeStatus.Ignored;
break;
case 'AA':
this.conflictStatus = GitFileConflictStatus.AddedByBoth;
break;
case 'AU':
this.conflictStatus = GitFileConflictStatus.AddedByUs;
break;
case 'UA':
this.conflictStatus = GitFileConflictStatus.AddedByThem;
break;
case 'DD':
this.conflictStatus = GitFileConflictStatus.DeletedByBoth;
break;
case 'DU':
this.conflictStatus = GitFileConflictStatus.DeletedByUs;
break;
case 'UD':
this.conflictStatus = GitFileConflictStatus.DeletedByThem;
break;
case 'UU':
this.conflictStatus = GitFileConflictStatus.ModifiedByBoth;
break;
}
}
get edited() {
return this.workingTreeStatus != null;
if (this.conflictStatus == null) {
switch (x) {
case 'A':
this.indexStatus = GitFileIndexStatus.Added;
break;
case 'D':
this.indexStatus = GitFileIndexStatus.Deleted;
break;
case 'M':
this.indexStatus = GitFileIndexStatus.Modified;
break;
case 'R':
this.indexStatus = GitFileIndexStatus.Renamed;
break;
case 'C':
this.indexStatus = GitFileIndexStatus.Copied;
break;
}
switch (y) {
case 'A':
this.workingTreeStatus = GitFileWorkingTreeStatus.Modified;
break;
case 'D':
this.workingTreeStatus = GitFileWorkingTreeStatus.Modified;
break;
case 'M':
this.workingTreeStatus = GitFileWorkingTreeStatus.Modified;
break;
}
}
}
get status(): GitFileStatus {
return this.indexStatus ?? this.workingTreeStatus ?? '?';
get conflicted() {
return this.conflictStatus != null;
}
get edited() {
return this.workingTreeStatus != null;
}
get staged() {
return this.indexStatus != null;
}
get status(): GitFileStatus {
return (this.conflictStatus ?? this.indexStatus ?? this.workingTreeStatus)!;
}
@memoize()
get uri(): Uri {
return GitUri.resolveToUri(this.fileName, this.repoPath);
@ -286,9 +403,32 @@ export class GitStatusFile implements GitFile {
}
async toPsuedoCommits(): Promise<GitLogCommit[]> {
if (this.workingTreeStatus == null && this.indexStatus == null) return [];
const commits: GitLogCommit[] = [];
if (this.conflictStatus != null) {
const user = await Container.git.getCurrentUser(this.repoPath);
commits.push(
new GitLogCommit(
GitCommitType.LogFile,
this.repoPath,
GitRevision.uncommitted,
'You',
user?.email ?? undefined,
new Date(),
new Date(),
'',
this.fileName,
[this],
this.status,
this.originalFileName,
GitRevision.uncommittedStaged,
this.originalFileName ?? this.fileName,
),
);
return commits;
}
const commits = [];
if (this.workingTreeStatus == null && this.indexStatus == null) return commits;
const user = await Container.git.getCurrentUser(this.repoPath);
if (this.workingTreeStatus != null && this.indexStatus != null) {
@ -351,15 +491,33 @@ export class GitStatusFile implements GitFile {
}
with(changes: {
indexStatus?: GitFileStatus | null;
workTreeStatus?: GitFileStatus | null;
conflictStatus?: GitFileConflictStatus | null;
indexStatus?: GitFileIndexStatus | null;
workTreeStatus?: GitFileWorkingTreeStatus | null;
fileName?: string;
originalFileName?: string | null;
}): GitStatusFile {
const working = this.getChangedValue(changes.workTreeStatus, this.workingTreeStatus);
let status: string;
switch (working) {
case GitFileWorkingTreeStatus.Untracked:
status = '??';
break;
case GitFileWorkingTreeStatus.Ignored:
status = '!!';
break;
default:
status =
this.getChangedValue(changes.conflictStatus, this.conflictStatus) ??
`${this.getChangedValue(changes.indexStatus, this.indexStatus) ?? ' '}${working ?? ' '}`;
break;
}
return new GitStatusFile(
this.repoPath,
this.getChangedValue(changes.indexStatus, this.indexStatus) as GitFileStatus,
this.getChangedValue(changes.workTreeStatus, this.workingTreeStatus) as GitFileStatus,
status[0]?.trim() || undefined,
status[1]?.trim() || undefined,
changes.fileName ?? this.fileName,
this.getChangedValue(changes.originalFileName, this.originalFileName),
);

+ 1
- 0
src/git/parsers/diffParser.ts View File

@ -154,6 +154,7 @@ export class GitDiffParser {
files.push({
repoPath: repoPath,
status: (!status.startsWith('.') ? status[0].trim() : '?') as GitFileStatus,
conflictStatus: undefined,
indexStatus: undefined,
workingTreeStatus: undefined,
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869

+ 15
- 15
src/git/parsers/logParser.ts View File

@ -5,7 +5,7 @@ import {
GitAuthor,
GitCommitType,
GitFile,
GitFileStatus,
GitFileIndexStatus,
GitLog,
GitLogCommit,
GitLogCommitLine,
@ -50,7 +50,7 @@ interface LogEntry {
originalFileName?: string;
files?: GitFile[];
status?: GitFileStatus;
status?: GitFileIndexStatus;
fileStats?: {
insertions: number;
deletions: number;
@ -224,13 +224,13 @@ export class GitLogParser {
renamedFileName = match[3];
if (renamedFileName !== undefined) {
entry.files.push({
status: match[1] as GitFileStatus,
status: match[1] as GitFileIndexStatus,
fileName: renamedFileName,
originalFileName: match[2],
});
} else {
entry.files.push({
status: match[1] as GitFileStatus,
status: match[1] as GitFileIndexStatus,
fileName: match[2],
});
}
@ -241,9 +241,9 @@ export class GitLogParser {
[, entry.originalFileName, entry.fileName] = match;
if (entry.fileName === entry.originalFileName) {
entry.originalFileName = undefined;
entry.status = 'M';
entry.status = GitFileIndexStatus.Modified;
} else {
entry.status = 'R';
entry.status = GitFileIndexStatus.Renamed;
}
void lines.next();
@ -280,12 +280,12 @@ export class GitLogParser {
switch (match[4]) {
case undefined:
entry.status = 'M' as GitFileStatus;
entry.status = 'M' as GitFileIndexStatus;
entry.fileName = match[3];
break;
case 'copy':
case 'rename':
entry.status = (match[4] === 'copy' ? 'C' : 'R') as GitFileStatus;
entry.status = (match[4] === 'copy' ? 'C' : 'R') as GitFileIndexStatus;
renamedFileName = match[3];
renamedMatch = fileStatusAndSummaryRenamedFilePathRegex.exec(
@ -312,15 +312,15 @@ export class GitLogParser {
break;
case 'create':
entry.status = 'A' as GitFileStatus;
entry.status = 'A' as GitFileIndexStatus;
entry.fileName = match[3];
break;
case 'delete':
entry.status = 'D' as GitFileStatus;
entry.status = 'D' as GitFileIndexStatus;
entry.fileName = match[3];
break;
default:
entry.status = 'M' as GitFileStatus;
entry.status = 'M' as GitFileIndexStatus;
entry.fileName = match[3];
break;
}
@ -523,7 +523,7 @@ export class GitLogParser {
data: string,
skip: number,
skipRef?: string,
): [string | undefined, string | undefined, GitFileStatus | undefined] {
): [string | undefined, string | undefined, GitFileIndexStatus | undefined] {
let ref;
let diffFile;
let diffRenamed;
@ -554,7 +554,7 @@ export class GitLogParser {
return [
ref == null || ref.length === 0 ? undefined : ` ${ref}`.substr(1),
file,
status as GitFileStatus | undefined,
status as GitFileIndexStatus | undefined,
];
}
@ -562,7 +562,7 @@ export class GitLogParser {
static parseSimpleRenamed(
data: string,
originalFileName: string,
): [string | undefined, string | undefined, GitFileStatus | undefined] {
): [string | undefined, string | undefined, GitFileIndexStatus | undefined] {
let match = logFileSimpleRenamedRegex.exec(data);
if (match == null) return [undefined, undefined, undefined];
@ -600,7 +600,7 @@ export class GitLogParser {
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
ref == null || ref.length === 0 || file == null ? undefined : ` ${ref}`.substr(1),
file,
status as GitFileStatus | undefined,
status as GitFileIndexStatus | undefined,
];
}
}

+ 3
- 3
src/git/parsers/stashParser.ts View File

@ -1,5 +1,5 @@
'use strict';
import { fileStatusRegex, GitCommitType, GitFile, GitFileStatus, GitStash, GitStashCommit } from '../git';
import { fileStatusRegex, GitCommitType, GitFile, GitFileIndexStatus, GitStash, GitStashCommit } from '../git';
import { Arrays, debug, Strings } from '../../system';
// import { Logger } from './logger';
@ -129,13 +129,13 @@ export class GitStashParser {
renamedFileName = match[3];
if (renamedFileName !== undefined) {
entry.files.push({
status: match[1] as GitFileStatus,
status: match[1] as GitFileIndexStatus,
fileName: renamedFileName,
originalFileName: match[2],
});
} else {
entry.files.push({
status: match[1] as GitFileStatus,
status: match[1] as GitFileIndexStatus,
fileName: match[2],
});
}

+ 9
- 15
src/git/parsers/statusParser.ts View File

@ -1,6 +1,6 @@
'use strict';
import { debug, Strings } from '../../system';
import { GitFileStatus, GitStatus, GitStatusFile } from '../git';
import { GitStatus, GitStatusFile } from '../git';
const emptyStr = '';
@ -131,25 +131,19 @@ export class GitStatusParser {
fileName: string,
originalFileName?: string,
): GitStatusFile {
let indexStatus = !rawStatus.startsWith('.') ? rawStatus[0].trim() : undefined;
if (indexStatus == null || indexStatus.length === 0) {
indexStatus = undefined;
let x = !rawStatus.startsWith('.') ? rawStatus[0].trim() : undefined;
if (x == null || x.length === 0) {
x = undefined;
}
let workTreeStatus = undefined;
let y = undefined;
if (rawStatus.length > 1) {
workTreeStatus = rawStatus[1] !== '.' ? rawStatus[1].trim() : undefined;
if (workTreeStatus == null || workTreeStatus.length === 0) {
workTreeStatus = undefined;
y = rawStatus[1] !== '.' ? rawStatus[1].trim() : undefined;
if (y == null || y.length === 0) {
y = undefined;
}
}
return new GitStatusFile(
repoPath,
indexStatus as GitFileStatus | undefined,
workTreeStatus as GitFileStatus | undefined,
fileName,
originalFileName,
);
return new GitStatusFile(repoPath, x, y, fileName, originalFileName);
}
}

+ 5
- 1
src/views/nodes/fileRevisionAsCommitNode.ts View File

@ -133,7 +133,11 @@ export class FileRevisionAsCommitNode extends ViewRefFileNode
}${this._options.unpublished ? '+unpublished' : ''}`;
}
return this.commit.isUncommittedStaged ? `${ContextValues.File}+staged` : `${ContextValues.File}+unstaged`;
return this.commit.hasConflicts
? `${ContextValues.File}+conflicted`
: this.commit.isUncommittedStaged
? `${ContextValues.File}+staged`
: `${ContextValues.File}+unstaged`;
}
getCommand(): Command | undefined {

+ 8
- 6
src/views/nodes/lineHistoryNode.ts View File

@ -8,6 +8,7 @@ import {
GitBranch,
GitCommitType,
GitFile,
GitFileIndexStatus,
GitLog,
GitLogCommit,
GitRevision,
@ -101,12 +102,13 @@ export class LineHistoryNode
const status = await Container.git.getStatusForFile(this.uri.repoPath!, this.uri.fsPath);
const file: GitFile = {
conflictStatus: status?.conflictStatus,
fileName: commit.fileName,
indexStatus: status?.indexStatus ?? '?',
indexStatus: status?.indexStatus,
originalFileName: commit.originalFileName,
repoPath: this.uri.repoPath!,
status: 'M',
workingTreeStatus: status?.workingTreeStatus ?? '?',
status: status?.status ?? GitFileIndexStatus.Modified,
workingTreeStatus: status?.workingTreeStatus,
};
if (status?.workingTreeStatus != null && status?.indexStatus != null) {
@ -121,7 +123,7 @@ export class LineHistoryNode
commit.message,
commit.fileName,
[file],
'M',
GitFileIndexStatus.Modified,
commit.originalFileName,
commit.previousSha,
commit.originalFileName ?? commit.fileName,
@ -146,7 +148,7 @@ export class LineHistoryNode
commit.message,
commit.fileName,
[file],
'M',
GitFileIndexStatus.Modified,
commit.originalFileName,
GitRevision.uncommittedStaged,
commit.originalFileName ?? commit.fileName,
@ -175,7 +177,7 @@ export class LineHistoryNode
commit.message,
commit.fileName,
[file],
'M',
GitFileIndexStatus.Modified,
commit.originalFileName,
commit.previousSha,
commit.originalFileName ?? commit.fileName,

Loading…
Cancel
Save