浏览代码

borg umount, fixes #1855

this refactors umount code we already used for the testsuite into the platform module's namespace.

also, it exposes that functionality via the cli api, so users can use it via "borg umount <mountpoint>",
which is more consistent than using borg to mount and fusermount -u (or umount) to un-mount.
Thomas Waldmann 8 年之前
父节点
当前提交
e17fe2b295
共有 9 个文件被更改,包括 82 次插入12 次删除
  1. 20 0
      borg/archiver.py
  2. 1 1
      borg/helpers.py
  3. 8 2
      borg/platform.py
  4. 1 1
      borg/platform_darwin.pyx
  5. 1 1
      borg/platform_freebsd.pyx
  6. 6 1
      borg/platform_linux.pyx
  7. 2 5
      borg/testsuite/__init__.py
  8. 3 1
      docs/usage.rst
  9. 40 0
      docs/usage/umount.rst.inc

+ 20 - 0
borg/archiver.py

@@ -34,6 +34,7 @@ from .key import key_creator, RepoKey, PassphraseKey
 from .keymanager import KeyManager
 from .archive import backup_io, BackupOSError, Archive, ArchiveChecker, CHUNKER_PARAMS, is_special
 from .remote import RepositoryServer, RemoteRepository, cache_if_remote
+from .platform import umount
 
 has_lchflags = hasattr(os, 'lchflags')
 
@@ -539,6 +540,10 @@ class Archiver:
                 self.exit_code = EXIT_ERROR
         return self.exit_code
 
+    def do_umount(self, args):
+        """un-mount the FUSE filesystem"""
+        return umount(args.mountpoint)
+
     @with_repository()
     def do_list(self, args, repository, manifest, key):
         """List archive or repository contents"""
@@ -1476,6 +1481,21 @@ class Archiver:
         subparser.add_argument('-o', dest='options', type=str,
                                help='Extra mount options')
 
