|
@@ -418,27 +418,31 @@ class ItemDiff:
|
|
self._numeric_owner = numeric_owner
|
|
self._numeric_owner = numeric_owner
|
|
self._can_compare_chunk_ids = can_compare_chunk_ids
|
|
self._can_compare_chunk_ids = can_compare_chunk_ids
|
|
self.equal = self._equal(chunk_iterator1, chunk_iterator2)
|
|
self.equal = self._equal(chunk_iterator1, chunk_iterator2)
|
|
-
|
|
|
|
- def __repr__(self):
|
|
|
|
- if self.equal:
|
|
|
|
- return 'equal'
|
|
|
|
-
|
|
|
|
changes = []
|
|
changes = []
|
|
|
|
|
|
if self._item1.is_link() or self._item2.is_link():
|
|
if self._item1.is_link() or self._item2.is_link():
|
|
- changes.append(self._link_string())
|
|
|
|
|
|
+ changes.append(self._link_diff())
|
|
|
|
|
|
if 'chunks' in self._item1 and 'chunks' in self._item2:
|
|
if 'chunks' in self._item1 and 'chunks' in self._item2:
|
|
- changes.append(self._content_string())
|
|
|
|
|
|
+ changes.append(self._content_diff())
|
|
|
|
|
|
if self._item1.is_dir() or self._item2.is_dir():
|
|
if self._item1.is_dir() or self._item2.is_dir():
|
|
- changes.append(self._dir_string())
|
|
|
|
|
|
+ changes.append(self._dir_diff())
|
|
|
|
|
|
if not (self._item1.get('deleted') or self._item2.get('deleted')):
|
|
if not (self._item1.get('deleted') or self._item2.get('deleted')):
|
|
- changes.append(self._owner_string())
|
|
|
|
- changes.append(self._mode_string())
|
|
|
|
|
|
+ changes.append(self._owner_diff())
|
|
|
|
+ changes.append(self._mode_diff())
|
|
|
|
+
|
|
|
|
+ # filter out empty changes
|
|
|
|
+ self._changes = [ch for ch in changes if ch]
|
|
|
|
|
|
- return ' '.join((x for x in changes if x))
|
|
|
|
|
|
+ def changes(self):
|
|
|
|
+ return self._changes
|
|
|
|
+
|
|
|
|
+ def __repr__(self):
|
|
|
|
+ if self.equal:
|
|
|
|
+ return 'equal'
|
|
|
|
+ return ' '.join(str for d,str in self._changes)
|
|
|
|
|
|
def _equal(self, chunk_iterator1, chunk_iterator2):
|
|
def _equal(self, chunk_iterator1, chunk_iterator2):
|
|
# if both are deleted, there is nothing at path regardless of what was deleted
|
|
# if both are deleted, there is nothing at path regardless of what was deleted
|
|
@@ -461,46 +465,52 @@ class ItemDiff:
|
|
|
|
|
|
return True
|
|
return True
|
|
|
|
|
|
- def _link_string(self):
|
|
|
|
|
|
+ def _link_diff(self):
|
|
if self._item1.get('deleted'):
|
|
if self._item1.get('deleted'):
|
|
- return 'added link'
|
|
|
|
|
|
+ return ({"type": 'added link'}, 'added link')
|
|
if self._item2.get('deleted'):
|
|
if self._item2.get('deleted'):
|
|
- return 'removed link'
|
|
|
|
|
|
+ return ({"type": 'removed link'}, 'removed link')
|
|
if 'source' in self._item1 and 'source' in self._item2 and self._item1.source != self._item2.source:
|
|
if 'source' in self._item1 and 'source' in self._item2 and self._item1.source != self._item2.source:
|
|
- return 'changed link'
|
|
|
|
|
|
+ return ({"type": 'changed link'}, 'changed link')
|
|
|
|
|
|
- def _content_string(self):
|
|
|
|
|
|
+ def _content_diff(self):
|
|
if self._item1.get('deleted'):
|
|
if self._item1.get('deleted'):
|
|
- return ('added {:>13}'.format(format_file_size(self._item2.get_size())))
|
|
|
|
|
|
+ sz = self._item2.get_size()
|
|
|
|
+ return ({"type": "added", "size": sz}, 'added {:>13}'.format(format_file_size(sz)))
|
|
if self._item2.get('deleted'):
|
|
if self._item2.get('deleted'):
|
|
- return ('removed {:>11}'.format(format_file_size(self._item1.get_size())))
|
|
|
|
|
|
+ sz = self._item1.get_size()
|
|
|
|
+ return ({"type": "removed", "size": sz}, 'removed {:>11}'.format(format_file_size(sz)))
|
|
if not self._can_compare_chunk_ids:
|
|
if not self._can_compare_chunk_ids:
|
|
- return 'modified'
|
|
|
|
|
|
+ return ({"type": "modified"}, "modified")
|
|
chunk_ids1 = {c.id for c in self._item1.chunks}
|
|
chunk_ids1 = {c.id for c in self._item1.chunks}
|
|
chunk_ids2 = {c.id for c in self._item2.chunks}
|
|
chunk_ids2 = {c.id for c in self._item2.chunks}
|
|
added_ids = chunk_ids2 - chunk_ids1
|
|
added_ids = chunk_ids2 - chunk_ids1
|
|
removed_ids = chunk_ids1 - chunk_ids2
|
|
removed_ids = chunk_ids1 - chunk_ids2
|
|
added = self._item2.get_size(consider_ids=added_ids)
|
|
added = self._item2.get_size(consider_ids=added_ids)
|
|
removed = self._item1.get_size(consider_ids=removed_ids)
|
|
removed = self._item1.get_size(consider_ids=removed_ids)
|
|
- return ('{:>9} {:>9}'.format(format_file_size(added, precision=1, sign=True),
|
|
|
|
- format_file_size(-removed, precision=1, sign=True)))
|
|
|
|
-
|
|
|
|
- def _dir_string(self):
|
|
|
|
|
|
+ return ({"type": "modified", "added": added, "removed": removed},
|
|
|
|
+ '{:>9} {:>9}'.format(format_file_size(added, precision=1, sign=True),
|
|
|
|
+ format_file_size(-removed, precision=1, sign=True)))
|
|
|
|
+
|
|
|
|
+ def _dir_diff(self):
|
|
if self._item2.get('deleted') and not self._item1.get('deleted'):
|
|
if self._item2.get('deleted') and not self._item1.get('deleted'):
|
|
- return 'removed directory'
|
|
|
|
|
|
+ return ({"type": 'removed directory'}, 'removed directory')
|
|
if self._item1.get('deleted') and not self._item2.get('deleted'):
|
|
if self._item1.get('deleted') and not self._item2.get('deleted'):
|
|
- return 'added directory'
|
|
|
|
|
|
+ return ({"type": 'added directory'}, 'added directory')
|
|
|
|
|
|
- def _owner_string(self):
|
|
|
|
|
|
+ def _owner_diff(self):
|
|
u_attr, g_attr = ('uid', 'gid') if self._numeric_owner else ('user', 'group')
|
|
u_attr, g_attr = ('uid', 'gid') if self._numeric_owner else ('user', 'group')
|
|
u1, g1 = self._item1.get(u_attr), self._item1.get(g_attr)
|
|
u1, g1 = self._item1.get(u_attr), self._item1.get(g_attr)
|
|
u2, g2 = self._item2.get(u_attr), self._item2.get(g_attr)
|
|
u2, g2 = self._item2.get(u_attr), self._item2.get(g_attr)
|
|
if (u1, g1) != (u2, g2):
|
|
if (u1, g1) != (u2, g2):
|
|
- return '[{}:{} -> {}:{}]'.format(u1, g1, u2, g2)
|
|
|
|
|
|
+ return ({"type": "owner", "old_user": u1, "old_group": g1, "new_user": u2, "new_group": g2},
|
|
|
|
+ '[{}:{} -> {}:{}]'.format(u1, g1, u2, g2))
|
|
|
|
|
|
- def _mode_string(self):
|
|
|
|
|
|
+ def _mode_diff(self):
|
|
if 'mode' in self._item1 and 'mode' in self._item2 and self._item1.mode != self._item2.mode:
|
|
if 'mode' in self._item1 and 'mode' in self._item2 and self._item1.mode != self._item2.mode:
|
|
- return '[{} -> {}]'.format(stat.filemode(self._item1.mode), stat.filemode(self._item2.mode))
|
|
|
|
|
|
+ mode1 = stat.filemode(self._item1.mode)
|
|
|
|
+ mode2 = stat.filemode(self._item2.mode)
|
|
|
|
+ return ({"type": "mode", "old_mode": mode1, "new_mode": mode2}, '[{} -> {}]'.format(mode1, mode2))
|
|
|
|
|
|
def _content_equal(self, chunk_iterator1, chunk_iterator2):
|
|
def _content_equal(self, chunk_iterator1, chunk_iterator2):
|
|
if self._can_compare_chunk_ids:
|
|
if self._can_compare_chunk_ids:
|