<p dir="ltr">I realized I should also make sure that pushing from flat to tree works. Will add tests (and fixes if necessary) and resend after lunch</p>
<br><div class="gmail_quote"><div dir="ltr">On Thu, Jan 28, 2016, 10:51 Martin von Zweigbergk <<a href="mailto:martinvonz@google.com">martinvonz@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Martin von Zweigbergk <<a href="mailto:martinvonz@google.com" target="_blank">martinvonz@google.com</a>><br>
# Date 1453914448 28800<br>
#      Wed Jan 27 09:07:28 2016 -0800<br>
# Branch stable<br>
# Node ID 798557f9b388175637a61a35503e3bc528ccf894<br>
# Parent  4511e8dac4c798e5fed91e629aa9802b01c2b6c3<br>
changegroup: fix pulling to treemanifest repo from flat repo (issue5066)<br>
<br>
In c0f11347b107 (changegroup: don't support versions 01 and 02 with<br>
treemanifests, 2016-01-19), I stopped supporting use of cg1 and cg2<br>
with treemanifest repos. What I had not considered was that it's<br>
perfectly safe to pull *to* a treemanifest repo using any changegroup<br>
version. As reported in issue5066, I therefore broke pull from old<br>
repos into a treemanifest repo. It was not covered by the test case,<br>
because that pulled from a local repo while enabling treemanifests,<br>
which enabled treemanifests on the source repo as well. After<br>
switching to pulling via HTTP, it breaks.<br>
<br>
Fix by splitting up changegroup.supportedversions() into<br>
supportedincomingversions() and supportedoutgoingversions().<br>
<br>
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py<br>
--- a/mercurial/bundle2.py<br>
+++ b/mercurial/bundle2.py<br>
@@ -1242,7 +1242,8 @@<br>
     Exists to allow extensions (like evolution) to mutate the capabilities.<br>
     """<br>
     caps = capabilities.copy()<br>
-    caps['changegroup'] = tuple(sorted(changegroup.supportedversions(repo)))<br>
+    caps['changegroup'] = tuple(sorted(<br>
+        changegroup.supportedincomingversions(repo)))<br>
     if obsolete.isenabled(repo, obsolete.exchangeopt):<br>
         supportedformat = tuple('V%i' % v for v in obsolete.formats)<br>
         caps['obsmarkers'] = supportedformat<br>
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py<br>
--- a/mercurial/bundlerepo.py<br>
+++ b/mercurial/bundlerepo.py<br>
@@ -282,7 +282,7 @@<br>
                                                   "multiple changegroups")<br>
                     cgstream = part<br>
                     version = part.params.get('version', '01')<br>
-                    if version not in changegroup.supportedversions(self):<br>
+                    if version not in changegroup.allsupportedversions(ui):<br>
                         msg = _('Unsupported changegroup version: %s')<br>
                         raise error.Abort(msg % version)<br>
                     if self.bundle.compressed():<br>
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py<br>
--- a/mercurial/changegroup.py<br>
+++ b/mercurial/changegroup.py<br>
@@ -946,10 +946,25 @@<br>
              '03': (cg3packer, cg3unpacker),<br>
 }<br>
<br>
-def supportedversions(repo):<br>
+def allsupportedversions(ui):<br>
     versions = set(_packermap.keys())<br>
-    if ('treemanifest' in repo.requirements or<br>
-        repo.ui.configbool('experimental', 'treemanifest')):<br>
+    versions.discard('03')<br>
+    if (ui.configbool('experimental', 'changegroup3') or<br>
+        ui.configbool('experimental', 'treemanifest')):<br>
+        versions.add('03')<br>
+    return versions<br>
+<br>
+# Changegroup versions that can be applied to the repo<br>
+def supportedincomingversions(repo):<br>
+    versions = allsupportedversions(repo.ui)<br>
+    if 'treemanifest' in repo.requirements:<br>
+        versions.add('03')<br>
+    return versions<br>
+<br>
+# Changegroup versions that can be created from the repo<br>
+def supportedoutgoingversions(repo):<br>
+    versions = allsupportedversions(repo.ui)<br>
+    if 'treemanifest' in repo.requirements:<br>
         # Versions 01 and 02 support only flat manifests and it's just too<br>
         # expensive to convert between the flat manifest and tree manifest on<br>
         # the fly. Since tree manifests are hashed differently, all of history<br>
@@ -957,22 +972,21 @@<br>
         # support versions 01 and 02.<br>
         versions.discard('01')<br>
         versions.discard('02')<br>
-    elif not repo.ui.configbool('experimental', 'changegroup3'):<br>
-        versions.discard('03')<br>
+        versions.add('03')<br>
     return versions<br>
<br>
 def safeversion(repo):<br>
     # Finds the smallest version that it's safe to assume clients of the repo<br>
     # will support. For example, all hg versions that support generaldelta also<br>
     # support changegroup 02.<br>
-    versions = supportedversions(repo)<br>
+    versions = supportedoutgoingversions(repo)<br>
     if 'generaldelta' in repo.requirements:<br>
         versions.discard('01')<br>
     assert versions<br>
     return min(versions)<br>
<br>
 def getbundler(version, repo, bundlecaps=None):<br>
-    assert version in supportedversions(repo)<br>
+    assert version in supportedoutgoingversions(repo)<br>
     return _packermap[version][0](repo, bundlecaps)<br>
<br>
 def getunbundler(version, fh, alg):<br>
diff --git a/mercurial/exchange.py b/mercurial/exchange.py<br>
--- a/mercurial/exchange.py<br>
+++ b/mercurial/exchange.py<br>
@@ -707,7 +707,8 @@<br>
                                                 pushop.outgoing)<br>
     else:<br>
         cgversions = [v for v in cgversions<br>
-                      if v in changegroup.supportedversions(pushop.repo)]<br>
+                      if v in changegroup.supportedoutgoingversions(<br>
+                          pushop.repo)]<br>
         if not cgversions:<br>
             raise ValueError(_('no common changegroup version'))<br>
         version = max(cgversions)<br>
@@ -1562,7 +1563,7 @@<br>
         getcgkwargs = {}<br>
         if cgversions:  # 3.1 and 3.2 ship with an empty value<br>
             cgversions = [v for v in cgversions<br>
-                          if v in changegroup.supportedversions(repo)]<br>
+                          if v in changegroup.supportedoutgoingversions(repo)]<br>
             if not cgversions:<br>
                 raise ValueError(_('no common changegroup version'))<br>
             version = getcgkwargs['version'] = max(cgversions)<br>
diff --git a/tests/test-treemanifest.t b/tests/test-treemanifest.t<br>
--- a/tests/test-treemanifest.t<br>
+++ b/tests/test-treemanifest.t<br>
@@ -202,11 +202,14 @@<br>
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved<br>
   (branch merge, don't forget to commit)<br>
   $ hg ci -m 'merge of flat manifests to new flat manifest'<br>
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log<br>
+  $ cat hg.pid >> $DAEMON_PIDS<br>
<br>
 Create clone with tree manifests enabled<br>
<br>
   $ cd ..<br>
-  $ hg clone --pull --config experimental.treemanifest=1 repo-flat repo-mixed<br>
+  $ hg clone --config experimental.treemanifest=1 \<br>
+  >   http://localhost:$HGPORT repo-mixed<br>
   requesting all changes<br>
   adding changesets<br>
   adding manifests<br>
@@ -441,13 +444,13 @@<br>
   $ hg ci -m troz<br>
<br>
 Test cloning a treemanifest repo over http.<br>
-  $ hg serve -p $HGPORT -d --pid-file=hg.pid --errorlog=errors.log<br>
+  $ hg serve -p $HGPORT2 -d --pid-file=hg.pid --errorlog=errors.log<br>
   $ cat hg.pid >> $DAEMON_PIDS<br>
   $ cd ..<br>
 We can clone even with the knob turned off and we'll get a treemanifest repo.<br>
   $ hg clone --config experimental.treemanifest=False \<br>
   >   --config experimental.changegroup3=True \<br>
-  >   http://localhost:$HGPORT deepclone<br>
+  >   http://localhost:$HGPORT2 deepclone<br>
   requesting all changes<br>
   adding changesets<br>
   adding manifests<br>
_______________________________________________<br>
Mercurial-devel mailing list<br>
<a href="mailto:Mercurial-devel@selenic.com" target="_blank">Mercurial-devel@selenic.com</a><br>
<a href="https://selenic.com/mailman/listinfo/mercurial-devel" rel="noreferrer" target="_blank">https://selenic.com/mailman/listinfo/mercurial-devel</a><br>
</blockquote></div>