#pragma section-numbers 2 <> <> = Subrepo Work = Proposed improvements and to-do list for [[Subrepositories|subrepos]]. <> == Internals == The {{{.hgsub}}} format uses the hgrc config format. It reserves a source prefix of {{{[}}} for future expansion (see below). Future expansion may also used named sections in this file. The {{{.hgsubstate}}} format is similar to the tags format, in the form {{{}}}. This file is not intended to be hand-edited, but will accept any identifier format that Mercurial accepts. It is also automatically merged when necessary. It is separated from {{{.hgsub}}} to keep automatic updates from muddling that file and to keep {{{.hgsub}}}'s history tidy. The combined state can be viewed with {{{hg debugsub}}}. Internally, subrepo states are represented as a hash of path to (source, revision) pairs that combine the elements of the above two files. There is also a new {{{subrepo}}} object type that exposes a limited set of operations on a subrepo. Subrepos can be traversed like this: {{{ # check whether subrepos are dirty c = repo['tip'] for s in c.substate: subrepo = c.sub[s] print s, subrepo.dirty() }}} {{{#!wiki comment The code snippet that worked for me was: def sbstate(ui, repo, source='default', **opts): # check whether subrepos are dirty c = repo['tip'] for s in c.substate: subrepo = c.sub(s) print s, subrepo.dirty() }}} === Wanted Feature per Command === The following repo structure will be used to illustrate the expected behavior of the commands: {{{ A B C D }}} So A has two subrepos (B and C), and C has D as a subrepo. ==== add ==== Add have an argument -S which makes it behave transparently with respect to subrepos. For example, supposte the user is in repo A and executes this command: {{{ $ hg add -S }}} The effect is that files are added in repos A, B, C and D. Suppose the user executes this command when his current directory is A: {{{ $ hg add -S C/D/foo.c }}} The effect is that `foo.c` is added in repo D. ==== archive ==== Archive should archive a revision in the current repo and recurse through subrepos, archiving an appropriate revision in each. ==== branch ==== Current behaviour: A new branch is created in repo A {{{ $ hg branch newBranch }}} A change is made and committed in repo A. The changeset has been added to newBranch. A change is made and committed in repo B, C or D. The changeset has been added to default branch in the subrepo. Should the creation of branches in subrepos be a concious decision? {{{ $ hg branch -r newBranch }}} or should the branch command recusively create branches by default? Desired behaviour: A new branch is created in repo A {{{ $ hg branch newBranch }}} A change is made and committed in repo A. The changeset has been added to newBranch. A change is made and committed in repo B, C or D. The changeset has been added to newBranch in the subrepo. ==== bundle/unbundle ==== Bundle should bundle changesets in the current repo and recurse through subrepos, bundling appropriate changesets in each. It is unclear if these bundles should be wrapped up into a super-bundle (a zip- or tar-file?) Unbundle should handle whatever bundle produces. ==== commit ==== Commit currently recurses by default. Its default behavior should be consistent with the behavior of other commands regarding subrepo handling. [[WhatsNew#Mercurial_2.0_.282011-11-01.29|2.0]] changed this such that commit now defaults to aborting if subrepos are dirty. This allows it to be more consistent with other commands regarding subrepo handling. ==== diff ==== Diff should recurse through subrepos. It is important that the correct revisions are looked up in each subrepo. For example, one should be able to execute `hg diff -r 3 -r 10` in repo A and, according to the .hgsubstates in A and C, appropriate diffs will be done in each of the subrepos. ==== export/import ==== Export should export changesets in the current repo and recurse through subrepos, exporting appropriate changesets from each. Import should handle whatever export produces. ==== incoming/outgoing ==== Incoming and outgoing can recourse into sub repositories by using the -S/--subrepo argument. The changesets are shown for each repository. {{{#!wiki caution Currently, outgoing's behavior is inconsistent with push: the latter will push changes that outgoing does not show. }}} ==== log ==== The log for subrepos should be interleaved with the log for the parent, according to the .hgsubstate. Options such as "limit" are applied per repo. ==== pull ==== Pull should recurse into subrepos. That is, it should simply do a pull in each subrepo recursively to bring them up to date. This is not to say that they should be updated at the same time. The current mechanism to do that, by updating the parent if fine when one want to update to new revisions of the subrepos based on the state of the parent's .hgsubstate ==== push ==== Push already recurses by default. The behavior should be consistent with other commands with respect to subrepo handling. ==== rollback ==== Rollback should recurse into subrepos. Do the `.hgsubstate` file need a revert as well since it is modified by commit? ==== root ==== Should not recurse, but can be extended to report the top-level repository, not just the root of the current repositroy. With this extension, aliases for other commands could be easily defined (following the UNIX approach of simplicity): {{{ [alias] commit-all = !hg -R $(hg root --parent) commit --sub status-all = !hg -R $(hg root --parent) status --sub diff-all = !hg -R $(hg root --parent) diff --sub in-all = !hg -R $(hg root --parent) incoming --sub out-all = ... }}} Probably it won't be much more effort to allow the --parent option on the listed commands directly - avoiding the alias. ==== status ==== Status should recurse into subrepos. Subrepos containing uncommitted changes should be listed, and a subrepo that does not have uncommitted changes but is not at the revision specified in its parent repo should also be listed. For example, suppose the user wants to see the status starting in A. Repo B contains no uncommitted changes but is not at the revision specified in A's .hgsubstate. Repos C and D contain uncommitted changes. The output could look like this {{{ hg status M B/ M C/ M C/file1.txt M C/D/ A C/D/file2.txt }}} ==== tip ==== Not yet reviewed: http://mercurial.markmail.org/thread/lcbbb7xkm6qjnwhq When the -S/--subrepos argument is used for the tip command. It recurses through the sub repositories and shows the tip of eachs. The templates support {subrepo} to show the path of the subrepo, relative to the main repo. {{{ hg tip -S }}} ==== update ==== Update currently recurses by default. The default behavior should be consistent with other commands with respect to subrepo handling. === To Do === * Add command-line support * Handle deletion of subrepos more completely * Reduce spurious message output such as 'nothing changed' * Extend this feature to support non-native subrepos from other systems such as Git (partially done for git and svn). * Command line flag to pull/update/etc. without changing subrepos. * Allow local overrides of sub-repository URLs. This is useful if one user has write access through e.g. ssh to a subrepo, while others do not. See SubrepoRemappingPlan. * Instructions on creating a subrepo on an existing folder with existing history. ---- CategoryDeveloper CategoryNewFeatures