diff --git a/src/git/git.ts b/src/git/git.ts index e301b6b..7531d21 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -395,6 +395,16 @@ export class Git { } } + static async config_getRegex(pattern: string, repoPath?: string) { + try { + const data = await gitCommandCore({ cwd: repoPath || '' }, 'config', '--get-regex', pattern); + return data.trim(); + } + catch { + return undefined; + } + } + static diff(repoPath: string, fileName: string, sha1?: string, sha2?: string, options: { encoding?: string } = {}) { const params = ['-c', 'color.diff=false', 'diff', '--diff-filter=M', '-M', '--no-ext-diff', '--minimal']; if (sha1) { diff --git a/src/git/parsers/blameParser.ts b/src/git/parsers/blameParser.ts index 248cb99..5771220 100644 --- a/src/git/parsers/blameParser.ts +++ b/src/git/parsers/blameParser.ts @@ -28,7 +28,7 @@ export class GitBlameParser { data: string, repoPath: string | undefined, fileName: string, - currentUser: string | undefined + currentUser: { name?: string, email?: string } | undefined ): GitBlame | undefined { if (!data) return undefined; @@ -69,9 +69,6 @@ export class GitBlameParser { .slice(1) .join(' ') .trim(); - if (currentUser !== undefined && currentUser === entry.author) { - entry.author = 'You'; - } } break; @@ -125,7 +122,7 @@ export class GitBlameParser { } first = false; - GitBlameParser.parseEntry(entry, repoPath, relativeFileName, commits, authors, lines); + GitBlameParser.parseEntry(entry, repoPath, relativeFileName, commits, authors, lines, currentUser); entry = undefined; break; @@ -160,11 +157,20 @@ export class GitBlameParser { fileName: string | undefined, commits: Map, authors: Map, - lines: GitCommitLine[] + lines: GitCommitLine[], + currentUser: {name?: string, email?: string} | undefined ) { let commit = commits.get(entry.sha); if (commit === undefined) { if (entry.author !== undefined) { + if ( + currentUser !== undefined && + (currentUser.name !== undefined || currentUser.email !== undefined) && + (currentUser.name === undefined || currentUser.name === entry.author) && + (currentUser.email === undefined || currentUser.email === entry.authorEmail) + ) { + entry.author = 'You'; + } let author = authors.get(entry.author); if (author === undefined) { author = { diff --git a/src/git/parsers/logParser.ts b/src/git/parsers/logParser.ts index 732a5a1..577c0f5 100644 --- a/src/git/parsers/logParser.ts +++ b/src/git/parsers/logParser.ts @@ -32,7 +32,7 @@ export class GitLogParser { repoPath: string | undefined, fileName: string | undefined, sha: string | undefined, - currentUser: string | undefined, + currentUser: { name?: string; email?: string } | undefined, maxCount: number | undefined, reverse: boolean, range: Range | undefined @@ -87,9 +87,6 @@ export class GitLogParser { } else { entry.author = line.substring(4); - if (currentUser !== undefined && currentUser === entry.author) { - entry.author = 'You'; - } } break; @@ -211,7 +208,8 @@ export class GitLogParser { relativeFileName, commits, authors, - recentCommit + recentCommit, + currentUser ); break; @@ -238,10 +236,19 @@ export class GitLogParser { relativeFileName: string, commits: Map, authors: Map, - recentCommit: GitLogCommit | undefined + recentCommit: GitLogCommit | undefined, + currentUser: {name?: string, email?: string} | undefined ): GitLogCommit | undefined { if (commit === undefined) { if (entry.author !== undefined) { + if ( + currentUser !== undefined && + (currentUser.name !== undefined || currentUser.email !== undefined) && + (currentUser.name === undefined || currentUser.name === entry.author) && + (currentUser.email === undefined || currentUser.email === entry.email) + ) { + entry.author = 'You'; + } let author = authors.get(entry.author); if (author === undefined) { author = { diff --git a/src/gitService.ts b/src/gitService.ts index e6cd12f..c62923b 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -612,7 +612,7 @@ export class GitService extends Disposable { args: Container.config.advanced.blame.customArguments, ignoreWhitespace: Container.config.blame.ignoreWhitespace }); - const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUsername(root)); + const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUser(root)); return blame; } catch (ex) { @@ -692,7 +692,7 @@ export class GitService extends Disposable { correlationKey: `:${key}`, ignoreWhitespace: Container.config.blame.ignoreWhitespace }); - const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUsername(root)); + const blame = GitBlameParser.parse(data, root, file, await this.getCurrentUser(root)); return blame; } catch (ex) { @@ -755,7 +755,7 @@ export class GitService extends Disposable { data, uri.repoPath, fileName, - await this.getCurrentUsername(uri.repoPath!) + await this.getCurrentUser(uri.repoPath!) ); if (blame === undefined) return undefined; @@ -808,7 +808,7 @@ export class GitService extends Disposable { startLine: lineToBlame, endLine: lineToBlame }); - const currentUser = await this.getCurrentUsername(uri.repoPath!); + const currentUser = await this.getCurrentUser(uri.repoPath!); const blame = GitBlameParser.parse(data, uri.repoPath, fileName, currentUser); if (blame === undefined) return undefined; @@ -925,14 +925,34 @@ export class GitService extends Disposable { } // TODO: Clear cache when git config changes - private _userNameMapCache: Map = new Map(); + private _userMapCache = new Map(); - async getCurrentUsername(repoPath: string) { - let user = this._userNameMapCache.get(repoPath); - if (user === undefined) { - user = await Git.config_get('user.name', repoPath); - this._userNameMapCache.set(repoPath, user); + async getCurrentUser(repoPath: string) { + let user = this._userMapCache.get(repoPath); + if (user != null) return user; + if (user === null) return undefined; + + const data = await Git.config_getRegex('user.(name|email)', repoPath); + if (!data) { + this._userMapCache.set(repoPath, null); + return undefined; } + + user = { name: undefined, email: undefined }; + + let match: RegExpExecArray | null = null; + const userConfigRegex = /^user\.(name|email) (.*)$/gm; + do { + match = userConfigRegex.exec(data); + if (match == null) { + break; + } + + // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 + user[match[1] as 'name' | 'email'] = (' ' + match[2]).substr(1); + } while (match !== null); + + this._userMapCache.set(repoPath, user); return user; } @@ -1120,7 +1140,7 @@ export class GitService extends Disposable { repoPath, undefined, options.ref, - await this.getCurrentUsername(repoPath), + await this.getCurrentUser(repoPath), maxCount, options.reverse!, undefined @@ -1182,7 +1202,7 @@ export class GitService extends Disposable { repoPath, undefined, undefined, - await this.getCurrentUsername(repoPath), + await this.getCurrentUser(repoPath), maxCount, false, undefined @@ -1337,7 +1357,7 @@ export class GitService extends Disposable { root, file, opts.ref, - await this.getCurrentUsername(root), + await this.getCurrentUser(root), maxCount, opts.reverse!, range