@youngwat/git-file-manager 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +441 -2
- package/package.json +38 -3
- package/src/backup.js +78 -0
- package/src/cli.js +183 -0
- package/src/commands/rescue.js +403 -0
- package/src/commands/sync.js +295 -0
- package/src/commands/undo.js +66 -0
- package/src/commitSpec.js +122 -0
- package/src/git.js +194 -0
- package/src/log.js +79 -0
package/src/log.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 终端输出与错误类型。零依赖:非 TTY 或设置了 NO_COLOR 时自动关色。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const useColor = !process.env.NO_COLOR
|
|
8
|
+
&& (Boolean(process.stdout.isTTY) || process.env.GFM_FORCE_COLOR === '1');
|
|
9
|
+
|
|
10
|
+
function paint(code, text) {
|
|
11
|
+
return useColor ? `\u001b[${code}m${text}\u001b[0m` : String(text);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const C = {
|
|
15
|
+
bold: (t) => paint('1', t),
|
|
16
|
+
dim: (t) => paint('2', t),
|
|
17
|
+
red: (t) => paint('31', t),
|
|
18
|
+
green: (t) => paint('32', t),
|
|
19
|
+
yellow: (t) => paint('33', t),
|
|
20
|
+
cyan: (t) => paint('36', t),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** 可预期的失败:只打印 message(+ hint),不打堆栈 */
|
|
24
|
+
class CliError extends Error {
|
|
25
|
+
constructor(message, hint) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'CliError';
|
|
28
|
+
this.hint = hint;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let verbose = false;
|
|
33
|
+
|
|
34
|
+
/** 粗略显示宽度:CJK 全角字符按 2 列算 */
|
|
35
|
+
function dispWidth(str) {
|
|
36
|
+
let w = 0;
|
|
37
|
+
for (const ch of String(str)) {
|
|
38
|
+
const cp = ch.codePointAt(0);
|
|
39
|
+
w += (cp >= 0x1100 && (cp <= 0x115f
|
|
40
|
+
|| (cp >= 0x2e80 && cp <= 0xa4cf)
|
|
41
|
+
|| (cp >= 0xac00 && cp <= 0xd7a3)
|
|
42
|
+
|| (cp >= 0xf900 && cp <= 0xfaff)
|
|
43
|
+
|| (cp >= 0xfe30 && cp <= 0xfe6f)
|
|
44
|
+
|| (cp >= 0xff00 && cp <= 0xff60)
|
|
45
|
+
|| (cp >= 0xffe0 && cp <= 0xffe6))) ? 2 : 1;
|
|
46
|
+
}
|
|
47
|
+
return w;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function pad(str, width) {
|
|
51
|
+
const gap = width - dispWidth(str);
|
|
52
|
+
return gap > 0 ? str + ' '.repeat(gap) : String(str);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 简易表格:返回多行字符串 */
|
|
56
|
+
function renderTable(headers, rows) {
|
|
57
|
+
const all = [headers, ...rows];
|
|
58
|
+
const widths = headers.map((_, i) => Math.max(...all.map((r) => dispWidth(r[i] == null ? '' : r[i]))));
|
|
59
|
+
return all
|
|
60
|
+
.map((r) => ' ' + r.map((cell, i) => pad(cell == null ? '' : String(cell), widths[i])).join(' ').trimEnd())
|
|
61
|
+
.join('\n');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
C,
|
|
66
|
+
CliError,
|
|
67
|
+
renderTable,
|
|
68
|
+
dispWidth,
|
|
69
|
+
setVerbose: (v) => { verbose = Boolean(v); },
|
|
70
|
+
isVerbose: () => verbose,
|
|
71
|
+
step: (title) => console.log(`\n${C.bold('>> ' + title)}`),
|
|
72
|
+
ok: (msg) => console.log(` ${C.green('[ok]')} ${msg}`),
|
|
73
|
+
warn: (msg) => console.log(` ${C.yellow('[warn]')} ${msg}`),
|
|
74
|
+
bad: (msg) => console.log(` ${C.red('[fail]')} ${msg}`),
|
|
75
|
+
info: (msg) => console.log(` ${msg}`),
|
|
76
|
+
plain: (msg) => console.log(msg),
|
|
77
|
+
debug: (msg) => { if (verbose) console.log(C.dim(` . ${msg}`)); },
|
|
78
|
+
title: (msg) => console.log(C.bold(msg)),
|
|
79
|
+
};
|