D10414: bundle: support multiple destinations

marmoute (Pierre-Yves David) phabricator at mercurial-scm.org
Wed Apr 14 23:40:27 UTC 2021


marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  `hg outgoing` and `hg push` now support multiple destination. We do the same
  for `hg bundle`. Various other commands needs this kind of behavior and it
  would be create to factor this code out for their usage. However this is an
  adventure for another time.
  
  They are some minor change to the tests (in addition to the new test for the
  feature):
  
  - one because I updated a message to plurals,
  - another one because the error changed, and I actually find it clearer.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10414

AFFECTED FILES
  hgext/patchbomb.py
  mercurial/commands.py
  tests/test-bundle-r.t
  tests/test-exchange-multi-source.t

CHANGE DETAILS

diff --git a/tests/test-exchange-multi-source.t b/tests/test-exchange-multi-source.t
--- a/tests/test-exchange-multi-source.t
+++ b/tests/test-exchange-multi-source.t
@@ -170,6 +170,11 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     C
   
+  $ hg bundle -R test-repo-bare bundle.hg ./branch-E-push ./branch-G-push ./branch-H-push
+  searching for changes
+  searching for changes
+  searching for changes
+  6 changesets found
   $ hg push --force -R test-repo-bare ./branch-E-push ./branch-G-push ./branch-H-push
   pushing to ./branch-E-push
   searching for changes
@@ -351,6 +356,11 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     C
   
+  $ hg bundle -R test-repo-bare bundle.hg ./branch-E-push ./branch-G-push ./branch-H-push --rev default
+  searching for changes
+  searching for changes
+  searching for changes
+  2 changesets found
   $ hg push --force -R test-repo-bare ./branch-E-push ./branch-G-push ./branch-H-push --rev default
   pushing to ./branch-E-push
   searching for changes
@@ -429,6 +439,11 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     C
   
+  $ hg bundle -R test-repo-bare bundle.hg ./branch-G-push ./branch-H-push ./branch-E-push --rev default
+  searching for changes
+  searching for changes
+  searching for changes
+  2 changesets found
   $ hg push --force -R test-repo-bare ./branch-G-push ./branch-H-push ./branch-E-push --rev default
   pushing to ./branch-G-push
   searching for changes
diff --git a/tests/test-bundle-r.t b/tests/test-bundle-r.t
--- a/tests/test-bundle-r.t
+++ b/tests/test-bundle-r.t
@@ -171,14 +171,15 @@
 should fail
 
   $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg test-3
-  abort: --base is incompatible with specifying a destination
+  abort: --base is incompatible with specifying destinations
   [10]
   $ hg -R test bundle -a -r tip test-bundle-branch1.hg test-3
-  abort: --all is incompatible with specifying a destination
+  abort: --all is incompatible with specifying destinations
   [10]
   $ hg -R test bundle -r tip test-bundle-branch1.hg
-  abort: repository default-push not found
-  [255]
+  config error: default repository not configured!
+  (see 'hg help config.paths')
+  [30]
 
   $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg
   2 changesets found
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1531,10 +1531,10 @@
         ),
     ]
     + remoteopts,
-    _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
+    _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]...'),
     helpcategory=command.CATEGORY_IMPORT_EXPORT,
 )
-def bundle(ui, repo, fname, dest=None, **opts):
+def bundle(ui, repo, fname, *dests, **opts):
     """create a bundle file
 
     Generate a bundle file containing data to be transferred to another
@@ -1545,7 +1545,7 @@
     all the nodes you specify with --base parameters. Otherwise, hg
     will assume the repository has all the nodes in destination, or
     default-push/default if no destination is specified, where destination
-    is the repository you provide through DEST option.
+    is the repositories you provide through DEST option.
 
     You can change bundle format with the -t/--type option. See
     :hg:`help bundlespec` for documentation on this format. By default,
@@ -1590,9 +1590,9 @@
         )
 
     if opts.get(b'all'):
-        if dest:
+        if dests:
             raise error.InputError(
-                _(b"--all is incompatible with specifying a destination")
+                _(b"--all is incompatible with specifying destinations")
             )
         if opts.get(b'base'):
             ui.warn(_(b"ignoring --base because --all was specified\n"))
@@ -1605,31 +1605,54 @@
         )
 
     if base:
-        if dest:
+        if dests:
             raise error.InputError(
-                _(b"--base is incompatible with specifying a destination")
+                _(b"--base is incompatible with specifying destinations")
             )
         common = [repo[rev].node() for rev in base]
         heads = [repo[r].node() for r in revs] if revs else None
         outgoing = discovery.outgoing(repo, common, heads)
+        missing = outgoing.missing
+        excluded = outgoing.excluded
     else:
-        dest = ui.expandpath(dest or b'default-push', dest or b'default')
-        dest, branches = urlutil.parseurl(dest, opts.get(b'branch'))
-        other = hg.peer(repo, opts, dest)
-        revs = [repo[r].hex() for r in revs]
-        revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
-        heads = revs and pycompat.maplist(repo.lookup, revs) or revs
-        outgoing = discovery.findcommonoutgoing(
-            repo,
-            other,
-            onlyheads=heads,
-            force=opts.get(b'force'),
-            portable=True,
+        missing = set()
+        excluded = set()
+        for path in urlutil.get_push_paths(repo, ui, dests):
+            other = hg.peer(repo, opts, path.rawloc)
+            if revs is not None:
+                hex_revs = [repo[r].hex() for r in revs]
+            else:
+                hex_revs = None
+            branches = (path.branch, [])
+            head_revs, checkout = hg.addbranchrevs(
+                repo, repo, branches, hex_revs
+            )
+            heads = (
+                head_revs
+                and pycompat.maplist(repo.lookup, head_revs)
+                or head_revs
+            )
+            outgoing = discovery.findcommonoutgoing(
+                repo,
+                other,
+                onlyheads=heads,
+                force=opts.get(b'force'),
+                portable=True,
+            )
+            missing.update(outgoing.missing)
+            excluded.update(outgoing.excluded)
+
+    if not missing:
+        scmutil.nochangesfound(ui, repo, not base and excluded)
+        return 1
+
+    if heads:
+        outgoing = discovery.outgoing(
+            repo, missingroots=missing, ancestorsof=heads
         )
-
-    if not outgoing.missing:
-        scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
-        return 1
+    else:
+        outgoing = discovery.outgoing(repo, missingroots=missing)
+    outgoing.excluded = sorted(excluded)
 
     if cgversion == b'01':  # bundle1
         bversion = b'HG10' + bundlespec.wirecompression
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -382,7 +382,10 @@
     if btype:
         opts['type'] = btype
     try:
-        commands.bundle(ui, repo, tmpfn, dest, **opts)
+        dests = []
+        if dests:
+            dests = [dest]
+        commands.bundle(ui, repo, tmpfn, *dests, **opts)
         return util.readfile(tmpfn)
     finally:
         try:



To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel


More information about the Mercurial-devel mailing list