Skip to content

feat(update): add overall progress bar with per-task spinners#11

Merged
TrekMax merged 10 commits into
mainfrom
feat/progress-bar
Apr 10, 2026
Merged

feat(update): add overall progress bar with per-task spinners#11
TrekMax merged 10 commits into
mainfrom
feat/progress-bar

Conversation

@TrekMax
Copy link
Copy Markdown
Owner

@TrekMax TrekMax commented Apr 10, 2026

Summary

  • Replace per-project spinners (59 lines of output) with a clean progress UI
  • Overall progress bar: [######----] 32/59 updating...
  • Active task spinners shown below the bar (max 8 concurrent)
  • Spinners auto-clear on success, persist with error message on failure
  • Overall bar clears after completion, leaving only the summary line

Before

⠋ arcs-sdk: cloning...
⠋ freertos: cloning...
⠋ cjson: done
⠋ cpr: done
... (59 lines)

After

[################--------------] 32/59 updating...
  ⠋ arcs-sdk: cloning...
  ⠋ freertos: fetching...
  ⠋ libpng: checking out main...

updated 59 projects

Test plan

  • All existing tests pass
  • Verified with 59-project workspace (arcs-sdk)

🤖 Generated with Claude Code

TrekMax and others added 2 commits April 10, 2026 08:49
When projects have nested paths (e.g. arcs-sdk and arcs-sdk/modules/x),
concurrent clones can create parent directories before the parent
project itself is cloned, causing git clone to fail. Now automatically
falls back to init+fetch when clone fails and the directory exists.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 59 individual spinners with a clean progress UI:
- Top-level bar showing [##---] pos/total updating...
- Per-task spinners below the bar (cloning/fetching/checking out)
- Spinners auto-clear on success, persist on failure
- Overall bar clears when all tasks complete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 10, 2026 01:04
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates east-cli update output to use a cleaner progress UI: a single overall progress bar with up to 8 concurrent per-project status spinners, reducing noisy multi-line output in large workspaces.

Changes:

  • Add a top-level overall progress bar showing {pos}/{len} update completion.
  • Insert per-project spinner progress indicators below the overall bar and clear them on success.
  • Add a clone fallback path that attempts init_and_fetch when a concurrent operation creates the destination directory mid-clone.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/east-cli/src/main.rs Outdated
Comment on lines +238 to +239
let pb = mp.insert_after(&overall, ProgressBar::new_spinner());
pb.set_style(spinner_style.clone());
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per-task ProgressBar::new_spinner() never calls tick() or enable_steady_tick(...), so the spinner glyph will stay static (and may not render as intended) until some other redraw happens. Consider enabling a steady tick for these spinners (bounded by MAX_CONCURRENT_GIT), or explicitly ticking on state updates so the UI matches the intended “spinner” behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +269 to +275
let clone_result = Git::clone(url, &project_path, revision.as_deref()).await;
if clone_result.is_err() && project_path.exists() {
pb.set_message(format!("{project_name}: initializing (fallback)..."));
Git::init_and_fetch(url, &project_path, revision.as_deref()).await
} else {
clone_result
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clone fallback triggers on any clone error as long as project_path.exists() afterward. Since git clone often creates the destination directory even when failing (e.g., auth/network failures), this can replace the original error with an init_and_fetch failure (e.g., remote origin already exists) and make debugging harder. Restrict the fallback to the specific “destination exists / not empty” failure mode (e.g., by inspecting the error’s stderr), or re-check that the destination is still a non-repo directory before falling back.

Copilot uses AI. Check for mistakes.
TrekMax and others added 8 commits April 10, 2026 09:14
When a project has uncommitted changes, east update now skips the
checkout step and warns the user instead of failing. The --force
flag overrides this safety check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When project paths are nested (e.g. arcs-sdk contains arcs-sdk/modules/xxx),
automatically add child project paths to the parent's .git/info/exclude.
This prevents child directories from showing as untracked in the parent
repo's git status, which is especially useful when migrating from
git submodules to east manifest management.

The managed block is clearly marked and idempotent — re-running
east update will update the block without duplicating entries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Display the relative path alongside the project name so users can
quickly locate the affected project directory.

Before: cat: skipped checkout (uncommitted changes, ...)
After:  cat (arcs-sdk/modules/cAT): skipped checkout (uncommitted changes, ...)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow specifying project names with --force to selectively override
dirty checkout protection:

  east update --force              # force all projects
  east update --force cat arcs-sdk # force only named projects

Unknown project names are rejected with a clear error message.
Add Git::force_checkout() for checkout -f. Add 4 integration tests
covering dirty skip, per-project force, global force, and unknown
project validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Windows git checkout converts \n to \r\n, causing exact string
comparison to fail. Use contains() for cross-platform compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only fallback to init+fetch when git clone fails specifically because
the destination already exists and is not a git repo. Other failures
(auth, network, etc.) now propagate the original error directly,
making debugging easier.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without steady tick, spinner glyphs stay static. Enable 100ms tick
interval so the animation renders correctly during git operations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add spinners to MultiProgress only after acquiring semaphore permit,
  preventing empty spinner lines for queued tasks
- Match both "already exists" and "File exists" in clone fallback to
  handle different git error message formats across platforms

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@TrekMax TrekMax merged commit 58b8389 into main Apr 10, 2026
8 checks passed
@TrekMax TrekMax deleted the feat/progress-bar branch April 10, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants