worktree-flow 0.0.9 → 0.0.10
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 +2 -2
- package/dist/commands/helpers.js +32 -0
- package/dist/commands/list.js +1 -28
- package/dist/commands/prune.js +36 -24
- package/dist/commands/remove.js +1 -1
- package/dist/lib/status.js +0 -1
- package/dist/usecases/createBranchWorkspace.js +1 -1
- package/dist/usecases/removeWorkspace.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,11 +80,11 @@ Fetches all repos before checking status to ensure accurate information. The sta
|
|
|
80
80
|
|
|
81
81
|
### `flow remove <name>`
|
|
82
82
|
|
|
83
|
-
Remove a workspace and all its worktrees. Fetches latest, checks for uncommitted changes
|
|
83
|
+
Remove a workspace and all its worktrees. Fetches latest, checks for uncommitted changes, and prompts for confirmation before removing. Committed changes are safe to remove since they're preserved in git history.
|
|
84
84
|
|
|
85
85
|
### `flow prune` (alias: `clean`)
|
|
86
86
|
|
|
87
|
-
Remove
|
|
87
|
+
Remove workspaces interactively. Shows all workspaces with their status (similar to `flow list`) and lets you select which ones to prune. Only workspaces with no uncommitted changes can be successfully removed.
|
|
88
88
|
|
|
89
89
|
### `flow tmux resume`
|
|
90
90
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/**
|
|
3
|
+
* Get a human-readable status indicator for a workspace based on its worktree statuses.
|
|
4
|
+
*/
|
|
5
|
+
export function getStatusIndicator(workspace) {
|
|
6
|
+
const hasUncommitted = workspace.statuses.some(s => s.status.type === 'uncommitted');
|
|
7
|
+
const hasAhead = workspace.statuses.some(s => s.status.type === 'ahead');
|
|
8
|
+
const hasBehind = workspace.statuses.some(s => s.status.type === 'behind');
|
|
9
|
+
const hasDiverged = workspace.statuses.some(s => s.status.type === 'diverged');
|
|
10
|
+
const hasError = workspace.statuses.some(s => s.status.type === 'error');
|
|
11
|
+
if (hasUncommitted) {
|
|
12
|
+
return chalk.yellow('uncommitted');
|
|
13
|
+
}
|
|
14
|
+
else if (hasDiverged) {
|
|
15
|
+
return chalk.red('diverged');
|
|
16
|
+
}
|
|
17
|
+
else if (hasAhead && hasBehind) {
|
|
18
|
+
return chalk.yellow('ahead');
|
|
19
|
+
}
|
|
20
|
+
else if (hasAhead) {
|
|
21
|
+
return chalk.yellow('ahead');
|
|
22
|
+
}
|
|
23
|
+
else if (hasBehind) {
|
|
24
|
+
return chalk.blue('behind');
|
|
25
|
+
}
|
|
26
|
+
else if (hasError) {
|
|
27
|
+
return chalk.red('error');
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return chalk.green('clean');
|
|
31
|
+
}
|
|
32
|
+
}
|
package/dist/commands/list.js
CHANGED
|
@@ -1,34 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createServices } from '../lib/services.js';
|
|
3
3
|
import { createUseCases } from '../usecases/usecases.js';
|
|
4
|
-
|
|
5
|
-
const hasUncommitted = workspace.statuses.some(s => s.status.type === 'uncommitted');
|
|
6
|
-
const hasAhead = workspace.statuses.some(s => s.status.type === 'ahead');
|
|
7
|
-
const hasBehind = workspace.statuses.some(s => s.status.type === 'behind');
|
|
8
|
-
const hasDiverged = workspace.statuses.some(s => s.status.type === 'diverged');
|
|
9
|
-
const hasError = workspace.statuses.some(s => s.status.type === 'error');
|
|
10
|
-
if (hasUncommitted) {
|
|
11
|
-
return chalk.yellow('uncommitted');
|
|
12
|
-
}
|
|
13
|
-
else if (hasDiverged) {
|
|
14
|
-
return chalk.red('diverged');
|
|
15
|
-
}
|
|
16
|
-
else if (hasAhead && hasBehind) {
|
|
17
|
-
return chalk.yellow('ahead');
|
|
18
|
-
}
|
|
19
|
-
else if (hasAhead) {
|
|
20
|
-
return chalk.yellow('ahead');
|
|
21
|
-
}
|
|
22
|
-
else if (hasBehind) {
|
|
23
|
-
return chalk.blue('behind');
|
|
24
|
-
}
|
|
25
|
-
else if (hasError) {
|
|
26
|
-
return chalk.red('error');
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
return chalk.green('clean');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
4
|
+
import { getStatusIndicator } from './helpers.js';
|
|
32
5
|
export async function runList(useCases, services) {
|
|
33
6
|
const { destPath, sourcePath } = services.config.getRequired();
|
|
34
7
|
const config = services.config.load();
|
package/dist/commands/prune.js
CHANGED
|
@@ -1,43 +1,55 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import checkbox from '@inquirer/checkbox';
|
|
2
3
|
import confirm from '@inquirer/confirm';
|
|
3
4
|
import { createServices } from '../lib/services.js';
|
|
4
5
|
import { createUseCases } from '../usecases/usecases.js';
|
|
6
|
+
import { getStatusIndicator } from './helpers.js';
|
|
5
7
|
export async function runPrune(useCases, services, deps) {
|
|
6
8
|
const { sourcePath, destPath } = services.config.getRequired();
|
|
7
9
|
const config = services.config.load();
|
|
8
|
-
services.
|
|
10
|
+
const cwd = services.process.cwd();
|
|
11
|
+
// Check if workspaces exist
|
|
12
|
+
const basicWorkspaces = services.workspaceDir.listWorkspaces(destPath);
|
|
13
|
+
if (basicWorkspaces.length === 0) {
|
|
14
|
+
services.console.log('No workspaces found.');
|
|
15
|
+
services.process.exit(0);
|
|
16
|
+
}
|
|
9
17
|
// Fetch repos used across all workspaces
|
|
10
18
|
await useCases.fetchUsedRepos.execute({
|
|
11
19
|
destPath,
|
|
12
20
|
sourcePath,
|
|
13
21
|
fetchCacheTtlSeconds: config.fetchCacheTtlSeconds,
|
|
14
22
|
});
|
|
15
|
-
//
|
|
16
|
-
const result = await useCases.
|
|
23
|
+
// Get full status for all workspaces
|
|
24
|
+
const result = await useCases.listWorkspacesWithStatus.execute({
|
|
17
25
|
destPath,
|
|
18
26
|
sourcePath,
|
|
19
|
-
|
|
27
|
+
cwd,
|
|
28
|
+
});
|
|
29
|
+
// Format choices for checkbox prompt
|
|
30
|
+
const choices = result.workspaces.map(workspace => {
|
|
31
|
+
const statusIndicator = getStatusIndicator(workspace);
|
|
32
|
+
const repoCount = chalk.dim(`(${workspace.repoCount} repo${workspace.repoCount === 1 ? '' : 's'})`);
|
|
33
|
+
return {
|
|
34
|
+
name: `${chalk.cyan(workspace.name)} ${repoCount} ${statusIndicator}`,
|
|
35
|
+
value: workspace.name,
|
|
36
|
+
};
|
|
20
37
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
// Let user select workspaces to prune
|
|
39
|
+
const selected = await deps.checkbox({
|
|
40
|
+
message: 'Select workspaces to prune:',
|
|
41
|
+
choices,
|
|
42
|
+
pageSize: 20,
|
|
43
|
+
});
|
|
44
|
+
if (selected.length === 0) {
|
|
45
|
+
services.console.log('No workspaces selected.');
|
|
27
46
|
services.process.exit(0);
|
|
28
47
|
}
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const daysOld = Math.floor((Date.now() - workspace.oldestCommitDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
33
|
-
services.console.log(` ${chalk.cyan(workspace.name)}`);
|
|
34
|
-
services.console.log(` Repos: ${workspace.repoCount}`);
|
|
35
|
-
services.console.log(` Last commit: ${daysOld} days ago`);
|
|
36
|
-
services.console.log(` Status: ${chalk.green('clean')}`);
|
|
37
|
-
services.console.log('');
|
|
38
|
-
}
|
|
48
|
+
// Get full workspace objects for selected items
|
|
49
|
+
const selectedWorkspaces = result.workspaces.filter(w => selected.includes(w.name));
|
|
50
|
+
// Confirm deletion
|
|
39
51
|
const confirmed = await deps.confirm({
|
|
40
|
-
message:
|
|
52
|
+
message: `Are you sure you want to prune ${selected.length} workspace(s)?`,
|
|
41
53
|
default: false,
|
|
42
54
|
});
|
|
43
55
|
if (!confirmed) {
|
|
@@ -48,7 +60,7 @@ export async function runPrune(useCases, services, deps) {
|
|
|
48
60
|
services.console.log('\nPruning workspaces...\n');
|
|
49
61
|
let successCount = 0;
|
|
50
62
|
let errorCount = 0;
|
|
51
|
-
for (const workspace of
|
|
63
|
+
for (const workspace of selectedWorkspaces) {
|
|
52
64
|
try {
|
|
53
65
|
services.console.log(`Removing ${chalk.cyan(workspace.name)}...`);
|
|
54
66
|
await useCases.removeWorkspace.execute({
|
|
@@ -78,12 +90,12 @@ export function registerPruneCommand(program) {
|
|
|
78
90
|
program
|
|
79
91
|
.command('prune')
|
|
80
92
|
.alias('clean')
|
|
81
|
-
.description('
|
|
93
|
+
.description('Select and remove workspaces')
|
|
82
94
|
.action(async () => {
|
|
83
95
|
const services = createServices();
|
|
84
96
|
const useCases = createUseCases(services);
|
|
85
97
|
try {
|
|
86
|
-
await runPrune(useCases, services, { confirm });
|
|
98
|
+
await runPrune(useCases, services, { checkbox, confirm });
|
|
87
99
|
}
|
|
88
100
|
catch (error) {
|
|
89
101
|
services.console.error(error.message);
|
package/dist/commands/remove.js
CHANGED
|
@@ -18,7 +18,7 @@ export async function runRemove(branchName, useCases, services, deps) {
|
|
|
18
18
|
sourcePath,
|
|
19
19
|
fetchCacheTtlSeconds: config.fetchCacheTtlSeconds,
|
|
20
20
|
});
|
|
21
|
-
services.console.log(`\nChecking for uncommitted changes
|
|
21
|
+
services.console.log(`\nChecking for uncommitted changes...`);
|
|
22
22
|
// Load workspace config to get per-repo base branches
|
|
23
23
|
const workspaceConfig = services.workspaceConfig.load(workspacePath);
|
|
24
24
|
const getBaseBranch = (repoName) => workspaceConfig.baseBranches[repoName] || 'master';
|
package/dist/lib/status.js
CHANGED
|
@@ -45,7 +45,7 @@ export class CreateBranchWorkspaceUseCase {
|
|
|
45
45
|
}
|
|
46
46
|
// Track the actual base branch used
|
|
47
47
|
baseBranches[name] = actualBaseBranch;
|
|
48
|
-
await this.worktree.createWorktreeWithBranch(repoPath, worktreeDest, params.branchName, actualBaseBranch);
|
|
48
|
+
await this.worktree.createWorktreeWithBranch(repoPath, worktreeDest, params.branchName, `origin/${actualBaseBranch}`);
|
|
49
49
|
this.worktree.copyConfigFilesToWorktree(repoPath, worktreeDest, params.copyFiles);
|
|
50
50
|
return 'created';
|
|
51
51
|
});
|
|
@@ -39,7 +39,7 @@ export class RemoveWorkspaceUseCase {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
if (issuesFound.length > 0) {
|
|
42
|
-
throw new WorkspaceHasIssuesError(`${issuesFound.length} repo(s) have uncommitted or
|
|
42
|
+
throw new WorkspaceHasIssuesError(`${issuesFound.length} repo(s) have uncommitted changes or errors.`);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
// 2. Remove all worktrees
|