Repository: borgbackup/borg

Issue:
borg extract --dry-run return code 
when extracting an archive that has files with all-zero replacement chunks, `borg extract --dry-run` emits warnings about these files being damaged.

but still it returns with rc = 0.

check also without --dry-run.

borg 1.1.3+


Discussion:

Resolving patch:
diff --git a/src/borg/archive.py b/src/borg/archive.py
--- a/src/borg/archive.py
+++ b/src/borg/archive.py
@@ -127,6 +127,12 @@ def is_special(mode):
     return stat.S_ISBLK(mode) or stat.S_ISCHR(mode) or stat.S_ISFIFO(mode)
 
 
+class BackupError(Exception):
+    """
+    Exception raised for non-OSError-based exceptions while accessing backup files.
+    """
+
+
 class BackupOSError(Exception):
     """
     Wrapper for OSError raised while accessing backup files.
@@ -551,11 +557,10 @@ def extract_item(self, item, restore_attrs=True, dry_run=False, stdout=False, sp
                 if 'size' in item:
                     item_size = item.size
                     if item_size != item_chunks_size:
-                        logger.warning('{}: size inconsistency detected: size {}, chunks size {}'.format(
-                            item.path, item_size, item_chunks_size))
+                        raise BackupError('Size inconsistency detected: size {}, chunks size {}'.format(
+                                          item_size, item_chunks_size))
             if has_damaged_chunks:
-                logger.warning('File %s has damaged (all-zero) chunks. Try running borg check --repair.' %
-                               remove_surrogates(item.path))
+                raise BackupError('File has damaged (all-zero) chunks. Try running borg check --repair.')
             return
 
         original_path = original_path or item.path
@@ -611,11 +616,10 @@ def make_parent(path):
                 if 'size' in item:
                     item_size = item.size
                     if item_size != item_chunks_size:
-                        logger.warning('{}: size inconsistency detected: size {}, chunks size {}'.format(
-                            item.path, item_size, item_chunks_size))
+                        raise BackupError('Size inconsistency detected: size {}, chunks size {}'.format(
+                                          item_size, item_chunks_size))
                 if has_damaged_chunks:
-                    logger.warning('File %s has damaged (all-zero) chunks. Try running borg check --repair.' %
-                                   remove_surrogates(item.path))
+                    raise BackupError('File has damaged (all-zero) chunks. Try running borg check --repair.')
             return
         with backup_io:
             # No repository access beyond this point.
diff --git a/src/borg/archiver.py b/src/borg/archiver.py
--- a/src/borg/archiver.py
+++ b/src/borg/archiver.py
@@ -37,7 +37,7 @@
 from . import shellpattern
 from .algorithms.checksums import crc32
 from .archive import Archive, ArchiveChecker, ArchiveRecreater, Statistics, is_special
-from .archive import BackupOSError, backup_io
+from .archive import BackupError, BackupOSError, backup_io
 from .cache import Cache, assert_secure, SecurityManager
 from .constants import *  # NOQA
 from .compress import CompressionSpec
@@ -750,7 +750,7 @@ def peek_and_store_hardlink_masters(item, matched):
                     else:
                         archive.extract_item(item, stdout=stdout, sparse=sparse, hardlink_masters=hardlink_masters,
                                              stripped_components=strip_components, original_path=orig_path, pi=pi)
-            except BackupOSError as e:
+            except (BackupOSError, BackupError) as e:
                 self.print_warning('%s: %s', remove_surrogates(orig_path), e)
 
         if pi:


Test patch: