# HG changeset patch # User Pierre-Yves David # Date 2021-05-30 16:08:52 # Node ID 9b841267253ca53aa172bffef277a13596c3ccf0 # Parent 34cc102c73f530365efddcc2e36e48e2ea5bb311 util: add `nb_bytes` argument to `copyfile` to partially copy a file When set, this allow to copy only the first `nb_bytes` of a file. This will be useful for censor/strip operation with revlogv2. Differential Revision: https://phab.mercurial-scm.org/D10798 diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1909,7 +1909,9 @@ def checksignature(func, depth=1): } -def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False): +def copyfile( + src, dest, hardlink=False, copystat=False, checkambig=False, nb_bytes=None +): """copy a file, preserving mode and optionally other stat info like atime/mtime @@ -1918,6 +1920,8 @@ def copyfile(src, dest, hardlink=False, repo.wlock). copystat and checkambig should be exclusive. + + nb_bytes: if set only copy the first `nb_bytes` of the source file. """ assert not (copystat and checkambig) oldstat = None @@ -1937,6 +1941,9 @@ def copyfile(src, dest, hardlink=False, if hardlink: try: oslink(src, dest) + if nb_bytes is not None: + m = "the `nb_bytes` argument is incompatible with `hardlink`" + raise error.ProgrammingError(m) return except (IOError, OSError): pass # fall back to normal copy @@ -1944,6 +1951,9 @@ def copyfile(src, dest, hardlink=False, os.symlink(os.readlink(src), dest) # copytime is ignored for symlinks, but in general copytime isn't needed # for them anyway + if nb_bytes is not None: + m = "cannot use `nb_bytes` on a symlink" + raise error.ProgrammingError(m) else: try: shutil.copyfile(src, dest) @@ -1960,6 +1970,10 @@ def copyfile(src, dest, hardlink=False, oldstat.stat[stat.ST_MTIME] + 1 ) & 0x7FFFFFFF os.utime(dest, (advanced, advanced)) + # We could do something smarter using `copy_file_range` call or similar + if nb_bytes is not None: + with open(dest, mode='r+') as f: + f.truncate(nb_bytes) except shutil.Error as inst: raise error.Abort(stringutil.forcebytestr(inst))