+        umount_epilog = textwrap.dedent("""
+        This command un-mounts a FUSE filesystem that was mounted with ``borg mount``.
+
+        This is a convenience wrapper that just calls the platform-specific shell
+        command - usually this is either umount or fusermount -u.
+        """)
+        subparser = subparsers.add_parser('umount', parents=[common_parser],
+                                          description=self.do_umount.__doc__,
+                                          epilog=umount_epilog,
+                                          formatter_class=argparse.RawDescriptionHelpFormatter,
+                                          help='umount repository')
+        subparser.set_defaults(func=self.do_umount)
+        subparser.add_argument('mountpoint', metavar='MOUNTPOINT', type=str,
+                               help='mountpoint of the filesystem to umount')
+
         info_epilog = textwrap.dedent("""
         This command displays some detailed information about the specified archive.
 

+ 1 - 1
borg/helpers.py

@@ -88,7 +88,7 @@ def check_extension_modules():
         raise ExtensionModuleError
     if crypto.API_VERSION != 2:
         raise ExtensionModuleError
-    if platform.API_VERSION != 2:
+    if platform.API_VERSION != 3:
         raise ExtensionModuleError
 
 

+ 8 - 2
borg/platform.py

@@ -1,5 +1,6 @@
 import errno
 import os
+import subprocess
 import sys
 
 
@@ -17,14 +18,19 @@ def sync_dir(path):
         os.close(fd)
 
 
+# most POSIX platforms (but not Linux), see also borg 1.1 platform.base
+def umount(mountpoint):
+    return subprocess.call(['umount', mountpoint])
+
+
 if sys.platform.startswith('linux'):  # pragma: linux only
-    from .platform_linux import acl_get, acl_set, API_VERSION
+    from .platform_linux import acl_get, acl_set, umount, API_VERSION
 elif sys.platform.startswith('freebsd'):  # pragma: freebsd only
     from .platform_freebsd import acl_get, acl_set, API_VERSION
 elif sys.platform == 'darwin':  # pragma: darwin only
     from .platform_darwin import acl_get, acl_set, API_VERSION
 else:  # pragma: unknown platform only
-    API_VERSION = 2
+    API_VERSION = 3
 
     def acl_get(path, item, st, numeric_owner=False):
         pass

+ 1 - 1
borg/platform_darwin.pyx

@@ -1,7 +1,7 @@
 import os
 from .helpers import user2uid, group2gid, safe_decode, safe_encode
 
-API_VERSION = 2
+API_VERSION = 3
 
 cdef extern from "sys/acl.h":
     ctypedef struct _acl_t:

+ 1 - 1
borg/platform_freebsd.pyx

@@ -1,7 +1,7 @@
 import os
 from .helpers import posix_acl_use_stored_uid_gid, safe_encode, safe_decode
 
-API_VERSION = 2
+API_VERSION = 3
 
 cdef extern from "errno.h":
     int errno

+ 6 - 1
borg/platform_linux.pyx

@@ -1,9 +1,10 @@
 import os
 import re
+import subprocess
 from stat import S_ISLNK
 from .helpers import posix_acl_use_stored_uid_gid, user2uid, group2gid, safe_decode, safe_encode
 
-API_VERSION = 2
+API_VERSION = 3
 
 cdef extern from "sys/types.h":
     int ACL_TYPE_ACCESS
@@ -141,3 +142,7 @@ def acl_set(path, item, numeric_owner=False):
                 acl_set_file(p, ACL_TYPE_DEFAULT, default_acl)
         finally:
             acl_free(default_acl)
+
+
+def umount(mountpoint):
+    return subprocess.call(['fusermount', '-u', mountpoint])

+ 2 - 5
borg/testsuite/__init__.py

@@ -9,6 +9,7 @@ import time
 import unittest
 from ..xattr import get_all
 from ..logger import setup_logging
+from ..platform import umount
 
 try:
     import llfuse
@@ -110,11 +111,7 @@ class BaseTestCase(unittest.TestCase):
         self.cmd(*args, fork=True)
         self.wait_for_mount(mountpoint)
         yield
-        if sys.platform.startswith('linux'):
-            cmd = 'fusermount -u %s' % mountpoint
-        else:
-            cmd = 'umount %s' % mountpoint
-        os.system(cmd)
+        umount(mountpoint)
         os.rmdir(mountpoint)
         # Give the daemon some time to exit
         time.sleep(.2)

+ 3 - 1
docs/usage.rst

@@ -545,6 +545,8 @@ Examples
 
 .. include:: usage/mount.rst.inc
 
+.. include:: usage/umount.rst.inc
+
 Examples
 ~~~~~~~~
 ::
@@ -552,7 +554,7 @@ Examples
     $ borg mount /path/to/repo::root-2016-02-15 /tmp/mymountpoint
     $ ls /tmp/mymountpoint
     bin  boot  etc	home  lib  lib64  lost+found  media  mnt  opt  root  sbin  srv  tmp  usr  var
-    $ fusermount -u /tmp/mymountpoint
+    $ borg umount /tmp/mymountpoint
 
 
 .. include:: usage/key_export.rst.inc

+ 40 - 0
docs/usage/umount.rst.inc

@@ -0,0 +1,40 @@
+.. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!
+
+.. _borg_umount:
+
+borg umount
+-----------
+::
+
+    usage: borg umount [-h] [--critical] [--error] [--warning] [--info] [--debug]
+                       [--lock-wait N] [--show-rc] [--no-files-cache] [--umask M]
+                       [--remote-path PATH]
+                       MOUNTPOINT
+    
+    un-mount the FUSE filesystem
+    
+    positional arguments:
+      MOUNTPOINT            mountpoint of the filesystem to umount
+    
+    optional arguments:
+      -h, --help            show this help message and exit
+      --critical            work on log level CRITICAL
+      --error               work on log level ERROR
+      --warning             work on log level WARNING (default)
+      --info, -v, --verbose
+                            work on log level INFO
+      --debug               work on log level DEBUG
+      --lock-wait N         wait for the lock, but max. N seconds (default: 1).
+      --show-rc             show/log the return code (rc)
+      --no-files-cache      do not load/update the file metadata cache used to
+                            detect unchanged files
+      --umask M             set umask to M (local and remote, default: 0077)
+      --remote-path PATH    set remote path to executable (default: "borg")
+    
+Description
+~~~~~~~~~~~
+
+This command un-mounts a FUSE filesystem that was mounted with ``borg mount``.
+
+This is a convenience wrapper that just calls the platform-specific shell
+command - usually this is either umount or fusermount -u.