--- a/review/api.py Wed Mar 03 18:04:53 2010 -0500
+++ b/review/api.py Wed Mar 03 18:55:40 2010 -0500
@@ -369,6 +369,7 @@
self.node, filename, lines, message)
comment._commit(self.ui, self.repo)
+
def full_diffs(self, filenames=None, opts={}):
"""Return full diffs of the given files (or all files).
@@ -402,7 +403,7 @@
if not filenames:
filenames = target_files
else:
- filenames = filter(lambda f: f in target_files, filenames)
+ filenames = filter(lambda f: self.has_diff(f), filenames)
opts['unified'] = '100000'
node2 = self.node
@@ -457,8 +458,8 @@
There's a lot of structure there, but it will provide everything you
need to display contextualized diffs.
+ """
- """
ds = self.full_diffs(filenames, {})
def _filter_diff(d):
@@ -477,6 +478,83 @@
return ds
+ def annotated_diff(self, filename, context=5):
+ """Return a generator that yields annotated lines of a diff.
+
+ The first item yielded will be a simple integer of the last line
+ number of the diff. This is ugly but useful when creating monospaced
+ line-number-prefixed output.
+
+ Each line yielded will be of the form:
+
+ {
+ # If 'skipped' is not None, this line is a "skip" line, which
+ # represents a group of lines that were skipped due to context.
+ 'skipped': 23,
+
+ # The line number of this line, or None for skip lines.
+ 'number': 585,
+
+ # The actual content of this line, or None for skip lines.
+ 'content': '+added line',
+
+ # Any comments that apply to this line.
+ # If the line is a skip line, this will be any comments that apply
+ # to any line in the skipped group.
+ 'comments': [ReviewComment(), ReviewComment()],
+ }
+ """
+
+ diffs = self.diffs([filename], context).values()
+ if not diffs:
+ return
+
+ diff = diffs[0]
+ max_line, content = diff['max'], diff['content']
+ line_level_comments = self.line_level_comments(filename)
+ previous_n = -1
+
+ yield content[-1][0]
+
+ for n, line in content:
+ if n - 1 > previous_n:
+ yield {
+ 'skipped': (n - previous_n) - (previous_n == -1 and 1 or 0),
+ 'number': None, 'content': None,
+ 'comments': filter(
+ lambda c: max(c.lines) in range(previous_n + 1, n),
+ line_level_comments
+ ),
+ }
+
+ yield {
+ 'skipped': None,
+ 'number': n, 'content': line,
+ 'comments': filter(
+ lambda c: max(c.lines) == n, line_level_comments
+ )
+ }
+
+ previous_n = n
+
+ if previous_n < max_line:
+ yield {
+ 'skipped': max_line - previous_n,
+ 'number': None, 'content': None,
+ 'comments': filter(
+ lambda c: max(c.lines) in range(previous_n + 1, max_line),
+ line_level_comments
+ ),
+ }
+
+ def has_diff(self, filename):
+ """Return whether the given filename has a diff in this revision."""
+ return filename in self.files()
+
+ def files(self):
+ """Return the list of files in the revision for this ReviewChangeset."""
+ return self.target[self.node].files()
+
def review_level_comments(self):
"""Comments on this changeset which aren't on a particular file."""
--- a/review/extension_ui.py Wed Mar 03 18:04:53 2010 -0500
+++ b/review/extension_ui.py Wed Mar 03 18:55:40 2010 -0500
@@ -147,6 +147,7 @@
ui.write(after)
+
if rcset.signoffs:
ui.write('\n')
for signoff in rcset.signoffs:
@@ -161,53 +162,31 @@
if ui.quiet:
return
+ if not fnames:
+ fnames = rcset.files()
fnames = [sanitize_path(fname, repo) for fname in fnames]
- diffs = rcset.diffs(fnames, context)
+ fnames = [fname for fname in fnames if rcset.has_diff(fname)]
- for filename, diff in diffs.iteritems():
- max_line = diff['max']
- content = diff['content']
-
+ for filename in fnames:
header = messages.REVIEW_LOG_FILE_HEADER % filename
print '\n\n%s %s' % (header, '-'*(80-(len(header)+1)))
for comment in rcset.file_level_comments(filename):
_print_comment(comment)
- line_level_comments = rcset.line_level_comments(filename)
- prefix = '%%%dd: ' % len(str(content[-1][0]))
- previous_n = -1
- for n, line in content:
- if n - 1 > previous_n:
- skipped = n - previous_n
- if previous_n == -1:
- skipped -= 1
- ui.write(messages.REVIEW_LOG_SKIPPED % skipped)
- skipped_comments = filter(
- lambda c: max(c.lines) in range(previous_n + 1, n),
- line_level_comments
- )
- for comment in skipped_comments:
+ annotated_diff = rcset.annotated_diff(filename, context)
+ prefix = '%%%dd: ' % len(str(annotated_diff.next()))
+
+ for line in annotated_diff:
+ if line['skipped']:
+ ui.write(messages.REVIEW_LOG_SKIPPED % line['skipped'])
+ for comment in line['comments']:
_print_comment(comment)
+ continue
- ui.write('%s %s\n' % (prefix % n, line))
-
- line_comments = filter(
- lambda c: max(c.lines) == n, line_level_comments
- )
- for comment in line_comments:
- _print_comment(comment)
+ ui.write('%s %s\n' % (prefix % line['number'], line['content']))
- previous_n = n
-
- if previous_n < max_line:
- skipped = max_line - previous_n
- ui.write(messages.REVIEW_LOG_SKIPPED % skipped)
- skipped_comments = filter(
- lambda c: max(c.lines) in range(previous_n + 1, max_line),
- line_level_comments
- )
- for comment in skipped_comments:
+ for comment in line['comments']:
_print_comment(comment)