@mcadam/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.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +315 -0
  3. package/bin/worktree.js +2 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +63 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/config.d.ts +2 -0
  9. package/dist/commands/config.d.ts.map +1 -0
  10. package/dist/commands/config.js +110 -0
  11. package/dist/commands/config.js.map +1 -0
  12. package/dist/commands/create.d.ts +2 -0
  13. package/dist/commands/create.d.ts.map +1 -0
  14. package/dist/commands/create.js +75 -0
  15. package/dist/commands/create.js.map +1 -0
  16. package/dist/commands/init.d.ts +2 -0
  17. package/dist/commands/init.d.ts.map +1 -0
  18. package/dist/commands/init.js +90 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/list.d.ts +2 -0
  21. package/dist/commands/list.d.ts.map +1 -0
  22. package/dist/commands/list.js +82 -0
  23. package/dist/commands/list.js.map +1 -0
  24. package/dist/components/WorktreeList.d.ts +10 -0
  25. package/dist/components/WorktreeList.d.ts.map +1 -0
  26. package/dist/components/WorktreeList.js +41 -0
  27. package/dist/components/WorktreeList.js.map +1 -0
  28. package/dist/config/detector.d.ts +4 -0
  29. package/dist/config/detector.d.ts.map +1 -0
  30. package/dist/config/detector.js +34 -0
  31. package/dist/config/detector.js.map +1 -0
  32. package/dist/config/manager.d.ts +19 -0
  33. package/dist/config/manager.d.ts.map +1 -0
  34. package/dist/config/manager.js +73 -0
  35. package/dist/config/manager.js.map +1 -0
  36. package/dist/config/schema.d.ts +77 -0
  37. package/dist/config/schema.d.ts.map +1 -0
  38. package/dist/config/schema.js +19 -0
  39. package/dist/config/schema.js.map +1 -0
  40. package/dist/utils/gh.d.ts +13 -0
  41. package/dist/utils/gh.d.ts.map +1 -0
  42. package/dist/utils/gh.js +41 -0
  43. package/dist/utils/gh.js.map +1 -0
  44. package/dist/utils/git.d.ts +14 -0
  45. package/dist/utils/git.d.ts.map +1 -0
  46. package/dist/utils/git.js +91 -0
  47. package/dist/utils/git.js.map +1 -0
  48. package/dist/utils/sanitize.d.ts +3 -0
  49. package/dist/utils/sanitize.d.ts.map +1 -0
  50. package/dist/utils/sanitize.js +13 -0
  51. package/dist/utils/sanitize.js.map +1 -0
  52. package/package.json +68 -0
