Skip to content

Fix status reporting, unify dry-run JSON schema, support non-git VCS#514

Merged
tony merged 17 commits intomasterfrom
misc-fixes-2026-02-08
Feb 8, 2026
Merged

Fix status reporting, unify dry-run JSON schema, support non-git VCS#514
tony merged 17 commits intomasterfrom
misc-fixes-2026-02-08

Conversation

@tony
Copy link
Copy Markdown
Member

@tony tony commented Feb 8, 2026

Summary

Fixes incorrect repository status counts, standardizes the
sync --dry-run JSON output schema, and improves support for
SVN / Mercurial repositories in status checks and dry-run plans.

Breaking: dry-run JSON schema changed

sync --dry-run --json previously emitted a nested
workspace-grouped object. It now emits a flat array of plan
entries, matching the schema used by sync --json and
status --json. Scripts consuming the old nested format will
need updating.

Status reporting fixes

  • Repositories with no upstream tracking branch were incorrectly
    shown as "up to date" (ahead=0, behind=0 instead of None)
  • Non-git directories (plain folders, SVN/Hg repos) were counted
    as "dirty" in the summary even though their clean state is
    unknown

Sync improvements

  • When multiple glob patterns match the same repo, it is now
    synced only once (deduplicated by path)
  • Non-git repos show UPDATE in dry-run plans instead of
    BLOCKED, since update_repo already supports SVN and Hg
  • update_repo return type corrected from GitSync to
    GitSync | HgSync | SvnSync

Help formatter completeness

  • Added _HelpTheme protocol documenting CPython 3.14+ argparse
    color attributes
  • Completed option classification sets (added -d, -x, -V,
    --fetch, --offline, --verbose, --max-concurrent,
    --name, --url, and others)

Docs

  • Updated README and quickstart sync examples to use --all
    (matching the v1.53.0 CLI change)

Test plan

  • 790 tests pass (including new formatter, status, and
    SVN/Hg sync tests)
  • mypy strict — no errors
  • ruff format and lint — clean

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.54%. Comparing base (bf42d26) to head (4b32b3d).
⚠️ Report is 18 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #514      +/-   ##
==========================================
+ Coverage   80.83%   81.54%   +0.70%     
==========================================
  Files          16       16              
  Lines        2249     2254       +5     
  Branches      471      473       +2     
==========================================
+ Hits         1818     1838      +20     
+ Misses        276      266      -10     
+ Partials      155      150       -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tony tony force-pushed the misc-fixes-2026-02-08 branch from 94b9e19 to 330132f Compare February 8, 2026 14:46
tony added 16 commits February 8, 2026 10:06
why: When no upstream is tracked, ahead/behind stayed at 0, causing
_determine_plan_action to report "up to date" instead of "remote state
unknown."
what:
- Change ahead/behind initialization from 0 to None
- None propagates correctly when upstream is unavailable
- _determine_plan_action already handles None via isinstance check
…matter

why: JSON dry-run output bypassed OutputFormatter, producing a different
schema (nested workspaces) than other commands (flat array) and skipping
centralized output logic.
what:
- Replace sys.stdout.write(json.dumps(...)) with formatter.emit() calls
- JSON and NDJSON dry-run now use the same emit path
- Update test parsing to expect flat JSON array format
- Remove unused json import
…nSync

why: Return type was annotated as GitSync but create_project() returns
GitSync | HgSync | SvnSync. The type:ignore comment masked this.
what:
- Import HgSync and SvnSync from libvcs
- Change return type to union of all VCS sync types
- Add explicit type annotation on create_project result
- Remove type:ignore and TODO comments
- Add isinstance assertions in tests that access git-specific attributes
why: The _theme colorization code hooks into CPython 3.13+ argparse internals
but lacked type documentation and test coverage, leading reviewers to mistakenly
flag it as dead code.
what:
- Add _HelpTheme protocol documenting the argparse theme attributes
- Type _fill_text's getattr with cast to _HelpTheme | None
- Type _colorize_example_line's theme param as _HelpTheme instead of Any
- Update class docstring explaining the CPython integration
- Add tests/cli/test_formatter.py with 11 tests covering:
  - _fill_text with None theme (pre-3.13 fallback)
  - _fill_text with mock theme (colorization active)
  - _fill_text with non-example text (passthrough)
  - Section heading variants
  - Parameterized _colorize_example_line token classification
