comparison cutils/treesum.py @ 337:e89eb63fc319

treesum: .write_file_digest() method: the "size" parameter is now positional and mandatory
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 31 Mar 2025 13:38:57 +0200
parents 0049f486e1cd
children e163e6754071
comparison
equal deleted inserted replaced
336:0049f486e1cd 337:e89eb63fc319
700 sz = "" if self._print_size else None 700 sz = "" if self._print_size else None
701 self._writer.write_file_digest( 701 self._writer.write_file_digest(
702 self._algorithm[1], 702 self._algorithm[1],
703 b"./@/", 703 b"./@/",
704 dir_dgst.digest(), 704 dir_dgst.digest(),
705 size=sz) 705 sz)
706 self._writer.flush() 706 self._writer.flush()
707 else: 707 else:
708 self._generate(os.path.normpath(root), tuple()) 708 self._generate(os.path.normpath(root), tuple())
709 self._writer.finish() 709 self._writer.finish()
710 710
755 else: 755 else:
756 opath = walk.WalkDirEntry.alt_fs(opath) 756 opath = walk.WalkDirEntry.alt_fs(opath)
757 if self._size_only: 757 if self._size_only:
758 self._writer.write_size(opath, None) 758 self._writer.write_size(opath, None)
759 else: 759 else:
760 self._writer.write_file_digest(self._algorithm[1], opath, None) 760 self._writer.write_file_digest(
761 self._algorithm[1], opath, None, None)
761 self._writer.flush() 762 self._writer.flush()
762 return (e.errno, None, None, None) 763 return (e.errno, None, None, None)
763 764
764 # Check whether to accept existing treesum digest files 765 # Check whether to accept existing treesum digest files
765 if self._fnmatcher: 766 if self._fnmatcher:
842 "utf-8")) 843 "utf-8"))
843 self._writer.write_file_digest( 844 self._writer.write_file_digest(
844 collector.algorithm or "MD5", 845 collector.algorithm or "MD5",
845 opath, 846 opath,
846 None, 847 None,
847 size=sz) 848 sz)
848 return (errno.ESRCH, None, None, None) 849 return (errno.ESRCH, None, None, None)
849 # We got all required infos without errors 850 # We got all required infos without errors
850 self._writer.write_accept_treesum_file(fpath) 851 self._writer.write_accept_treesum_file(fpath)
851 if self._size_only: 852 if self._size_only:
852 self._writer.write_size(opath, collector.size) 853 self._writer.write_size(opath, collector.size)
853 else: 854 else:
854 self._writer.write_file_digest( 855 self._writer.write_file_digest(
855 collector.algorithm, opath, collector.digest, 856 collector.algorithm, opath, collector.digest,
856 size=sz) 857 sz)
857 return (0, 858 return (0,
858 collector.algorithm, 859 collector.algorithm,
859 collector.digest, 860 collector.digest,
860 collector.size) 861 collector.size)
861 else: 862 else:
870 util.b(emsg, "utf-8"))) 871 util.b(emsg, "utf-8")))
871 if self._size_only: 872 if self._size_only:
872 self._writer.write_size(opath, None) 873 self._writer.write_size(opath, None)
873 else: 874 else:
874 self._writer.write_file_digest( 875 self._writer.write_file_digest(
875 self._algorithm[1], opath, None, 876 self._algorithm[1], opath, None, None)
876 size=None)
877 return (eno, None, None, None) 877 return (eno, None, None, None)
878 # 878 #
879 # No treesum file: just process normally with digesting 879 # No treesum file: just process normally with digesting
880 # 880 #
881 if self._utf8_mode: 881 if self._utf8_mode:
969 self._writer.write_file_digest( 969 self._writer.write_file_digest(
970 self._algorithm[1], 970 self._algorithm[1],
971 util.interpolate_bytes( 971 util.interpolate_bytes(
972 b"%s/./@%s", opath, special_tag), 972 b"%s/./@%s", opath, special_tag),
973 linkdgst.digest(), 973 linkdgst.digest(),
974 size=sz) 974 sz)
975 else: 975 else:
976 # 976 #
977 # Follow the symlink to special file and/or handle a 977 # Follow the symlink to special file and/or handle a
978 # special file 978 # special file
979 # 979 #
1009 self._writer.write_file_digest( 1009 self._writer.write_file_digest(
1010 self._algorithm[1], 1010 self._algorithm[1],
1011 util.interpolate_bytes( 1011 util.interpolate_bytes(
1012 b"%s/./%s", opath, special_tag), 1012 b"%s/./%s", opath, special_tag),
1013 b"", 1013 b"",
1014 size=sz) 1014 sz)
1015 elif fso.is_dir: 1015 elif fso.is_dir:
1016 assert fso.stat is not None # because .is_dir is True 1016 assert fso.stat is not None # because .is_dir is True
1017 if fso.is_symlink and not self._follow_symlinks.directory: 1017 if fso.is_symlink and not self._follow_symlinks.directory:
1018 linktgt = walk.WalkDirEntry.from_readlink( 1018 linktgt = walk.WalkDirEntry.from_readlink(
1019 os.readlink(fso.path)) 1019 os.readlink(fso.path))
1050 sz = "" if self._print_size else None 1050 sz = "" if self._print_size else None
1051 self._writer.write_file_digest( 1051 self._writer.write_file_digest(
1052 self._algorithm[1], 1052 self._algorithm[1],
1053 util.interpolate_bytes(b"%s/./@/", opath), 1053 util.interpolate_bytes(b"%s/./@/", opath),
1054 linkdgst.digest(), 1054 linkdgst.digest(),
1055 size=sz) 1055 sz)
1056 else: 1056 else:
1057 # 1057 #
1058 # Follow the symlink to dir or handle a "real" directory 1058 # Follow the symlink to dir or handle a "real" directory
1059 # 1059 #
1060 1060
1143 sz = "" if self._print_size else None 1143 sz = "" if self._print_size else None
1144 self._writer.write_file_digest( 1144 self._writer.write_file_digest(
1145 self._algorithm[1], 1145 self._algorithm[1],
1146 util.interpolate_bytes(b"%s/./@", opath), 1146 util.interpolate_bytes(b"%s/./@", opath),
1147 linkdgst.digest(), 1147 linkdgst.digest(),
1148 size=sz) 1148 sz)
1149 else: 1149 else:
1150 # 1150 #
1151 # Follow the symlink to file or handle a "real" file 1151 # Follow the symlink to file or handle a "real" file
1152 # 1152 #
1153 1153
1173 opath) 1173 opath)
1174 if self._size_only: 1174 if self._size_only:
1175 self._writer.write_size(opath, None) 1175 self._writer.write_size(opath, None)
1176 else: 1176 else:
1177 self._writer.write_file_digest( 1177 self._writer.write_file_digest(
1178 self._algorithm[1], opath, None) 1178 self._algorithm[1], opath, None, None)
1179 else: 1179 else:
1180 # 1180 #
1181 # Ok: File has normal stat info 1181 # Ok: File has normal stat info
1182 # 1182 #
1183 # XXX FIXME: Handle special files (fifo, socket, 1183 # XXX FIXME: Handle special files (fifo, socket,
1221 e.errno, 1221 e.errno,
1222 util.b(e.strerror, "utf-8"))) 1222 util.b(e.strerror, "utf-8")))
1223 sz = (fso.stat.st_size if self._print_size 1223 sz = (fso.stat.st_size if self._print_size
1224 else None) 1224 else None)
1225 self._writer.write_file_digest( 1225 self._writer.write_file_digest(
1226 self._algorithm[1], opath, None, 1226 self._algorithm[1], opath, None, sz)
1227 size=sz)
1228 else: 1227 else:
1229 dir_dgst.update(util.interpolate_bytes( 1228 dir_dgst.update(util.interpolate_bytes(
1230 b"%d:%s,%d:%s,", 1229 b"%d:%s,%d:%s,",
1231 len(self._algorithm[1]), 1230 len(self._algorithm[1]),
1232 util.b(self._algorithm[1]), 1231 util.b(self._algorithm[1]),
1233 len(dgst), 1232 len(dgst),
1234 dgst)) 1233 dgst))
1235 sz = (fso.stat.st_size if self._print_size 1234 sz = (fso.stat.st_size if self._print_size
1236 else None) 1235 else None)
1237 self._writer.write_file_digest( 1236 self._writer.write_file_digest(
1238 self._algorithm[1], opath, dgst, 1237 self._algorithm[1], opath, dgst, sz)
1239 size=sz)
1240 self._writer.flush() 1238 self._writer.flush()
1241 opath = join_output_path(top, None) 1239 opath = join_output_path(top, None)
1242 if opath: 1240 if opath:
1243 if self._utf8_mode: 1241 if self._utf8_mode:
1244 opath = walk.WalkDirEntry.alt_u8(opath) 1242 opath = walk.WalkDirEntry.alt_u8(opath)
1254 if self._size_only: 1252 if self._size_only:
1255 self._writer.write_size(opath, dir_size) 1253 self._writer.write_size(opath, dir_size)
1256 else: 1254 else:
1257 sz = dir_size if self._print_size else None 1255 sz = dir_size if self._print_size else None
1258 self._writer.write_file_digest( 1256 self._writer.write_file_digest(
1259 self._algorithm[1], opath, dir_dgst.digest(), size=sz) 1257 self._algorithm[1], opath, dir_dgst.digest(), sz)
1260 self._writer.flush() 1258 self._writer.flush()
1261 return (0, self._algorithm[1], dir_dgst.digest(), dir_size) 1259 return (0, self._algorithm[1], dir_dgst.digest(), dir_size)
1262 1260
1263 1261
1264 def join_output_path(top, name): 1262 def join_output_path(top, name):
1344 required. 1342 required.
1345 1343
1346 """ 1344 """
1347 raise NotImplementedError("write_size") 1345 raise NotImplementedError("write_size")
1348 1346
1349 def write_file_digest(self, algorithm, filename, digest, size=None): 1347 def write_file_digest(self, algorithm, filename, digest, size):
1350 """ 1348 """
1351 1349
1352 If `size` is `None` and the output of a size is required then this 1350 If `size` is `None` and the output of a size is required then this
1353 is an error signal. 1351 is an error signal.
1354 1352
1476 assert isinstance(filename, bytes) 1474 assert isinstance(filename, bytes)
1477 self.write(b"ACCEPT-TREESUM (") 1475 self.write(b"ACCEPT-TREESUM (")
1478 self.write(filename) 1476 self.write(filename)
1479 self.writeln(b")") 1477 self.writeln(b")")
1480 1478
1481 def write_file_digest(self, algorithm, filename, digest, size=None): 1479 def write_file_digest(self, algorithm, filename, digest, size):
1482 assert isinstance(filename, bytes) 1480 assert isinstance(filename, bytes)
1483 if digest is not None: 1481 if digest is not None:
1484 digest = (base64.b64encode(digest) 1482 digest = (base64.b64encode(digest)
1485 if self.use_base64 1483 if self.use_base64
1486 else binascii.hexlify(digest)) 1484 else binascii.hexlify(digest))
1584 def write_accept_treesum_file(self, filename): 1582 def write_accept_treesum_file(self, filename):
1585 assert isinstance(filename, bytes) 1583 assert isinstance(filename, bytes)
1586 self.write(b"ACCEPT-TREESUM\t") 1584 self.write(b"ACCEPT-TREESUM\t")
1587 self.writeln(filename) 1585 self.writeln(filename)
1588 1586
1589 def write_file_digest(self, algorithm, filename, digest, size=None): 1587 def write_file_digest(self, algorithm, filename, digest, size):
1590 assert isinstance(filename, bytes) 1588 assert isinstance(filename, bytes)
1591 if digest is not None: 1589 if digest is not None:
1592 digest = (base64.b64encode(digest) 1590 digest = (base64.b64encode(digest)
1593 if self.use_base64 1591 if self.use_base64
1594 else binascii.hexlify(digest)) 1592 else binascii.hexlify(digest))