@@ -327,6 +327,12 @@ function getGitErrorCode(stderr: string): string | undefined {
327327 return undefined ;
328328}
329329
330+ // https://github.com/microsoft/vscode/issues/89373
331+ // https://github.com/git-for-windows/git/issues/2478
332+ function sanitizePath ( path : string ) : string {
333+ return path . replace ( / ^ ( [ a - z ] ) : \\ / i, ( _ , letter ) => `${ letter . toUpperCase ( ) } :\\` ) ;
334+ }
335+
330336const COMMIT_FORMAT = '%H\n%aN\n%aE\n%at\n%P\n%B' ;
331337
332338export class Git {
@@ -496,6 +502,10 @@ export class Git {
496502 LANG : 'en_US.UTF-8'
497503 } ) ;
498504
505+ if ( options . cwd ) {
506+ options . cwd = sanitizePath ( options . cwd ) ;
507+ }
508+
499509 if ( options . log !== false ) {
500510 this . log ( `> git ${ args . join ( ' ' ) } \n` ) ;
501511 }
@@ -887,12 +897,12 @@ export class Repository {
887897 }
888898
889899 async lstree ( treeish : string , path : string ) : Promise < LsTreeElement [ ] > {
890- const { stdout } = await this . run ( [ 'ls-tree' , '-l' , treeish , '--' , path ] ) ;
900+ const { stdout } = await this . run ( [ 'ls-tree' , '-l' , treeish , '--' , sanitizePath ( path ) ] ) ;
891901 return parseLsTree ( stdout ) ;
892902 }
893903
894904 async lsfiles ( path : string ) : Promise < LsFilesElement [ ] > {
895- const { stdout } = await this . run ( [ 'ls-files' , '--stage' , '--' , path ] ) ;
905+ const { stdout } = await this . run ( [ 'ls-files' , '--stage' , '--' , sanitizePath ( path ) ] ) ;
896906 return parseLsFiles ( stdout ) ;
897907 }
898908
@@ -986,7 +996,7 @@ export class Repository {
986996 return await this . diffFiles ( false ) ;
987997 }
988998
989- const args = [ 'diff' , '--' , path ] ;
999+ const args = [ 'diff' , '--' , sanitizePath ( path ) ] ;
9901000 const result = await this . run ( args ) ;
9911001 return result . stdout ;
9921002 }
@@ -999,7 +1009,7 @@ export class Repository {
9991009 return await this . diffFiles ( false , ref ) ;
10001010 }
10011011
1002- const args = [ 'diff' , ref , '--' , path ] ;
1012+ const args = [ 'diff' , ref , '--' , sanitizePath ( path ) ] ;
10031013 const result = await this . run ( args ) ;
10041014 return result . stdout ;
10051015 }
@@ -1012,7 +1022,7 @@ export class Repository {
10121022 return await this . diffFiles ( true ) ;
10131023 }
10141024
1015- const args = [ 'diff' , '--cached' , '--' , path ] ;
1025+ const args = [ 'diff' , '--cached' , '--' , sanitizePath ( path ) ] ;
10161026 const result = await this . run ( args ) ;
10171027 return result . stdout ;
10181028 }
@@ -1025,7 +1035,7 @@ export class Repository {
10251035 return await this . diffFiles ( true , ref ) ;
10261036 }
10271037
1028- const args = [ 'diff' , '--cached' , ref , '--' , path ] ;
1038+ const args = [ 'diff' , '--cached' , ref , '--' , sanitizePath ( path ) ] ;
10291039 const result = await this . run ( args ) ;
10301040 return result . stdout ;
10311041 }
@@ -1045,7 +1055,7 @@ export class Repository {
10451055 return await this . diffFiles ( false , range ) ;
10461056 }
10471057
1048- const args = [ 'diff' , range , '--' , path ] ;
1058+ const args = [ 'diff' , range , '--' , sanitizePath ( path ) ] ;
10491059 const result = await this . run ( args ) ;
10501060
10511061 return result . stdout . trim ( ) ;
@@ -1158,7 +1168,7 @@ export class Repository {
11581168 args . push ( '--' ) ;
11591169
11601170 if ( paths && paths . length ) {
1161- args . push . apply ( args , paths ) ;
1171+ args . push . apply ( args , paths . map ( sanitizePath ) ) ;
11621172 } else {
11631173 args . push ( '.' ) ;
11641174 }
@@ -1173,13 +1183,13 @@ export class Repository {
11731183 return ;
11741184 }
11751185
1176- args . push ( ...paths ) ;
1186+ args . push ( ...paths . map ( sanitizePath ) ) ;
11771187
11781188 await this . run ( args ) ;
11791189 }
11801190
11811191 async stage ( path : string , data : string ) : Promise < void > {
1182- const child = this . stream ( [ 'hash-object' , '--stdin' , '-w' , '--path' , path ] , { stdio : [ null , null , null ] } ) ;
1192+ const child = this . stream ( [ 'hash-object' , '--stdin' , '-w' , '--path' , sanitizePath ( path ) ] , { stdio : [ null , null , null ] } ) ;
11831193 child . stdin ! . end ( data , 'utf8' ) ;
11841194
11851195 const { exitCode, stdout } = await exec ( child ) ;
@@ -1224,7 +1234,7 @@ export class Repository {
12241234
12251235 try {
12261236 if ( paths && paths . length > 0 ) {
1227- for ( const chunk of splitInChunks ( paths , MAX_CLI_LENGTH ) ) {
1237+ for ( const chunk of splitInChunks ( paths . map ( sanitizePath ) , MAX_CLI_LENGTH ) ) {
12281238 await this . run ( [ ...args , '--' , ...chunk ] ) ;
12291239 }
12301240 } else {
@@ -1363,7 +1373,7 @@ export class Repository {
13631373 }
13641374
13651375 async clean ( paths : string [ ] ) : Promise < void > {
1366- const pathsByGroup = groupBy ( paths , p => path . dirname ( p ) ) ;
1376+ const pathsByGroup = groupBy ( paths . map ( sanitizePath ) , p => path . dirname ( p ) ) ;
13671377 const groups = Object . keys ( pathsByGroup ) . map ( k => pathsByGroup [ k ] ) ;
13681378
13691379 const limiter = new Limiter ( 5 ) ;
@@ -1409,7 +1419,7 @@ export class Repository {
14091419 }
14101420
14111421 if ( paths && paths . length ) {
1412- args . push . apply ( args , paths ) ;
1422+ args . push . apply ( args , paths . map ( sanitizePath ) ) ;
14131423 } else {
14141424 args . push ( '.' ) ;
14151425 }
@@ -1560,11 +1570,8 @@ export class Repository {
15601570
15611571 async blame ( path : string ) : Promise < string > {
15621572 try {
1563- const args = [ 'blame' ] ;
1564- args . push ( path ) ;
1565-
1566- let result = await this . run ( args ) ;
1567-
1573+ const args = [ 'blame' , sanitizePath ( path ) ] ;
1574+ const result = await this . run ( args ) ;
15681575 return result . stdout . trim ( ) ;
15691576 } catch ( err ) {
15701577 if ( / ^ f a t a l : n o s u c h p a t h / . test ( err . stderr || '' ) ) {
@@ -1894,7 +1901,7 @@ export class Repository {
18941901 async updateSubmodules ( paths : string [ ] ) : Promise < void > {
18951902 const args = [ 'submodule' , 'update' , '--' ] ;
18961903
1897- for ( const chunk of splitInChunks ( paths , MAX_CLI_LENGTH ) ) {
1904+ for ( const chunk of splitInChunks ( paths . map ( sanitizePath ) , MAX_CLI_LENGTH ) ) {
18981905 await this . run ( [ ...args , ...chunk ] ) ;
18991906 }
19001907 }
0 commit comments