@@ -54,9 +54,6 @@ import {
5454 getRemoteNameFromBranchName ,
5555} from '../../../git/models/branch.utils' ;
5656import type { GitCommit , GitStashCommit } from '../../../git/models/commit' ;
57- import type { GitContributorStats } from '../../../git/models/contributor' ;
58- import { GitContributor } from '../../../git/models/contributor' ;
59- import { calculateContributionScore } from '../../../git/models/contributor.utils' ;
6057import type {
6158 GitDiff ,
6259 GitDiffFile ,
@@ -114,7 +111,6 @@ import {
114111import {
115112 createLogParserSingle ,
116113 createLogParserWithFilesAndStats ,
117- getContributorsParser ,
118114 getGraphParser ,
119115 getGraphStatsParser ,
120116 getRefAndDateParser ,
@@ -182,6 +178,7 @@ import type { GitLocation } from './locator';
182178import { findGitPath , InvalidGitConfigError , UnableToFindGitError } from './locator' ;
183179import { CancelledRunError , fsExists } from './shell' ;
184180import { BranchesGitSubProvider } from './sub-providers/branches' ;
181+ import { ContributorsGitSubProvider } from './sub-providers/contributors' ;
185182import { PatchGitSubProvider } from './sub-providers/patch' ;
186183import { RemotesGitSubProvider } from './sub-providers/remotes' ;
187184import { StagingGitSubProvider } from './sub-providers/staging' ;
@@ -2454,162 +2451,6 @@ export class LocalGitProvider implements GitProvider, Disposable {
24542451 return this . git . config__set ( key , value , repoPath ) ;
24552452 }
24562453
2457- @log ( )
2458- async getContributorsStats (
2459- repoPath : string ,
2460- options ?: { merges ?: boolean ; since ?: string } ,
2461- ) : Promise < GitContributorStats | undefined > {
2462- if ( repoPath == null ) return undefined ;
2463-
2464- const scope = getLogScope ( ) ;
2465-
2466- const args = [ 'shortlog' , '-s' , '--all' ] ;
2467- if ( ! options ?. merges ) {
2468- args . push ( '--no-merges' ) ;
2469- }
2470- if ( options ?. since ) {
2471- args . push ( `--since=${ options . since } ` ) ;
2472- }
2473-
2474- try {
2475- const data = await this . git . exec < string > ( { cwd : repoPath } , ...args ) ;
2476- if ( data == null ) return undefined ;
2477-
2478- const contributions = data
2479- . split ( '\n' )
2480- . map ( line => parseInt ( line . trim ( ) . split ( '\t' , 1 ) [ 0 ] , 10 ) )
2481- . filter ( c => ! isNaN ( c ) )
2482- . sort ( ( a , b ) => b - a ) ;
2483-
2484- const result : GitContributorStats = {
2485- count : contributions . length ,
2486- contributions : contributions ,
2487- } ;
2488- return result ;
2489- } catch ( ex ) {
2490- Logger . error ( ex , scope ) ;
2491- debugger ;
2492-
2493- return undefined ;
2494- }
2495- }
2496-
2497- @log ( )
2498- async getContributors (
2499- repoPath : string ,
2500- options ?: { all ?: boolean ; merges ?: boolean | 'first-parent' ; ref ?: string ; stats ?: boolean } ,
2501- ) : Promise < GitContributor [ ] > {
2502- if ( repoPath == null ) return [ ] ;
2503-
2504- let key = options ?. ref ?? '' ;
2505- if ( options ?. all ) {
2506- key += ':all' ;
2507- }
2508- if ( options ?. merges ) {
2509- key += `:merges:${ options . merges } ` ;
2510- }
2511- if ( options ?. stats ) {
2512- key += ':stats' ;
2513- }
2514-
2515- const contributorsCache = this . _cache . contributors ?. get ( repoPath ) ;
2516-
2517- let contributors = contributorsCache ?. get ( key ) ;
2518- if ( contributors == null ) {
2519- async function load ( this : LocalGitProvider ) {
2520- try {
2521- repoPath = normalizePath ( repoPath ) ;
2522- const currentUser = await this . getCurrentUser ( repoPath ) ;
2523- const parser = getContributorsParser ( options ?. stats ) ;
2524-
2525- const args = [ ...parser . arguments , '--full-history' , '--use-mailmap' ] ;
2526-
2527- const merges = options ?. merges ?? true ;
2528- if ( merges ) {
2529- args . push ( merges === 'first-parent' ? '--first-parent' : '--no-min-parents' ) ;
2530- } else {
2531- args . push ( '--no-merges' ) ;
2532- }
2533-
2534- if ( options ?. all ) {
2535- args . push ( '--all' , '--single-worktree' ) ;
2536- }
2537-
2538- const data = await this . git . log ( repoPath , { ref : options ?. ref } , ...args ) ;
2539-
2540- const contributors = new Map < string , GitContributor > ( ) ;
2541- const commits = parser . parse ( data ) ;
2542- for ( const c of commits ) {
2543- const key = `${ c . author } |${ c . email } ` ;
2544- const timestamp = Number ( c . date ) * 1000 ;
2545-
2546- let contributor : Mutable < GitContributor > | undefined = contributors . get ( key ) ;
2547- if ( contributor == null ) {
2548- contributor = new GitContributor (
2549- repoPath ,
2550- c . author ,
2551- c . email ,
2552- 1 ,
2553- new Date ( timestamp ) ,
2554- new Date ( timestamp ) ,
2555- isUserMatch ( currentUser , c . author , c . email ) ,
2556- c . stats
2557- ? {
2558- ...c . stats ,
2559- contributionScore : calculateContributionScore ( c . stats , timestamp ) ,
2560- }
2561- : undefined ,
2562- ) ;
2563- contributors . set ( key , contributor ) ;
2564- } else {
2565- contributor . commits ++ ;
2566- const date = new Date ( timestamp ) ;
2567- if ( date > contributor . latestCommitDate ! ) {
2568- contributor . latestCommitDate = date ;
2569- }
2570- if ( date < contributor . firstCommitDate ! ) {
2571- contributor . firstCommitDate = date ;
2572- }
2573- if ( options ?. stats && c . stats != null ) {
2574- if ( contributor . stats == null ) {
2575- contributor . stats = {
2576- ...c . stats ,
2577- contributionScore : calculateContributionScore ( c . stats , timestamp ) ,
2578- } ;
2579- } else {
2580- contributor . stats = {
2581- additions : contributor . stats . additions + c . stats . additions ,
2582- deletions : contributor . stats . deletions + c . stats . deletions ,
2583- files : contributor . stats . files + c . stats . files ,
2584- contributionScore :
2585- contributor . stats . contributionScore +
2586- calculateContributionScore ( c . stats , timestamp ) ,
2587- } ;
2588- }
2589- }
2590- }
2591- }
2592-
2593- return [ ...contributors . values ( ) ] ;
2594- } catch ( _ex ) {
2595- contributorsCache ?. delete ( key ) ;
2596-
2597- return [ ] ;
2598- }
2599- }
2600-
2601- contributors = load . call ( this ) ;
2602-
2603- if ( contributorsCache == null ) {
2604- this . _cache . contributors ?. set ( repoPath , new Map ( [ [ key , contributors ] ] ) ) ;
2605- } else {
2606- contributorsCache . set ( key , contributors ) ;
2607- }
2608- }
2609-
2610- return contributors ;
2611- }
2612-
26132454 @gate ( )
26142455 @log ( )
26152456 async getCurrentUser ( repoPath : string ) : Promise < GitUser | undefined > {
@@ -4833,6 +4674,11 @@ export class LocalGitProvider implements GitProvider, Disposable {
48334674 return ( this . _branches ??= new BranchesGitSubProvider ( this . container , this . git , this . _cache , this ) ) ;
48344675 }
48354676
4677+ private _contributors : ContributorsGitSubProvider | undefined ;
4678+ get contributors ( ) : ContributorsGitSubProvider {
4679+ return ( this . _contributors ??= new ContributorsGitSubProvider ( this . container , this . git , this . _cache , this ) ) ;
4680+ }
4681+
48364682 private _patch : PatchGitSubProvider | undefined ;
48374683 get patch ( ) : PatchGitSubProvider | undefined {
48384684 return ( this . _patch ??= new PatchGitSubProvider ( this . container , this . git , this ) ) ;
0 commit comments