浏览代码

[FEATURE] #4489 – Deprecate --nobsdflags option

Replaced by --noflags. In internal data structure the key 'bsdflags' is kept for backwards compatibility.
Thalian 5 年之前
父节点
当前提交
08a7661e67

+ 1 - 1
docs/deployment/pull-backup.rst

@@ -19,7 +19,7 @@ BorgBackup is not run with root privileges.
 SSHFS is a FUSE file system and uses the SFTP protocol, so there may be also
 other unsupported features that the actual implementations of ssfs, libfuse and
 sftp on the backup server do not support, like file name encodings, ACLs, xattrs
-or bsdflags. So there is no guarantee that you are able to restore a system
+or flags. So there is no guarantee that you are able to restore a system
 completely in every aspect from such a backup.
 
 .. warning::

+ 1 - 1
docs/internals/data-structures.rst

@@ -563,7 +563,7 @@ dictionary created by the ``Item`` class that contains:
 * mtime, atime, ctime in nanoseconds
 * xattrs
 * acl (various OS-dependent fields)
-* bsdflags
+* flags
 
 All items are serialized using msgpack and the resulting byte stream
 is fed into the same chunker algorithm as used for regular file data

+ 7 - 7
docs/usage/notes.rst

@@ -71,15 +71,15 @@ affect metadata stream deduplication: if only this timestamp changes between
 backups and is stored into the metadata stream, the metadata stream chunks
 won't deduplicate just because of that.
 
-``--nobsdflags``
-~~~~~~~~~~~~~~~~
+``--nobsdflags / --noflags``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-You can use this to not query and store (or not extract and set) bsdflags -
-in case you don't need them or if they are broken somehow for your fs.
+You can use this to not query and store (or not extract and set) flags - in case
+you don't need them or if they are broken somehow for your fs.
 
-On Linux, dealing with the bsflags needs some additional syscalls.
-Especially when dealing with lots of small files, this causes a noticable
-overhead, so you can use this option also for speeding up operations.
+On Linux, dealing with the flags needs some additional syscalls. Especially when
+dealing with lots of small files, this causes a noticable overhead, so you can
+use this option also for speeding up operations.
 
 ``--umask``
 ~~~~~~~~~~~

+ 2 - 2
scripts/shell_completions/bash/borg

@@ -75,10 +75,10 @@ _borg()
                 local opts="-e --encryption --append-only --storage-quota --make-parent-dirs ${common_opts}"
                 ;;
             *' create '*)
-                local opts="-n --dry-run -s --stats --list --filter --json --no-cache-sync --stdin-name -e --exclude --exclude-from --pattern --patterns-from --exclude-caches --exclude-if-present --keep-exclude-tags --exclude-nodump -x --one-file-system --numeric-owner --noatime --noctime --nobirthtime --nobsdflags --files-cache --read-special --comment --timestamp -c --checkpoint-interval --chunker-params -C --compression ${common_opts}"
+                local opts="-n --dry-run -s --stats --list --filter --json --no-cache-sync --stdin-name -e --exclude --exclude-from --pattern --patterns-from --exclude-caches --exclude-if-present --keep-exclude-tags --exclude-nodump -x --one-file-system --numeric-owner --noatime --noctime --nobirthtime --nobsdflags --noflags --files-cache --read-special --comment --timestamp -c --checkpoint-interval --chunker-params -C --compression ${common_opts}"
                 ;;
             *' extract '*)
-                local opts="--list -n --dry-run --numeric-owner --nobsdflags --stdout --sparse -e --exclude --exclude-from --pattern --patterns-from --strip-components ${common_opts}"
+                local opts="--list -n --dry-run --numeric-owner --nobsdflags --noflags --stdout --sparse -e --exclude --exclude-from --pattern --patterns-from --strip-components ${common_opts}"
                 ;;
             *' check '*)
                 local opts="--repository-only --archives-only --verify-data --repair --save-space --max-duration -P --prefix -a --glob-archives --sort-by --first --last ${common_opts}"

