merge with stable
authorPulkit Goyal <pulkit@yandex-team.ru>
Mon, 04 Feb 2019 20:35:21 +0300
changeset 41529 13a6dd952ffe
parent 41528 b7a0efb3c370 (current diff)
parent 41460 8b2892d5a9f2 (diff)
child 41530 4dd07bf84608
merge with stable
mercurial/commands.py
mercurial/help/config.txt
mercurial/localrepo.py
mercurial/revlog.py
mercurial/subrepo.py
tests/test-help.t
--- a/.hgsigs	Mon Feb 04 18:14:03 2019 +0300
+++ b/.hgsigs	Mon Feb 04 20:35:21 2019 +0300
@@ -175,3 +175,4 @@
 1c8c54cf97256f4468da2eb4dbee24f7f3888e71 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAlwG+eIQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91YqSD/9IAwdaPrOeiT+DVBW2x33oFeY1X1f5CBG/vCJptalOd2QDIsD0ANEzQHmzV25RKD851v155Txt/BPlkuBfO/kg0BbOoqTpGZk+5CcoFWeyhJct2CxtCLdEpyZ/98/htMR4VfWprCX2GHXPjS813l9pebsN3WgBUOc2VaUdHNRoAGsMVgWC5BWwNP4XSA9oixFL/O4aGLQ6pPfP3vmMFySWXWnIN8gUZ4sm53eKaT0QCICAgzFh+GzRd81uACDfoJn1d8RS9GK+h6j8x0crLY5CpQQy8lRVkokvc0h6XK44ofc57p9GHAOfprHY3DbBhD9H6fLAf5raUsqPkLRYVGqhg8bOsBr3vJ56hiXJYOYPZSYXGjnHRcUrgfPVrY+6mPTeCIQMPmWBHwYH5Tc5TLrPuxxCL4wVywqGbfmIVP+WFUikkykAAwuPOZAswxJJOB0gsnnxcApmTeXRznBXyvzscMlWVZiMjzflKRRJ9V5RI4Fdc6n1wQ4vuLSO4AUnIypIsV6ZFAOBuFKH7x6nPG0tP3FYzcICaMOPbxEx3LStnuU+UuEs6TIxM6IiR3LPiiDGZ2BA2gjJhDxQFV8hAl8KDO3LsYuyUQCv3RTAP+YejH21bIXdnwDlNqy8Hrd53rq7jZsdb2pMVvOZZ3VmIu64f+jVkD/r5msDUkQL3M9jwg==
 197f092b2cd9691e2a55d198f717b231af9be6f9 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAlwz6DUQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91SbtD/47TJkSFuDJrvrpLuZROeR48opM8kPtMdbFKZxmeUtap/1q1ahBcA8cnkf5t5iEna57OkPfx0FVw7zupFZSD970q8KeQa1C1oRf+DV83rkOqMEzTLmDYZ5YWWILyDb2NrSkBzArhLNhEtWrFFo9uoigwJWiyNGXUkjVd7XUaYvxVYvnHJcmr98l9sW+RxgV2Cm/6ImeW6BkSUjfrJpZlHUecxcHIaDVniSCVzVF7T+tgG0+CxpehmRrPE/qlPTY2DVHuG6ogwjmu7pWr4kW3M6pTmOYICKjkojIhPTAfNDZGNYruJMukEeB2JyxSz+J9jhjPe//9x4JznpCzm/JzCHFO9CfONjHIcUqLa9qxqhmBFpr1U5J7vRir4ch7v8TGtGbcR3833HTUA7EEMu/Ca48XVfGNDmySQs8zgGpj1yzf/lBGbiAzTSp7Zp+ANLu+R3NjeiDUYQbgf3vcpoHL44duk4dzhD+ofFD75PF1SMTluWbeLCSENH9io2pxVDj3I5VhlNxHdbqY1WXb+sDBVr4niIGzQiKqVOV33ghyRpzVJFZ7SaQG7VR/mLL3UnvJuapLYtUV9+/7Si/CHl7m8NntPMvx1nM/Z4t/BN8Z5cdhPn2PLxp9f5VCmCqLlCQDSv94cCTLlatiCTfF7axgE0u7+CWiOUNyyqg/vu0pjTwIA==
 593718ff5844cad7a27ee3eb5adad89ac8550949 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAlxCG6EQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91YptD/9DG76IvubjzVsfX1UiQcV1mqWuSgz/idpeFCrc6Z1dyFB5UmbHKfAaZnrPBR7ly6bGD9+NZupB9A8QRxX92koiq0Hw2ywbwR5oWVrBaDiinIDLiTQTUCPnNMH0FSNrt4Kf9Gj4RqMufZvL+dR0pDYV0n6HP3aGOeTnowNhv0lUbw/Gx20YrcCU9uf3GbgRvMQiFNv9cTJAdQlH++98C8MVLfRU4ZxP11hI7sR8mp1q6ruJoozd0Cta67E6MyC/L2Rp3W89psvvY7DSTg9RwQwoS8I6U9iyQJ16Bb6UgZVV6jqQqOSxWUaPfKUhJLl2ENHH5f3rzoi3NH6jHuy5rq2v9XuvOpQ7LqSi1Ev0oq1xllZiyD4Zm69Z/Is0mxwqPskZGWR5Lh6Uq3Dh0zJW7O5M2m1IHdAYqffHpUr2NgEQVST4VDvO4fR2d7n6+ZNXYbZrpmQ1j4bpOZCEMqWXPfl4HY7a60hWa884mWxtVLGvhYycxnN8r1o5ouS0pAMAI6qEFFW1XFFN4eNDDWl83BkuDa32DTEthoyi15JM5jS7VPDYACdHE3IVqsTsZq7nn60uoFCGpdMcSqrD2mlUd9Z12x8NnCIrxKhlHLkq89OrQAcz8/0bbluGuzm3FHKb+8VQWr0MgkvOLTqqvOqn97oBdKqo0eyT0IPz8QeVYPbZfQ==
