git-dedup-core 0.1.0 → 2.0.1

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 CHANGED
@@ -3,17 +3,18 @@
3
3
  [![npm version](https://img.shields.io/npm/v/git-dedup-core.svg)](https://www.npmjs.com/package/git-dedup-core)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/git-dedup-core.svg)](https://www.npmjs.com/package/git-dedup-core)
5
5
  [![CI](https://github.com/bhouston/git-dedup/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/bhouston/git-dedup/actions/workflows/ci.yml)
6
+ [![Coverage](https://codecov.io/gh/bhouston/git-dedup/branch/main/graph/badge.svg)](https://codecov.io/gh/bhouston/git-dedup)
6
7
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/bhouston/git-dedup/blob/main/LICENSE)
7
- [![Documentation](https://img.shields.io/badge/docs-git-dedup-blue)](https://git-dedup.ben3d.ca/)
8
+ [![Documentation](https://img.shields.io/badge/docs-git--dedup-blue)](https://git-dedup.ben3d.ca/)
8
9
  [![Discord](https://img.shields.io/badge/Discord-Join-5865F2?logo=discord&logoColor=white)](https://discord.gg/5J5Ur3F6Z2)
9
10
 
10
- _The TypeScript storage engine behind [git-dedup](https://www.npmjs.com/package/git-dedup)._
11
+ **Faster checkouts, a fraction of the disk space.** _The TypeScript storage engine behind [git-dedup](https://www.npmjs.com/package/git-dedup)._
11
12
 
12
- Build Node.js tools that share one Git object pool across checkouts. The core owns cloning, submodule and worktree integration, repository consolidation, and store maintenance. It invokes native Git; the CLI handles command parsing and presentation.
13
+ Build agent runners, editors, and other Node.js tools that create many checkouts without storing the same Git history many times. Clones, forks, and worktree submodules share one local object pool and borrow from it through Git alternates. The pool holds objects from different remotes, including forks and unrelated repositories.
13
14
 
14
- Optimized for short-lived repositories in agentic workflows. **Automatically** reuse Git objects across repeated checkouts and worktrees with submodules. The pool holds objects from different remotes, including forks and unrelated repositories. Checkouts borrow from it through Git alternates.
15
+ The core owns cloning, submodule and worktree integration, repository consolidation, and store maintenance. It invokes native Git; the CLI handles command parsing and presentation.
15
16
 
16
- In one typical local setup spanning 117 checkouts (94 distinct Git object databases, with linked worktrees counted once), git-dedup uses 11.1 GB for Git objects versus an estimated 35.5 GB without sharing, saving about 24.4 GB (69%).
17
+ In one typical local setup spanning 117 checkouts (94 distinct Git object databases, with linked worktrees counted once), git-dedup uses 11.1 GB for Git objects versus 35.5 GB without sharing, saving about 24.4 GB (70%). Checkout is also 6x faster for large repos, dropping from over 1 minute to 10 seconds.
17
18
 
18
19
  **[Documentation](https://git-dedup.ben3d.ca/) · [Source](https://github.com/bhouston/git-dedup) · [CLI package](https://www.npmjs.com/package/git-dedup)**
19
20
 
@@ -31,8 +32,12 @@ npm install git-dedup-core
31
32
  import { createGitDedup } from 'git-dedup-core';
32
33
 
33
34
  const dedup = createGitDedup({ cwd: process.cwd() });
34
- const exitCode = await dedup.run(['clone', 'https://github.com/bhouston/git-dedup.git', 'git-dedup-checkout']);
35
- process.exitCode = exitCode;
35
+
36
+ // check out a new repo automatically using the dedup store
37
+ await dedup.run(['clone', 'https://github.com/you/project.git']);
38
+
39
+ // dedup an existing repo into the store
40
+ await dedup.add('./my-existing-repo');
36
41
  ```
37
42
 
38
43
  `run()` accepts Git arguments and returns an exit code. It optimizes supported remote clones, `submodule update --init`, and `worktree add` with submodules. Recursive updates handle nested submodules. `submodule add` adopts the module after Git creates it. Other commands and unsupported clone forms, including local paths, shallow or partial clones, and SHA-256 repositories, pass through to Git.
@@ -50,16 +55,17 @@ process.exitCode = exitCode;
50
55
 
51
56
  The returned methods are asynchronous:
52
57
 
53
- | Method | Result and behavior |
54
- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
55
- | `run(args)` | Git exit code; optimizes supported operations |
56
- | `cache(path?)` | `{ cached, skipped, failed, repositories }`; adopts a repository and discoverable submodules, including local commits. Each repository reports its path, status, and any reason or full error detail. |
57
- | `storePath()` | Resolved store path |
58
- | `storeInfo()` | `{ path, sizeBytes, remoteCount }` |
59
- | `fetch()` | `{ fetched }`; fetches registered remotes into the pool |
60
- | `gc()` | `{ compacted }`; compacts the pool without pruning objects |
61
- | `doctor()` | `{ checks }`; each check has `name`, `ok`, and `detail` |
62
- | `gitVersion()` | Underlying Git version line, such as `git version 2.50.1` |
58
+ | Method | Result and behavior |
59
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
60
+ | `run(args)` | Git exit code; optimizes supported operations |
61
+ | `add(path?)` | `{ added, skipped, failed, repositories }`; adopts a repository and discoverable submodules, including local commits. Each repository reports its path, status, and any reason or full error detail. |
62
+ | `storePath()` | Resolved store path |
63
+ | `storeInfo()` | `{ path, sizeBytes, remoteCount }` |
64
+ | `fetch()` | `{ fetched }`; fetches registered remotes into the pool |
65
+ | `gc()` | `{ compacted }`; compacts the pool without pruning objects |
66
+ | `doctor()` | `{ checks }`; each check has `name`, `ok`, and `detail` |
67
+ | `gitVersion()` | Underlying Git version line, such as `git version 2.50.1` |
68
+ | `gitPath()` | Path of the underlying Git executable, honoring the `gitPath` option and `git-dedup.gitPath` |
63
69
 
64
70
  ### Consolidate an existing repository
65
71
 
@@ -67,8 +73,8 @@ The returned methods are asynchronous:
67
73
  import { createGitDedup } from 'git-dedup-core';
68
74
 
69
75
  const dedup = createGitDedup({ cwd: process.cwd() });
70
- const { cached, skipped, failed, repositories } = await dedup.cache('./git-dedup-checkout');
71
- console.log({ cached, skipped, failed, repositories });
76
+ const { added, skipped, failed, repositories } = await dedup.add('./git-dedup-checkout');
77
+ console.log({ added, skipped, failed, repositories });
72
78
  console.log(await dedup.storeInfo());
73
79
  ```
74
80
 
@@ -91,12 +97,10 @@ const dedup = createGitDedup({
91
97
  },
92
98
  });
93
99
 
94
- await dedup.cache('./git-dedup-checkout');
100
+ await dedup.add('./git-dedup-checkout');
95
101
  ```
96
102
 
97
- The callback enables metadata scans after optimized clones and checkout adoption. Without it, these scans are skipped. `StorageReport` also includes optional `beforeUniqueBytes` and `afterUniqueBytes` for checkout adoption. The package exports `GitDedupOptions`, `StorageReport`, `StoreInfo`, `CacheResult`, `DoctorCheck`, and `DoctorResult` types.
98
-
99
- Adoption estimates count the reduction in private pack bytes. Counts cover `.pack`, `.idx`, and `.rev` files, excluding loose objects. They measure logical file sizes, not physical disk blocks reclaimed. Clone reports do not estimate savings.
103
+ The callback enables metadata scans after optimized clones and checkout adoption. Without it, these scans are skipped. `StorageReport` also includes optional `beforeUniqueBytes` and `afterUniqueBytes` for checkout adoption. The package exports `GitDedupOptions`, `StorageReport`, `StoreInfo`, `StoreAddResult`, `DoctorCheck`, and `DoctorResult` types. See [storage reports](https://git-dedup.ben3d.ca/docs/how-it-works#storage-reports) for what the estimates measure.
100
104
 
101
105
  ## Configuration
102
106
 
package/dist/index.d.ts CHANGED
@@ -5,11 +5,11 @@ export interface GitDedupOptions {
5
5
  onStorageReport?: (report: StorageReport) => void;
6
6
  }
7
7
  export interface StorageReport {
8
- operation: 'clone' | 'cache';
8
+ operation: 'clone' | 'add';
9
9
  repository: string;
10
10
  poolReused: boolean;
11
11
  estimatedSavedBytes: number;
12
- /** Logical bytes in private pack files before/after cache adoption. Loose objects are excluded. */
12
+ /** Logical bytes in private pack files before/after checkout adoption. Loose objects are excluded. */
13
13
  beforeUniqueBytes?: number;
14
14
  afterUniqueBytes?: number;
15
15
  }
@@ -22,23 +22,55 @@ export interface StoreRemote {
22
22
  key: string;
23
23
  remote: string;
24
24
  }
25
+ export interface PruneResult {
26
+ reclaimedBytes: number;
27
+ }
25
28
  export interface DoctorCheck {
26
29
  name: string;
27
30
  ok: boolean;
28
31
  detail: string;
29
32
  }
30
33
  export interface DoctorResult {
34
+ /** True when no object pool exists yet; the pool check is then omitted. */
35
+ empty: boolean;
31
36
  checks: DoctorCheck[];
32
37
  }
33
- export interface CacheResult {
34
- cached: number;
38
+ export interface StoreAddResult {
39
+ added: number;
40
+ skipped: number;
41
+ failed: number;
42
+ repositories: StoreAddRepositoryResult[];
43
+ }
44
+ export interface StoreAddRepositoryResult {
45
+ path: string;
46
+ status: 'added' | 'skipped' | 'failed';
47
+ reason?: string;
48
+ /** Full underlying error for diagnostic output. */
49
+ detail?: string;
50
+ }
51
+ export interface StoreRemoveResult {
52
+ removed: number;
35
53
  skipped: number;
36
54
  failed: number;
37
- repositories: CacheRepositoryResult[];
55
+ repositories: StoreRemoveRepositoryResult[];
38
56
  }
39
- export interface CacheRepositoryResult {
57
+ export interface StoreRemoveRepositoryResult {
40
58
  path: string;
41
- status: 'cached' | 'skipped' | 'failed';
59
+ status: 'removed' | 'skipped' | 'failed';
60
+ reason?: string;
61
+ /** Full underlying error for diagnostic output. */
62
+ detail?: string;
63
+ /** Bytes in the checkout's own object directory after removal. */
64
+ objectBytes?: number;
65
+ }
66
+ export interface StoreFetchResult {
67
+ fetched: number;
68
+ failed: number;
69
+ remotes: StoreFetchRemoteResult[];
70
+ }
71
+ export interface StoreFetchRemoteResult {
72
+ key: string;
73
+ status: 'fetched' | 'failed';
42
74
  reason?: string;
43
75
  /** Full underlying error for diagnostic output. */
44
76
  detail?: string;
@@ -46,18 +78,20 @@ export interface CacheRepositoryResult {
46
78
  declare function keyForRemote(remote: string): string | undefined;
47
79
  export declare function createGitDedup(options?: GitDedupOptions): {
48
80
  run: (args: string[]) => Promise<number>;
49
- cache: (path?: string) => Promise<CacheResult>;
81
+ add: (path?: string, quiet?: boolean) => Promise<StoreAddResult>;
82
+ remove: (path?: string) => Promise<StoreRemoveResult>;
50
83
  storeInfo: () => Promise<StoreInfo>;
51
84
  listRemotes: () => Promise<StoreRemote[]>;
52
- fetch: () => Promise<{
53
- fetched: number;
54
- }>;
85
+ fetch: () => Promise<StoreFetchResult>;
55
86
  gc: () => Promise<{
56
87
  compacted: boolean;
57
88
  }>;
89
+ prune: () => Promise<PruneResult>;
90
+ forget: (path: string) => Promise<string[]>;
58
91
  doctor: () => Promise<DoctorResult>;
59
92
  storePath: () => Promise<string>;
60
93
  gitVersion: () => Promise<string>;
94
+ gitPath: () => Promise<string>;
61
95
  };
62
96
  export { keyForRemote };
63
97
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CACnD;AACD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mGAAmG;IACnG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AACD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AACD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,qBAAqB,EAAE,CAAC;CACvC;AACD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6BD,iBAAS,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA8BxD;AAiPD,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAoB;gBAskBjC,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAAC;8BAxQjB,OAAO,CAAC,WAAW,CAAC;qBAuI1B,OAAO,CAAC,SAAS,CAAC;uBAUhB,OAAO,CAAC,WAAW,EAAE,CAAC;iBA2B5B,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;cAkB/B,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;kBAS3B,OAAO,CAAC,YAAY,CAAC;qBA/ZlB,OAAO,CAAC,MAAM,CAAC;sBA2fd,OAAO,CAAC,MAAM,CAAC;EAO7C;AAWD,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}