git-drive 0.1.6 → 0.1.7

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 (95) hide show
  1. package/.github/workflows/ci.yml +77 -0
  2. package/.planning/codebase/ARCHITECTURE.md +151 -0
  3. package/.planning/codebase/CONCERNS.md +191 -0
  4. package/.planning/codebase/CONVENTIONS.md +169 -0
  5. package/.planning/codebase/INTEGRATIONS.md +94 -0
  6. package/.planning/codebase/STACK.md +77 -0
  7. package/.planning/codebase/STRUCTURE.md +157 -0
  8. package/.planning/codebase/TESTING.md +156 -0
  9. package/Dockerfile.cli +30 -0
  10. package/Dockerfile.server +32 -0
  11. package/README.md +157 -0
  12. package/docker-compose.yml +48 -0
  13. package/package.json +20 -55
  14. package/packages/cli/Dockerfile +26 -0
  15. package/packages/cli/jest.config.js +26 -0
  16. package/packages/cli/package.json +65 -0
  17. package/packages/cli/src/__tests__/commands/companion.test.ts +152 -0
  18. package/packages/cli/src/__tests__/commands/init.test.ts +154 -0
  19. package/packages/cli/src/__tests__/commands/list.test.ts +122 -0
  20. package/packages/cli/src/__tests__/commands/push.test.ts +155 -0
  21. package/packages/cli/src/__tests__/commands/restore.test.ts +135 -0
  22. package/packages/cli/src/__tests__/commands/status.test.ts +199 -0
  23. package/packages/cli/src/__tests__/config.test.ts +198 -0
  24. package/packages/cli/src/__tests__/e2e.test.ts +125 -0
  25. package/packages/cli/src/__tests__/errors.test.ts +66 -0
  26. package/packages/cli/src/__tests__/git.test.ts +250 -0
  27. package/packages/cli/src/__tests__/server.test.ts +371 -0
  28. package/packages/cli/src/commands/archive.ts +39 -0
  29. package/packages/cli/src/commands/companion.ts +205 -0
  30. package/packages/cli/src/commands/init.ts +130 -0
  31. package/packages/cli/src/commands/link.ts +151 -0
  32. package/packages/cli/src/commands/list.ts +94 -0
  33. package/packages/cli/src/commands/push.ts +77 -0
  34. package/packages/cli/src/commands/restore.ts +36 -0
  35. package/packages/cli/src/commands/status.ts +127 -0
  36. package/packages/cli/src/config.ts +73 -0
  37. package/packages/cli/src/errors.ts +23 -0
  38. package/packages/cli/src/git.ts +60 -0
  39. package/packages/cli/src/index.ts +129 -0
  40. package/packages/cli/src/server.ts +700 -0
  41. package/packages/cli/tsconfig.json +13 -0
  42. package/packages/git-drive-docker/package.json +15 -0
  43. package/packages/server/package.json +44 -0
  44. package/packages/server/src/index.ts +569 -0
  45. package/packages/server/tsconfig.json +9 -0
  46. package/packages/ui/README.md +73 -0
  47. package/packages/ui/eslint.config.js +23 -0
  48. package/packages/ui/index.html +13 -0
  49. package/packages/ui/package.json +52 -0
  50. package/packages/ui/postcss.config.js +6 -0
  51. package/packages/ui/public/vite.svg +1 -0
  52. package/packages/ui/src/App.css +23 -0
  53. package/packages/ui/src/App.test.tsx +248 -0
  54. package/packages/ui/src/App.tsx +803 -0
  55. package/packages/ui/src/assets/react.svg +8 -0
  56. package/packages/ui/src/assets/vite.svg +3 -0
  57. package/packages/ui/src/index.css +37 -0
  58. package/packages/ui/src/main.tsx +14 -0
  59. package/packages/ui/src/test/setup.ts +1 -0
  60. package/packages/ui/tailwind.config.js +11 -0
  61. package/packages/ui/tsconfig.app.json +28 -0
  62. package/packages/ui/tsconfig.json +26 -0
  63. package/packages/ui/tsconfig.node.json +12 -0
  64. package/packages/ui/vite.config.ts +7 -0
  65. package/packages/ui/vitest.config.ts +20 -0
  66. package/pnpm-workspace.yaml +4 -0
  67. package/rewrite_app.js +731 -0
  68. package/tsconfig.json +14 -0
  69. package/dist/__tests__/commands/init.test.js +0 -123
  70. package/dist/__tests__/commands/list.test.js +0 -91
  71. package/dist/__tests__/commands/push.test.js +0 -128
  72. package/dist/__tests__/commands/restore.test.js +0 -99
  73. package/dist/__tests__/commands/status.test.js +0 -151
  74. package/dist/__tests__/config.test.js +0 -150
  75. package/dist/__tests__/e2e.test.js +0 -107
  76. package/dist/__tests__/errors.test.js +0 -56
  77. package/dist/__tests__/git.test.js +0 -184
  78. package/dist/__tests__/server.test.js +0 -310
  79. package/dist/commands/archive.js +0 -32
  80. package/dist/commands/init.js +0 -55
  81. package/dist/commands/link.js +0 -175
  82. package/dist/commands/list.js +0 -83
  83. package/dist/commands/push.js +0 -112
  84. package/dist/commands/restore.js +0 -30
  85. package/dist/commands/status.js +0 -116
  86. package/dist/config.js +0 -62
  87. package/dist/errors.js +0 -30
  88. package/dist/git.js +0 -67
  89. package/dist/index.js +0 -108
  90. package/dist/server.js +0 -535
  91. /package/{ui → packages/cli/ui}/assets/index-Br8xQbJz.js +0 -0
  92. /package/{ui → packages/cli/ui}/assets/index-Cc2q1t5k.js +0 -0
  93. /package/{ui → packages/cli/ui}/assets/index-DrL7ojPA.css +0 -0
  94. /package/{ui → packages/cli/ui}/index.html +0 -0
  95. /package/{ui → packages/cli/ui}/vite.svg +0 -0
