Mercurial > hgrepos > Python > apps > py-cutils
comparison cutils/treesum.py @ 331:9ee84624587f
treesum: move the handling of base64 digest output into the writers completely
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 28 Mar 2025 15:16:12 +0100 |
| parents | 61cbae10103c |
| children | 5b98810fe367 |
comparison
equal
deleted
inserted
replaced
| 330:61cbae10103c | 331:9ee84624587f |
|---|---|
| 537 writerstyle = TabularTreesumWriter | 537 writerstyle = TabularTreesumWriter |
| 538 else: | 538 else: |
| 539 raise NotImplementedError("`output_style'") | 539 raise NotImplementedError("`output_style'") |
| 540 | 540 |
| 541 with out_cm as outfp: | 541 with out_cm as outfp: |
| 542 writer = writerstyle(outfp) | 542 writer = writerstyle(outfp, use_base64=opts.base64) |
| 543 for d in opts.directories: | 543 for d in opts.directories: |
| 544 V1DirectoryTreesumGenerator( | 544 V1DirectoryTreesumGenerator( |
| 545 opts.algorithm, opts.mmap, opts.base64, | 545 opts.algorithm, opts.mmap, |
| 546 opts.follow_symlinks, | 546 opts.follow_symlinks, |
| 547 opts.generator, | 547 opts.generator, |
| 548 opts.metadata_mode, | 548 opts.metadata_mode, |
| 549 opts.metadata_full_mode, | 549 opts.metadata_full_mode, |
| 550 opts.metadata_mtime, | 550 opts.metadata_mtime, |
| 556 writer, d, comment=opts.comment) | 556 writer, d, comment=opts.comment) |
| 557 | 557 |
| 558 | 558 |
| 559 class V1DirectoryTreesumGenerator(object): | 559 class V1DirectoryTreesumGenerator(object): |
| 560 | 560 |
| 561 def __init__(self, algorithm, use_mmap, use_base64, | 561 def __init__(self, algorithm, use_mmap, |
| 562 follow_symlinks, | 562 follow_symlinks, |
| 563 with_generator, | 563 with_generator, |
| 564 with_metadata_mode, with_metadata_full_mode, | 564 with_metadata_mode, with_metadata_full_mode, |
| 565 with_metadata_mtime, size_only, print_size, utf8_mode, | 565 with_metadata_mtime, size_only, print_size, utf8_mode, |
| 566 minimal=None, | 566 minimal=None, |
| 567 fnmatcher=None): | 567 fnmatcher=None): |
| 568 super(V1DirectoryTreesumGenerator, self).__init__() | 568 super(V1DirectoryTreesumGenerator, self).__init__() |
| 569 self._algorithm = algorithm | 569 self._algorithm = algorithm |
| 570 self._use_mmap = use_mmap | 570 self._use_mmap = use_mmap |
| 571 self._use_base64 = use_base64 | |
| 572 self._follow_symlinks = follow_symlinks | 571 self._follow_symlinks = follow_symlinks |
| 573 self._with_generator = with_generator | 572 self._with_generator = with_generator |
| 574 self._with_metadata_mode = with_metadata_mode | 573 self._with_metadata_mode = with_metadata_mode |
| 575 self._with_metadata_full_mode = with_metadata_full_mode | 574 self._with_metadata_full_mode = with_metadata_full_mode |
| 576 self._with_metadata_mtime = with_metadata_mtime | 575 self._with_metadata_mtime = with_metadata_mtime |
| 676 sz = "" if self._print_size else None | 675 sz = "" if self._print_size else None |
| 677 self._writer.write_file_digest( | 676 self._writer.write_file_digest( |
| 678 self._algorithm[1], | 677 self._algorithm[1], |
| 679 b"./@/", | 678 b"./@/", |
| 680 dir_dgst.digest(), | 679 dir_dgst.digest(), |
| 681 self._use_base64, | |
| 682 size=sz) | 680 size=sz) |
| 683 self._writer.flush() | 681 self._writer.flush() |
| 684 else: | 682 else: |
| 685 self._generate(os.path.normpath(root), tuple()) | 683 self._generate(os.path.normpath(root), tuple()) |
| 686 self._writer.finish() | 684 self._writer.finish() |
| 819 "utf-8")) | 817 "utf-8")) |
| 820 self._writer.write_file_digest( | 818 self._writer.write_file_digest( |
| 821 collector.algorithm or "MD5", | 819 collector.algorithm or "MD5", |
| 822 opath, | 820 opath, |
| 823 None, | 821 None, |
| 824 use_base64=self._use_base64, | |
| 825 size=sz) | 822 size=sz) |
| 826 return (errno.ESRCH, None, None, None) | 823 return (errno.ESRCH, None, None, None) |
| 827 # We got all required infos without errors | 824 # We got all required infos without errors |
| 828 self._writer.write_accept_treesum_file(fpath) | 825 self._writer.write_accept_treesum_file(fpath) |
| 829 if self._size_only: | 826 if self._size_only: |
| 830 self._writer.write_size(opath, collector.size) | 827 self._writer.write_size(opath, collector.size) |
| 831 else: | 828 else: |
| 832 self._writer.write_file_digest( | 829 self._writer.write_file_digest( |
| 833 collector.algorithm, opath, collector.digest, | 830 collector.algorithm, opath, collector.digest, |
| 834 use_base64=self._use_base64, size=sz) | 831 size=sz) |
| 835 return (0, | 832 return (0, |
| 836 collector.algorithm, | 833 collector.algorithm, |
| 837 collector.digest, | 834 collector.digest, |
| 838 collector.size) | 835 collector.size) |
| 839 else: | 836 else: |
| 849 if self._size_only: | 846 if self._size_only: |
| 850 self._writer.write_size(opath, None) | 847 self._writer.write_size(opath, None) |
| 851 else: | 848 else: |
| 852 self._writer.write_file_digest( | 849 self._writer.write_file_digest( |
| 853 self._algorithm[1], opath, None, | 850 self._algorithm[1], opath, None, |
| 854 use_base64=self._use_base64, size=None) | 851 size=None) |
| 855 return (eno, None, None, None) | 852 return (eno, None, None, None) |
| 856 # | 853 # |
| 857 # No treesum file: just process normally with digesting | 854 # No treesum file: just process normally with digesting |
| 858 # | 855 # |
| 859 if self._utf8_mode: | 856 if self._utf8_mode: |
| 947 self._writer.write_file_digest( | 944 self._writer.write_file_digest( |
| 948 self._algorithm[1], | 945 self._algorithm[1], |
| 949 util.interpolate_bytes( | 946 util.interpolate_bytes( |
| 950 b"%s/./@%s", opath, special_tag), | 947 b"%s/./@%s", opath, special_tag), |
| 951 linkdgst.digest(), | 948 linkdgst.digest(), |
| 952 self._use_base64, | |
| 953 size=sz) | 949 size=sz) |
| 954 else: | 950 else: |
| 955 # | 951 # |
| 956 # Follow the symlink to special file and/or handle a | 952 # Follow the symlink to special file and/or handle a |
| 957 # special file | 953 # special file |
| 988 self._writer.write_file_digest( | 984 self._writer.write_file_digest( |
| 989 self._algorithm[1], | 985 self._algorithm[1], |
| 990 util.interpolate_bytes( | 986 util.interpolate_bytes( |
| 991 b"%s/./%s", opath, special_tag), | 987 b"%s/./%s", opath, special_tag), |
| 992 b"", | 988 b"", |
| 993 self._use_base64, | |
| 994 size=sz) | 989 size=sz) |
| 995 elif fso.is_dir: | 990 elif fso.is_dir: |
| 996 assert fso.stat is not None # because .is_dir is True | 991 assert fso.stat is not None # because .is_dir is True |
| 997 if fso.is_symlink and not self._follow_symlinks.directory: | 992 if fso.is_symlink and not self._follow_symlinks.directory: |
| 998 linktgt = walk.WalkDirEntry.from_readlink( | 993 linktgt = walk.WalkDirEntry.from_readlink( |
| 1029 else: | 1024 else: |
| 1030 sz = "" if self._print_size else None | 1025 sz = "" if self._print_size else None |
| 1031 self._writer.write_file_digest( | 1026 self._writer.write_file_digest( |
| 1032 self._algorithm[1], | 1027 self._algorithm[1], |
| 1033 util.interpolate_bytes(b"%s/./@/", opath), | 1028 util.interpolate_bytes(b"%s/./@/", opath), |
| 1034 linkdgst.digest(), | 1029 linkdgst.digest()) |
| 1035 self._use_base64) | |
| 1036 else: | 1030 else: |
| 1037 # | 1031 # |
| 1038 # Follow the symlink to dir or handle a "real" directory | 1032 # Follow the symlink to dir or handle a "real" directory |
| 1039 # | 1033 # |
| 1040 | 1034 |
| 1123 sz = "" if self._print_size else None | 1117 sz = "" if self._print_size else None |
| 1124 self._writer.write_file_digest( | 1118 self._writer.write_file_digest( |
| 1125 self._algorithm[1], | 1119 self._algorithm[1], |
| 1126 util.interpolate_bytes(b"%s/./@", opath), | 1120 util.interpolate_bytes(b"%s/./@", opath), |
| 1127 linkdgst.digest(), | 1121 linkdgst.digest(), |
| 1128 self._use_base64, | |
| 1129 size=sz) | 1122 size=sz) |
| 1130 else: | 1123 else: |
| 1131 # | 1124 # |
| 1132 # Follow the symlink to file or handle a "real" file | 1125 # Follow the symlink to file or handle a "real" file |
| 1133 # | 1126 # |
| 1215 dgst)) | 1208 dgst)) |
| 1216 sz = (fso.stat.st_size if self._print_size | 1209 sz = (fso.stat.st_size if self._print_size |
| 1217 else None) | 1210 else None) |
| 1218 self._writer.write_file_digest( | 1211 self._writer.write_file_digest( |
| 1219 self._algorithm[1], opath, dgst, | 1212 self._algorithm[1], opath, dgst, |
| 1220 use_base64=self._use_base64, | |
| 1221 size=sz) | 1213 size=sz) |
| 1222 self._writer.flush() | 1214 self._writer.flush() |
| 1223 opath = join_output_path(top, None) | 1215 opath = join_output_path(top, None) |
| 1224 if opath: | 1216 if opath: |
| 1225 if self._utf8_mode: | 1217 if self._utf8_mode: |
| 1236 if self._size_only: | 1228 if self._size_only: |
| 1237 self._writer.write_size(opath, dir_size) | 1229 self._writer.write_size(opath, dir_size) |
| 1238 else: | 1230 else: |
| 1239 sz = dir_size if self._print_size else None | 1231 sz = dir_size if self._print_size else None |
| 1240 self._writer.write_file_digest( | 1232 self._writer.write_file_digest( |
| 1241 self._algorithm[1], opath, dir_dgst.digest(), | 1233 self._algorithm[1], opath, dir_dgst.digest(), size=sz) |
| 1242 use_base64=self._use_base64, size=sz) | |
| 1243 self._writer.flush() | 1234 self._writer.flush() |
| 1244 return (0, self._algorithm[1], dir_dgst.digest(), dir_size) | 1235 return (0, self._algorithm[1], dir_dgst.digest(), dir_size) |
| 1245 | 1236 |
| 1246 | 1237 |
| 1247 def join_output_path(top, name): | 1238 def join_output_path(top, name): |
| 1294 | 1285 |
| 1295 """ | 1286 """ |
| 1296 | 1287 |
| 1297 LS = util.b(os.linesep) | 1288 LS = util.b(os.linesep) |
| 1298 | 1289 |
| 1299 def __init__(self, outfp): | 1290 def __init__(self, outfp, use_base64=False): |
| 1300 self._outfp = outfp | 1291 self._outfp = outfp |
| 1292 self.use_base64 = use_base64 | |
| 1301 self.reset_crc() | 1293 self.reset_crc() |
| 1302 | 1294 |
| 1303 @property | 1295 @property |
| 1304 def crc(self): | 1296 def crc(self): |
| 1305 return self._crc | 1297 return self._crc |
| 1334 class TaggedTreesumWriter(WriterBase): | 1326 class TaggedTreesumWriter(WriterBase): |
| 1335 | 1327 |
| 1336 """Writer to write treesum digest files in a format similar to BSD | 1328 """Writer to write treesum digest files in a format similar to BSD |
| 1337 digest files. | 1329 digest files. |
| 1338 | 1330 |
| 1339 Provides high-level methods to write data lines. | 1331 Provides high-level methods to write data lines and some very common |
| 1332 attributes that control some aspects of the output format. | |
| 1340 | 1333 |
| 1341 """ | 1334 """ |
| 1342 | 1335 |
| 1343 def __init__(self, outfp, **kwds): | 1336 def __init__(self, outfp, **kwds): |
| 1344 # IGNORE **kwds | 1337 super(TaggedTreesumWriter, self).__init__(outfp, **kwds) |
| 1345 super(TaggedTreesumWriter, self).__init__(outfp) | |
| 1346 | 1338 |
| 1347 def start(self, version): | 1339 def start(self, version): |
| 1348 """Begin a new block, reset the current CRC and write the VERSION | 1340 """Begin a new block, reset the current CRC and write the VERSION |
| 1349 tag. | 1341 tag. |
| 1350 | 1342 |
| 1417 assert isinstance(filename, bytes) | 1409 assert isinstance(filename, bytes) |
| 1418 self.write(b"ACCEPT-TREESUM (") | 1410 self.write(b"ACCEPT-TREESUM (") |
| 1419 self.write(filename) | 1411 self.write(filename) |
| 1420 self.writeln(b")") | 1412 self.writeln(b")") |
| 1421 | 1413 |
| 1422 def write_file_digest(self, algorithm, filename, digest, | 1414 def write_file_digest(self, algorithm, filename, digest, size=None): |
| 1423 use_base64=False, size=None): | |
| 1424 assert isinstance(filename, bytes) | 1415 assert isinstance(filename, bytes) |
| 1425 if digest is not None: | 1416 if digest is not None: |
| 1426 digest = (base64.b64encode(digest) | 1417 digest = (base64.b64encode(digest) |
| 1427 if use_base64 | 1418 if self.use_base64 |
| 1428 else binascii.hexlify(digest)) | 1419 else binascii.hexlify(digest)) |
| 1429 self.write(util.b(algorithm)) | 1420 self.write(util.b(algorithm)) |
| 1430 self.write(b" (") | 1421 self.write(b" (") |
| 1431 self.write(filename) | 1422 self.write(filename) |
| 1432 self.write(b")") | 1423 self.write(b")") |
| 1455 Provides high-level methods to write data lines. | 1446 Provides high-level methods to write data lines. |
| 1456 | 1447 |
| 1457 """ | 1448 """ |
| 1458 | 1449 |
| 1459 def __init__(self, outfp, **kwds): | 1450 def __init__(self, outfp, **kwds): |
| 1460 super(TabularTreesumWriter, self).__init__(outfp) | 1451 super(TabularTreesumWriter, self).__init__(outfp, **kwds) |
| 1461 | 1452 |
| 1462 def start(self, version): | 1453 def start(self, version): |
| 1463 """Begin a new block, reset the current CRC and write the VERSION | 1454 """Begin a new block, reset the current CRC and write the VERSION |
| 1464 tag. | 1455 tag. |
| 1465 | 1456 |
| 1523 def write_accept_treesum_file(self, filename): | 1514 def write_accept_treesum_file(self, filename): |
| 1524 assert isinstance(filename, bytes) | 1515 assert isinstance(filename, bytes) |
| 1525 self.write(b"ACCEPT-TREESUM\t") | 1516 self.write(b"ACCEPT-TREESUM\t") |
| 1526 self.writeln(filename) | 1517 self.writeln(filename) |
| 1527 | 1518 |
| 1528 def write_file_digest(self, algorithm, filename, digest, | 1519 def write_file_digest(self, algorithm, filename, digest, size=None): |
| 1529 use_base64=False, size=None): | |
| 1530 assert isinstance(filename, bytes) | 1520 assert isinstance(filename, bytes) |
| 1531 if digest is not None: | 1521 if digest is not None: |
| 1532 digest = (base64.b64encode(digest) | 1522 digest = (base64.b64encode(digest) |
| 1533 if use_base64 | 1523 if self.use_base64 |
| 1534 else binascii.hexlify(digest)) | 1524 else binascii.hexlify(digest)) |
| 1535 self.write(util.b(algorithm)) | 1525 self.write(util.b(algorithm)) |
| 1536 self.write(b":") | 1526 self.write(b":") |
| 1537 if digest is not None: | 1527 if digest is not None: |
| 1538 self.write(digest) | 1528 self.write(digest) |
