repo-dive 0.4.1 → 0.4.2
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/README.md +32 -0
- package/dist/cli.js +149 -23
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -81,6 +81,38 @@ export default defineConfig({
|
|
|
81
81
|
|
|
82
82
|
`contributors.aliases` merges the multiple identities one person commits under (work + personal email, GitHub noreply, name variants) so attribution, the contributors table and code-survival-by-contributor count them once; a group can also carry a `displayName`, a profile `url` and a `kind` (`human`/`bot`/`ai`, otherwise auto-derived — the dashboard badges bots and AI agents and lists them apart from humans). The config is read by `index`. See [docs/specs/07-config.md](docs/specs/07-config.md) for details.
|
|
83
83
|
|
|
84
|
+
## AI agents (MCP)
|
|
85
|
+
|
|
86
|
+
`repo-dive mcp` serves the metrics cube over the Model Context Protocol on stdio, so an agent can explore a repository's history by asking SQL questions. Two tools:
|
|
87
|
+
|
|
88
|
+
- **`schema`** — tables, available metrics with row counts, sample category keys per metric and the commit range; worth calling before writing queries.
|
|
89
|
+
- **`query`** — one read-only statement (`SELECT`/`WITH`/`EXPLAIN`) against the cube, returning `{ columns, rows, truncated }` (up to 200 rows).
|
|
90
|
+
|
|
91
|
+
Run `scan` and `index` first: the server exits immediately if there is no cube at `.repo-dive/index/metrics.sqlite`. The database is opened read-only, so nothing an agent asks can change the catalog.
|
|
92
|
+
|
|
93
|
+
For [Claude Code](https://code.claude.com/docs/en/mcp), run this inside the repository you want to ask questions about:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
claude mcp add repo-dive -- npx -y repo-dive mcp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Or commit a project-scoped `.mcp.json` at the repository root, so everyone on the team gets the same server:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"mcpServers": {
|
|
104
|
+
"repo-dive": {
|
|
105
|
+
"command": "npx",
|
|
106
|
+
"args": ["-y", "repo-dive", "mcp"]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then ask things like "which languages grew fastest last year?" or "how has the share of AI-assisted commits changed?".
|
|
113
|
+
|
|
114
|
+
The same stdio server works with any MCP client — point yours at `npx repo-dive mcp`, adding `--repo /path/to/repo` if the client does not start it inside the repository being analyzed.
|
|
115
|
+
|
|
84
116
|
## Development
|
|
85
117
|
|
|
86
118
|
The project is written in TypeScript with [Effect](https://effect.website) v4 (beta) and its built-in CLI toolkit (`effect/unstable/cli`).
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import http from "node:http";
|
|
|
5
5
|
import * as Crypto$1 from "node:crypto";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
7
|
import * as NFS from "node:fs";
|
|
8
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { existsSync, mkdirSync, statSync } from "node:fs";
|
|
9
9
|
import * as OS from "node:os";
|
|
10
10
|
import os from "node:os";
|
|
11
11
|
import * as Path from "node:path";
|
|
@@ -52170,7 +52170,7 @@ var runWith = (command, config) => {
|
|
|
52170
52170
|
};
|
|
52171
52171
|
var package_default = {
|
|
52172
52172
|
name: "repo-dive",
|
|
52173
|
-
version: "0.4.
|
|
52173
|
+
version: "0.4.2",
|
|
52174
52174
|
description: "Dive into a git repository's history: per-commit snapshots, an indexed metrics catalog and an interactive dashboard",
|
|
52175
52175
|
keywords: [
|
|
52176
52176
|
"git",
|
|
@@ -52240,6 +52240,7 @@ var package_default = {
|
|
|
52240
52240
|
"lint-staged": { "**": ["prettier --ignore-unknown --write"] },
|
|
52241
52241
|
prettier: "@kachkaev/prettier-config",
|
|
52242
52242
|
devDependencies: {
|
|
52243
|
+
"@changesets/changelog-github": "0.7.0",
|
|
52243
52244
|
"@changesets/cli": "2.31.1",
|
|
52244
52245
|
"@changesets/config": "3.1.4",
|
|
52245
52246
|
"@effect/platform-node": "4.0.0-beta.99",
|
|
@@ -52723,12 +52724,12 @@ var writeCollectorOutput = ({ catalog, sha, collector, cacheKey, output, duratio
|
|
|
52723
52724
|
var openCaches = /* @__PURE__ */ new Map();
|
|
52724
52725
|
/** Bump when the table shape changes; a mismatch drops the cache and rebuilds. */
|
|
52725
52726
|
var schemaVersion = 2;
|
|
52727
|
+
var blobCachePath = (repoRoot) => path.join(repoRoot, catalogDirName, "cache", "blob-cache.sqlite");
|
|
52726
52728
|
var getBlobCache = (repoRoot) => {
|
|
52727
52729
|
const existing = openCaches.get(repoRoot);
|
|
52728
|
-
if (existing) return existing;
|
|
52729
|
-
|
|
52730
|
-
|
|
52731
|
-
const db = new DatabaseSync(path.join(cacheDir, "blob-cache.sqlite"));
|
|
52730
|
+
if (existing) return existing.cache;
|
|
52731
|
+
mkdirSync(path.join(repoRoot, catalogDirName, "cache"), { recursive: true });
|
|
52732
|
+
const db = new DatabaseSync(blobCachePath(repoRoot));
|
|
52732
52733
|
db.exec("PRAGMA journal_mode = WAL");
|
|
52733
52734
|
const storedSchema = db.prepare("PRAGMA user_version").get();
|
|
52734
52735
|
if (Number(storedSchema?.["user_version"] ?? 0) !== schemaVersion) {
|
|
@@ -52768,9 +52769,82 @@ var getBlobCache = (repoRoot) => {
|
|
|
52768
52769
|
}
|
|
52769
52770
|
}
|
|
52770
52771
|
};
|
|
52771
|
-
openCaches.set(repoRoot,
|
|
52772
|
+
openCaches.set(repoRoot, {
|
|
52773
|
+
db,
|
|
52774
|
+
cache
|
|
52775
|
+
});
|
|
52772
52776
|
return cache;
|
|
52773
52777
|
};
|
|
52778
|
+
/** Bytes the cache occupies, counting the write-ahead log SQLite keeps beside it. */
|
|
52779
|
+
var blobCacheSizeBytes = (repoRoot) => {
|
|
52780
|
+
const base = blobCachePath(repoRoot);
|
|
52781
|
+
return [
|
|
52782
|
+
"",
|
|
52783
|
+
"-wal",
|
|
52784
|
+
"-shm"
|
|
52785
|
+
].map((suffix) => `${base}${suffix}`).reduce((total, filePath) => total + (existsSync(filePath) ? statSync(filePath).size : 0), 0);
|
|
52786
|
+
};
|
|
52787
|
+
/** Opens the cache file for maintenance, or `undefined` when there is none. */
|
|
52788
|
+
var openForMaintenance = (repoRoot) => {
|
|
52789
|
+
const filePath = blobCachePath(repoRoot);
|
|
52790
|
+
if (!existsSync(filePath)) return;
|
|
52791
|
+
const open = openCaches.get(repoRoot);
|
|
52792
|
+
if (open) {
|
|
52793
|
+
open.db.close();
|
|
52794
|
+
openCaches.delete(repoRoot);
|
|
52795
|
+
}
|
|
52796
|
+
const db = new DatabaseSync(filePath);
|
|
52797
|
+
if (!db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'blob_results'").get()) {
|
|
52798
|
+
db.close();
|
|
52799
|
+
return;
|
|
52800
|
+
}
|
|
52801
|
+
return db;
|
|
52802
|
+
};
|
|
52803
|
+
/** What the cache currently holds, one row per (collector, fingerprint) pair. */
|
|
52804
|
+
var listBlobCacheNamespaces = (repoRoot) => {
|
|
52805
|
+
const db = openForMaintenance(repoRoot);
|
|
52806
|
+
if (!db) return [];
|
|
52807
|
+
try {
|
|
52808
|
+
return db.prepare("SELECT collector, cache_key, count(*) AS entry_count FROM blob_results GROUP BY collector, cache_key").all().flatMap((row) => {
|
|
52809
|
+
const collector = row["collector"];
|
|
52810
|
+
const cacheKey = row["cache_key"];
|
|
52811
|
+
return typeof collector === "string" && typeof cacheKey === "string" ? [{
|
|
52812
|
+
collector,
|
|
52813
|
+
cacheKey,
|
|
52814
|
+
entryCount: Number(row["entry_count"])
|
|
52815
|
+
}] : [];
|
|
52816
|
+
});
|
|
52817
|
+
} finally {
|
|
52818
|
+
db.close();
|
|
52819
|
+
}
|
|
52820
|
+
};
|
|
52821
|
+
/**
|
|
52822
|
+
* Deletes the given namespaces and compacts the file, returning how many bytes
|
|
52823
|
+
* that gave back. Entries are content-derived, so removing them costs at most
|
|
52824
|
+
* a re-scan of the blobs involved — never any recorded data.
|
|
52825
|
+
*/
|
|
52826
|
+
var pruneBlobCacheNamespaces = (repoRoot, namespaces) => {
|
|
52827
|
+
if (namespaces.length === 0) return 0;
|
|
52828
|
+
const sizeBefore = blobCacheSizeBytes(repoRoot);
|
|
52829
|
+
const db = openForMaintenance(repoRoot);
|
|
52830
|
+
if (!db) return 0;
|
|
52831
|
+
try {
|
|
52832
|
+
const deleteNamespace = db.prepare("DELETE FROM blob_results WHERE collector = ? AND cache_key = ?");
|
|
52833
|
+
db.exec("BEGIN");
|
|
52834
|
+
try {
|
|
52835
|
+
for (const { collector, cacheKey } of namespaces) deleteNamespace.run(collector, cacheKey);
|
|
52836
|
+
db.exec("COMMIT");
|
|
52837
|
+
} catch (error) {
|
|
52838
|
+
db.exec("ROLLBACK");
|
|
52839
|
+
throw error;
|
|
52840
|
+
}
|
|
52841
|
+
db.exec("VACUUM");
|
|
52842
|
+
db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
52843
|
+
} finally {
|
|
52844
|
+
db.close();
|
|
52845
|
+
}
|
|
52846
|
+
return Math.max(0, sizeBefore - blobCacheSizeBytes(repoRoot));
|
|
52847
|
+
};
|
|
52774
52848
|
//#endregion
|
|
52775
52849
|
//#region src/lib/collectors/tree-files.ts
|
|
52776
52850
|
/**
|
|
@@ -54459,9 +54533,12 @@ var buildPlan = (repoRoot) => gen(function* () {
|
|
|
54459
54533
|
"rev-list",
|
|
54460
54534
|
"HEAD"
|
|
54461
54535
|
])).split("\n").filter(Boolean));
|
|
54536
|
+
const firstParentShas = yield* listFirstParentShas(repoRoot);
|
|
54462
54537
|
const config = yield* loadConfig(repoRoot);
|
|
54463
54538
|
const currentCacheKeys = new Map(builtInCollectors.map((collector) => [collector.name, collectorCacheKey(collector, config)]));
|
|
54539
|
+
const snapshotCollectorNames = new Set(builtInCollectors.filter((collector) => describesTreeState(collector)).map((collector) => collector.name));
|
|
54464
54540
|
const unreachableShas = [];
|
|
54541
|
+
const offMainlineOutputs = [];
|
|
54465
54542
|
const staleOutputs = [];
|
|
54466
54543
|
const countsByCollector = /* @__PURE__ */ new Map();
|
|
54467
54544
|
for (const sha of catalogShas) {
|
|
@@ -54472,6 +54549,10 @@ var buildPlan = (repoRoot) => gen(function* () {
|
|
|
54472
54549
|
const collectorNames = yield* readdirIfExists(path.join(commitsPath, sha));
|
|
54473
54550
|
for (const collectorName of collectorNames) {
|
|
54474
54551
|
countsByCollector.set(collectorName, (countsByCollector.get(collectorName) ?? 0) + 1);
|
|
54552
|
+
if (!firstParentShas.has(sha) && snapshotCollectorNames.has(collectorName)) offMainlineOutputs.push({
|
|
54553
|
+
sha,
|
|
54554
|
+
collectorName
|
|
54555
|
+
});
|
|
54475
54556
|
const currentCacheKey = currentCacheKeys.get(collectorName);
|
|
54476
54557
|
if (currentCacheKey === void 0) {
|
|
54477
54558
|
staleOutputs.push({
|
|
@@ -54492,12 +54573,18 @@ var buildPlan = (repoRoot) => gen(function* () {
|
|
|
54492
54573
|
});
|
|
54493
54574
|
}
|
|
54494
54575
|
}
|
|
54576
|
+
const liveNamespaces = new Set([...currentCacheKeys].map(([collectorName, cacheKey]) => `${collectorName}:${cacheKey}`));
|
|
54495
54577
|
return {
|
|
54496
54578
|
catalogPath,
|
|
54497
54579
|
commitsPath,
|
|
54498
54580
|
unreachableShas,
|
|
54581
|
+
offMainlineOutputs,
|
|
54499
54582
|
staleOutputs,
|
|
54500
|
-
countsByCollector
|
|
54583
|
+
countsByCollector,
|
|
54584
|
+
staleCacheNamespaces: (yield* try_({
|
|
54585
|
+
try: () => listBlobCacheNamespaces(repoRoot),
|
|
54586
|
+
catch: toError$2
|
|
54587
|
+
})).filter((namespace) => !liveNamespaces.has(`${namespace.collector}:${namespace.cacheKey}`))
|
|
54501
54588
|
};
|
|
54502
54589
|
});
|
|
54503
54590
|
var removePaths = (paths, dryRun) => dryRun ? void_$1 : forEach$1(paths, (target) => tryPromise({
|
|
@@ -54528,11 +54615,30 @@ var pruneEmptyCommitDirs = (commitsPath) => gen(function* () {
|
|
|
54528
54615
|
}
|
|
54529
54616
|
return pruned;
|
|
54530
54617
|
});
|
|
54531
|
-
var
|
|
54532
|
-
|
|
54618
|
+
var staleCacheEntryCount = (plan) => plan.staleCacheNamespaces.reduce((total, namespace) => total + namespace.entryCount, 0);
|
|
54619
|
+
/** Human-readable size, e.g. "3.4 MB". */
|
|
54620
|
+
var formatBytes = (bytes) => {
|
|
54621
|
+
const units = [
|
|
54622
|
+
"B",
|
|
54623
|
+
"KB",
|
|
54624
|
+
"MB",
|
|
54625
|
+
"GB"
|
|
54626
|
+
];
|
|
54627
|
+
let value = bytes;
|
|
54628
|
+
let unitIndex = 0;
|
|
54629
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
54630
|
+
value /= 1024;
|
|
54631
|
+
unitIndex += 1;
|
|
54632
|
+
}
|
|
54633
|
+
return `${unitIndex === 0 ? value : value.toFixed(1)} ${units[unitIndex]}`;
|
|
54634
|
+
};
|
|
54635
|
+
var runGc = ({ repoPath, unreachable, offMainline, stale, collectorNames, dryRun = false, yes = false }) => gen(function* () {
|
|
54636
|
+
const repoRoot = yield* resolveRepoRoot(repoPath);
|
|
54637
|
+
const plan = yield* buildPlan(repoRoot);
|
|
54533
54638
|
const requestedCollectors = (collectorNames ?? "").split(",").map((name) => name.trim()).filter(Boolean);
|
|
54534
|
-
const anyFlagGiven = unreachable === true || stale === true || requestedCollectors.length > 0;
|
|
54639
|
+
const anyFlagGiven = unreachable === true || offMainline === true || stale === true || requestedCollectors.length > 0;
|
|
54535
54640
|
let removeUnreachable = unreachable === true;
|
|
54641
|
+
let removeOffMainline = offMainline === true;
|
|
54536
54642
|
let removeStale = stale === true;
|
|
54537
54643
|
let collectorsToRemove = requestedCollectors;
|
|
54538
54644
|
if (!anyFlagGiven) {
|
|
@@ -54541,10 +54647,17 @@ var runGc = ({ repoPath, unreachable, stale, collectorNames, dryRun = false, yes
|
|
|
54541
54647
|
title: `Data for ${plan.unreachableShas.length} commits no longer reachable from HEAD`,
|
|
54542
54648
|
value: { kind: "unreachable" }
|
|
54543
54649
|
});
|
|
54544
|
-
if (plan.
|
|
54545
|
-
title: `${plan.
|
|
54546
|
-
value: { kind: "
|
|
54650
|
+
if (plan.offMainlineOutputs.length > 0) choices.push({
|
|
54651
|
+
title: `${plan.offMainlineOutputs.length} snapshot outputs taken off HEAD's first-parent chain (left out of the cube)`,
|
|
54652
|
+
value: { kind: "offMainline" }
|
|
54547
54653
|
});
|
|
54654
|
+
if (plan.staleOutputs.length > 0 || plan.staleCacheNamespaces.length > 0) {
|
|
54655
|
+
const parts = [...plan.staleOutputs.length > 0 ? [`${plan.staleOutputs.length} collector outputs`] : [], ...plan.staleCacheNamespaces.length > 0 ? [`${staleCacheEntryCount(plan)} blob-cache entries`] : []];
|
|
54656
|
+
choices.push({
|
|
54657
|
+
title: `Stale ${parts.join(" and ")} (old versions or removed collectors)`,
|
|
54658
|
+
value: { kind: "stale" }
|
|
54659
|
+
});
|
|
54660
|
+
}
|
|
54548
54661
|
for (const [name, count] of [...plan.countsByCollector.entries()].toSorted(([left], [right]) => left.localeCompare(right))) choices.push({
|
|
54549
54662
|
title: `All ${count} outputs of collector "${name}"`,
|
|
54550
54663
|
value: {
|
|
@@ -54565,19 +54678,26 @@ var runGc = ({ repoPath, unreachable, stale, collectorNames, dryRun = false, yes
|
|
|
54565
54678
|
return;
|
|
54566
54679
|
}
|
|
54567
54680
|
removeUnreachable = selected.some((action) => action.kind === "unreachable");
|
|
54681
|
+
removeOffMainline = selected.some((action) => action.kind === "offMainline");
|
|
54568
54682
|
removeStale = selected.some((action) => action.kind === "stale");
|
|
54569
54683
|
collectorsToRemove = selected.flatMap((action) => action.kind === "collector" ? [action.name] : []);
|
|
54570
54684
|
}
|
|
54571
|
-
const targets =
|
|
54685
|
+
const targets = /* @__PURE__ */ new Set();
|
|
54572
54686
|
const reportLines = [];
|
|
54573
54687
|
if (removeUnreachable && plan.unreachableShas.length > 0) {
|
|
54574
|
-
|
|
54688
|
+
for (const sha of plan.unreachableShas) targets.add(path.join(plan.commitsPath, sha));
|
|
54575
54689
|
reportLines.push(`${plan.unreachableShas.length} unreachable commit folders`);
|
|
54576
54690
|
}
|
|
54691
|
+
if (removeOffMainline && plan.offMainlineOutputs.length > 0) {
|
|
54692
|
+
for (const output of plan.offMainlineOutputs) targets.add(path.join(plan.commitsPath, output.sha, output.collectorName));
|
|
54693
|
+
reportLines.push(`${plan.offMainlineOutputs.length} off-mainline snapshot outputs`);
|
|
54694
|
+
}
|
|
54577
54695
|
if (removeStale && plan.staleOutputs.length > 0) {
|
|
54578
|
-
|
|
54696
|
+
for (const output of plan.staleOutputs) targets.add(path.join(plan.commitsPath, output.sha, output.collectorName));
|
|
54579
54697
|
reportLines.push(`${plan.staleOutputs.length} stale collector outputs`);
|
|
54580
54698
|
}
|
|
54699
|
+
const pruneCacheNamespaces = removeStale && plan.staleCacheNamespaces.length > 0;
|
|
54700
|
+
if (pruneCacheNamespaces) reportLines.push(`${staleCacheEntryCount(plan)} stale blob-cache entries`);
|
|
54581
54701
|
for (const name of collectorsToRemove) {
|
|
54582
54702
|
const count = plan.countsByCollector.get(name) ?? 0;
|
|
54583
54703
|
if (count === 0) {
|
|
@@ -54585,10 +54705,10 @@ var runGc = ({ repoPath, unreachable, stale, collectorNames, dryRun = false, yes
|
|
|
54585
54705
|
continue;
|
|
54586
54706
|
}
|
|
54587
54707
|
const shas = yield* readdirIfExists(plan.commitsPath);
|
|
54588
|
-
for (const sha of shas) targets.
|
|
54708
|
+
for (const sha of shas) targets.add(path.join(plan.commitsPath, sha, name));
|
|
54589
54709
|
reportLines.push(`${count} outputs of collector "${name}"`);
|
|
54590
54710
|
}
|
|
54591
|
-
if (targets.
|
|
54711
|
+
if (targets.size === 0 && !pruneCacheNamespaces) {
|
|
54592
54712
|
yield* log("Nothing to garbage-collect.");
|
|
54593
54713
|
return;
|
|
54594
54714
|
}
|
|
@@ -54603,22 +54723,28 @@ var runGc = ({ repoPath, unreachable, stale, collectorNames, dryRun = false, yes
|
|
|
54603
54723
|
return;
|
|
54604
54724
|
}
|
|
54605
54725
|
}
|
|
54606
|
-
yield* removePaths(targets, false);
|
|
54726
|
+
yield* removePaths([...targets], false);
|
|
54607
54727
|
const pruned = yield* pruneEmptyCommitDirs(plan.commitsPath);
|
|
54608
|
-
|
|
54728
|
+
const cacheBytesReclaimed = pruneCacheNamespaces ? yield* try_({
|
|
54729
|
+
try: () => pruneBlobCacheNamespaces(repoRoot, plan.staleCacheNamespaces),
|
|
54730
|
+
catch: toError$2
|
|
54731
|
+
}) : 0;
|
|
54732
|
+
yield* log(`${summary}${pruned > 0 ? ` Pruned ${pruned} empty commit folders.` : ""}${cacheBytesReclaimed > 0 ? ` Blob cache shrank by ${formatBytes(cacheBytesReclaimed)}.` : ""} Run \`repo-dive index\` to refresh rollups.`);
|
|
54609
54733
|
}).pipe(provide(layer$1));
|
|
54610
54734
|
//#endregion
|
|
54611
54735
|
//#region src/commands/gc.ts
|
|
54612
54736
|
var gcCommand = make$3("gc", {
|
|
54613
54737
|
repoPath: string("repo").pipe(withDefault("."), withDescription$1("Path to the git repository whose catalog to clean (defaults to the current directory)")),
|
|
54614
54738
|
unreachable: boolean("unreachable").pipe(withDescription$1("Remove data for commits no longer reachable from HEAD")),
|
|
54615
|
-
|
|
54739
|
+
offMainline: boolean("off-mainline").pipe(withDescription$1("Remove tree snapshots stored under commits that are not on HEAD's first-parent chain")),
|
|
54740
|
+
stale: boolean("stale").pipe(withDescription$1("Remove catalog outputs and blob-cache entries written by old collector versions or by collectors that no longer exist")),
|
|
54616
54741
|
collectorNames: optional$1(string("collectors").pipe(withDescription$1("Comma-separated collector names whose outputs should be removed entirely"))),
|
|
54617
54742
|
dryRun: boolean("dry-run").pipe(withDescription$1("Report what would be removed without removing it")),
|
|
54618
54743
|
yes: boolean("yes").pipe(withAlias("y"), withDescription$1("Skip the confirmation prompt"))
|
|
54619
|
-
}).pipe(withDescription("Garbage-collect the catalog: unreachable commits, stale versions or whole collectors (interactive without flags)"), withHandler((config) => runGc({
|
|
54744
|
+
}).pipe(withDescription("Garbage-collect the catalog: unreachable commits, off-mainline snapshots, stale versions or whole collectors (interactive without flags)"), withHandler((config) => runGc({
|
|
54620
54745
|
repoPath: config.repoPath,
|
|
54621
54746
|
unreachable: config.unreachable,
|
|
54747
|
+
offMainline: config.offMainline,
|
|
54622
54748
|
stale: config.stale,
|
|
54623
54749
|
collectorNames: getOrUndefined$1(config.collectorNames),
|
|
54624
54750
|
dryRun: config.dryRun,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repo-dive",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Dive into a git repository's history: per-commit snapshots, an indexed metrics catalog and an interactive dashboard",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"git",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"prettier": "@kachkaev/prettier-config",
|
|
54
54
|
"devDependencies": {
|
|
55
|
+
"@changesets/changelog-github": "0.7.0",
|
|
55
56
|
"@changesets/cli": "2.31.1",
|
|
56
57
|
"@changesets/config": "3.1.4",
|
|
57
58
|
"@effect/platform-node": "4.0.0-beta.99",
|