Repository: borgbackup/borg

Issue:
prune --stats works only with --verbose
`borg prune --stats` only actually prints stats when `--verbose` is specified too.

I'm using the 0.29.0 32bit Linux binary.



Discussion:
yes, this is expected.

--verbose lowers the log level to INFO (default is WARNING).

--stats emits informative output using the logging system and level INFO.

But `borg create --stats` prints stats without needing --verbose, as expected. If prune --stats is supposed not to do anything by itself, it's really counter-intuitive.

oh, yeah, that sounds inconsistent. i'll look into it.


Resolving patch:
diff --git a/borg/archiver.py b/borg/archiver.py
--- a/borg/archiver.py
+++ b/borg/archiver.py
@@ -21,7 +21,7 @@
     get_cache_dir, get_keys_dir, prune_within, prune_split, unhexlify, \
     Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
     dir_is_tagged, bigint_to_int, ChunkerParams, CompressionSpec, is_slow_msgpack, yes, sysinfo, \
-    EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
+    EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, log_multi
 from .logger import create_logger, setup_logging
 logger = create_logger()
 from .compress import Compressor, COMPR_BUFFER
@@ -37,6 +37,8 @@
 # default umask, overriden by --umask, defaults to read/write only for owner
 UMASK_DEFAULT = 0o077
 
+DASHES = '-' * 78
+
 
 class ToggleAction(argparse.Action):
     """argparse action to handle "toggle" flags easily
@@ -187,12 +189,12 @@ def do_create(self, args):
                 archive.stats.show_progress(final=True)
             if args.stats:
                 archive.end = datetime.now()
-                print('-' * 78)
-                print(str(archive))
-                print()
-                print(str(archive.stats))
-                print(str(cache))
-                print('-' * 78)
+                log_multi(DASHES,
+                          str(archive),
+                          DASHES,
+                          str(archive.stats),
+                          str(cache),
+                          DASHES)
         return self.exit_code
 
     def _process(self, archive, cache, excludes, exclude_caches, exclude_if_present,
@@ -339,9 +341,12 @@ def do_delete(self, args):
             manifest.write()
             repository.commit(save_space=args.save_space)
             cache.commit()
+            logger.info("Archive deleted.")
             if args.stats:
-                logger.info(stats.summary.format(label='Deleted data:', stats=stats))
-                logger.info(str(cache))
+                log_multi(DASHES,
+                          stats.summary.format(label='Deleted data:', stats=stats),
+                          str(cache),
+                          DASHES)
         else:
             if not args.cache_only:
                 msg = []
@@ -495,8 +500,10 @@ def do_prune(self, args):
             repository.commit(save_space=args.save_space)
             cache.commit()
         if args.stats:
-            logger.info(stats.summary.format(label='Deleted data:', stats=stats))
-            logger.info(str(cache))
+            log_multi(DASHES,
+                      stats.summary.format(label='Deleted data:', stats=stats),
+                      str(cache),
+                      DASHES)
         return self.exit_code
 
     def do_upgrade(self, args):
diff --git a/borg/helpers.py b/borg/helpers.py
--- a/borg/helpers.py
+++ b/borg/helpers.py
@@ -18,6 +18,10 @@ def get_terminal_size(fallback=(80, 24)):
 import time
 import unicodedata
 
+import logging
+from .logger import create_logger
+logger = create_logger()
+
 from datetime import datetime, timezone, timedelta
 from fnmatch import translate
 from operator import attrgetter
@@ -971,3 +975,16 @@ def sysinfo():
     info.append('Python: %s %s' % (platform.python_implementation(), platform.python_version()))
     info.append('')
     return '\n'.join(info)
+
+
+def log_multi(*msgs, level=logging.INFO):
+    """
+    log multiple lines of text, each line by a separate logging call for cosmetic reasons
+
+    each positional argument may be a single or multiple lines (separated by \n) of text.
+    """
+    lines = []
+    for msg in msgs:
+        lines.extend(msg.splitlines())
+    for line in lines:
+        logger.log(level, line)


Test patch: