Mercurial > hg
changeset 27370:d9e3ebe56970 stable
record: don't dereference symlinks while copying over stat data
Previously, we could be calling os.utime or os.chflags (via shutil.copystat) on
a symlink. These functions dereference symlinks, so this would have caused the
timestamp of the target to be set. On a read-only or similarly weird
filesystem, this might cause an exception to be raised.
This is pretty hard to test because conjuring up a read-only filesystem for
test purposes is non-trivial.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Sat, 12 Dec 2015 10:58:05 -0800 |
parents | c48ecc0b5bc9 |
children | 4eeef1b2d689 00aa37c65e0a |
files | mercurial/cmdutil.py |
diffstat | 1 files changed, 7 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/cmdutil.py Sat Dec 12 11:00:04 2015 -0800 +++ b/mercurial/cmdutil.py Sat Dec 12 10:58:05 2015 -0800 @@ -7,7 +7,7 @@ from node import hex, bin, nullid, nullrev, short from i18n import _ -import os, sys, errno, re, tempfile, cStringIO, shutil +import os, sys, errno, re, tempfile, cStringIO import util, scmutil, templater, patch, error, templatekw, revlog, copies import match as matchmod import repair, graphmod, revset, phases, obsolete, pathutil @@ -166,8 +166,7 @@ dir=backupdir) os.close(fd) ui.debug('backup %r as %r\n' % (f, tmpname)) - util.copyfile(repo.wjoin(f), tmpname) - shutil.copystat(repo.wjoin(f), tmpname) + util.copyfile(repo.wjoin(f), tmpname, copystat=True) backups[f] = tmpname fp = cStringIO.StringIO() @@ -216,15 +215,12 @@ # to be treated as unmodified dirstate.normallookup(realname) - util.copyfile(tmpname, repo.wjoin(realname)) - # Our calls to copystat() here and above are a - # hack to trick any editors that have f open that - # we haven't modified them. + # copystat=True here and above are a hack to trick any + # editors that have f open that we haven't modified them. # - # Also note that this racy as an editor could - # notice the file's mtime before we've finished - # writing it. - shutil.copystat(tmpname, repo.wjoin(realname)) + # Also note that this racy as an editor could notice the + # file's mtime before we've finished writing it. + util.copyfile(tmpname, repo.wjoin(realname), copystat=True) os.unlink(tmpname) if tobackup: os.rmdir(backupdir)