grootx-vcs 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/README.md +356 -0
- package/dist/cli.js +4427 -0
- package/package.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# Groot — A Git-Inspired Version Control System
|
|
2
|
+
|
|
3
|
+
A lightweight, Git-inspired version control system CLI built with TypeScript and Bun. Groot implements core version control mechanics from first principles: content-addressable storage, staging indices, commit graphs, and history traversal.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Groot is a proof-of-concept VCS that demonstrates how distributed version control systems work under the hood. It provides essential Git-like commands while maintaining a minimal, readable codebase suitable for learning or extending.
|
|
8
|
+
|
|
9
|
+
**Key Design Principles:**
|
|
10
|
+
|
|
11
|
+
- **Content-Addressable Storage**: Files are stored by SHA-256 hash of their content, ensuring deduplication and integrity
|
|
12
|
+
- **Staging Workflow**: Changes are staged before commit, allowing selective snapshots
|
|
13
|
+
- **Immutable History**: Commit objects are immutable; history is a directed acyclic graph traversable via linked lists
|
|
14
|
+
- **Efficient Diff Detection**: Myers diff algorithm for identifying line-level changes between commits
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
### Architecture
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌─────────────────────────────────────────────────────┐
|
|
22
|
+
│ CLI Layer │
|
|
23
|
+
│ (init, add, commit, log, etc.) │
|
|
24
|
+
└──────────────────────┬──────────────────────────────┘
|
|
25
|
+
│
|
|
26
|
+
┌──────────────────────▼──────────────────────────────┐
|
|
27
|
+
│ Core Version Control System Engine │
|
|
28
|
+
│ ┌────────────────────────────────────────────────┐ │
|
|
29
|
+
│ │ • Staging Index (JSON-backed) │ │
|
|
30
|
+
│ │ • HEAD pointer management │ │
|
|
31
|
+
│ │ • Commit graph construction │ │
|
|
32
|
+
│ └────────────────────────────────────────────────┘ │
|
|
33
|
+
└──────────────────────┬──────────────────────────────┘
|
|
34
|
+
│
|
|
35
|
+
┌──────────────────────▼──────────────────────────────┐
|
|
36
|
+
│ Object Store (`.groot/`) │
|
|
37
|
+
│ ┌────────────────────────────────────────────────┐ │
|
|
38
|
+
│ │ objects/ (SHA-256 hashed file blobs) │ │
|
|
39
|
+
│ │ commits/ (Commit metadata JSON) │ │
|
|
40
|
+
│ │ HEAD.json (Current commit pointer) │ │
|
|
41
|
+
│ │ index.json (Staging area state) │ │
|
|
42
|
+
│ └────────────────────────────────────────────────┘ │
|
|
43
|
+
└─────────────────────────────────────────────────────┘
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Data Model
|
|
47
|
+
|
|
48
|
+
**Commit Object** (`commits/{id}.json`)
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"commitId": "40ef1b3d...",
|
|
53
|
+
"commitMessage": "Initial commit",
|
|
54
|
+
"timeStamp": "2026-06-13T14:32:57.815Z",
|
|
55
|
+
"snapshot": {
|
|
56
|
+
"/path/to/file.ts": "sha256_hash_of_content"
|
|
57
|
+
},
|
|
58
|
+
"parent": "previous_commit_id or null"
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Staging Index** (`.groot/index.json`)
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"/path/to/file.ts": "sha256_hash_of_staged_content"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**File Storage** (`objects/{sha256_hash}`)
|
|
71
|
+
|
|
72
|
+
- Raw file content stored by SHA-256 hash
|
|
73
|
+
- Deduplication: identical files share one object
|
|
74
|
+
- No metadata overhead; hash serves as integrity check
|
|
75
|
+
|
|
76
|
+
### Algorithm Highlights
|
|
77
|
+
|
|
78
|
+
**Myers Diff Algorithm**
|
|
79
|
+
|
|
80
|
+
- Implemented for efficient line-level diff detection
|
|
81
|
+
- Tracks edit distance and generates minimal edit scripts
|
|
82
|
+
- Used in `diff` command to show changes between working directory and HEAD
|
|
83
|
+
|
|
84
|
+
**File System Traversal**
|
|
85
|
+
|
|
86
|
+
- Recursive directory traversal with `.grootignore` support
|
|
87
|
+
- Pattern-based file exclusion (similar to `.gitignore`)
|
|
88
|
+
- Efficient staging of large file trees
|
|
89
|
+
|
|
90
|
+
**Commit Graph Traversal**
|
|
91
|
+
|
|
92
|
+
- Linked-list graph structure via parent pointers
|
|
93
|
+
- Linear history traversal for `log` command
|
|
94
|
+
- O(n) complexity for history retrieval
|
|
95
|
+
|
|
96
|
+
## Commands
|
|
97
|
+
|
|
98
|
+
### `groot init`
|
|
99
|
+
|
|
100
|
+
Initialize a new Groot repository in the current directory.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
$ groot init
|
|
104
|
+
Initializing an empty groot repository...
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Creates `.groot/` with the object store, commit history, and index structure.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### `groot add <file>`
|
|
112
|
+
|
|
113
|
+
Stage a file for commit. The file is hashed via SHA-256 and stored in the object store.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
$ groot add src/utils.ts
|
|
117
|
+
Staging area updated successfully.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Updates `.groot/index.json` with the file's SHA-256 hash.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### `groot commit -m "<message>"`
|
|
125
|
+
|
|
126
|
+
Create a commit from staged files. Records a snapshot of the staging index and links to the parent commit.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
$ groot commit -m "Add user authentication module"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Creates a new commit object in `.groot/commits/` with:
|
|
133
|
+
|
|
134
|
+
- Unique commit ID (SHA-256 of metadata)
|
|
135
|
+
- Message and timestamp
|
|
136
|
+
- Snapshot of staged files
|
|
137
|
+
- Parent commit reference
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### `groot log [--oneline]`
|
|
142
|
+
|
|
143
|
+
Display commit history in chronological order.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
$ groot log
|
|
147
|
+
commit 40ef1b3d9d9842694e8e78174b94a50e2261a03e76af36dd5cf987cd43cc33a
|
|
148
|
+
Author: groot
|
|
149
|
+
Date: 2026-06-13T14:32:57.815Z
|
|
150
|
+
Initial commit
|
|
151
|
+
|
|
152
|
+
$ groot log --oneline
|
|
153
|
+
40ef1b3d(Head->) Initial commit
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Traverses the commit graph via parent pointers from HEAD.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### `groot status`
|
|
161
|
+
|
|
162
|
+
Show the working tree status: staged changes and untracked files.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
$ groot status
|
|
166
|
+
Changes waiting to be committed:
|
|
167
|
+
new file: src/auth.ts
|
|
168
|
+
modified: src/utils.ts
|
|
169
|
+
|
|
170
|
+
Untracked files:
|
|
171
|
+
src/test.ts
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Compares the working directory against the staging index and HEAD commit.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### `groot diff <file>`
|
|
179
|
+
|
|
180
|
+
Show differences between the working file and the HEAD commit.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
$ groot diff src/utils.ts
|
|
184
|
+
{ line: "const x = 1;", moveType: "unchanged" }
|
|
185
|
+
{ line: "const y = 2;", moveType: "add" }
|
|
186
|
+
{ line: "const z = 3;", moveType: "delete" }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Uses Myers diff algorithm to generate a minimal edit script. Output shows:
|
|
190
|
+
|
|
191
|
+
- `unchanged`: Lines present in both versions
|
|
192
|
+
- `add`: New lines in working directory
|
|
193
|
+
- `delete`: Lines removed from working directory
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### `groot restore --staged <file>`
|
|
198
|
+
|
|
199
|
+
Unstage a file, removing it from the staging index.
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
$ groot restore --staged src/auth.ts
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
### `groot help`
|
|
208
|
+
|
|
209
|
+
Display all available commands and usage.
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
$ groot help
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Installation
|
|
216
|
+
|
|
217
|
+
### Prerequisites
|
|
218
|
+
|
|
219
|
+
- **Bun** (v1.3.14+): Fast JavaScript runtime
|
|
220
|
+
- **Node.js** (v18+): For TypeScript/crypto support
|
|
221
|
+
- **TypeScript** (v5.9+): Type safety
|
|
222
|
+
|
|
223
|
+
### Setup
|
|
224
|
+
|
|
225
|
+
1. **Clone or download the repository**
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
git clone <repo-url>
|
|
229
|
+
cd groot
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
2. **Install dependencies**
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
bun install
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
3. **Run locally**
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Start the CLI
|
|
242
|
+
bun run src/cli.ts init
|
|
243
|
+
bun run src/cli.ts add <file>
|
|
244
|
+
bun run src/cli.ts commit -m "Your message"
|
|
245
|
+
|
|
246
|
+
# Watch mode for development
|
|
247
|
+
bun run --watch src/cli.ts
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
4. **(Optional) Link as global command**
|
|
251
|
+
```bash
|
|
252
|
+
bun link --global
|
|
253
|
+
groot init
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Project Structure
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
groot/
|
|
260
|
+
├── src/
|
|
261
|
+
│ ├── cli.ts # Entry point, command routing
|
|
262
|
+
│ ├── utils.ts # Core VCS logic, storage APIs
|
|
263
|
+
│ └── commands/
|
|
264
|
+
│ ├── init.ts # Repository initialization
|
|
265
|
+
│ ├── add.ts # Stage files
|
|
266
|
+
│ ├── commit.ts # Create commits
|
|
267
|
+
│ ├── log.ts # Display commit history
|
|
268
|
+
│ ├── status.ts # Show working tree status
|
|
269
|
+
│ ├── restore.ts # Unstage files
|
|
270
|
+
│ ├── diff.ts # Myers diff algorithm + output
|
|
271
|
+
│ └── help.ts # Help message
|
|
272
|
+
├── .groot/ # Repository storage (created at init)
|
|
273
|
+
│ ├── objects/ # SHA-256 hashed file blobs
|
|
274
|
+
│ ├── commits/ # Commit metadata (JSON)
|
|
275
|
+
│ ├── HEAD.json # Current commit pointer
|
|
276
|
+
│ └── index.json # Staging area snapshot
|
|
277
|
+
├── .grootignore # File exclusion patterns
|
|
278
|
+
├── package.json # Dependencies (Bun, TypeScript)
|
|
279
|
+
├── tsconfig.json # TypeScript configuration
|
|
280
|
+
└── README.md # This file
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Development
|
|
284
|
+
|
|
285
|
+
### Running in Watch Mode
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
bun run --watch src/cli.ts <command>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Type Checking
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npx tsc --noEmit
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Key Files
|
|
298
|
+
|
|
299
|
+
| File | Purpose |
|
|
300
|
+
| ---------------------- | ---------------------------------------------------- |
|
|
301
|
+
| `src/utils.ts` | Core VCS engine: hashing, object store, commit graph |
|
|
302
|
+
| `src/commands/diff.ts` | Myers diff algorithm implementation |
|
|
303
|
+
| `src/cli.ts` | Command-line interface and routing |
|
|
304
|
+
|
|
305
|
+
### Extending Groot
|
|
306
|
+
|
|
307
|
+
**Add a new command:**
|
|
308
|
+
|
|
309
|
+
1. Create `src/commands/newcommand.ts`
|
|
310
|
+
2. Export a function matching the command name
|
|
311
|
+
3. Import and route in `src/cli.ts`
|
|
312
|
+
|
|
313
|
+
**Example:**
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// src/commands/branch.ts
|
|
317
|
+
export function branch(branchName: string) {
|
|
318
|
+
// Your implementation
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/cli.ts
|
|
322
|
+
import { branch } from "./commands/branch.ts";
|
|
323
|
+
|
|
324
|
+
case "branch":
|
|
325
|
+
branch(args[1]);
|
|
326
|
+
break;
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Technical Notes
|
|
330
|
+
|
|
331
|
+
- **Hashing**: SHA-256 via Node.js `crypto` module ensures content integrity
|
|
332
|
+
- **Storage**: All metadata stored as JSON for simplicity; production systems would use binary formats
|
|
333
|
+
- **Performance**: Object store uses direct file I/O; large repositories may need indexing
|
|
334
|
+
- **Concurrency**: No locking mechanism; assumes single-user access
|
|
335
|
+
|
|
336
|
+
## Limitations
|
|
337
|
+
|
|
338
|
+
- Single-branch workflow (no branch support yet)
|
|
339
|
+
- Linear history only (no merge/rebase)
|
|
340
|
+
- No remote operations
|
|
341
|
+
- File permissions not tracked
|
|
342
|
+
- Binary files not optimized
|
|
343
|
+
|
|
344
|
+
## Future Enhancements
|
|
345
|
+
|
|
346
|
+
- [ ] Branching and merging
|
|
347
|
+
- [ ] Rebase operations
|
|
348
|
+
- [ ] Remote repository support (push/pull)
|
|
349
|
+
- [ ] Garbage collection for unused objects
|
|
350
|
+
- [ ] Tag support
|
|
351
|
+
- [ ] Stash functionality
|
|
352
|
+
- [ ] Interactive rebase
|
|
353
|
+
|
|
354
|
+
## Contributing
|
|
355
|
+
|
|
356
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|