Repository: borgbackup/borg

Issue:
display chunkid when replacing with all-zero chunk
From @W1zzardTPU :
```
Chunk ID 6168965f75dec00691f7e417f35b2e83e371a0a658c848eb14eca9c206831b11 missing from chunks index, corrupted chunks index - aborting transaction.

Command 'borg prune --prefix 2 --keep-hourly 4 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 1 borg@server:/backup/borg/repo/mysql' returned non-zero exit status 2.

# borg check -v .
Starting repository check
Starting repository index check
Index object count match.
Completed repository check, no problems found.
Starting archive consistency check...
Analyzing archive 2021-01-17T19:41:57 (1/16)
Analyzing archive 2021-01-24T19:42:37 (2/16)
Analyzing archive 2021-01-31T22:01:52 (3/16)
Analyzing archive 2021-02-07T21:48:17 (4/16)
Analyzing archive 2021-02-11T22:05:55 (5/16)
2021-02-11T22:05:55: mysql/gpuz/results_text_compressed2.sql.gz: New missing file chunk detected (Byte 1083166524-1086353891). Replacing with all-zero chunk .
Analyzing archive 2021-02-12T22:03:05 (6/16)
2021-02-12T22:03:05: mysql/gpuz/results_text_compressed2.sql.gz: New missing file chunk detected (Byte 1083166635-1086354002). Replacing with all-zero chunk .
Analyzing archive 2021-02-13T22:07:58 (7/16)
2021-02-13T22:07:58: mysql/gpuz/results_text_compressed2.sql.gz: New missing file chunk detected (Byte 1083166591-1086353958). Replacing with all-zero chunk .
Analyzing archive 2021-02-14T22:01:35 (8/16)
```

```
Isn't it surprising that a chunk in the same file is corrupted 3 times, on 3 different days?
```

```
No, that's rather expected due to deduplication, if the chunk happens to be identical.
```

```
Oh so it refers to the same chunk in all those 3 error messages?

Maybe this could be a future enhancement to the error message, to display the chunk id?
```



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
@@ -1480,23 +1480,23 @@ def replacement_chunk(size):
                 if chunk_id not in self.chunks:
                     # a chunk of the healthy list is missing
                     if chunk_current == chunk_healthy:
-                        logger.error('{}: {}: New missing file chunk detected (Byte {}-{}). '
+                        logger.error('{}: {}: New missing file chunk detected (Byte {}-{}, Chunk {}). '
                                      'Replacing with all-zero chunk.'.format(
-                                     archive_name, item.path, offset, offset + size))
+                                     archive_name, item.path, offset, offset + size, bin_to_hex(chunk_id)))
                         self.error_found = chunks_replaced = True
                         chunk_id, size, csize, cdata = replacement_chunk(size)
                         add_reference(chunk_id, size, csize, cdata)
                     else:
-                        logger.info('{}: {}: Previously missing file chunk is still missing (Byte {}-{}). It has a '
-                                    'all-zero replacement chunk already.'.format(
-                                    archive_name, item.path, offset, offset + size))
+                        logger.info('{}: {}: Previously missing file chunk is still missing (Byte {}-{}, Chunk {}). '
+                                    'It has an all-zero replacement chunk already.'.format(
+                                    archive_name, item.path, offset, offset + size, bin_to_hex(chunk_id)))
                         chunk_id, size, csize = chunk_current
                         if chunk_id in self.chunks:
                             add_reference(chunk_id, size, csize)
                         else:
-                            logger.warning('{}: {}: Missing all-zero replacement chunk detected (Byte {}-{}). '
+                            logger.warning('{}: {}: Missing all-zero replacement chunk detected (Byte {}-{}, Chunk {}). '
                                            'Generating new replacement chunk.'.format(
-                                           archive_name, item.path, offset, offset + size))
+                                           archive_name, item.path, offset, offset + size, bin_to_hex(chunk_id)))
                             self.error_found = chunks_replaced = True
                             chunk_id, size, csize, cdata = replacement_chunk(size)
                             add_reference(chunk_id, size, csize, cdata)
@@ -1505,8 +1505,8 @@ def replacement_chunk(size):
                         # normal case, all fine.
                         add_reference(chunk_id, size, csize)
                     else:
-                        logger.info('{}: {}: Healed previously missing file chunk! '
-                                    '(Byte {}-{}).'.format(archive_name, item.path, offset, offset + size))
+                        logger.info('{}: {}: Healed previously missing file chunk! (Byte {}-{}, Chunk {}).'.format(
+                            archive_name, item.path, offset, offset + size, bin_to_hex(chunk_id)))
                         add_reference(chunk_id, size, csize)
                         mark_as_possibly_superseded(chunk_current[0])  # maybe orphaned the all-zero replacement chunk
                 chunk_list.append([chunk_id, size, csize])  # list-typed element as chunks_healthy is list-of-lists


Test patch: