瀏覽代碼

Adds changes stats for file commits

main
Eric Amodio 5 年之前
父節點
當前提交
79b960cdf3
共有 5 個檔案被更改,包括 115 行新增30 行删除
  1. +8
    -11
      src/git/formatters/commitFormatter.ts
  2. +2
    -2
      src/git/git.ts
  3. +32
    -7
      src/git/models/logCommit.ts
  4. +66
    -9
      src/git/parsers/logParser.ts
  5. +7
    -1
      src/views/nodes/commitFileNode.ts

+ 8
- 11
src/git/formatters/commitFormatter.ts 查看文件

@ -10,7 +10,7 @@ import {
import { DateStyle, FileAnnotationType } from '../../configuration';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { GitCommit, GitCommitType, GitLogCommit, GitRemote, GitService, GitUri } from '../gitService';
import { GitCommit, GitLogCommit, GitRemote, GitService, GitUri } from '../gitService';
import { Strings } from '../../system';
import { FormatOptions, Formatter } from './formatter';
import * as emojis from '../../emojis.json';
@ -143,20 +143,17 @@ export class CommitFormatter extends Formatter {
}
get changes() {
if (!(this._item instanceof GitLogCommit) || this._item.type === GitCommitType.LogFile) {
return this._padOrTruncate(emptyStr, this._options.tokenOptions.changes);
}
return this._padOrTruncate(this._item.getFormattedDiffStatus(), this._options.tokenOptions.changes);
return this._padOrTruncate(
this._item instanceof GitLogCommit ? this._item.getFormattedDiffStatus() : emptyStr,
this._options.tokenOptions.changes
);
}
get changesShort() {
if (!(this._item instanceof GitLogCommit) || this._item.type === GitCommitType.LogFile) {
return this._padOrTruncate(emptyStr, this._options.tokenOptions.changesShort);
}
return this._padOrTruncate(
this._item.getFormattedDiffStatus({ compact: true, separator: emptyStr }),
this._item instanceof GitLogCommit
? this._item.getFormattedDiffStatus({ compact: true, separator: emptyStr })
: emptyStr,
this._options.tokenOptions.changesShort
);
}

+ 2
- 2
src/git/git.ts 查看文件

@ -685,7 +685,7 @@ export class Git {
) {
const [file, root] = Git.splitPath(fileName, repoPath);
const params = ['log', '--name-status', `--format=${format}`];
const params = ['log', `--format=${format}`];
if (maxCount && !reverse) {
params.push(`-n${maxCount}`);
@ -697,7 +697,7 @@ export class Git {
}
if (startLine == null) {
params.push('--name-status');
params.push('--numstat', '--summary');
}
else {
// Don't include --name-status or -s because Git won't honor it

+ 32
- 7
src/git/models/logCommit.ts 查看文件

@ -6,6 +6,12 @@ import { GitUri } from '../gitUri';
import { GitCommit, GitCommitType } from './commit';
import { GitFile, GitFileStatus } from './file';
const emptyStats = Object.freeze({
added: 0,
deleted: 0,
changed: 0
});
export interface GitLogCommitLine {
from: {
line: number;
@ -36,6 +42,12 @@ export class GitLogCommit extends GitCommit {
originalFileName?: string | undefined,
previousSha?: string | undefined,
previousFileName?: string | undefined,
private readonly _fileStats?:
| {
insertions: number;
deletions: number;
}
| undefined,
public readonly parentShas?: string[],
public readonly line?: GitLogCommitLine
) {
@ -69,13 +81,21 @@ export class GitLogCommit extends GitCommit {
@memoize()
getDiffStatus() {
if (this._fileStats !== undefined) {
return {
added: this._fileStats.insertions,
deleted: this._fileStats.deletions,
changed: 0
};
}
if (this.isFile || this.files.length === 0) return emptyStats;
const diff = {
added: 0,
deleted: 0,
changed: 0
};
if (this.files.length === 0) return diff;
for (const f of this.files) {
switch (f.status) {
case 'A':
@ -113,21 +133,24 @@ export class GitLogCommit extends GitCommit {
if (added === 0 && changed === 0 && deleted === 0) return empty || '';
if (expand) {
const type = this.isFile ? 'line' : 'file';
let status = '';
if (added) {
status += `${Strings.pluralize('file', added)} added`;
status += `${Strings.pluralize(type, added)} added`;
}
if (changed) {
status += `${status.length === 0 ? '' : separator}${Strings.pluralize('file', changed)} changed`;
status += `${status.length === 0 ? '' : separator}${Strings.pluralize(type, changed)} changed`;
}
if (deleted) {
status += `${status.length === 0 ? '' : separator}${Strings.pluralize('file', deleted)} deleted`;
status += `${status.length === 0 ? '' : separator}${Strings.pluralize(type, deleted)} deleted`;
}
return `${prefix}${status}${suffix}`;
}
// When `isFile` we are getting line changes -- and we can't get changed lines (only inserts and deletes)
return `${prefix}${compact && added === 0 ? '' : `+${added}${separator}`}${
compact && changed === 0 ? '' : `~${changed}${separator}`
(compact || this.isFile) && changed === 0 ? '' : `~${changed}${separator}`
}${compact && deleted === 0 ? '' : `-${deleted}`}${suffix}`;
}
@ -195,7 +218,9 @@ export class GitLogCommit extends GitCommit {
this.getChangedValue(changes.originalFileName, this.originalFileName),
this.getChangedValue(changes.previousSha, this.previousSha),
this.getChangedValue(changes.previousFileName, this.previousFileName),
undefined
this._fileStats,
this.parentShas,
this.line
);
}
}

+ 66
- 9
src/git/parsers/logParser.ts 查看文件

@ -12,6 +12,10 @@ const diffRegex = /diff --git a\/(.*) b\/(.*)/;
const diffRangeRegex = /^@@ -(\d+?),(\d+?) \+(\d+?),(\d+?) @@/;
export const fileStatusRegex = /(\S)\S*\t([^\t\n]+)(?:\t(.+))?/;
const fileStatusAndSummaryRegex = /^(\d+?|-)\s+?(\d+?|-)\s+?(.*)(?:\n\s(delete|rename|create))?/;
const fileStatusAndSummaryRenamedFileRegex = /(.+)\s=>\s(.+)/;
const fileStatusAndSummaryRenamedFilePathRegex = /(.*?){(.+?)\s=>\s(.+?)}(.*)/;
const logFileSimpleRegex = /^<r> (.*)\s*(?:(?:diff --git a\/(.*) b\/(.*))|(?:(\S)\S*\t([^\t\n]+)(?:\t(.+))?))/gm;
const logFileSimpleRenamedRegex = /^<r> (\S+)\s*(.*)$/s;
const logFileSimpleRenamedFilesRegex = /^(\S)\S*\t([^\t\n]+)(?:\t(.+)?)$/gm;
@ -37,6 +41,10 @@ interface LogEntry {
files?: GitFile[];
status?: GitFileStatus;
fileStats?: {
insertions: number;
deletions: number;
};
summary?: string;
@ -99,6 +107,7 @@ export class GitLogParser {
let match;
let renamedFileName;
let renamedMatch;
while (true) {
next = lines.next();
@ -242,18 +251,64 @@ export class GitLogParser {
break;
}
else {
match = fileStatusRegex.exec(line);
next = lines.next();
match = fileStatusAndSummaryRegex.exec(`${line}\n${next.value}`);
if (match != null) {
entry.status = match[1] as GitFileStatus;
renamedFileName = match[3];
if (renamedFileName !== undefined) {
entry.fileName = renamedFileName;
entry.originalFileName = match[2];
}
else {
entry.fileName = match[2];
entry.fileStats = {
insertions: Number(match[1]) || 0,
deletions: Number(match[2]) || 0
};
switch (match[4]) {
case undefined:
entry.status = 'M' as GitFileStatus;
entry.fileName = match[3];
break;
case 'rename':
entry.status = 'R' as GitFileStatus;
renamedFileName = match[3];
renamedMatch = fileStatusAndSummaryRenamedFilePathRegex.exec(
renamedFileName
);
if (renamedMatch != null) {
entry.fileName = `${renamedMatch[1]}${renamedMatch[3]}${
renamedMatch[4]
}`;
entry.originalFileName = `${renamedMatch[1]}${renamedMatch[2]}${
renamedMatch[4]
}`;
}
else {
renamedMatch = fileStatusAndSummaryRenamedFileRegex.exec(
renamedFileName
);
if (renamedMatch != null) {
entry.fileName = renamedMatch[2];
entry.originalFileName = renamedMatch[1];
}
else {
entry.fileName = renamedFileName;
}
}
break;
case 'create':
entry.status = 'A' as GitFileStatus;
entry.fileName = match[3];
break;
case 'delete':
entry.status = 'D' as GitFileStatus;
entry.fileName = match[3];
break;
default:
entry.status = 'M' as GitFileStatus;
entry.fileName = match[3];
break;
}
}
if (next.done || next.value === '</f>') break;
}
}
}
@ -355,6 +410,7 @@ export class GitLogParser {
const originalFileName =
entry.originalFileName || (relativeFileName !== entry.fileName ? entry.fileName : undefined);
if (type === GitCommitType.LogFile) {
entry.files = [
{
@ -380,6 +436,7 @@ export class GitLogParser {
originalFileName,
type === GitCommitType.Log ? entry.parentShas![0] : undefined,
undefined,
entry.fileStats,
entry.parentShas!,
entry.line
);

+ 7
- 1
src/views/nodes/commitFileNode.ts 查看文件

@ -162,7 +162,13 @@ export class CommitFileNode extends ViewRefFileNode {
this._tooltip = CommitFormatter.fromTemplate(
this.commit.isUncommitted
? `\${author} ${GlyphChars.Dash} \${id}\n${status}\n\${ago} (\${date})`
: `\${author} ${GlyphChars.Dash} \${id}\n${status}\n\${ago} (\${date})\n\n\${message}`,
: `\${author} ${
GlyphChars.Dash
} \${id}\n${status}\n\${ago} (\${date})\n\n\${message}${this.commit.getFormattedDiffStatus({
expand: true,
prefix: '\n\n',
separator: '\n'
})}`,
this.commit,
{
dateFormat: Container.config.defaultDateFormat

Loading…
取消
儲存