spindb 0.50.8 → 0.51.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 +13 -0
- package/dist/cli/commands/branch.js +537 -0
- package/dist/cli/commands/branch.js.map +1 -0
- package/dist/cli/commands/info.js +15 -0
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/menu/container-handlers.js +136 -0
- package/dist/cli/commands/menu/container-handlers.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/version.js +1 -1
- package/dist/core/branch-manager.js +441 -0
- package/dist/core/branch-manager.js.map +1 -0
- package/dist/core/container-manager.js +117 -79
- package/dist/core/container-manager.js.map +1 -1
- package/dist/core/cow-copy.js +108 -0
- package/dist/core/cow-copy.js.map +1 -0
- package/dist/core/git-branch-sync.js +331 -0
- package/dist/core/git-branch-sync.js.map +1 -0
- package/dist/engines/base-engine.js +18 -0
- package/dist/engines/base-engine.js.map +1 -1
- package/dist/engines/clickhouse/index.js +8 -0
- package/dist/engines/clickhouse/index.js.map +1 -1
- package/dist/engines/ferretdb/index.js +15 -0
- package/dist/engines/ferretdb/index.js.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -181,6 +181,19 @@ Every engine works the same way. Learn one, use them all.
|
|
|
181
181
|
|
|
182
182
|
> See [CHEATSHEET.md](CHEATSHEET.md) for the complete command reference, connection strings, backup formats, scripting patterns, and more.
|
|
183
183
|
|
|
184
|
+
### Branching (copy-on-write)
|
|
185
|
+
|
|
186
|
+
Fork a database instantly, the way Neon/Vercel do — but locally and for **every engine**:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
spindb branch myapp myapp-feature # instant copy-on-write fork (auto stop/restart if running)
|
|
190
|
+
spindb branch list # see the lineage tree
|
|
191
|
+
spindb branch reset myapp-feature # discard the branch's changes, re-fork from parent
|
|
192
|
+
spindb branch delete myapp-feature
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
On copy-on-write filesystems (APFS on macOS; Btrfs / XFS-reflink / ZFS on Linux) a branch is instant and shares disk blocks with its source until they diverge; elsewhere it falls back to a full copy. See [docs/BRANCHING.md](docs/BRANCHING.md).
|
|
196
|
+
|
|
184
197
|
---
|
|
185
198
|
|
|
186
199
|
## Why SpinDB?
|
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { containerManager } from '../../core/container-manager.js';
|
|
4
|
+
import { branchManager } from '../../core/branch-manager.js';
|
|
5
|
+
import { isRemoteContainer } from '../../types/index.js';
|
|
6
|
+
import { promptContainerSelect, promptContainerName, promptConfirm, } from '../ui/prompts.js';
|
|
7
|
+
import { createSpinner } from '../ui/spinner.js';
|
|
8
|
+
import { connectionBox, header, keyValue, uiWarning, uiSuccess, theme, } from '../ui/theme.js';
|
|
9
|
+
import { exitWithError } from '../../core/error-handler.js';
|
|
10
|
+
import { initRepo, sync as gitSync, prune as gitPrune, status as gitStatus, installHooks, uninstallHooks, findRepoRoot, } from '../../core/git-branch-sync.js';
|
|
11
|
+
export const branchCommand = new Command('branch').description('Branch a database — an instant copy-on-write fork (Neon/Vercel-style)');
|
|
12
|
+
// ---- branch create (default) ----
|
|
13
|
+
branchCommand
|
|
14
|
+
.command('create [source] [name]', { isDefault: true })
|
|
15
|
+
.description('Create a branch of a container (auto stop/snapshot/restart of a running source)')
|
|
16
|
+
.option('-j, --json', 'Output result as JSON')
|
|
17
|
+
.option('--no-start', "Don't start the branch after creating it")
|
|
18
|
+
.option('-p, --port <port>', 'Run the branch on a specific port')
|
|
19
|
+
.action(async (source, name, options) => {
|
|
20
|
+
try {
|
|
21
|
+
let sourceName = source;
|
|
22
|
+
if (!sourceName) {
|
|
23
|
+
if (options.json) {
|
|
24
|
+
return exitWithError({
|
|
25
|
+
message: 'Source container name is required',
|
|
26
|
+
json: true,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const containers = await containerManager.list();
|
|
30
|
+
if (containers.length === 0) {
|
|
31
|
+
console.log(uiWarning('No containers found. Create one with: spindb create'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Branching can stop+restart a running source, so all local
|
|
35
|
+
// containers are eligible (remote/linked are not).
|
|
36
|
+
const branchable = containers.filter((c) => !isRemoteContainer(c));
|
|
37
|
+
const selected = await promptContainerSelect(branchable, 'Select container to branch:');
|
|
38
|
+
if (!selected)
|
|
39
|
+
return;
|
|
40
|
+
sourceName = selected;
|
|
41
|
+
}
|
|
42
|
+
const sourceConfig = await containerManager.getConfig(sourceName);
|
|
43
|
+
if (!sourceConfig) {
|
|
44
|
+
return exitWithError({
|
|
45
|
+
message: `Container "${sourceName}" not found`,
|
|
46
|
+
json: options.json,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (isRemoteContainer(sourceConfig)) {
|
|
50
|
+
return exitWithError({
|
|
51
|
+
message: 'Cannot branch a linked remote container. Use "spindb backup" to export data, then "spindb restore" to import it locally.',
|
|
52
|
+
json: options.json,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
let branchName = name;
|
|
56
|
+
if (!branchName) {
|
|
57
|
+
if (options.json) {
|
|
58
|
+
return exitWithError({
|
|
59
|
+
message: 'Branch name is required',
|
|
60
|
+
json: true,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const picked = await promptContainerName(`${sourceName}-branch`);
|
|
64
|
+
if (!picked)
|
|
65
|
+
return;
|
|
66
|
+
branchName = picked;
|
|
67
|
+
}
|
|
68
|
+
let port;
|
|
69
|
+
if (options.port !== undefined) {
|
|
70
|
+
port = parseInt(options.port, 10);
|
|
71
|
+
if (Number.isNaN(port) || port <= 0) {
|
|
72
|
+
return exitWithError({
|
|
73
|
+
message: `Invalid port: ${options.port}`,
|
|
74
|
+
json: options.json,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const spinner = options.json
|
|
79
|
+
? null
|
|
80
|
+
: createSpinner(`Branching ${sourceName} → ${branchName}...`);
|
|
81
|
+
spinner?.start();
|
|
82
|
+
const result = await branchManager.createBranch({
|
|
83
|
+
source: sourceName,
|
|
84
|
+
name: branchName,
|
|
85
|
+
start: options.start !== false,
|
|
86
|
+
port,
|
|
87
|
+
});
|
|
88
|
+
const methodNote = result.method === 'reflink' ? ' (copy-on-write)' : '';
|
|
89
|
+
spinner?.succeed(`Created branch "${branchName}" from "${sourceName}"${methodNote}`);
|
|
90
|
+
if (options.json) {
|
|
91
|
+
console.log(JSON.stringify({
|
|
92
|
+
success: true,
|
|
93
|
+
source: sourceName,
|
|
94
|
+
name: branchName,
|
|
95
|
+
engine: result.config.engine,
|
|
96
|
+
port: result.config.port,
|
|
97
|
+
started: result.started,
|
|
98
|
+
method: result.method,
|
|
99
|
+
branchParent: result.config.branchParent,
|
|
100
|
+
connectionString: result.connectionString,
|
|
101
|
+
...(result.warning ? { warning: result.warning } : {}),
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
if (result.warning)
|
|
106
|
+
console.log(uiWarning(result.warning));
|
|
107
|
+
console.log();
|
|
108
|
+
console.log(connectionBox(branchName, result.connectionString, result.config.port));
|
|
109
|
+
console.log();
|
|
110
|
+
if (!result.started) {
|
|
111
|
+
console.log(chalk.gray(' Start the branch:'));
|
|
112
|
+
console.log(chalk.cyan(` spindb start ${branchName}`));
|
|
113
|
+
console.log();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return exitWithError({
|
|
119
|
+
message: error.message,
|
|
120
|
+
json: options.json,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// ---- branch list ----
|
|
125
|
+
branchCommand
|
|
126
|
+
.command('list')
|
|
127
|
+
.description('Show the branch lineage tree')
|
|
128
|
+
.option('-j, --json', 'Output as JSON')
|
|
129
|
+
.action(async (options) => {
|
|
130
|
+
try {
|
|
131
|
+
const tree = await branchManager.getBranchTree();
|
|
132
|
+
if (options.json) {
|
|
133
|
+
console.log(JSON.stringify(tree, null, 2));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (tree.length === 0) {
|
|
137
|
+
console.log(uiWarning('No containers found. Create one with: spindb create'));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
console.log();
|
|
141
|
+
console.log(header('Branch tree'));
|
|
142
|
+
renderBranchTree(tree, '');
|
|
143
|
+
console.log();
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
return exitWithError({
|
|
147
|
+
message: error.message,
|
|
148
|
+
json: options.json,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
// ---- branch delete ----
|
|
153
|
+
branchCommand
|
|
154
|
+
.command('delete <name>')
|
|
155
|
+
.description('Delete a branch (use --cascade to also delete its child branches)')
|
|
156
|
+
.option('--cascade', 'Also delete all child branches')
|
|
157
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
158
|
+
.option('-j, --json', 'Output result as JSON')
|
|
159
|
+
.action(async (name, options) => {
|
|
160
|
+
try {
|
|
161
|
+
const config = await containerManager.getConfig(name);
|
|
162
|
+
if (!config) {
|
|
163
|
+
return exitWithError({
|
|
164
|
+
message: `Container "${name}" not found`,
|
|
165
|
+
json: options.json,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (!options.json && !options.force) {
|
|
169
|
+
const children = await branchManager.childrenOf(name);
|
|
170
|
+
const message = children.length > 0 && options.cascade
|
|
171
|
+
? `Delete branch "${name}" and its ${children.length} child branch(es)?`
|
|
172
|
+
: `Delete branch "${name}"?`;
|
|
173
|
+
const confirmed = await promptConfirm(message, false);
|
|
174
|
+
if (!confirmed) {
|
|
175
|
+
console.log(chalk.gray('Cancelled'));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const spinner = options.json
|
|
180
|
+
? null
|
|
181
|
+
: createSpinner(`Deleting ${name}...`);
|
|
182
|
+
spinner?.start();
|
|
183
|
+
const result = await branchManager.deleteBranch(name, {
|
|
184
|
+
cascade: options.cascade,
|
|
185
|
+
});
|
|
186
|
+
spinner?.succeed(result.deleted.length === 1
|
|
187
|
+
? `Deleted "${name}"`
|
|
188
|
+
: `Deleted ${result.deleted.length} branches`);
|
|
189
|
+
if (options.json) {
|
|
190
|
+
console.log(JSON.stringify({ success: true, deleted: result.deleted }));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
return exitWithError({
|
|
195
|
+
message: error.message,
|
|
196
|
+
json: options.json,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
// ---- branch reset ----
|
|
201
|
+
branchCommand
|
|
202
|
+
.command('reset <name>')
|
|
203
|
+
.description("Discard a branch's changes and re-fork from its parent's current state")
|
|
204
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
205
|
+
.option('-j, --json', 'Output result as JSON')
|
|
206
|
+
.action(async (name, options) => {
|
|
207
|
+
try {
|
|
208
|
+
const config = await containerManager.getConfig(name);
|
|
209
|
+
if (!config) {
|
|
210
|
+
return exitWithError({
|
|
211
|
+
message: `Container "${name}" not found`,
|
|
212
|
+
json: options.json,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (!config.branchParent) {
|
|
216
|
+
return exitWithError({
|
|
217
|
+
message: `"${name}" is not a branch (no parent to reset from).`,
|
|
218
|
+
json: options.json,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (!options.json && !options.force) {
|
|
222
|
+
const confirmed = await promptConfirm(`Reset branch "${name}" to match "${config.branchParent}"? This discards all changes in the branch.`, false);
|
|
223
|
+
if (!confirmed) {
|
|
224
|
+
console.log(chalk.gray('Cancelled'));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const spinner = options.json
|
|
229
|
+
? null
|
|
230
|
+
: createSpinner(`Resetting ${name}...`);
|
|
231
|
+
spinner?.start();
|
|
232
|
+
const result = await branchManager.resetBranch(name);
|
|
233
|
+
spinner?.succeed(`Reset "${name}" to "${config.branchParent}"`);
|
|
234
|
+
if (options.json) {
|
|
235
|
+
console.log(JSON.stringify({
|
|
236
|
+
success: true,
|
|
237
|
+
name,
|
|
238
|
+
branchParent: result.config.branchParent,
|
|
239
|
+
method: result.method,
|
|
240
|
+
started: result.started,
|
|
241
|
+
connectionString: result.connectionString,
|
|
242
|
+
...(result.warning ? { warning: result.warning } : {}),
|
|
243
|
+
}));
|
|
244
|
+
}
|
|
245
|
+
else if (result.warning) {
|
|
246
|
+
console.log(uiWarning(result.warning));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
return exitWithError({
|
|
251
|
+
message: error.message,
|
|
252
|
+
json: options.json,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
// ---- branch rename ----
|
|
257
|
+
branchCommand
|
|
258
|
+
.command('rename <oldName> <newName>')
|
|
259
|
+
.description('Rename a branch (repoints its children to the new name)')
|
|
260
|
+
.option('-j, --json', 'Output result as JSON')
|
|
261
|
+
.action(async (oldName, newName, options) => {
|
|
262
|
+
try {
|
|
263
|
+
const spinner = options.json
|
|
264
|
+
? null
|
|
265
|
+
: createSpinner(`Renaming ${oldName} → ${newName}...`);
|
|
266
|
+
spinner?.start();
|
|
267
|
+
const config = await branchManager.renameBranch(oldName, newName);
|
|
268
|
+
spinner?.succeed(`Renamed "${oldName}" to "${newName}"`);
|
|
269
|
+
if (options.json) {
|
|
270
|
+
console.log(JSON.stringify({
|
|
271
|
+
success: true,
|
|
272
|
+
oldName,
|
|
273
|
+
newName,
|
|
274
|
+
engine: config.engine,
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
return exitWithError({
|
|
280
|
+
message: error.message,
|
|
281
|
+
json: options.json,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
// ---- branch info ----
|
|
286
|
+
branchCommand
|
|
287
|
+
.command('info <name>')
|
|
288
|
+
.description("Show a branch's lineage (parent and children)")
|
|
289
|
+
.option('-j, --json', 'Output as JSON')
|
|
290
|
+
.action(async (name, options) => {
|
|
291
|
+
try {
|
|
292
|
+
const info = await branchManager.getBranchInfo(name);
|
|
293
|
+
if (options.json) {
|
|
294
|
+
console.log(JSON.stringify({
|
|
295
|
+
name: info.config.name,
|
|
296
|
+
engine: info.config.engine,
|
|
297
|
+
port: info.config.port,
|
|
298
|
+
status: info.config.status,
|
|
299
|
+
branchParent: info.parent,
|
|
300
|
+
branchedAt: info.config.branchedAt,
|
|
301
|
+
gitBranch: info.config.gitBranch,
|
|
302
|
+
children: info.children,
|
|
303
|
+
}, null, 2));
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
console.log();
|
|
307
|
+
console.log(header(`Branch: ${name}`));
|
|
308
|
+
console.log(keyValue('Engine', info.config.engine));
|
|
309
|
+
if (info.parent)
|
|
310
|
+
console.log(keyValue('Branched from', info.parent));
|
|
311
|
+
if (info.config.branchedAt) {
|
|
312
|
+
console.log(keyValue('Branched at', info.config.branchedAt));
|
|
313
|
+
}
|
|
314
|
+
if (info.config.gitBranch) {
|
|
315
|
+
console.log(keyValue('Git branch', info.config.gitBranch));
|
|
316
|
+
}
|
|
317
|
+
console.log(keyValue('Children', info.children.length > 0 ? info.children.join(', ') : '(none)'));
|
|
318
|
+
console.log();
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
return exitWithError({
|
|
322
|
+
message: error.message,
|
|
323
|
+
json: options.json,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
/**
|
|
328
|
+
* Render the branch forest as an indented tree. Roots have no glyph; children
|
|
329
|
+
* are drawn with ├─ / └─ connectors.
|
|
330
|
+
*/
|
|
331
|
+
// ---- git-driven branching ----
|
|
332
|
+
branchCommand
|
|
333
|
+
.command('init [base]')
|
|
334
|
+
.description('Set up git-driven branching for this repo (writes .spindb/branch.json + installs a post-checkout hook)')
|
|
335
|
+
.option('-j, --json', 'Output result as JSON')
|
|
336
|
+
.action(async (base, options) => {
|
|
337
|
+
try {
|
|
338
|
+
let baseContainer = base;
|
|
339
|
+
if (!baseContainer) {
|
|
340
|
+
if (options.json) {
|
|
341
|
+
return exitWithError({
|
|
342
|
+
message: 'Base container name is required',
|
|
343
|
+
json: true,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
const containers = await containerManager.list();
|
|
347
|
+
const eligible = containers.filter((c) => !isRemoteContainer(c) && c.status !== 'linked' && c.port > 0);
|
|
348
|
+
if (eligible.length === 0) {
|
|
349
|
+
console.log(uiWarning('No server-based containers found. Create one with: spindb create'));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const selected = await promptContainerSelect(eligible, 'Select the base container for this repo:');
|
|
353
|
+
if (!selected)
|
|
354
|
+
return;
|
|
355
|
+
baseContainer = selected;
|
|
356
|
+
}
|
|
357
|
+
const { repoRoot, config } = await initRepo({ baseContainer });
|
|
358
|
+
if (options.json) {
|
|
359
|
+
console.log(JSON.stringify({
|
|
360
|
+
success: true,
|
|
361
|
+
repoRoot,
|
|
362
|
+
baseContainer: config.baseContainer,
|
|
363
|
+
stablePort: config.stablePort,
|
|
364
|
+
mainBranch: config.mainBranch,
|
|
365
|
+
hooksInstalled: true,
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
console.log(uiSuccess('Git branching enabled for this repo'));
|
|
370
|
+
console.log(chalk.gray(' Base container: ') + chalk.cyan(config.baseContainer));
|
|
371
|
+
console.log(chalk.gray(' Stable port: ') +
|
|
372
|
+
chalk.green(String(config.stablePort)) +
|
|
373
|
+
chalk.gray(' (your DATABASE_URL never changes)'));
|
|
374
|
+
console.log(chalk.gray(' Main branch: ') + chalk.cyan(config.mainBranch));
|
|
375
|
+
console.log();
|
|
376
|
+
console.log(chalk.gray(' Switch git branches and the matching database follows automatically.'));
|
|
377
|
+
console.log(chalk.gray(' Tip: commit .spindb/branch.json to share it; ') +
|
|
378
|
+
chalk.gray('teammates run ') +
|
|
379
|
+
chalk.cyan('spindb branch hooks install'));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
return exitWithError({
|
|
384
|
+
message: error.message,
|
|
385
|
+
json: options.json,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
branchCommand
|
|
390
|
+
.command('sync')
|
|
391
|
+
.description('Swap the active database branch to match the current git branch')
|
|
392
|
+
.option('--git-checkout', 'Invoked from the post-checkout hook (quieter)')
|
|
393
|
+
.option('-j, --json', 'Output result as JSON')
|
|
394
|
+
.action(async (options) => {
|
|
395
|
+
try {
|
|
396
|
+
const result = await gitSync({ fromHook: options.gitCheckout });
|
|
397
|
+
if (options.json) {
|
|
398
|
+
console.log(JSON.stringify({ success: true, ...result }));
|
|
399
|
+
}
|
|
400
|
+
else if (!options.gitCheckout) {
|
|
401
|
+
const what = result.isBase
|
|
402
|
+
? `base "${result.container}"`
|
|
403
|
+
: `branch "${result.container}"`;
|
|
404
|
+
console.log(uiSuccess(`Active database is now ${what}${result.created ? ' (created)' : ''}`));
|
|
405
|
+
console.log(chalk.gray(' ') + chalk.cyan(result.connectionString));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
return exitWithError({
|
|
410
|
+
message: error.message,
|
|
411
|
+
json: options.json,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
branchCommand
|
|
416
|
+
.command('status')
|
|
417
|
+
.description('Show git-branching config and the active database branch')
|
|
418
|
+
.option('-j, --json', 'Output as JSON')
|
|
419
|
+
.action(async (options) => {
|
|
420
|
+
try {
|
|
421
|
+
const st = await gitStatus({});
|
|
422
|
+
if (!st) {
|
|
423
|
+
if (options.json) {
|
|
424
|
+
console.log(JSON.stringify({ configured: false }));
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
console.log(uiWarning('Git branching is not set up here. Run: spindb branch init --base <container>'));
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (options.json) {
|
|
431
|
+
console.log(JSON.stringify({ configured: true, ...st }));
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
console.log();
|
|
435
|
+
console.log(header('Git branching'));
|
|
436
|
+
console.log(keyValue('Base', st.config.baseContainer));
|
|
437
|
+
console.log(keyValue('Stable port', String(st.config.stablePort)));
|
|
438
|
+
console.log(keyValue('Main branch', st.config.mainBranch));
|
|
439
|
+
console.log(keyValue('Current branch', st.gitBranch));
|
|
440
|
+
console.log(keyValue('Maps to', st.target));
|
|
441
|
+
console.log(keyValue('Active now', st.active ?? '(none running)'));
|
|
442
|
+
console.log(keyValue('Hook installed', st.hooksInstalled ? 'yes' : 'no'));
|
|
443
|
+
console.log();
|
|
444
|
+
}
|
|
445
|
+
catch (error) {
|
|
446
|
+
return exitWithError({
|
|
447
|
+
message: error.message,
|
|
448
|
+
json: options.json,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
branchCommand
|
|
453
|
+
.command('prune')
|
|
454
|
+
.description('Delete database branches whose git branch no longer exists')
|
|
455
|
+
.option('-j, --json', 'Output as JSON')
|
|
456
|
+
.action(async (options) => {
|
|
457
|
+
try {
|
|
458
|
+
const spinner = options.json
|
|
459
|
+
? null
|
|
460
|
+
: createSpinner('Pruning orphaned branches...');
|
|
461
|
+
spinner?.start();
|
|
462
|
+
const { deleted } = await gitPrune({});
|
|
463
|
+
spinner?.succeed(deleted.length > 0
|
|
464
|
+
? `Pruned ${deleted.length} branch(es)`
|
|
465
|
+
: 'Nothing to prune');
|
|
466
|
+
if (options.json) {
|
|
467
|
+
console.log(JSON.stringify({ success: true, deleted }));
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
for (const name of deleted) {
|
|
471
|
+
console.log(chalk.gray(' removed ') + name);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
return exitWithError({
|
|
477
|
+
message: error.message,
|
|
478
|
+
json: options.json,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
branchCommand
|
|
483
|
+
.command('hooks <action>')
|
|
484
|
+
.description('Install or uninstall the git post-checkout hook (action: install | uninstall)')
|
|
485
|
+
.option('-j, --json', 'Output as JSON')
|
|
486
|
+
.action(async (action, options) => {
|
|
487
|
+
try {
|
|
488
|
+
if (action !== 'install' && action !== 'uninstall') {
|
|
489
|
+
return exitWithError({
|
|
490
|
+
message: `Unknown action "${action}". Use "install" or "uninstall".`,
|
|
491
|
+
json: options.json,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
const repoRoot = await findRepoRoot();
|
|
495
|
+
if (!repoRoot) {
|
|
496
|
+
return exitWithError({
|
|
497
|
+
message: 'Not a git repository.',
|
|
498
|
+
json: options.json,
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
if (action === 'install') {
|
|
502
|
+
await installHooks(repoRoot);
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
await uninstallHooks(repoRoot);
|
|
506
|
+
}
|
|
507
|
+
if (options.json) {
|
|
508
|
+
console.log(JSON.stringify({ success: true, action }));
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
console.log(uiSuccess(`post-checkout hook ${action === 'install' ? 'installed' : 'removed'}`));
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
catch (error) {
|
|
515
|
+
return exitWithError({
|
|
516
|
+
message: error.message,
|
|
517
|
+
json: options.json,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
function renderBranchTree(nodes, prefix) {
|
|
522
|
+
nodes.forEach((node, index) => {
|
|
523
|
+
const isLast = index === nodes.length - 1;
|
|
524
|
+
const connector = prefix === '' ? '' : isLast ? '└─ ' : '├─ ';
|
|
525
|
+
const statusBadge = node.status === 'running'
|
|
526
|
+
? theme.running
|
|
527
|
+
: node.status === 'created'
|
|
528
|
+
? theme.created
|
|
529
|
+
: theme.stopped;
|
|
530
|
+
const portStr = node.port ? chalk.gray(` :${node.port}`) : '';
|
|
531
|
+
const gitTag = node.gitBranch ? chalk.magenta(` ⎇ ${node.gitBranch}`) : '';
|
|
532
|
+
console.log(`${prefix}${connector}${chalk.cyan(node.name)} ${chalk.gray(node.engine)}${portStr} ${statusBadge}${gitTag}`);
|
|
533
|
+
const childPrefix = prefix === '' ? ' ' : prefix + (isLast ? ' ' : '│ ');
|
|
534
|
+
renderBranchTree(node.children, childPrefix);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
//# sourceMappingURL=branch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch.js","sourceRoot":"","sources":["../../../cli/commands/branch.ts"],"names":[],"mappings":"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"}
|
|
@@ -134,6 +134,21 @@ async function displayContainerInfo(config, options) {
|
|
|
134
134
|
chalk.white('Cloned From:'.padEnd(14)) +
|
|
135
135
|
chalk.gray(config.clonedFrom));
|
|
136
136
|
}
|
|
137
|
+
if (config.branchParent) {
|
|
138
|
+
console.log(chalk.gray(' ') +
|
|
139
|
+
chalk.white('Branched From:'.padEnd(14)) +
|
|
140
|
+
chalk.gray(config.branchParent));
|
|
141
|
+
}
|
|
142
|
+
if (config.branchedAt) {
|
|
143
|
+
console.log(chalk.gray(' ') +
|
|
144
|
+
chalk.white('Branched At:'.padEnd(14)) +
|
|
145
|
+
chalk.gray(formatDate(config.branchedAt)));
|
|
146
|
+
}
|
|
147
|
+
if (config.gitBranch) {
|
|
148
|
+
console.log(chalk.gray(' ') +
|
|
149
|
+
chalk.white('Git Branch:'.padEnd(14)) +
|
|
150
|
+
chalk.magenta(config.gitBranch));
|
|
151
|
+
}
|
|
137
152
|
console.log();
|
|
138
153
|
console.log(chalk.gray(' ') + chalk.white('Connection String:'));
|
|
139
154
|
console.log(chalk.gray(' ') + chalk.cyan(connectionString));
|