summaryrefslogtreecommitdiff
path: root/summainlib.py
diff options
context:
space:
mode:
Diffstat (limited to 'summainlib.py')
-rw-r--r--summainlib.py51
1 files changed, 25 insertions, 26 deletions
diff --git a/summainlib.py b/summainlib.py
index ce5d130..6466383 100644
--- a/summainlib.py
+++ b/summainlib.py
@@ -35,27 +35,27 @@ __version__ = '0.19'
class NumberNormalizer(object):
'''Normalize inode and device numbers.
-
+
When we make two manifests of the same directory tree, but the
tree may have been moved to another disk, the inode and device
numbers may be different. This should not be a cause for concern,
however. What is important is that if two names were hardlinked
to the same file before, they still are, and if they weren't,
they still aren't.
-
+
To achieve this, we normalize the inode and device numbers.
The input files are fed to the normalizer in a deterministic
sequence, and the sequence defines the numbers we use. Thus,
if the input files have inode numbers [42, 13, 105], we produce
[1, 2, 3]. If one of the input numbers is repeated, that number
is re-used.
-
+
This is not a perfect solution. If the second manifest has a
new file, it will throw off the entire remaining sequence, causing
a big diff. But we'll live with that.
-
+
'''
-
+
def __init__(self):
self.reset()
@@ -65,11 +65,11 @@ class NumberNormalizer(object):
else:
numbers[input_number] = next
return numbers[input_number], next + 1
-
+
def get_ino(self, ino):
output, self.next_ino = self.get(ino, self.ino_numbers, self.next_ino)
return output
-
+
def get_dev(self, dev):
output, self.next_dev = self.get(dev, self.dev_numbers, self.next_dev)
return output
@@ -86,20 +86,20 @@ class NumberNormalizer(object):
class PathNormalizer(object):
'''Normalize a filesystem path.
-
+
Paths are normalized by using SHA-1 on a secret plus the real path.
The checksum is the normalized path.
-
+
'''
-
+
def __init__(self, secret):
self._secret = secret
-
+
def normalize(self, path):
return hmac.new(self._secret, path).hexdigest()
-class SamePath(object): # pragma: no cover
+class SamePath(object): # pragma: no cover
def normalize(self, path):
return path
@@ -127,15 +127,15 @@ RESULT_CTIME_NSEC = 16
class FilesystemObject(object):
'''An object in the file system.
-
+
Responsible for gathering information and formatting it for
reporting.
-
+
The optional arguments are intended for unit tests.
-
+
'''
-
- def __init__(self, filename, nn, pn, exclude,
+
+ def __init__(self, filename, nn, pn, exclude,
stat_result=None, sha1=None, sha224=None,
sha256=None, sha384=None, sha512=None,
md5=None, open_file=None, readlink=None,
@@ -152,7 +152,7 @@ class FilesystemObject(object):
self._sha384 = sha384 or hashlib.sha384()
self._sha512 = sha512 or hashlib.sha512()
self._stat_result = stat_result or _summain.lstat(filename)
- self._xattrs = (xattrs if xattrs is not None
+ self._xattrs = (xattrs if xattrs is not None
else self.get_xattrs(filename))
self.open_file = open_file or file
self.readlink = readlink or os.readlink
@@ -162,7 +162,7 @@ class FilesystemObject(object):
if self.relative is None:
name = self.filename
else:
- name = self.relative # pragma: no cover
+ name = self.relative # pragma: no cover
return urllib.quote(self._pn.normalize(name))
def _compute_mtime(self):
@@ -219,7 +219,7 @@ class FilesystemObject(object):
if stat.S_ISLNK(self._stat_result[RESULT_MODE]):
return self.readlink(self.filename)
- def _compute_xattrs(self): # pragma: no cover
+ def _compute_xattrs(self): # pragma: no cover
if len(self._xattrs) == 0:
return ''
@@ -231,7 +231,7 @@ class FilesystemObject(object):
parts = [' %s=%s' % (k, quote(self._xattrs[k])) for k in self._xattrs]
return '\n' + '\n'.join(parts)
-
+
def format_time(self, secs, nsecs):
s = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(secs))
s += '.%09d' % nsecs
@@ -248,7 +248,7 @@ class FilesystemObject(object):
if stat.S_ISREG(self._stat_result[RESULT_MODE]):
with self.open_file(filename) as f:
while True:
- data = f.read(64*1024) # 64 KiB seems reasonable.
+ data = f.read(64*1024) # 64 KiB seems reasonable.
if not data:
break
checksummer.update(data)
@@ -260,7 +260,7 @@ class FilesystemObject(object):
key = key.lower()
key = '_'.join(key.split('-'))
return key
-
+
def __getitem__(self, key):
normalized = self._normalize_key(key)
if normalized in self._exclude:
@@ -275,11 +275,11 @@ class FilesystemObject(object):
raise KeyError(key)
return self.values.get(key, '')
- def isdir(self): # pragma: no cover
+ def isdir(self): # pragma: no cover
'''Is this a directory?'''
return stat.S_ISDIR(int(self['Mode'], 8))
- def get_xattrs(self, filename): # pragma: no cover
+ def get_xattrs(self, filename): # pragma: no cover
ret = _summain.llistxattr(filename)
if type(ret) is int:
# Some file types don't support xattr, e.g. named pipes on FreeBSD:
@@ -293,4 +293,3 @@ class FilesystemObject(object):
for name in names:
xattrs[name] = _summain.lgetxattr(filename, name)
return xattrs
-