]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/metadata.py
Replace remaining print statements with print function
[bup.git] / lib / bup / metadata.py
index 3dd8af9dc718043c4783b1b82d3b5bcb2f96d88a..58e3afa2beaab94926ec9b864b0508bd33e0bd2a 100644 (file)
@@ -5,8 +5,11 @@
 # This code is covered under the terms of the GNU Library General
 # Public License as described in the bup LICENSE file.
 
+from __future__ import absolute_import, print_function
+from copy import deepcopy
 from errno import EACCES, EINVAL, ENOTTY, ENOSYS, EOPNOTSUPP
 from io import BytesIO
+from time import gmtime, strftime
 import errno, os, sys, stat, time, pwd, grp, socket, struct
 
 from bup import vint, xstat
@@ -463,7 +466,9 @@ class Metadata:
         return self.symlink_target
 
     def _load_symlink_target_rec(self, port):
-        self.symlink_target = vint.read_bvec(port)
+        target = vint.read_bvec(port)
+        self.symlink_target = target
+        self.size = len(target)
 
 
     ## Hardlink targets
@@ -718,30 +723,69 @@ class Metadata:
         self.linux_xattr = None
         self.posix1e_acl = None
 
+    def __eq__(self, other):
+        if not isinstance(other, Metadata): return False
+        if self.mode != other.mode: return False
+        if self.mtime != other.mtime: return False
+        if self.ctime != other.ctime: return False
+        if self.atime != other.atime: return False
+        if self.path != other.path: return False
+        if self.uid != other.uid: return False
+        if self.gid != other.gid: return False
+        if self.size != other.size: return False
+        if self.user != other.user: return False
+        if self.group != other.group: return False
+        if self.symlink_target != other.symlink_target: return False
+        if self.hardlink_target != other.hardlink_target: return False
+        if self.linux_attr != other.linux_attr: return False
+        if self.posix1e_acl != other.posix1e_acl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __hash__(self):
+        return hash((self.mode,
+                     self.mtime,
+                     self.ctime,
+                     self.atime,
+                     self.path,
+                     self.uid,
+                     self.gid,
+                     self.size,
+                     self.user,
+                     self.group,
+                     self.symlink_target,
+                     self.hardlink_target,
+                     self.linux_attr,
+                     self.posix1e_acl))
+
     def __repr__(self):
         result = ['<%s instance at %s' % (self.__class__, hex(id(self)))]
-        if self.path:
+        if self.path is not None:
             result += ' path:' + repr(self.path)
-        if self.mode:
+        if self.mode is not None:
             result += ' mode:' + repr(xstat.mode_str(self.mode)
-                                      + '(%s)' % hex(self.mode))
-        if self.uid:
+                                      + '(%s)' % oct(self.mode))
+        if self.uid is not None:
             result += ' uid:' + str(self.uid)
-        if self.gid:
+        if self.gid is not None:
             result += ' gid:' + str(self.gid)
-        if self.user:
+        if self.user is not None:
             result += ' user:' + repr(self.user)
-        if self.group:
+        if self.group is not None:
             result += ' group:' + repr(self.group)
-        if self.size:
+        if self.size is not None:
             result += ' size:' + repr(self.size)
         for name, val in (('atime', self.atime),
                           ('mtime', self.mtime),
                           ('ctime', self.ctime)):
-            result += ' %s:%r' \
-                % (name,
-                   time.strftime('%Y-%m-%d %H:%M %z',
-                                 time.gmtime(xstat.fstime_floor_secs(val))))
+            if val is not None:
+                result += ' %s:%r (%d)' \
+                          % (name,
+                             strftime('%Y-%m-%d %H:%M %z',
+                                      gmtime(xstat.fstime_floor_secs(val))),
+                             val)
         result += '>'
         return ''.join(result)
 
@@ -766,6 +810,9 @@ class Metadata:
         self.write(port, include_path)
         return port.getvalue()
 
+    def copy(self):
+        return deepcopy(self)
+
     @staticmethod
     def read(port):
         # This method should either return a valid Metadata object,
