( repository: Repository, file: WorkingDirectoryFileChange, hideWhitespaceInDiff: boolean = false )
| 340 | * that all content in the file will be treated as additions. |
| 341 | */ |
| 342 | export async function getWorkingDirectoryDiff( |
| 343 | repository: Repository, |
| 344 | file: WorkingDirectoryFileChange, |
| 345 | hideWhitespaceInDiff: boolean = false |
| 346 | ): Promise<IDiff> { |
| 347 | // `--no-ext-diff` should be provided wherever we invoke `git diff` so that any |
| 348 | // diff.external program configured by the user is ignored |
| 349 | const args = [ |
| 350 | 'diff', |
| 351 | ...(hideWhitespaceInDiff ? ['-w'] : []), |
| 352 | '--no-ext-diff', |
| 353 | '--patch-with-raw', |
| 354 | '-z', |
| 355 | '--no-color', |
| 356 | ] |
| 357 | const successExitCodes = new Set([0]) |
| 358 | const isSubmodule = file.status.submoduleStatus !== undefined |
| 359 | |
| 360 | // For added submodules, we'll use the "default" parameters, which are able |
| 361 | // to output the submodule commit. |
| 362 | if ( |
| 363 | !isSubmodule && |
| 364 | (file.status.kind === AppFileStatusKind.New || |
| 365 | file.status.kind === AppFileStatusKind.Untracked) |
| 366 | ) { |
| 367 | // `git diff --no-index` seems to emulate the exit codes from `diff` irrespective of |
| 368 | // whether you set --exit-code |
| 369 | // |
| 370 | // this is the behavior: |
| 371 | // - 0 if no changes found |
| 372 | // - 1 if changes found |
| 373 | // - and error otherwise |
| 374 | // |
| 375 | // citation in source: |
| 376 | // https://github.com/git/git/blob/1f66975deb8402131fbf7c14330d0c7cdebaeaa2/diff-no-index.c#L300 |
| 377 | successExitCodes.add(1) |
| 378 | args.push('--no-index', '--', '/dev/null', file.path) |
| 379 | } else if (file.status.kind === AppFileStatusKind.Renamed) { |
| 380 | // NB: Technically this is incorrect, the best kind of incorrect. |
| 381 | // In order to show exactly what will end up in the commit we should |
| 382 | // perform a diff between the new file and the old file as it appears |
| 383 | // in HEAD. By diffing against the index we won't show any changes |
| 384 | // already staged to the renamed file which differs from our other diffs. |
| 385 | // The closest I got to that was running hash-object and then using |
| 386 | // git diff <blob> <blob> but that seems a bit excessive. |
| 387 | args.push('--', ensureRelativePath(file.path)) |
| 388 | } else { |
| 389 | args.push('HEAD', '--', ensureRelativePath(file.path)) |
| 390 | } |
| 391 | |
| 392 | const { stdout, stderr } = await git( |
| 393 | args, |
| 394 | repository.path, |
| 395 | 'getWorkingDirectoryDiff', |
| 396 | { successExitCodes, encoding: 'buffer' } |
| 397 | ) |
| 398 | const lineEndingsChange = parseLineEndingsWarning(stderr) |
| 399 |
no test coverage detected