+ 2 - 0
scripts/shell_completions/fish/borg.fish

@@ -117,6 +117,7 @@ complete -c borg -f      -l 'noatime'               -d 'Do not store atime'
 complete -c borg -f      -l 'noctime'               -d 'Do not store ctime'                         -n "__fish_seen_subcommand_from create"
 complete -c borg -f      -l 'nobirthtime'           -d 'Do not store creation date'                 -n "__fish_seen_subcommand_from create"
 complete -c borg -f      -l 'nobsdflags'            -d 'Do not store bsdflags'                      -n "__fish_seen_subcommand_from create"
+complete -c borg -f      -l 'noflags'               -d 'Do not store flags'                         -n "__fish_seen_subcommand_from create"
 set -l files_cache_mode "ctime,size,inode mtime,size,inode ctime,size mtime,size rechunk,ctime rechunk,mtime disabled"
 complete -c borg -f      -l 'files-cache'           -d 'Operate files cache in MODE' -a "$files_cache_mode" -n "__fish_seen_subcommand_from create"
 complete -c borg -f      -l 'read-special'          -d 'Open device files like regular files'       -n "__fish_seen_subcommand_from create"
@@ -134,6 +135,7 @@ complete -c borg -f      -l 'list'                  -d 'Print verbose list of it
 complete -c borg -f -s n -l 'dry-run'               -d 'Do not actually extract any files'          -n "__fish_seen_subcommand_from extract"
 complete -c borg -f      -l 'numeric-owner'         -d 'Only obey numeric user:group identifiers'   -n "__fish_seen_subcommand_from extract"
 complete -c borg -f      -l 'nobsdflags'            -d 'Do not extract/set bsdflags'                -n "__fish_seen_subcommand_from extract"
+complete -c borg -f      -l 'noflags'               -d 'Do not extract/set flags'                   -n "__fish_seen_subcommand_from extract"
 complete -c borg -f      -l 'stdout'                -d 'Write all extracted data to stdout'         -n "__fish_seen_subcommand_from extract"
 complete -c borg -f      -l 'sparse'                -d 'Create holes in output sparse file'         -n "__fish_seen_subcommand_from extract"
 # Exclusion options

+ 2 - 0
scripts/shell_completions/zsh/_borg

