|
@@ -28,7 +28,7 @@ try:
|
|
|
from .common import with_repository, with_archive, Highlander
|
|
|
from .. import __version__
|
|
|
from .. import helpers
|
|
|
- from ..archive import Archive, ArchiveRecreater, Statistics, is_special
|
|
|
+ from ..archive import Archive, ArchiveRecreater, is_special
|
|
|
from ..archive import BackupError, BackupOSError, backup_io, OsOpen, stat_update_check
|
|
|
from ..archive import FilesystemObjectProcessors, MetadataCollector, ChunksProcessor
|
|
|
from ..cache import Cache
|
|
@@ -39,7 +39,7 @@ try:
|
|
|
from ..helpers import location_validator, archivename_validator, ChunkerParams, Location
|
|
|
from ..helpers import NameSpec, CommentSpec, FilesCacheMode
|
|
|
from ..helpers import BaseFormatter, ItemFormatter, ArchiveFormatter
|
|
|
- from ..helpers import format_timedelta, format_file_size, format_archive
|
|
|
+ from ..helpers import format_timedelta, format_file_size
|
|
|
from ..helpers import remove_surrogates, bin_to_hex, eval_escapes
|
|
|
from ..helpers import timestamp
|
|
|
from ..helpers import get_cache_dir, os_stat
|
|
@@ -93,6 +93,7 @@ from .check import CheckMixIn
|
|
|
from .compact import CompactMixIn
|
|
|
from .config import ConfigMixIn
|
|
|
from .debug import DebugMixIn
|
|
|
+from .delete import DeleteMixIn
|
|
|
from .diff import DiffMixIn
|
|
|
from .help import HelpMixIn
|
|
|
from .keys import KeysMixIn
|
|
@@ -112,6 +113,7 @@ class Archiver(
|
|
|
ConfigMixIn,
|
|
|
CompactMixIn,
|
|
|
DebugMixIn,
|
|
|
+ DeleteMixIn,
|
|
|
DiffMixIn,
|
|
|
TarMixIn,
|
|
|
BenchmarkMixIn,
|
|
@@ -697,83 +699,6 @@ class Archiver(
|
|
|
pi.finish()
|
|
|
return self.exit_code
|
|
|
|
|
|
- @with_repository(exclusive=True, manifest=False)
|
|
|
- def do_delete(self, args, repository):
|
|
|
- """Delete archives"""
|
|
|
- self.output_list = args.output_list
|
|
|
- dry_run = args.dry_run
|
|
|
- manifest, key = Manifest.load(repository, (Manifest.Operation.DELETE,))
|
|
|
- archive_names = tuple(x.name for x in manifest.archives.list_considering(args))
|
|
|
- if not archive_names:
|
|
|
- return self.exit_code
|
|
|
- if args.glob_archives is None and args.first == 0 and args.last == 0:
|
|
|
- self.print_error(
|
|
|
- "Aborting: if you really want to delete all archives, please use -a '*' "
|
|
|
- "or just delete the whole repository (might be much faster)."
|
|
|
- )
|
|
|
- return EXIT_ERROR
|
|
|
-
|
|
|
- if args.forced == 2:
|
|
|
- deleted = False
|
|
|
- logger_list = logging.getLogger("borg.output.list")
|
|
|
- for i, archive_name in enumerate(archive_names, 1):
|
|
|
- try:
|
|
|
- current_archive = manifest.archives.pop(archive_name)
|
|
|
- except KeyError:
|
|
|
- self.exit_code = EXIT_WARNING
|
|
|
- logger.warning(f"Archive {archive_name} not found ({i}/{len(archive_names)}).")
|
|
|
- else:
|
|
|
- deleted = True
|
|
|
- if self.output_list:
|
|
|
- msg = "Would delete: {} ({}/{})" if dry_run else "Deleted archive: {} ({}/{})"
|
|
|
- logger_list.info(msg.format(format_archive(current_archive), i, len(archive_names)))
|
|
|
- if dry_run:
|
|
|
- logger.info("Finished dry-run.")
|
|
|
- elif deleted:
|
|
|
- manifest.write()
|
|
|
- # note: might crash in compact() after committing the repo
|
|
|
- repository.commit(compact=False)
|
|
|
- logger.warning('Done. Run "borg check --repair" to clean up the mess.')
|
|
|
- else:
|
|
|
- logger.warning("Aborted.")
|
|
|
- return self.exit_code
|
|
|
-
|
|
|
- stats = Statistics(iec=args.iec)
|
|
|
- with Cache(repository, key, manifest, progress=args.progress, lock_wait=self.lock_wait, iec=args.iec) as cache:
|
|
|
- msg_delete = "Would delete archive: {} ({}/{})" if dry_run else "Deleting archive: {} ({}/{})"
|
|
|
- msg_not_found = "Archive {} not found ({}/{})."
|
|
|
- logger_list = logging.getLogger("borg.output.list")
|
|
|
- delete_count = 0
|
|
|
- for i, archive_name in enumerate(archive_names, 1):
|
|
|
- try:
|
|
|
- archive_info = manifest.archives[archive_name]
|
|
|
- except KeyError:
|
|
|
- logger.warning(msg_not_found.format(archive_name, i, len(archive_names)))
|
|
|
- else:
|
|
|
- if self.output_list:
|
|
|
- logger_list.info(msg_delete.format(format_archive(archive_info), i, len(archive_names)))
|
|
|
-
|
|
|
- if not dry_run:
|
|
|
- archive = Archive(
|
|
|
- repository,
|
|
|
- key,
|
|
|
- manifest,
|
|
|
- archive_name,
|
|
|
- cache=cache,
|
|
|
- consider_part_files=args.consider_part_files,
|
|
|
- )
|
|
|
- archive.delete(stats, progress=args.progress, forced=args.forced)
|
|
|
- delete_count += 1
|
|
|
- if delete_count > 0:
|
|
|
- # only write/commit if we actually changed something, see #6060.
|
|
|
- manifest.write()
|
|
|
- repository.commit(compact=False, save_space=args.save_space)
|
|
|
- cache.commit()
|
|
|
- if args.stats:
|
|
|
- log_multi(str(stats), logger=logging.getLogger("borg.output.stats"))
|
|
|
-
|
|
|
- return self.exit_code
|
|
|
-
|
|
|
@with_repository(compatibility=(Manifest.Operation.READ,))
|
|
|
def do_list(self, args, repository, manifest, key):
|
|
|
"""List archive contents"""
|
|
@@ -1672,78 +1597,10 @@ 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_delete(subparsers, common_parser, mid_common_parser)
|
|
|
self.build_parser_help(subparsers, common_parser, mid_common_parser, parser)
|
|
|
self.build_parser_rdelete(subparsers, common_parser, mid_common_parser, parser)
|
|
|
|
|
|
- # borg delete
|
|
|
- delete_epilog = process_epilog(
|
|
|
- """
|
|
|
- This command deletes archives from the repository.
|
|
|
-
|
|
|
- Important: When deleting archives, repository disk space is **not** freed until
|
|
|
- you run ``borg compact``.
|
|
|
-
|
|
|
- When in doubt, use ``--dry-run --list`` to see what would be deleted.
|
|
|
-
|
|
|
- When using ``--stats``, you will get some statistics about how much data was
|
|
|
- deleted - the "Deleted data" deduplicated size there is most interesting as
|
|
|
- that is how much your repository will shrink.
|
|
|
- Please note that the "All archives" stats refer to the state after deletion.
|
|
|
-
|
|
|
- You can delete multiple archives by specifying a matching shell pattern,
|
|
|
- using the ``--glob-archives GLOB`` option (for more info on these patterns,
|
|
|
- see :ref:`borg_patterns`).
|
|
|
-
|
|
|
- Always first use ``--dry-run --list`` to see what would be deleted.
|
|
|
- """
|
|
|
- )
|
|
|
- subparser = subparsers.add_parser(
|
|
|
- "delete",
|
|
|
- parents=[common_parser],
|
|
|
- add_help=False,
|
|
|
- description=self.do_delete.__doc__,
|
|
|
- epilog=delete_epilog,
|
|
|
- formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
- help="delete archive",
|
|
|
- )
|
|
|
- subparser.set_defaults(func=self.do_delete)
|
|
|
- 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(
|
|
|
- "--consider-checkpoints",
|
|
|
- action="store_true",
|
|
|
- dest="consider_checkpoints",
|
|
|
- help="consider checkpoint archives for deletion (default: not considered).",
|
|
|
- )
|
|
|
- subparser.add_argument(
|
|
|
- "-s", "--stats", dest="stats", action="store_true", help="print statistics for the deleted archive"
|
|
|
- )
|
|
|
- subparser.add_argument(
|
|
|
- "--cache-only",
|
|
|
- dest="cache_only",
|
|
|
- action="store_true",
|
|
|
- help="delete only the local cache for the given repository",
|
|
|
- )
|
|
|
- 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(
|
|
|
- "--keep-security-info",
|
|
|
- dest="keep_security_info",
|
|
|
- action="store_true",
|
|
|
- help="keep the local security info when deleting a repository",
|
|
|
- )
|
|
|
- subparser.add_argument(
|
|
|
- "--save-space", dest="save_space", action="store_true", help="work slower, but using less space"
|
|
|
- )
|
|
|
- define_archive_filters_group(subparser)
|
|
|
-
|
|
|
# borg extract
|
|
|
extract_epilog = process_epilog(
|
|
|
"""
|