mirror of
https://github.com/borgbackup/borg.git
synced 2024-12-25 01:06:50 +00:00
move delete command to archiver.delete
This commit is contained in:
parent
06fe8d3e64
commit
350a8fe252
3 changed files with 169 additions and 148 deletions
|
@ -121,6 +121,7 @@ per_file_ignores =
|
|||
src/borg/archiver/config.py:F405,E722
|
||||
src/borg/archiver/common.py:E501,F405
|
||||
src/borg/archiver/debug.py:F405
|
||||
src/borg/archiver/delete.py:F405
|
||||
src/borg/archiver/diff.py:F405
|
||||
src/borg/archiver/help.py:E501,F405
|
||||
src/borg/archiver/keys.py:F405
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
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 @@
|
|||
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 @@ def get_func(args):
|
|||
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 @@ def do_extract(self, args, repository, manifest, key, archive):
|
|||
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 @@ def define_common_options(add_common_option):
|
|||
|
||||
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(
|
||||
"""
|
||||
|
|
163
src/borg/archiver/delete.py
Normal file
163
src/borg/archiver/delete.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
import argparse
|
||||
import logging
|
||||
|
||||
from .common import with_repository
|
||||
from ..archive import Archive, Statistics
|
||||
from ..cache import Cache
|
||||
from ..constants import * # NOQA
|
||||
from ..helpers import Manifest
|
||||
from ..helpers import log_multi, format_archive
|
||||
|
||||
from ..logger import create_logger
|
||||
|
||||
logger = create_logger()
|
||||
|
||||
|
||||
class DeleteMixIn:
|
||||
@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
|
||||
|
||||
def build_parser_delete(self, subparsers, common_parser, mid_common_parser):
|
||||
from .common import process_epilog, define_archive_filters_group
|
||||
|
||||
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)
|
Loading…
Reference in a new issue