소스 검색

Merge pull request #6723 from KN4CK3R/forwardport-6722

Forwardport: borg debug dump-repo-objs --ghost (#6722)
TW 3 년 전
부모
커밋
e8046bc761
2개의 변경된 파일18개의 추가작업 그리고 6개의 파일을 삭제
  1. 5 1
      src/borg/archiver.py
  2. 13 5
      src/borg/repository.py

+ 5 - 1
src/borg/archiver.py

@@ -2290,7 +2290,7 @@ class Archiver:
                     key = key_factory(repository, cdata)
                     key = key_factory(repository, cdata)
                     break
                     break
             i = 0
             i = 0
-            for id, cdata, tag, segment, offset in repository.scan_low_level():
+            for id, cdata, tag, segment, offset in repository.scan_low_level(segment=args.segment, offset=args.offset):
                 if tag == TAG_PUT:
                 if tag == TAG_PUT:
                     decrypt_dump(i, id, cdata, tag='put', segment=segment, offset=offset)
                     decrypt_dump(i, id, cdata, tag='put', segment=segment, offset=offset)
                 elif tag == TAG_DELETE:
                 elif tag == TAG_DELETE:
@@ -3917,6 +3917,10 @@ class Archiver:
                                help='repository to dump')
                                help='repository to dump')
         subparser.add_argument('--ghost', dest='ghost', action='store_true',
         subparser.add_argument('--ghost', dest='ghost', action='store_true',
                                help='dump all segment file contents, including deleted/uncommitted objects and commits.')
                                help='dump all segment file contents, including deleted/uncommitted objects and commits.')
+        subparser.add_argument('--segment', metavar='SEG', dest='segment', default=None, type=positive_int_validator,
+                               help='used together with --ghost: limit processing to given segment.')
+        subparser.add_argument('--offset', metavar='OFFS', dest='offset', default=None, type=positive_int_validator,
+                               help='used together with --ghost: limit processing to given offset.')
 
 
         debug_search_repo_objs_epilog = process_epilog("""
         debug_search_repo_objs_epilog = process_epilog("""
         This command searches raw (but decrypted and decompressed) repo objects for a specific bytes sequence.
         This command searches raw (but decrypted and decompressed) repo objects for a specific bytes sequence.

+ 13 - 5
src/borg/repository.py

@@ -1102,7 +1102,7 @@ class Repository:
             logger.info('Finished %s repository check, no problems found.', mode)
             logger.info('Finished %s repository check, no problems found.', mode)
         return not error_found or repair
         return not error_found or repair
 
 
-    def scan_low_level(self):
+    def scan_low_level(self, segment=None, offset=None):
         """Very low level scan over all segment file entries.
         """Very low level scan over all segment file entries.
 
 
         It does NOT care about what's committed and what not.
         It does NOT care about what's committed and what not.
@@ -1111,13 +1111,21 @@ class Repository:
 
 
         This is intended as a last-resort way to get access to all repo contents of damaged repos,
         This is intended as a last-resort way to get access to all repo contents of damaged repos,
         when there is uncommitted, but valuable data in there...
         when there is uncommitted, but valuable data in there...
+
+        When segment or segment+offset is given, limit processing to this location only.
         """
         """
-        for segment, filename in self.io.segment_iterator():
+        for current_segment, filename in self.io.segment_iterator(segment=segment):
+            if segment is not None and current_segment > segment:
+                break
             try:
             try:
-                for tag, key, offset, data in self.io.iter_objects(segment, include_data=True):
-                    yield key, data, tag, segment, offset
+                for tag, key, current_offset, data in self.io.iter_objects(segment=current_segment,
+                                                                           offset=offset or 0, include_data=True):
+                    if offset is not None and current_offset > offset:
+                        break
+                    yield key, data, tag, current_segment, current_offset
             except IntegrityError as err:
             except IntegrityError as err:
-                logger.error('Segment %d (%s) has IntegrityError(s) [%s] - skipping.' % (segment, filename, str(err)))
+                logger.error('Segment %d (%s) has IntegrityError(s) [%s] - skipping.' % (
+                             current_segment, filename, str(err)))
 
 
     def _rollback(self, *, cleanup):
     def _rollback(self, *, cleanup):
         """
         """