gent-cli 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 ADDED
@@ -0,0 +1,316 @@
1
+ # Gent CLI - A Git-like Version Control System
2
+
3
+ šŸš€ **Gent** is a lightweight, Git-inspired version control CLI tool built with Node.js. It provides essential version control features with an intuitive command-line interface.
4
+
5
+ ## Features
6
+
7
+ - **Repository Initialization** - Set up new Gent repositories with custom configuration
8
+ - **File Staging** - Add files to staging area before committing
9
+ - **Commit Management** - Record changes with descriptive messages
10
+ - **Branch Operations** - Create, switch, and manage branches
11
+ - **Status Tracking** - View working tree status and changes
12
+ - **Commit History** - Browse commit logs with detailed information
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ # Navigate to the CLI directory
18
+ cd apps/Cli
19
+
20
+ # Install dependencies
21
+ npm install
22
+
23
+ # Link globally (optional)
24
+ npm link
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Initialize a Repository
30
+
31
+ Create a new Gent repository in the current directory:
32
+
33
+ ```bash
34
+ gent init
35
+ ```
36
+
37
+ With default configuration (skip prompts):
38
+
39
+ ```bash
40
+ gent init -y
41
+ ```
42
+
43
+ ### Check Status
44
+
45
+ View the current state of your working tree:
46
+
47
+ ```bash
48
+ gent status
49
+ ```
50
+
51
+ Short format:
52
+
53
+ ```bash
54
+ gent status -s
55
+ ```
56
+
57
+ ### Stage Files
58
+
59
+ Add files to the staging area:
60
+
61
+ ```bash
62
+ # Add specific files
63
+ gent add file1.js file2.js
64
+
65
+ # Add all files
66
+ gent add --all
67
+ gent add .
68
+ ```
69
+
70
+ ### Commit Changes
71
+
72
+ Record changes to the repository:
73
+
74
+ ```bash
75
+ # With inline message
76
+ gent commit -m "Your commit message"
77
+
78
+ # Interactive (will prompt for message)
79
+ gent commit
80
+ ```
81
+
82
+ Auto-stage all modified files:
83
+
84
+ ```bash
85
+ gent commit -a -m "Commit all changes"
86
+ ```
87
+
88
+ ### View Commit History
89
+
90
+ Display commit logs:
91
+
92
+ ```bash
93
+ # Show last 10 commits (default)
94
+ gent log
95
+
96
+ # Show specific number of commits
97
+ gent log -n 5
98
+
99
+ # Compact oneline format
100
+ gent log --oneline
101
+ ```
102
+
103
+ ### Branch Management
104
+
105
+ List all branches:
106
+
107
+ ```bash
108
+ gent branch
109
+ ```
110
+
111
+ Create a new branch:
112
+
113
+ ```bash
114
+ gent branch feature-name
115
+ ```
116
+
117
+ Delete a branch:
118
+
119
+ ```bash
120
+ gent branch -d branch-name
121
+ ```
122
+
123
+ ### Switch Branches
124
+
125
+ Switch to an existing branch:
126
+
127
+ ```bash
128
+ gent checkout branch-name
129
+ ```
130
+
131
+ Create and switch to a new branch:
132
+
133
+ ```bash
134
+ gent checkout -b new-branch
135
+ ```
136
+
137
+ ## Project Structure
138
+
139
+ ```
140
+ apps/Cli/
141
+ ā”œā”€ā”€ src/
142
+ │ ā”œā”€ā”€ index.js # Main entry point
143
+ │ ā”œā”€ā”€ commands/ # Command implementations
144
+ │ │ ā”œā”€ā”€ init.js # Initialize repository
145
+ │ │ ā”œā”€ā”€ status.js # Show status
146
+ │ │ ā”œā”€ā”€ add.js # Stage files
147
+ │ │ ā”œā”€ā”€ commit.js # Create commits
148
+ │ │ ā”œā”€ā”€ log.js # View history
149
+ │ │ ā”œā”€ā”€ branch.js # Manage branches
150
+ │ │ └── checkout.js # Switch branches
151
+ │ └── utils/ # Utility modules
152
+ │ ā”œā”€ā”€ constants.js # Application constants
153
+ │ ā”œā”€ā”€ fileSystem.js # File operations
154
+ │ └── helpers.js # Helper functions
155
+ ā”œā”€ā”€ package.json # Dependencies and scripts
156
+ └── README.md # Documentation
157
+ ```
158
+
159
+ ## Repository Structure
160
+
161
+ When you initialize a Gent repository, it creates a `.gent` directory:
162
+
163
+ ```
164
+ .gent/
165
+ ā”œā”€ā”€ config.json # Repository configuration
166
+ ā”œā”€ā”€ staging.json # Staged files
167
+ ā”œā”€ā”€ commits.json # Commit history
168
+ ā”œā”€ā”€ HEAD # Current branch reference
169
+ ā”œā”€ā”€ objects/ # File objects (future use)
170
+ └── refs/ # Branch references
171
+ ā”œā”€ā”€ heads/ # Branch pointers
172
+ └── tags/ # Tag references
173
+ ```
174
+
175
+ ## Configuration
176
+
177
+ Gent stores configuration in `.gent/config.json`:
178
+
179
+ ```json
180
+ {
181
+ "user": {
182
+ "name": "Your Name",
183
+ "email": "your.email@example.com"
184
+ },
185
+ "repository": {
186
+ "name": "project-name",
187
+ "description": "Project description",
188
+ "created": "2025-11-06T00:00:00.000Z"
189
+ }
190
+ }
191
+ ```
192
+
193
+ ## Ignore Patterns
194
+
195
+ Create a `.gentignore` file to exclude files from tracking:
196
+
197
+ ```
198
+ # Dependencies
199
+ node_modules/
200
+
201
+ # Build outputs
202
+ dist/
203
+ build/
204
+
205
+ # Environment files
206
+ .env
207
+ .env.local
208
+
209
+ # Logs
210
+ *.log
211
+
212
+ # OS files
213
+ .DS_Store
214
+ ```
215
+
216
+ ## Command Reference
217
+
218
+ | Command | Description | Options |
219
+ |---------|-------------|---------|
220
+ | `gent init` | Initialize repository | `-y, --yes` Skip prompts |
221
+ | `gent status` | Show working tree status | `-s, --short` Short format |
222
+ | `gent add <files>` | Stage files | `-A, --all` Stage all files |
223
+ | `gent commit` | Record changes | `-m <msg>` Message, `-a` Stage all |
224
+ | `gent log` | Show commit history | `-n <num>` Limit, `--oneline` Compact |
225
+ | `gent branch [name]` | Manage branches | `-d <name>` Delete, `-a` List all |
226
+ | `gent checkout <branch>` | Switch branches | `-b` Create new |
227
+ | `gent help [command]` | Show help | |
228
+
229
+ ## Dependencies
230
+
231
+ - **commander** - CLI framework
232
+ - **chalk** - Terminal styling
233
+ - **inquirer** - Interactive prompts
234
+ - **ora** - Elegant terminal spinners
235
+ - **boxen** - Create boxes in terminal
236
+ - **date-fns** - Date formatting utilities
237
+
238
+ ## Development
239
+
240
+ ```bash
241
+ # Run locally
242
+ npm start
243
+
244
+ # Run specific command
245
+ node src/index.js init
246
+ node src/index.js status
247
+ ```
248
+
249
+ ## Examples
250
+
251
+ ### Complete Workflow
252
+
253
+ ```bash
254
+ # Initialize repository
255
+ gent init
256
+
257
+ # Add some files
258
+ echo "console.log('Hello');" > app.js
259
+ gent add app.js
260
+
261
+ # Commit changes
262
+ gent commit -m "Initial commit"
263
+
264
+ # Create a feature branch
265
+ gent branch feature-login
266
+ gent checkout feature-login
267
+
268
+ # Make changes and commit
269
+ echo "// Login logic" >> app.js
270
+ gent add app.js
271
+ gent commit -m "Add login feature"
272
+
273
+ # View history
274
+ gent log
275
+
276
+ # Switch back to main
277
+ gent checkout main
278
+ ```
279
+
280
+ ## Error Handling
281
+
282
+ Gent provides clear error messages:
283
+
284
+ - **Not a gent repository** - Run `gent init` first
285
+ - **No changes to commit** - Stage files with `gent add`
286
+ - **Branch not found** - Check available branches with `gent branch`
287
+
288
+ ## Best Practices
289
+
290
+ 1. **Commit Often** - Make small, focused commits
291
+ 2. **Write Clear Messages** - Describe what and why
292
+ 3. **Use Branches** - Isolate features and experiments
293
+ 4. **Check Status** - Review changes before committing
294
+ 5. **Update .gentignore** - Exclude unnecessary files
295
+
296
+ ## Future Enhancements
297
+
298
+ - [ ] Diff visualization
299
+ - [ ] Remote repository support
300
+ - [ ] Merge functionality
301
+ - [ ] Tag management
302
+ - [ ] Stash implementation
303
+ - [ ] File restoration
304
+ - [ ] Conflict resolution
305
+
306
+ ## License
307
+
308
+ ISC
309
+
310
+ ## Author
311
+
312
+ Built with ā¤ļø using Node.js
313
+
314
+ ---
315
+
316
+ **Note**: Gent is a learning project and educational tool. For production use, consider established version control systems like Git.
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Gent CLI - Command Summary
5
+ * Quick reference for all available commands
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const boxen = require('boxen');
10
+
11
+ const commands = [
12
+ {
13
+ name: 'init',
14
+ description: 'Initialize a new gent repository',
15
+ usage: 'gent init [options]',
16
+ options: ['-y, --yes Skip prompts and use defaults'],
17
+ examples: ['gent init', 'gent init -y']
18
+ },
19
+ {
20
+ name: 'status',
21
+ description: 'Show the working tree status',
22
+ usage: 'gent status [options]',
23
+ options: ['-s, --short Give output in short format'],
24
+ examples: ['gent status', 'gent status -s']
25
+ },
26
+ {
27
+ name: 'add',
28
+ description: 'Add file contents to the staging area',
29
+ usage: 'gent add <files...> [options]',
30
+ options: ['-A, --all Add all files'],
31
+ examples: ['gent add file.js', 'gent add .', 'gent add --all']
32
+ },
33
+ {
34
+ name: 'commit',
35
+ description: 'Record changes to the repository',
36
+ usage: 'gent commit [options]',
37
+ options: [
38
+ '-m, --message <message> Commit message',
39
+ '-a, --all Auto stage modified files'
40
+ ],
41
+ examples: ['gent commit -m "Fix bug"', 'gent commit', 'gent commit -a -m "Update all"']
42
+ },
43
+ {
44
+ name: 'log',
45
+ description: 'Show commit logs',
46
+ usage: 'gent log [options]',
47
+ options: [
48
+ '-n, --number <count> Limit commits (default: 10)',
49
+ '--oneline Show each commit on one line'
50
+ ],
51
+ examples: ['gent log', 'gent log -n 5', 'gent log --oneline']
52
+ },
53
+ {
54
+ name: 'branch',
55
+ description: 'List, create, or delete branches',
56
+ usage: 'gent branch [name] [options]',
57
+ options: [
58
+ '-d, --delete <name> Delete a branch',
59
+ '-a, --all List all branches'
60
+ ],
61
+ examples: ['gent branch', 'gent branch feature-x', 'gent branch -d old-feature']
62
+ },
63
+ {
64
+ name: 'checkout',
65
+ description: 'Switch branches',
66
+ usage: 'gent checkout <branch> [options]',
67
+ options: ['-b, --create Create a new branch'],
68
+ examples: ['gent checkout main', 'gent checkout -b new-feature']
69
+ }
70
+ ];
71
+
72
+ console.log(chalk.bold.cyan('\nšŸš€ Gent CLI - Command Reference\n'));
73
+
74
+ commands.forEach((cmd, index) => {
75
+ console.log(chalk.yellow.bold(`${index + 1}. ${cmd.name.toUpperCase()}`));
76
+ console.log(chalk.white(` ${cmd.description}`));
77
+ console.log(chalk.gray(` Usage: ${cmd.usage}`));
78
+
79
+ if (cmd.options.length > 0) {
80
+ console.log(chalk.gray(' Options:'));
81
+ cmd.options.forEach(opt => {
82
+ console.log(chalk.gray(` ${opt}`));
83
+ });
84
+ }
85
+
86
+ console.log(chalk.cyan(' Examples:'));
87
+ cmd.examples.forEach(ex => {
88
+ console.log(chalk.green(` $ ${ex}`));
89
+ });
90
+
91
+ console.log();
92
+ });
93
+
94
+ const tips = `
95
+ ${chalk.bold('šŸ’” Quick Tips:')}
96
+
97
+ ${chalk.cyan('•')} Always run ${chalk.yellow('gent init')} first in a new project
98
+ ${chalk.cyan('•')} Use ${chalk.yellow('gent status')} to see what changed
99
+ ${chalk.cyan('•')} Stage files with ${chalk.yellow('gent add')} before committing
100
+ ${chalk.cyan('•')} Create branches for new features
101
+ ${chalk.cyan('•')} Check ${chalk.yellow('gent log')} to view history
102
+
103
+ ${chalk.bold('šŸ“š Documentation:')}
104
+ ${chalk.gray('• README.md - Complete documentation')}
105
+ ${chalk.gray('• QUICKSTART.md - Quick start guide')}
106
+ ${chalk.gray('• demo.sh - Interactive demo')}
107
+ `;
108
+
109
+ console.log(boxen(tips, {
110
+ padding: 1,
111
+ margin: 1,
112
+ borderStyle: 'round',
113
+ borderColor: 'cyan'
114
+ }));
115
+
116
+ console.log(chalk.gray('Run'), chalk.yellow('gent --help'), chalk.gray('for more information\n'));
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "gent-cli",
3
+ "version": "1.0.0",
4
+ "description": "A Git-like version control CLI tool",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "gent": "./src/index.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node src/index.js",
11
+ "test": "echo \"Error: no test specified\" && exit 1",
12
+ "demo": "bash demo.sh",
13
+ "link": "npm link",
14
+ "unlink": "npm unlink"
15
+ },
16
+ "keywords": [
17
+ "cli",
18
+ "version-control",
19
+ "git-like",
20
+ "gent"
21
+ ],
22
+ "author": "Abdalrahman Kanawati <kanawatiabdalrahman@gmail.com>",
23
+ "license": "ISC",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/SaadShaya7/gent.git"
27
+ },
28
+ "homepage": "https://github.com/SaadShaya7/gent#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/SaadShaya7/gent/issues"
31
+ },
32
+ "dependencies": {
33
+ "commander": "^11.1.0",
34
+ "chalk": "^4.1.2",
35
+ "inquirer": "^8.2.5",
36
+ "ora": "^5.4.1",
37
+ "boxen": "^5.1.2",
38
+ "date-fns": "^2.30.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=14.0.0"
42
+ }
43
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Add Command - Add file contents to the staging area
3
+ * Stages files for the next commit
4
+ */
5
+
6
+ const path = require('path');
7
+ const chalk = require('chalk');
8
+ const ora = require('ora');
9
+ const { getGentPath, readJSON, writeJSON, pathExists, getAllFiles, getIgnorePatterns } = require('../utils/fileSystem');
10
+ const { STAGING_FILE } = require('../utils/constants');
11
+
12
+ /**
13
+ * Add files to staging area
14
+ * @param {Array} files - Files to add
15
+ * @param {Object} options - Command options
16
+ */
17
+ async function add(files, options) {
18
+ const spinner = ora('Adding files to staging area...').start();
19
+
20
+ try {
21
+ const gentPath = await getGentPath();
22
+ const cwd = process.cwd();
23
+ const stagingPath = path.join(gentPath, STAGING_FILE);
24
+
25
+ // Read current staging area
26
+ const staging = await readJSON(stagingPath);
27
+ const stagedFiles = new Set(staging.files || []);
28
+
29
+ let filesToAdd = [];
30
+
31
+ // Handle --all option
32
+ if (options.all || files.includes('.') || files.includes('*')) {
33
+ spinner.text = 'Scanning for all files...';
34
+ const ignorePatterns = await getIgnorePatterns(cwd);
35
+ const allFiles = await getAllFiles(cwd, ignorePatterns);
36
+ filesToAdd = allFiles.map(f => path.relative(cwd, f));
37
+ } else {
38
+ // Add specified files
39
+ for (const file of files) {
40
+ const filePath = path.resolve(cwd, file);
41
+
42
+ if (!await pathExists(filePath)) {
43
+ spinner.warn(chalk.yellow(`Warning: File not found: ${file}`));
44
+ continue;
45
+ }
46
+
47
+ const relativePath = path.relative(cwd, filePath);
48
+ filesToAdd.push(relativePath);
49
+ }
50
+ }
51
+
52
+ // Add files to staging
53
+ let addedCount = 0;
54
+ for (const file of filesToAdd) {
55
+ if (!stagedFiles.has(file)) {
56
+ stagedFiles.add(file);
57
+ addedCount++;
58
+ }
59
+ }
60
+
61
+ // Save staging area
62
+ staging.files = Array.from(stagedFiles);
63
+ await writeJSON(stagingPath, staging);
64
+
65
+ spinner.succeed(chalk.green(`āœ“ Added ${addedCount} file(s) to staging area`));
66
+
67
+ if (addedCount > 0) {
68
+ console.log(chalk.gray('\nStaged files:'));
69
+ staging.files.forEach(file => {
70
+ console.log(chalk.green(` ${file}`));
71
+ });
72
+ console.log(chalk.cyan('\nℹ Use "gent commit" to record your changes'));
73
+ }
74
+
75
+ } catch (error) {
76
+ spinner.fail(chalk.red('Failed to add files'));
77
+
78
+ if (error.code === 'ENOENT' && error.message.includes('.gent')) {
79
+ console.error(chalk.red('\nError: Not a gent repository'));
80
+ console.log(chalk.yellow('ℹ Run "gent init" to initialize a repository'));
81
+ } else {
82
+ console.error(chalk.red('\nError:'), error.message);
83
+ }
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+ module.exports = add;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Branch Command - List, create, or delete branches
3
+ * Manages repository branches
4
+ */
5
+
6
+ const path = require('path');
7
+ const chalk = require('chalk');
8
+ const { getGentPath, readJSON, writeJSON } = require('../utils/fileSystem');
9
+ const { COMMITS_FILE } = require('../utils/constants');
10
+
11
+ /**
12
+ * Manage branches
13
+ * @param {String} name - Branch name (optional)
14
+ * @param {Object} options - Command options
15
+ */
16
+ async function branch(name, options) {
17
+ try {
18
+ const gentPath = await getGentPath();
19
+ const repository = await readJSON(path.join(gentPath, COMMITS_FILE));
20
+
21
+ // Delete branch
22
+ if (options.delete) {
23
+ await deleteBranch(options.delete, repository, gentPath);
24
+ return;
25
+ }
26
+
27
+ // Create new branch
28
+ if (name) {
29
+ await createBranch(name, repository, gentPath);
30
+ return;
31
+ }
32
+
33
+ // List branches
34
+ listBranches(repository, options.all);
35
+
36
+ } catch (error) {
37
+ if (error.code === 'ENOENT' && error.message.includes('.gent')) {
38
+ console.error(chalk.red('Error: Not a gent repository'));
39
+ console.log(chalk.yellow('\nℹ Run "gent init" to initialize a repository'));
40
+ } else {
41
+ console.error(chalk.red('Error:'), error.message);
42
+ }
43
+ process.exit(1);
44
+ }
45
+ }
46
+
47
+ /**
48
+ * List all branches
49
+ */
50
+ function listBranches(repository, showAll) {
51
+ const branches = repository.branches || {};
52
+ const currentBranch = repository.currentBranch || 'main';
53
+
54
+ console.log(chalk.bold.cyan('\nBranches:\n'));
55
+
56
+ for (const [branch, commitHash] of Object.entries(branches)) {
57
+ const isCurrent = branch === currentBranch;
58
+ const prefix = isCurrent ? chalk.green('* ') : ' ';
59
+ const branchName = isCurrent ? chalk.green.bold(branch) : chalk.white(branch);
60
+ const commitInfo = commitHash ? chalk.gray(` (${commitHash.substring(0, 7)})`) : chalk.gray(' (no commits)');
61
+
62
+ console.log(`${prefix}${branchName}${commitInfo}`);
63
+ }
64
+
65
+ console.log();
66
+ }
67
+
68
+ /**
69
+ * Create a new branch
70
+ */
71
+ async function createBranch(name, repository, gentPath) {
72
+ const branches = repository.branches || {};
73
+
74
+ if (branches.hasOwnProperty(name)) {
75
+ console.error(chalk.red(`Error: Branch '${name}' already exists`));
76
+ process.exit(1);
77
+ }
78
+
79
+ // Create branch from current HEAD
80
+ const currentCommit = branches[repository.currentBranch] || null;
81
+ branches[name] = currentCommit;
82
+ repository.branches = branches;
83
+
84
+ await writeJSON(path.join(gentPath, COMMITS_FILE), repository);
85
+
86
+ console.log(chalk.green(`āœ“ Created branch '${name}'`));
87
+ console.log(chalk.gray(`Based on: ${repository.currentBranch}`));
88
+ }
89
+
90
+ /**
91
+ * Delete a branch
92
+ */
93
+ async function deleteBranch(name, repository, gentPath) {
94
+ const branches = repository.branches || {};
95
+
96
+ if (!branches.hasOwnProperty(name)) {
97
+ console.error(chalk.red(`Error: Branch '${name}' not found`));
98
+ process.exit(1);
99
+ }
100
+
101
+ if (name === repository.currentBranch) {
102
+ console.error(chalk.red(`Error: Cannot delete current branch '${name}'`));
103
+ console.log(chalk.yellow('Switch to another branch first using "gent checkout <branch>"'));
104
+ process.exit(1);
105
+ }
106
+
107
+ delete branches[name];
108
+ repository.branches = branches;
109
+
110
+ await writeJSON(path.join(gentPath, COMMITS_FILE), repository);
111
+
112
+ console.log(chalk.green(`āœ“ Deleted branch '${name}'`));
113
+ }
114
+
115
+ module.exports = branch;