@@ -101,6 +101,7 @@ _borg() {
                 --noatime'[do not store atime into archive]'\
                 --nobirthtime'[do not store birthtime (creation date) into archive]'\
                 --nobsdflags'[do not read and store bsdflags (e.g. NODUMP, IMMUTABLE) into archive]'\
+                --noflags'[do not read and store flags (e.g. NODUMP, IMMUTABLE) into archive]'\
                 --files-cache'[operate files cache in MODE. default: ctime,size,inode]:mode:(ctime,size,inode mtime,size,inode ctime,size mtime,size rechunk,ctime rechunk,mtime disabled)'\
                 --read-special'[open and read block and char device files as well as FIFOs as if they were regular files.]'\
                 --comment'[add a comment text to the archive]:COMMENT'\
@@ -119,6 +120,7 @@ _borg() {
                 {-n,--dry-run}'[do not actually change any files]'\
                 --numeric-owner'[only obey numeric user and group identifiers]'\
                 --nobsdflags'[do not extract/set bsdflags (e.g. NODUMP, IMMUTABLE)]'\
+                --noflags'[do not extract/set flags (e.g. NODUMP, IMMUTABLE)]'\
                 --stdout'[write all extracted data to stdout]'\
                 --sparse'[create holes in output sparse file from all-zero chunks]'\
                 {-e,--exclude}'[exclude paths matching PATTERN]:PATTERN'\

+ 10 - 10
src/borg/archive.py

@@ -375,7 +375,7 @@ class Archive:
         """Failed to encode filename "{}" into file system encoding "{}". Consider configuring the LANG environment variable."""
 
     def __init__(self, repository, key, manifest, name, cache=None, create=False,
-                 checkpoint_interval=1800, numeric_owner=False, noatime=False, noctime=False, nobsdflags=False,
+                 checkpoint_interval=1800, numeric_owner=False, noatime=False, noctime=False, noflags=False,
                  progress=False, chunker_params=CHUNKER_PARAMS, start=None, start_monotonic=None, end=None,
                  consider_part_files=False, log_json=False):
         self.cwd = os.getcwd()
@@ -393,7 +393,7 @@ class Archive:
         self.numeric_owner = numeric_owner
         self.noatime = noatime
         self.noctime = noctime
-        self.nobsdflags = nobsdflags
+        self.noflags = noflags
         assert (start is None) == (start_monotonic is None), 'Logic error: if start is given, start_monotonic must be given as well and vice versa.'
         if start is None:
             start = datetime.utcnow()
@@ -846,7 +846,7 @@ Utilization of max. archive size: {csize_max:.0%}
             if warning:
                 set_ec(EXIT_WARNING)
             # bsdflags include the immutable flag and need to be set last:
-            if not self.nobsdflags and 'bsdflags' in item:
+            if not self.noflags and 'bsdflags' in item:
                 try:
                     set_flags(path, item.bsdflags, fd=fd)
                 except OSError:
@@ -1025,11 +1025,11 @@ Utilization of max. archive size: {csize_max:.0%}
 
 
 class MetadataCollector:
-    def __init__(self, *, noatime, noctime, numeric_owner, nobsdflags, nobirthtime):
+    def __init__(self, *, noatime, noctime, numeric_owner, noflags, nobirthtime):
         self.noatime = noatime
         self.noctime = noctime
         self.numeric_owner = numeric_owner
-        self.nobsdflags = nobsdflags
+        self.noflags = noflags
         self.nobirthtime = nobirthtime
 
     def stat_simple_attrs(self, st):
@@ -1058,16 +1058,16 @@ class MetadataCollector:
 
     def stat_ext_attrs(self, st, path, fd=None):
         attrs = {}
-        bsdflags = 0
+        flags = 0
         with backup_io('extended stat'):
-            if not self.nobsdflags:
-                bsdflags = get_flags(path, st, fd=fd)
+            if not self.noflags:
+                flags = get_flags(path, st, fd=fd)
             xattrs = xattr.get_all(fd or path, follow_symlinks=False)
             acl_get(path, attrs, st, self.numeric_owner, fd=fd)
         if xattrs:
             attrs['xattrs'] = StableDict(xattrs)
-        if bsdflags:
-            attrs['bsdflags'] = bsdflags
+        if flags:
+            attrs['bsdflags'] = flags
         return attrs
 
     def stat_attrs(self, st, path, fd=None):

+ 11 - 6
src/borg/archiver.py

@@ -175,7 +175,7 @@ def with_archive(method):
     def wrapper(self, args, repository, key, manifest, **kwargs):
         archive = Archive(repository, key, manifest, args.location.archive,
                           numeric_owner=getattr(args, 'numeric_owner', False),
-                          nobsdflags=getattr(args, 'nobsdflags', False),
+                          noflags=getattr(args, 'nobsdflags', False) or getattr(args, 'noflags', False),
                           cache=kwargs.get('cache'),
                           consider_part_files=args.consider_part_files, log_json=args.log_json)
         return method(self, args, repository=repository, manifest=manifest, key=key, archive=archive, **kwargs)
@@ -557,7 +557,7 @@ class Archiver:
 
         self.output_filter = args.output_filter
         self.output_list = args.output_list
-        self.nobsdflags = args.nobsdflags
+        self.noflags = args.nobsdflags or args.noflags
         self.exclude_nodump = args.exclude_nodump
         dry_run = args.dry_run
         t0 = datetime.utcnow()
@@ -574,7 +574,7 @@ class Archiver:
                                   chunker_params=args.chunker_params, start=t0, start_monotonic=t0_monotonic,
                                   log_json=args.log_json)
                 metadata_collector = MetadataCollector(noatime=not args.atime, noctime=args.noctime,
-                    nobsdflags=args.nobsdflags, numeric_owner=args.numeric_owner, nobirthtime=args.nobirthtime)
+                    noflags=args.nobsdflags or args.noflags, numeric_owner=args.numeric_owner, nobirthtime=args.nobirthtime)
                 cp = ChunksProcessor(cache=cache, key=key,
                     add_item=archive.add_item, write_checkpoint=archive.write_checkpoint,
                     checkpoint_interval=args.checkpoint_interval, rechunkify=False)
