You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A repo entry can pin options.rev, list git remotes and worktrees, and (after #576) set git_options, but it cannot say what vcspull sync should do when the checkout on disk is on a different ref than configured, or has uncommitted changes. Git-only keys sit beside VCS-neutral ones, and Mercurial and Subversion have no place for their own settings. This proposes one entry shape for every VCS: five VCS-neutral keys plus one block per VCS named after the URL scheme. Depends on libvcs#554. Sized for one evening once that lands.
What sync does on drift is implicit. update_repo pops shallow and depth onto GitSync (https://github.com/vcs-python/vcspull/blob/v1.67.0/src/vcspull/cli/sync.py#L2086-L2096) and libvcs then checks out rev if set, else pulls whatever branch is on disk. There is no way to say "keep what is on disk", "follow the config", or "only warn", and only git sets aside uncommitted changes first.
Give every entry the same VCS-neutral core, move VCS-specific keys into one block per VCS, and make drift and dirty handling explicit policy.
These must hold; everything after them is open:
VCS-neutral keys are identical for git+, hg+, and svn+ entries. VCS-specific keys live in exactly one block named after the URL scheme, and a block for the wrong VCS fails at load, naming the entry.
The main checkout and each worktree describe their target the same way: exactly one of branch, tag, commit, or rev.
sync policy is explicit and VCS-neutral: what to do when the checkout is on a different ref than configured, and what to do with uncommitted changes. Discarding changes still requires the caller's confirmation, and setting them aside uses each VCS's own mechanism through libvcs.
Every existing config keeps loading. Old locations warn, vcspull migrate rewrites them in one pass, and add, discover, import, and fmt write the new layout.
working_copy holds the target ref, the remote pulls come from (default: the repo URL), and sync. drift is one of keep (leave the checkout where it is), follow (move it to the configured ref), or warn (report in vcspull status, touch nothing). dirty is one of abort (skip the entry and report), preserve (set changes aside, then restore), or discard (needs --yes).
Each <vcs>: block is exactly the option set of the matching libvcs class, so adding a knob is one libvcs field plus one TypedDict field, and a test can check the two agree by introspection.
pin and pin_reason move to the entry level; options then has nothing left in it.
Worktree items keep their shape and gain working_copy's sync; whether to rename worktrees to working_copies is open.
Schema: post-process the generated schema with an if on the repo scheme that forbids the other VCS blocks, and a oneOf on the ref keys.
Migration in one vcspull migrate pass: options.rev to working_copy.rev; git_options.* to git.*, which can be folded into Config cannot request partial clones (git clone --filter) #576 before it ships; options.pin, options.pin_reason, and options.allow_overwrite to the entry level.
Details that cost time to rediscover:
"Working copy" is the word three of the six tools use (jj, Subversion, CVS). git says "working tree" (glossary at v2.55.0), got says "work tree" (got(1)), Mercurial says "working directory" (glossary at 7.2.4). rev is the word Mercurial, Subversion, CVS, and gitrevisions share; branch and tag exist in all six; commit fits git, got, and jj.
Drift means "the configured ref resolves to what is checked out", not "the same string". git records a branch name, got a branch plus a base commit, jj only the "working-copy commit" @ with "no concept of an active/current/checked-out bookmark" (bookmarks at v0.45.1), and Subversion and CVS record positions per directory or file, so mixed-revision working copies exist there. detach can be derived from the ref kind: a branch is followed, a tag or commit is pinned; jj is always detached and got never is.
preserve resolves per VCS: git stash, Mercurial shelve, Subversion a patch file because x-shelve is experimental, jj nothing because changes are already a commit (FAQ at v0.45.1), got and CVS a patch file. Naming the policy rather than the mechanism is what keeps a key like backup-to-stash from being git-only.
Fetch and push targets are separate in git, Mercurial, jj, and got. remotes entries keep fetch_url and push_url; the working_copy.remote is only where pulls come from.
Subversion's branch is part of the URL (svn switch is "Update the working copy to a different URL within the same repository.", svn.c at 1.14.5), so its working_copy is a rev plus the entry URL, not a branch name.
Not doing:
jj, got, or CVS entries until libvcs has backends; the schema may reserve the block names.
Flat git_options, hg_options, svn_options keys: also avoid the depth collision, but grow one top-level key per VCS and give VCS-neutral policy no home.
Keeping options as a catch-all: the mixed audiences and the collision above are what it produces.
Nesting working_copy inside the VCS block, as first sketched: puts a concept every VCS has into a per-VCS namespace, and Subversion and Mercurial would each need their own copy.
Summary
A repo entry can pin
options.rev, list gitremotesandworktrees, and (after #576) setgit_options, but it cannot say whatvcspull syncshould do when the checkout on disk is on a different ref than configured, or has uncommitted changes. Git-only keys sit beside VCS-neutral ones, and Mercurial and Subversion have no place for their own settings. This proposes one entry shape for every VCS: five VCS-neutral keys plus one block per VCS named after the URL scheme. Depends on libvcs#554. Sized for one evening once that lands.Problem
RepoOptionsDictmixes three audiences:revapplies to every VCS,shallowanddepthare git-only, andpin,allow_overwrite, andpin_reasonare vcspull's own policy about the entry (https://github.com/vcs-python/vcspull/blob/v1.67.0/src/vcspull/types.py#L133-L190). Config cannot request partial clones (git clone --filter) #576 addsgit_optionsbeside it. Subversion'sdepthmeans directory depth (empty,files,immediates,infinity), git's means history length; a flat layout has to invent a second name for one of them.syncdoes on drift is implicit.update_repopopsshallowanddepthontoGitSync(https://github.com/vcs-python/vcspull/blob/v1.67.0/src/vcspull/cli/sync.py#L2086-L2096) and libvcs then checks outrevif set, else pulls whatever branch is on disk. There is no way to say "keep what is on disk", "follow the config", or "only warn", and only git sets aside uncommitted changes first.tag,branch, orcommitplusdetach(https://github.com/vcs-python/vcspull/blob/v1.67.0/src/vcspull/types.py#L41-L95, enforced by_validate_worktrees_configat https://github.com/vcs-python/vcspull/blob/v1.67.0/src/vcspull/config.py#L104), but only for extra worktrees. The main checkout gets an opaqueoptions.rev.remotesis wired for git only, although Mercurial's[paths](default,default:pushurl) has the same fetch and push shape.git clone --filter) #576 cannot yet express "the per-VCS block must match the URL scheme".Prompt
Give every entry the same VCS-neutral core, move VCS-specific keys into one block per VCS, and make drift and dirty handling explicit policy.
These must hold; everything after them is open:
git+,hg+, andsvn+entries. VCS-specific keys live in exactly one block named after the URL scheme, and a block for the wrong VCS fails at load, naming the entry.branch,tag,commit, orrev.syncpolicy is explicit and VCS-neutral: what to do when the checkout is on a different ref than configured, and what to do with uncommitted changes. Discarding changes still requires the caller's confirmation, and setting them aside uses each VCS's own mechanism through libvcs.vcspull migraterewrites them in one pass, andadd,discover,import, andfmtwrite the new layout.git clone --filter) #576.Direction, non-binding. Target shape:
working_copyholds the target ref, the remote pulls come from (default: the repo URL), andsync.driftis one ofkeep(leave the checkout where it is),follow(move it to the configured ref), orwarn(report invcspull status, touch nothing).dirtyis one ofabort(skip the entry and report),preserve(set changes aside, then restore), ordiscard(needs--yes).<vcs>:block is exactly the option set of the matching libvcs class, so adding a knob is one libvcs field plus oneTypedDictfield, and a test can check the two agree by introspection.pinandpin_reasonmove to the entry level;optionsthen has nothing left in it.working_copy'ssync; whether to renameworktreestoworking_copiesis open.ifon thereposcheme that forbids the other VCS blocks, and aoneOfon the ref keys.vcspull migratepass:options.revtoworking_copy.rev;git_options.*togit.*, which can be folded into Config cannot request partial clones (git clone --filter) #576 before it ships;options.pin,options.pin_reason, andoptions.allow_overwriteto the entry level.Details that cost time to rediscover:
got(1)), Mercurial says "working directory" (glossary at 7.2.4).revis the word Mercurial, Subversion, CVS, and gitrevisions share;branchandtagexist in all six;commitfits git, got, and jj.@with "no concept of an active/current/checked-out bookmark" (bookmarks at v0.45.1), and Subversion and CVS record positions per directory or file, so mixed-revision working copies exist there.detachcan be derived from the ref kind: a branch is followed, a tag or commit is pinned; jj is always detached and got never is.preserveresolves per VCS: gitstash, Mercurialshelve, Subversion a patch file becausex-shelveis experimental, jj nothing because changes are already a commit (FAQ at v0.45.1), got and CVS a patch file. Naming the policy rather than the mechanism is what keeps a key likebackup-to-stashfrom being git-only.remotesentries keepfetch_urlandpush_url; theworking_copy.remoteis only where pulls come from.svn switchis "Update the working copy to a different URL within the same repository.",svn.cat 1.14.5), so itsworking_copyis arevplus the entry URL, not abranchname.Not doing:
git clone --filter) #576, libvcs add/discover: capture rev and shallow state when importing #553).git clone --filter) #576 stays.Alternatives
Weighed and set aside:
git_options,hg_options,svn_optionskeys: also avoid thedepthcollision, but grow one top-level key per VCS and give VCS-neutral policy no home.optionsas a catch-all: the mixed audiences and the collision above are what it produces.working_copyinside the VCS block, as first sketched: puts a concept every VCS has into a per-VCS namespace, and Subversion and Mercurial would each need their own copy.References
git clone --filter) #576 and libvcs#553, partial clones and thegit_optionsblockTypedDicts$schemacomment