diff --git a/darc/archiver.py b/darc/archiver.py index 89126342b..1d571e42a 100644 --- a/darc/archiver.py +++ b/darc/archiver.py @@ -9,7 +9,7 @@ from .cache import Cache from .keychain import Keychain from .helpers import location_validator, format_file_size, format_time,\ - format_file_mode, walk_dir, IncludePattern, ExcludePattern, exclude_path + format_file_mode, walk_path, IncludePattern, ExcludePattern, exclude_path class Archiver(object): @@ -53,8 +53,22 @@ def do_create(self, args): return self.exit_code archive = Archive(store, keychain) cache = Cache(store, keychain) + # Add darc cache dir to inode_skip list + skip_inodes = [] + try: + st = os.stat(Cache.cache_dir_path()) + skip_inodes.append((st.st_ino, st.st_dev)) + except IOError: + pass + # Add local store dir to inode_skip list + if not args.archive.host: + try: + st = os.stat(args.archive.path) + skip_inodes.append((st.st_ino, st.st_dev)) + except IOError: + pass for path in args.paths: - for path, st in walk_dir(unicode(path)): + for path, st in walk_path(unicode(path)): if exclude_path(path, args.patterns): continue self.print_verbose(path) diff --git a/darc/cache.py b/darc/cache.py index 8fe0825c9..acd02da18 100644 --- a/darc/cache.py +++ b/darc/cache.py @@ -11,13 +11,18 @@ class Cache(object): def __init__(self, store, keychain): self.store = store self.keychain = keychain - self.path = os.path.join(os.path.expanduser('~'), '.darc', 'cache', + self.path = os.path.join(Cache.cache_dir_path(), '%s.cache' % self.store.id.encode('hex')) self.tid = -1 self.open() if self.tid != self.store.tid: self.init() + @staticmethod + def cache_dir_path(): + """Return path to directory used for storing users cache files""" + return os.path.join(os.path.expanduser('~'), '.darc', 'cache') + def open(self): if not os.path.exists(self.path): return diff --git a/darc/helpers.py b/darc/helpers.py index 676d79a0d..c4bb499b3 100644 --- a/darc/helpers.py +++ b/darc/helpers.py @@ -8,6 +8,29 @@ import stat +def encode_long(v): + bytes = [] + while True: + if v > 0x7f: + bytes.append(0x80 | (v % 0x80)) + v >>= 7 + else: + bytes.append(v) + return ''.join(chr(x) for x in bytes) + + +def decode_long(bytes): + v = 0 + base = 0 + for x in bytes: + b = ord(x) + if b & 0x80: + v += (b & 0x7f) << base + base += 7 + else: + return v + (b << base) + + def zero_pad(data, length): """Make sure data is `length` bytes long by prepending zero bytes @@ -63,12 +86,14 @@ class ExcludePattern(IncludePattern): """ -def walk_dir(path): +def walk_path(path, skip_inodes=None): st = os.lstat(path) + if skip_inodes and (st.st_ino, st.st_dev) in skip_inodes: + return yield path, st if stat.S_ISDIR(st.st_mode): for f in os.listdir(path): - for x in walk_dir(os.path.join(path, f)): + for x in walk_path(os.path.join(path, f), skip_inodes): yield x