comparison cutils/treesum.py @ 178:dac26a2d9de5

Cleanup: remove non used walk-code
author Franz Glasner <fzglas.hg@dom66.de>
date Sat, 11 Jan 2025 21:18:53 +0100
parents 089c40240061
children 53614a724bf0
comparison
equal deleted inserted replaced
177:089c40240061 178:dac26a2d9de5
291 opts.size_only, 291 opts.size_only,
292 opts.print_size, 292 opts.print_size,
293 minimal=opts.minimal).generate( 293 minimal=opts.minimal).generate(
294 outfp, d, comment=opts.comment) 294 outfp, d, comment=opts.comment)
295 295
296 generate_treesum_for_directory(
297 outfp, d, opts.algorithm, opts.mmap, opts.base64, opts.logical,
298 opts.follow_directory_symlinks,
299 opts.metadata_mode,
300 opts.metadata_full_mode,
301 opts.metadata_mtime,
302 opts.size_only,
303 opts.print_size,
304 minimal=opts.minimal,
305 comment=opts.comment)
306
307 296
308 class V1DirectoryTreesumGenerator(object): 297 class V1DirectoryTreesumGenerator(object):
309 298
310 def __init__(self, algorithm, use_mmap, use_base64, 299 def __init__(self, algorithm, use_mmap, use_base64,
311 handle_root_logical, follow_directory_symlinks, 300 handle_root_logical, follow_directory_symlinks,
529 self._outfp.write(format_bsd_line( 518 self._outfp.write(format_bsd_line(
530 self._algorithm[1], dir_dgst.digest(), opath, 519 self._algorithm[1], dir_dgst.digest(), opath,
531 self._use_base64)) 520 self._use_base64))
532 self._outfp.flush() 521 self._outfp.flush()
533 return (dir_dgst.digest(), dir_size) 522 return (dir_dgst.digest(), dir_size)
534
535
536 def generate_treesum_for_directory(
537 outfp, root, algorithm, use_mmap, use_base64, handle_root_logical,
538 follow_directory_symlinks, with_metadata_mode, with_metadata_full_mode,
539 with_metadata_mtime, size_only, print_size,
540 minimal=None, comment=None):
541 """
542
543 :param outfp: a *binary* file with a "write()" and a "flush()" method
544
545 """
546 outfp.write(format_bsd_line("VERSION", "1", None, False))
547 outfp.flush()
548
549 # Note given non-default flags that are relevant for directory traversal
550 flags = []
551 if with_metadata_full_mode:
552 flags.append("with-metadata-fullmode")
553 elif with_metadata_mode:
554 flags.append("with-metadata-mode")
555 if with_metadata_mtime:
556 flags.append("with-metadata-mtime")
557 if handle_root_logical:
558 flags.append("logical")
559 if follow_directory_symlinks:
560 flags.append("follow-directory-symlinks")
561 if size_only:
562 flags.append("size-only")
563 else:
564 if print_size:
565 flags.append("print-size")
566 if flags:
567 flags.sort()
568 outfp.write(format_bsd_line("FLAGS", ",".join(flags), None, False))
569 outfp.flush()
570
571 if minimal is None:
572 # Write execution timestamps in POSIX epoch and ISO format
573 ts = int(time.time())
574 outfp.write(format_bsd_line("TIMESTAMP", ts, None, False))
575 ts = (datetime.datetime.utcfromtimestamp(ts)).isoformat("T")
576 outfp.write(format_bsd_line("ISOTIMESTAMP", ts, None, False))
577 outfp.flush()
578
579 if comment:
580 for line in comment:
581 outfp.write(format_bsd_line("COMMENT", None, line, False))
582
583 if minimal is not None:
584 outfp.write(
585 format_bsd_line(
586 "ROOT", None, minimal if minimal else "", False))
587 else:
588 outfp.write(format_bsd_line("ROOT", None, root, False))
589 outfp.flush()
590
591 dir_digests = {}
592
593 if not handle_root_logical and os.path.islink(root):
594 linktgt = util.fsencode(os.readlink(root))
595 linkdgst = algorithm[0]()
596 linkdgst.update(
597 util.interpolate_bytes(b"%d:%s,", len(linktgt), linktgt))
598 dir_dgst = algorithm[0]()
599 dir_dgst.update(b"1:L,")
600 dir_dgst.update(
601 util.interpolate_bytes(
602 b"%d:%s,", len(linkdgst.digest()), linkdgst.digest()))
603 if size_only:
604 outfp.write(
605 format_bsd_line(
606 "SIZE",
607 None,
608 "./@",
609 False,
610 0))
611 else:
612 outfp.write(
613 format_bsd_line(
614 algorithm[1],
615 dir_dgst.digest(),
616 "./@",
617 use_base64))
618 outfp.flush()
619 return
620
621 for top, fsobjects in walk.walk(
622 root,
623 follow_symlinks=follow_directory_symlinks):
624 dir_dgst = algorithm[0]()
625 dir_size = 0
626
627 for fso in fsobjects:
628 if fso.is_dir:
629 if fso.is_symlink and not follow_directory_symlinks:
630 linktgt = util.fsencode(os.readlink(fso.path))
631 linkdgst = algorithm[0]()
632 linkdgst.update(
633 util.interpolate_bytes(
634 b"%d:%s,", len(linktgt), linktgt))
635 dir_dgst.update(util.interpolate_bytes(
636 b"1:S,%d:%s,", len(fso.fsname), fso.fsname))
637 # no mtime and no mode for symlinks
638 dir_dgst.update(util.interpolate_bytes(
639 b"%d:%s,",
640 len(linkdgst.digest()), linkdgst.digest()))
641 opath = "/".join(top) + "/" + fso.name if top else fso.name
642 if size_only:
643 outfp.write(
644 format_bsd_line(
645 "SIZE",
646 None,
647 "%s/./@" % (opath,),
648 False,
649 0))
650 else:
651 outfp.write(
652 format_bsd_line(
653 algorithm[1],
654 linkdgst.digest(),
655 "%s/./@" % (opath,),
656 use_base64))
657 outfp.flush()
658 continue
659 # fetch from dir_digests
660 dgst, dsz = dir_digests[top + (fso.name,)]
661 dir_size += dsz
662 dir_dgst.update(util.interpolate_bytes(
663 b"1:d,%d:%s,", len(fso.fsname), fso.fsname))
664 dir_dgst.update(util.interpolate_bytes(
665 b"%d:%s,", len(dgst), dgst))
666 if with_metadata_full_mode:
667 modestr = normalized_mode_str(fso.stat.st_mode)
668 if not isinstance(modestr, bytes):
669 modestr = modestr.encode("ascii")
670 dir_dgst.update(util.interpolate_bytes(
671 b"8:fullmode,%d:%s,", len(modestr), modestr))
672 elif with_metadata_mode:
673 modestr = normalized_compatible_mode_str(fso.stat.st_mode)
674 if not isinstance(modestr, bytes):
675 modestr = modestr.encode("ascii")
676 dir_dgst.update(util.interpolate_bytes(
677 b"4:mode,%d:%s,", len(modestr), modestr))
678 else:
679 dir_dgst.update(util.interpolate_bytes(
680 b"1:f,%d:%s,", len(fso.fsname), fso.fsname))
681 dir_size += fso.stat.st_size
682 if with_metadata_mtime:
683 mtime = datetime.datetime.utcfromtimestamp(
684 int(fso.stat.st_mtime))
685 mtime = mtime.isoformat("T") + "Z"
686 if not isinstance(mtime, bytes):
687 mtime = mtime.encode("ascii")
688 dir_dgst.update(util.interpolate_bytes(
689 b"5:mtime,%d:%s,", len(mtime), mtime))
690 if with_metadata_full_mode:
691 modestr = normalized_mode_str(fso.stat.st_mode)
692 if not isinstance(modestr, bytes):
693 modestr = modestr.encode("ascii")
694 dir_dgst.update(util.interpolate_bytes(
695 b"8:fullmode,%d:%s,", len(modestr), modestr))
696 elif with_metadata_mode:
697 modestr = normalized_compatible_mode_str(fso.stat.st_mode)
698 if not isinstance(modestr, bytes):
699 modestr = modestr.encode("ascii")
700 dir_dgst.update(util.interpolate_bytes(
701 b"4:mode,%d:%s,", len(modestr), modestr))
702 if not size_only:
703 dgst = digest.compute_digest_file(
704 algorithm[0], fso.path, use_mmap=use_mmap)
705 dir_dgst.update(util.interpolate_bytes(
706 b"%d:%s,", len(dgst), dgst))
707 opath = "/".join(top) + "/" + fso.name if top else fso.name
708 if size_only:
709 outfp.write(
710 format_bsd_line(
711 "SIZE", None, opath, False, fso.stat.st_size))
712 else:
713 if print_size:
714 outfp.write(
715 format_bsd_line(
716 algorithm[1], dgst, opath, use_base64,
717 fso.stat.st_size))
718 else:
719 outfp.write(
720 format_bsd_line(
721 algorithm[1], dgst, opath, use_base64))
722 outfp.flush()
723 opath = "/".join(top) + "/" if top else ""
724 if size_only:
725 outfp.write(format_bsd_line(
726 "SIZE", None, opath, False, dir_size))
727 else:
728 if print_size:
729 outfp.write(format_bsd_line(
730 algorithm[1], dir_dgst.digest(), opath,
731 use_base64, dir_size))
732 else:
733 outfp.write(format_bsd_line(
734 algorithm[1], dir_dgst.digest(), opath, use_base64))
735 outfp.flush()
736 dir_digests[top] = (dir_dgst.digest(), dir_size)
737 523
738 524
739 def normalized_compatible_mode_str(mode): 525 def normalized_compatible_mode_str(mode):
740 # XXX FIXME: Windows and "executable" 526 # XXX FIXME: Windows and "executable"
741 modebits = stat.S_IMODE(mode) 527 modebits = stat.S_IMODE(mode)