# HG changeset patch # User Franz Glasner # Date 1735943617 -3600 # Node ID b26c4290e9284e941bc1b8ecd02bc2bd1e5238b9 # Parent f84cf853da228c073b1dba1ed491b25dae36dce3 Implement "--mtime" for treesum to include a file's mtime in a directory digest. Pure file diests are not affected. diff -r f84cf853da22 -r b26c4290e928 cutils/treesum.py --- a/cutils/treesum.py Fri Jan 03 23:08:02 2025 +0100 +++ b/cutils/treesum.py Fri Jan 03 23:33:37 2025 +0100 @@ -78,6 +78,11 @@ help="Use mmap if available. Default is to determine " "automatically from the filesize.") gp.add_argument( + "--mtime", action="store_true", dest="metadata_mtime", + help="Consider the mtime of files (non-directories) when " + "generating digests for directories. Digests for files are " + "not affected.") + gp.add_argument( "--no-mmap", action="store_false", dest="mmap", default=None, help="Dont use mmap.") gp.add_argument( @@ -184,6 +189,7 @@ logical=None, minimal=None, mmap=None, + mtime=False, output=None): opts = argparse.Namespace( directories=directories, @@ -196,6 +202,7 @@ logical=logical, minimal=minimal, mmap=mmap, + metadata_mtime=mtime, output=output) return opts @@ -232,13 +239,15 @@ generate_treesum_for_directory( outfp, d, opts.algorithm, opts.mmap, opts.base64, opts.logical, opts.follow_directory_symlinks, + opts.metadata_mtime, minimal=opts.minimal, comment=opts.comment) def generate_treesum_for_directory( outfp, root, algorithm, use_mmap, use_base64, handle_root_logical, - follow_directory_symlinks, minimal=None, comment=None): + follow_directory_symlinks, with_metadata_mtime, + minimal=None, comment=None): """ :param outfp: a *binary* file with a "write()" and a "flush()" method @@ -249,6 +258,8 @@ # Note given non-default flags that are relevant for directory traversal flags = [] + if with_metadata_mtime: + flags.append("with-metadata-mtime") if handle_root_logical: flags.append("logical") if follow_directory_symlinks: @@ -321,6 +332,13 @@ dir_dgst.update(dgst) for fn in nondirs: dir_dgst.update(b"1:f,%d:%s," % (len(fn.fsname), fn.fsname)) + if with_metadata_mtime: + mtime = datetime.datetime.utcfromtimestamp( + int(fn.stat.st_mtime)) + mtime = mtime.isoformat("T") + "Z" + if not isinstance(mtime, bytes): + mtime = mtime.encode("ascii") + dir_dgst.update(b"5:mtime,%d:%s," % (len(mtime), mtime)) dgst = digest.compute_digest_file( algorithm[0], fn.path, use_mmap=use_mmap) dir_dgst.update(dgst)