@@ -6,7 +6,7 @@ import * as vscode from 'vscode';
66import { AskpassEnvironment , AskpassManager } from './askpass/askpassManager' ;
77import { getConfig } from './config' ;
88import { Logger } from './logger' ;
9- import { CommitOrdering , DateType , DeepWriteable , ErrorInfo , ErrorInfoExtensionPrefix , GitCommit , GitCommitDetails , GitCommitStash , GitConfigLocation , GitFileChange , GitFileStatus , GitPushBranchMode , GitRepoConfig , GitRepoConfigBranches , GitResetMode , GitSignature , GitSignatureStatus , GitStash , GitTagDetails , MergeActionOn , RebaseActionOn , SquashMessageFormat , TagType , Writeable } from './types' ;
9+ import { ActionedUser , CommitOrdering , DateType , DeepWriteable , ErrorInfo , ErrorInfoExtensionPrefix , GitCommit , GitCommitDetails , GitCommitStash , GitConfigLocation , GitFileChange , GitFileStatus , GitPushBranchMode , GitRepoConfig , GitRepoConfigBranches , GitResetMode , GitSignature , GitSignatureStatus , GitStash , GitTagDetails , MergeActionOn , RebaseActionOn , SquashMessageFormat , TagType , Writeable } from './types' ;
1010import { GitExecutable , GitVersionRequirement , UNABLE_TO_FIND_GIT_MSG , UNCOMMITTED , abbrevCommit , constructIncompatibleGitVersionMessage , doesVersionMeetRequirement , getPathFromStr , getPathFromUri , openGitTerminal , pathWithTrailingSlash , realpath , resolveSpawnOutput , showErrorMessage } from './utils' ;
1111import { Disposable } from './utils/disposable' ;
1212import { Event } from './utils/event' ;
@@ -140,12 +140,12 @@ export class DataSource extends Disposable {
140140 this . getRemotes ( repo ) ,
141141 showStashes ? this . getStashes ( repo ) : Promise . resolve ( [ ] )
142142 ] ) . then ( ( results ) => {
143+ /* eslint no-console: "error" */
143144 return { branches : results [ 0 ] . branches , head : results [ 0 ] . head , remotes : results [ 1 ] , stashes : results [ 2 ] , error : null } ;
144145 } ) . catch ( ( errorMessage ) => {
145146 return { branches : [ ] , head : null , remotes : [ ] , stashes : [ ] , error : errorMessage } ;
146147 } ) ;
147148 }
148-
149149 /**
150150 * Get the commits in a repository.
151151 * @param repo The path of the repository.
@@ -161,10 +161,10 @@ export class DataSource extends Disposable {
161161 * @param stashes An array of all stashes in the repository.
162162 * @returns The commits in the repository.
163163 */
164- public getCommits ( repo : string , branches : ReadonlyArray < string > | null , maxCommits : number , showTags : boolean , showRemoteBranches : boolean , includeCommitsMentionedByReflogs : boolean , onlyFollowFirstParent : boolean , commitOrdering : CommitOrdering , remotes : ReadonlyArray < string > , hideRemotes : ReadonlyArray < string > , stashes : ReadonlyArray < GitStash > ) : Promise < GitCommitData > {
164+ public getCommits ( repo : string , branches : ReadonlyArray < string > | null , authors : ReadonlyArray < string > | null , maxCommits : number , showTags : boolean , showRemoteBranches : boolean , includeCommitsMentionedByReflogs : boolean , onlyFollowFirstParent : boolean , commitOrdering : CommitOrdering , remotes : ReadonlyArray < string > , hideRemotes : ReadonlyArray < string > , stashes : ReadonlyArray < GitStash > ) : Promise < GitCommitData > {
165165 const config = getConfig ( ) ;
166166 return Promise . all ( [
167- this . getLog ( repo , branches , maxCommits + 1 , showTags && config . showCommitsOnlyReferencedByTags , showRemoteBranches , includeCommitsMentionedByReflogs , onlyFollowFirstParent , commitOrdering , remotes , hideRemotes , stashes ) ,
167+ this . getLog ( repo , branches , authors , maxCommits + 1 , showTags && config . showCommitsOnlyReferencedByTags , showRemoteBranches , includeCommitsMentionedByReflogs , onlyFollowFirstParent , commitOrdering , remotes , hideRemotes , stashes ) ,
168168 this . getRefs ( repo , showRemoteBranches , config . showRemoteHeads , hideRemotes ) . then ( ( refData : GitRefData ) => refData , ( errorMessage : string ) => errorMessage )
169169 ] ) . then ( async ( results ) => {
170170 let commits : GitCommitRecord [ ] = results [ 0 ] , refData : GitRefData | string = results [ 1 ] , i ;
@@ -282,9 +282,10 @@ export class DataSource extends Disposable {
282282 return Promise . all ( [
283283 this . getConfigList ( repo ) ,
284284 this . getConfigList ( repo , GitConfigLocation . Local ) ,
285- this . getConfigList ( repo , GitConfigLocation . Global )
285+ this . getConfigList ( repo , GitConfigLocation . Global ) ,
286+ this . getAuthorList ( repo )
286287 ] ) . then ( ( results ) => {
287- const consolidatedConfigs = results [ 0 ] , localConfigs = results [ 1 ] , globalConfigs = results [ 2 ] ;
288+ const consolidatedConfigs = results [ 0 ] , localConfigs = results [ 1 ] , globalConfigs = results [ 2 ] , authors = results [ 3 ] ;
288289
289290 const branches : GitRepoConfigBranches = { } ;
290291 Object . keys ( localConfigs ) . forEach ( ( key ) => {
@@ -304,10 +305,10 @@ export class DataSource extends Disposable {
304305 }
305306 }
306307 } ) ;
307-
308308 return {
309309 config : {
310310 branches : branches ,
311+ authors,
311312 diffTool : getConfigValue ( consolidatedConfigs , GitConfigKey . DiffTool ) ,
312313 guiDiffTool : getConfigValue ( consolidatedConfigs , GitConfigKey . DiffGuiTool ) ,
313314 pushDefault : getConfigValue ( consolidatedConfigs , GitConfigKey . RemotePushDefault ) ,
@@ -334,7 +335,53 @@ export class DataSource extends Disposable {
334335 } ) ;
335336 }
336337
337-
338+ private async getAuthorList ( repo : string ) : Promise < ActionedUser [ ] > {
339+ const args = [ 'shortlog' , '-e' , '-s' , '-n' , 'HEAD' ] ;
340+ const dict = new Set < string > ( ) ;
341+ const result = await this . spawnGit ( args , repo , ( authors ) => {
342+ return authors . split ( / \r ? \n / g)
343+ . map ( line => line . trim ( ) )
344+ . filter ( line => line . trim ( ) . length > 0 )
345+ . map ( line => line . substring ( line . indexOf ( '\t' ) + 1 ) )
346+ . map ( line => {
347+ const indexOfEmailSeparator = line . indexOf ( '<' ) ;
348+ if ( indexOfEmailSeparator === - 1 ) {
349+ return {
350+ name : line . trim ( ) ,
351+ email : ''
352+ } ;
353+ } else {
354+ const nameParts = line . split ( '<' ) ;
355+ const name = nameParts . shift ( ) ! . trim ( ) ;
356+ const email = nameParts [ 0 ] . substring ( 0 , nameParts [ 0 ] . length - 1 ) . trim ( ) ;
357+ return {
358+ name,
359+ email
360+ } ;
361+ }
362+ } )
363+ . filter ( item => {
364+ if ( dict . has ( item . name ) ) {
365+ return false ;
366+ }
367+ dict . add ( item . name ) ;
368+ return true ;
369+ } )
370+ . sort ( ( a , b ) => ( a . name > b . name ? 1 : - 1 ) ) ;
371+ } ) . catch ( ( errorMessage ) => {
372+ if ( typeof errorMessage === 'string' ) {
373+ const message = errorMessage . toLowerCase ( ) ;
374+ if ( message . startsWith ( 'fatal: unable to read config file' ) && message . endsWith ( 'no such file or directory' ) ) {
375+ // If the Git command failed due to the configuration file not existing, return an empty list instead of throwing the exception
376+ return { } ;
377+ }
378+ } else {
379+ errorMessage = 'An unexpected error occurred while spawning the Git child process.' ;
380+ }
381+ throw errorMessage ;
382+ } ) as Promise < ActionedUser [ ] > ;
383+ return result ;
384+ }
338385 /* Get Data Methods - Commit Details View */
339386
340387 /**
@@ -1496,11 +1543,16 @@ export class DataSource extends Disposable {
14961543 * @param stashes An array of all stashes in the repository.
14971544 * @returns An array of commits.
14981545 */
1499- private getLog ( repo : string , branches : ReadonlyArray < string > | null , num : number , includeTags : boolean , includeRemotes : boolean , includeCommitsMentionedByReflogs : boolean , onlyFollowFirstParent : boolean , order : CommitOrdering , remotes : ReadonlyArray < string > , hideRemotes : ReadonlyArray < string > , stashes : ReadonlyArray < GitStash > ) {
1546+ private getLog ( repo : string , branches : ReadonlyArray < string > | null , authors : ReadonlyArray < string > | null , num : number , includeTags : boolean , includeRemotes : boolean , includeCommitsMentionedByReflogs : boolean , onlyFollowFirstParent : boolean , order : CommitOrdering , remotes : ReadonlyArray < string > , hideRemotes : ReadonlyArray < string > , stashes : ReadonlyArray < GitStash > ) {
15001547 const args = [ '-c' , 'log.showSignature=false' , 'log' , '--max-count=' + num , '--format=' + this . gitFormatLog , '--' + order + '-order' ] ;
15011548 if ( onlyFollowFirstParent ) {
15021549 args . push ( '--first-parent' ) ;
15031550 }
1551+ if ( authors !== null ) {
1552+ for ( let i = 0 ; i < authors . length ; i ++ ) {
1553+ args . push ( `--author=${ authors [ i ] } ` ) ;
1554+ }
1555+ }
15041556 if ( branches !== null ) {
15051557 for ( let i = 0 ; i < branches . length ; i ++ ) {
15061558 args . push ( branches [ i ] ) ;
@@ -1519,7 +1571,6 @@ export class DataSource extends Disposable {
15191571 } ) ;
15201572 }
15211573 }
1522-
15231574 // Add the unique list of base hashes of stashes, so that commits only referenced by stashes are displayed
15241575 const stashBaseHashes = stashes . map ( ( stash ) => stash . baseHash ) ;
15251576 stashBaseHashes . filter ( ( hash , index ) => stashBaseHashes . indexOf ( hash ) === index ) . forEach ( ( hash ) => args . push ( hash ) ) ;
@@ -1528,6 +1579,8 @@ export class DataSource extends Disposable {
15281579 }
15291580 args . push ( '--' ) ;
15301581
1582+
1583+
15311584 return this . spawnGit ( args , repo , ( stdout ) => {
15321585 let lines = stdout . split ( EOL_REGEX ) ;
15331586 let commits : GitCommitRecord [ ] = [ ] ;
0 commit comments