forked from MichaelCurrin/auto-commit-msg
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.ts
More file actions
93 lines (76 loc) · 2.57 KB
/
cli.ts
File metadata and controls
93 lines (76 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* Git CLI module.
*
* Run Git CLI commands within the extension and capture the text output.
*/
import { exec as _exec } from "child_process";
import * as util from "util";
import { Repository } from "../api/git";
const exec = util.promisify(_exec);
// Ensure Git will show special characters literally without quoting the string
// and escaping characters.
const QUOTE_PATH = '-c "core.quotePath=false"';
const DIFF_INDEX_CMD = "diff-index";
const DIFF_INDEX_OPTIONS = [
"--name-status",
"--find-renames",
"--find-copies",
"--no-color",
];
/**
* Run a `git` subcommand and return the result, with stdout and stderr available.
*/
function _execute(cwd: string, subcommand: string, options: string[] = []) {
const command = `git ${QUOTE_PATH} ${subcommand} ${options.join(" ")}`;
console.debug(`Running command: ${command}, cwd: ${cwd}`);
return exec(command, { cwd });
}
/**
* Run `git diff-index` with given flags and return the output.
*
* This will return both staged and unstaged changes. Pass '--cached' in
* `options` param to use staged changes only. Always excludes untracked files.
*
* Empty lines will be dropped, because of no changes or just the way the
* command-line data comes in or got split.
*
* The output already seems to never have color info, from testing, but the
* no-color flagged is added still to be safe.
*/
async function _diffIndex(
repository: Repository,
options: string[] = [],
): Promise<Array<string>> {
const cwd = repository.rootUri.fsPath;
const fullOptions = [...DIFF_INDEX_OPTIONS, ...options, "HEAD"];
const { stdout, stderr } = await _execute(cwd, DIFF_INDEX_CMD, fullOptions);
if (stderr) {
console.debug(`stderr for 'git ${DIFF_INDEX_CMD}' command:`, stderr);
}
const lines = stdout.split("\n");
return lines.filter(line => line !== "");
}
/**
* List files changed and how they changed.
*
* Look for diff description of staged files, otherwise fall back to all files.
* Always excludes untracked files - make sure to stage a file so it becomes
* tracked, especially in the case of a rename.
*
* Returns an array of strings.
*/
export async function getChanges(repository: Repository) {
const stagedChanges = await _diffIndex(repository, ["--cached"]);
if (stagedChanges.length) {
console.debug("Found staged changes");
return stagedChanges;
}
console.debug(
"Staging area is empty. Using unstaged files (tracked files only still).",
);
const allChanges = await _diffIndex(repository);
if (!allChanges.length) {
console.debug("No changes found");
}
return allChanges;
}