why: argparse _theme was added in CPython 3.14 (PR #132323), not 3.13.
what:
- Fix docstring references in _HelpTheme and VcspullHelpFormatter
- Fix test comment referencing pre-3.13 path
why: Since v1.53.0 bare `vcspull sync` prints help; needs --all or a pattern.
what:
- Update README.md sync example to use --all
- Update docs/quickstart.md sync examples to use --all
…orkspace_mapping

why: After _emit_plan_output was refactored to stream entries through
formatter.emit(), these methods were dead code only called from their test.
what:
- Remove to_workspace_mapping() and to_json_object() from PlanResult
- Remove test_plan_result_grouping_and_json_output test
- Clean up unused PlanResult import in test file
why: Missing flags caused the formatter to misclassify the next token
when those options appeared in help example lines.
what:
- Add --exit-on-error, -x, --fetch, --long, --offline, --relative-paths,
  --show-unchanged, --summary-only, --version, -V, --no-concurrent,
  --sequential, --no-merge, --verbose to OPTIONS_FLAG_ONLY
- Add --max-concurrent, --name, --url to OPTIONS_EXPECTING_VALUE
- Add parametrized tests for representative new flags
…counts

why: Non-git directories have clean=None, which was treated as falsy and
counted as dirty in the summary.
what:
- Use identity checks (is True / is False) instead of truthiness
- Add test verifying non-git dirs are not counted as dirty
…in dry-run

why: The actual sync (update_repo → create_project) supports all VCS types.
Only the dry-run plan was blocking non-git repos.
what:
- Change non-git repos from BLOCKED to UPDATE with descriptive detail
- Update test fixture to expect PlanAction.UPDATE
why: When multiple patterns match the same repo (e.g. "myrepo" and "*"),
the repo was synced multiple times.
what:
- Add deduplication by path after the pattern-matching loop
- Add test verifying a repo matched by two patterns only syncs once
why: discover_repos only scans for .git directories; .hg and .svn are
not detected despite vcspull supporting all three VCS types.
what:
- Add TODO comment noting the missing .hg/.svn scanning
why: update_repo supports all VCS types via create_project but only had
git-focused tests.
what:
- Add test_update_repo_svn using create_svn_remote_repo fixture
- Add test_update_repo_hg using create_hg_remote_repo fixture
- Both use skip decorators for graceful skip when binaries unavailable
- Use bare file:// URLs with explicit vcs since VCS binaries don't
  understand the vcs+ prefix used by vcspull for detection
why: -d is the short form of --detailed but was absent from
OPTIONS_FLAG_ONLY, causing the formatter to misclassify the next
token after -d in help example lines.
what:
- Add "-d" to OPTIONS_FLAG_ONLY set
why: Inline imports inside function bodies are harder to find and
violate the project convention of top-level stdlib imports.
what:
- Move `import json` from inside test_sync_deduplicates function to
  module-level imports
@tony tony force-pushed the misc-fixes-2026-02-08 branch from e9d02c8 to a07516e Compare February 8, 2026 16:06
@tony
Copy link
Copy Markdown
Member Author

tony commented Feb 8, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

why: The dry-run --json output changed from a nested workspace schema
to a flat array. Scripts parsing sync --dry-run --json would break.
what:
- Move cli(sync) OutputFormatter entry from Bug fixes to Breaking changes
@tony tony changed the title Fix pre-existing issues from multi-model review Fix status reporting, unify dry-run JSON schema, support non-git VCS Feb 8, 2026
@tony tony marked this pull request as ready for review February 8, 2026 16:53
@tony tony merged commit 25f3567 into master Feb 8, 2026
9 checks passed
@tony tony deleted the misc-fixes-2026-02-08 branch February 8, 2026 16:55
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.

1 participant