##// END OF EJS Templates
Updated contrib/vim/patchreview.* to version 0.2.1...
Manpreet Singh -
r10545:b9e4a673 stable
parent child Browse files
Show More
@@ -1,97 +1,120 b''
1 *patchreview.txt* Vim global plugin for doing single or multipatch code reviews
1 *patchreview.txt* Vim global plugin for doing single, multi-patch or diff code reviews
2 Version v0.2.1 (for Vim version 7.0 or higher)
2 3
3 Author: Manpreet Singh (junkblocker-CAT-yahoo-DOG-com)
4 (Replace -CAT- and -DOG- with @ and . first)
5 Copyright (C) 2006 by Manpreet Singh
4 Author: Manpreet Singh < junkblocker@yahoo.com >
5 Copyright (C) 2006-2010 by Manpreet Singh
6 6 License : This file is placed in the public domain.
7 7
8 8 =============================================================================
9 9
10 CONTENTS *patchreview* *patchreview-contents*
10 CONTENTS *patchreview* *diffreview* *patchreview-contents*
11 11
12 12 1. Contents.........................................: |patchreview-contents|
13 13 2. Introduction.....................................: |patchreview-intro|
14 14 3. PatchReview options..............................: |patchreview-options|
15 15 4. PatchReview Usage................................: |patchreview-usage|
16 4.1 PatchReview Usage............................: |:PatchReview|
17 4.2 PatchReview Usage............................: |:PatchReviewCleanup|
16 4.1 DiffReview Usage.............................: |:DiffReview|
17 4.2 PatchReview Usage............................: |:PatchReview|
18 4.3 DiffReviewCleanup Usage......................: |:DiffReviewCleanup|
19 4.4 PatchReviewCleanup Usage.....................: |:PatchReviewCleanup|
18 20
19 21 =============================================================================
20 22
21 23 PatchReview Introduction *patchreview-intro*
22 24
23 The Patch Review plugin allows single or multipatch code review to be done in
24 VIM. VIM provides the |:diffpatch| command to do single file reviews but can
25 not handle patch files containing multiple patches as is common with software
26 development projects. This plugin provides that missing functionality. It also
27 tries to improve on |:diffpatch|'s behaviour of creating the patched files in
25 The Patch Review plugin allows easy single or multipatch code or diff reviews.
26
27 It opens each affected file in the patch or in a workspace diff in a diff view
28 in a separate tab.
29
30 VIM provides the |:diffpatch| and related commands to do single file reviews
31 but can not handle patch files containing multiple patches as is common with
32 software development projects. This plugin provides that missing
33 functionality.
34
35 It also improves on |:diffpatch|'s behaviour of creating the patched files in
28 36 the same directory as original file which can lead to project workspace
29 37 pollution.
30 38
31 39 =============================================================================
32 40
33 41 PatchReview Options *patchreview-options*
34 42
35 g:patchreview_filterdiff : Optional path to filterdiff binary. PatchReview
36 tries to locate filterdiff on system path
37 automatically. If the binary is not on system
38 path, this option tell PatchReview the full path
39 to the binary. This option, if specified,
40 overrides the default filterdiff binary on the
41 path.
43 g:patchreview_tmpdir = {string}
44 Optional path where the plugin can save temporary files. If this is not
45 specified, the plugin tries to use TMP, TEMP and TMPDIR environment
46 variables in succession.
47
48 examples:
49 (On Windows) >
50 let g:patchreview_tmpdir = 'c:\\tmp'
51 <
52 (On *nix systems) >
53 let g:patchreview_tmpdir = '~/tmp'
54 <
55
56 g:patchreview_filterdiff = {string}
57 Optional path to filterdiff binary. PatchReview tries to locate
58 filterdiff on system path automatically. If the binary is not on system
59 path, this option tell PatchReview the full path to the binary. This
60 option, if specified, overrides the default filterdiff binary on the
61 path.
42 62
43 63 examples:
44 64 (On Windows with Cygwin)
45
65 >
46 66 let g:patchreview_filterdiff = 'c:\\cygwin\\bin\\filterdiff.exe'
47
67 <
48 68 (On *nix systems)
49
69 >
50 70 let g:patchreview_filterdiff = '/usr/bin/filterdiff'
51
52 g:patchreview_patch : Optional path to patch binary. PatchReview tries
53 to locate patch on system path automatically. If
54 the binary is not on system path, this option
55 tell PatchReview the full path to the binary.
56 This option, if specified, overrides the default
57 patch binary on the path.
58
59 examples:
60 (On Windows with Cygwin)
61
62 let g:patchreview_patch = 'c:\\cygwin\\bin\\patch.exe'
63
64 (On *nix systems)
65
66 let g:patchreview_patch = '/usr/bin/gpatch'
67
68
69 g:patchreview_tmpdir : Optional path where the plugin can save temporary
70 files. If this is not specified, the plugin tries to
71 use TMP, TEMP and TMPDIR environment variables in
72 succession.
71 <
72 g:patchreview_patch = {string}
73 Optional path to patch binary. PatchReview tries to locate patch on
74 system path automatically. If the binary is not on system path, this
75 option tell PatchReview the full path to the binary. This option, if
76 specified, overrides the default patch binary on the path.
73 77
74 78 examples:
75 (On Windows) let g:patchreview_tmpdir = 'c:\\tmp'
76 (On *nix systems) let g:patchreview_tmpdir = '~/tmp'
79 (On Windows with Cygwin) >
80 let g:patchreview_patch = 'c:\\cygwin\\bin\\patch.exe'
81 <
82 (On *nix systems) >
83 let g:patchreview_patch = '/usr/bin/gpatch'
84 <
77 85
78 86 =============================================================================
79 87
80 88 PatchReview Usage *patchreview-usage*
89 *:DiffReview*
90
91 :DiffReview
92
93 Perform a diff review in the current directory under version control.
94 Currently supports Mercurial (hg), Subversion (svn), CVS, Bazaar (bzr) and
95 Monotone.
96
81 97 *:PatchReview*
82 98
83 99 :PatchReview patchfile_path [optional_source_directory]
84 100
85 101 Perform a patch review in the current directory based on the supplied
86 102 patchfile_path. If optional_source_directory is specified, patchreview is
87 done on that directory. Othewise, the current directory is assumed to be
103 done on that directory. Otherwise, the current directory is assumed to be
88 104 the source directory.
105
106 Only supports context or unified format patches.
107
108 *:DiffReviewCleanup*
89 109 *:PatchReviewCleanup*
90 110
111 :DiffReviewCleanup
91 112 :PatchReviewCleanup
92 113
93 After you are done using the :PatchReview command, you can cleanup the
94 temporary files in the temporary directory using this command.
114 After you are done using the :DiffReview or :PatchReview command, you can
115 cleanup the temporary files in the temporary directory using either of
116 these commands.
95 117
96 =============================================================================
97 vim: ft=help:ts=2:sts=2:sw=2:tw=78:tw=78
118 ------------------------------------------------------------------------------
119
120 vim: ft=help:ts=2:sts=2:sw=2:tw=78:norl:
This diff has been collapsed as it changes many lines, (952 lines changed) Show them Hide them
@@ -1,332 +1,926 b''
1 " Vim global plugin for doing single or multipatch code reviews"{{{
1 " VIM plugin for doing single, multi-patch or diff code reviews {{{
2 " Home: http://www.vim.org/scripts/script.php?script_id=1563
2 3
3 " Version : 0.1 "{{{
4 " Last Modified : Thu 25 May 2006 10:15:11 PM PDT
5 " Author : Manpreet Singh (junkblocker AT yahoo DOT com)
6 " Copyright : 2006 by Manpreet Singh
4 " Version : 0.2.1 "{{{
5 " Author : Manpreet Singh < junkblocker@yahoo.com >
6 " Copyright : 2006-2010 by Manpreet Singh
7 7 " License : This file is placed in the public domain.
8 " No warranties express or implied. Use at your own risk.
8 9 "
9 " History : 0.1 - First released
10 " Changelog :
11 "
12 " 0.2.1 - Minor temp directory autodetection logic and cleanup
13 "
14 " 0.2 - Removed the need for filterdiff by implemeting it in pure vim script
15 " - Added DiffReview command for reverse (changed repository to
16 " pristine state) reviews.
17 " (PatchReview does pristine repository to patch review)
18 " - DiffReview does automatic detection and generation of diffs for
19 " various Source Control systems
20 " - Skip load if VIM 7.0 or higher unavailable
21 "
22 " 0.1 - First released
10 23 "}}}
24
11 25 " Documentation: "{{{
12 26 " ===========================================================================
13 " This plugin allows single or multipatch code reviews to be done in VIM. Vim
14 " has :diffpatch command to do single file reviews but can not handle patch
15 " files containing multiple patches. This plugin provides that missing
16 " functionality and doesn't require the original file to be open.
27 " This plugin allows single or multiple, patch or diff based code reviews to
28 " be easily done in VIM. VIM has :diffpatch command to do single file reviews
29 " but a) can not handle patch files containing multiple patches or b) do
30 " automated diff generation for various version control systems. This plugin
31 " attempts to provide those functionalities. It opens each changed / added or
32 " removed file diff in new tabs.
33 "
34 " Installing:
17 35 "
18 " Installing: "{{{
36 " For a quick start...
37 "
38 " Requirements:
39 "
40 " 1) VIM 7.0 or higher built with +diff option.
19 41 "
20 " For a quick start...
42 " 2) A gnu compatible patch command installed. This is the standard patch
43 " command on Linux, Mac OS X, *BSD, Cygwin or /usr/bin/gpatch on newer
44 " Solaris.
21 45 "
22 " Requirements: "{{{
46 " 3) Optional (but recommended for speed)
23 47 "
24 " 1) (g)vim 7.0 or higher built with +diff option.
25 " 2) patch and patchutils ( http://cyberelk.net/tim/patchutils/ ) installed
26 " for your OS. For windows it is availble from Cygwin (
27 " http://www.cygwin.com ) or GnuWin32 ( http://gnuwin32.sourceforge.net/
28 " ).
29 ""}}}
30 " Install: "{{{
48 " Install patchutils ( http://cyberelk.net/tim/patchutils/ ) for your
49 " OS. For windows it is availble from Cygwin
50 "
51 " http://www.cygwin.com
52 "
53 " or GnuWin32
54 "
55 " http://gnuwin32.sourceforge.net/
56 "
57 " Install:
31 58 "
32 " 1) Extract this in your $VIM/vimfiles or $HOME/.vim directory and restart
33 " vim.
59 " 1) Extract the zip in your $HOME/.vim or $VIM/vimfiles directory and
60 " restart vim. The directory location relevant to your platform can be
61 " seen by running :help add-global-plugin in vim.
34 62 "
35 " 2) Make sure that you have filterdiff from patchutils and patch commands
36 " installed.
63 " 2) Restart vim.
37 64 "
38 " 3) Optinally, specify the locations to filterdiff and patch commands and
39 " location of a temporary directory to use in your .vimrc.
65 " Configuration:
40 66 "
41 " let g:patchreview_filterdiff = '/path/to/filterdiff'
42 " let g:patchreview_patch = '/path/to/patch'
67 " Optionally, specify the locations to these filterdiff and patch commands
68 " and location of a temporary directory to use in your .vimrc.
69 "
70 " let g:patchreview_patch = '/path/to/gnu/patch'
43 71 " let g:patchreview_tmpdir = '/tmp/or/something'
44 72 "
45 " 4) Optionally, generate help tags to use help
73 " " If you are using filterdiff
74 " let g:patchreview_filterdiff = '/path/to/filterdiff'
46 75 "
47 " :helptags ~/.vim/doc
48 " or
49 " :helptags c:\vim\vimfiles\doc
50 ""}}}
51 ""}}}
52 " Usage: "{{{
53 76 "
54 " :PatchReview path_to_submitted_patchfile [optional_source_directory]
55 77 "
56 " after review is done
78 " Usage:
57 79 "
58 " :PatchReviewCleanup
80 " Please see :help patchreview or :help diffreview for details.
59 81 "
60 " See :help patchreview for details after you've created help tags.
61 82 ""}}}
62 "}}}
63 " Code "{{{
64 83
65 " Enabled only during development "{{{
84 " Enabled only during development
66 85 " unlet! g:loaded_patchreview " DEBUG
67 86 " unlet! g:patchreview_tmpdir " DEBUG
87 " unlet! g:patchreview_patch " DEBUG
68 88 " unlet! g:patchreview_filterdiff " DEBUG
69 " unlet! g:patchreview_patch " DEBUG
70 "}}}
89 " let g:patchreview_patch = 'patch' " DEBUG
71 90
72 " load only once "{{{
73 if exists('g:loaded_patchreview')
91 if v:version < 700
92 finish
93 endif
94 if ! has('diff')
95 call confirm('patchreview.vim plugin needs (G)VIM built with +diff support to work.')
96 finish
97 endif
98
99 " load only once
100 if (! exists('g:patchreview_debug') && exists('g:loaded_patchreview')) || &compatible
74 101 finish
75 102 endif
76 let g:loaded_patchreview=1
77 let s:msgbufname = 'Patch Review Messages'
103 let g:loaded_patchreview="0.2.1"
104
105 let s:msgbufname = '-PatchReviewMessages-'
106
107 function! <SID>Debug(str) "{{{
108 if exists('g:patchreview_debug')
109 Pecho 'DEBUG: ' . a:str
110 endif
111 endfunction
112 command! -nargs=+ -complete=expression Debug call s:Debug(<args>)
78 113 "}}}
79 114
80 function! <SID>PR_wipeMsgBuf() "{{{
81 let s:winnum = bufwinnr(s:msgbufname)
82 if s:winnum != -1 " If the window is already open, jump to it
83 let s:cur_winnr = winnr()
84 if winnr() != s:winnum
85 exe s:winnum . 'wincmd w'
115 function! <SID>PR_wipeMsgBuf() "{{{
116 let winnum = bufwinnr(s:msgbufname)
117 if winnum != -1 " If the window is already open, jump to it
118 let cur_winnr = winnr()
119 if winnr() != winnum
120 exe winnum . 'wincmd w'
86 121 exe 'bw'
87 exe s:cur_winnr . 'wincmd w'
122 exe cur_winnr . 'wincmd w'
88 123 endif
89 124 endif
90 125 endfunction
91 126 "}}}
92 127
93 function! <SID>PR_echo(...) "{{{
94 " Usage: PR_echo(msg, [return_to_original_window_flag])
128 function! <SID>Pecho(...) "{{{
129 " Usage: Pecho(msg, [return_to_original_window_flag])
95 130 " default return_to_original_window_flag = 0
96 131 "
97 let s:cur_winnr = winnr()
98 let s:winnum = bufwinnr(s:msgbufname)
99 if s:winnum != -1 " If the window is already open, jump to it
100 if winnr() != s:winnum
101 exe s:winnum . 'wincmd w'
132 let cur_winnr = winnr()
133 let winnum = bufwinnr(s:msgbufname)
134 if winnum != -1 " If the window is already open, jump to it
135 if winnr() != winnum
136 exe winnum . 'wincmd w'
102 137 endif
103 138 else
104 let s:bufnum = bufnr(s:msgbufname)
105 if s:bufnum == -1
106 let s:wcmd = s:msgbufname
139 let bufnum = bufnr(s:msgbufname)
140 if bufnum == -1
141 let wcmd = s:msgbufname
107 142 else
108 let s:wcmd = '+buffer' . s:bufnum
143 let wcmd = '+buffer' . bufnum
109 144 endif
110 exe 'silent! botright 5split ' . s:wcmd
145 exe 'silent! botright 5split ' . wcmd
111 146 endif
112 147 setlocal modifiable
113 148 setlocal buftype=nofile
114 149 setlocal bufhidden=delete
115 150 setlocal noswapfile
116 151 setlocal nowrap
117 152 setlocal nobuflisted
118 153 if a:0 != 0
119 154 silent! $put =a:1
120 155 endif
121 156 exe ':$'
122 157 setlocal nomodifiable
123 158 if a:0 > 1 && a:2
124 exe s:cur_winnr . 'wincmd w'
159 exe cur_winnr . 'wincmd w'
125 160 endif
126 161 endfunction
162
163 command! -nargs=+ -complete=expression Pecho call s:Pecho(<args>)
127 164 "}}}
128 165
129 function! <SID>PR_checkBinary(BinaryName) "{{{
166 function! <SID>PR_checkBinary(BinaryName) "{{{
130 167 " Verify that BinaryName is specified or available
131 168 if ! exists('g:patchreview_' . a:BinaryName)
132 169 if executable(a:BinaryName)
133 170 let g:patchreview_{a:BinaryName} = a:BinaryName
134 171 return 1
135 172 else
136 call s:PR_echo('g:patchreview_' . a:BinaryName . ' is not defined and could not be found on path. Please define it in your .vimrc.')
173 Pecho 'g:patchreview_' . a:BinaryName . ' is not defined and ' . a:BinaryName . ' command could not be found on path.'
174 Pecho 'Please define it in your .vimrc.'
137 175 return 0
138 176 endif
139 177 elseif ! executable(g:patchreview_{a:BinaryName})
140 call s:PR_echo('Specified g:patchreview_' . a:BinaryName . ' [' . g:patchreview_{a.BinaryName} . '] is not executable.')
178 Pecho 'Specified g:patchreview_' . a:BinaryName . ' [' . g:patchreview_{a:BinaryName} . '] is not executable.'
141 179 return 0
142 180 else
143 181 return 1
144 182 endif
145 183 endfunction
146 184 "}}}
147 185
148 function! <SID>PR_GetTempDirLocation(Quiet) "{{{
186 function! <SID>PR_GetTempDirLocation(Quiet) "{{{
149 187 if exists('g:patchreview_tmpdir')
150 188 if ! isdirectory(g:patchreview_tmpdir) || ! filewritable(g:patchreview_tmpdir)
151 189 if ! a:Quiet
152 call s:PR_echo('Temporary directory specified by g:patchreview_tmpdir [' . g:patchreview_tmpdir . '] is not accessible.')
190 Pecho 'Temporary directory specified by g:patchreview_tmpdir [' . g:patchreview_tmpdir . '] is not accessible.'
153 191 return 0
154 192 endif
155 193 endif
156 194 elseif exists("$TMP") && isdirectory($TMP) && filewritable($TMP)
157 195 let g:patchreview_tmpdir = $TMP
158 196 elseif exists("$TEMP") && isdirectory($TEMP) && filewritable($TEMP)
159 197 let g:patchreview_tmpdir = $TEMP
160 198 elseif exists("$TMPDIR") && isdirectory($TMPDIR) && filewritable($TMPDIR)
161 199 let g:patchreview_tmpdir = $TMPDIR
162 200 else
163 if ! a:Quiet
164 call s:PR_echo('Could not figure out a temporary directory to use. Please specify g:patchreview_tmpdir in your .vimrc.')
201 if has("unix")
202 if isdirectory("/tmp")
203 let g:patchreview_tmpdir = "/tmp"
204 elseif isdirectory(expand("~/tmp"))
205 let g:patchreview_tmpdir = expand("~/tmp")
206 endif
207 elseif has("win32")
208 if isdirectory('c:\\tmp')
209 let g:patchreview_tmpdir = 'c:\\tmp'
210 elseif isdirectory('c:\\temp')
211 let g:patchreview_tmpdir = 'c:\\temp'
212 elseif isdirectory('c:\\windows\\temp')
213 let g:patchreview_tmpdir = 'c:\\windows\\temp'
214 elseif isdirectory($USERPROFILE . '\Local Settings\Temp') # NOTE : No \ issue here
215 let g:patchreview_tmpdir = $USERPROFILE . '\Local Settings\Temp'
216 endif
217 endif
218 if !exists('g:patchreview_tmpdir')
219 if ! a:Quiet
220 Pecho 'Could not figure out a temporary directory to use. Please specify g:patchreview_tmpdir in your .vimrc.'
221 endif
165 222 return 0
166 223 endif
167 224 endif
225 let g:patchreview_tmpdir = expand(g:patchreview_tmpdir, ':p')
168 226 let g:patchreview_tmpdir = g:patchreview_tmpdir . '/'
169 227 let g:patchreview_tmpdir = substitute(g:patchreview_tmpdir, '\\', '/', 'g')
170 let g:patchreview_tmpdir = substitute(g:patchreview_tmpdir, '/+$', '/', '')
228 let g:patchreview_tmpdir = substitute(g:patchreview_tmpdir, '/\+$', '/', '')
171 229 if has('win32')
172 230 let g:patchreview_tmpdir = substitute(g:patchreview_tmpdir, '/', '\\', 'g')
173 231 endif
174 232 return 1
175 233 endfunction
176 234 "}}}
177 235
178 function! <SID>PatchReview(...) "{{{
179 " VIM 7+ required"{{{
180 if version < 700
181 call s:PR_echo('This plugin needs VIM 7 or higher')
236 function! <SID>ExtractDiffsNative(...) "{{{
237 " Sets g:patches = {'reason':'', 'patch':[
238 " {
239 " 'filename': filepath
240 " 'type' : '+' | '-' | '!'
241 " 'content' : patch text for this file
242 " },
243 " ...
244 " ]}
245 let g:patches = {'reason' : '', 'patch' : []}
246 " TODO : User pointers into lines list rather then use collect
247 if a:0 == 0
248 let g:patches['reason'] = "ExtractDiffsNative expects at least a patchfile argument"
249 return
250 endif
251 let patchfile = expand(a:1, ':p')
252 if a:0 > 1
253 let patch = a:2
254 endif
255 if ! filereadable(patchfile)
256 let g:patches['reason'] = "File " . patchfile . " is not readable"
182 257 return
183 258 endif
259 unlet! filterdiffcmd
260 let filterdiffcmd = '' . g:patchreview_filterdiff . ' --list -s ' . patchfile
261 let fileslist = split(system(filterdiffcmd), '[\r\n]')
262 for filewithchangetype in fileslist
263 if filewithchangetype !~ '^[!+-] '
264 Pecho '*** Skipping review generation due to unknown change for [' . filewithchangetype . ']'
265 continue
266 endif
267
268 unlet! this_patch
269 let this_patch = {}
270
271 unlet! relpath
272 let relpath = substitute(filewithchangetype, '^. ', '', '')
273
274 let this_patch['filename'] = relpath
275
276 if filewithchangetype =~ '^! '
277 let this_patch['type'] = '!'
278 elseif filewithchangetype =~ '^+ '
279 let this_patch['type'] = '+'
280 elseif filewithchangetype =~ '^- '
281 let this_patch['type'] = '-'
282 endif
283
284 unlet! filterdiffcmd
285 let filterdiffcmd = '' . g:patchreview_filterdiff . ' -i ' . relpath . ' ' . patchfile
286 let this_patch['content'] = split(system(filterdiffcmd), '[\n\r]')
287 let g:patches['patch'] += [this_patch]
288 Debug "Patch collected for " . relpath
289 endfor
290 endfunction
184 291 "}}}
185 292
186 let s:save_shortmess = &shortmess
187 set shortmess+=aW
188 call s:PR_wipeMsgBuf()
189
190 " Check passed arguments "{{{
293 function! <SID>ExtractDiffsPureVim(...) "{{{
294 " Sets g:patches = {'reason':'', 'patch':[
295 " {
296 " 'filename': filepath
297 " 'type' : '+' | '-' | '!'
298 " 'content' : patch text for this file
299 " },
300 " ...
301 " ]}
302 let g:patches = {'reason' : '', 'patch' : []}
303 " TODO : User pointers into lines list rather then use collect
191 304 if a:0 == 0
192 call s:PR_echo('PatchReview command needs at least one argument specifying a patchfile path.')
193 let &shortmess = s:save_shortmess
305 let g:patches['reason'] = "ExtractDiffsPureVim expects at least a patchfile argument"
306 return
307 endif
308 let patchfile = expand(a:1, ':p')
309 if a:0 > 1
310 let patch = a:2
311 endif
312 if ! filereadable(patchfile)
313 let g:patches['reason'] = "File " . patchfile . " is not readable"
194 314 return
195 315 endif
196 if a:0 >= 1 && a:0 <= 2
197 let s:PatchFilePath = expand(a:1, ':p')
198 if ! filereadable(s:PatchFilePath)
199 call s:PR_echo('File [' . s:PatchFilePath . '] is not accessible.')
200 let &shortmess = s:save_shortmess
316 call s:PR_wipeMsgBuf()
317 let collect = []
318 let linum = 0
319 let lines = readfile(patchfile)
320 let linescount = len(lines)
321 State 'START'
322 while linum < linescount
323 let line = lines[linum]
324 let linum += 1
325 if State() == 'START'
326 let mat = matchlist(line, '^--- \([^\t]\+\).*$')
327 if ! empty(mat) && mat[1] != ''
328 State 'MAYBE_UNIFIED_DIFF'
329 let p_first_file = mat[1]
330 let collect = [line]
331 Debug line . State()
332 continue
333 endif
334 let mat = matchlist(line, '^\*\*\* \([^\t]\+\).*$')
335 if ! empty(mat) && mat[1] != ''
336 State 'MAYBE_CONTEXT_DIFF'
337 let p_first_file = mat[1]
338 let collect = [line]
339 Debug line . State()
340 continue
341 endif
342 continue
343 elseif State() == 'MAYBE_CONTEXT_DIFF'
344 let mat = matchlist(line, '^--- \([^\t]\+\).*$')
345 if empty(mat) || mat[1] == ''
346 State 'START'
347 let linum -= 1
348 continue
349 Debug 'Back to square one ' . line()
350 endif
351 let p_second_file = mat[1]
352 if p_first_file == '/dev/null'
353 if p_second_file == '/dev/null'
354 let g:patches['reason'] = "Malformed diff found at line " . linum
355 return
356 endif
357 let p_type = '+'
358 let filepath = p_second_file
359 else
360 if p_second_file == '/dev/null'
361 let p_type = '-'
362 let filepath = p_first_file
363 else
364 let p_type = '!'
365 let filepath = p_first_file
366 endif
367 endif
368 State 'EXPECT_15_STARS'
369 let collect += [line]
370 Debug line . State()
371 elseif State() == 'EXPECT_15_STARS'
372 if line !~ '^*\{15}$'
373 State 'START'
374 let linum -= 1
375 Debug line . State()
376 continue
377 endif
378 State 'EXPECT_CONTEXT_CHUNK_HEADER_1'
379 let collect += [line]
380 Debug line . State()
381 elseif State() == 'EXPECT_CONTEXT_CHUNK_HEADER_1'
382 let mat = matchlist(line, '^\*\*\* \(\d\+,\)\?\(\d\+\) \*\*\*\*$')
383 if empty(mat) || mat[1] == ''
384 State 'START'
385 let linum -= 1
386 Debug line . State()
387 continue
388 endif
389 let collect += [line]
390 State 'SKIP_CONTEXT_STUFF_1'
391 Debug line . State()
392 continue
393 elseif State() == 'SKIP_CONTEXT_STUFF_1'
394 if line !~ '^[ !+].*$'
395 let mat = matchlist(line, '^--- \(\d\+\),\(\d\+\) ----$')
396 if ! empty(mat) && mat[1] != '' && mat[2] != ''
397 let goal_count = mat[2] - mat[1] + 1
398 let c_count = 0
399 State 'READ_CONTEXT_CHUNK'
400 let collect += [line]
401 Debug line . State() . " Goal count set to " . goal_count
402 continue
403 endif
404 State 'START'
405 let linum -= 1
406 Debug line . State()
407 continue
408 endif
409 let collect += [line]
410 continue
411 elseif State() == 'READ_CONTEXT_CHUNK'
412 let c_count += 1
413 if c_count == goal_count
414 let collect += [line]
415 State 'BACKSLASH_OR_CRANGE_EOF'
416 continue
417 else " goal not met yet
418 let mat = matchlist(line, '^\([\\!+ ]\).*$')
419 if empty(mat) || mat[1] == ''
420 let linum -= 1
421 State 'START'
422 Debug line . State()
423 continue
424 endif
425 let collect += [line]
426 continue
427 endif
428 elseif State() == 'BACKSLASH_OR_CRANGE_EOF'
429 if line =~ '^\\ No newline.*$' " XXX: Can we go to another chunk from here??
430 let collect += [line]
431 let this_patch = {}
432 let this_patch['filename'] = filepath
433 let this_patch['type'] = p_type
434 let this_patch['content'] = collect
435 let g:patches['patch'] += [this_patch]
436 Debug "Patch collected for " . filepath
437 State 'START'
438 continue
439 endif
440 if line =~ '^\*\{15}$'
441 let collect += [line]
442 State 'EXPECT_CONTEXT_CHUNK_HEADER_1'
443 Debug line . State()
444 continue
445 endif
446 let this_patch = {}
447 let this_patch['filename'] = filepath
448 let this_patch['type'] = p_type
449 let this_patch['content'] = collect
450 let g:patches['patch'] += [this_patch]
451 let linum -= 1
452 State 'START'
453 Debug "Patch collected for " . filepath
454 Debug line . State()
455 continue
456 elseif State() == 'MAYBE_UNIFIED_DIFF'
457 let mat = matchlist(line, '^+++ \([^\t]\+\).*$')
458 if empty(mat) || mat[1] == ''
459 State 'START'
460 let linum -= 1
461 Debug line . State()
462 continue
463 endif
464 let p_second_file = mat[1]
465 if p_first_file == '/dev/null'
466 if p_second_file == '/dev/null'
467 let g:patches['reason'] = "Malformed diff found at line " . linum
468 return
469 endif
470 let p_type = '+'
471 let filepath = p_second_file
472 else
473 if p_second_file == '/dev/null'
474 let p_type = '-'
475 let filepath = p_first_file
476 else
477 let p_type = '!'
478 let filepath = p_first_file
479 endif
480 endif
481 State 'EXPECT_UNIFIED_RANGE_CHUNK'
482 let collect += [line]
483 Debug line . State()
484 continue
485 elseif State() == 'EXPECT_UNIFIED_RANGE_CHUNK'
486 let mat = matchlist(line, '^@@ -\(\d\+,\)\?\(\d\+\) +\(\d\+,\)\?\(\d\+\) @@$')
487 if ! empty(mat)
488 let old_goal_count = mat[2]
489 let new_goal_count = mat[4]
490 let o_count = 0
491 let n_count = 0
492 Debug "Goal count set to " . old_goal_count . ', ' . new_goal_count
493 State 'READ_UNIFIED_CHUNK'
494 let collect += [line]
495 Debug line . State()
496 continue
497 endif
498 State 'START'
499 Debug line . State()
500 continue
501 elseif State() == 'READ_UNIFIED_CHUNK'
502 if o_count == old_goal_count && n_count == new_goal_count
503 if line =~ '^\\.*$' " XXX: Can we go to another chunk from here??
504 let collect += [line]
505 let this_patch = {}
506 let this_patch['filename'] = filepath
507 let this_patch['type'] = p_type
508 let this_patch['content'] = collect
509 let g:patches['patch'] += [this_patch]
510 Debug "Patch collected for " . filepath
511 State 'START'
512 continue
513 endif
514 let mat = matchlist(line, '^@@ -\(\d\+,\)\?\(\d\+\) +\(\d\+,\)\?\(\d\+\) @@$')
515 if ! empty(mat)
516 let old_goal_count = mat[2]
517 let new_goal_count = mat[4]
518 let o_count = 0
519 let n_count = 0
520 Debug "Goal count set to " . old_goal_count . ', ' . new_goal_count
521 let collect += [line]
522 Debug line . State()
523 continue
524 endif
525 let this_patch = {}
526 let this_patch['filename'] = filepath
527 let this_patch['type'] = p_type
528 let this_patch['content'] = collect
529 let g:patches['patch'] += [this_patch]
530 Debug "Patch collected for " . filepath
531 let linum -= 1
532 State 'START'
533 Debug line . State()
534 continue
535 else " goal not met yet
536 let mat = matchlist(line, '^\([\\+ -]\).*$')
537 if empty(mat) || mat[1] == ''
538 let linum -= 1
539 State 'START'
540 continue
541 endif
542 let chr = mat[1]
543 if chr == '+'
544 let n_count += 1
545 endif
546 if chr == ' '
547 let o_count += 1
548 let n_count += 1
549 endif
550 if chr == '-'
551 let o_count += 1
552 endif
553 let collect += [line]
554 Debug line . State()
555 continue
556 endif
557 else
558 let g:patches['reason'] = "Internal error: Do not use the plugin anymore and if possible please send the diff or patch file you tried it with to Manpreet Singh <junkblocker@yahoo.com>"
201 559 return
202 560 endif
203 if a:0 == 2
204 let s:SrcDirectory = expand(a:2, ':p')
205 if ! isdirectory(s:SrcDirectory)
206 call s:PR_echo('[' . s:SrcDirectory . '] is not a directory')
207 let &shortmess = s:save_shortmess
208 return
209 endif
210 try
211 exe 'cd ' . s:SrcDirectory
212 catch /^.*E344.*/
213 call s:PR_echo('Could not change to directory [' . s:SrcDirectory . ']')
214 let &shortmess = s:save_shortmess
215 return
216 endtry
561 endwhile
562 "Pecho State()
563 if (State() == 'READ_CONTEXT_CHUNK' && c_count == goal_count) || (State() == 'READ_UNIFIED_CHUNK' && n_count == new_goal_count && o_count == old_goal_count)
564 let this_patch = {}
565 let this_patch['filename'] = filepath
566 let this_patch['type'] = p_type
567 let this_patch['content'] = collect
568 let g:patches['patch'] += [this_patch]
569 Debug "Patch collected for " . filepath
570 endif
571 return
572 endfunction
573 "}}}
574
575 function! State(...) " For easy manipulation of diff extraction state "{{{
576 if a:0 != 0
577 let s:STATE = a:1
578 else
579 if ! exists('s:STATE')
580 let s:STATE = 'START'
217 581 endif
218 else
219 call s:PR_echo('PatchReview command needs at most two arguments: patchfile path and optional source directory path.')
220 let &shortmess = s:save_shortmess
221 return
582 return s:STATE
222 583 endif
584 endfunction
585 com! -nargs=+ -complete=expression State call State(<args>)
223 586 "}}}
224 587
225 " Verify that filterdiff and patch are specified or available "{{{
226 if ! s:PR_checkBinary('filterdiff') || ! s:PR_checkBinary('patch')
227 let &shortmess = s:save_shortmess
588 function! <SID>PatchReview(...) "{{{
589 let s:save_shortmess = &shortmess
590 let s:save_aw = &autowrite
591 let s:save_awa = &autowriteall
592 set shortmess=aW
593 call s:PR_wipeMsgBuf()
594 let s:reviewmode = 'patch'
595 call s:_GenericReview(a:000)
596 let &autowriteall = s:save_awa
597 let &autowrite = s:save_aw
598 let &shortmess = s:save_shortmess
599 endfunction
600 "}}}
601
602 function! <SID>_GenericReview(argslist) "{{{
603 " diff mode:
604 " arg1 = patchfile
605 " arg2 = strip count
606 " patch mode:
607 " arg1 = patchfile
608 " arg2 = strip count
609 " arg3 = directory
610
611 " VIM 7+ required
612 if version < 700
613 Pecho 'This plugin needs VIM 7 or higher'
228 614 return
229 615 endif
230 616
231 let s:retval = s:PR_GetTempDirLocation(0)
232 if ! s:retval
233 let &shortmess = s:save_shortmess
617 " +diff required
618 if ! has('diff')
619 Pecho 'This plugin needs VIM built with +diff feature.'
620 return
621 endif
622
623
624 if s:reviewmode == 'diff'
625 let patch_R_option = ' -t -R '
626 elseif s:reviewmode == 'patch'
627 let patch_R_option = ''
628 else
629 Pecho 'Fatal internal error in patchreview.vim plugin'
630 return
631 endif
632
633 " Check passed arguments
634 if len(a:argslist) == 0
635 Pecho 'PatchReview command needs at least one argument specifying a patchfile path.'
234 636 return
235 637 endif
236 "}}}
638 let StripCount = 0
639 if len(a:argslist) >= 1 && ((s:reviewmode == 'patch' && len(a:argslist) <= 3) || (s:reviewmode == 'diff' && len(a:argslist) == 2))
640 let PatchFilePath = expand(a:argslist[0], ':p')
641 if ! filereadable(PatchFilePath)
642 Pecho 'File [' . PatchFilePath . '] is not accessible.'
643 return
644 endif
645 if len(a:argslist) >= 2 && s:reviewmode == 'patch'
646 let s:SrcDirectory = expand(a:argslist[1], ':p')
647 if ! isdirectory(s:SrcDirectory)
648 Pecho '[' . s:SrcDirectory . '] is not a directory'
649 return
650 endif
651 try
652 " Command line has already escaped the path
653 exe 'cd ' . s:SrcDirectory
654 catch /^.*E344.*/
655 Pecho 'Could not change to directory [' . s:SrcDirectory . ']'
656 return
657 endtry
658 endif
659 if s:reviewmode == 'diff'
660 " passed in by default
661 let StripCount = eval(a:argslist[1])
662 elseif s:reviewmode == 'patch'
663 let StripCount = 1
664 " optional strip count
665 if len(a:argslist) == 3
666 let StripCount = eval(a:argslist[2])
667 endif
668 endif
669 else
670 if s:reviewmode == 'patch'
671 Pecho 'PatchReview command needs at most three arguments: patchfile path, optional source directory path and optional strip count.'
672 elseif s:reviewmode == 'diff'
673 Pecho 'DiffReview command accepts no arguments.'
674 endif
675 return
676 endif
237 677
238 " Requirements met, now execute "{{{
239 let s:PatchFilePath = fnamemodify(s:PatchFilePath, ':p')
240 call s:PR_echo('Patch file : ' . s:PatchFilePath)
241 call s:PR_echo('Source directory: ' . getcwd())
242 call s:PR_echo('------------------')
243 let s:theFilterDiffCommand = '' . g:patchreview_filterdiff . ' --list -s ' . s:PatchFilePath
244 let s:theFilesString = system(s:theFilterDiffCommand)
245 let s:theFilesList = split(s:theFilesString, '[\r\n]')
246 for s:filewithchangetype in s:theFilesList
247 if s:filewithchangetype !~ '^[!+-] '
248 call s:PR_echo('*** Skipping review generation due to understood change for [' . s:filewithchangetype . ']', 1)
678 " Verify that patch command and temporary directory are available or specified
679 if ! s:PR_checkBinary('patch')
680 return
681 endif
682
683 let retval = s:PR_GetTempDirLocation(0)
684 if ! retval
685 return
686 endif
687
688 " Requirements met, now execute
689 let PatchFilePath = fnamemodify(PatchFilePath, ':p')
690 if s:reviewmode == 'patch'
691 Pecho 'Patch file : ' . PatchFilePath
692 endif
693 Pecho 'Source directory: ' . getcwd()
694 Pecho '------------------'
695 if s:PR_checkBinary('filterdiff')
696 Debug "Using filterdiff"
697 call s:ExtractDiffsNative(PatchFilePath)
698 else
699 Debug "Using own diff extraction (slower)"
700 call s:ExtractDiffsPureVim(PatchFilePath)
701 endif
702 for patch in g:patches['patch']
703 if patch.type !~ '^[!+-]$'
704 Pecho '*** Skipping review generation due to unknown change [' . patch.type . ']', 1
249 705 continue
250 706 endif
251 unlet! s:RelativeFilePath
252 let s:RelativeFilePath = substitute(s:filewithchangetype, '^. ', '', '')
253 let s:RelativeFilePath = substitute(s:RelativeFilePath, '^[a-z][^\\\/]*[\\\/]' , '' , '')
254 if s:filewithchangetype =~ '^! '
255 let s:msgtype = 'Modification : '
256 elseif s:filewithchangetype =~ '^+ '
257 let s:msgtype = 'Addition : '
258 elseif s:filewithchangetype =~ '^- '
259 let s:msgtype = 'Deletion : '
707 unlet! relpath
708 let relpath = patch.filename
709 " XXX: svn diff and hg diff produce different kind of outputs, one requires
710 " XXX: stripping but the other doesn't. We need to take care of that
711 let stripmore = StripCount
712 let StrippedRelativeFilePath = relpath
713 while stripmore > 0
714 " strip one
715 let StrippedRelativeFilePath = substitute(StrippedRelativeFilePath, '^[^\\\/]\+[^\\\/]*[\\\/]' , '' , '')
716 let stripmore -= 1
717 endwhile
718 if patch.type == '!'
719 if s:reviewmode == 'patch'
720 let msgtype = 'Patch modifies file: '
721 elseif s:reviewmode == 'diff'
722 let msgtype = 'File has changes: '
723 endif
724 elseif patch.type == '+'
725 if s:reviewmode == 'patch'
726 let msgtype = 'Patch adds file : '
727 elseif s:reviewmode == 'diff'
728 let msgtype = 'New file : '
729 endif
730 elseif patch.type == '-'
731 if s:reviewmode == 'patch'
732 let msgtype = 'Patch removes file : '
733 elseif s:reviewmode == 'diff'
734 let msgtype = 'Removed file : '
735 endif
260 736 endif
261 let s:bufnum = bufnr(s:RelativeFilePath)
262 if buflisted(s:bufnum) && getbufvar(s:bufnum, '&mod')
263 call s:PR_echo('Old buffer for file [' . s:RelativeFilePath . '] exists in modified state. Skipping review.', 1)
737 let bufnum = bufnr(relpath)
738 if buflisted(bufnum) && getbufvar(bufnum, '&mod')
739 Pecho 'Old buffer for file [' . relpath . '] exists in modified state. Skipping review.', 1
264 740 continue
265 741 endif
266 let s:tmpname = substitute(s:RelativeFilePath, '/', '_', 'g')
267 let s:tmpname = substitute(s:tmpname, '\\', '_', 'g')
268 let s:tmpname = g:patchreview_tmpdir . 'PatchReview.' . s:tmpname . '.' . strftime('%Y%m%d%H%M%S')
742 let tmpname = substitute(relpath, '/', '_', 'g')
743 let tmpname = substitute(tmpname, '\\', '_', 'g')
744 let tmpname = g:patchreview_tmpdir . 'PatchReview.' . tmpname . '.' . strftime('%Y%m%d%H%M%S')
269 745 if has('win32')
270 let s:tmpname = substitute(s:tmpname, '/', '\\', 'g')
746 let tmpname = substitute(tmpname, '/', '\\', 'g')
271 747 endif
272 if ! exists('s:patchreview_tmpfiles')
273 let s:patchreview_tmpfiles = []
274 endif
275 let s:patchreview_tmpfiles = s:patchreview_tmpfiles + [s:tmpname]
276 748
277 let s:filterdiffcmd = '!' . g:patchreview_filterdiff . ' -i ' . s:RelativeFilePath . ' ' . s:PatchFilePath . ' > ' . s:tmpname
278 silent! exe s:filterdiffcmd
279 if s:filewithchangetype =~ '^+ '
280 if has('win32')
281 let s:inputfile = 'nul'
282 else
283 let s:inputfile = '/dev/null'
284 endif
749 " write patch for patch.filename into tmpname
750 call writefile(patch.content, tmpname)
751 if patch.type == '+' && s:reviewmode == 'patch'
752 let inputfile = ''
753 let patchcmd = '!' . g:patchreview_patch . patch_R_option . ' -o "' . tmpname . '.file" "' . inputfile . '" < "' . tmpname . '"'
754 elseif patch.type == '+' && s:reviewmode == 'diff'
755 let inputfile = ''
756 unlet! patchcmd
285 757 else
286 let s:inputfile = expand(s:RelativeFilePath, ':p')
758 let inputfile = expand(StrippedRelativeFilePath, ':p')
759 let patchcmd = '!' . g:patchreview_patch . patch_R_option . ' -o "' . tmpname . '.file" "' . inputfile . '" < "' . tmpname . '"'
287 760 endif
288 silent exe '!' . g:patchreview_patch . ' -o ' . s:tmpname . '.file ' . s:inputfile . ' < ' . s:tmpname
761 if exists('patchcmd')
762 let v:errmsg = ''
763 Debug patchcmd
764 silent exe patchcmd
765 if v:errmsg != '' || v:shell_error
766 Pecho 'ERROR: Could not execute patch command.'
767 Pecho 'ERROR: ' . patchcmd
768 Pecho 'ERROR: ' . v:errmsg
769 Pecho 'ERROR: Diff skipped.'
770 continue
771 endif
772 endif
289 773 let s:origtabpagenr = tabpagenr()
290 silent! exe 'tabedit ' . s:RelativeFilePath
291 silent! exe 'vert diffsplit ' . s:tmpname . '.file'
292 if filereadable(s:tmpname . '.file.rej')
293 silent! exe 'topleft 5split ' . s:tmpname . '.file.rej'
294 call s:PR_echo(s:msgtype . '*** REJECTED *** ' . s:RelativeFilePath, 1)
774 silent! exe 'tabedit ' . StrippedRelativeFilePath
775 if exists('patchcmd')
776 silent! exe 'vert diffsplit ' . tmpname . '.file'
295 777 else
296 call s:PR_echo(s:msgtype . ' ' . s:RelativeFilePath, 1)
778 silent! exe 'vnew'
779 endif
780 if filereadable(tmpname . '.file.rej')
781 silent! exe 'topleft 5split ' . tmpname . '.file.rej'
782 Pecho msgtype . '*** REJECTED *** ' . relpath, 1
783 else
784 Pecho msgtype . ' ' . relpath, 1
297 785 endif
298 786 silent! exe 'tabn ' . s:origtabpagenr
299 787 endfor
300 call s:PR_echo('-----')
301 call s:PR_echo('Done.')
302 let &shortmess = s:save_shortmess
303 "}}}
788 Pecho '-----'
789 Pecho 'Done.'
790
304 791 endfunction
305 792 "}}}
306 793
307 function! <SID>PatchReviewCleanup() "{{{
308 let s:retval = s:PR_GetTempDirLocation(1)
309 if s:retval && exists('g:patchreview_tmpdir') && isdirectory(g:patchreview_tmpdir) && filewritable(g:patchreview_tmpdir)
310 let s:zefilestr = globpath(g:patchreview_tmpdir, 'PatchReview.*')
311 let s:theFilesList = split(s:zefilestr, '\m[\r\n]\+')
312 for s:thefile in s:theFilesList
313 call delete(s:thefile)
794 function! <SID>PatchReviewCleanup() "{{{
795 let retval = s:PR_GetTempDirLocation(1)
796 if retval && exists('g:patchreview_tmpdir') && isdirectory(g:patchreview_tmpdir) && filewritable(g:patchreview_tmpdir)
797 let zefilestr = globpath(g:patchreview_tmpdir, 'PatchReview.*')
798 let fileslist = split(zefilestr, '\m[\r\n]\+')
799 for thefile in fileslist
800 call delete(thefile)
314 801 endfor
315 802 endif
316 803 endfunction
317 804 "}}}
318 805
319 " Commands "{{{
806 function! <SID>DiffReview(...) "{{{
807 let s:save_shortmess = &shortmess
808 set shortmess=aW
809 call s:PR_wipeMsgBuf()
810
811 let vcsdict = {
812 \'Mercurial' : {'dir' : '.hg', 'binary' : 'hg', 'diffargs' : 'diff' , 'strip' : 1},
813 \'Bazaar-NG' : {'dir' : '.bzr', 'binary' : 'bzr', 'diffargs' : 'diff' , 'strip' : 0},
814 \'monotone' : {'dir' : '_MTN', 'binary' : 'mtn', 'diffargs' : 'diff --unified', 'strip' : 0},
815 \'Subversion' : {'dir' : '.svn', 'binary' : 'svn', 'diffargs' : 'diff' , 'strip' : 0},
816 \'cvs' : {'dir' : 'CVS', 'binary' : 'cvs', 'diffargs' : '-q diff -u' , 'strip' : 0},
817 \}
818
819 unlet! s:theDiffCmd
820 unlet! l:vcs
821 if ! exists('g:patchreview_diffcmd')
822 for key in keys(vcsdict)
823 if isdirectory(vcsdict[key]['dir'])
824 if ! s:PR_checkBinary(vcsdict[key]['binary'])
825 Pecho 'Current directory looks like a ' . vcsdict[key] . ' repository but ' . vcsdist[key]['binary'] . ' command was not found on path.'
826 let &shortmess = s:save_shortmess
827 return
828 else
829 let s:theDiffCmd = vcsdict[key]['binary'] . ' ' . vcsdict[key]['diffargs']
830 let strip = vcsdict[key]['strip']
831
832 Pecho 'Using [' . s:theDiffCmd . '] to generate diffs for this ' . key . ' review.'
833 let &shortmess = s:save_shortmess
834 let l:vcs = vcsdict[key]['binary']
835 break
836 endif
837 else
838 continue
839 endif
840 endfor
841 else
842 let s:theDiffCmd = g:patchreview_diffcmd
843 let strip = 0
844 endif
845 if ! exists('s:theDiffCmd')
846 Pecho 'Please define g:patchreview_diffcmd and make sure you are in a VCS controlled top directory.'
847 let &shortmess = s:save_shortmess
848 return
849 endif
850
851 let retval = s:PR_GetTempDirLocation(0)
852 if ! retval
853 Pecho 'DiffReview aborted.'
854 let &shortmess = s:save_shortmess
855 return
856 endif
857 let outfile = g:patchreview_tmpdir . 'PatchReview.diff.' . strftime('%Y%m%d%H%M%S')
858 let cmd = '!' . s:theDiffCmd . ' > "' . outfile . '"'
859 let v:errmsg = ''
860 silent exe cmd
861 if v:errmsg == '' && exists('l:vcs') && l:vcs == 'cvs' && v:shell_error == 1
862 " Ignoring CVS non-error
863 elseif v:errmsg != '' || v:shell_error
864 Pecho 'Could not execute [' . s:theDiffCmd . ']'
865 Pecho v:errmsg
866 Pecho 'Diff review aborted.'
867 let &shortmess = s:save_shortmess
868 return
869 endif
870 let s:reviewmode = 'diff'
871 call s:_GenericReview([outfile, strip])
872 let &shortmess = s:save_shortmess
873 endfunction
874 "}}}
875
876 " End user commands "{{{
320 877 "============================================================================
321 878 " :PatchReview
322 879 command! -nargs=* -complete=file PatchReview call s:PatchReview (<f-args>)
323 880
881 " :DiffReview
882 command! -nargs=0 DiffReview call s:DiffReview()
324 883
325 884 " :PatchReviewCleanup
326 885 command! -nargs=0 PatchReviewCleanup call s:PatchReviewCleanup ()
327 "}}}
886 command! -nargs=0 DiffReviewCleanup call s:PatchReviewCleanup ()
328 887 "}}}
329 888
330 " vim: textwidth=78 nowrap tabstop=2 shiftwidth=2 softtabstop=2 expandtab
331 " vim: filetype=vim encoding=latin1 fileformat=unix foldlevel=0 foldmethod=marker
889 " Development "{{{
890 if exists('g:patchreview_debug')
891 " Tests
892 function! <SID>PRExtractTestNative(...)
893 "let patchfiles = glob(expand(a:1) . '/?*')
894 "for fname in split(patchfiles)
895 call s:PR_wipeMsgBuf()
896 let fname = a:1
897 call s:ExtractDiffsNative(fname)
898 for patch in g:patches['patch']
899 for line in patch.content
900 Pecho line
901 endfor
902 endfor
903 "endfor
904 endfunction
905
906 function! <SID>PRExtractTestVim(...)
907 "let patchfiles = glob(expand(a:1) . '/?*')
908 "for fname in split(patchfiles)
909 call s:PR_wipeMsgBuf()
910 let fname = a:1
911 call s:ExtractDiffsPureVim(fname)
912 for patch in g:patches['patch']
913 for line in patch.content
914 Pecho line
915 endfor
916 endfor
917 "endfor
918 endfunction
919
920 command! -nargs=+ -complete=file PRTestVim call s:PRExtractTestVim(<f-args>)
921 command! -nargs=+ -complete=file PRTestNative call s:PRExtractTestNative(<f-args>)
922 endif
332 923 "}}}
924
925 " modeline
926 " vim: set et fdl=0 fdm=marker fenc=latin ff=unix ft=vim sw=2 sts=0 ts=2 textwidth=78 nowrap :
General Comments 0
You need to be logged in to leave comments. Login now