Skip to content

Support numeric depth: N and move per-repo sync keys under options:#554

Merged
tony merged 11 commits into
masterfrom
depth-options-552
May 31, 2026
Merged

Support numeric depth: N and move per-repo sync keys under options:#554
tony merged 11 commits into
masterfrom
depth-options-552

Conversation

@tony
Copy link
Copy Markdown
Member

@tony tony commented May 31, 2026

Summary

  • Add a numeric options.depth: N per-repository key (and --depth N on add/discover) so workspaces can keep a small window of history instead of the all-or-nothing shallow: true. Resolves add/discover: support numeric depth: N (follow-up to #550) #552.
  • Add automatic clone-depth detection on import: a depth-1 checkout records options.shallow: true, a deeper window records options.depth: N.
  • Relocate the per-repository sync keys rev, shallow, and depth under an options: block (joining the existing pin/pin_reason), so VCS-sync tuning and mutation policy share one namespace.
  • Add a vcspull migrate subcommand that rewrites configs from the deprecated top-level form into options:.
  • Deprecate the top-level rev:/shallow: keys that shipped in v1.61.0 — they are still read, and vcspull sync warns and points at vcspull migrate.
  • Require libvcs>=0.42.0, which honors an arbitrary GitSync(depth=N).

Changes by area

Dependencies

  • pyproject.toml / uv.lock: bump the floor to libvcs>=0.42.0,<0.43.0.

Schema & config (src/vcspull/types.py, src/vcspull/config.py)

  • RepoOptionsDict: now carries rev/shallow/depth alongside pin/pin_reason; RepoEntryDict marks the top-level rev/shallow as deprecated; ConfigDict gains depth.
  • extract_repos: lifts options.{rev,shallow,depth} onto the flat internal config; an options: value wins over a legacy top-level key, so the sync path is unchanged apart from depth.
  • detect_git_depth: reports a shallow checkout's commit count.
  • resolve_clone_depth: the shared hybrid precedence used by add and discover (explicit --depth → explicit --shallow → auto-detect).
  • migrate_repo_entry / detect_legacy_repo_options: relocate top-level keys under options: (depth wins over shallow) and scan a raw config for entries still using the old form.

CLI (add, discover, sync)

  • add / discover: add --depth N (validated >= 1); record sync keys under options: via a shared build_repo_entry; log the recorded depth/shallow.
  • sync: applies options.depth as GitSync.depth (git-only, depth wins over shallow), and warns when it loads a config still using top-level keys.

Migrate command (src/vcspull/cli/migrate.py)

  • vcspull migrate: mirrors fmt (-f/--file, --write, --all). Previews by default, rewrites with --write, and is idempotent.

Docs

  • docs/configuration/: an options: "Sync options" section (rev/shallow/depth), a clone-depth section, and a migration note.
  • docs/cli/migrate.md (+ index/grid/API page): the new command's reference.

Design decisions

  • options: is the home for sync tuning, not the entry root: rev/shallow/depth join pin under one per-repository namespace rather than scattering VCS keys across the root. This keeps "how to clone" and "may vcspull edit this entry" co-located and the entry root limited to repo/remotes/worktrees.
  • Deprecate-and-migrate over hard break: the top-level keys that shipped in v1.61.0 are still read (with a sync warning) and rewritten by a dedicated vcspull migrate command, so existing configs keep working through a grace period.
  • Hybrid auto-detection: an auto-detected depth-1 checkout records the boolean shallow: true (the common case, unchanged from v1.61.0); only a genuine window (depth > 1) records depth: N.
  • Precedence delegated to libvcs: GitSync.obtain() already resolves "explicit depth wins, else shallow→depth 1, else full," so vcspull records and forwards rather than re-implementing precedence at sync time.

Verification

--depth is wired into both importers:

$ rg -n '"--depth"' src/vcspull/cli/add.py src/vcspull/cli/discover.py

The reader and migrator share one canonical key list:

$ rg -n 'LEGACY_REPO_OPTION_KEYS' src/vcspull

The migrate subcommand is registered and dispatched:

$ rg -n 'migrate' src/vcspull/cli/__init__.py

End-to-end migrate (preview → write → idempotent):

$ vcspull migrate -f ~/.vcspull.yaml
$ vcspull migrate -f ~/.vcspull.yaml --write
$ vcspull migrate -f ~/.vcspull.yaml

Before / After

Config written by vcspull add/discover and read by sync:

# Before (v1.61.0)
~/code/:
  flask:
    repo: git+https://github.com/pallets/flask.git
    shallow: true
    rev: v3.0.0
# After
~/code/:
  flask:
    repo: git+https://github.com/pallets/flask.git
    options:
      rev: v3.0.0
      shallow: true   # or `depth: 50` for a history window

Test plan

  • uv run ruff format . — formatting clean
  • uv run ruff check . --fix --show-fixes — lint clean
  • uv run mypy . — types clean
  • uv run py.test --reruns 0 — full suite green
  • just build-docs — docs build; new cli-migrate / config references resolve
  • test_detect_git_depth, test_resolve_clone_depth_explicit, test_resolve_clone_depth_autodetect — depth detection and hybrid precedence
  • test_extract_repos_lifts_options_sync_keys — reader surfaces options: and legacy forms, options: wins
  • test_migrate_repo_entry, test_migrate_config, test_migrate_idempotent, test_migrate_cli_end_to_end — relocation, depth-wins, idempotency, CLI
  • test_update_repo_git_depthoptions.depth clones at --depth N on sync
  • test_load_configs_warns_on_legacy_options — sync warns on the deprecated top-level form
  • test_discover_detects_numeric_depth, test_discover_detects_shallow_clone — auto-detection records the right key
  • add/discover fixtures assert the options: output shape with --depth cases

Closes #552

tony added 6 commits May 31, 2026 12:07
why: libvcs 0.42.0 adds an arbitrary GitSync clone depth (depth=N) and
fixes a constructor bug that dropped git_shallow/tls_verify. vcspull
needs the depth argument to persist and apply a numeric depth: N per
repository (issue #552); the prior <0.42.0 pin cannot honor it.
what:
- Bump the libvcs dependency floor to >=0.42.0,<0.43.0
- Relock uv.lock (libvcs 0.41.0 -> 0.42.0)
…epth helpers

why: Issue #552 adds a numeric clone depth and relocates the per-repo
sync-tuning keys (rev/shallow/depth) into the existing options: block,
keeping them out of the entry root. The reader must accept the new
canonical form while still honoring v1.61.0's top-level keys, and the
add/discover/migrate paths need shared primitives for depth.
what:
- types: add rev/shallow/depth to RepoOptionsDict; add depth to
  ConfigDict; mark top-level rev/shallow in RepoEntryDict as deprecated
- config.extract_repos: lift options.{rev,shallow,depth} onto the flat
  ConfigDict (options wins over a legacy top-level key)
- config.detect_git_depth: report a shallow checkout's commit count
- config.resolve_clone_depth: shared hybrid precedence for add/discover
- config.migrate_repo_entry: relocate legacy top-level keys under
  options: (depth wins over shallow)
- config.detect_legacy_repo_options: find entries still using top-level
  keys (drives the deprecation warning)
- tests: cover the reader, helpers, and migration with parametrized
  NamedTuple fixtures
why: Issue #552 lets workspaces keep a small history window (e.g.
--depth 50) instead of only the boolean shallow flag, and relocates the
per-repo sync keys into options:. libvcs 0.42.0 honors GitSync(depth=N),
so add/discover can persist it and sync can apply it.
what:
- build_repo_entry: nest rev/shallow/depth under options:; depth wins
  over shallow
- add: add --depth N (validated >=1); resolve_clone_depth replaces the
  inline shallow check (hybrid auto-detect); thread depth to add_repo
- discover: add --depth N; carry depth on _FoundRepo; per-repo
  resolve_clone_depth; log and persist depth
- sync.update_repo: apply options.depth as GitSync.depth (git-gated,
  depth wins); refresh the git_shallow comment for libvcs 0.42.0
- sync: load_configs(warn_legacy_options=True) warns on top-level
  rev/shallow/depth and points at vcspull migrate
- tests: depth cases for add/discover, sync depth + deprecation-warning
  coverage; existing assertions moved to the options: form
why: Moving rev/shallow/depth under options: deprecates the v1.61.0
top-level keys. Users need a one-shot, idempotent rewrite of existing
configs rather than hand-editing, and sync only warns about the old
form.
what:
- Add `vcspull migrate` (mirrors fmt: -f/--file, --write, --all),
  reusing config.migrate_repo_entry; dry-run previews, --write rewrites
- Register the subparser and dispatch arm in the CLI
- Extend the CLI logger-names expectation for the new module
- tests: migrate_config relocation matrix, write/dry-run, idempotency,
  and an end-to-end CLI run
why: The per-repo sync keys now live under options:, depth: N is new,
and the top-level form is deprecated. Users need the canonical shape,
the precedence rules, and the migration path documented.
what:
- configuration: group rev/shallow/depth under an "options:" section,
  add a clone-depth section, and document migrating off the top-level
  form via vcspull migrate
- cli: add the vcspull migrate page (grid, toctree, see-also) and its
  API automodule page
why: Record the user-facing add/discover/sync/migrate changes for the
unreleased 1.61 line.
what:
- Add "Numeric clone depth" (#552) deliverable
- Add "Migrate configs to the options: form" (#552) deliverable
- Note the libvcs>=0.42.0 floor and the deprecation of top-level
  rev/shallow/depth with a before/after migration path
@codecov
Copy link
Copy Markdown

codecov Bot commented May 31, 2026

Codecov Report

❌ Patch coverage is 66.82243% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.82%. Comparing base (37b2c53) to head (597104f).

Files with missing lines Patch % Lines
src/vcspull/cli/migrate.py 46.66% 50 Missing and 6 partials ⚠️
src/vcspull/cli/add.py 40.00% 3 Missing and 3 partials ⚠️
src/vcspull/config.py 91.17% 5 Missing and 1 partial ⚠️
src/vcspull/cli/discover.py 76.92% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #554      +/-   ##
==========================================
- Coverage   83.69%   82.82%   -0.88%     
==========================================
  Files          29       30       +1     
  Lines        4159     4354     +195     
  Branches      820      873      +53     
==========================================
+ Hits         3481     3606     +125     
- Misses        442      502      +60     
- Partials      236      246      +10     

☔ 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 added 5 commits May 31, 2026 13:59
why: Users on v1.61.0 wrote top-level rev/shallow keys; they need a
migration note telling them the form changed, that the old keys still
load but warn, and how to rewrite configs.
what:
- Add a 'Next release' entry covering the rev/shallow/depth move under
  options:, with before/after YAML and the vcspull migrate --write step
- Mention depth: N as the new numeric clone-depth key
why: The migration story spans three pages (config schema, the migrate
command, and the migration notes); readers landing on one had no path to
the others.
what:
- Link the configuration migration subsection to the migration notes
- Add a 'See also' on the migrate command page pointing to the config
  schema and the migration notes
why: Only a single shape (top-level shallow) proved the legacy-format
warning; the rev/depth/combo/multi paths and the negative cases
(canonical options:, string shorthand) were unverified.
what:
- Replace the single test with a NamedTuple + test_id matrix over
  load_configs(warn_legacy_options=True)
- Cover rev/shallow/depth/combo and multi-entry (assert affected count
  parsed from the message), plus canonical and string entries that must
  NOT warn
- Assert on caplog.records schema (level, vcspull_config_path, message)
…ing text

why: The deprecation-warning test counted affected entries by parsing the
rendered log message ("Affected: ...".split), which couples the test to
message formatting. The project standard is to assert on structured
record attributes, not the message string.
what:
- Carry the affected-entry count as a scalar `vcspull_legacy_count` in the
  warning's `extra` (alongside `vcspull_config_path`)
- Assert `record.vcspull_legacy_count == affected_count`; narrow the record
  filter on both extras so the access stays type-checked
…ment

why: The comment omitted the actual reason for applying the keys
post-construction (libvcs names shallow `git_shallow`, so it must be
translated) and overstated "leaking git-only kwargs into the svn/hg sync
constructors" — HgSync/SvnSync absorb unknown **kwargs harmlessly, so
that was never the failure mode.
what:
- State the real rationale: translate shallow->git_shallow, apply both as
  attributes for git only, and let obtain() resolve precedence
- Comment-only; no behavior change
@tony tony merged commit 3df7f4e into master May 31, 2026
8 checks passed
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.

add/discover: support numeric depth: N (follow-up to #550)

1 participant