More work on the diff kitten

This commit is contained in:
Kovid Goyal
2018-05-05 13:38:28 +05:30
parent 4691257233
commit 67379c67cc
2 changed files with 52 additions and 21 deletions

View File

@@ -47,7 +47,12 @@ class Collection:
def __iter__(self):
for path in self.all_paths:
typ = self.type_map[path]
data = self.changes[path] if typ == 'diff' else None
if typ == 'diff':
data = self.changes[path]
elif typ == 'rename':
data = self.renames[path]
else:
data = None
yield path, self.type_map[path], data
@@ -76,7 +81,7 @@ def collect_files(collection, left, right):
for name, rh in rhash.items():
for n, ah in ahash.items():
if ah == rh and data_for_path(left_path_map[name]) == data_for_path(right_path_map[n]):
collection.add_rename(left_path_map[name], right_path_map[name])
collection.add_rename(left_path_map[name], right_path_map[n])
added.discard(n)
break
else:
@@ -103,9 +108,14 @@ def mime_type_for_path(path):
@lru_cache(maxsize=1024)
def data_for_path(path):
def raw_data_for_path(path):
with open(path, 'rb') as f:
ans = f.read()
return f.read()
@lru_cache(maxsize=1024)
def data_for_path(path):
ans = raw_data_for_path(path)
if not mime_type_for_path(path).startswith('image/'):
try:
ans = ans.decode('utf-8')
@@ -122,7 +132,7 @@ def lines_for_path(path):
@lru_cache(maxsize=1024)
def hash_for_path(path):
md5(data_for_path(path)).digest()
return md5(raw_data_for_path(path)).digest()
def create_collection(left, right):

View File

@@ -124,13 +124,21 @@ def title_lines(left_path, args, columns, margin_size):
def binary_lines(path, other_path, columns, margin_size):
template = _('Binary file: {}')
available_cols = columns // 2 - margin_size
def fl(path):
def fl(path, fmt):
text = template.format(human_readable(len(data_for_path(path))))
text = place_in(text, columns // 2 - margin_size)
return margin_format(' ' * margin_size) + text_format(text)
text = place_in(text, available_cols)
return margin_format(' ' * margin_size) + fmt(text)
return fl(path) + fl(other_path)
if path is None:
filler = render_diff_line('', '', 'filler', margin_size, available_cols)
yield filler + fl(other_path, added_format)
elif other_path is None:
filler = render_diff_line('', '', 'filler', margin_size, available_cols)
yield fl(other_path, added_format) + filler
else:
yield fl(path, removed_format) + fl(other_path, added_format)
def split_to_size(line, width):
@@ -289,17 +297,24 @@ def all_lines(path, args, columns, margin_size, is_add=True):
ltype = 'add' if is_add else 'remove'
lines = lines_for_path(path)
filler = render_diff_line('', '', 'filler', margin_size, available_cols)
msg_written = False
for line_number in range(len(lines)):
h = render_half_line(line_number, lines, ltype, margin_size, available_cols)
for i, hl in enumerate(h):
ref = Reference(path, LineRef(line_number, i))
text = (filler + h) if is_add else (h + filler)
empty = filler
if not msg_written:
msg_written = True
empty = render_diff_line(
'', _('This file was added') if is_add else _('This file was removed'),
'filler', margin_size, available_cols)
text = (empty + hl) if is_add else (hl + empty)
yield Line(text, ref)
def rename_lines(path, other_path, args, columns, margin_size):
m = ' ' * margin_size
for line in split_to_size(margin_size + _('The file {0} was renamed to {1}').format(
for line in split_to_size(_('The file {0} was renamed to {1}').format(
sanitize(path_name_map[path]), sanitize(path_name_map[other_path])), columns - margin_size):
yield m + line
@@ -316,19 +331,25 @@ def render_diff(collection, diff_map, args, columns):
for path, item_type, other_path in collection:
item_ref = Reference(path)
is_binary = isinstance(data_for_path(path), bytes)
yield from yield_lines_from(title_lines(path, args, columns, margin_size), item_ref)
if item_type == 'diff':
yield from yield_lines_from(title_lines(path, args, columns, margin_size), item_ref)
is_binary = isinstance(data_for_path(path), bytes)
if is_binary:
yield from yield_lines_from(binary_lines(path, other_path, columns, margin_size), item_ref)
ans = yield_lines_from(binary_lines(path, other_path, columns, margin_size), item_ref)
else:
yield from lines_for_diff(path, other_path, diff_map[path], args, columns, margin_size)
ans = lines_for_diff(path, other_path, diff_map[path], args, columns, margin_size)
elif item_type == 'add':
yield from yield_lines_from(title_lines(other_path, args, columns, margin_size), item_ref)
yield from all_lines(other_path, args, columns, margin_size, is_add=True)
if is_binary:
ans = yield_lines_from(binary_lines(None, path, columns, margin_size), item_ref)
else:
ans = all_lines(path, args, columns, margin_size, is_add=True)
elif item_type == 'removal':
yield from yield_lines_from(title_lines(path, args, columns, margin_size), item_ref)
yield from all_lines(path, args, columns, margin_size, is_add=False)
if is_binary:
ans = yield_lines_from(binary_lines(path, None, columns, margin_size), item_ref)
else:
ans = all_lines(path, args, columns, margin_size, is_add=False)
elif item_type == 'rename':
yield from yield_lines_from(title_lines(path, args, columns, margin_size), item_ref)
yield from yield_lines_from(rename_lines(path, other_path, args, columns, margin_size))
ans = yield_lines_from(rename_lines(path, other_path, args, columns, margin_size), item_ref)
else:
raise ValueError('Unsupported item type: {}'.format(item_type))
yield from ans