@@ -1,112 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.push = push;
40
- const git_js_1 = require("../git.js");
41
- const errors_js_1 = require("../errors.js");
42
- const prompts_1 = __importDefault(require("prompts"));
43
- const fs = __importStar(require("fs"));
44
- const path = __importStar(require("path"));
45
- const os = __importStar(require("os"));
46
- async function push(args) {
47
- if (!(0, git_js_1.isGitRepo)()) {
48
- throw new errors_js_1.GitDriveError("Not in a git repository.");
49
- }
50
- const existingUrl = (0, git_js_1.getRemoteUrl)("gd");
51
- if (!existingUrl) {
52
- throw new errors_js_1.GitDriveError("No git-drive linked for this project. Please run 'git-drive link' first.");
53
- }
54
- try {
55
- const currentBranch = (0, git_js_1.git)("branch --show-current") || "HEAD";
56
- // Check for --all or --current flags for non-interactive mode
57
- const pushAll = args.includes("--all");
58
- const pushCurrent = args.includes("--current");
59
- let pushMode = null;
60
- if (pushAll) {
61
- pushMode = "all";
62
- }
63
- else if (pushCurrent) {
64
- pushMode = "current";
65
- }
66
- else {
67
- const result = await (0, prompts_1.default)({
68
- type: "select",
69
- name: "pushMode",
70
- message: `Pushing to ${existingUrl}\nSelect what to branch to push:`,
71
- choices: [
72
- { title: `Current branch only (${currentBranch})`, value: "current" },
73
- { title: "All branches & tags", value: "all" }
74
- ]
75
- });
76
- pushMode = result.pushMode;
77
- }
78
- if (!pushMode)
79
- return;
80
- if (pushMode === "current") {
81
- console.log(`\nPushing ${currentBranch}...`);
82
- (0, git_js_1.git)(`push gd ${currentBranch}`);
83
- console.log(`✅ Successfully pushed ${currentBranch} to git-drive.`);
84
- }
85
- else {
86
- console.log("\nPushing all branches and tags...");
87
- (0, git_js_1.git)("push gd --all");
88
- (0, git_js_1.git)("push gd --tags");
89
- console.log(`✅ Successfully pushed all branches and tags to git-drive.`);
90
- }
91
- // Write context to a central pushlog safely inside the git-drive repo folder
92
- try {
93
- if (fs.existsSync(existingUrl)) {
94
- const payload = {
95
- date: new Date().toISOString(),
96
- computer: os.hostname(),
97
- user: os.userInfo().username,
98
- localDir: process.cwd(),
99
- mode: pushMode,
100
- };
101
- const logFile = path.join(existingUrl, "git-drive-pushlog.json");
102
- fs.appendFileSync(logFile, JSON.stringify(payload) + "\n", "utf-8");
103
- }
104
- }
105
- catch {
106
- // Intentionally swallow telemetry tracking errors
107
- }
108
- }
109
- catch (err) {
110
- throw new errors_js_1.GitDriveError(`Failed to push to drive. Make sure the drive is connected.\n${err.message}`);
111
- }
112
- }
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.restore = restore;
4
- const fs_1 = require("fs");
5
- const path_1 = require("path");
6
- const config_js_1 = require("../config.js");
7
- const git_js_1 = require("../git.js");
8
- const errors_js_1 = require("../errors.js");
9
- function restore(args) {
10
- const projectName = args[0];
11
- const targetDir = args[1] || projectName;
12
- if (!projectName) {
13
- throw new errors_js_1.GitDriveError("Usage: git drive restore <project-name> [target-dir]");
14
- }
15
- const config = (0, config_js_1.requireConfig)();
16
- (0, config_js_1.assertDriveMounted)(config.drivePath);
17
- const storePath = (0, config_js_1.getDriveStorePath)(config.drivePath);
18
- const bareRepoPath = (0, path_1.join)(storePath, `${projectName}.git`);
19
- if (!(0, fs_1.existsSync)(bareRepoPath)) {
20
- throw new errors_js_1.GitDriveError(`Project '${projectName}' not found on drive.`);
21
- }
22
- const targetPath = (0, path_1.resolve)(targetDir);
23
- if ((0, fs_1.existsSync)(targetPath)) {
24
- throw new errors_js_1.GitDriveError(`Directory already exists: ${targetPath}`);
25
- }
26
- (0, git_js_1.git)(`clone ${bareRepoPath} ${targetPath}`);
27
- // Rename origin to drive so the remote stays consistent
28
- (0, git_js_1.git)("remote rename origin drive", targetPath);
29
- console.log(`Restored ${projectName} into ${targetPath}`);
30
- }
@@ -1,116 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.status = status;
4
- const fs_1 = require("fs");
5
- const path_1 = require("path");
6
- const os_1 = require("os");
7
- const node_disk_info_1 = require("node-disk-info");
8
- const git_js_1 = require("../git.js");
9
- function loadLinks() {
10
- const linksFile = (0, path_1.join)((0, os_1.homedir)(), ".config", "git-drive", "links.json");
11
- if (!(0, fs_1.existsSync)(linksFile))
12
- return {};
13
- try {
14
- return JSON.parse((0, fs_1.readFileSync)(linksFile, "utf-8"));
15
- }
16
- catch {
17
- return {};
18
- }
19
- }
20
- function getGitDrivePath(mountpoint) {
21
- return (0, path_1.join)(mountpoint, ".git-drive");
22
- }
23
- async function status(_args) {
24
- console.log("Git Drive Status\n");
25
- // Get all connected drives
26
- let drives = [];
27
- try {
28
- drives = await (0, node_disk_info_1.getDiskInfo)();
29
- }
30
- catch (err) {
31
- console.error("Error detecting drives:", err);
32
- return;
33
- }
34
- // Filter to external/removable drives
35
- const externalDrives = drives.filter((d) => {
36
- const mp = d.mounted;
37
- if (!mp)
38
- return false;
39
- if (mp === "/" || mp === "100%")
40
- return false;
41
- if (process.platform === "darwin") {
42
- return mp.startsWith("/Volumes/") && !mp.startsWith("/Volumes/Recovery");
43
- }
44
- if (mp.startsWith("/sys") || mp.startsWith("/proc") || mp.startsWith("/run") || mp.startsWith("/snap") || mp.startsWith("/boot"))
45
- return false;
46
- if (d.filesystem === "tmpfs" || d.filesystem === "devtmpfs" || d.filesystem === "udev" || d.filesystem === "overlay")
47
- return false;
48
- return true;
49
- });
50
- // Load links
51
- const links = loadLinks();
52
- const linkEntries = Object.entries(links);
53
- // Show connected drives with git-drive
54
- console.log("=== Connected Drives ===\n");
55
- if (externalDrives.length === 0) {
56
- console.log("No external drives connected.\n");
57
- }
58
- else {
59
- for (const drive of externalDrives) {
60
- const mp = drive.mounted;
61
- const gitDrivePath = getGitDrivePath(mp);
62
- const hasGitDrive = (0, fs_1.existsSync)(gitDrivePath);
63
- if (hasGitDrive) {
64
- const entries = (0, fs_1.readdirSync)(gitDrivePath).filter(n => n.endsWith(".git") || (0, fs_1.existsSync)((0, path_1.join)(gitDrivePath, n, "HEAD")));
65
- console.log(`✓ ${mp}`);
66
- console.log(` ${entries.length} repo${entries.length === 1 ? "" : "s"} backed up`);
67
- }
68
- else {
69
- console.log(`○ ${mp} (not initialized)`);
70
- }
71
- }
72
- console.log();
73
- }
74
- // Show registered drives (from links)
75
- console.log("=== Registered Repositories ===\n");
76
- if (linkEntries.length === 0) {
77
- console.log("No repositories linked to drives yet.");
78
- console.log("Run 'git-drive link' to link a repository.\n");
79
- }
80
- else {
81
- for (const [localPath, link] of linkEntries) {
82
- const stillConnected = (0, fs_1.existsSync)(link.mountpoint);
83
- const localExists = (0, fs_1.existsSync)(localPath);
84
- console.log(`${localPath}`);
85
- console.log(` → ${link.mountpoint} (${link.repoName})`);
86
- console.log(` Drive: ${stillConnected ? "connected" : "NOT CONNECTED"}`);
87
- console.log(` Local: ${localExists ? "exists" : "NOT FOUND"}`);
88
- console.log();
89
- }
90
- }
91
- // Show current repo status if in a git repo
92
- if ((0, git_js_1.isGitRepo)()) {
93
- console.log("=== Current Repository ===\n");
94
- const name = (0, git_js_1.getProjectName)();
95
- const remoteUrl = (0, git_js_1.getRemoteUrl)("gd");
96
- console.log(`Repository: ${name}`);
97
- if (remoteUrl) {
98
- console.log(`Remote 'gd': ${remoteUrl}`);
99
- // Check if this repo is linked
100
- const cwd = process.cwd();
101
- const link = links[cwd];
102
- if (link) {
103
- console.log(`Linked to: ${link.mountpoint}`);
104
- }
105
- }
106
- else {
107
- console.log(`No 'gd' remote configured.`);
108
- console.log("Run 'git-drive link' to set up backup.");
109
- }
110
- console.log();
111
- }
112
- // Server status hint
113
- console.log("=== Server ===\n");
114
- console.log("Web UI: http://localhost:4483");
115
- console.log("Run 'git-drive server' to start the web interface.\n");
116
- }
package/dist/config.js DELETED
@@ -1,62 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadConfig = loadConfig;
4
- exports.saveConfig = saveConfig;
5
- exports.requireConfig = requireConfig;
6
- exports.assertDriveMounted = assertDriveMounted;
7
- exports.getDriveStorePath = getDriveStorePath;
8
- exports.loadLinks = loadLinks;
9
- exports.saveLink = saveLink;
10
- const os_1 = require("os");
11
- const path_1 = require("path");
12
- const fs_1 = require("fs");
13
- const errors_js_1 = require("./errors.js");
14
- const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), ".config", "git-drive");
15
- const CONFIG_FILE = (0, path_1.join)(CONFIG_DIR, "config.json");
16
- function loadConfig() {
17
- if (!(0, fs_1.existsSync)(CONFIG_FILE))
18
- return null;
19
- const raw = (0, fs_1.readFileSync)(CONFIG_FILE, "utf-8");
20
- return JSON.parse(raw);
21
- }
22
- function saveConfig(config) {
23
- (0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
24
- (0, fs_1.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2) + "\n");
25
- }
26
- function requireConfig() {
27
- const config = loadConfig();
28
- if (!config) {
29
- throw new errors_js_1.GitDriveError("No drive configured. Run: git drive init <path>");
30
- }
31
- return config;
32
- }
33
- function assertDriveMounted(drivePath) {
34
- if (!(0, fs_1.existsSync)(drivePath)) {
35
- throw new errors_js_1.GitDriveError(`Drive not found at ${drivePath}. Is it connected?`);
36
- }
37
- }
38
- function getDriveStorePath(drivePath) {
39
- return (0, path_1.join)(drivePath, ".git-drive");
40
- }
41
- const LINKS_FILE = (0, path_1.join)(CONFIG_DIR, "links.json");
42
- function loadLinks() {
43
- if (!(0, fs_1.existsSync)(LINKS_FILE))
44
- return {};
45
- try {
46
- const raw = (0, fs_1.readFileSync)(LINKS_FILE, "utf-8");
47
- return JSON.parse(raw);
48
- }
49
- catch {
50
- return {};
51
- }
52
- }
53
- function saveLink(localPath, mountpoint, repoName) {
54
- (0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
55
- const links = loadLinks();
56
- links[localPath] = {
57
- mountpoint,
58
- repoName,
59
- linkedAt: new Date().toISOString(),
60
- };
61
- (0, fs_1.writeFileSync)(LINKS_FILE, JSON.stringify(links, null, 2) + "\n");
62
- }
package/dist/errors.js DELETED
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GitDriveError = void 0;
4
- exports.handleError = handleError;
5
- class GitDriveError extends Error {
6
- constructor(message) {
7
- super(message);
8
- this.name = "GitDriveError";
9
- }
10
- }
11
- exports.GitDriveError = GitDriveError;
12
- function handleError(err) {
13
- if (err instanceof GitDriveError) {
14
- console.error(`error: ${err.message}`);
15
- }
16
- else if (err instanceof Error) {
17
- const msg = err.message;
18
- // execSync errors include stderr in the message
19
- const stderrMatch = msg.match(/stderr:\s*([\s\S]*)/);
20
- if (stderrMatch) {
21
- console.error(`error: ${stderrMatch[1].trim()}`);
22
- }
23
- else {
24
- console.error(`error: ${msg}`);
25
- }
26
- }
27
- else {
28
- console.error("An unexpected error occurred.");
29
- }
30
- }
package/dist/git.js DELETED
@@ -1,67 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.git = git;
4
- exports.listDrives = listDrives;
5
- exports.getRepoRoot = getRepoRoot;
6
- exports.getProjectName = getProjectName;
7
- exports.getRemoteUrl = getRemoteUrl;
8
- exports.isGitRepo = isGitRepo;
9
- const child_process_1 = require("child_process");
10
- const path_1 = require("path");
11
- const node_disk_info_1 = require("node-disk-info");
12
- function git(args, cwd) {
13
- return (0, child_process_1.execSync)(`git ${args}`, {
14
- cwd,
15
- encoding: "utf-8",
16
- stdio: ["pipe", "pipe", "pipe"],
17
- }).trim();
18
- }
19
- async function listDrives() {
20
- const drives = await (0, node_disk_info_1.getDiskInfo)();
21
- return drives.filter((d) => {
22
- const mp = d.mounted;
23
- if (!mp)
24
- return false;
25
- if (mp === "/" || mp === "100%")
26
- return false;
27
- // Exclude temporary and system paths on all platforms
28
- if (mp.startsWith("/var/") || mp.startsWith("/private/var/") || mp.startsWith("/tmp") || mp.startsWith("/private/tmp"))
29
- return false;
30
- if (mp.includes("TemporaryItems") || mp.includes("NSIRD_"))
31
- return false;
32
- if (mp.startsWith("/System/") || mp.startsWith("/Library/"))
33
- return false;
34
- if (process.platform === "darwin") {
35
- return mp.startsWith("/Volumes/") && !mp.startsWith("/Volumes/Recovery");
36
- }
37
- if (mp.startsWith("/sys") || mp.startsWith("/proc") || mp.startsWith("/run") || mp.startsWith("/snap") || mp.startsWith("/boot"))
38
- return false;
39
- if (d.filesystem === "tmpfs" || d.filesystem === "devtmpfs" || d.filesystem === "udev" || d.filesystem === "overlay")
40
- return false;
41
- return true;
42
- });
43
- }
44
- function getRepoRoot() {
45
- return git("rev-parse --show-toplevel");
46
- }
47
- function getProjectName() {
48
- const root = getRepoRoot();
49
- return (0, path_1.basename)(root);
50
- }
51
- function getRemoteUrl(remoteName) {
52
- try {
53
- return git(`remote get-url ${remoteName}`);
54
- }
55
- catch {
56
- return null;
57
- }
58
- }
59
- function isGitRepo() {
60
- try {
61
- git("rev-parse --is-inside-work-tree");
62
- return true;
63
- }
64
- catch {
65
- return false;
66
- }
67
- }
package/dist/index.js DELETED
@@ -1,108 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- const child_process_1 = require("child_process");
5
- const fs_1 = require("fs");
6
- const push_js_1 = require("./commands/push.js");
7
- const list_js_1 = require("./commands/list.js");
8
- const status_js_1 = require("./commands/status.js");
9
- const link_js_1 = require("./commands/link.js");
10
- const init_js_1 = require("./commands/init.js");
11
- const errors_js_1 = require("./errors.js");
12
- const server_js_1 = require("./server.js");
13
- const { version: VERSION } = JSON.parse((0, fs_1.readFileSync)(__dirname + '/../package.json', 'utf-8'));
14
- const commands = {
15
- init: init_js_1.init,
16
- push: push_js_1.push,
17
- list: list_js_1.list,
18
- status: status_js_1.status,
19
- link: link_js_1.link,
20
- server: startServer,
21
- start: startServer,
22
- ui: startServer,
23
- };
24
- // Commands that don't need the server running
25
- const NO_SERVER_COMMANDS = ['server', 'start', 'ui'];
26
- function printUsage() {
27
- console.log(`
28
- git-drive - Turn any external drive into a git remote backup for your code
29
-
30
- Usage:
31
- git-drive <command> [options]
32
-
33
- Commands:
34
- init Initialize git-drive on an external drive
35
- link Link current repo to a drive
36
- push Push current repo to drive
37
- list Show connected drives and their status
38
- status Show detailed status of drives and repos
39
- server, start, ui Start the git-drive web UI server
40
-
41
- Options:
42
- -v, -V, --version Show version number
43
- -h, --help Show this help message
44
-
45
- Examples:
46
- git-drive init /Volumes/MyDrive Initialize git-drive on a drive
47
- git-drive link Link current repo to a drive
48
- git-drive push Push current repo to drive
49
- git-drive list List connected drives
50
- git-drive status Show detailed status
51
- git-drive server Start the web UI at http://localhost:4483
52
-
53
- Environment Variables:
54
- GIT_DRIVE_PORT Port for the web server (default: 4483)
55
-
56
- Docker:
57
- docker run -it --rm -v /Volumes:/Volumes -p 4483:4483 git-drive
58
-
59
- Documentation:
60
- https://github.com/josmanvis/git-drive
61
- `);
62
- }
63
- function startServer(_args) {
64
- console.log('\n 🚀 Starting Git Drive server...\n');
65
- console.log(' Web UI: http://localhost:4483\n');
66
- console.log(' Press Ctrl+C to stop\n');
67
- const serverPath = require.resolve('./server.js');
68
- const child = (0, child_process_1.spawn)(process.execPath, [serverPath], {
69
- stdio: 'inherit',
70
- env: process.env
71
- });
72
- child.on('error', (err) => {
73
- console.error('Failed to start server:', err.message);
74
- process.exit(1);
75
- });
76
- child.on('exit', (code) => {
77
- process.exit(code || 0);
78
- });
79
- }
80
- const [command, ...args] = process.argv.slice(2);
81
- (async () => {
82
- try {
83
- if (!command || command === "--help" || command === "-h") {
84
- printUsage();
85
- process.exit(0);
86
- }
87
- // Handle version flags
88
- if (command === "--version" || command === "-v" || command === "-V" || command === "version") {
89
- console.log(`git-drive v${VERSION}`);
90
- process.exit(0);
91
- }
92
- const handler = commands[command];
93
- if (!handler) {
94
- console.error(`Unknown command: ${command}\n`);
95
- printUsage();
96
- process.exit(1);
97
- }
98
- // Ensure server is running for commands that need it
99
- if (!NO_SERVER_COMMANDS.includes(command)) {
100
- await (0, server_js_1.ensureServerRunning)();
101
- }
102
- await handler(args);
103
- }
104
- catch (err) {
105
- (0, errors_js_1.handleError)(err);
106
- process.exit(1);
107
- }
108
- })();