git-easy-worktree 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 +46 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Git Easy Worktree
|
|
2
|
+
|
|
3
|
+
A Node.js CLI tool to easily create git worktrees from a repository URL.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install globally from npm
|
|
9
|
+
npm install -g git-easy-worktree
|
|
10
|
+
|
|
11
|
+
# Or install from source
|
|
12
|
+
git clone https://github.com/your-username/git-easy-worktree.git
|
|
13
|
+
cd git-easy-worktree
|
|
14
|
+
npm install
|
|
15
|
+
npm link
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git-wt <repo-url> <branch-name> [options]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Options
|
|
25
|
+
|
|
26
|
+
- `-d, --dir <directory>`: Base directory for worktrees (default: current directory)
|
|
27
|
+
|
|
28
|
+
### Example
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Create a worktree for the 'master' branch of Hello-World
|
|
32
|
+
git-wt https://github.com/octocat/Hello-World.git master
|
|
33
|
+
|
|
34
|
+
# Resulting structure:
|
|
35
|
+
# ./Hello-World/
|
|
36
|
+
# .bare/ (Bare repository)
|
|
37
|
+
# master/ (Worktree)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Development
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install
|
|
44
|
+
npm run dev -- <url> <branch>
|
|
45
|
+
npm run build
|
|
46
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { simpleGit } from 'simple-git';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import * as fs from 'fs-extra';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import boxen from 'boxen';
|
|
10
|
+
import figlet from 'figlet';
|
|
11
|
+
import gradient from 'gradient-string';
|
|
12
|
+
const program = new Command();
|
|
13
|
+
const printBanner = () => {
|
|
14
|
+
const title = figlet.textSync('Git Easy WT', { font: 'Standard' });
|
|
15
|
+
console.log(gradient.pastel.multiline(title));
|
|
16
|
+
};
|
|
17
|
+
const run = async () => {
|
|
18
|
+
printBanner();
|
|
19
|
+
program
|
|
20
|
+
.name('git-wt')
|
|
21
|
+
.description('A CLI tool to create git worktrees from a repository URL and branch name')
|
|
22
|
+
.version('1.0.0')
|
|
23
|
+
.argument('[url]', 'Git repository URL')
|
|
24
|
+
.argument('[branch]', 'Branch name to checkout')
|
|
25
|
+
.option('-d, --dir <directory>', 'Base directory for worktrees', process.cwd())
|
|
26
|
+
.action(async (urlArg, branchArg, options) => {
|
|
27
|
+
let url = urlArg;
|
|
28
|
+
let branch = branchArg;
|
|
29
|
+
// Interactive Mode if args missing
|
|
30
|
+
if (!url || !branch) {
|
|
31
|
+
console.log(boxen(chalk.cyan('Welcome to Git Easy Worktree! 🚀\nLet\'s set up your workspace.'), { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
|
|
32
|
+
const answers = await inquirer.prompt([
|
|
33
|
+
{
|
|
34
|
+
type: 'input',
|
|
35
|
+
name: 'url',
|
|
36
|
+
message: 'Enter Git Repository URL:',
|
|
37
|
+
when: !url,
|
|
38
|
+
validate: (input) => input ? true : 'URL is required'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'input',
|
|
42
|
+
name: 'branch',
|
|
43
|
+
message: 'Enter Branch Name:',
|
|
44
|
+
when: !branch,
|
|
45
|
+
validate: (input) => input ? true : 'Branch name is required'
|
|
46
|
+
}
|
|
47
|
+
]);
|
|
48
|
+
if (!url)
|
|
49
|
+
url = answers.url;
|
|
50
|
+
if (!branch)
|
|
51
|
+
branch = answers.branch;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
// 1. Extract repo name
|
|
55
|
+
const repoNameMatch = url.match(/\/([^\/]+?)(\.git)?$/);
|
|
56
|
+
if (!repoNameMatch) {
|
|
57
|
+
throw new Error('Invalid Git URL. Could not extract repository name.');
|
|
58
|
+
}
|
|
59
|
+
const repoName = repoNameMatch[1];
|
|
60
|
+
const baseDir = path.resolve(options.dir);
|
|
61
|
+
const repoDir = path.join(baseDir, repoName);
|
|
62
|
+
const bareRepoPath = path.join(repoDir, '.bare');
|
|
63
|
+
const worktreePath = path.join(repoDir, branch);
|
|
64
|
+
await fs.ensureDir(repoDir);
|
|
65
|
+
const git = simpleGit();
|
|
66
|
+
const spinner = ora();
|
|
67
|
+
// 2. Check/Clone Bare Repo
|
|
68
|
+
if (fs.existsSync(bareRepoPath)) {
|
|
69
|
+
spinner.start(`Checking bare repository at ${chalk.dim(bareRepoPath)}`);
|
|
70
|
+
spinner.succeed('Bare repository found');
|
|
71
|
+
spinner.start('Fetching latest updates from remote...');
|
|
72
|
+
await simpleGit(bareRepoPath).fetch('origin');
|
|
73
|
+
spinner.succeed('Repository updated');
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
spinner.start(`Cloning bare repository to ${chalk.dim(bareRepoPath)}...`);
|
|
77
|
+
await git.clone(url, bareRepoPath, ['--bare']);
|
|
78
|
+
spinner.succeed('Repository cloned successfully');
|
|
79
|
+
}
|
|
80
|
+
// 3. Create Worktree
|
|
81
|
+
if (fs.existsSync(worktreePath)) {
|
|
82
|
+
spinner.fail(`Worktree path ${worktreePath} already exists.`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
spinner.start(`Creating worktree for branch ${chalk.green(branch)}...`);
|
|
86
|
+
const bareGit = simpleGit(bareRepoPath);
|
|
87
|
+
try {
|
|
88
|
+
await bareGit.raw(['worktree', 'add', worktreePath, branch]);
|
|
89
|
+
spinner.succeed('Worktree created successfully!');
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
if (err.message.includes('invalid reference') || err.message.includes('not a valid object name')) {
|
|
93
|
+
spinner.text = `Branch ${branch} not found. Creating new branch...`;
|
|
94
|
+
await bareGit.raw(['worktree', 'add', '-b', branch, worktreePath]);
|
|
95
|
+
spinner.succeed('New branch worktree created!');
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
console.log('\n' + boxen(chalk.green(`🎉 All done! \n\n`) +
|
|
102
|
+
`📂 Worktree: ${chalk.cyan(worktreePath)}\n` +
|
|
103
|
+
`🌿 Branch: ${chalk.cyan(branch)}\n\n` +
|
|
104
|
+
chalk.dim(`cd ${path.relative(process.cwd(), worktreePath)}`), { padding: 1, borderStyle: 'round', borderColor: 'green' }));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
ora().fail(chalk.red(error.message));
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
program.parse(process.argv);
|
|
112
|
+
};
|
|
113
|
+
run();
|
|
114
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-easy-worktree",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to create git worktrees from URL",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"git-wt": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "ts-node src/index.ts",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"git",
|
|
19
|
+
"worktree",
|
|
20
|
+
"cli"
|
|
21
|
+
],
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@inquirer/prompts": "^8.2.0",
|
|
32
|
+
"@types/inquirer": "^9.0.9",
|
|
33
|
+
"boxen": "^8.0.1",
|
|
34
|
+
"chalk": "^4.1.2",
|
|
35
|
+
"commander": "^14.0.3",
|
|
36
|
+
"figlet": "^1.10.0",
|
|
37
|
+
"fs-extra": "^11.3.3",
|
|
38
|
+
"gradient-string": "^3.0.0",
|
|
39
|
+
"inquirer": "^9.3.8",
|
|
40
|
+
"ora": "^9.3.0",
|
|
41
|
+
"simple-git": "^3.30.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/figlet": "^1.7.0",
|
|
45
|
+
"@types/fs-extra": "^11.0.4",
|
|
46
|
+
"@types/gradient-string": "^1.1.6",
|
|
47
|
+
"@types/node": "^25.2.2",
|
|
48
|
+
"ts-node": "^10.9.2",
|
|
49
|
+
"typescript": "^5.9.3"
|
|
50
|
+
}
|
|
51
|
+
}
|