+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
--- a/.hgtags	Mon Feb 04 18:14:03 2019 +0300
+++ b/.hgtags	Mon Feb 04 20:35:21 2019 +0300
@@ -188,3 +188,4 @@
 1c8c54cf97256f4468da2eb4dbee24f7f3888e71 4.8.1
 197f092b2cd9691e2a55d198f717b231af9be6f9 4.8.2
 593718ff5844cad7a27ee3eb5adad89ac8550949 4.9rc0
+83377b4b4ae0e9a6b8e579f7b0a693b8cf5c3b10 4.9
--- a/contrib/packaging/debian/copyright	Mon Feb 04 18:14:03 2019 +0300
+++ b/contrib/packaging/debian/copyright	Mon Feb 04 20:35:21 2019 +0300
@@ -3,7 +3,7 @@
 Source: https://www.mercurial-scm.org/
 
 Files: *
-Copyright: 2005-2018, Matt Mackall <mpm@selenic.com> and others.
+Copyright: 2005-2019, Matt Mackall <mpm@selenic.com> and others.
 License: GPL-2+
  This program is free software; you can redistribute it
  and/or modify it under the terms of the GNU General Public
--- a/contrib/win32/ReadMe.html	Mon Feb 04 18:14:03 2019 +0300
+++ b/contrib/win32/ReadMe.html	Mon Feb 04 20:35:21 2019 +0300
@@ -140,7 +140,7 @@
     </p>
 
     <p>
-      Mercurial is Copyright 2005-2018 Matt Mackall and others. See
+      Mercurial is Copyright 2005-2019 Matt Mackall and others. See
       the <tt>Contributors.txt</tt> file for a list of contributors.
     </p>
 
--- a/contrib/win32/mercurial.iss	Mon Feb 04 18:14:03 2019 +0300
+++ b/contrib/win32/mercurial.iss	Mon Feb 04 20:35:21 2019 +0300
@@ -21,7 +21,7 @@
 #endif
 
 [Setup]