@@ -878,7 +925,7 @@ def save_tree(output_file, paths,
             m = from_path(p, statinfo=st, archive_path=safe_path,
                           save_symlinks=save_symlinks)
             if verbose:
-                print >> sys.stderr, m.path
+                print(m.path, file=sys.stderr)
             m.write(output_file, include_path=write_paths)
     else:
         start_dir = os.getcwd()
@@ -890,7 +937,7 @@ def save_tree(output_file, paths,
                 m = from_path(p, statinfo=st, archive_path=safe_path,
                               save_symlinks=save_symlinks)
                 if verbose:
-                    print >> sys.stderr, m.path
+                    print(m.path, file=sys.stderr)
                 m.write(output_file, include_path=write_paths)
                 os.chdir(dirlist_dir)
         finally:
@@ -938,7 +985,7 @@ def summary_str(meta, numeric_ids = False, classification = None,
         mode_str = xstat.mode_str(meta.mode)
         symlink_target = meta.symlink_target
         mtime_secs = xstat.fstime_floor_secs(meta.mtime)
-        mtime_str = time.strftime('%Y-%m-%d %H:%M', time.localtime(mtime_secs))
+        mtime_str = strftime('%Y-%m-%d %H:%M', time.localtime(mtime_secs))
         if meta.user and not numeric_ids:
             user_str = meta.user
         elif meta.uid != None:
@@ -1060,20 +1107,19 @@ def display_archive(file):
         first_item = True
         for meta in _ArchiveIterator(file):
             if not first_item:
-                print
-            print detailed_str(meta)
+                print()
+            print(detailed_str(meta))
             first_item = False
     elif verbose > 0:
         for meta in _ArchiveIterator(file):
-            print summary_str(meta)
+            print(summary_str(meta))
     elif verbose == 0:
         for meta in _ArchiveIterator(file):
             if not meta.path:
-                print >> sys.stderr, \
-                    'bup: no metadata path, but asked to only display path', \
-                    '(increase verbosity?)'
+                print('bup: no metadata path, but asked to only display path'
+                     '(increase verbosity?)')
                 sys.exit(1)
-            print meta.path
+            print(meta.path)
 
 
 def start_extract(file, create_symlinks=True):
@@ -1081,7 +1127,7 @@ def start_extract(file, create_symlinks=True):
         if not meta: # Hit end record.
             break
         if verbose:
-            print >> sys.stderr, meta.path
+            print(meta.path, file=sys.stderr)
         xpath = _clean_up_extract_path(meta.path)
         if not xpath:
             add_error(Exception('skipping risky path "%s"' % meta.path))
@@ -1103,7 +1149,7 @@ def finish_extract(file, restore_numeric_ids=False):
                 all_dirs.append(meta)
             else:
                 if verbose:
-                    print >> sys.stderr, meta.path
+                    print(meta.path, file=sys.stderr)
                 meta.apply_to_path(path=xpath,
                                    restore_numeric_ids=restore_numeric_ids)
     all_dirs.sort(key = lambda x : len(x.path), reverse=True)
@@ -1111,7 +1157,7 @@ def finish_extract(file, restore_numeric_ids=False):
         # Don't need to check xpath -- won't be in all_dirs if not OK.
         xpath = _clean_up_extract_path(dir.path)
         if verbose:
-            print >> sys.stderr, dir.path
+            print(dir.path, file=sys.stderr)
         dir.apply_to_path(path=xpath, restore_numeric_ids=restore_numeric_ids)
 
 
@@ -1128,20 +1174,20 @@ def extract(file, restore_numeric_ids=False, create_symlinks=True):
         else:
             meta.path = xpath
             if verbose:
-                print >> sys.stderr, '+', meta.path
+                print('+', meta.path, file=sys.stderr)
             _set_up_path(meta, create_symlinks=create_symlinks)
             if os.path.isdir(meta.path):
                 all_dirs.append(meta)
             else:
                 if verbose:
-                    print >> sys.stderr, '=', meta.path
+                    print('=', meta.path, file=sys.stderr)
                 meta.apply_to_path(restore_numeric_ids=restore_numeric_ids)
     all_dirs.sort(key = lambda x : len(x.path), reverse=True)
     for dir in all_dirs:
         # Don't need to check xpath -- won't be in all_dirs if not OK.
         xpath = _clean_up_extract_path(dir.path)
         if verbose:
-            print >> sys.stderr, '=', xpath
+            print('=', xpath, file=sys.stderr)
         # Shouldn't have to check for risky paths here (omitted above).
         dir.apply_to_path(path=dir.path,
                           restore_numeric_ids=restore_numeric_ids)