Summary
vcspull sync --workspace <path> --all can hang indefinitely when syncing large batches of repositories. The sync loop is sequential with no subprocess timeouts and no protection against git blocking on stdin for credential prompts.
Reproduction
$ vcspull sync --workspace ~/study/rust/ --all
With a workspace containing ~60+ repos, sync completes the first several repos then hangs indefinitely on a repo that either:
- Needs SSH credentials (git waits on stdin)
- Has a very large
.git directory (e.g. rust-lang/rust at 15GB)
- Has a malformed URL causing protocol negotiation to stall
Root cause
- No subprocess timeout —
subprocess.run() in _maybe_fetch() (cli/sync.py) has no timeout parameter. libvcs update_repo() calls also lack timeouts.
- No
GIT_TERMINAL_PROMPT=0 — git can prompt for credentials on stdin, blocking the entire process with no visible indication.
- Sequential sync loop — repos are synced one-by-one; one hanging repo blocks all subsequent repos.
Proposed fix
1. Set GIT_TERMINAL_PROMPT=0 during batch sync
os.environ.setdefault("GIT_TERMINAL_PROMPT", "0")
At the start of sync(), prevent git from blocking on credential prompts. Uses setdefault so users can override with GIT_TERMINAL_PROMPT=1 if desired. This is the highest-impact fix — git fails fast instead of hanging.
2. Add timeout to _maybe_fetch
result = subprocess.run(
["git", "fetch", "--prune"],
cwd=repo_path,
capture_output=True,
text=True,
check=False,
timeout=120,
env=_get_no_prompt_env(),
)
Catch subprocess.TimeoutExpired and return a meaningful error instead of blocking forever.
3. Future: --timeout CLI flag
Allow users to configure the per-repo timeout for sync operations. Would need to be threaded through to libvcs calls.
Files affected
src/vcspull/cli/sync.py — _maybe_fetch(), sync(), update_repo()
Summary
vcspull sync --workspace <path> --allcan hang indefinitely when syncing large batches of repositories. The sync loop is sequential with no subprocess timeouts and no protection against git blocking on stdin for credential prompts.Reproduction
$ vcspull sync --workspace ~/study/rust/ --allWith a workspace containing ~60+ repos, sync completes the first several repos then hangs indefinitely on a repo that either:
.gitdirectory (e.g. rust-lang/rust at 15GB)Root cause
subprocess.run()in_maybe_fetch()(cli/sync.py) has notimeoutparameter. libvcsupdate_repo()calls also lack timeouts.GIT_TERMINAL_PROMPT=0— git can prompt for credentials on stdin, blocking the entire process with no visible indication.Proposed fix
1. Set
GIT_TERMINAL_PROMPT=0during batch syncAt the start of
sync(), prevent git from blocking on credential prompts. Usessetdefaultso users can override withGIT_TERMINAL_PROMPT=1if desired. This is the highest-impact fix — git fails fast instead of hanging.2. Add timeout to
_maybe_fetchCatch
subprocess.TimeoutExpiredand return a meaningful error instead of blocking forever.3. Future:
--timeoutCLI flagAllow users to configure the per-repo timeout for sync operations. Would need to be threaded through to libvcs calls.
Files affected
src/vcspull/cli/sync.py—_maybe_fetch(),sync(),update_repo()