changeset 367:8a8a43e8369d

treesum: FIX: Handle line endings on Windows with redirected stdout properly
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 10 Apr 2025 01:54:09 +0200
parents 5fffacc390eb
children 7761a15b9736
files cutils/treesum.py
diffstat 1 files changed, 28 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/cutils/treesum.py	Wed Apr 09 22:21:35 2025 +0200
+++ b/cutils/treesum.py	Thu Apr 10 01:54:09 2025 +0200
@@ -566,11 +566,13 @@
             out_cm = cm.nullcontext(sys.stdout.buffer)
         else:
             out_cm = cm.nullcontext(sys.stdout)
+        is_stdout = True
     else:
         if opts.append_output:
             out_cm = open(opts.output, "ab")
         else:
             out_cm = open(opts.output, "wb")
+        is_stdout = False
 
     fnmatcher = fnmatch.FnMatcher.build_from_commandline_patterns(
         opts.fnmatch_filters)
@@ -584,6 +586,7 @@
 
     with out_cm as outfp:
         writer = writerstyle(outfp,
+                             is_stdout=is_stdout,
                              size_only=opts.size_only,
                              print_size=opts.print_size,
                              use_base64=opts.base64,
@@ -1328,13 +1331,20 @@
     DEFAULT_GROUPING_SEPARATOR = ""
     """Disable the thousands separator in case no subclass redefines it"""
 
-    def __init__(self, outfp, size_only=False, print_size=False,
+    def __init__(self, outfp, is_stdout=False,
+                 size_only=False, print_size=False,
                  use_base64=False, grouping_separator=None,
                  size_column_width=None):
         # Poor man's abstract abstract class implemenetation
         assert self.__class__ is not WriterBase
 
         self._outfp = outfp
+        try:
+            self._outfp_is_tty = self._outfp.isatty()
+        except:      # noqa: E722  bare except
+            self._outfp_is_tty = None
+        self._is_windows = sys.platform == "win32"
+        self._is_stdout = is_stdout
         self.size_only = size_only
         self.print_size = print_size
         self.use_base64 = use_base64
@@ -1385,7 +1395,23 @@
 
         """
         self.write(line)
-        self.write(self.LS)
+        if self._is_windows:
+            if self._is_stdout:
+                if self._outfp_is_tty:
+                    # Windows handles this correctly in its terminal
+                    self.write(self.LS)
+                else:
+                    #
+                    # Simulate a CR-LF for the CRC but write a LF only.
+                    # This will be converted to a CR-LF on Windows by
+                    # the runtime libs.
+                    #
+                    self._crc.update(b'\r')
+                    self.write(b'\n')
+            else:
+                self.write(self.LS)
+        else:
+            self.write(self.LS)
 
     def write(self, data):
         """Write `data` into the output file and update the CRC accordingly.