# HG changeset patch # User Franz Glasner # Date 1736250517 -3600 # Node ID d8cdd1985d43ce6c12275708cbd54fcb9c919ba1 # Parent 27d1aaf5fe3973a466ceb0d92def4bf949efc19c Implement "--full-mode" for "treesum.py" diff -r 27d1aaf5fe39 -r d8cdd1985d43 cutils/treesum.py --- a/cutils/treesum.py Mon Jan 06 21:03:10 2025 +0100 +++ b/cutils/treesum.py Tue Jan 07 12:48:37 2025 +0100 @@ -65,6 +65,12 @@ "\"--logical\" or \"--physical\" for arguments given " "directly on the command line") gp.add_argument( + "--full-mode", action="store_true", dest="metadata_full_mode", + help="Consider all mode bits as returned from stat(2) when " + "computing directory digests. " + "Note that mode bits on symbolic links itself are not " + "considered.") + gp.add_argument( "--logical", "-L", dest="logical", action="store_true", default=None, help="Follow symbolic links given on command line arguments." @@ -80,10 +86,10 @@ "automatically from the filesize.") gp.add_argument( "--mode", action="store_true", dest="metadata_mode", - help="Consider the permission bits of stat using S_IMODE (i.e. " + help="Consider the permission bits of stat(2) using S_IMODE (i.e. " "all bits without the filetype bits) when " - "computing directory digests. Note that symbolic links " - "are not considered.") + "computing directory digests. Note that mode bits on " + "symbolic links itself are not considered.") gp.add_argument( "--mtime", action="store_true", dest="metadata_mtime", help="Consider the mtime of files (non-directories) when " @@ -194,6 +200,7 @@ base64=False, comment=[], follow_directory_symlinks=False, + full_mode=False, logical=None, minimal=None, mode=False, @@ -211,6 +218,7 @@ logical=logical, minimal=minimal, mmap=mmap, + metadata_full_mode=full_mode, metadata_mode=mode, metadata_mtime=mtime, output=output) @@ -250,6 +258,7 @@ outfp, d, opts.algorithm, opts.mmap, opts.base64, opts.logical, opts.follow_directory_symlinks, opts.metadata_mode, + opts.metadata_full_mode, opts.metadata_mtime, minimal=opts.minimal, comment=opts.comment) @@ -257,7 +266,8 @@ def generate_treesum_for_directory( outfp, root, algorithm, use_mmap, use_base64, handle_root_logical, - follow_directory_symlinks, with_metadata_mode, with_metadata_mtime, + follow_directory_symlinks, with_metadata_mode, with_metadata_full_mode, + with_metadata_mtime, minimal=None, comment=None): """ @@ -322,8 +332,9 @@ follow_symlinks=follow_directory_symlinks): dir_dgst = algorithm[0]() for fso in fsobjects: - # print("NNNNNNNN", fso.name, fso.stat, - # "%o (%o)" % (fso.stat.st_mode, stat.S_IMODE(fso.stat.st_mode))) + print("NNNNNNNN", fso.name, fso.stat, + "%o (%o)" + % (fso.stat.st_mode, stat.S_IMODE(fso.stat.st_mode))) if fso.is_dir: if fso.is_symlink and not follow_directory_symlinks: linktgt = util.fsencode(os.readlink(fso.path)) @@ -346,10 +357,16 @@ dgst = dir_digests[top + (fso.name,)] dir_dgst.update(b"1:d,%d:%s," % (len(fso.fsname), fso.fsname)) dir_dgst.update(dgst) - if with_metadata_mode: + if with_metadata_full_mode: modestr = normalized_mode_str(fso.stat.st_mode) if not isinstance(modestr, bytes): modestr = modestr.encode("ascii") + dir_dgst.update(b"8:fullmode,%d:%s," + % (len(modestr), modestr)) + elif with_metadata_mode: + modestr = normalized_compatible_mode_str(fso.stat.st_mode) + if not isinstance(modestr, bytes): + modestr = modestr.encode("ascii") dir_dgst.update(b"4:mode,%d:%s," % (len(modestr), modestr)) else: dir_dgst.update(b"1:f,%d:%s," % (len(fso.fsname), fso.fsname)) @@ -360,10 +377,16 @@ if not isinstance(mtime, bytes): mtime = mtime.encode("ascii") dir_dgst.update(b"5:mtime,%d:%s," % (len(mtime), mtime)) - if with_metadata_mode: + if with_metadata_full_mode: modestr = normalized_mode_str(fso.stat.st_mode) if not isinstance(modestr, bytes): modestr = modestr.encode("ascii") + dir_dgst.update(b"8:fullmode,%d:%s," + % (len(modestr), modestr)) + elif with_metadata_mode: + modestr = normalized_compatible_mode_str(fso.stat.st_mode) + if not isinstance(modestr, bytes): + modestr = modestr.encode("ascii") dir_dgst.update(b"4:mode,%d:%s," % (len(modestr), modestr)) dgst = digest.compute_digest_file( algorithm[0], fso.path, use_mmap=use_mmap) @@ -380,7 +403,7 @@ dir_digests[top] = dir_dgst.digest() -def normalized_mode_str(mode): +def normalized_compatible_mode_str(mode): # XXX FIXME: Windows and "executable" modebits = stat.S_IMODE(mode) modestr = "%o" % (modebits,) @@ -389,6 +412,13 @@ return modestr +def normalized_mode_str(mode): + modestr = "%o" % (mode,) + if not modestr.startswith("0"): + modestr = "0" + modestr + return modestr + + def format_bsd_line(digestname, value, filename, use_base64): ls = os.linesep if isinstance(os.linesep, bytes) \ else os.linesep.encode("utf-8")