diff cutils/treesum.py @ 341:728ad9c639f2

treesum: right-align the output of size when using the tabular style
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 31 Mar 2025 15:24:48 +0200
parents cfa544fbb9f9
children 0a58948df713
line wrap: on
line diff
--- a/cutils/treesum.py	Mon Mar 31 14:51:32 2025 +0200
+++ b/cutils/treesum.py	Mon Mar 31 15:24:48 2025 +0200
@@ -563,7 +563,8 @@
                              size_only=opts.size_only,
                              print_size=opts.print_size,
                              use_base64=opts.base64,
-                             grouping_separator=opts.grouping_separator
+                             grouping_separator=opts.grouping_separator,
+                             size_column_width=opts.size_column_width,
                              )
         for d in opts.directories:
             V1DirectoryTreesumGenerator(
@@ -1490,9 +1491,10 @@
     def write_file_digest(self, algorithm, filename, digest, size):
         assert isinstance(filename, bytes)
         if digest is not None:
-            digest = (base64.b64encode(digest)
-                      if self.use_base64
-                      else binascii.hexlify(digest))
+            if digest != b"":
+                digest = (base64.b64encode(digest)
+                          if self.use_base64
+                          else binascii.hexlify(digest))
         self.write(util.b(algorithm))
         self.write(b" (")
         self.write(filename)
@@ -1531,6 +1533,18 @@
 
     def __init__(self, outfp, **kwds):
         super(TabularTreesumWriter, self).__init__(outfp, **kwds)
+        # Prepare some format strings for performance reasons
+        if self.size_column_width > 0:
+            self._formatstring_size = '>' + str(self.size_column_width)
+            self._errorstring_size = b'?' * self.size_column_width
+            self._emptystring_size = b' ' * self.size_column_width
+        else:
+            self._formatstring_size = ">"
+            self._errorstring_size = b"?????"
+            self._emptystring_size = b''
+        if self.grouping_separator:
+            self._formatstring_size += ','
+        self._formatstring_size += 'd'
 
     def start(self, version):
         """Begin a new block, reset the current CRC and write the VERSION
@@ -1590,10 +1604,13 @@
         assert isinstance(filename, bytes)
         if sz is not None:
             if sz >= 0:
-                self.write(util.b(format(sz, ',').replace(
-                    ',', self.grouping_separator)))
+                self.write(util.b(format(
+                    sz, self._formatstring_size).replace(
+                        ',', self.grouping_separator)))
             else:
-                self.write(b"?????")
+                self.write(self._emptystring_size)
+        else:
+            self.write(self._errorstring_size)
         self.write(b"\t")
         self.writeln(filename)
 
@@ -1604,23 +1621,35 @@
 
     def write_file_digest(self, algorithm, filename, digest, size):
         assert isinstance(filename, bytes)
-        if digest is not None:
-            digest = (base64.b64encode(digest)
-                      if self.use_base64
+        if digest is not None and digest != b"":
+            digest = (base64.b64encode(digest) if self.use_base64
                       else binascii.hexlify(digest))
+        else:
+            #
+            # Compute an error digest string with the "correct" length for
+            # given algorithm
+            #
+            nulldigest = b'\0' * util.algotag2digest_size(algorithm)
+            dsz = len(base64.b64encode(nulldigest) if self.use_base64
+                      else binascii.hexlify(nulldigest))
+            if digest is None:
+                digest = b'?' * dsz
+            else:
+                digest = b' ' * dsz
         self.write(util.b(algorithm))
         self.write(b":")
-        if digest is not None:
-            self.write(digest)
-        else:
-            self.write(b"?????")
+        self.write(digest)
         self.write(b"\t")
-        if size is not None:
-            if size >= 0:
-                self.write(util.b(format(size, ',').replace(
-                    ',', self.grouping_separator)))
+        if self.print_size:
+            if size is not None:
+                if size >= 0:
+                    self.write(util.b(format(
+                        size, self._formatstring_size).replace(
+                            ',', self.grouping_separator)))
+                else:
+                    self.write(self._emptystring_size)
             else:
-                self.write(b"?????")
+                self.write(self._errorstring_size)
             self.write(b"\t")
         self.writeln(filename)