dsh-gitnexus-plus 0.1.2 → 0.1.4

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.
Files changed (72) hide show
  1. package/README-CN.md +189 -0
  2. package/README.md +219 -597
  3. package/lib/bin/graph-helper.d.ts +21 -0
  4. package/lib/bin/graph-helper.d.ts.map +1 -0
  5. package/lib/bin/graph-helper.js +71 -0
  6. package/lib/bin/graph-helper.js.map +1 -0
  7. package/lib/client.js +4107 -2029
  8. package/lib/gitnexus/analyze.d.ts +48 -8
  9. package/lib/gitnexus/analyze.d.ts.map +1 -1
  10. package/lib/gitnexus/analyze.js +376 -75
  11. package/lib/gitnexus/analyze.js.map +1 -1
  12. package/lib/gitnexus/commands.d.ts +8 -1
  13. package/lib/gitnexus/commands.d.ts.map +1 -1
  14. package/lib/gitnexus/commands.js +19 -0
  15. package/lib/gitnexus/commands.js.map +1 -1
  16. package/lib/gitnexus/coverage.d.ts +16 -0
  17. package/lib/gitnexus/coverage.d.ts.map +1 -1
  18. package/lib/gitnexus/coverage.js +58 -1
  19. package/lib/gitnexus/coverage.js.map +1 -1
  20. package/lib/gitnexus/delta.d.ts +144 -0
  21. package/lib/gitnexus/delta.d.ts.map +1 -0
  22. package/lib/gitnexus/delta.js +347 -0
  23. package/lib/gitnexus/delta.js.map +1 -0
  24. package/lib/gitnexus/git-activity.d.ts +77 -0
  25. package/lib/gitnexus/git-activity.d.ts.map +1 -1
  26. package/lib/gitnexus/git-activity.js +327 -8
  27. package/lib/gitnexus/git-activity.js.map +1 -1
  28. package/lib/gitnexus/graph.d.ts +126 -0
  29. package/lib/gitnexus/graph.d.ts.map +1 -0
  30. package/lib/gitnexus/graph.js +472 -0
  31. package/lib/gitnexus/graph.js.map +1 -0
  32. package/lib/gitnexus/root.d.ts +0 -3
  33. package/lib/gitnexus/root.d.ts.map +1 -1
  34. package/lib/gitnexus/root.js +64 -5
  35. package/lib/gitnexus/root.js.map +1 -1
  36. package/lib/gitnexus/scan.d.ts +2 -0
  37. package/lib/gitnexus/scan.d.ts.map +1 -1
  38. package/lib/gitnexus/scan.js +3 -2
  39. package/lib/gitnexus/scan.js.map +1 -1
  40. package/lib/gitnexus/search.d.ts +21 -8
  41. package/lib/gitnexus/search.d.ts.map +1 -1
  42. package/lib/gitnexus/search.js +87 -13
  43. package/lib/gitnexus/search.js.map +1 -1
  44. package/lib/index.d.ts +6 -0
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +170 -2
  47. package/lib/index.js.map +1 -1
  48. package/lib/routes/analyze.d.ts +3 -2
  49. package/lib/routes/analyze.d.ts.map +1 -1
  50. package/lib/routes/analyze.js +8 -2
  51. package/lib/routes/analyze.js.map +1 -1
  52. package/lib/routes/coverage.d.ts +2 -1
  53. package/lib/routes/coverage.d.ts.map +1 -1
  54. package/lib/routes/coverage.js +53 -1
  55. package/lib/routes/coverage.js.map +1 -1
  56. package/lib/routes/delta.d.ts +22 -0
  57. package/lib/routes/delta.d.ts.map +1 -0
  58. package/lib/routes/delta.js +50 -0
  59. package/lib/routes/delta.js.map +1 -0
  60. package/lib/routes/file-diff.d.ts +19 -0
  61. package/lib/routes/file-diff.d.ts.map +1 -0
  62. package/lib/routes/file-diff.js +69 -0
  63. package/lib/routes/file-diff.js.map +1 -0
  64. package/lib/routes/file-history.d.ts +21 -0
  65. package/lib/routes/file-history.d.ts.map +1 -0
  66. package/lib/routes/file-history.js +69 -0
  67. package/lib/routes/file-history.js.map +1 -0
  68. package/lib/routes/graph.d.ts +22 -0
  69. package/lib/routes/graph.d.ts.map +1 -0
  70. package/lib/routes/graph.js +71 -0
  71. package/lib/routes/graph.js.map +1 -0
  72. package/package.json +3 -2
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Tier 0 staleness: is a refresh worth running at all?
3
+ *
4
+ * WHY THIS EXISTS
5
+ * ---------------
6
+ * The panel's only maintenance action used to be "run `gitnexus analyze`", and it ran
7
+ * the analyzer every time — on a repository where nothing had changed since the index
8
+ * was written. That is not a correctness bug, it is a cost bug with a bad shape: the
9
+ * work is measured in seconds on a small repository and in minutes on a large one, and
10
+ * the user has no way to know beforehand whether they are about to spend it.
11
+ *
12
+ * The index already records what it saw: `.gitnexus/gitnexus.json` carries
13
+ * `fileHashes`, a map of repo-relative path to sha256. Comparing the working tree
14
+ * against those hashes answers "would a re-analysis change anything?" exactly, and it
15
+ * needs nothing but git and a hash function.
16
+ *
17
+ * WHAT IS COMPARED, AND AGAINST WHAT
18
+ * ----------------------------------
19
+ * The baseline is the **index snapshot**, not `HEAD`. Those differ whenever the index
20
+ * was built from a dirty tree, and the manifest records that case in
21
+ * `indexCoverage.dirtyPaths`. Comparing against `HEAD` would call a file unchanged
22
+ * merely because it was committed, even though the index remembered different content
23
+ * — which is the direction that produces a stale graph the panel says is current.
24
+ *
25
+ * The candidate set is therefore everything that differs from the *indexed commit*:
26
+ *
27
+ * `git diff --no-renames --name-only <lastCommit>` tracked files, working tree vs
28
+ * that commit (staged and unstaged)
29
+ * `git ls-files --others --exclude-standard` untracked files git would include
30
+ *
31
+ * `--no-renames` on purpose: with rename detection on, git reports only the new path,
32
+ * so a rename looks like a pure addition and the index's old path silently disappears
33
+ * from the comparison. Forcing add+delete pairs lets each side be classified on its
34
+ * own evidence.
35
+ *
36
+ * Hash comparison is per candidate, not per indexed file, which is what keeps this
37
+ * cheap: a clean working tree produces an empty candidate set and no file is read at
38
+ * all. `mtime` is *not* used as a prefilter even though the plan called for one — the
39
+ * manifest stores a hash and no mtime, so "the mtime did not move" cannot prove the
40
+ * content matches, and using it would trade an exact answer for a fast wrong one.
41
+ *
42
+ * WHAT IT DOES NOT DO
43
+ * -------------------
44
+ * It never runs the analyzer, never writes, and never reads the graph. It also does not
45
+ * decide *which* tier of refresh to run — that needs the analyzer's own judgement about
46
+ * schema and FTS state. It answers one question: has indexed content changed?
47
+ */
48
+ import { createHash } from 'node:crypto';
49
+ import { createReadStream } from 'node:fs';
50
+ import fs from 'node:fs/promises';
51
+ import path from 'node:path';
52
+ import { execFile } from 'node:child_process';
53
+ import { promisify } from 'node:util';
54
+ import { formatBytes } from './coverage.js';
55
+ import { readIndexMeta } from './index-meta.js';
56
+ /**
57
+ * `execFile`, promisified, resolved as decoded text.
58
+ *
59
+ * No shell: the repository path is caller-supplied and only ever travels as `cwd`.
60
+ * `-z` output is NUL-separated rather than newline-separated precisely because a path
61
+ * may contain a newline, and `git status` would otherwise quote it into an unparseable
62
+ * form.
63
+ */
64
+ const run = promisify(execFile);
65
+ const DEFAULT_MAX_FILES = 4000;
66
+ const DEFAULT_HASH_CONCURRENCY = 8;
67
+ const DEFAULT_GIT_TIMEOUT_MS = 15_000;
68
+ /** Run one git command, or report that git could not answer. */
69
+ async function git(repoPath, args, timeoutMs) {
70
+ try {
71
+ const { stdout } = await run('git', args, {
72
+ cwd: repoPath,
73
+ timeout: timeoutMs,
74
+ windowsHide: true,
75
+ // Name lists on a very large repository can exceed the default 1 MB cap. The
76
+ // cap exists so a runaway command cannot exhaust memory; 32 MB of paths is
77
+ // already an unreasonable candidate set, and `maxFiles` truncates it anyway.
78
+ maxBuffer: 32 * 1024 * 1024,
79
+ });
80
+ return stdout;
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ /** Split `-z` output on NUL and drop the trailing empty record. */
87
+ function splitNul(text) {
88
+ return text.split('\0').filter((part) => part !== '');
89
+ }
90
+ /** The key form `fileHashes` uses: forward slashes, no leading `./`. */
91
+ function toKey(relativePath) {
92
+ return relativePath.replace(/\\/g, '/').replace(/^\.\//, '');
93
+ }
94
+ /** Stream one file through sha256. Returns null when it cannot be read. */
95
+ async function hashFile(absolutePath) {
96
+ try {
97
+ const hash = createHash('sha256');
98
+ await new Promise((resolvePromise, reject) => {
99
+ const stream = createReadStream(absolutePath);
100
+ stream.on('error', reject);
101
+ stream.on('data', (chunk) => hash.update(chunk));
102
+ stream.on('end', () => resolvePromise());
103
+ });
104
+ return hash.digest('hex');
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ /** The counts of an empty report, so every early return carries the same shape. */
111
+ const ZERO_COUNTS = {
112
+ checked: 0,
113
+ hashed: 0,
114
+ unchanged: 0,
115
+ modified: 0,
116
+ added: 0,
117
+ deleted: 0,
118
+ excluded: 0,
119
+ };
120
+ /**
121
+ * Compare the working tree against the content the index recorded.
122
+ *
123
+ * @param repoPath absolute repository root
124
+ */
125
+ export async function readDelta(repoPath, options = {}) {
126
+ const now = options.now ?? (() => Date.now());
127
+ const startedAt = now();
128
+ const absRepo = path.resolve(repoPath);
129
+ const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
130
+ const concurrency = Math.max(1, options.hashConcurrency ?? DEFAULT_HASH_CONCURRENCY);
131
+ const gitTimeoutMs = options.gitTimeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
132
+ const empty = (patch) => ({
133
+ repoPath: absRepo,
134
+ indexed: false,
135
+ comparable: false,
136
+ basis: null,
137
+ indexedCommit: null,
138
+ headCommit: null,
139
+ entries: [],
140
+ counts: { ...ZERO_COUNTS },
141
+ needsRefresh: false,
142
+ certain: false,
143
+ truncated: false,
144
+ notes: [],
145
+ durationMs: now() - startedAt,
146
+ readAt: new Date().toISOString(),
147
+ ...patch,
148
+ });
149
+ const meta = await readIndexMeta(absRepo);
150
+ if (meta === null) {
151
+ return empty({ notes: ['该项目还没有 GitNexus 索引,先初始化再说'] });
152
+ }
153
+ const indexedCommit = meta.lastCommit === '' ? null : meta.lastCommit;
154
+ const base = { indexed: true, indexedCommit };
155
+ // The map is normalized-key -> original key, and the hash is read through the
156
+ // original: `fileHashes` is written by GitNexus, and a manifest whose keys use
157
+ // backslashes (Windows builds did) must still match the forward-slash key git
158
+ // reports. Rewriting the manifest's keys instead would mutate what we only read.
159
+ const hashByKey = new Map();
160
+ for (const [rawPath, hash] of Object.entries(meta.fileHashes)) {
161
+ hashByKey.set(toKey(rawPath), hash.toLowerCase());
162
+ }
163
+ if (hashByKey.size === 0) {
164
+ return empty({
165
+ ...base,
166
+ notes: ['该索引没有记录文件哈希(旧格式 manifest),无法判断内容是否变化 —— 直接刷新'],
167
+ });
168
+ }
169
+ const headCommit = (await git(absRepo, ['rev-parse', 'HEAD'], gitTimeoutMs))?.trim() ?? null;
170
+ let basis = null;
171
+ let candidates = [];
172
+ if (indexedCommit !== null && headCommit !== null) {
173
+ const diff = await git(absRepo, ['diff', '--no-renames', '--name-only', '-z', indexedCommit, '--'], gitTimeoutMs);
174
+ if (diff !== null) {
175
+ basis = 'index';
176
+ candidates = splitNul(diff);
177
+ }
178
+ }
179
+ if (basis === null && headCommit !== null) {
180
+ // The recorded commit is gone (rebase, branch rewrite, shallow clone) or the
181
+ // manifest never had one. Working tree vs HEAD is the honest fallback: it finds
182
+ // uncommitted and newly committed files, and it cannot see a difference that was
183
+ // committed before the index was written. Say so rather than implying otherwise.
184
+ const againstHead = await git(absRepo, ['diff', '--no-renames', '--name-only', '-z', 'HEAD', '--'], gitTimeoutMs);
185
+ if (againstHead !== null) {
186
+ basis = 'worktree';
187
+ candidates = splitNul(againstHead);
188
+ }
189
+ }
190
+ if (basis === null) {
191
+ return empty({
192
+ ...base,
193
+ headCommit,
194
+ notes: [
195
+ indexedCommit === null
196
+ ? '索引没有记录提交基线,且 git 也无法读取 HEAD —— 无法比较,直接刷新'
197
+ : '索引记录的提交在本地 git 历史中已不可用,且无法读取 HEAD —— 无法比较,直接刷新',
198
+ ],
199
+ });
200
+ }
201
+ const untracked = await git(absRepo, ['ls-files', '--others', '--exclude-standard', '-z'], gitTimeoutMs);
202
+ if (untracked !== null) {
203
+ candidates.push(...splitNul(untracked));
204
+ }
205
+ const seen = new Set();
206
+ const unique = [];
207
+ for (const candidate of candidates) {
208
+ const key = toKey(candidate);
209
+ if (key === '' || seen.has(key))
210
+ continue;
211
+ // The index's own storage is never indexed content. `.gitnexus/` self-ignores in
212
+ // most repositories (GitNexus writes a `*` .gitignore there), so this only matters
213
+ // where it does not — but in exactly that case every read would report the index
214
+ // manifest itself as a new file and ask for a refresh forever.
215
+ if (key.startsWith('.gitnexus/') || key.startsWith('.git/'))
216
+ continue;
217
+ seen.add(key);
218
+ unique.push(key);
219
+ }
220
+ unique.sort();
221
+ const truncated = unique.length > maxFiles;
222
+ const examined = truncated ? unique.slice(0, maxFiles) : unique;
223
+ const entries = [];
224
+ const counts = { ...ZERO_COUNTS };
225
+ counts.checked = examined.length;
226
+ // Bounded parallelism rather than one read at a time: a 4000-file candidate set read
227
+ // sequentially is dominated by syscall latency, and these are local files.
228
+ for (let offset = 0; offset < examined.length; offset += concurrency) {
229
+ const batch = examined.slice(offset, offset + concurrency);
230
+ const settled = await Promise.all(batch.map(async (key) => {
231
+ const absolute = path.join(absRepo, key);
232
+ let size;
233
+ try {
234
+ const stat = await fs.stat(absolute);
235
+ if (!stat.isFile())
236
+ return null;
237
+ size = stat.size;
238
+ }
239
+ catch {
240
+ // Gone from the working tree. Only worth reporting when the index had it;
241
+ // an untracked file deleted between `ls-files` and this stat is not news.
242
+ return hashByKey.has(key) ? { path: key, kind: 'deleted', reason: null } : null;
243
+ }
244
+ const recorded = hashByKey.get(key);
245
+ if (recorded === undefined) {
246
+ const cap = meta.coverageMaxFileSizeBytes;
247
+ if (cap !== null && size > cap) {
248
+ return {
249
+ path: key,
250
+ kind: 'excluded',
251
+ reason: `超过索引记录的大小上限(${formatBytes(cap)}),刷新也会被跳过`,
252
+ };
253
+ }
254
+ return { path: key, kind: 'added', reason: null };
255
+ }
256
+ counts.hashed += 1;
257
+ const current = await hashFile(absolute);
258
+ if (current === null) {
259
+ // Unreadable is not unchanged. Treating it as modified makes the panel ask
260
+ // for a refresh; treating it as unchanged would report a stale index as
261
+ // current, which is the one error this module exists to prevent.
262
+ return { path: key, kind: 'modified', reason: '无法读取文件内容,按已变更处理' };
263
+ }
264
+ if (current === recorded) {
265
+ counts.unchanged += 1;
266
+ return null;
267
+ }
268
+ return { path: key, kind: 'modified', reason: null };
269
+ }));
270
+ for (const entry of settled) {
271
+ if (entry !== null)
272
+ entries.push(entry);
273
+ }
274
+ }
275
+ entries.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
276
+ for (const entry of entries)
277
+ counts[entry.kind] += 1;
278
+ const actionable = counts.modified + counts.added + counts.deleted;
279
+ const certain = basis === 'index';
280
+ const notes = [];
281
+ if (basis === 'worktree') {
282
+ notes.push('索引没有记录可用的提交基线:只比较了工作区相对 HEAD 的改动,索引建立之后已提交的改动看不到');
283
+ }
284
+ if (truncated) {
285
+ notes.push(`候选文件超过 ${maxFiles} 个,只检查了前 ${maxFiles} 个 —— 建议直接刷新`);
286
+ }
287
+ if (actionable === 0) {
288
+ // A clean worktree is not the same claim as a clean index. Saying "一致" on the
289
+ // worktree basis is how a stale index gets reported as current: the next commit
290
+ // makes it stale and this comparison will still be empty.
291
+ notes.push(certain
292
+ ? counts.checked === 0
293
+ ? '工作区与索引记录一致:没有任何文件相对索引提交发生改动'
294
+ : `工作区与索引记录一致:${counts.checked} 个候选文件中 ${counts.unchanged} 个内容哈希匹配` +
295
+ (counts.excluded > 0 ? `,${counts.excluded} 个属索引策略排除` : '')
296
+ : '工作区相对 HEAD 没有改动,但无法确认索引已包含当前提交 —— 需要刷新才能确定');
297
+ if (counts.excluded > 0) {
298
+ notes.push('被排除的文件刷新也会再次跳过,因此不需要为它们刷新索引');
299
+ }
300
+ }
301
+ else {
302
+ const parts = [];
303
+ if (counts.modified > 0)
304
+ parts.push(`${counts.modified} 个修改`);
305
+ if (counts.added > 0)
306
+ parts.push(`${counts.added} 个新增`);
307
+ if (counts.deleted > 0)
308
+ parts.push(`${counts.deleted} 个删除`);
309
+ notes.unshift(`索引内容已落后:${parts.join('、')}`);
310
+ }
311
+ return {
312
+ repoPath: absRepo,
313
+ indexed: true,
314
+ comparable: true,
315
+ basis,
316
+ indexedCommit,
317
+ headCommit,
318
+ entries,
319
+ counts,
320
+ needsRefresh: actionable > 0,
321
+ certain,
322
+ truncated,
323
+ notes,
324
+ durationMs: now() - startedAt,
325
+ readAt: new Date().toISOString(),
326
+ };
327
+ }
328
+ /** One-line verdict for a tool result or a log line. */
329
+ export function describeDelta(report) {
330
+ if (!report.comparable) {
331
+ return `无法差量判断:${report.notes[0] ?? '原因未知'}`;
332
+ }
333
+ if (!report.needsRefresh) {
334
+ return report.certain
335
+ ? `无需刷新(${report.counts.checked} 个候选,${report.counts.hashed} 次哈希,${report.durationMs}ms)`
336
+ : `无法确认(${report.counts.checked} 个候选,${report.durationMs}ms):${report.notes[0] ?? '索引没有记录提交基线'}`;
337
+ }
338
+ const changed = report.entries.filter((entry) => entry.kind !== 'excluded');
339
+ const preview = changed
340
+ .slice(0, 10)
341
+ .map((entry) => `${entry.kind === 'modified' ? 'M' : entry.kind === 'added' ? 'A' : 'D'} ${entry.path}`)
342
+ .join('\n');
343
+ const more = changed.length > 10 ? `\n…还有 ${changed.length - 10} 个` : '';
344
+ return (`需要刷新:${report.counts.modified} 改 / ${report.counts.added} 增 / ${report.counts.deleted} 删` +
345
+ `(${report.durationMs}ms)\n${preview}${more}`);
346
+ }
347
+ //# sourceMappingURL=delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/gitnexus/delta.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@
21
21
  * truncated activity list reads as "this is all the activity there was", which is
22
22
  * the one thing it must not mean.
23
23
  */
24
+ import type { CommitDiff, FileHistory } from 'dsh-gitnexus-wire';
24
25
  /**
25
26
  * indexed — the manifest holds this path, so the graph can answer about it.
26
27
  * excluded — a fresh scan would not select it either (dotfile, ignore rule, or
@@ -58,6 +59,48 @@ export interface ActivityBranch {
58
59
  lastAuthor: string;
59
60
  current: boolean;
60
61
  }
62
+ /** One commit in the activity window, with the index verdict of its touched files. */
63
+ export interface ActivityCommit {
64
+ sha: string;
65
+ shortSha: string;
66
+ date: string;
67
+ author: string;
68
+ subject: string;
69
+ files: number;
70
+ insertions: number;
71
+ deletions: number;
72
+ verdict: FileVerdict;
73
+ }
74
+ /** One row of the activity × index cross-tab. */
75
+ export interface ActivityCrossRow {
76
+ verdict: FileVerdict;
77
+ files: number;
78
+ changes: number;
79
+ insertions: number;
80
+ deletions: number;
81
+ }
82
+ export interface ActivityCross {
83
+ rows: ActivityCrossRow[];
84
+ totalFiles: number;
85
+ totalChanges: number;
86
+ }
87
+ /** What changed since the commit the index was built from. */
88
+ export interface ActivityBaseline {
89
+ ref: string | null;
90
+ /** `window` is the explicit fallback when the index recorded no commit. */
91
+ source: 'index' | 'window';
92
+ available: boolean;
93
+ shortSha: string | null;
94
+ date: string | null;
95
+ subject: string | null;
96
+ author: string | null;
97
+ commits: number;
98
+ files: number;
99
+ insertions: number;
100
+ deletions: number;
101
+ changedFiles: ActivityFile[];
102
+ reason: string | null;
103
+ }
61
104
  export interface HistogramBucket {
62
105
  label: string;
63
106
  commits: number;
@@ -105,6 +148,30 @@ export interface ActivityInfo {
105
148
  branches: ActivityBranch[];
106
149
  histogram: ActivityHistogram;
107
150
  currentBranch: string | null;
151
+ /** Activity × index cross-tab over every file in the window. */
152
+ cross: ActivityCross;
153
+ /** Changes since the index's recorded commit, or null when there is no baseline. */
154
+ baseline: ActivityBaseline | null;
155
+ /** Newest commits first, capped; each carries its aggregate index verdict. */
156
+ timeline: ActivityCommit[];
157
+ /** True when the activity window held more commits than the timeline cap. */
158
+ timelineTruncated: boolean;
159
+ }
160
+ /** One commit's patch for a single file, bounded for the panel. */
161
+ export type { CommitDiff } from 'dsh-gitnexus-wire';
162
+ /**
163
+ * The change a commit made to one file.
164
+ *
165
+ * `git show <sha> -- <path>` is the only command that answers this without checking
166
+ * out anything, and it is read-only. The path has already been resolved inside the
167
+ * project by the route; the sha is validated here because it reaches git as an argument.
168
+ */
169
+ export declare function readCommitDiff(repoPath: string, filePath: string, sha: string): Promise<CommitDiff>;
170
+ /** One commit touching a specific file, and a file's bounded history. */
171
+ export type { FileHistory, FileHistoryCommit } from 'dsh-gitnexus-wire';
172
+ export interface ReadFileHistoryOptions {
173
+ days?: number;
174
+ maxCommits?: number;
108
175
  }
109
176
  export interface ReadGitActivityOptions {
110
177
  sinceDays?: number;
@@ -114,6 +181,8 @@ export interface ReadGitActivityOptions {
114
181
  maxBranches?: number;
115
182
  indexedPaths?: Iterable<string>;
116
183
  scannablePaths?: Iterable<string>;
184
+ /** The index's recorded commit; when set, also review HEAD against it. */
185
+ baselineRef?: string | null;
117
186
  }
118
187
  /**
119
188
  * Bucket commit stamps into a time histogram.
@@ -133,4 +202,12 @@ export declare function buildHistogram(stamps: ActivityStamp[], sinceDays: numbe
133
202
  * Returns `null` when git cannot answer at all.
134
203
  */
135
204
  export declare function readGitActivity(repoPath: string, options?: ReadGitActivityOptions): Promise<ActivityInfo | null>;
205
+ /**
206
+ * Read one file's commits for its own timeline.
207
+ *
208
+ * Kept separate from {@link readGitActivity} because "show me this file's history"
209
+ * should not pay for the whole repository's numstat. `--follow` is intentional: a
210
+ * renamed file's timeline that stops at the rename is a misleading one.
211
+ */
212
+ export declare function readFileActivity(repoPath: string, filePath: string, options?: ReadFileHistoryOptions): Promise<FileHistory>;
136
213
  //# sourceMappingURL=git-activity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-activity.d.ts","sourceRoot":"","sources":["../../src/gitnexus/git-activity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git-activity.d.ts","sourceRoot":"","sources":["../../src/gitnexus/git-activity.ts"],"names":[],"mappings":"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"}