@@ -2370,7 +2370,8 @@ class Archiver:
     def preprocess_args(self, args):
         deprecations = [
             # ('--old', '--new' or None, 'Warning: "--old" has been deprecated. Use "--new" instead.'),
-            ('--noatime', None, 'Warning: "--noatime" has been deprecated because it is the default now.')
+            ('--noatime', None, 'Warning: "--noatime" has been deprecated because it is the default now.'),
+            ('--nobsdflags', None, 'Warning: "--nobsdflags" has been deprecated. Use --noflags instead.')
         ]
         for i, arg in enumerate(args[:]):
             for old_name, new_name, warning in deprecations:
@@ -3133,7 +3134,9 @@ class Archiver:
         fs_group.add_argument('--nobirthtime', dest='nobirthtime', action='store_true',
                               help='do not store birthtime (creation date) into archive')
         fs_group.add_argument('--nobsdflags', dest='nobsdflags', action='store_true',
-                              help='do not read and store bsdflags (e.g. NODUMP, IMMUTABLE) into archive')
+                              help='deprecated, use ``--noflags`` instead')
+        fs_group.add_argument('--noflags', dest='noflags', action='store_true',
+                              help='do not read and store flags (e.g. NODUMP, IMMUTABLE) into archive')
         fs_group.add_argument('--files-cache', metavar='MODE', dest='files_cache_mode',
                               type=FilesCacheMode, default=DEFAULT_FILES_CACHE_MODE_UI,
                               help='operate files cache in MODE. default: %s' % DEFAULT_FILES_CACHE_MODE_UI)
