* Returns a callback which can be passed along to the processCallback option * in IGitExecution. The callback then takes care of reading stderr of the * process and parsing its contents using the provided parser.
( parser: IGitProgressParser, lfsProgressPath: string | null, progressCallback: (progress: IGitProgress | IGitOutput) => void )
| 51 | * process and parsing its contents using the provided parser. |
| 52 | */ |
| 53 | function createProgressProcessCallback( |
| 54 | parser: IGitProgressParser, |
| 55 | lfsProgressPath: string | null, |
| 56 | progressCallback: (progress: IGitProgress | IGitOutput) => void |
| 57 | ): (process: ChildProcess) => void { |
| 58 | return process => { |
| 59 | let lfsProgressActive = false |
| 60 | |
| 61 | if (lfsProgressPath) { |
| 62 | const lfsParser = new GitLFSProgressParser() |
| 63 | const disposable = tailByLine(lfsProgressPath, line => { |
| 64 | const progress = lfsParser.parse(line) |
| 65 | |
| 66 | if (progress.kind === 'progress') { |
| 67 | lfsProgressActive = true |
| 68 | progressCallback(progress) |
| 69 | } |
| 70 | }) |
| 71 | |
| 72 | process.on('close', () => { |
| 73 | disposable.dispose() |
| 74 | // the order of these callbacks is important because |
| 75 | // - unlink can only be done on files |
| 76 | // - rmdir can only be done when the directory is empty |
| 77 | // - we don't want to surface errors to the user if something goes |
| 78 | // wrong (these files can stay in TEMP and be cleaned up eventually) |
| 79 | Fs.unlink(lfsProgressPath, err => { |
| 80 | if (err == null) { |
| 81 | const directory = Path.dirname(lfsProgressPath) |
| 82 | Fs.rmdir(directory, () => {}) |
| 83 | } |
| 84 | }) |
| 85 | }) |
| 86 | } |
| 87 | |
| 88 | // If Node.js encounters a synchronous runtime error while spawning |
| 89 | // `stderr` will be undefined and the error will be emitted asynchronously |
| 90 | if (process.stderr) { |
| 91 | byline(process.stderr).on('data', (line: string) => { |
| 92 | const progress = parser.parse(line) |
| 93 | |
| 94 | if (lfsProgressActive) { |
| 95 | // While we're sending LFS progress we don't want to mix |
| 96 | // any non-progress events in with the output or we'll get |
| 97 | // flickering between the indeterminate LFS progress and |
| 98 | // the regular progress. |
| 99 | if (progress.kind === 'context') { |
| 100 | return |
| 101 | } |
| 102 | |
| 103 | const { title, done } = progress.details |
| 104 | |
| 105 | // The 'Filtering content' title happens while the LFS |
| 106 | // filter is running and when it's done we know that the |
| 107 | // filter is done but until then we don't want to display |
| 108 | // it for the same reason that we don't want to display |
| 109 | // the context above. |
| 110 | if (title === 'Filtering content') { |
no test coverage detected