From c306bca3733f05677340908e4a65a551f37882d3 Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Sat, 23 Nov 2013 12:50:37 -0500 Subject: [PATCH 1/2] moved the process_diff_method from gitless to gitpylib --- gitpylib/file.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/gitpylib/file.py b/gitpylib/file.py index 0f6ce77..3fad88e 100644 --- a/gitpylib/file.py +++ b/gitpylib/file.py @@ -5,7 +5,9 @@ """Module for dealing with Git files.""" +import collections import os.path +import re import common @@ -14,6 +16,12 @@ FILE_NOT_FOUND = 2 FILE_NOT_FOUND_AT_CP = 3 +# Possible diff output lines. +DIFF_INFO = 4 # line carrying diff info for new hunk. +DIFF_SAME = 5 # line that git diff includes for context. +DIFF_ADDED = 6 +DIFF_MINUS = 7 + def stage(fp): """Stages the given file. @@ -118,7 +126,7 @@ def diff(fp): fp = common.real_case(fp) out, unused_err = common.safe_git_call('diff -- "%s"' % fp) - return out + return _process_diff_output(_strip_diff_header(out.splitlines())) def staged_diff(fp): @@ -133,4 +141,75 @@ def staged_diff(fp): fp = common.real_case(fp) out, unused_err = common.safe_git_call('diff --cached -- "%s"' % fp) - return out + return _process_diff_output(_strip_diff_header(out.splitlines())) + + +# Private functions. + + +def _strip_diff_header(diff_out): + """Removes the diff header lines.""" + first_non_header_line = 0 + for line in diff_out: + if line.startswith('@@'): + break + first_non_header_line += 1 + return diff_out[first_non_header_line:] + + +def _process_diff_output(diff_out): + """Process the git diff output. + + Args: + diff_out: a list of lines output by the git diff command. + + Returns: + a 2-tuple of: + - a list of namedtuples with fields 'line', 'status', 'old_line_number' + and 'new_line_number' where 'status' is one of DIFF_INFO, DIFF_SAME, + DIFF_ADDED or DIFF_MINUS and 'old_line_number', 'new_line_number' + correspond to the line's old line number and new line number respectively. + (Note that, for example, if the line is DIFF_ADDED, then 'old_line_number' + is None since that line is not present in the old file). + - max_line_digits: return the maximum amount of line digits found while + parsing the git diff output, this is useful for padding. + """ + MIN_LINE_PADDING = 8 + LineData = collections.namedtuple( + 'LineData', + ['line', 'status', 'old_line_number', 'new_line_number']) + + resulting = [] # accumulates line information for formatting. + max_line_digits = 0 + old_line_number = 1 + new_line_number = 1 + + for line in diff_out: + # @@ -(start of old),(length of old) +(start of new),(length of new) @@ + new_hunk_regex = "^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@" + new_hunk_info = re.search(new_hunk_regex, line) + if new_hunk_info: + old_line_number = int(new_hunk_info.group(1)) + old_diff_length = int(new_hunk_info.group(2)) + new_line_number = int(new_hunk_info.group(3)) + new_diff_length = int(new_hunk_info.group(4)) + resulting.append( + LineData(line, DIFF_INFO, old_line_number, new_line_number)) + max_line_digits = max([old_line_number + old_diff_length, + new_line_number + new_diff_length, + max_line_digits]) # start + length of each diff. + elif line.startswith(' '): + resulting.append( + LineData(line, DIFF_SAME, old_line_number, new_line_number)) + old_line_number += 1 + new_line_number += 1 + elif line.startswith('-'): + resulting.append(LineData(line, DIFF_MINUS, old_line_number, None)) + old_line_number += 1 + elif line.startswith('+'): + resulting.append(LineData(line, DIFF_ADDED, None, new_line_number)) + new_line_number += 1 + + max_line_digits = len(str(max_line_digits)) # digits = len(string of number). + max_line_digits = max(MIN_LINE_PADDING, max_line_digits + 1) + return resulting, max_line_digits From 63853578ab483bfe995b42f56ec08e324024d5cd Mon Sep 17 00:00:00 2001 From: Santiago Perez De Rosso Date: Sat, 23 Nov 2013 13:17:59 -0500 Subject: [PATCH 2/2] Release 0.4 --- RELEASE_NOTES.md | 10 ++++++++++ setup.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 RELEASE_NOTES.md diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..9b5f5bd --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,10 @@ +Gitpylib's Release Notes +======================== + +23rd Nov 2013 - 0.4 +------------------- + +* machine-friendly output of diff command. + + +(No notes for previous releases) diff --git a/setup.py b/setup.py index 7edd456..64964c1 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='gitpylib', - version='0.2.1', + version='0.4', description='A Python library for Git', long_description=open('README.md').read(), author='Santiago Perez De Rosso',