@@ -3526,7 +3529,9 @@ class Archiver:
         subparser.add_argument('--numeric-owner', dest='numeric_owner', action='store_true',
                                help='only obey numeric user and group identifiers')
         subparser.add_argument('--nobsdflags', dest='nobsdflags', action='store_true',
-                               help='do not extract/set bsdflags (e.g. NODUMP, IMMUTABLE)')
+                               help='deprecated, use ``--noflags`` instead')
+        subparser.add_argument('--noflags', dest='noflags', action='store_true',
+                               help='do not extract/set flags (e.g. NODUMP, IMMUTABLE)')
         subparser.add_argument('--stdout', dest='stdout', action='store_true',
                                help='write all extracted data to stdout')
         subparser.add_argument('--sparse', dest='sparse', action='store_true',

+ 3 - 3
src/borg/testsuite/__init__.py

@@ -186,7 +186,7 @@ class BaseTestCase(unittest.TestCase):
         diff = filecmp.dircmp(dir1, dir2)
         self._assert_dirs_equal_cmp(diff, **kwargs)
 
-    def _assert_dirs_equal_cmp(self, diff, ignore_bsdflags=False, ignore_xattrs=False, ignore_ns=False):
+    def _assert_dirs_equal_cmp(self, diff, ignore_flags=False, ignore_xattrs=False, ignore_ns=False):
         self.assert_equal(diff.left_only, [])
         self.assert_equal(diff.right_only, [])
         self.assert_equal(diff.diff_files, [])
@@ -206,7 +206,7 @@ class BaseTestCase(unittest.TestCase):
             d2 = [filename] + [getattr(s2, a) for a in attrs]
             d1.insert(1, oct(s1.st_mode))
             d2.insert(1, oct(s2.st_mode))
-            if not ignore_bsdflags:
+            if not ignore_flags:
                 d1.append(get_flags(path1, s1))
                 d2.append(get_flags(path2, s2))
             # ignore st_rdev if file is not a block/char device, fixes #203
@@ -232,7 +232,7 @@ class BaseTestCase(unittest.TestCase):
                 d2.append(no_selinux(get_all(path2, follow_symlinks=False)))
             self.assert_equal(d1, d2)
         for sub_diff in diff.subdirs.values():
-            self._assert_dirs_equal_cmp(sub_diff, ignore_bsdflags=ignore_bsdflags, ignore_xattrs=ignore_xattrs, ignore_ns=ignore_ns)
+            self._assert_dirs_equal_cmp(sub_diff, ignore_flags=ignore_flags, ignore_xattrs=ignore_xattrs, ignore_ns=ignore_ns)
 
     @contextmanager
     def fuse_mount(self, location, mountpoint, *options):

+ 7 - 7
src/borg/testsuite/archiver.py

@@ -2182,16 +2182,16 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
         # mount the whole repository, archive contents shall show up in archivename subdirs of mountpoint:
         with self.fuse_mount(self.repository_location, mountpoint):
-            # bsdflags are not supported by the FUSE mount
+            # flags are not supported by the FUSE mount
             # we also ignore xattrs here, they are tested separately
             self.assert_dirs_equal(self.input_path, os.path.join(mountpoint, 'archive', 'input'),
-                                   ignore_bsdflags=True, ignore_xattrs=True)
+                                   ignore_flags=True, ignore_xattrs=True)
             self.assert_dirs_equal(self.input_path, os.path.join(mountpoint, 'archive2', 'input'),
-                                   ignore_bsdflags=True, ignore_xattrs=True)
+                                   ignore_flags=True, ignore_xattrs=True)
         # mount only 1 archive, its contents shall show up directly in mountpoint:
         with self.fuse_mount(self.repository_location + '::archive', mountpoint):
             self.assert_dirs_equal(self.input_path, os.path.join(mountpoint, 'input'),
-                                   ignore_bsdflags=True, ignore_xattrs=True)
+                                   ignore_flags=True, ignore_xattrs=True)
             # regular file
             in_fn = 'input/file1'
             out_fn = os.path.join(mountpoint, 'input', 'file1')
@@ -2896,7 +2896,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02
         with changedir('output'):
             # This probably assumes GNU tar. Note -p switch to extract permissions regardless of umask.
             subprocess.check_call(['tar', 'xpf', '../simple.tar', '--warning=no-timestamp'])
-        self.assert_dirs_equal('input', 'output/input', ignore_bsdflags=True, ignore_xattrs=True, ignore_ns=True)
+        self.assert_dirs_equal('input', 'output/input', ignore_flags=True, ignore_xattrs=True, ignore_ns=True)
 
     @requires_gnutar
     @requires_gzip
@@ -2912,7 +2912,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02
         assert 'input/dir2\n' in list
         with changedir('output'):
             subprocess.check_call(['tar', 'xpf', '../simple.tar.gz', '--warning=no-timestamp'])
-        self.assert_dirs_equal('input', 'output/input', ignore_bsdflags=True, ignore_xattrs=True, ignore_ns=True)
+        self.assert_dirs_equal('input', 'output/input', ignore_flags=True, ignore_xattrs=True, ignore_ns=True)
 
     @requires_gnutar
     def test_export_tar_strip_components(self):
@@ -2928,7 +2928,7 @@ id: 2 / e29442 3506da 4e1ea7 / 25f62a 5a3d41 - 02
         assert 'input/dir2\n' in list
         with changedir('output'):
             subprocess.check_call(['tar', 'xpf', '../simple.tar', '--warning=no-timestamp'])
-        self.assert_dirs_equal('input', 'output/', ignore_bsdflags=True, ignore_xattrs=True, ignore_ns=True)
+        self.assert_dirs_equal('input', 'output/', ignore_flags=True, ignore_xattrs=True, ignore_ns=True)
 
     @requires_hardlinks
     @requires_gnutar