| 5 | import { GitNotFoundError } from '../errors' |
| 6 | |
| 7 | export class GitVCSProvider implements VCSProvider { |
| 8 | private root!: string |
| 9 | |
| 10 | private async resolveFilesWithGitCommand(args: string[]): Promise<string[]> { |
| 11 | let result: Output |
| 12 | |
| 13 | try { |
| 14 | result = await x('git', args, { nodeOptions: { cwd: this.root } }) |
| 15 | } |
| 16 | catch (e: any) { |
| 17 | e.message = e.stderr |
| 18 | |
| 19 | throw e |
| 20 | } |
| 21 | |
| 22 | return result.stdout |
| 23 | .split('\n') |
| 24 | .filter(s => s !== '') |
| 25 | .map(changedPath => resolve(this.root, changedPath)) |
| 26 | } |
| 27 | |
| 28 | async findChangedFiles(options: VCSProviderOptions): Promise<string[]> { |
| 29 | const root = this.root || await this.getRoot(options.root) |
| 30 | if (!root) { |
| 31 | throw new GitNotFoundError() |
| 32 | } |
| 33 | |
| 34 | this.root = root |
| 35 | |
| 36 | const changedSince = options.changedSince |
| 37 | if (typeof changedSince === 'string') { |
| 38 | const [committed, staged, unstaged] = await Promise.all([ |
| 39 | this.getFilesSince(changedSince), |
| 40 | this.getStagedFiles(), |
| 41 | this.getUnstagedFiles(), |
| 42 | ]) |
| 43 | return [...committed, ...staged, ...unstaged] |
| 44 | } |
| 45 | const [staged, unstaged] = await Promise.all([ |
| 46 | this.getStagedFiles(), |
| 47 | this.getUnstagedFiles(), |
| 48 | ]) |
| 49 | return [...staged, ...unstaged] |
| 50 | } |
| 51 | |
| 52 | private getFilesSince(hash: string) { |
| 53 | return this.resolveFilesWithGitCommand([ |
| 54 | 'diff', |
| 55 | '--name-only', |
| 56 | `${hash}...HEAD`, |
| 57 | ]) |
| 58 | } |
| 59 | |
| 60 | private getStagedFiles() { |
| 61 | return this.resolveFilesWithGitCommand(['diff', '--cached', '--name-only']) |
| 62 | } |
| 63 | |
| 64 | private getUnstagedFiles() { |
nothing calls this directly
no outgoing calls
no test coverage detected