wukong-gitlog-cli 0.0.2 → 0.0.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.0.3](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v0.0.2...v0.0.3) (2025-11-26)
6
+
7
+
8
+ ### Features
9
+
10
+ * 🎸 gerrit ([76f71b8](https://github.com/tomatobybike/wukong-gitlog-cli/commit/76f71b8ab7b1636bee4c243fd670383268e1f771))
11
+
5
12
  ### [0.0.2](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v0.0.1...v0.0.2) (2025-11-26)
6
13
 
7
14
  ### 0.0.1 (2025-11-26)
package/README.md CHANGED
@@ -65,7 +65,9 @@ Command-line options:
65
65
  - `--format <type>` Output format: `text` | `excel` | `json` (default: `text`)
66
66
  - `--group-by <type>` Group commits by date: `day` | `month`
67
67
  - `--stats` Include a `Stats` sheet in the Excel export
68
- - `--gerrit <prefix>` Show Gerrit URL for each commit (supports templates `{{hash}}` and `{{changeId}}`; `{{changeId}}` falls back to `hash` when absent)
68
+ - `--gerrit-api <url>` Optional: Gerrit REST API base URL for resolving `{{changeNumber}}` (e.g. `https://gerrit.example.com/gerrit`)
69
+ - `--gerrit-auth <token>` Optional: Authorization for Gerrit REST API (either `user:pass` for Basic or token string for Bearer)
70
+ - `--gerrit <prefix>` Show Gerrit URL for each commit (supports templates `{{hash}}`, `{{changeId}}` and `{{changeNumber}}`; `{{changeId}}` falls back to `hash` when absent; `{{changeNumber}}` requires `--gerrit-api` and falls back to `changeId` or `hash`)
69
71
  - `--out <file>` Output file name (without path). Defaults: `commits.json` / `commits.txt` / `commits.xlsx`
70
72
  - `--out-dir <dir>` Output directory path — supports relative or absolute path, e.g., `--out-dir ../output`
71
73
  - `--out-parent` Place output in the parent directory's `output/` folder (same as `--out-dir ../output`)
@@ -105,8 +107,9 @@ Note: `--out <file>` is the filename only and the directory used to store that f
105
107
  For example:
106
108
 
107
109
  ```bash
108
- node ./src/cli.mjs --out parent.json --out-parent
109
- node ./src/cli.mjs --out demo.txt --out-dir ../temp
110
+ # using globally installed CLI
111
+ wukong-gitlog-cli --out parent.json --out-parent
112
+ wukong-gitlog-cli --out demo.txt --out-dir ../temp
110
113
  ```
111
114
 
112
115
  ---
@@ -116,7 +119,20 @@ node ./src/cli.mjs --out demo.txt --out-dir ../temp
116
119
  Export as text, grouped by month, with Gerrit links:
117
120
 
118
121
  ```bash
119
- node ./src/cli.mjs --format text --group-by month --gerrit "https://gerrit.example.com/c/project/+/{{hash}}"
122
+ wukong-gitlog-cli --format text --group-by month --gerrit "https://gerrit.example.com/c/project/+/{{hash}}"
123
+ ```
124
+
125
+ // Resolve numeric change ID using Gerrit API (if available)
126
+ wukong-gitlog-cli --format text --group-by month --gerrit "https://gerrit.example.com/c/project/+/{{changeNumber}}" --gerrit-api <GERRIT_API_BASE_URL>
127
+
128
+ If your Gerrit requires authentication (HTTP Basic or token), use `--gerrit-auth`:
129
+
130
+ ```bash
131
+ # HTTP Basic: username:password
132
+ wukong-gitlog-cli --format text --gerrit "https://gerrit.example.com/c/project/+/{{changeNumber}}" --gerrit-api <GERRIT_API_BASE_URL> --gerrit-auth "username:password"
133
+
134
+ # Token (Bearer)
135
+ wukong-gitlog-cli --format text --gerrit "https://gerrit.example.com/c/project/+/{{changeNumber}}" --gerrit-api <GERRIT_API_BASE_URL> --gerrit-auth "MYTOKEN"
120
136
  ```
121
137
 
122
138
  Export to Excel with stats and Gerrit URLs:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wukong-gitlog-cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Advanced Git commit log exporter with Excel/JSON/TXT output, grouping, stats and CLI.",
5
5
  "keywords": [
6
6
  "git",
package/src/cli.mjs CHANGED
@@ -22,6 +22,8 @@ program
22
22
  .option('--group-by <type>', '按日期分组: day | month')
23
23
  .option('--stats', '输出每日统计数据')
24
24
  .option('--gerrit <prefix>', '显示 Gerrit 地址,支持在 prefix 中使用 {{hash}} 占位符')
25
+ .option('--gerrit-api <url>', '可选:Gerrit REST API 基础地址,用于解析 changeNumber,例如 `https://gerrit.example.com`')
26
+ .option('--gerrit-auth <tokenOrUserPass>', '可选:Gerrit API 授权,格式为 `user:pass` 或 `TOKEN`(表示 Bearer token)')
25
27
  .option('--out <file>', '输出文件名(不含路径)')
26
28
  .option('--out-dir <dir>', '自定义输出目录,支持相对路径或绝对路径,例如 `--out-dir ../output`')
27
29
  .option('--out-parent', '将输出目录放到当前工程的父目录的 `output/`(等同于 `--out-dir ../output`)')
@@ -40,8 +42,78 @@ const opts = program.opts();
40
42
  // --- Gerrit 地址处理(若提供) ---
41
43
  if (opts.gerrit) {
42
44
  const prefix = opts.gerrit;
45
+ // support optional changeNumber resolution via Gerrit REST API
46
+ const { gerritApi, gerritAuth } = opts;
43
47
  // create new array to avoid mutating function parameters (eslint: no-param-reassign)
44
- records = records.map(r => {
48
+ if (prefix.includes('{{changeNumber}}') && gerritApi) {
49
+ // async mapping to resolve changeNumber using Gerrit API
50
+ const cache = new Map();
51
+ const headers = {};
52
+ if (gerritAuth) {
53
+ if (gerritAuth.includes(':')) {
54
+ headers.Authorization = `Basic ${Buffer.from(gerritAuth).toString('base64')}`;
55
+ } else {
56
+ headers.Authorization = `Bearer ${gerritAuth}`;
57
+ }
58
+ }
59
+
60
+ const fetchGerritJson = async (url) => {
61
+ try {
62
+ const res = await fetch(url, { headers });
63
+ const txt = await res.text();
64
+ // Gerrit prepends )]}' to JSON responses — strip it
65
+ const jsonText = txt.replace(/^\)\]\}'\n/, '');
66
+ return JSON.parse(jsonText);
67
+ } catch (err) {
68
+ return null;
69
+ }
70
+ };
71
+
72
+ const resolveChangeNumber = async (r) => {
73
+ // try changeId first
74
+ if (r.changeId) {
75
+ if (cache.has(r.changeId)) return cache.get(r.changeId);
76
+ // try `changes/{changeId}/detail`
77
+ const url = `${gerritApi.replace(/\/$/, '')}/changes/${encodeURIComponent(r.changeId)}/detail`;
78
+ let j = await fetchGerritJson(url);
79
+ if (j && j._number) {
80
+ cache.set(r.changeId, j._number);
81
+ return j._number;
82
+ }
83
+ // fallback: query search
84
+ const url2 = `${gerritApi.replace(/\/$/, '')}/changes/?q=change:${encodeURIComponent(r.changeId)}`;
85
+ j = await fetchGerritJson(url2);
86
+ if (Array.isArray(j) && j.length > 0 && j[0]._number) {
87
+ cache.set(r.changeId, j[0]._number);
88
+ return j[0]._number;
89
+ }
90
+ }
91
+ // try commit hash
92
+ if (r.hash) {
93
+ if (cache.has(r.hash)) return cache.get(r.hash);
94
+ const url3 = `${gerritApi.replace(/\/$/, '')}/changes/?q=commit:${encodeURIComponent(r.hash)}`;
95
+ const j = await fetchGerritJson(url3);
96
+ if (Array.isArray(j) && j.length > 0 && j[0]._number) {
97
+ cache.set(r.hash, j[0]._number);
98
+ return j[0]._number;
99
+ }
100
+ }
101
+ return null;
102
+ };
103
+
104
+ records = await Promise.all(
105
+ records.map(async (r) => {
106
+ const changeNumber = await resolveChangeNumber(r);
107
+ const changeNumberOrFallback = changeNumber || r.changeId || r.hash;
108
+ const gerritUrl = prefix.replace('{{changeNumber}}', changeNumberOrFallback);
109
+ return { ...r, gerrit: gerritUrl };
110
+ })
111
+ );
112
+ } else if (prefix.includes('{{changeNumber}}') && !gerritApi) {
113
+ console.warn('prefix contains {{changeNumber}} but no --gerrit-api provided — falling back to changeId/hash');
114
+ records = records.map((r) => ({ ...r, gerrit: prefix.replace('{{changeNumber}}', r.changeId || r.hash) }));
115
+ } else {
116
+ records = records.map((r) => {
45
117
  let gerritUrl;
46
118
  if (prefix.includes('{{changeId}}')) {
47
119
  const changeId = r.changeId || r.hash;
@@ -54,7 +126,8 @@ const opts = program.opts();
54
126
  }
55
127
 
56
128
  return { ...r, gerrit: gerritUrl };
57
- });
129
+ });
130
+ }
58
131
  }
59
132
 
60
133
  // --- 分组 ---