diff --git a/src/git/git.ts b/src/git/git.ts index 74c5c12..bc65f1e 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -259,6 +259,14 @@ export class Git { return gitCommand({ cwd: repoPath }, ...params); } + static diff_shortstat(repoPath: string, sha?: string) { + const params = [`diff`, `--shortstat`, `--no-ext-diff`]; + if (sha) { + params.push(sha); + } + return gitCommand({ cwd: repoPath }, ...params); + } + static difftool_dirDiff(repoPath: string, sha1: string, sha2?: string) { const params = [`difftool`, `--dir-diff`, sha1]; if (sha2) { diff --git a/src/git/models/diff.ts b/src/git/models/diff.ts index 5685c9f..ce6b90d 100644 --- a/src/git/models/diff.ts +++ b/src/git/models/diff.ts @@ -33,4 +33,10 @@ export interface GitDiff { chunks: GitDiffChunk[]; diff?: string; +} + +export interface GitDiffShortStat { + files: number; + insertions: number; + deletions: number; } \ No newline at end of file diff --git a/src/git/parsers/diffParser.ts b/src/git/parsers/diffParser.ts index d3ab82b..cdda06a 100644 --- a/src/git/parsers/diffParser.ts +++ b/src/git/parsers/diffParser.ts @@ -1,8 +1,9 @@ 'use strict'; import { Iterables, Strings } from '../../system'; -import { GitDiff, GitDiffChunk, GitDiffChunkLine, GitDiffLine } from './../git'; +import { GitDiff, GitDiffChunk, GitDiffChunkLine, GitDiffLine, GitDiffShortStat } from './../git'; const unifiedDiffRegex = /^@@ -([\d]+),([\d]+) [+]([\d]+),([\d]+) @@([\s\S]*?)(?=^@@)/gm; +const shortStatDiffRegex = /^\s*(\d+)\sfiles? changed(?:,\s+(\d+)\s+insertions?\(\+\))?(?:,\s+(\d+)\s+deletions?\(-\))?/; export class GitDiffParser { @@ -116,4 +117,20 @@ export class GitDiffParser { return chunkLines; } + + static parseShortStat(data: string): GitDiffShortStat | undefined { + if (!data) return undefined; + + const match = shortStatDiffRegex.exec(data); + if (match == null) return undefined; + + const files = match[1]; + const insertions = match[2]; + const deletions = match[3]; + return { + files: files == null ? 0 : parseInt(files, 10), + insertions: insertions == null ? 0 : parseInt(insertions, 10), + deletions: deletions == null ? 0 : parseInt(deletions, 10) + } as GitDiffShortStat; + } } \ No newline at end of file diff --git a/src/gitService.ts b/src/gitService.ts index f7a2608..ad0081f 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -4,7 +4,7 @@ import { Disposable, Event, EventEmitter, FileSystemWatcher, Location, Position, import { IConfig } from './configuration'; import { DocumentSchemes, ExtensionKey, GlyphChars } from './constants'; import { RemoteProviderFactory } from './git/remotes/factory'; -import { Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitDiff, GitDiffChunkLine, GitDiffParser, GitLog, GitLogCommit, GitLogParser, GitRemote, GitRemoteParser, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, IGit, setDefaultEncoding } from './git/git'; +import { Git, GitAuthor, GitBlame, GitBlameCommit, GitBlameLine, GitBlameLines, GitBlameParser, GitBranch, GitBranchParser, GitCommit, GitDiff, GitDiffChunkLine, GitDiffParser, GitDiffShortStat, GitLog, GitLogCommit, GitLogParser, GitRemote, GitRemoteParser, GitStash, GitStashParser, GitStatus, GitStatusFile, GitStatusParser, IGit, setDefaultEncoding } from './git/git'; import { GitUri, IGitCommitInfo, IGitUriData } from './git/gitUri'; import { Logger } from './logger'; import * as fs from 'fs'; @@ -599,6 +599,10 @@ export class GitService extends Disposable { return Git.normalizePath(typeof fileNameOrUri === 'string' ? fileNameOrUri : fileNameOrUri.fsPath).toLowerCase(); } + async getChangedFilesCount(repoPath: string, sha?: string): Promise { + return GitDiffParser.parseShortStat(await Git.diff_shortstat(repoPath, sha)); + } + async getConfig(key: string, repoPath?: string): Promise { Logger.log(`getConfig('${key}', '${repoPath}')`);