diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2524,10 +2524,11 @@ def _dograft(ui, repo, *revs, **opts): revs.remove(ids[n]) elif ctx.hex() in ids: r = ids[ctx.hex()] - ui.warn(_('skipping already grafted revision %d:%s ' - '(was grafted from %d:%s)\n') % - (r, repo[r], rev, ctx)) - revs.remove(r) + if r in revs: + ui.warn(_('skipping already grafted revision %d:%s ' + '(was grafted from %d:%s)\n') % + (r, repo[r], rev, ctx)) + revs.remove(r) if not revs: return -1 diff --git a/mercurial/posix.py b/mercurial/posix.py --- a/mercurial/posix.py +++ b/mercurial/posix.py @@ -181,7 +181,22 @@ def checkexec(path): try: EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - cachedir = os.path.join(path, '.hg', 'cache') + basedir = os.path.join(path, '.hg') + cachedir = os.path.join(basedir, 'cache') + storedir = os.path.join(basedir, 'store') + if not os.path.exists(cachedir): + try: + # we want to create the 'cache' directory, not the '.hg' one. + # Automatically creating '.hg' directory could silently spawn + # invalid Mercurial repositories. That seems like a bad idea. + os.mkdir(cachedir) + if os.path.exists(storedir): + copymode(storedir, cachedir) + else: + copymode(basedir, cachedir) + except (IOError, OSError): + # we other fallback logic triggers + pass if os.path.isdir(cachedir): checkisexec = os.path.join(cachedir, 'checkisexec') checknoexec = os.path.join(cachedir, 'checknoexec') diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -622,7 +622,11 @@ class hgsubrepo(abstractsubrepo): return True self._repo._subsource = source srcurl = _abssource(self._repo) - other = hg.peer(self._repo, {}, srcurl) + + # Defer creating the peer until after the status message is logged, in + # case there are network problems. + getpeer = lambda: hg.peer(self._repo, {}, srcurl) + if len(self._repo) == 0: # use self._repo.vfs instead of self.wvfs to remove .hg only self._repo.vfs.rmtree() @@ -636,7 +640,7 @@ class hgsubrepo(abstractsubrepo): self.ui.status(_('sharing subrepo %s from %s\n') % (subrelpath(self), srcurl)) shared = hg.share(self._repo._subparent.baseui, - other, self._repo.root, + getpeer(), self._repo.root, update=False, bookmarks=False) self._repo = shared.local() else: @@ -657,7 +661,7 @@ class hgsubrepo(abstractsubrepo): self.ui.status(_('cloning subrepo %s from %s\n') % (subrelpath(self), util.hidepassword(srcurl))) other, cloned = hg.clone(self._repo._subparent.baseui, {}, - other, self._repo.root, + getpeer(), self._repo.root, update=False, shareopts=shareopts) self._repo = cloned.local() self._initrepo(parentrepo, source, create=True) @@ -666,7 +670,7 @@ class hgsubrepo(abstractsubrepo): self.ui.status(_('pulling subrepo %s from %s\n') % (subrelpath(self), util.hidepassword(srcurl))) cleansub = self.storeclean(srcurl) - exchange.pull(self._repo, other) + exchange.pull(self._repo, getpeer()) if cleansub: # keep the repo clean after pull self._cachestorehash(srcurl) diff --git a/tests/test-fncache.t b/tests/test-fncache.t --- a/tests/test-fncache.t +++ b/tests/test-fncache.t @@ -88,6 +88,9 @@ Non store repo: .hg/00manifest.i .hg/cache .hg/cache/branch2-served + .hg/cache/checkisexec (execbit !) + .hg/cache/checklink (symlink !) + .hg/cache/checklink-target (symlink !) .hg/cache/manifestfulltextcache (reporevlogstore !) .hg/cache/rbc-names-v1 .hg/cache/rbc-revs-v1 @@ -122,6 +125,9 @@ Non fncache repo: .hg/00changelog.i .hg/cache .hg/cache/branch2-served + .hg/cache/checkisexec (execbit !) + .hg/cache/checklink (symlink !) + .hg/cache/checklink-target (symlink !) .hg/cache/manifestfulltextcache (reporevlogstore !) .hg/cache/rbc-names-v1 .hg/cache/rbc-revs-v1 diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -1422,6 +1422,52 @@ also detecting that both 3 and 5 should $ cd .. +Grafted revision should be warned and skipped only once. (issue6024) + + $ mkdir issue6024 + $ cd issue6024 + + $ hg init base + $ cd base + $ touch x + $ hg commit -qAminit + $ echo a > x + $ hg commit -mchange + $ hg update -q 0 + $ hg graft -r 1 + grafting 1:a0b923c546aa "change" (tip) + $ cd .. + + $ hg clone -qr 2 base clone + $ cd clone + $ hg pull -q + $ hg merge -q 2 + $ hg commit -mmerge + $ hg update -q 0 + $ hg graft -r 1 + grafting 1:04fc6d444368 "change" + $ hg update -q 3 + $ hg log -G -T '{rev}:{node|shortest} <- {extras.source|shortest}\n' + o 4:4e16 <- a0b9 + | + | @ 3:f0ac <- + | |\ + +---o 2:a0b9 <- + | | + | o 1:04fc <- a0b9 + |/ + o 0:7848 <- + + + the source of rev 4 is an ancestor of the working parent, and was also + grafted as rev 1. it should be stripped from the target revisions only once. + + $ hg graft -r 4 + skipping already grafted revision 4:4e16bab40c9c (1:04fc6d444368 also has origin 2:a0b923c546aa) + [255] + + $ cd ../.. + Testing the reading of old format graftstate file with newer mercurial $ hg init oldgraft diff --git a/tests/test-http-bundle1.t b/tests/test-http-bundle1.t --- a/tests/test-http-bundle1.t +++ b/tests/test-http-bundle1.t @@ -340,6 +340,7 @@ clone of serve with repo in root and uns added 3 changesets with 7 changes to 7 files new changesets 8b6053c928fe:56f9bc90cce6 updating to branch default + cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found [255] $ hg clone http://localhost:$HGPORT/ slash-clone @@ -350,6 +351,7 @@ clone of serve with repo in root and uns added 3 changesets with 7 changes to 7 files new changesets 8b6053c928fe:56f9bc90cce6 updating to branch default + cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found [255] diff --git a/tests/test-http.t b/tests/test-http.t --- a/tests/test-http.t +++ b/tests/test-http.t @@ -417,6 +417,7 @@ clone of serve with repo in root and uns added 3 changesets with 7 changes to 7 files new changesets 8b6053c928fe:56f9bc90cce6 updating to branch default + cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found [255] $ hg clone http://localhost:$HGPORT/ slash-clone @@ -427,6 +428,7 @@ clone of serve with repo in root and uns added 3 changesets with 7 changes to 7 files new changesets 8b6053c928fe:56f9bc90cce6 updating to branch default + cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found [255] diff --git a/tests/test-inherit-mode.t b/tests/test-inherit-mode.t --- a/tests/test-inherit-mode.t +++ b/tests/test-inherit-mode.t @@ -69,6 +69,9 @@ new directories are setgid 00600 ./.hg/00changelog.i 00770 ./.hg/cache/ 00660 ./.hg/cache/branch2-served + 00711 ./.hg/cache/checkisexec + 00777 ./.hg/cache/checklink + 00600 ./.hg/cache/checklink-target 00660 ./.hg/cache/manifestfulltextcache (reporevlogstore !) 00660 ./.hg/cache/rbc-names-v1 00660 ./.hg/cache/rbc-revs-v1 diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -22,16 +22,22 @@ share shouldn't have a store dir $ test -d .hg/store [1] -share shouldn't have a cache dir, original repo should +share shouldn't have a full cache dir, original repo should $ hg branches default 0:d3873e73d99e $ hg tags tip 0:d3873e73d99e - $ test -d .hg/cache - [1] + $ ls -1 .hg/cache || true + ls: .hg/cache: $ENOENT$ (no-execbit no-symlink !) + checkisexec (execbit !) + checklink (symlink !) + checklink-target (symlink !) $ ls -1 ../repo1/.hg/cache branch2-served + checkisexec (execbit !) + checklink (symlink !) + checklink-target (symlink !) manifestfulltextcache (reporevlogstore !) rbc-names-v1 rbc-revs-v1 diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -108,6 +108,7 @@ are also available as siblings of 'main' added 1 changesets with 3 changes to 3 files new changesets 7f491f53a367 updating to branch default + cloning subrepo sub1 from http://localhost:$HGPORT/../sub1 abort: HTTP Error 404: Not Found [255] diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t --- a/tests/test-subrepo-recursion.t +++ b/tests/test-subrepo-recursion.t @@ -574,6 +574,7 @@ whereas clone should fail. $ hg --config progress.disable=True clone ../empty2 ../empty_clone updating to branch default + cloning subrepo foo from $TESTTMP/empty2/foo abort: repository $TESTTMP/empty2/foo not found! [255] diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t --- a/tests/test-subrepo.t +++ b/tests/test-subrepo.t @@ -1889,6 +1889,7 @@ test for ssh exploit 2017-07-25 $ cd .. $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default + cloning subrepo s from ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' (in subrepository "s") [255] @@ -1901,6 +1902,7 @@ also check that a percent encoded '-' (% $ rm -r malicious-proxycommand-clone $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default + cloning subrepo s from ssh://-oProxyCommand%3Dtouch%24%7BIFS%7Downed/path abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' (in subrepository "s") [255] @@ -1913,6 +1915,7 @@ also check for a pipe $ rm -r malicious-proxycommand-clone $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default + cloning subrepo s from ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path abort: no suitable response from remote hg! [255] $ [ ! -f owned ] || echo 'you got owned' @@ -1926,6 +1929,7 @@ also check that a percent encoded '|' (% $ rm -r malicious-proxycommand-clone $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default + cloning subrepo s from ssh://fakehost%7Ctouch%20owned/path abort: no suitable response from remote hg! [255] $ [ ! -f owned ] || echo 'you got owned' @@ -1938,6 +1942,7 @@ and bad usernames: $ rm -r malicious-proxycommand-clone $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default + cloning subrepo s from ssh://-oProxyCommand%3Dtouch%20owned@example.com/path abort: potentially unsafe url: 'ssh://-oProxyCommand=touch owned@example.com/path' (in subrepository "s") [255]