borg/src/borg/archiver/rdelete_cmd.py

141 lines
5.5 KiB
Python

import argparse
from ._common import with_repository
from ..cache import Cache, SecurityManager
from ..constants import * # NOQA
from ..helpers import EXIT_ERROR
from ..helpers import format_archive
from ..helpers import bin_to_hex
from ..helpers import yes
from ..manifest import Manifest, NoManifestError
from ..logger import create_logger
logger = create_logger()
class RDeleteMixIn:
@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 = 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 not to 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
def build_parser_rdelete(self, subparsers, common_parser, mid_common_parser):
from ._common import process_epilog
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",
)