]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/helpers.py
import-duplicity: use readpipe, not check_output
[bup.git] / lib / bup / helpers.py
index b052b63021511b035a94ac9945e01dce1099637d..385647ec1b8f1d90e2b5ccba7f69c38626a4e55e 100644 (file)
@@ -41,15 +41,25 @@ def atof(s):
 buglvl = atoi(os.environ.get('BUP_DEBUG', 0))
 
 
+try:
+    _fdatasync = os.fdatasync
+except AttributeError:
+    _fdatasync = os.fsync
+
 if sys.platform.startswith('darwin'):
-    # Apparently fsync on OS X doesn't guarantee to sync all the way down
+    # Apparently os.fsync on OS X doesn't guarantee to sync all the way down
     import fcntl
-    fdatasync = lambda fd : fcntl.fcntl(fd, fcntl.F_FULLFSYNC)
-else: # If the platform doesn't have fdatasync, fall back to fsync
-    try:
-        fdatasync = os.fdatasync
-    except AttributeError:
-        fdatasync = os.fsync
+    def fdatasync(fd):
+        try:
+            return fcntl.fcntl(fd, fcntl.F_FULLFSYNC)
+        except IOError as e:
+            # Fallback for file systems (SMB) that do not support F_FULLFSYNC
+            if e.errno == errno.ENOTSUP:
+                return _fdatasync(fd)
+            else:
+                raise
+else:
+    fdatasync = _fdatasync
 
 
 # Write (blockingly) to sockets that may or may not be in blocking mode.
@@ -202,9 +212,10 @@ def unlink(f):
             raise
 
 
-def readpipe(argv, preexec_fn=None):
+def readpipe(argv, preexec_fn=None, shell=False):
     """Run a subprocess and return its output."""
-    p = subprocess.Popen(argv, stdout=subprocess.PIPE, preexec_fn=preexec_fn)
+    p = subprocess.Popen(argv, stdout=subprocess.PIPE, preexec_fn=preexec_fn,
+                         shell=shell)
     out, err = p.communicate()
     if p.returncode != 0:
         raise Exception('subprocess %r failed with status %d'
@@ -1079,3 +1090,22 @@ else:
         return time.strftime('%z', localtime(t))
     def to_py_time(x):
         return x
+
+
+_some_invalid_save_parts_rx = re.compile(r'[[ ~^:?*\\]|\.\.|//|@{')
+
+def valid_save_name(name):
+    # Enforce a superset of the restrictions in git-check-ref-format(1)
+    if name == '@' \
+       or name.startswith('/') or name.endswith('/') \
+       or name.endswith('.'):
+        return False
+    if _some_invalid_save_parts_rx.search(name):
+        return False
+    for c in name:
+        if ord(c) < 0x20 or ord(c) == 0x7f:
+            return False
+    for part in name.split('/'):
+        if part.startswith('.') or part.endswith('.lock'):
+            return False
+    return True