# HG changeset patch # User Kyle Lippincott # Date 2018-03-08 19:44:03 # Node ID 08890706366ed7856abeb78759916bef1210b4ad # Parent e4640ec346ac34a9c818c6ee5db1e623b0ad5b47 copyfile: preserve stat info (mtime, etc.) when doing copies/renames Differential Revision: https://phab.mercurial-scm.org/D2729 diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py --- a/hgext/largefiles/overrides.py +++ b/hgext/largefiles/overrides.py @@ -667,7 +667,7 @@ def overridecopy(orig, ui, repo, pats, o try: origcopyfile = util.copyfile copiedfiles = [] - def overridecopyfile(src, dest): + def overridecopyfile(src, dest, *args, **kwargs): if (lfutil.shortname in src and dest.startswith(repo.wjoin(lfutil.shortname))): destlfile = dest.replace(lfutil.shortname, '') @@ -675,7 +675,7 @@ def overridecopy(orig, ui, repo, pats, o raise IOError('', _('destination largefile already exists')) copiedfiles.append((src, dest)) - origcopyfile(src, dest) + origcopyfile(src, dest, *args, **kwargs) util.copyfile = overridecopyfile result += orig(ui, repo, listpats, opts, rename) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1192,7 +1192,9 @@ def copy(ui, repo, pats, opts, rename=Fa os.rename(src, tmp) os.rename(tmp, target) else: - util.copyfile(src, target) + # Preserve stat info on renames, not on copies; this matches + # Linux CLI behavior. + util.copyfile(src, target, copystat=rename) srcexists = True except IOError as inst: if inst.errno == errno.ENOENT: diff --git a/tests/test-rename.t b/tests/test-rename.t --- a/tests/test-rename.t +++ b/tests/test-rename.t @@ -657,3 +657,36 @@ check illegal path components [255] $ hg status -C +check that stat information such as mtime is preserved on rename - it's unclear +whether the `touch` and `stat` commands are portable, so we mimic them using +python. Not all platforms support precision of even one-second granularity, so +we allow a rather generous fudge factor here; 1234567890 is 2009, and the +primary thing we care about is that it's not the machine's current time; +hopefully it's really unlikely for a machine to have such a broken clock that +this test fails. :) + + $ mkdir mtime +Create the file (as empty), then update its mtime and atime to be 1234567890. + >>> import os + >>> filename = "mtime/f" + >>> mtime = 1234567890 + >>> open(filename, "w").close() + >>> os.utime(filename, (mtime, mtime)) + $ hg ci -qAm 'add mtime dir' +"hg cp" does not preserve the mtime, so it should be newer than the 2009 +timestamp. + $ hg cp -q mtime mtime_cp + >>> from __future__ import print_function + >>> import os + >>> filename = "mtime_cp/f" + >>> print(os.stat(filename).st_mtime < 1234567999) + False +"hg mv" preserves the mtime, so it should be ~equal to the 2009 timestamp +(modulo some fudge factor due to not every system supporting 1s-level +precision). + $ hg mv -q mtime mtime_mv + >>> from __future__ import print_function + >>> import os + >>> filename = "mtime_mv/f" + >>> print(os.stat(filename).st_mtime < 1234567999) + True