--- a/mercurial/hgweb/webcommands.py Sat Nov 12 03:06:07 2016 +0000
+++ b/mercurial/hgweb/webcommands.py Wed Nov 16 23:29:28 2016 -0500
@@ -861,12 +861,24 @@
f = fctx.path()
parity = paritygen(web.stripecount)
+ # parents() is called once per line and several lines likely belong to
+ # same revision. So it is worth caching.
+ # TODO there are still redundant operations within basefilectx.parents()
+ # and from the fctx.annotate() call itself that could be cached.
+ parentscache = {}
def parents(f):
- for p in f.parents():
- yield {
- "node": p.hex(),
- "rev": p.rev(),
- }
+ rev = f.rev()
+ if rev not in parentscache:
+ parentscache[rev] = []
+ for p in f.parents():
+ entry = {
+ 'node': p.hex(),
+ 'rev': p.rev(),
+ }
+ parentscache[rev].append(entry)
+
+ for p in parentscache[rev]:
+ yield p
def annotate(**map):
if util.binary(fctx.data()):
--- a/mercurial/scmutil.py Sat Nov 12 03:06:07 2016 +0000
+++ b/mercurial/scmutil.py Wed Nov 16 23:29:28 2016 -0500
@@ -392,8 +392,7 @@
newstat = util.filestat(dstpath)
if newstat.isambig(oldstat):
# stat of renamed file is ambiguous to original one
- advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
- os.utime(dstpath, (advanced, advanced))
+ newstat.avoidambig(dstpath, oldstat)
return ret
return util.rename(self.join(src), dstpath)
@@ -1460,8 +1459,7 @@
newstat = util.filestat(self._origfh.name)
if newstat.isambig(oldstat):
# stat of changed file is ambiguous to original one
- advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
- os.utime(self._origfh.name, (advanced, advanced))
+ newstat.avoidambig(self._origfh.name, oldstat)
def __exit__(self, exc_type, exc_value, exc_tb):
self._origfh.__exit__(exc_type, exc_value, exc_tb)
--- a/mercurial/util.py Sat Nov 12 03:06:07 2016 +0000
+++ b/mercurial/util.py Wed Nov 16 23:29:28 2016 -0500
@@ -1499,6 +1499,24 @@
except AttributeError:
return False
+ def avoidambig(self, path, old):
+ """Change file stat of specified path to avoid ambiguity
+
+ 'old' should be previous filestat of 'path'.
+
+ This skips avoiding ambiguity, if a process doesn't have
+ appropriate privileges for 'path'.
+ """
+ advanced = (old.stat.st_mtime + 1) & 0x7fffffff
+ try:
+ os.utime(path, (advanced, advanced))
+ except OSError as inst:
+ if inst.errno == errno.EPERM:
+ # utime() on the file created by another user causes EPERM,
+ # if a process doesn't have appropriate privileges
+ return
+ raise
+
def __ne__(self, other):
return not self == other