34caeeba9ae2

Add line-level commenting.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Tue, 06 Oct 2009 19:27:47 -0400
parents 1ef154bb1a4f
children ab4cc556087d
branches/tags (none)
files review/api.py review/extension_ui.py review/messages.py review/tests/sample_data.py review/tests/test_comment.py review/tests/util.py

Changes

--- a/review/api.py	Mon Oct 05 20:50:06 2009 -0400
+++ b/review/api.py	Tue Oct 06 19:27:47 2009 -0400
@@ -106,14 +106,17 @@
             commentfns = filter(_match('%s/comments' % node), relevant)
             signofffns = filter(_match('%s/signoffs' % node), relevant)
             
-            self.comments = [ 
-                ReviewComment(**_parse_data(self.repo['tip'][fn].data()))
-                              for fn in commentfns
-            ]
-            self.signoffs = [ 
-                ReviewSignoff(**_parse_data(self.repo['tip'][fn].data()))
-                              for fn in signofffns
-            ]
+            self.comments = []
+            for fn in commentfns:
+                data = _parse_data(self.repo['tip'][fn].data())
+                data['lines'] = data['lines'].split(',')
+                data['lines'] = map(int, filter(None, data['lines']))
+                self.comments.append(ReviewComment(**data))
+            
+            self.signoffs = []
+            for fn in signofffns:
+                data = _parse_data(self.repo['tip'][fn].data())
+                self.signoffs.append(ReviewSignoff(**data))
         else:
             self.comments = []
             self.signoffs = []
@@ -235,6 +238,17 @@
         return templates.COMMENT_FILE_TEMPLATE % ( self.author, datetime,
             self.node, self.filename, lines, self.message )
     
+    def __str__(self):
+        return '\n'.join(map(str, [
+            self.author,
+            self.datetime,
+            self.node,
+            self.filename,
+            self.lines,
+            self.message,
+            '\n',
+        ]))
+    
 
 class ReviewSignoff(_ReviewObject):
     '''A single review signoff.'''
--- a/review/extension_ui.py	Mon Oct 05 20:50:06 2009 -0400
+++ b/review/extension_ui.py	Tue Oct 06 19:27:47 2009 -0400
@@ -6,6 +6,7 @@
 from mercurial import util
 from mercurial.node import short
 
+
 def _init_command(ui, repo, **opts):
     ui.note(messages.INIT_START)
     try:
@@ -23,6 +24,7 @@
     rev = opts.pop('rev')
     filename = fnames[0] if fnames else ''
     message = opts.pop('message')
+    lines = opts.pop('lines')
     
     rd = ReviewDatastore(ui, repo)
     rcset = rd[rev]
@@ -35,10 +37,13 @@
                 messages.COMMENT_FILE_DOES_NOT_EXIST % (filename, repo[rev].rev())
             )
     
+    if lines and not filename:
+        raise util.Abort(messages.COMMENT_LINES_REQUIRE_FILE)
+    
     if not message:
         raise util.Abort(messages.COMMENT_REQUIRES_MESSAGE)
     
-    rcset.add_comment(message=message, filename=filename)
+    rcset.add_comment(message=message, filename=filename, lines=lines.split(','))
 
 def _signoff_command(ui, repo, **opts):
     rd = ReviewDatastore(ui, repo)
@@ -76,13 +81,18 @@
     ui.write(messages.REVIEW_LOG_SIGNOFFS % len(rcset.signoffs))
     ui.write(messages.REVIEW_LOG_COMMENTS % (comment_count, author_count))
     
+    def _print_comment(comment, before='', after=''):
+        ui.write(before)
+        ui.write(messages.REVIEW_LOG_COMMENT_AUTHOR % comment.author)
+        for line in comment.message.splitlines():
+            ui.write(messages.REVIEW_LOG_COMMENT_LINE % line)
+        ui.write(after)
+    
     review_level_comments = filter(lambda c: not c.filename, rcset.comments)
     if review_level_comments:
         ui.write('\n')
     for comment in review_level_comments:
-        ui.write('\n' + messages.REVIEW_LOG_COMMENT_AUTHOR % comment.author)
-        for line in comment.message.splitlines():
-            ui.write(messages.REVIEW_LOG_COMMENT_LINE % line)
+        _print_comment(comment, before='\n')
     
     diffs = rcset.full_diffs(fnames, opts)
     
@@ -90,18 +100,26 @@
         header = messages.REVIEW_LOG_FILE_HEADER % filename
         print '\n\n%s %s' % (header, '-'*(80-(len(header)+1)))
         
-        file_level_comments = filter(lambda c: filename == c.filename, rcset.comments)
+        file_level_comments = filter(
+            lambda c: filename == c.filename and not c.lines, rcset.comments
+        )
         for comment in file_level_comments:
-            ui.write(messages.REVIEW_LOG_COMMENT_AUTHOR % comment.author)
-            for line in comment.message.splitlines():
-                ui.write(messages.REVIEW_LOG_COMMENT_LINE % line)
-            
+            _print_comment(comment)
         
         content = diffs[filename].splitlines()[2:]
         
+        line_level_comments = filter(
+            lambda c: filename == c.filename and c.lines, rcset.comments
+        )
         prefix = '%%%dd: ' % len(str(len(content)-1))
         for n, line in enumerate(content):
             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)
+        
 
 
 def review(ui, repo, *fnames, **opts):
@@ -130,6 +148,7 @@
         ('',  'force',       False, 'overwrite an existing signoff'),