这也是实际工作中遇到的问题,所以还是分类到了oceabase分类里面。
遇到的情况是这样的,有可能同时做多个任务的修改,或者说上一个任务的修改并未提交(尚未ship不能提交),但是下一个已经修改了,这样的话,post-review的时候是需要管理post列表的,而不能把所有的修改一起post。之前应该写过一篇文章说一个post-review插件的实现,但是实际上颇为不便,最好的办法是直接在vim里面操作一个修改列表。这里我们首先通过如下方式生成修改列表。
alias sta='st|grep ^A '
alias stm='st|grep ^M '
alias std='st|grep ^D '
alias po='echo "#!/bin/sh" >post-review.sh && echo "post-review \\" >>post-review.sh && sta >> post-review.sh ; std >>post-review.sh; stm >> post-review.sh ; vi post-review.sh'
之后可以得到类似如下所示的post-review.sh,当然这个是不能直接运行的。
#!/bin/sh
post-review \
M tests/rootserver/root_table/iterator/test_ob_server_tablet_iter.cpp
M tests/rootserver/root_table/iterator/test_ob_root_replica_iter.cpp
M tests/rootserver/root_table/iterator/test_ob_server_replica_iter.cpp
M tests/rootserver/root_table/iterator/test_iterator_base.h
M tests/rootserver/root_table/iterator/Makefile.am
M tests/rootserver/root_table/iterator/test_ob_root_table_iter.cpp
M tests/rootserver/root_table/iterator/run.sh
M tests/rootserver/root_table/iterator/test_ob_alive_root_table_iter.cpp
我们面临两个问题:
- 每行的格式都略有差别,比如前面有A/M/D标记,后面没有续行符号\,没有空格什么的。
- 需要能够针对每一行或者多行进行svn操作(svn diff/revert 应该是最常见的操作)
这里我们通过vim脚本实现如下的功能:
svn.vim 实现如下
function! StripSVN() range
"Step through each line in the range...
for linenum in range(a:firstline, a:lastline)
"Replace loose ampersands (as in DeAmperfy())...
let curr_line = getline(linenum)
let replacement = substitute(curr_line,'^\(A\|M\|D\)','','g')
call setline(linenum, replacement." \\")
endfor
call cursor(linenum)
"Report what was done...
if a:lastline > a:firstline
echo "Strip Svn" (a:lastline - a:firstline + 1) "lines"
endif
endfunction
function! SVNCommand(cmd, prompt, combine) range
if a:prompt
let sure = input("Are you sure? (y/n) ")
if sure != 'y'
return
endif
endif
let cmd = '!svn '.a:cmd
for linenum in range(a:firstline, a:lastline)
"Replace loose ampersands (as in DeAmperfy())...
let curr_line = getline(linenum)
let replacement = substitute(curr_line,'^\(A\|M\)','','g')
let replacement = Trim(Trim(replacement,'\\'),' ')
if a:combine
let cmd = cmd.' '.replacement.' '
else
let cmd = '!svn ' . a:cmd. ' ' . replacement
execute cmd
"echo cmd
endif
endfor
if a:combine
execute cmd
"echo cmd
endif
endfunction
第一个函数处理每行的格式,第二个函数读取每行的内容,生成命令并执行,prompt=1 的时候会提示并让用户确认, combine=1 的时候所有行会拼成一条执行,否则每行执行一次。
然后在vimrc中添加:
noremap <leader>sp :call StripSVN()<CR>
noremap <leader>sf :call SVNCommand("diff", 0 ,1)<cr>
noremap <leader>sr :call SVNCommand("revert", 1 ,0)<cr>dd
noremap <leader>sl :call SVNCommand("log", 0 ,0)<cr>
noremap <leader>sa :call SVNCommand("add", 0 ,1)<cr>
noremap <leader>sb :call SVNCommand("blame", 0 ,1)<cr>
noremap <leader>sd :call SVNCommand("delete", 1 ,0)<cr>dd
这样实现了两种操作,n状态下在当前行执行操作,v状态下在选中的所有行执行操作。
其实偶然发现我好像没说怎么用,大致流程是这样的:
- po(alias),生成修改列表
- 在每个行,或者选中多个行执行svn命令(
sf, sr什么的),查看diff啊,回滚啊,查看log啊,查看blame啊 - 提交前选中所有行执行
sp, 去掉行首的A/M/D标记,在行尾加续行符 - 执行post-review.sh提交
参考文献:
[1] SVN 命令参考(svn command reference), http://riaoo.com/subpages/svn_cmd_reference.html
[2] 使用脚本编写 Vim 编辑器, http://www.ibm.com/developerworks/cn/linux/l-vim-script-2/
PREVIOUS关于svn commit fail的问题