diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -225,7 +225,7 @@ class mercurial_sink(converter_sink): def hascommit(self, rev): if not rev in self.repo and self.clonebranches: - raise util.Abort(_('revision %s not be found in destination ' + raise util.Abort(_('revision %s not found in destination ' 'repository (lookups with clonebranches=true ' 'are not implemented)') % rev) return rev in self.repo diff --git a/hgext/convert/subversion.py b/hgext/convert/subversion.py --- a/hgext/convert/subversion.py +++ b/hgext/convert/subversion.py @@ -1194,5 +1194,5 @@ class svn_sink(converter_sink, commandli if rev in self.childmap: return True raise util.Abort(_('splice map revision %s not found in subversion ' - 'child map (revision lookups are not implemented') + 'child map (revision lookups are not implemented)') % rev) diff --git a/hgext/largefiles/basestore.py b/hgext/largefiles/basestore.py --- a/hgext/largefiles/basestore.py +++ b/hgext/largefiles/basestore.py @@ -8,8 +8,6 @@ '''base class for store implementations and store-related utility code''' -import os -import tempfile import binascii import re @@ -75,13 +73,8 @@ class basestore(object): ui.note(_('getting %s:%s\n') % (filename, hash)) storefilename = lfutil.storepath(self.repo, hash) - storedir = os.path.dirname(storefilename) - - # No need to pass mode='wb' to fdopen(), since mkstemp() already - # opened the file in binary mode. - (tmpfd, tmpfilename) = tempfile.mkstemp( - dir=storedir, prefix=os.path.basename(filename)) - tmpfile = os.fdopen(tmpfd, 'w') + tmpfile = util.atomictempfile(storefilename, + createmode=self.repo.store.createmode) try: hhash = binascii.hexlify(self._getfile(tmpfile, filename, hash)) @@ -93,14 +86,11 @@ class basestore(object): if hhash != "": ui.warn(_('%s: data corruption (expected %s, got %s)\n') % (filename, hash, hhash)) - tmpfile.close() # no-op if it's already closed - os.remove(tmpfilename) + tmpfile.discard() # no-op if it's already closed missing.append(filename) continue - if os.path.exists(storefilename): # Windows - os.remove(storefilename) - os.rename(tmpfilename, storefilename) + tmpfile.close() lfutil.linktousercache(self.repo, hash) success.append((filename, hhash)) diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py --- a/hgext/largefiles/lfutil.py +++ b/hgext/largefiles/lfutil.py @@ -13,7 +13,6 @@ import errno import platform import shutil import stat -import tempfile from mercurial import dirstate, httpconnection, match as match_, util, scmutil from mercurial.i18n import _ @@ -237,11 +236,11 @@ def copytostoreabsolute(repo, file, hash if inusercache(repo.ui, hash): link(usercachepath(repo.ui, hash), storepath(repo, hash)) else: - dst = util.atomictempfile(storepath(repo, hash)) + dst = util.atomictempfile(storepath(repo, hash), + createmode=repo.store.createmode) for chunk in util.filechunkiter(open(file, 'rb')): dst.write(chunk) dst.close() - util.copymode(file, storepath(repo, hash)) linktousercache(repo, hash) def linktousercache(repo, hash): @@ -439,13 +438,6 @@ def islfilesrepo(repo): return ('largefiles' in repo.requirements and util.any(shortname + '/' in f[0] for f in repo.store.datafiles())) -def mkstemp(repo, prefix): - '''Returns a file descriptor and a filename corresponding to a temporary - file in the repo's largefiles store.''' - path = repo.join(longname) - util.makedirs(path) - return tempfile.mkstemp(prefix=prefix, dir=path) - class storeprotonotcapable(Exception): def __init__(self, storetypes): self.storetypes = storetypes diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py --- a/hgext/largefiles/proto.py +++ b/hgext/largefiles/proto.py @@ -20,23 +20,22 @@ def putlfile(repo, proto, sha): user cache.''' proto.redirect() - fd, tmpname = lfutil.mkstemp(repo, prefix='hg-putlfile') - tmpfp = os.fdopen(fd, 'wb+') + tmpfp = util.atomictempfile(lfutil.storepath(repo, sha), + createmode=repo.store.createmode) try: try: proto.getfile(tmpfp) - tmpfp.seek(0) - if sha != lfutil.hexsha1(tmpfp): + tmpfp._fp.seek(0) + if sha != lfutil.hexsha1(tmpfp._fp): raise IOError(0, _('largefile contents do not match hash')) tmpfp.close() - lfutil.copytostoreabsolute(repo, tmpname, sha) + lfutil.linktousercache(repo, sha) except IOError, e: repo.ui.warn(_('largefiles: failed to put %s into store: %s') % (sha, e.strerror)) return wireproto.pushres(1) finally: - tmpfp.close() - os.unlink(tmpname) + tmpfp.discard() return wireproto.pushres(0) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1024,8 +1024,15 @@ def walkchangerevs(repo, match, opts, pr return reversed(revs) def iterfiles(): + pctx = repo['.'] for filename in match.files(): - yield filename, None + if follow: + if filename not in pctx: + raise util.Abort(_('cannot follow file not in parent ' + 'revision: "%s"') % filename) + yield filename, pctx[filename].filenode() + else: + yield filename, None for filename_node in copies: yield filename_node for file_, node in iterfiles(): diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2605,7 +2605,7 @@ def graft(ui, repo, *revs, **opts): repo.dirstate.setparents(current.node(), nullid) repo.dirstate.write() # fix up dirstate for copies and renames - cmdutil.duplicatecopies(repo, ctx.rev(), current.node()) + cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev()) # report any conflicts if stats and stats[3] > 0: # write out state for --continue diff --git a/tests/test-check-code-hg.t b/tests/test-check-code-hg.t --- a/tests/test-check-code-hg.t +++ b/tests/test-check-code-hg.t @@ -3,7 +3,7 @@ $ hg manifest | xargs "$check_code" || echo 'FAILURE IS NOT AN OPTION!!!' - $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0 + $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0 || true contrib/check-code.py:0: > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"), warning: line over 80 characters @@ -654,4 +654,3 @@ tests/test-walkrepo.py:0: > print "Found %d repositories when I should have found 3" % (len(reposet),) warning: line over 80 characters - [123] diff --git a/tests/test-convert-hg-startrev.t b/tests/test-convert-hg-startrev.t --- a/tests/test-convert-hg-startrev.t +++ b/tests/test-convert-hg-startrev.t @@ -115,6 +115,7 @@ Convert from merge parent o 0 "1: add c" files: a b c $ cd conv1 + $ hg up -q Check copy preservation diff --git a/tests/test-convert-splicemap.t b/tests/test-convert-splicemap.t --- a/tests/test-convert-splicemap.t +++ b/tests/test-convert-splicemap.t @@ -203,7 +203,7 @@ Test clonebranches > --splicemap splicemap ordered ordered-hg3 initializing destination ordered-hg3 repository scanning source... - abort: revision 717d54d67e6c31fd75ffef2ff3042bdd98418437 not be found in destination repository (lookups with clonebranches=true are not implemented) + abort: revision 717d54d67e6c31fd75ffef2ff3042bdd98418437 not found in destination repository (lookups with clonebranches=true are not implemented) [255] Test invalid dependency diff --git a/tests/test-largefiles-cache.t b/tests/test-largefiles-cache.t --- a/tests/test-largefiles-cache.t +++ b/tests/test-largefiles-cache.t @@ -1,3 +1,5 @@ + $ "$TESTDIR/hghave" unix-permissions || exit 80 + Create user cache directory $ USERCACHE=`pwd`/cache; export USERCACHE @@ -70,3 +72,50 @@ Update working directory to tip, again. 0 largefiles updated, 0 removed $ hg status ! large + +Portable way to print file permissions: + + $ cd .. + $ cat > ls-l.py < #!/usr/bin/env python + > import sys, os + > path = sys.argv[1] + > print '%03o' % (os.lstat(path).st_mode & 0777) + > EOF + $ chmod +x ls-l.py + +Test that files in .hg/largefiles inherit mode from .hg/store, not +from file in working copy: + + $ cd src + $ chmod 750 .hg/store + $ chmod 660 large + $ echo change >> large + $ hg commit -m change + $ ../ls-l.py .hg/largefiles/e151b474069de4ca6898f67ce2f2a7263adf8fea + 640 + +Test permission of with files in .hg/largefiles created by update: + + $ cd ../mirror + $ rm -r "$USERCACHE" .hg/largefiles # avoid links + $ chmod 750 .hg/store + $ hg pull ../src --update -q + $ ../ls-l.py .hg/largefiles/e151b474069de4ca6898f67ce2f2a7263adf8fea + 640 + +Test permission of files created by push: + + $ hg serve -R ../src -d -p $HGPORT --pid-file hg.pid \ + > --config "web.allow_push=*" --config web.push_ssl=no + $ cat hg.pid >> $DAEMON_PIDS + + $ echo change >> large + $ hg commit -m change + + $ rm -r "$USERCACHE" + + $ hg push -q http://localhost:$HGPORT/ + + $ ../ls-l.py ../src/.hg/largefiles/b734e14a0971e370408ab9bce8d56d8485e368a9 + 640 diff --git a/tests/test-log.t b/tests/test-log.t --- a/tests/test-log.t +++ b/tests/test-log.t @@ -1,20 +1,28 @@ $ "$TESTDIR/hghave" execbit || exit 80 +The g is crafted to have 2 filelog topological heads in a linear +changeset graph + $ hg init a - $ cd a $ echo a > a + $ echo f > f $ hg ci -Ama -d '1 0' adding a + adding f $ hg cp a b + $ hg cp f g $ hg ci -mb -d '2 0' $ mkdir dir $ hg mv b dir + $ echo g >> g + $ echo f >> f $ hg ci -mc -d '3 0' $ hg mv a b + $ hg cp -f f g $ echo a > d $ hg add d $ hg ci -md -d '4 0' @@ -23,7 +31,7 @@ $ hg ci -me -d '5 0' $ hg log a - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 summary: a @@ -32,34 +40,34 @@ -f, directory $ hg log -f dir - abort: cannot follow nonexistent file: "dir" + abort: cannot follow file not in parent revision: "dir" [255] -f, but no args $ hg log -f - changeset: 4:66c1345dc4f9 + changeset: 4:7e4639b4691b tag: tip user: test date: Thu Jan 01 00:00:05 1970 +0000 summary: e - changeset: 3:7c6c671bb7cc + changeset: 3:2ca5ba701980 user: test date: Thu Jan 01 00:00:04 1970 +0000 summary: d - changeset: 2:41dd4284081e + changeset: 2:f8954cd4dc1f user: test date: Thu Jan 01 00:00:03 1970 +0000 summary: c - changeset: 1:784de7cef101 + changeset: 1:d89b0a12d229 user: test date: Thu Jan 01 00:00:02 1970 +0000 summary: b - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 summary: a @@ -67,11 +75,12 @@ one rename + $ hg up -q 2 $ hg log -vf a - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 - files: a + files: a f description: a @@ -79,8 +88,9 @@ one rename many renames + $ hg up -q tip $ hg log -vf e - changeset: 4:66c1345dc4f9 + changeset: 4:7e4639b4691b tag: tip user: test date: Thu Jan 01 00:00:05 1970 +0000 @@ -89,26 +99,26 @@ many renames e - changeset: 2:41dd4284081e + changeset: 2:f8954cd4dc1f user: test date: Thu Jan 01 00:00:03 1970 +0000 - files: b dir/b + files: b dir/b f g description: c - changeset: 1:784de7cef101 + changeset: 1:d89b0a12d229 user: test date: Thu Jan 01 00:00:02 1970 +0000 - files: b + files: b g description: b - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 - files: a + files: a f description: a @@ -117,35 +127,36 @@ many renames log -pf dir/b + $ hg up -q 3 $ hg log -pf dir/b - changeset: 2:41dd4284081e + changeset: 2:f8954cd4dc1f user: test date: Thu Jan 01 00:00:03 1970 +0000 summary: c - diff -r 784de7cef101 -r 41dd4284081e dir/b + diff -r d89b0a12d229 -r f8954cd4dc1f dir/b --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000 @@ -0,0 +1,1 @@ +a - changeset: 1:784de7cef101 + changeset: 1:d89b0a12d229 user: test date: Thu Jan 01 00:00:02 1970 +0000 summary: b - diff -r 8580ff50825a -r 784de7cef101 b + diff -r 9161b9aeaf16 -r d89b0a12d229 b --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/b Thu Jan 01 00:00:02 1970 +0000 @@ -0,0 +1,1 @@ +a - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 summary: a - diff -r 000000000000 -r 8580ff50825a a + diff -r 000000000000 -r 9161b9aeaf16 a --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/a Thu Jan 01 00:00:01 1970 +0000 @@ -0,0 +1,1 @@ @@ -155,39 +166,53 @@ log -pf dir/b log -vf dir/b $ hg log -vf dir/b - changeset: 2:41dd4284081e + changeset: 2:f8954cd4dc1f user: test date: Thu Jan 01 00:00:03 1970 +0000 - files: b dir/b + files: b dir/b f g description: c - changeset: 1:784de7cef101 + changeset: 1:d89b0a12d229 user: test date: Thu Jan 01 00:00:02 1970 +0000 - files: b + files: b g description: b - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 - files: a + files: a f description: a +-f and multiple filelog heads + + $ hg up -q 2 + $ hg log -f g --template '{rev}\n' + 2 + 1 + 0 + $ hg up -q tip + $ hg log -f g --template '{rev}\n' + 3 + 2 + 0 + + log copies with --copies $ hg log -vC --template '{rev} {file_copies}\n' 4 e (dir/b) - 3 b (a) + 3 b (a)g (f) 2 dir/b (b) - 1 b (a) + 1 b (a)g (f) 0 log copies switch without --copies, with old filecopy template @@ -203,16 +228,16 @@ log copies switch with --copies $ hg log -vC --template '{rev} {file_copies_switch}\n' 4 e (dir/b) - 3 b (a) + 3 b (a)g (f) 2 dir/b (b) - 1 b (a) + 1 b (a)g (f) 0 log copies with hardcoded style and with --style=default $ hg log -vC -r4 - changeset: 4:66c1345dc4f9 + changeset: 4:7e4639b4691b tag: tip user: test date: Thu Jan 01 00:00:05 1970 +0000 @@ -223,7 +248,7 @@ log copies with hardcoded style and with $ hg log -vC -r4 --style=default - changeset: 4:66c1345dc4f9 + changeset: 4:7e4639b4691b tag: tip user: test date: Thu Jan 01 00:00:05 1970 +0000 @@ -259,15 +284,15 @@ log copies, execute bit set log -p d $ hg log -pv d - changeset: 3:7c6c671bb7cc + changeset: 3:2ca5ba701980 user: test date: Thu Jan 01 00:00:04 1970 +0000 - files: a b d + files: a b d g description: d - diff -r 41dd4284081e -r 7c6c671bb7cc d + diff -r f8954cd4dc1f -r 2ca5ba701980 d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/d Thu Jan 01 00:00:04 1970 +0000 @@ -0,0 +1,1 @@ @@ -278,18 +303,18 @@ log -p d log --removed file $ hg log --removed -v a - changeset: 3:7c6c671bb7cc + changeset: 3:2ca5ba701980 user: test date: Thu Jan 01 00:00:04 1970 +0000 - files: a b d + files: a b d g description: d - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 - files: a + files: a f description: a @@ -298,10 +323,10 @@ log --removed file log --removed revrange file $ hg log --removed -v -r0:2 a - changeset: 0:8580ff50825a + changeset: 0:9161b9aeaf16 user: test date: Thu Jan 01 00:00:01 1970 +0000 - files: a + files: a f description: a