@@ -0,0 +1,91 @@
1
+ import { execa } from 'execa';
2
+ import path from 'path';
3
+ export async function createWorktree(basePath, worktreeName, branchName, gitRoot) {
4
+ const worktreePath = path.join(basePath, worktreeName);
5
+ // Check if branch exists
6
+ try {
7
+ await execa('git', ['rev-parse', '--verify', branchName], { cwd: gitRoot });
8
+ }
9
+ catch {
10
+ // Branch doesn't exist locally, check remote
11
+ try {
12
+ await execa('git', ['fetch', 'origin', branchName], { cwd: gitRoot });
13
+ await execa('git', ['worktree', 'add', worktreePath, `origin/${branchName}`], { cwd: gitRoot });
14
+ return;
15
+ }
16
+ catch {
17
+ // Create new branch
18
+ await execa('git', ['worktree', 'add', '-b', branchName, worktreePath], { cwd: gitRoot });
19
+ return;
20
+ }
21
+ }
22
+ // Branch exists locally
23
+ await execa('git', ['worktree', 'add', worktreePath, branchName], { cwd: gitRoot });
24
+ }
25
+ export async function listWorktrees(gitRoot) {
26
+ try {
27
+ const { stdout } = await execa('git', ['worktree', 'list', '--porcelain'], { cwd: gitRoot });
28
+ const worktrees = [];
29
+ const lines = stdout.split('\n');
30
+ let currentWorktree = {};
31
+ for (const line of lines) {
32
+ if (line.startsWith('worktree ')) {
33
+ if (currentWorktree.path) {
34
+ worktrees.push(currentWorktree);
35
+ }
36
+ currentWorktree = {
37
+ path: line.substring(9),
38
+ isMain: false,
39
+ };
40
+ }
41
+ else if (line.startsWith('HEAD ')) {
42
+ currentWorktree.commit = line.substring(5);
43
+ }
44
+ else if (line.startsWith('branch ')) {
45
+ currentWorktree.branch = line.substring(7).replace('refs/heads/', '');
46
+ }
47
+ else if (line === 'bare') {
48
+ currentWorktree.isMain = true;
49
+ }
50
+ else if (line === '') {
51
+ if (currentWorktree.path) {
52
+ worktrees.push(currentWorktree);
53
+ currentWorktree = {};
54
+ }
55
+ }
56
+ }
57
+ if (currentWorktree.path) {
58
+ worktrees.push(currentWorktree);
59
+ }
60
+ // Check if branches are pushed to remote
61
+ for (const worktree of worktrees) {
62
+ if (!worktree.branch || worktree.isMain)
63
+ continue;
64
+ try {
65
+ await execa('git', ['rev-parse', `origin/${worktree.branch}`], { cwd: gitRoot });
66
+ worktree.isPushed = true;
67
+ }
68
+ catch {
69
+ worktree.isPushed = false;
70
+ }
71
+ }
72
+ return worktrees;
73
+ }
74
+ catch (error) {
75
+ console.error('Error listing worktrees:', error);
76
+ return [];
77
+ }
78
+ }
79
+ export async function removeWorktree(worktreePath, gitRoot) {
80
+ await execa('git', ['worktree', 'remove', worktreePath, '--force'], { cwd: gitRoot });
81
+ }
82
+ export async function getAllBranches(gitRoot) {
83
+ try {
84
+ const { stdout } = await execa('git', ['branch', '-a', '--format=%(refname:short)'], { cwd: gitRoot });
85
+ return stdout.split('\n').filter(Boolean);
86
+ }
87
+ catch {
88
+ return [];
89
+ }
90
+ }
91
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function sanitizeBranchName(branch: string): string;
2
+ export declare function createWorktreeName(branch: string, prefix: string): string;
3
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGzE"}
@@ -0,0 +1,13 @@
1
+ export function sanitizeBranchName(branch) {
2
+ // Replace common special characters with hyphens
3
+ return branch
4
+ .replace(/[\\/:\s*?"<>|]/g, '-') // Replace special chars with hyphen
5
+ .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens
6
+ .replace(/-{2,}/g, '-') // Replace multiple hyphens with single
7
+ .toLowerCase(); // Convert to lowercase for consistency
8
+ }
9
+ export function createWorktreeName(branch, prefix) {
10
+ const sanitized = sanitizeBranchName(branch);
11
+ return `${prefix}${sanitized}`;
12
+ }
13
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,iDAAiD;IACjD,OAAO,MAAM;SACV,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,oCAAoC;SACpE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,kCAAkC;SAC1D,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,uCAAuC;SAC9D,WAAW,EAAE,CAAA,CAAC,uCAAuC;AAC1D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAc;IAC/D,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAC5C,OAAO,GAAG,MAAM,GAAG,SAAS,EAAE,CAAA;AAChC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@mcadam/worktree",
3
+ "version": "1.0.0",
4
+ "description": "A CLI tool for managing Git worktrees across multiple repositories",
5
+ "main": "dist/cli.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "worktree": "./bin/worktree.js"
9
+ },
10
+ "keywords": [
11
+ "git",
12
+ "worktree",
13
+ "cli",
14
+ "development",
15
+ "workflow"
16
+ ],
17
+ "author": "",
18
+ "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/un/worktree.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/un/worktree/issues"
25
+ },
26
+ "homepage": "https://github.com/un/worktree#readme",
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "dependencies": {
31
+ "chalk": "^5.3.0",
32
+ "commander": "^11.1.0",
33
+ "execa": "^8.0.1",
34
+ "fs-extra": "^11.2.0",
35
+ "ink": "^5.2.1",
36
+ "ink-select-input": "^6.2.0",
37
+ "ink-spinner": "^5.0.0",
38
+ "ink-text-input": "^6.0.0",
39
+ "ora": "^7.0.1",
40
+ "react": "^18.2.0",
41
+ "zod": "^3.22.4"
42
+ },
43
+ "devDependencies": {
44
+ "@biomejs/biome": "^1.5.0",
45
+ "@types/fs-extra": "^11.0.4",
46
+ "@types/node": "^20.10.5",
47
+ "@types/react": "^18.2.45",
48
+ "tsx": "^4.7.0",
49
+ "typescript": "^5.3.3"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ },
54
+ "packageManager": "pnpm@8.12.0",
55
+ "files": [
56
+ "dist",
57
+ "bin"
58
+ ],
59
+ "scripts": {
60
+ "build": "tsc",
61
+ "dev": "tsx watch src/cli.tsx",
62
+ "typecheck": "tsc --noEmit",
63
+ "clean": "rm -rf dist",
64
+ "lint": "biome check .",
65
+ "lint:fix": "biome check --apply .",
66
+ "format": "biome format --write ."
67
+ }
68
+ }