| 
				
			 | 
			
			
				@@ -2,13 +2,13 @@ 
			 | 
		
	
		
			
			| 
				2
			 | 
			
				2
			 | 
			
			
				 # -*- coding: utf-8 -*- 
			 | 
		
	
		
			
			| 
				3
			 | 
			
				3
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				4
			 | 
			
				4
			 | 
			
			
				 """ 
			 | 
		
	
		
			
			| 
				5
			 | 
			
				
			 | 
			
			
				-Term based tool to view **colored**, **incremental** diff in *git/svn/hg* 
			 | 
		
	
		
			
			| 
				
			 | 
			
				5
			 | 
			
			
				+Term based tool to view **colored**, **incremental** diff in Git/Mercurial/Svn 
			 | 
		
	
		
			
			| 
				6
			 | 
			
				6
			 | 
			
			
				 workspace, given patch or two files, or from stdin, with **side by side** and 
			 | 
		
	
		
			
			| 
				7
			 | 
			
				7
			 | 
			
			
				 **auto pager** support.  Requires python (>= 2.5.0) and ``less``. 
			 | 
		
	
		
			
			| 
				8
			 | 
			
				8
			 | 
			
			
				 """ 
			 | 
		
	
		
			
			| 
				9
			 | 
			
				9
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				10
			 | 
			
				10
			 | 
			
			
				 META_INFO = { 
			 | 
		
	
		
			
			| 
				11
			 | 
			
				
			 | 
			
			
				-    'version'     : '0.5', 
			 | 
		
	
		
			
			| 
				
			 | 
			
				11
			 | 
			
			
				+    'version'     : '0.5.1', 
			 | 
		
	
		
			
			| 
				12
			 | 
			
				12
			 | 
			
			
				     'license'     : 'BSD-3', 
			 | 
		
	
		
			
			| 
				13
			 | 
			
				13
			 | 
			
			
				     'author'      : 'Matthew Wang', 
			 | 
		
	
		
			
			| 
				14
			 | 
			
				14
			 | 
			
			
				     'email'       : 'mattwyl(@)gmail(.)com', 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -50,12 +50,24 @@ COLORS = { 
			 | 
		
	
		
			
			| 
				50
			 | 
			
				50
			 | 
			
			
				 } 
			 | 
		
	
		
			
			| 
				51
			 | 
			
				51
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				52
			 | 
			
				52
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				53
			 | 
			
				
			 | 
			
			
				-# Keys for checking and values for diffing. 
			 | 
		
	
		
			
			| 
				54
			 | 
			
				
			 | 
			
			
				-REVISION_CONTROL = ( 
			 | 
		
	
		
			
			| 
				55
			 | 
			
				
			 | 
			
			
				-    (['git', 'rev-parse'], ['git', 'diff'], ['git', 'log', '--patch']), 
			 | 
		
	
		
			
			| 
				56
			 | 
			
				
			 | 
			
			
				-    (['svn', 'info'],      ['svn', 'diff'], ['svn', 'log', '--diff']), 
			 | 
		
	
		
			
			| 
				57
			 | 
			
				
			 | 
			
			
				-    (['hg',  'summary'],   ['hg',  'diff'], ['hg',  'log', '--patch']) 
			 | 
		
	
		
			
			| 
				58
			 | 
			
				
			 | 
			
			
				-) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				53
			 | 
			
			
				+# Keys for revision control probe, diff and log with diff 
			 | 
		
	
		
			
			| 
				
			 | 
			
				54
			 | 
			
			
				+VCS_INFO = { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				55
			 | 
			
			
				+    'Git': { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				56
			 | 
			
			
				+        'probe' : ['git', 'rev-parse'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				57
			 | 
			
			
				+        'diff'  : ['git', 'diff'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				58
			 | 
			
			
				+        'log'   : ['git', 'log', '--patch'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				59
			 | 
			
			
				+    }, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				60
			 | 
			
			
				+    'Mercurial': { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				61
			 | 
			
			
				+        'probe' : ['hg', 'summary'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				62
			 | 
			
			
				+        'diff'  : ['hg', 'diff'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				63
			 | 
			
			
				+        'log'   : ['hg', 'log', '--patch'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				64
			 | 
			
			
				+    }, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				65
			 | 
			
			
				+    'Svn': { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				66
			 | 
			
			
				+        'probe' : ['svn', 'info'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				67
			 | 
			
			
				+        'diff'  : ['svn', 'diff'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				68
			 | 
			
			
				+        'log'   : ['svn', 'log', '--diff'], 
			 | 
		
	
		
			
			| 
				
			 | 
			
				69
			 | 
			
			
				+    }, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				70
			 | 
			
			
				+} 
			 | 
		
	
		
			
			| 
				59
			 | 
			
				71
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				60
			 | 
			
				72
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				61
			 | 
			
				73
			 | 
			
			
				 def ansi_code(color): 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -86,9 +98,10 @@ class Hunk(object): 
			 | 
		
	
		
			
			| 
				86
			 | 
			
				98
			 | 
			
			
				     def get_new_addr(self): 
			 | 
		
	
		
			
			| 
				87
			 | 
			
				99
			 | 
			
			
				         return self._new_addr 
			 | 
		
	
		
			
			| 
				88
			 | 
			
				100
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				89
			 | 
			
				
			 | 
			
			
				-    def append(self, attr, line): 
			 | 
		
	
		
			
			| 
				90
			 | 
			
				
			 | 
			
			
				-        """attr: '-': old, '+': new, ' ': common""" 
			 | 
		
	
		
			
			| 
				91
			 | 
			
				
			 | 
			
			
				-        self._hunk_list.append((attr, line)) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				101
			 | 
			
			
				+    def append(self, hunk_line): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				102
			 | 
			
			
				+        """hunk_line is a 2-element tuple: (attr, text), where attris : '-': 
			 | 
		
	
		
			
			| 
				
			 | 
			
				103
			 | 
			
			
				+        old, '+': new, ' ': common""" 
			 | 
		
	
		
			
			| 
				
			 | 
			
				104
			 | 
			
			
				+        self._hunk_list.append(hunk_line) 
			 | 
		
	
		
			
			| 
				92
			 | 
			
				105
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				93
			 | 
			
				106
			 | 
			
			
				     def mdiff(self): 
			 | 
		
	
		
			
			| 
				94
			 | 
			
				107
			 | 
			
			
				         r"""The difflib._mdiff() function returns an interator which returns a 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -134,9 +147,9 @@ class Diff(object): 
			 | 
		
	
		
			
			| 
				134
			 | 
			
				147
			 | 
			
			
				         self._new_path = new_path 
			 | 
		
	
		
			
			| 
				135
			 | 
			
				148
			 | 
			
			
				         self._hunks = hunks 
			 | 
		
	
		
			
			| 
				136
			 | 
			
				149
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				137
			 | 
			
				
			 | 
			
			
				-    # Follow detector and the parse_hunk_meta() are suppose to be overwritten 
			 | 
		
	
		
			
			| 
				138
			 | 
			
				
			 | 
			
			
				-    # by derived class.  No is_header() anymore, all non-recognized lines are 
			 | 
		
	
		
			
			| 
				139
			 | 
			
				
			 | 
			
			
				-    # considered as headers 
			 | 
		
	
		
			
			| 
				
			 | 
			
				150
			 | 
			
			
				+    # Following detectors, parse_hunk_meta() and parse_hunk_line() are suppose 
			 | 
		
	
		
			
			| 
				
			 | 
			
				151
			 | 
			
			
				+    # to be overwritten by derived class.  No is_header() anymore, all 
			 | 
		
	
		
			
			| 
				
			 | 
			
				152
			 | 
			
			
				+    # non-recognized lines are considered as headers 
			 | 
		
	
		
			
			| 
				140
			 | 
			
				153
			 | 
			
			
				     # 
			 | 
		
	
		
			
			| 
				141
			 | 
			
				154
			 | 
			
			
				     def is_old_path(self, line): 
			 | 
		
	
		
			
			| 
				142
			 | 
			
				155
			 | 
			
			
				         return False 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -148,9 +161,14 @@ class Diff(object): 
			 | 
		
	
		
			
			| 
				148
			 | 
			
				161
			 | 
			
			
				         return False 
			 | 
		
	
		
			
			| 
				149
			 | 
			
				162
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				150
			 | 
			
				163
			 | 
			
			
				     def parse_hunk_meta(self, line): 
			 | 
		
	
		
			
			| 
				151
			 | 
			
				
			 | 
			
			
				-        """Returns a 2-eliment tuple, each of them is a tuple in form of (start, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				164
			 | 
			
			
				+        """Returns a 2-element tuple, each of them is a tuple in form of (start, 
			 | 
		
	
		
			
			| 
				152
			 | 
			
				165
			 | 
			
			
				         offset)""" 
			 | 
		
	
		
			
			| 
				153
			 | 
			
				
			 | 
			
			
				-        return False 
			 | 
		
	
		
			
			| 
				
			 | 
			
				166
			 | 
			
			
				+        return None 
			 | 
		
	
		
			
			| 
				
			 | 
			
				167
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				168
			 | 
			
			
				+    def parse_hunk_line(self, line): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				169
			 | 
			
			
				+        """Returns a 2-element tuple: (attr, text), where attr is: '-': old, 
			 | 
		
	
		
			
			| 
				
			 | 
			
				170
			 | 
			
			
				+        '+': new, ' ': common""" 
			 | 
		
	
		
			
			| 
				
			 | 
			
				171
			 | 
			
			
				+        return None 
			 | 
		
	
		
			
			| 
				154
			 | 
			
				172
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				155
			 | 
			
				173
			 | 
			
			
				     def is_old(self, line): 
			 | 
		
	
		
			
			| 
				156
			 | 
			
				174
			 | 
			
			
				         return False 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -203,8 +221,9 @@ class Diff(object): 
			 | 
		
	
		
			
			| 
				203
			 | 
			
				221
			 | 
			
			
				             return line.replace('\t', ' '*8).replace('\n', '').replace('\r', '') 
			 | 
		
	
		
			
			| 
				204
			 | 
			
				222
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				205
			 | 
			
				223
			 | 
			
			
				         def _fit_width(markup, width, pad=False): 
			 | 
		
	
		
			
			| 
				206
			 | 
			
				
			 | 
			
			
				-            """str len does not count correctly if left column contains ansi 
			 | 
		
	
		
			
			| 
				207
			 | 
			
				
			 | 
			
			
				-            color code.  Only left side need to set `pad` 
			 | 
		
	
		
			
			| 
				
			 | 
			
				224
			 | 
			
			
				+            """Fit input markup to given width, pad or wrap accordingly, str len 
			 | 
		
	
		
			
			| 
				
			 | 
			
				225
			 | 
			
			
				+            does not count correctly if line contains ansi color code.  Only 
			 | 
		
	
		
			
			| 
				
			 | 
			
				226
			 | 
			
			
				+            left side need to set `pad` 
			 | 
		
	
		
			
			| 
				208
			 | 
			
				227
			 | 
			
			
				             """ 
			 | 
		
	
		
			
			| 
				209
			 | 
			
				228
			 | 
			
			
				             out = [] 
			 | 
		
	
		
			
			| 
				210
			 | 
			
				229
			 | 
			
			
				             count = 0 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -214,6 +233,9 @@ class Diff(object): 
			 | 
		
	
		
			
			| 
				214
			 | 
			
				233
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				215
			 | 
			
				234
			 | 
			
			
				             while markup and count < width: 
			 | 
		
	
		
			
			| 
				216
			 | 
			
				235
			 | 
			
			
				                 if patt.match(markup): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				236
			 | 
			
			
				+                    # Extract the ansi color code seq to target output and 
			 | 
		
	
		
			
			| 
				
			 | 
			
				237
			 | 
			
			
				+                    # remove the seq from input markup, no update on counter  
			 | 
		
	
		
			
			| 
				
			 | 
			
				238
			 | 
			
			
				+                    # 
			 | 
		
	
		
			
			| 
				217
			 | 
			
				239
			 | 
			
			
				                     out.append(patt.sub(r'\1', markup)) 
			 | 
		
	
		
			
			| 
				218
			 | 
			
				240
			 | 
			
			
				                     markup = patt.sub(r'\3', markup) 
			 | 
		
	
		
			
			| 
				219
			 | 
			
				241
			 | 
			
			
				                 else: 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -227,7 +249,7 @@ class Diff(object): 
			 | 
		
	
		
			
			| 
				227
			 | 
			
				249
			 | 
			
			
				                     markup = markup[1:] 
			 | 
		
	
		
			
			| 
				228
			 | 
			
				250
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				229
			 | 
			
				251
			 | 
			
			
				             if count == width and repl.sub('', markup): 
			 | 
		
	
		
			
			| 
				230
			 | 
			
				
			 | 
			
			
				-                # stripped: output fulfil and still have ascii in markup 
			 | 
		
	
		
			
			| 
				
			 | 
			
				252
			 | 
			
			
				+                # Was stripped: output fulfil and still has ascii in markup 
			 | 
		
	
		
			
			| 
				231
			 | 
			
				253
			 | 
			
			
				                 out[-1] = ansi_code('reset') + colorize('>', 'lightmagenta') 
			 | 
		
	
		
			
			| 
				232
			 | 
			
				254
			 | 
			
			
				             elif count < width and pad: 
			 | 
		
	
		
			
			| 
				233
			 | 
			
				255
			 | 
			
			
				                 pad_len = width - count 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -366,6 +388,9 @@ class Udiff(Diff): 
			 | 
		
	
		
			
			| 
				366
			 | 
			
				388
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				367
			 | 
			
				389
			 | 
			
			
				         return (old_addr, new_addr) 
			 | 
		
	
		
			
			| 
				368
			 | 
			
				390
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				391
			 | 
			
			
				+    def parse_hunk_line(self, line): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				392
			 | 
			
			
				+        return (line[0], line[1:]) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				393
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				369
			 | 
			
				394
			 | 
			
			
				     def is_old(self, line): 
			 | 
		
	
		
			
			| 
				370
			 | 
			
				395
			 | 
			
			
				         """Exclude header line from svn log --diff output""" 
			 | 
		
	
		
			
			| 
				371
			 | 
			
				396
			 | 
			
			
				         return line.startswith('-') and not self.is_old_path(line) and \ 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -387,33 +412,33 @@ class PatchStream(object): 
			 | 
		
	
		
			
			| 
				387
			 | 
			
				412
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				388
			 | 
			
				413
			 | 
			
			
				     def __init__(self, diff_hdl): 
			 | 
		
	
		
			
			| 
				389
			 | 
			
				414
			 | 
			
			
				         self._diff_hdl = diff_hdl 
			 | 
		
	
		
			
			| 
				390
			 | 
			
				
			 | 
			
			
				-        self._header_chunk_size = 0 
			 | 
		
	
		
			
			| 
				391
			 | 
			
				
			 | 
			
			
				-        self._header_chunk = [] 
			 | 
		
	
		
			
			| 
				
			 | 
			
				415
			 | 
			
			
				+        self._stream_header_size = 0 
			 | 
		
	
		
			
			| 
				
			 | 
			
				416
			 | 
			
			
				+        self._stream_header = [] 
			 | 
		
	
		
			
			| 
				392
			 | 
			
				417
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				393
			 | 
			
				418
			 | 
			
			
				         # Test whether stream is empty by read 1 line 
			 | 
		
	
		
			
			| 
				394
			 | 
			
				419
			 | 
			
			
				         line = self._diff_hdl.readline() 
			 | 
		
	
		
			
			| 
				395
			 | 
			
				
			 | 
			
			
				-        if line is None: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				420
			 | 
			
			
				+        if not line: 
			 | 
		
	
		
			
			| 
				396
			 | 
			
				421
			 | 
			
			
				             self._is_empty = True 
			 | 
		
	
		
			
			| 
				397
			 | 
			
				422
			 | 
			
			
				         else: 
			 | 
		
	
		
			
			| 
				398
			 | 
			
				
			 | 
			
			
				-            self._header_chunk.append(line) 
			 | 
		
	
		
			
			| 
				399
			 | 
			
				
			 | 
			
			
				-            self._header_chunk_size += 1 
			 | 
		
	
		
			
			| 
				
			 | 
			
				423
			 | 
			
			
				+            self._stream_header.append(line) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				424
			 | 
			
			
				+            self._stream_header_size += 1 
			 | 
		
	
		
			
			| 
				400
			 | 
			
				425
			 | 
			
			
				             self._is_empty = False 
			 | 
		
	
		
			
			| 
				401
			 | 
			
				426
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				402
			 | 
			
				427
			 | 
			
			
				     def is_empty(self): 
			 | 
		
	
		
			
			| 
				403
			 | 
			
				428
			 | 
			
			
				         return self._is_empty 
			 | 
		
	
		
			
			| 
				404
			 | 
			
				429
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				405
			 | 
			
				
			 | 
			
			
				-    def read_header_chunks(self, header_chunk_size): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				430
			 | 
			
			
				+    def read_stream_header(self, stream_header_size): 
			 | 
		
	
		
			
			| 
				406
			 | 
			
				431
			 | 
			
			
				         """Returns a small chunk for patch type detect, suppose to call once""" 
			 | 
		
	
		
			
			| 
				407
			 | 
			
				
			 | 
			
			
				-        for i in range(1, header_chunk_size): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				432
			 | 
			
			
				+        for i in range(1, stream_header_size): 
			 | 
		
	
		
			
			| 
				408
			 | 
			
				433
			 | 
			
			
				             line = self._diff_hdl.readline() 
			 | 
		
	
		
			
			| 
				409
			 | 
			
				
			 | 
			
			
				-            if line is None: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				434
			 | 
			
			
				+            if not line: 
			 | 
		
	
		
			
			| 
				410
			 | 
			
				435
			 | 
			
			
				                 break 
			 | 
		
	
		
			
			| 
				411
			 | 
			
				
			 | 
			
			
				-            self._header_chunk.append(line) 
			 | 
		
	
		
			
			| 
				412
			 | 
			
				
			 | 
			
			
				-            self._header_chunk_size += 1 
			 | 
		
	
		
			
			| 
				413
			 | 
			
				
			 | 
			
			
				-            yield line 
			 | 
		
	
		
			
			| 
				
			 | 
			
				436
			 | 
			
			
				+            self._stream_header.append(line) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				437
			 | 
			
			
				+            self._stream_header_size += 1 
			 | 
		
	
		
			
			| 
				
			 | 
			
				438
			 | 
			
			
				+        return self._stream_header 
			 | 
		
	
		
			
			| 
				414
			 | 
			
				439
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				415
			 | 
			
				440
			 | 
			
			
				     def __iter__(self): 
			 | 
		
	
		
			
			| 
				416
			 | 
			
				
			 | 
			
			
				-        for line in self._header_chunk: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				441
			 | 
			
			
				+        for line in self._stream_header: 
			 | 
		
	
		
			
			| 
				417
			 | 
			
				442
			 | 
			
			
				             yield line 
			 | 
		
	
		
			
			| 
				418
			 | 
			
				443
			 | 
			
			
				         for line in self._diff_hdl: 
			 | 
		
	
		
			
			| 
				419
			 | 
			
				444
			 | 
			
			
				             yield line 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -428,7 +453,7 @@ class DiffParser(object): 
			 | 
		
	
		
			
			| 
				428
			 | 
			
				453
			 | 
			
			
				         self._stream = stream 
			 | 
		
	
		
			
			| 
				429
			 | 
			
				454
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				430
			 | 
			
				455
			 | 
			
			
				         flag = 0 
			 | 
		
	
		
			
			| 
				431
			 | 
			
				
			 | 
			
			
				-        for line in self._stream.read_header_chunks(100): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				456
			 | 
			
			
				+        for line in self._stream.read_stream_header(100): 
			 | 
		
	
		
			
			| 
				432
			 | 
			
				457
			 | 
			
			
				             line = decode(line) 
			 | 
		
	
		
			
			| 
				433
			 | 
			
				458
			 | 
			
			
				             if line.startswith('--- '): 
			 | 
		
	
		
			
			| 
				434
			 | 
			
				459
			 | 
			
			
				                 flag |= 1 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -436,7 +461,7 @@ class DiffParser(object): 
			 | 
		
	
		
			
			| 
				436
			 | 
			
				461
			 | 
			
			
				                 flag |= 2 
			 | 
		
	
		
			
			| 
				437
			 | 
			
				462
			 | 
			
			
				             elif line.startswith('@@ ') or line.startswith('## '): 
			 | 
		
	
		
			
			| 
				438
			 | 
			
				463
			 | 
			
			
				                 flag |= 4 
			 | 
		
	
		
			
			| 
				439
			 | 
			
				
			 | 
			
			
				-            if flag & 7: 
			 | 
		
	
		
			
			| 
				
			 | 
			
				464
			 | 
			
			
				+            if (flag & 7) == 7: 
			 | 
		
	
		
			
			| 
				440
			 | 
			
				465
			 | 
			
			
				                 self._type = 'udiff' 
			 | 
		
	
		
			
			| 
				441
			 | 
			
				466
			 | 
			
			
				                 break 
			 | 
		
	
		
			
			| 
				442
			 | 
			
				467
			 | 
			
			
				         else: 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -481,8 +506,7 @@ class DiffParser(object): 
			 | 
		
	
		
			
			| 
				481
			 | 
			
				506
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				482
			 | 
			
				507
			 | 
			
			
				             elif len(diff._hunks) > 0 and (difflet.is_old(line) or \ 
			 | 
		
	
		
			
			| 
				483
			 | 
			
				508
			 | 
			
			
				                     difflet.is_new(line) or difflet.is_common(line)): 
			 | 
		
	
		
			
			| 
				484
			 | 
			
				
			 | 
			
			
				-                hunk_line = line 
			 | 
		
	
		
			
			| 
				485
			 | 
			
				
			 | 
			
			
				-                diff._hunks[-1].append(hunk_line[0], hunk_line[1:]) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				509
			 | 
			
			
				+                diff._hunks[-1].append(difflet.parse_hunk_line(line)) 
			 | 
		
	
		
			
			| 
				486
			 | 
			
				510
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				487
			 | 
			
				511
			 | 
			
			
				             elif difflet.is_eof(line): 
			 | 
		
	
		
			
			| 
				488
			 | 
			
				512
			 | 
			
			
				                 # ignore 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -557,16 +581,16 @@ def check_command_status(arguments): 
			 | 
		
	
		
			
			| 
				557
			 | 
			
				581
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				558
			 | 
			
				582
			 | 
			
			
				 def revision_control_diff(): 
			 | 
		
	
		
			
			| 
				559
			 | 
			
				583
			 | 
			
			
				     """Return diff from revision control system.""" 
			 | 
		
	
		
			
			| 
				560
			 | 
			
				
			 | 
			
			
				-    for check, diff, _ in REVISION_CONTROL: 
			 | 
		
	
		
			
			| 
				561
			 | 
			
				
			 | 
			
			
				-        if check_command_status(check): 
			 | 
		
	
		
			
			| 
				562
			 | 
			
				
			 | 
			
			
				-            return subprocess.Popen(diff, stdout=subprocess.PIPE).stdout 
			 | 
		
	
		
			
			| 
				
			 | 
			
				584
			 | 
			
			
				+    for _, ops in VCS_INFO.items(): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				585
			 | 
			
			
				+        if check_command_status(ops['probe']): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				586
			 | 
			
			
				+            return subprocess.Popen(ops['diff'], stdout=subprocess.PIPE).stdout 
			 | 
		
	
		
			
			| 
				563
			 | 
			
				587
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				564
			 | 
			
				588
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				565
			 | 
			
				589
			 | 
			
			
				 def revision_control_log(): 
			 | 
		
	
		
			
			| 
				566
			 | 
			
				590
			 | 
			
			
				     """Return log from revision control system.""" 
			 | 
		
	
		
			
			| 
				567
			 | 
			
				
			 | 
			
			
				-    for check, _, log in REVISION_CONTROL: 
			 | 
		
	
		
			
			| 
				568
			 | 
			
				
			 | 
			
			
				-        if check_command_status(check): 
			 | 
		
	
		
			
			| 
				569
			 | 
			
				
			 | 
			
			
				-            return subprocess.Popen(log, stdout=subprocess.PIPE).stdout 
			 | 
		
	
		
			
			| 
				
			 | 
			
				591
			 | 
			
			
				+    for _, ops in VCS_INFO.items(): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				592
			 | 
			
			
				+        if check_command_status(ops['probe']): 
			 | 
		
	
		
			
			| 
				
			 | 
			
				593
			 | 
			
			
				+            return subprocess.Popen(ops['log'], stdout=subprocess.PIPE).stdout 
			 | 
		
	
		
			
			| 
				570
			 | 
			
				594
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				571
			 | 
			
				595
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				572
			 | 
			
				596
			 | 
			
			
				 def decode(line): 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -580,7 +604,7 @@ def decode(line): 
			 | 
		
	
		
			
			| 
				580
			 | 
			
				604
			 | 
			
			
				 def main(): 
			 | 
		
	
		
			
			| 
				581
			 | 
			
				605
			 | 
			
			
				     import optparse 
			 | 
		
	
		
			
			| 
				582
			 | 
			
				606
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				583
			 | 
			
				
			 | 
			
			
				-    supported_vcs = [check[0][0] for check in REVISION_CONTROL] 
			 | 
		
	
		
			
			| 
				
			 | 
			
				607
			 | 
			
			
				+    supported_vcs = sorted(VCS_INFO.keys()) 
			 | 
		
	
		
			
			| 
				584
			 | 
			
				608
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				585
			 | 
			
				609
			 | 
			
			
				     usage = """ 
			 | 
		
	
		
			
			| 
				586
			 | 
			
				610
			 | 
			
			
				   %prog [options] 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -589,14 +613,14 @@ def main(): 
			 | 
		
	
		
			
			| 
				589
			 | 
			
				613
			 | 
			
			
				     parser = optparse.OptionParser(usage=usage, 
			 | 
		
	
		
			
			| 
				590
			 | 
			
				614
			 | 
			
			
				             description=META_INFO['description'], 
			 | 
		
	
		
			
			| 
				591
			 | 
			
				615
			 | 
			
			
				             version='%%prog %s' % META_INFO['version']) 
			 | 
		
	
		
			
			| 
				592
			 | 
			
				
			 | 
			
			
				-    parser.add_option('-c', '--color', default='auto', metavar='WHEN', 
			 | 
		
	
		
			
			| 
				593
			 | 
			
				
			 | 
			
			
				-            help='colorize mode "auto" (default), "always", or "never"') 
			 | 
		
	
		
			
			| 
				594
			 | 
			
				616
			 | 
			
			
				     parser.add_option('-s', '--side-by-side', action='store_true', 
			 | 
		
	
		
			
			| 
				595
			 | 
			
				617
			 | 
			
			
				             help='show in side-by-side mode') 
			 | 
		
	
		
			
			| 
				596
			 | 
			
				618
			 | 
			
			
				     parser.add_option('-w', '--width', type='int', default=80, metavar='N', 
			 | 
		
	
		
			
			| 
				597
			 | 
			
				619
			 | 
			
			
				             help='set text width (side-by-side mode only), default is 80') 
			 | 
		
	
		
			
			| 
				598
			 | 
			
				620
			 | 
			
			
				     parser.add_option('-l', '--log', action='store_true', 
			 | 
		
	
		
			
			| 
				599
			 | 
			
				621
			 | 
			
			
				             help='show diff log from revision control') 
			 | 
		
	
		
			
			| 
				
			 | 
			
				622
			 | 
			
			
				+    parser.add_option('-c', '--color', default='auto', metavar='X', 
			 | 
		
	
		
			
			| 
				
			 | 
			
				623
			 | 
			
			
				+            help='colorize mode "auto" (default), "always", or "never"') 
			 | 
		
	
		
			
			| 
				600
			 | 
			
				624
			 | 
			
			
				     opts, args = parser.parse_args() 
			 | 
		
	
		
			
			| 
				601
			 | 
			
				625
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				602
			 | 
			
				626
			 | 
			
			
				     if opts.log: 
			 |