worktree-flow 0.0.15 → 0.0.16

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.
@@ -13,6 +13,40 @@ export function formatRepoStatusLine(repoName, status, baseBranch) {
13
13
  : chalk.dim(' (no upstream)');
14
14
  return ` ${indicator} ${chalk.yellow(repoName)}: ${message}${trackingInfo}`;
15
15
  }
16
+ /**
17
+ * Render Phase 1: print a header and workspace rows with a "fetching..." indicator.
18
+ * Returns the number of lines printed so the caller can clear them later.
19
+ */
20
+ export function logStatusFetching(header, workspaces, console) {
21
+ console.log(chalk.bold(`\n${header}`));
22
+ for (const ws of workspaces) {
23
+ const repoCount = chalk.dim(`(${ws.repoCount} repo${ws.repoCount === 1 ? '' : 's'})`);
24
+ console.log(` ${chalk.cyan(ws.name)} ${repoCount} ${chalk.dim('fetching...')}`);
25
+ }
26
+ console.log('');
27
+ // blank line + header + N workspace lines + trailing blank
28
+ return workspaces.length + 3;
29
+ }
30
+ /**
31
+ * Render Phase 2: clear the Phase 1 lines then print the header and full workspace status.
32
+ */
33
+ export function logStatus(header, workspaces, linesToClear, getBaseBranch, console) {
34
+ for (let i = 0; i < linesToClear; i++) {
35
+ console.write('\x1b[1A'); // Move cursor up one line
36
+ console.write('\x1b[2K'); // Clear entire line
37
+ }
38
+ console.log(chalk.bold(`\n${header}`));
39
+ for (const workspace of workspaces) {
40
+ const activeIndicator = workspace.isActive ? chalk.green('* ') : ' ';
41
+ const repoCount = chalk.dim(`(${workspace.repoCount} repo${workspace.repoCount === 1 ? '' : 's'})`);
42
+ console.log(`${activeIndicator}${chalk.cyan(workspace.name)} ${repoCount}`);
43
+ for (const { repoName, status } of workspace.statuses) {
44
+ const baseBranch = getBaseBranch(workspace.path, repoName);
45
+ console.log(formatRepoStatusLine(repoName, status, baseBranch));
46
+ }
47
+ console.log('');
48
+ }
49
+ }
16
50
  /**
17
51
  * Get a human-readable status indicator for a workspace based on its worktree statuses.
18
52
  */
@@ -1,7 +1,6 @@
1
- import chalk from 'chalk';
2
1
  import { createServices } from '../lib/services.js';
3
2
  import { createUseCases } from '../usecases/usecases.js';
