| 
					
				 | 
			
			
				@@ -31,11 +31,11 @@ try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..archive import Archive, ArchiveRecreater, Statistics, is_special 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..archive import BackupError, BackupOSError, backup_io, OsOpen, stat_update_check 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..archive import FilesystemObjectProcessors, MetadataCollector, ChunksProcessor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    from ..cache import Cache, SecurityManager 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    from ..cache import Cache 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..constants import *  # NOQA 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..compress import CompressionSpec 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR, EXIT_SIGNAL_BASE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    from ..helpers import Error, NoManifestError, set_ec 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    from ..helpers import Error, set_ec 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import location_validator, archivename_validator, ChunkerParams, Location 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import NameSpec, CommentSpec, FilesCacheMode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import BaseFormatter, ItemFormatter, ArchiveFormatter 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -46,7 +46,7 @@ try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import Manifest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import HardLinkManager 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import check_python, check_extension_modules 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    from ..helpers import dir_is_tagged, is_slow_msgpack, is_supported_msgpack, yes, sysinfo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    from ..helpers import dir_is_tagged, is_slow_msgpack, is_supported_msgpack, sysinfo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import log_multi 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import signal_handler, raising_signal_handler, SigHup, SigTerm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     from ..helpers import ErrorIgnoringTextIOWrapper 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -100,6 +100,7 @@ from .locks import LocksMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .mount import MountMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .prune import PruneMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .rcreate import RCreateMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from .rdelete import RDeleteMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .serve import ServeMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .tar import TarMixIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .transfer import TransferMixIn 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -119,6 +120,7 @@ class Archiver( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     PruneMixIn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     HelpMixIn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     RCreateMixIn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    RDeleteMixIn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ServeMixIn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     TransferMixIn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -703,80 +705,6 @@ class Archiver( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         cache.commit() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return self.exit_code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @with_repository(exclusive=True, manifest=False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def do_rdelete(self, args, repository): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """Delete a repository""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.output_list = args.output_list 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        dry_run = args.dry_run 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        keep_security_info = args.keep_security_info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if not args.cache_only: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if args.forced == 0:  # without --force, we let the user see the archives list and confirm. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                id = bin_to_hex(repository.id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                location = repository._location.canonical_path() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    n_archives = len(manifest.archives) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    msg.append( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        f"You requested to completely DELETE the following repository " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        f"*including* {n_archives} archives it contains:" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                except NoManifestError: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    n_archives = None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    msg.append( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        "You requested to completely DELETE the following repository " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        "*including* all archives it may contain:" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg.append(DASHES) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg.append(f"Repository ID: {id}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg.append(f"Location: {location}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if self.output_list: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    msg.append("") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    msg.append("Archives:") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if n_archives is not None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if n_archives > 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            for archive_info in manifest.archives.list(sort_by=["ts"]): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                msg.append(format_archive(archive_info)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            msg.append("This repository seems to not have any archives.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        msg.append( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            "This repository seems to have no manifest, so we can't " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            "tell anything about its contents." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg.append(DASHES) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg.append("Type 'YES' if you understand this and want to continue: ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                msg = "\n".join(msg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if not yes( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    msg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    false_msg="Aborting.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    invalid_msg="Invalid answer, aborting.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    truish=("YES",), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    retry=False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    env_var_override="BORG_DELETE_I_KNOW_WHAT_I_AM_DOING", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                ): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    self.exit_code = EXIT_ERROR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return self.exit_code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if not dry_run: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                repository.destroy() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                logger.info("Repository deleted.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if not keep_security_info: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    SecurityManager.destroy(repository) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                logger.info("Would delete repository.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                logger.info("Would %s security info." % ("keep" if keep_security_info else "delete")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if not dry_run: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            Cache.destroy(repository) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            logger.info("Cache deleted.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            logger.info("Would delete cache.") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return self.exit_code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @with_repository(exclusive=True, manifest=False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def do_delete(self, args, repository): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         """Delete archives""" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1753,53 +1681,7 @@ class Archiver( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.build_parser_config(subparsers, common_parser, mid_common_parser) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.build_parser_debug(subparsers, common_parser, mid_common_parser) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.build_parser_help(subparsers, common_parser, mid_common_parser, parser) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # borg rdelete 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rdelete_epilog = process_epilog( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        This command deletes the complete repository. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        When you delete a complete repository, the security info and local cache for it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        (if any) are also deleted. Alternatively, you can delete just the local cache 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with the ``--cache-only`` option, or keep the security info with the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ``--keep-security-info`` option. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Always first use ``--dry-run --list`` to see what would be deleted. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser = subparsers.add_parser( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "rdelete", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            parents=[common_parser], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            add_help=False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            description=self.do_rdelete.__doc__, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            epilog=rdelete_epilog, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            formatter_class=argparse.RawDescriptionHelpFormatter, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            help="delete repository", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser.set_defaults(func=self.do_rdelete) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser.add_argument("-n", "--dry-run", dest="dry_run", action="store_true", help="do not change repository") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser.add_argument( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--list", dest="output_list", action="store_true", help="output verbose list of archives" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser.add_argument( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--force", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dest="forced", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            action="count", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            default=0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            help="force deletion of corrupted archives, " "use ``--force --force`` in case ``--force`` does not work.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser.add_argument( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--cache-only", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dest="cache_only", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            action="store_true", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            help="delete only the local cache for the given repository", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        subparser.add_argument( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--keep-security-info", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dest="keep_security_info", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            action="store_true", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            help="keep the local security info when deleting a repository", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.build_parser_rdelete(subparsers, common_parser, mid_common_parser, parser) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # borg delete 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         delete_epilog = process_epilog( 
			 |