gent-cli 2.1.0 → 5.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 +215 -65
- package/package.json +1 -1
- package/src/commands/add.js +102 -23
- package/src/commands/clone.js +137 -86
- package/src/commands/commit.js +89 -81
- package/src/commands/diff.js +257 -0
- package/src/commands/init.js +5 -36
- package/src/commands/log.js +57 -13
- package/src/commands/merge.js +245 -0
- package/src/commands/pull.js +176 -86
- package/src/commands/push.js +172 -79
- package/src/commands/remote.js +97 -113
- package/src/commands/reset.js +149 -0
- package/src/commands/rm.js +85 -0
- package/src/commands/show.js +167 -0
- package/src/commands/stash.js +255 -0
- package/src/commands/status.js +80 -46
- package/src/commands/tag.js +146 -0
- package/src/index.js +108 -57
- package/src/utils/constants.js +10 -26
- package/src/utils/diff-engine.js +236 -0
- package/src/utils/fileSystem.js +8 -60
- package/src/utils/hash-engine.js +337 -0
- package/src/utils/merge-engine.js +379 -0
- package/src/utils/object-store.js +54 -0
- package/src/commands/create.js +0 -121
- package/src/commands/list.js +0 -67
- package/src/services/repo-service.js +0 -291
- package/src/utils/cloud-sync.js +0 -323
- package/src/utils/diff.js +0 -121
package/README.md
CHANGED
|
@@ -1,17 +1,47 @@
|
|
|
1
1
|
# Gent CLI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Gent is a lightweight version control system that feels exactly like Git but handles user identity automatically through the cloud. No more configuring `user.name` and `user.email` for every repository!
|
|
3
|
+

|
|
4
|
+