4
- import { formatRepoStatusLine } from './helpers.js';
3
+ import { logStatusFetching, logStatus } from './helpers.js';
5
4
  export async function runList(useCases, services) {
6
5
  const { destPath, sourcePath } = services.config.getRequired();
7
6
  const config = services.config.load();
@@ -13,12 +12,7 @@ export async function runList(useCases, services) {
13
12
  return;
14
13
  }
15
14
  // Phase 1: Show basic list immediately
16
- services.console.log(chalk.bold('\nWorkspaces:'));
17
- for (const workspace of basicWorkspaces) {
18
- const repoCount = chalk.dim(`(${workspace.repoCount} repo${workspace.repoCount === 1 ? '' : 's'})`);
19
- services.console.log(` ${chalk.cyan(workspace.name)} ${repoCount} ${chalk.dim('fetching...')}`);
20
- }
21
- services.console.log('');
15
+ const loadingLines = logStatusFetching('Workspaces:', basicWorkspaces, services.console);
22
16
  // Phase 2: Fetch repos used across all workspaces
23
17
  await useCases.fetchUsedRepos.execute({
24
18
  destPath,
@@ -32,32 +26,8 @@ export async function runList(useCases, services) {
32
26
  sourcePath,
33
27
  cwd,
34
28
  });
35
- // Phase 4: Clear previous output and re-print with status
36
- // Lines to clear:
37
- // - 2 lines from '\nWorkspaces:' (blank line + header)
38
- // - N workspace lines
39
- // - 1 empty line after workspaces
40
- const linesToClear = 2 + basicWorkspaces.length + 1;
41
- for (let i = 0; i < linesToClear; i++) {
42
- services.console.write('\x1b[1A'); // Move cursor up one line
43
- services.console.write('\x1b[2K'); // Clear entire line
44
- }
45
- // Re-print with full status information
46
- services.console.log(chalk.bold('\nWorkspaces:'));
47
- for (const workspace of result.workspaces) {
48
- const activeIndicator = workspace.isActive ? chalk.green('* ') : ' ';
49
- const repoCount = chalk.dim(`(${workspace.repoCount} repo${workspace.repoCount === 1 ? '' : 's'})`);
50
- services.console.log(`${activeIndicator}${chalk.cyan(workspace.name)} ${repoCount}`);
51
- // Load workspace config to get per-repo base branches
52
- const workspaceConfig = services.workspaceConfig.load(workspace.path);
53
- const getBaseBranch = (repoName) => workspaceConfig.baseBranches[repoName] || 'master';
54
- // Display each repo with its status and tracking branch
55
- for (const { repoName, status } of workspace.statuses) {
56
- const baseBranch = getBaseBranch(repoName);
57
- services.console.log(formatRepoStatusLine(repoName, status, baseBranch));
58
- }
59
- services.console.log(''); // Blank line between workspaces
60
- }
29
+ // Phase 4: Clear previous output and re-print with full status
30
+ logStatus('Workspaces:', result.workspaces, loadingLines, (wsPath, repoName) => services.workspaceConfig.load(wsPath).baseBranches[repoName] || 'master', services.console);
61
31
  }
62
32
  export function registerListCommand(program) {
63
33
  program
@@ -1,47 +1,35 @@
1
- import chalk from 'chalk';
1
+ import path from 'node:path';
2
2
  import { createServices } from '../lib/services.js';
3
3
  import { createUseCases } from '../usecases/usecases.js';
4
- import { StatusService } from '../lib/status.js';
5
4
  import { resolveWorkspace } from '../lib/workspaceResolver.js';
6
- import { formatRepoStatusLine } from './helpers.js';
5
+ import { logStatusFetching, logStatus } from './helpers.js';
7
6
  export async function runStatus(branchName, useCases, services) {
8
7
  const { sourcePath } = services.config.getRequired();
9
8
  const config = services.config.load();
10
9
  const { workspacePath } = resolveWorkspace(branchName, services.workspaceDir, services.config, services.process);
11
- services.console.log(`Workspace: ${chalk.cyan(workspacePath)}`);
12
10
  const worktreeDirs = services.workspaceDir.getWorktreeDirs(workspacePath);
13
11
  if (worktreeDirs.length === 0) {
14
12
  services.console.log('\nNo worktrees found in workspace.');
15
13
  return;
16
14
  }
15
+ const workspaceName = path.basename(workspacePath);
16
+ const repoCount = worktreeDirs.length;
17
+ // Phase 1: Show header with fetching indicator
18
+ const loadingLines = logStatusFetching('Workspace:', [{ name: workspaceName, repoCount }], services.console);
17
19
  // Fetch workspace repos
18
20
  await useCases.fetchWorkspaceRepos.execute({
19
21
  workspacePath,
20
22
  sourcePath,
21
23
  fetchCacheTtlSeconds: config.fetchCacheTtlSeconds,
24
+ silent: true,
22
25
  });
23
- services.console.log('');
24
- services.console.log(`\nStatus:\n`);
25
26
  const result = await useCases.checkWorkspaceStatus.execute({
26
27
  workspacePath,
27
28
  });
28
29
  // Load workspace config to get per-repo base branches
29
30
  const workspaceConfig = services.workspaceConfig.load(workspacePath);
30
- const getBaseBranch = (repoName) => workspaceConfig.baseBranches[repoName] || 'master';
31
- let cleanCount = 0;
32
- let issuesCount = 0;
33
- for (const { repoName, status } of result.statuses) {
34
- const baseBranch = getBaseBranch(repoName);
35
- services.console.log(formatRepoStatusLine(repoName, status, baseBranch));
36
- if (StatusService.hasIssues(status)) {
37
- issuesCount++;
38
- }
39
- else {
40
- cleanCount++;
41
- }
42
- }
43
- services.console.log('');
44
- services.console.log(`Summary: ${chalk.green(`${cleanCount} up to date`)}, ${issuesCount > 0 ? chalk.red(`${issuesCount} with issues`) : chalk.green('0 with issues')}`);
31
+ // Phase 2: Clear Phase 1 lines and re-render with full status
32
+ logStatus('Workspace:', [{ name: workspaceName, path: workspacePath, repoCount, isActive: false, statuses: result.statuses }], loadingLines, (_, repoName) => workspaceConfig.baseBranches[repoName] || 'master', services.console);
45
33
  }
46
34
  export function registerStatusCommand(program) {
47
35
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worktree-flow",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Manage git worktrees across a poly-repo environment",
5
5
  "type": "module",
6
6
  "bin": {