11import * as childProcess from "node:child_process" ;
2+ import * as fs from "node:fs/promises" ;
23import * as os from "node:os" ;
34import * as path from "node:path" ;
45import { promisify } from "node:util" ;
@@ -845,8 +846,59 @@ export async function gitHashObject(cwd: vscode.Uri, content: string) {
845846 return ( await stdoutPromise ) . trim ( ) ;
846847}
847848
849+ async function gitDiffBlobsInternal (
850+ cwd : vscode . Uri ,
851+ filename : string ,
852+ blobIdA : string ,
853+ blobIdB : string ,
854+ ) {
855+ const ext = path . extname ( filename ) ;
856+ const tmpDir = await fs . mkdtemp (
857+ path . join ( os . tmpdir ( ) , "electron-build-tools-" ) ,
858+ ) ;
859+ const tmpFileA = path . join ( tmpDir , `${ blobIdA } ${ ext } ` ) ;
860+ const tmpFileB = path . join ( tmpDir , `${ blobIdB } ${ ext } ` ) ;
861+
862+ let stdout : string ;
863+
864+ const [ contentA , contentB ] = await Promise . all ( [
865+ getContentForBlobId ( blobIdA , cwd ) ,
866+ getContentForBlobId ( blobIdB , cwd ) ,
867+ ] ) ;
868+
869+ await Promise . all ( [
870+ fs . writeFile ( tmpFileA , contentA ) ,
871+ fs . writeFile ( tmpFileB , contentB ) ,
872+ ] ) ;
873+
874+ try {
875+ ( { stdout } = await exec (
876+ `git diff --full-index --no-index ${ tmpFileA } ${ tmpFileB } ` ,
877+ { encoding : "utf8" , cwd : cwd . fsPath } ,
878+ ) ) ;
879+ } catch ( err ) {
880+ // git diff --no-index exits with code 1 when files differ
881+ if (
882+ err instanceof Error &&
883+ Object . prototype . hasOwnProperty . call ( err , "code" ) &&
884+ ( err as PromisifiedExecError ) . code === 1
885+ ) {
886+ stdout = ( err as PromisifiedExecError ) . stdout ;
887+ } else {
888+ throw err ;
889+ }
890+ } finally {
891+ await fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( ( ) => { } ) ;
892+ }
893+
894+ return stdout
895+ . replaceAll ( `a${ tmpFileA } ` , `a/${ blobIdA } ` )
896+ . replaceAll ( `b${ tmpFileB } ` , `b/${ blobIdB } ` ) ;
897+ }
898+
848899export async function gitDiffBlobs (
849900 cwd : vscode . Uri ,
901+ filename : string ,
850902 blobIdA : string ,
851903 blobIdB : string ,
852904) {
@@ -862,12 +914,11 @@ export async function gitDiffBlobs(
862914 if ( / ^ [ 0 ] + $ / . test ( blobIdA ) ) {
863915 // Git doesn't like the all-zero blob ID, so use the empty blob SHA instead
864916 // The empty blob SHA is the SHA of an empty file (e.g., /dev/null)
865- let { stdout : fileDiff } = await exec (
866- `git diff --full-index ${ EMPTY_BLOB_SHA } ..${ blobIdB } ` ,
867- {
868- encoding : "utf8" ,
869- cwd : cwd . fsPath ,
870- } ,
917+ let fileDiff = await gitDiffBlobsInternal (
918+ cwd ,
919+ filename ,
920+ EMPTY_BLOB_SHA ,
921+ blobIdB ,
871922 ) ;
872923
873924 // Restore the original all zero blob ID in the diff output
@@ -885,13 +936,7 @@ export async function gitDiffBlobs(
885936 return fileDiff ;
886937 }
887938
888- const { stdout } = await exec (
889- `git diff --full-index ${ blobIdA } ..${ blobIdB } ` ,
890- {
891- encoding : "utf8" ,
892- cwd : cwd . fsPath ,
893- } ,
894- ) ;
939+ const stdout = await gitDiffBlobsInternal ( cwd , filename , blobIdA , blobIdB ) ;
895940
896941 return stdout ;
897942}
0 commit comments