|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
> A modern, Git-like version control CLI with built-in cloud authentication and global user identity management.
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
8
|
+
Gent is a lightweight version control system that feels like Git but handles user identity automatically through the cloud. No more configuring `user.name` and `user.email` for every repository.
|
|
9
|
+
|
|
10
|
+
## Highlights
|
|
11
|
+
|
|
12
|
+
- **Cloud Authentication** — Login once, work everywhere. JWT-based auth with automatic token refresh.
|
|
13
|
+
- **Git-like Experience** — Familiar commands: `init`, `add`, `commit`, `status`, `log`, `branch`, `checkout`, `merge`, `push`, `pull`, `clone`, and more.
|
|
14
|
+
- **Zero Configuration** — `gent init` auto-detects your authenticated user profile.
|
|
15
|
+
- **Global Identity** — Commits are automatically authored with your cloud profile.
|
|
16
|
+
- **Content-Addressable Storage** — SHA-256 object store with zlib compression and deduplication.
|
|
17
|
+
- **Smart Diff & Merge** — Line-level LCS diff, three-way merge with conflict detection.
|
|
18
|
+
- **Remote Sync** — Push, pull, and clone repositories from the cloud backend.
|
|
19
|
+
- **Secure** — Tokens stored with AES encryption in `~/.gent/auth.json`.
|
|
20
|
+
|
|
21
|
+
## Table of Contents
|
|
22
|
+
|
|
23
|
+
- [Requirements](#requirements)
|
|
24
|
+
- [Installation](#installation)
|
|
25
|
+
- [Quickstart](#quickstart)
|
|
26
|
+
- [Authentication](#authentication)
|
|
27
|
+
- [Commands](#commands)
|
|
28
|
+
- [Repository Setup](#repository-setup)
|
|
29
|
+
- [Staging & Working Tree](#staging--working-tree)
|
|
30
|
+
- [History](#history)
|
|
31
|
+
- [Branching & Merging](#branching--merging)
|
|
32
|
+
- [Remote & Sync](#remote--sync)
|
|
33
|
+
- [Authentication Commands](#authentication-commands)
|
|
34
|
+
- [Usage Examples](#usage-examples)
|
|
35
|
+
- [Repository Structure](#repository-structure)
|
|
36
|
+
- [Configuration](#configuration)
|
|
37
|
+
- [Docs](#docs)
|
|
38
|
+
- [Troubleshooting](#troubleshooting)
|
|
39
|
+
- [Contributing](#contributing)
|
|
40
|
+
- [License](#license)
|
|
41
|
+
|
|
42
|
+
## Requirements
|
|
43
|
+
|
|
44
|
+
- Node.js >= 14
|
|
15
45
|
|
|
16
46
|
## Installation
|
|
17
47
|
|
|
@@ -19,11 +49,33 @@ Gent is a lightweight version control system that feels exactly like Git but han
|
|
|
19
49
|
npm install -g gent-cli
|
|
20
50
|
```
|
|
21
51
|
|
|
52
|
+
Run locally without installing:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd apps/Cli
|
|
56
|
+
npm install
|
|
57
|
+
node src/index.js --help
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Quickstart
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 1) Authenticate
|
|
64
|
+
gent login
|
|
65
|
+
|
|
66
|
+
# 2) Initialize a repo
|
|
67
|
+
gent init
|
|
68
|
+
|
|
69
|
+
# 3) Make a first commit
|
|
70
|
+
gent add .
|
|
71
|
+
gent commit -m "Initial commit"
|
|
72
|
+
```
|
|
73
|
+
|
|
22
74
|
## Authentication
|
|
23
75
|
|
|
24
|
-
Gent uses a global authentication system. You only need to
|
|
76
|
+
Gent uses a global authentication system. You only need to log in once.
|
|
25
77
|
|
|
26
|
-
###
|
|
78
|
+
### Register a New Account
|
|
27
79
|
|
|
28
80
|
```bash
|
|
29
81
|
gent register
|
|
@@ -33,11 +85,11 @@ gent register
|
|
|
33
85
|
|
|
34
86
|
```bash
|
|
35
87
|
gent login
|
|
36
|
-
# or
|
|
88
|
+
# or with flags
|
|
37
89
|
gent login -e user@example.com -p YourPassword
|
|
38
90
|
```
|
|
39
91
|
|
|
40
|
-
### Check
|
|
92
|
+
### Check Current User
|
|
41
93
|
|
|
42
94
|
```bash
|
|
43
95
|
gent whoami
|
|
@@ -49,103 +101,201 @@ gent whoami
|
|
|
49
101
|
gent logout
|
|
50
102
|
```
|
|
51
103
|
|
|
52
|
-
##
|
|
104
|
+
## Commands
|
|
53
105
|
|
|
54
|
-
###
|
|
106
|
+
### Repository Setup
|
|
107
|
+
|
|
108
|
+
| Command | Description |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `gent init [-y]` | Initialize a new Gent repository in the current directory. Use `-y` to skip prompts. |
|
|
111
|
+
| `gent clone <url> [directory]` | Clone a remote repository from the cloud backend. |
|
|
112
|
+
|
|
113
|
+
### Staging & Working Tree
|
|
114
|
+
|
|
115
|
+
| Command | Description |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `gent status [-s]` | Show the working tree status. Use `-s` for short format. |
|
|
118
|
+
| `gent add <files...> [-A]` | Add files to the staging area. Use `-A` or `--all` to add all files. |
|
|
119
|
+
| `gent rm <files...> [--cached]` | Remove files from the working tree and staging area. Use `--cached` to keep the file on disk. |
|
|
120
|
+
| `gent reset [files...] [--hard <hash> \| --soft <hash>]` | Unstage files or reset HEAD to a specific commit. |
|
|
121
|
+
| `gent diff [files...] [--staged] [--stat]` | Show changes between working tree, staging area, and commits. |
|
|
122
|
+
|
|
123
|
+
### History
|
|
124
|
+
|
|
125
|
+
| Command | Description |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `gent commit [-m <message>] [-a]` | Record changes to the repository. Use `-a` to auto-stage all modified files. |
|
|
128
|
+
| `gent log [-n <count>] [--oneline] [--stat]` | Show commit history. Default limit is 10 commits. |
|
|
129
|
+
| `gent show [ref] [--no-patch]` | Show commit details and diff. |
|
|
130
|
+
| `gent tag [name] [-m <message>] [-d <name>]` | Create, list, or delete tags. |
|
|
131
|
+
|
|
132
|
+
### Branching & Merging
|
|
133
|
+
|
|
134
|
+
| Command | Description |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `gent branch [name] [-d <name>] [-a]` | List, create, or delete branches. |
|
|
137
|
+
| `gent checkout <branch> [-b]` | Switch branches. Use `-b` to create and switch to a new branch. |
|
|
138
|
+
| `gent merge <branch> [-m <message>]` | Merge a branch into the current branch using a three-way smart merge. |
|
|
139
|
+
| `gent stash [pop \| list \| drop \| apply] [-m <message>] [-i <index>]` | Stash working tree changes. |
|
|
140
|
+
|
|
141
|
+
### Remote & Sync
|
|
142
|
+
|
|
143
|
+
| Command | Description |
|
|
144
|
+
|---|---|
|
|
145
|
+
| `gent remote [add \| remove \| set-url] [args...] [-v]` | Manage remote connections. |
|
|
146
|
+
| `gent push [remote] [branch] [-f]` | Push local commits to the remote. Use `-f` to force push. |
|
|
147
|
+
| `gent pull [remote] [branch]` | Pull and merge remote commits into the current branch. |
|
|
148
|
+
|
|
149
|
+
### Authentication Commands
|
|
150
|
+
|
|
151
|
+
| Command | Description |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `gent register` | Create a new user account interactively. |
|
|
154
|
+
| `gent login [-e <email>] [-p <password>]` | Log in to your account. |
|
|
155
|
+
| `gent logout` | Log out and clear stored tokens. |
|
|
156
|
+
| `gent whoami` | Display the currently logged-in user. |
|
|
157
|
+
|
|
158
|
+
## Usage Examples
|
|
159
|
+
|
|
160
|
+
### Initialize a Repository
|
|
55
161
|
|
|
56
162
|
```bash
|
|
57
163
|
gent init
|
|
58
164
|
# Output: Initialized empty Gent repository in /path/to/project
|
|
59
165
|
```
|
|
60
166
|
|
|
61
|
-
###
|
|
167
|
+
### Stage and Commit
|
|
62
168
|
|
|
63
169
|
```bash
|
|
64
|
-
gent
|
|
170
|
+
gent add .
|
|
171
|
+
gent commit -m "Initial commit"
|
|
65
172
|
```
|
|
66
173
|
|
|
67
|
-
###
|
|
174
|
+
### Work with Branches
|
|
68
175
|
|
|
69
176
|
```bash
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
177
|
+
# Create and switch to a new branch
|
|
178
|
+
gent checkout -b feature-login
|
|
179
|
+
|
|
180
|
+
# List branches
|
|
181
|
+
gent branch
|
|
182
|
+
|
|
183
|
+
# Switch back to main
|
|
184
|
+
gent checkout main
|
|
185
|
+
|
|
186
|
+
# Delete a branch
|
|
187
|
+
gent branch -d feature-login
|
|
73
188
|
```
|
|
74
189
|
|
|
75
|
-
###
|
|
190
|
+
### View History
|
|
76
191
|
|
|
77
192
|
```bash
|
|
78
|
-
gent
|
|
79
|
-
|
|
80
|
-
|
|
193
|
+
gent log
|
|
194
|
+
gent log --oneline
|
|
195
|
+
gent log -n 5
|
|
81
196
|
```
|
|
82
197
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
### 1. Create a Cloud Repository
|
|
198
|
+
### Remote Workflow
|
|
86
199
|
|
|
87
200
|
```bash
|
|
88
|
-
#
|
|
89
|
-
gent
|
|
201
|
+
# Add a remote
|
|
202
|
+
gent remote add origin https://gent-api.onrender.com/api/repos/123/
|
|
203
|
+
|
|
204
|
+
# Push to remote
|
|
205
|
+
gent push origin main
|
|
90
206
|
|
|
91
|
-
#
|
|
92
|
-
gent
|
|
207
|
+
# Pull from remote
|
|
208
|
+
gent pull origin main
|
|
209
|
+
|
|
210
|
+
# Clone a repository
|
|
211
|
+
gent clone https://gent-api.onrender.com/api/repos/123/ my-project
|
|
93
212
|
```
|
|
94
213
|
|
|
95
|
-
|
|
214
|
+
## Repository Structure
|
|
96
215
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
gent
|
|
216
|
+
Gent creates a `.gent` directory in your project root:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
.gent/
|
|
220
|
+
├── config.json # Project configuration, remotes, user info
|
|
221
|
+
├── commits.json # Full commit history, branches, and tags
|
|
222
|
+
├── staging.json # Current staging area
|
|
223
|
+
├── stash.json # Stashed changes (created on first stash)
|
|
224
|
+
├── HEAD # Current branch reference
|
|
225
|
+
├── objects/ # Content-addressable blob and tree store
|
|
226
|
+
│ ├── ab/ # First 2 characters of SHA-256 hash
|
|
227
|
+
│ │ └── cdef... # zlib-compressed object
|
|
228
|
+
│ └── ...
|
|
229
|
+
└── refs/
|
|
230
|
+
├── heads/ # Branch references (reserved for future use)
|
|
231
|
+
└── tags/ # Tag references (reserved for future use)
|
|
101
232
|
```
|
|
102
233
|
|
|
103
|
-
|
|
234
|
+
Your authentication tokens are stored globally in `~/.gent/auth.json`.
|
|
235
|
+
|
|
236
|
+
## Configuration
|
|
237
|
+
|
|
238
|
+
### Ignore Files
|
|
239
|
+
|
|
240
|
+
Create a `.gentignore` file in your repository root to exclude files from tracking:
|
|
104
241
|
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
|
|
242
|
+
```
|
|
243
|
+
node_modules/
|
|
244
|
+
dist/
|
|
245
|
+
.env
|
|
246
|
+
*.log
|
|
108
247
|
```
|
|
109
248
|
|
|
110
|
-
|
|
249
|
+
Default ignored patterns include: `.gent`, `node_modules`, `.git`, `.DS_Store`, `.env`, `dist`, `build`, `coverage`, `.vscode`, `.idea`, and `*.log`.
|
|
111
250
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
251
|
+
### Remotes
|
|
252
|
+
|
|
253
|
+
Remotes are stored in `.gent/config.json`:
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"remotes": {
|
|
258
|
+
"origin": {
|
|
259
|
+
"url": "https://gent-api.onrender.com/api/repos/123/"
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
116
263
|
```
|
|
117
264
|
|
|
118
|
-
|
|
265
|
+
## Troubleshooting
|
|
119
266
|
|
|
267
|
+
**Command not found?**
|
|
268
|
+
|
|
269
|
+
Make sure the CLI is linked globally:
|
|
120
270
|
```bash
|
|
121
|
-
|
|
271
|
+
npm link
|
|
122
272
|
```
|
|
123
273
|
|
|
124
|
-
|
|
125
|
-
|
|
274
|
+
Or run it directly:
|
|
126
275
|
```bash
|
|
127
|
-
|
|
128
|
-
gent remote -v
|
|
276
|
+
node src/index.js <command>
|
|
129
277
|
```
|
|
130
278
|
|
|
131
|
-
|
|
279
|
+
**Not a Gent repository?**
|
|
132
280
|
|
|
133
|
-
|
|
281
|
+
Run `gent init` in your project directory first.
|
|
134
282
|
|
|
135
|
-
|
|
136
|
-
.gent/
|
|
137
|
-
├── config.json # Project configuration
|
|
138
|
-
├── objects/ # Stored file contents
|
|
139
|
-
├── refs/ # Branch pointers
|
|
140
|
-
├── remote.json # Remote configuration
|
|
141
|
-
└── HEAD # Current branch reference
|
|
142
|
-
```
|
|
283
|
+
**No changes to commit?**
|
|
143
284
|
|
|
144
|
-
|
|
285
|
+
Stage files with `gent add <files>` before committing.
|
|
286
|
+
|
|
287
|
+
**Authentication errors?**
|
|
288
|
+
|
|
289
|
+
Run `gent login` to refresh your session. Tokens expire automatically and should refresh; if not, log in again.
|
|
290
|
+
|
|
291
|
+
## Docs
|
|
292
|
+
|
|
293
|
+
- [QUICKSTART.md](QUICKSTART.md)
|
|
294
|
+
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
|
|
145
295
|
|
|
146
296
|
## Contributing
|
|
147
297
|
|
|
148
|
-
|
|
298
|
+
Contributions are welcome! Please fork the repository and submit a Pull Request.
|
|
149
299
|
|
|
150
300
|
## License
|
|
151
301
|
|
package/package.json
CHANGED
package/src/commands/add.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Add Command - Add file contents to the staging area
|
|
3
|
-
* Stages files
|
|
3
|
+
* Stages files with content snapshots (blobs) and diff stats
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
const fs = require('fs').promises;
|
|
6
7
|
const path = require('path');
|
|
7
8
|
const chalk = require('chalk');
|
|
8
9
|
const ora = require('ora');
|
|
9
10
|
const { getGentPath, readJSON, writeJSON, pathExists, getAllFiles, getIgnorePatterns } = require('../utils/fileSystem');
|
|
10
|
-
const { STAGING_FILE } = require('../utils/constants');
|
|
11
|
+
const { STAGING_FILE, COMMITS_FILE } = require('../utils/constants');
|
|
12
|
+
const { storeBlob, hashBlob, isBinaryBuffer, snapshotFile } = require('../utils/hash-engine');
|
|
13
|
+
const { diffText, formatUnifiedDiff } = require('../utils/diff-engine');
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* Add files to staging area
|
|
@@ -24,7 +27,19 @@ async function add(files, options) {
|
|
|
24
27
|
|
|
25
28
|
// Read current staging area
|
|
26
29
|
const staging = await readJSON(stagingPath);
|
|
27
|
-
const
|
|
30
|
+
const stagedEntries = staging.entries || [];
|
|
31
|
+
const stagedMap = new Map(stagedEntries.map(e => [e.path, e]));
|
|
32
|
+
|
|
33
|
+
// Get last commit tree for diff comparison
|
|
34
|
+
const repository = await readJSON(path.join(gentPath, COMMITS_FILE));
|
|
35
|
+
const lastCommitHash = repository.branches[repository.currentBranch] || null;
|
|
36
|
+
const lastCommit = lastCommitHash
|
|
37
|
+
? (repository.commits || []).find(c => c.hash === lastCommitHash)
|
|
38
|
+
: null;
|
|
39
|
+
const lastTreeMap = new Map(
|
|
40
|
+
(lastCommit && lastCommit.tree ? lastCommit.tree : (lastCommit ? lastCommit.files : []))
|
|
41
|
+
.map(f => [f.path || f.name, f.hash])
|
|
42
|
+
);
|
|
28
43
|
|
|
29
44
|
let filesToAdd = [];
|
|
30
45
|
|
|
@@ -35,49 +50,113 @@ async function add(files, options) {
|
|
|
35
50
|
const allFiles = await getAllFiles(cwd, ignorePatterns);
|
|
36
51
|
filesToAdd = allFiles.map(f => path.relative(cwd, f));
|
|
37
52
|
} else {
|
|
38
|
-
// Add specified files
|
|
39
53
|
for (const file of files) {
|
|
40
54
|
const filePath = path.resolve(cwd, file);
|
|
41
|
-
|
|
42
55
|
if (!await pathExists(filePath)) {
|
|
43
56
|
spinner.warn(chalk.yellow(`Warning: File not found: ${file}`));
|
|
44
57
|
continue;
|
|
45
58
|
}
|
|
46
|
-
|
|
47
|
-
const relativePath = path.relative(cwd, filePath);
|
|
48
|
-
filesToAdd.push(relativePath);
|
|
59
|
+
filesToAdd.push(path.relative(cwd, filePath));
|
|
49
60
|
}
|
|
50
61
|
}
|
|
51
62
|
|
|
52
|
-
//
|
|
63
|
+
// Snapshot each file → store blob, compute diff
|
|
53
64
|
let addedCount = 0;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
let totalInsertions = 0;
|
|
66
|
+
let totalDeletions = 0;
|
|
67
|
+
const diffSummaries = [];
|
|
68
|
+
|
|
69
|
+
for (const relPath of filesToAdd) {
|
|
70
|
+
const fullPath = path.join(cwd, relPath);
|
|
71
|
+
const content = await fs.readFile(fullPath);
|
|
72
|
+
|
|
73
|
+
// Skip binary files for diff (still store blob)
|
|
74
|
+
const binary = isBinaryBuffer(content);
|
|
75
|
+
const blobHash = await storeBlob(gentPath, content);
|
|
76
|
+
|
|
77
|
+
// Check if changed vs last commit
|
|
78
|
+
const prevHash = lastTreeMap.get(relPath);
|
|
79
|
+
if (prevHash === blobHash && stagedMap.has(relPath)) {
|
|
80
|
+
continue; // unchanged, already staged
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Determine change status
|
|
84
|
+
let status = 'added';
|
|
85
|
+
let stats = { insertions: 0, deletions: 0 };
|
|
86
|
+
|
|
87
|
+
if (prevHash && prevHash !== blobHash && !binary) {
|
|
88
|
+
status = 'modified';
|
|
89
|
+
try {
|
|
90
|
+
const { readBlobAsString } = require('../utils/hash-engine');
|
|
91
|
+
const oldContent = await readBlobAsString(gentPath, prevHash);
|
|
92
|
+
const diff = diffText(oldContent, content.toString('utf-8'));
|
|
93
|
+
stats = { insertions: diff.stats.insertions, deletions: diff.stats.deletions };
|
|
94
|
+
} catch {
|
|
95
|
+
// Old blob may not exist yet (first time adding objects)
|
|
96
|
+
}
|
|
97
|
+
} else if (!prevHash) {
|
|
98
|
+
status = 'added';
|
|
99
|
+
stats.insertions = content.toString('utf-8').split('\n').length;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
totalInsertions += stats.insertions;
|
|
103
|
+
totalDeletions += stats.deletions;
|
|
104
|
+
|
|
105
|
+
// Update staging entry
|
|
106
|
+
stagedMap.set(relPath, {
|
|
107
|
+
path: relPath,
|
|
108
|
+
hash: blobHash,
|
|
109
|
+
status,
|
|
110
|
+
binary,
|
|
111
|
+
stats
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
diffSummaries.push({ path: relPath, status, stats, binary });
|
|
115
|
+
addedCount++;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Detect deleted files (tracked in last commit but gone from disk)
|
|
119
|
+
for (const [trackedPath, trackedHash] of lastTreeMap) {
|
|
120
|
+
const fullPath = path.join(cwd, trackedPath);
|
|
121
|
+
if (!await pathExists(fullPath) && !stagedMap.has(trackedPath)) {
|
|
122
|
+
stagedMap.set(trackedPath, {
|
|
123
|
+
path: trackedPath,
|
|
124
|
+
hash: null,
|
|
125
|
+
status: 'deleted',
|
|
126
|
+
binary: false,
|
|
127
|
+
stats: { insertions: 0, deletions: 0 }
|
|
128
|
+
});
|
|
129
|
+
diffSummaries.push({ path: trackedPath, status: 'deleted', stats: { insertions: 0, deletions: 0 }, binary: false });
|
|
57
130
|
addedCount++;
|
|
58
131
|
}
|
|
59
132
|
}
|
|
60
133
|
|
|
61
|
-
// Save staging area
|
|
62
|
-
staging.
|
|
134
|
+
// Save staging area (new format with entries)
|
|
135
|
+
staging.entries = Array.from(stagedMap.values());
|
|
136
|
+
staging.files = staging.entries.map(e => e.path); // backward compat
|
|
63
137
|
await writeJSON(stagingPath, staging);
|
|
64
138
|
|
|
65
|
-
spinner.succeed(chalk.green(
|
|
139
|
+
spinner.succeed(chalk.green(`Added ${addedCount} file(s) to staging area`));
|
|
66
140
|
|
|
67
|
-
if (
|
|
68
|
-
console.log(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
141
|
+
if (diffSummaries.length > 0) {
|
|
142
|
+
console.log('');
|
|
143
|
+
for (const d of diffSummaries) {
|
|
144
|
+
const statusIcon = d.status === 'added' ? chalk.green('+ new')
|
|
145
|
+
: d.status === 'deleted' ? chalk.red('- del')
|
|
146
|
+
: chalk.yellow('~ mod');
|
|
147
|
+
const statsStr = d.binary ? chalk.gray('(binary)')
|
|
148
|
+
: chalk.green(`+${d.stats.insertions}`) + ' ' + chalk.red(`-${d.stats.deletions}`);
|
|
149
|
+
console.log(` ${statusIcon} ${d.path} ${statsStr}`);
|
|
150
|
+
}
|
|
151
|
+
console.log(chalk.gray(`\n Total: `) + chalk.green(`+${totalInsertions}`) + ' ' + chalk.red(`-${totalDeletions}`));
|
|
152
|
+
console.log(chalk.cyan('\nUse "gent commit" to record your changes'));
|
|
73
153
|
}
|
|
74
154
|
|
|
75
155
|
} catch (error) {
|
|
76
156
|
spinner.fail(chalk.red('Failed to add files'));
|
|
77
|
-
|
|
78
157
|
if (error.code === 'ENOENT' && error.message.includes('.gent')) {
|
|
79
158
|
console.error(chalk.red('\nError: Not a gent repository'));
|
|
80
|
-
console.log(chalk.yellow('
|
|
159
|
+
console.log(chalk.yellow('Run "gent init" to initialize a repository'));
|
|
81
160
|
} else {
|
|
82
161
|
console.error(chalk.red('\nError:'), error.message);
|
|
83
162
|
}
|