mirror of
https://github.com/borgbackup/borg.git
synced 2026-06-11 09:59:19 -04:00
borg < 2: obj = encrypted(compressed(data)) borg 2: obj = enc_meta_len32 + encrypted(msgpacked(meta)) + encrypted(compressed(data)) handle compr / decompr in repoobj move the assert_id call from decrypt to RepoObj.parse also: - for AEADKeyBase, add a dummy assert_id (not needed here) - only test assert_id for other if not AEADKeyBase instance - remove test_getting_wrong_chunk. assert_id is called elsewhere and is not needed any more anyway with the new AEAD crypto. - only give manifest (includes key, repo, repo_objs) - only return manifest from Manifest.load (includes key, repo, repo_objs)
118 lines
4.7 KiB
Python
118 lines
4.7 KiB
Python
import argparse
|
|
import json
|
|
|
|
from ._common import with_repository, with_archive, build_matcher
|
|
from ..archive import Archive
|
|
from ..constants import * # NOQA
|
|
from ..helpers import archivename_validator
|
|
from ..manifest import Manifest
|
|
|
|
from ..logger import create_logger
|
|
|
|
logger = create_logger()
|
|
|
|
|
|
class DiffMixIn:
|
|
@with_repository(compatibility=(Manifest.Operation.READ,))
|
|
@with_archive
|
|
def do_diff(self, args, repository, manifest, archive):
|
|
"""Diff contents of two archives"""
|
|
|
|
def print_json_output(diff, path):
|
|
print(json.dumps({"path": path, "changes": [j for j, str in diff]}))
|
|
|
|
def print_text_output(diff, path):
|
|
print("{:<19} {}".format(" ".join([str for j, str in diff]), path))
|
|
|
|
print_output = print_json_output if args.json_lines else print_text_output
|
|
|
|
archive1 = archive
|
|
archive2 = Archive(manifest, args.other_name, consider_part_files=args.consider_part_files)
|
|
|
|
can_compare_chunk_ids = (
|
|
archive1.metadata.get("chunker_params", False) == archive2.metadata.get("chunker_params", True)
|
|
or args.same_chunker_params
|
|
)
|
|
if not can_compare_chunk_ids:
|
|
self.print_warning(
|
|
"--chunker-params might be different between archives, diff will be slow.\n"
|
|
"If you know for certain that they are the same, pass --same-chunker-params "
|
|
"to override this check."
|
|
)
|
|
|
|
matcher = build_matcher(args.patterns, args.paths)
|
|
|
|
diffs = Archive.compare_archives_iter(archive1, archive2, matcher, can_compare_chunk_ids=can_compare_chunk_ids)
|
|
# Conversion to string and filtering for diff.equal to save memory if sorting
|
|
diffs = ((path, diff.changes()) for path, diff in diffs if not diff.equal)
|
|
|
|
if args.sort:
|
|
diffs = sorted(diffs)
|
|
|
|
for path, diff in diffs:
|
|
print_output(diff, path)
|
|
|
|
for pattern in matcher.get_unmatched_include_patterns():
|
|
self.print_warning("Include pattern '%s' never matched.", pattern)
|
|
|
|
return self.exit_code
|
|
|
|
def build_parser_diff(self, subparsers, common_parser, mid_common_parser):
|
|
|
|
from ._common import process_epilog
|
|
from ._common import define_exclusion_group
|
|
|
|
diff_epilog = process_epilog(
|
|
"""
|
|
This command finds differences (file contents, user/group/mode) between archives.
|
|
|
|
A repository location and an archive name must be specified for REPO::ARCHIVE1.
|
|
ARCHIVE2 is just another archive name in same repository (no repository location
|
|
allowed).
|
|
|
|
For archives created with Borg 1.1 or newer diff automatically detects whether
|
|
the archives are created with the same chunker params. If so, only chunk IDs
|
|
are compared, which is very fast.
|
|
|
|
For archives prior to Borg 1.1 chunk contents are compared by default.
|
|
If you did not create the archives with different chunker params,
|
|
pass ``--same-chunker-params``.
|
|
Note that the chunker params changed from Borg 0.xx to 1.0.
|
|
|
|
For more help on include/exclude patterns, see the :ref:`borg_patterns` command output.
|
|
"""
|
|
)
|
|
subparser = subparsers.add_parser(
|
|
"diff",
|
|
parents=[common_parser],
|
|
add_help=False,
|
|
description=self.do_diff.__doc__,
|
|
epilog=diff_epilog,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
help="find differences in archive contents",
|
|
)
|
|
subparser.set_defaults(func=self.do_diff)
|
|
subparser.add_argument(
|
|
"--numeric-ids",
|
|
dest="numeric_ids",
|
|
action="store_true",
|
|
help="only consider numeric user and group identifiers",
|
|
)
|
|
subparser.add_argument(
|
|
"--same-chunker-params",
|
|
dest="same_chunker_params",
|
|
action="store_true",
|
|
help="Override check of chunker parameters.",
|
|
)
|
|
subparser.add_argument("--sort", dest="sort", action="store_true", help="Sort the output lines by file path.")
|
|
subparser.add_argument("--json-lines", action="store_true", help="Format output as JSON Lines. ")
|
|
subparser.add_argument("name", metavar="ARCHIVE1", type=archivename_validator(), help="ARCHIVE1 name")
|
|
subparser.add_argument("other_name", metavar="ARCHIVE2", type=archivename_validator(), help="ARCHIVE2 name")
|
|
subparser.add_argument(
|
|
"paths",
|
|
metavar="PATH",
|
|
nargs="*",
|
|
type=str,
|
|
help="paths of items inside the archives to compare; patterns are supported",
|
|
)
|
|
define_exclusion_group(subparser)
|