-AppCopyright=Copyright 2005-2018 Matt Mackall and others
+AppCopyright=Copyright 2005-2019 Matt Mackall and others
 AppName=Mercurial
 AppVersion={#VERSION}
 #if ARCH == "x64"
@@ -45,7 +45,7 @@
 DefaultDirName={pf}\Mercurial
 SourceDir=..\..
 VersionInfoDescription=Mercurial distributed SCM (version {#VERSION})
-VersionInfoCopyright=Copyright 2005-2018 Matt Mackall and others
+VersionInfoCopyright=Copyright 2005-2019 Matt Mackall and others
 VersionInfoCompany=Matt Mackall and others
 InternalCompressLevel=max
 SolidCompression=true
Binary file contrib/wix/COPYING.rtf has changed
--- a/mercurial/commands.py	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/commands.py	Mon Feb 04 20:35:21 2019 +0300
@@ -6173,7 +6173,7 @@
              util.version())
     license = _(
         "(see https://mercurial-scm.org for more information)\n"
-        "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
+        "\nCopyright (C) 2005-2019 Matt Mackall and others\n"
         "This is free software; see the source for copying conditions. "
         "There is NO\nwarranty; "
         "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
--- a/mercurial/help/config.txt	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/help/config.txt	Mon Feb 04 20:35:21 2019 +0300
@@ -857,6 +857,16 @@
 
     Enabled by default.
 
+``sparse-revlog``
+    Enable or disable the ``sparse-revlog`` delta strategy. This format improves
+    delta re-use inside revlog. For very branchy repositories, it results in a
+    smaller store. For repositories with many revisions, it also helps
+    performance (by using shortened delta chains.)
+
+    Repositories with this on-disk format require Mercurial version 4.7
+
+    Enabled by default.
+
 ``graph``
 ---------
 
--- a/mercurial/help/hg.1.txt	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/help/hg.1.txt	Mon Feb 04 20:35:21 2019 +0300
@@ -112,7 +112,7 @@
 
 Copying
 """""""
-Copyright (C) 2005-2018 Matt Mackall.
+Copyright (C) 2005-2019 Matt Mackall.
 Free use of this software is granted under the terms of the GNU General
 Public License version 2 or any later version.
 
--- a/mercurial/help/hgignore.5.txt	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/help/hgignore.5.txt	Mon Feb 04 20:35:21 2019 +0300
@@ -26,7 +26,7 @@
 Copying
 =======
 This manual page is copyright 2006 Vadim Gelfer.
-Mercurial is copyright 2005-2018 Matt Mackall.
+Mercurial is copyright 2005-2019 Matt Mackall.
 Free use of this software is granted under the terms of the GNU General
 Public License version 2 or any later version.
 
--- a/mercurial/help/hgrc.5.txt	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/help/hgrc.5.txt	Mon Feb 04 20:35:21 2019 +0300
@@ -34,7 +34,7 @@
 Copying
 =======
 This manual page is copyright 2005 Bryan O'Sullivan.
-Mercurial is copyright 2005-2018 Matt Mackall.
+Mercurial is copyright 2005-2019 Matt Mackall.
 Free use of this software is granted under the terms of the GNU General
 Public License version 2 or any later version.
 
--- a/mercurial/localrepo.py	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/localrepo.py	Mon Feb 04 20:35:21 2019 +0300
@@ -2904,7 +2904,6 @@
 
     if scmutil.gdinitconfig(ui):
         requirements.add('generaldelta')
-        # experimental config: format.sparse-revlog
         if ui.configbool('format', 'sparse-revlog'):
             requirements.add(SPARSEREVLOG_REQUIREMENT)
     if ui.configbool('experimental', 'treemanifest'):
--- a/mercurial/revlog.py	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/revlog.py	Mon Feb 04 20:35:21 2019 +0300
@@ -497,6 +497,9 @@
         else:
             raise error.RevlogError(_('unknown version (%d) in revlog %s') %
                                     (fmt, self.indexfile))
+        # sparse-revlog can't be on without general-delta (issue6056)
+        if not self._generaldelta:
+            self._sparserevlog = False
 
         self._storedeltachains = True
 
--- a/mercurial/revlogutils/deltas.py	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/revlogutils/deltas.py	Mon Feb 04 20:35:21 2019 +0300
@@ -755,7 +755,8 @@
     The group order aims at providing fast or small candidates first.
     """
     gdelta = revlog._generaldelta
-    sparse = revlog._sparserevlog
+    # gate sparse behind general-delta because of issue6056
+    sparse = gdelta and revlog._sparserevlog
     curr = len(revlog)
     prev = curr - 1
     deltachain = lambda rev: revlog._deltachain(rev)[0]
--- a/mercurial/subrepo.py	Mon Feb 04 18:14:03 2019 +0300
+++ b/mercurial/subrepo.py	Mon Feb 04 20:35:21 2019 +0300
@@ -115,6 +115,10 @@
                 vfs.unlink(vfs.reljoin(dirname, f))
 
 def _auditsubrepopath(repo, path):
+    # sanity check for potentially unsafe paths such as '~' and '$FOO'
+    if path.startswith('~') or '$' in path or util.expandpath(path) != path:
+        raise error.Abort(_('subrepo path contains illegal component: %s')
+                          % path)
     # auditor doesn't check if the path itself is a symlink
     pathutil.pathauditor(repo.root)(path)
     if repo.wvfs.islink(path):
@@ -403,7 +407,16 @@
         r = ctx.repo()
         root = r.wjoin(path)
         create = allowcreate and not r.wvfs.exists('%s/.hg' % path)
+        # repository constructor does expand variables in path, which is
+        # unsafe since subrepo path might come from untrusted source.
+        if os.path.realpath(util.expandpath(root)) != root:
+            raise error.Abort(_('subrepo path contains illegal component: %s')
+                              % path)
         self._repo = hg.repository(r.baseui, root, create=create)
+        if self._repo.root != root:
+            raise error.ProgrammingError('failed to reject unsafe subrepo '
+                                         'path: %s (expanded to %s)'
+                                         % (root, self._repo.root))
 
         # Propagate the parent's --hidden option
         if r is r.unfiltered():
--- a/setup.py	Mon Feb 04 18:14:03 2019 +0300
+++ b/setup.py	Mon Feb 04 20:35:21 2019 +0300
@@ -1134,7 +1134,7 @@
 if py2exeloaded:
     extra['console'] = [
         {'script':'hg',
-         'copyright':'Copyright (C) 2005-2018 Matt Mackall and others',
+         'copyright':'Copyright (C) 2005-2019 Matt Mackall and others',
          'product_version':version}]
     # sub command of 'build' because 'py2exe' does not handle sub_commands
     build.sub_commands.insert(0, ('build_hgextindex', None))
--- a/tests/test-audit-subrepo.t	Mon Feb 04 18:14:03 2019 +0300
+++ b/tests/test-audit-subrepo.t	Mon Feb 04 20:35:21 2019 +0300
@@ -36,6 +36,372 @@
   abort: path 'sub/.hg' is inside nested repo 'sub'
   [255]
 
+Test absolute path
+------------------
+
+on commit:
+
+  $ hg init absolutepath
+  $ cd absolutepath
+  $ hg init sub
+  $ echo '/sub = sub' >> .hgsub
+  $ hg ci -qAm 'add subrepo "/sub"'
+  abort: path contains illegal component: /sub
+  [255]
+
+prepare tampered repo (including the commit above):
+
+  $ hg import --bypass -qm 'add subrepo "/sub"' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +/sub = sub
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 /sub
+  > EOF
+  $ cd ..
+
+on clone (and update):
+
+  $ hg clone -q absolutepath absolutepath2
+  abort: path contains illegal component: /sub
+  [255]
+
+Test root path
+--------------
+
+on commit:
+
+  $ hg init rootpath
+  $ cd rootpath
+  $ hg init sub
+  $ echo '/ = sub' >> .hgsub
+  $ hg ci -qAm 'add subrepo "/"'
+  abort: path ends in directory separator: /
+  [255]
+
+prepare tampered repo (including the commit above):
+
+  $ hg import --bypass -qm 'add subrepo "/"' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +/ = sub
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 /
+  > EOF
+  $ cd ..
+
+on clone (and update):
+
+  $ hg clone -q rootpath rootpath2
+  abort: path ends in directory separator: /
+  [255]
+
+Test empty path
+---------------
+
+on commit:
+
+  $ hg init emptypath
+  $ cd emptypath
+  $ hg init sub
+  $ echo '= sub' >> .hgsub
+  $ hg ci -qAm 'add subrepo ""'
+  hg: parse error at .hgsub:1: = sub
+  [255]
+
+prepare tampered repo (including the commit above):
+
+  $ hg import --bypass -qm 'add subrepo ""' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > += sub
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000
+  > EOF
+  $ cd ..
+
+on clone (and update):
+
+  $ hg clone -q emptypath emptypath2
+  hg: parse error at .hgsub:1: = sub
+  [255]
+
+Test current path
+-----------------
+
+on commit:
+
+  $ hg init currentpath
+  $ cd currentpath
+  $ hg init sub
+  $ echo '. = sub' >> .hgsub
+  $ hg ci -qAm 'add subrepo "."'
+  abort: subrepo path contains illegal component: .
+  [255]
+
+prepare tampered repo (including the commit above):
+
+  $ hg import --bypass -qm 'add subrepo "."' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +.= sub
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 .
+  > EOF
+  $ cd ..
+
+on clone (and update):
+
+  $ hg clone -q currentpath currentpath2
+  abort: subrepo path contains illegal component: .
+  [255]
+
+Test outer path
+---------------
+
+on commit:
+
+  $ mkdir outerpath
+  $ cd outerpath
+  $ hg init main
+  $ cd main
+  $ hg init ../sub
+  $ echo '../sub = ../sub' >> .hgsub
+  $ hg ci -qAm 'add subrepo "../sub"'
+  abort: path contains illegal component: ../sub
+  [255]
+
+prepare tampered repo (including the commit above):
+
+  $ hg import --bypass -qm 'add subrepo "../sub"' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +../sub = ../sub
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 ../sub
+  > EOF
+  $ cd ..
+
+on clone (and update):
+
+  $ hg clone -q main main2
+  abort: path contains illegal component: ../sub
+  [255]
+  $ cd ..
+
+Test variable expansion
+-----------------------
+
+Subrepository paths shouldn't be expanded, but we fail to handle them
+properly. Any local repository paths are expanded.
+
+on commit:
+
+  $ mkdir envvar
+  $ cd envvar
+  $ hg init main
+  $ cd main
+  $ hg init sub1
+  $ cat <<'EOF' > sub1/hgrc
+  > [hooks]
+  > log = echo pwned
+  > EOF
+  $ hg -R sub1 ci -qAm 'add sub1 files'
+  $ hg -R sub1 log -r. -T '{node}\n'
+  39eb4b4d3e096527668784893a9280578a8f38b8
+  $ echo '$SUB = sub1' >> .hgsub
+  $ SUB=sub1 hg ci -qAm 'add subrepo "$SUB"'
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+
+prepare tampered repo (including the changes above as two commits):
+
+  $ hg import --bypass -qm 'add subrepo "$SUB"' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +$SUB = sub1
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 $SUB
+  > EOF
+  $ hg debugsetparents 0
+  $ hg import --bypass -qm 'update subrepo "$SUB"' - <<'EOF'
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > --- a/.hgsubstate
+  > +++ b/.hgsubstate
+  > @@ -1,1 +1,1 @@
+  > -0000000000000000000000000000000000000000 $SUB
+  > +39eb4b4d3e096527668784893a9280578a8f38b8 $SUB
+  > EOF
+  $ cd ..
+
+on clone (and update) with various substitutions:
+
+  $ hg clone -q main main2
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main2
+
+  $ SUB=sub1 hg clone -q main main3
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main3
+
+  $ SUB=sub2 hg clone -q main main4
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main4
+
+on clone empty subrepo into .hg, then pull (and update), which at least fails:
+
+  $ SUB=.hg hg clone -qr0 main main5
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main5
+  $ test -d main5/.hg/.hg
+  [1]
+  $ SUB=.hg hg -R main5 pull -u
+  pulling from $TESTTMP/envvar/main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  new changesets 7a2f0e59146f
+  .hgsubstate: untracked file differs
+  abort: untracked files in working directory differ from files in requested revision
+  [255]
+  $ cat main5/.hg/hgrc | grep pwned
+  [1]
+
+on clone (and update) into .hg, which at least fails:
+
+  $ SUB=.hg hg clone -q main main6
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main6
+  $ cat main6/.hg/hgrc | grep pwned
+  [1]
+
+on clone (and update) into .hg/* subdir:
+
+  $ SUB=.hg/foo hg clone -q main main7
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main7
+  $ test -d main7/.hg/.hg
+  [1]
+
+on clone (and update) into outer tree:
+
+  $ SUB=../out-of-tree-write hg clone -q main main8
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main8
+
+on clone (and update) into e.g. $HOME, which doesn't work since subrepo paths
+are concatenated prior to variable expansion:
+
+  $ SUB="$TESTTMP/envvar/fakehome" hg clone -q main main9
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls main9 | wc -l
+  \s*0 (re)
+
+  $ ls
+  main
+  main2
+  main3
+  main4
+  main5
+  main6
+  main7
+  main8
+  main9
+  $ cd ..
+
+Test tilde
+----------
+
+The leading tilde may be expanded to $HOME, but it can be a valid subrepo
+path in theory. However, we want to prohibit it as there might be unsafe
+handling of such paths.
+
+on commit:
+
+  $ hg init tilde
+  $ cd tilde
+  $ hg init './~'
+  $ echo '~ = ~' >> .hgsub
+  $ hg ci -qAm 'add subrepo "~"'
+  abort: subrepo path contains illegal component: ~
+  [255]
+
+prepare tampered repo (including the commit above):
+
+  $ hg import --bypass -qm 'add subrepo "~"' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +~ = ~
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 ~
+  > EOF
+  $ cd ..
+
+on clone (and update):
+
+  $ hg clone -q tilde tilde2
+  abort: subrepo path contains illegal component: ~
+  [255]
+
 Test direct symlink traversal
 -----------------------------
 
@@ -130,3 +496,167 @@
   root
 
 #endif
+
+Test symlink traversal by variable expansion
+--------------------------------------------
+
+#if symlink
+
+  $ FAKEHOME="$TESTTMP/envvarsym/fakehome"
+
+on commit:
+
+  $ mkdir envvarsym
+  $ cd envvarsym
+  $ hg init main
+  $ cd main
+  $ ln -s "`echo "$FAKEHOME" | sed 's|\(.\)/.*|\1|'`"
+  $ hg ci -qAm 'add symlink to top-level system directory'
+
+  $ hg init sub1
+  $ echo pwned > sub1/pwned
+  $ hg -R sub1 ci -qAm 'add sub1 files'
+  $ hg -R sub1 log -r. -T '{node}\n'
+  f40c9134ba1b6961e12f250868823f0092fb68a8
+  $ echo '$SUB = sub1' >> .hgsub
+  $ SUB="$FAKEHOME" hg ci -qAm 'add subrepo "$SUB"'
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+
+prepare tampered repo (including the changes above as two commits):
+
+  $ hg import --bypass -qm 'add subrepo "$SUB"' - <<'EOF'
+  > diff --git a/.hgsub b/.hgsub
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsub
+  > @@ -0,0 +1,1 @@
+  > +$SUB = sub1
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > new file mode 100644
+  > --- /dev/null
+  > +++ b/.hgsubstate
+  > @@ -0,0 +1,1 @@
+  > +0000000000000000000000000000000000000000 $SUB
+  > EOF
+  $ hg debugsetparents 1
+  $ hg import --bypass -qm 'update subrepo "$SUB"' - <<'EOF'
+  > diff --git a/.hgsubstate b/.hgsubstate
+  > --- a/.hgsubstate
+  > +++ b/.hgsubstate
+  > @@ -1,1 +1,1 @@
+  > -0000000000000000000000000000000000000000 $SUB
+  > +f40c9134ba1b6961e12f250868823f0092fb68a8 $SUB
+  > EOF
+  $ cd ..
+
+on clone (and update) without fakehome directory:
+
+  $ rm -fR "$FAKEHOME"
+  $ SUB="$FAKEHOME" hg clone -q main main2
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ test -d "$FAKEHOME"
+  [1]
+
+on clone (and update) with empty fakehome directory:
+
+  $ rm -fR "$FAKEHOME"
+  $ mkdir "$FAKEHOME"
+  $ SUB="$FAKEHOME" hg clone -q main main3
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls "$FAKEHOME"
+
+on clone (and update) with non-empty fakehome directory:
+
+  $ rm -fR "$FAKEHOME"
+  $ mkdir "$FAKEHOME"
+  $ touch "$FAKEHOME/a"
+  $ SUB="$FAKEHOME" hg clone -q main main4
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls "$FAKEHOME"
+  a
+
+on clone empty subrepo with non-empty fakehome directory,
+then pull (and update):
+
+  $ rm -fR "$FAKEHOME"
+  $ mkdir "$FAKEHOME"
+  $ touch "$FAKEHOME/a"
+  $ SUB="$FAKEHOME" hg clone -qr1 main main5
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls "$FAKEHOME"
+  a
+  $ test -d "$FAKEHOME/.hg"
+  [1]
+  $ SUB="$FAKEHOME" hg -R main5 pull -u
+  pulling from $TESTTMP/envvarsym/main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  new changesets * (glob)
+  .hgsubstate: untracked file differs
+  abort: untracked files in working directory differ from files in requested revision
+  [255]
+  $ ls "$FAKEHOME"
+  a
+  $ test -d "$FAKEHOME/.hg"
+  [1]
+
+on clone empty subrepo with hg-managed fakehome directory,
+then pull (and update):
+
+  $ rm -fR "$FAKEHOME"
+  $ hg init "$FAKEHOME"
+  $ touch "$FAKEHOME/a"
+  $ hg -R "$FAKEHOME" ci -qAm 'add fakehome file'
+  $ SUB="$FAKEHOME" hg clone -qr1 main main6
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls "$FAKEHOME"
+  a
+  $ SUB="$FAKEHOME" hg -R main6 pull -u
+  pulling from $TESTTMP/envvarsym/main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  new changesets * (glob)
+  .hgsubstate: untracked file differs
+  abort: untracked files in working directory differ from files in requested revision
+  [255]
+  $ ls "$FAKEHOME"
+  a
+
+on clone only symlink with hg-managed fakehome directory,
+then pull (and update):
+
+  $ rm -fR "$FAKEHOME"
+  $ hg init "$FAKEHOME"
+  $ touch "$FAKEHOME/a"
+  $ hg -R "$FAKEHOME" ci -qAm 'add fakehome file'
+  $ SUB="$FAKEHOME" hg clone -qr0 main main7
+  $ ls "$FAKEHOME"
+  a
+  $ SUB="$FAKEHOME" hg -R main7 pull -uf
+  pulling from $TESTTMP/envvarsym/main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 3 changes to 2 files
+  new changesets * (glob)
+  abort: subrepo path contains illegal component: $SUB
+  [255]
+  $ ls "$FAKEHOME"
+  a
+
+  $ cd ..
+
+#endif
--- a/tests/test-help.t	Mon Feb 04 18:14:03 2019 +0300
+++ b/tests/test-help.t	Mon Feb 04 20:35:21 2019 +0300
@@ -1504,6 +1504,8 @@
   
       "usestore"
   
+      "sparse-revlog"
+  
       "profiling"
       -----------
   
--- a/tests/test-init.t	Mon Feb 04 18:14:03 2019 +0300
+++ b/tests/test-init.t	Mon Feb 04 20:35:21 2019 +0300
@@ -268,3 +268,25 @@
   exporting bookmark test
   $ hg -R remote-bookmarks bookmarks
      test                      0:08b9e9f63b32
+
+Check format constraint
+-----------------------
+
+  $ hg init issue6056 --config format.usegeneraldelta=0 --config format.sparse-revlog=0
+  $ cd issue6056
+  $ echo foo > 1
+  $ echo foo > 2
+  $ echo foo > 3
+  $ echo foo > 4
+  $ echo foo > 5
+  $ hg add *
+
+Build a bogus repository (sparserevlog without general delta)
+
+  $ hg commit -m 'initial changesets'
+  $ echo 'sparserevlog' >> .hg/requires
+  $ for x in `$TESTDIR/seq.py 100`; do
+  >     echo $x >> `expr $x % 5 + 1`
+  >     hg commit -m $x
+  > done
+  $ cd ..