Clipboard plugin.
[profile.git] / .vim / plugin / vcsgit.vim
1 " vim600: set foldmethod=marker:
2 "
3 " git extension for VCSCommand.
4 "
5 " Version:       VCS development
6 " Maintainer:    Bob Hiestand <bob.hiestand@gmail.com>
7 " License:
8 " Copyright (c) 2008 Bob Hiestand
9 "
10 " Permission is hereby granted, free of charge, to any person obtaining a copy
11 " of this software and associated documentation files (the "Software"), to
12 " deal in the Software without restriction, including without limitation the
13 " rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14 " sell copies of the Software, and to permit persons to whom the Software is
15 " furnished to do so, subject to the following conditions:
16 "
17 " The above copyright notice and this permission notice shall be included in
18 " all copies or substantial portions of the Software.
19 "
20 " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 " IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 " FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 " AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 " LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 " FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 " IN THE SOFTWARE.
27 "
28 " Section: Documentation {{{1
29 "
30 " Options documentation: {{{2
31 "
32 " VCSCommandGitExec
33 "   This variable specifies the git executable.  If not set, it defaults to
34 "   'git' executed from the user's executable path.
35 "
36 " VCSCommandGitDiffOpt
37 "   This variable, if set, determines the default options passed to the
38 "   VCSDiff command.  If any options (starting with '-') are passed to the
39 "   command, this variable is not used.
40
41 " Section: Plugin header {{{1
42
43 if exists('VCSCommandDisableAll')
44         finish
45 endif
46
47 if v:version < 700
48         "echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None
49         finish
50 endif
51
52 runtime plugin/vcscommand.vim
53
54 if !executable(VCSCommandGetOption('VCSCommandGitExec', 'git'))
55         " git is not installed
56         finish
57 endif
58
59 let s:save_cpo=&cpo
60 set cpo&vim
61
62 " Section: Variable initialization {{{1
63
64 let s:gitFunctions = {}
65
66 " Section: Utility functions {{{1
67
68 " Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2
69 " Wrapper to VCSCommandDoCommand to add the name of the git executable to the
70 " command argument.
71 function! s:DoCommand(cmd, cmdName, statusText, options)
72         if VCSCommandGetVCSType(expand('%')) == 'git'
73                 let fullCmd = VCSCommandGetOption('VCSCommandGitExec', 'git',) . ' ' . a:cmd
74                 return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
75         else
76                 throw 'git VCSCommand plugin called on non-git item.'
77         endif
78 endfunction
79
80 " Section: VCS function implementations {{{1
81
82 " Function: s:gitFunctions.Identify(buffer) {{{2
83 " This function only returns an inexact match due to the detection method used
84 " by git, which simply traverses the directory structure upward.
85 function! s:gitFunctions.Identify(buffer)
86         let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer)))
87         try
88                 call system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' rev-parse --is-inside-work-tree')
89                 if(v:shell_error)
90                         return 0
91                 else
92                         return g:VCSCOMMAND_IDENTIFY_INEXACT
93                 endif
94         finally
95                 call VCSCommandChdir(oldCwd)
96         endtry
97 endfunction
98
99 " Function: s:gitFunctions.Add(argList) {{{2
100 function! s:gitFunctions.Add(argList)
101         return s:DoCommand(join(['add'] + ['-v'] + a:argList, ' '), 'add', join(a:argList, ' '), {})
102 endfunction
103
104 " Function: s:gitFunctions.Annotate(argList) {{{2
105 function! s:gitFunctions.Annotate(argList)
106         if len(a:argList) == 0
107                 if &filetype == 'gitAnnotate'
108                         " Perform annotation of the version indicated by the current line.
109                         let options = matchstr(getline('.'),'^\x\+')
110                 else
111                         let options = ''
112                 endif
113         elseif len(a:argList) == 1 && a:argList[0] !~ '^-'
114                 let options = a:argList[0]
115         else
116                 let options = join(a:argList, ' ')
117         endif
118
119         let resultBuffer = s:DoCommand('blame ' . options . ' -- ', 'annotate', options, {})
120         if resultBuffer > 0
121                 normal 1G
122                 set filetype=gitAnnotate
123         endif
124         return resultBuffer
125 endfunction
126
127 " Function: s:gitFunctions.Commit(argList) {{{2
128 function! s:gitFunctions.Commit(argList)
129         let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {})
130         if resultBuffer == 0
131                 echomsg 'No commit needed.'
132         endif
133         return resultBuffer
134 endfunction
135
136 " Function: s:gitFunctions.Delete() {{{2
137 " All options are passed through.
138 function! s:gitFunctions.Delete(argList)
139         let options = a:argList
140         let caption = join(a:argList, ' ')
141         return s:DoCommand(join(['rm'] + options, ' '), 'delete', caption, {})
142 endfunction
143
144 " Function: s:gitFunctions.Diff(argList) {{{2
145 " Pass-through call to git-diff.  If no options (starting with '-') are found,
146 " then the options in the 'VCSCommandGitDiffOpt' variable are added.
147 function! s:gitFunctions.Diff(argList)
148         let gitDiffOpt = VCSCommandGetOption('VCSCommandGitDiffOpt', '')
149         if gitDiffOpt == ''
150                 let diffOptions = []
151         else
152                 let diffOptions = [gitDiffOpt]
153                 for arg in a:argList
154                         if arg =~ '^-'
155                                 let diffOptions = []
156                                 break
157                         endif
158                 endfor
159         endif
160
161         let resultBuffer = s:DoCommand(join(['diff'] + diffOptions + a:argList), 'diff', join(a:argList), {})
162         if resultBuffer > 0
163                 set filetype=diff
164         else
165                 echomsg 'No differences found'
166         endif
167         return resultBuffer
168 endfunction
169
170 " Function: s:gitFunctions.GetBufferInfo() {{{2
171 " Provides version control details for the current file.  Current version
172 " number and current repository version number are required to be returned by
173 " the vcscommand plugin.  This CVS extension adds branch name to the return
174 " list as well.
175 " Returns: List of results:  [revision, repository, branch]
176
177 function! s:gitFunctions.GetBufferInfo()
178         let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname('%')))
179         try
180                 let branch = substitute(system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' symbolic-ref -q HEAD'), '\n$', '', '')
181                 if v:shell_error
182                         let branch = 'DETACHED'
183                 else
184                         let branch = substitute(branch, '^refs/heads/', '', '')
185                 endif
186
187                 let info = [branch]
188
189                 for method in split(VCSCommandGetOption('VCSCommandGitDescribeArgList', (',tags,all,always')), ',', 1)
190                         if method != ''
191                                 let method = ' --' . method
192                         endif
193                         let tag = substitute(system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' describe' . method), '\n$', '', '')
194                         if !v:shell_error
195                                 call add(info, tag)
196                                 break
197                         endif
198                 endfor
199
200                 return info
201         finally
202                 call VCSCommandChdir(oldCwd)
203         endtry
204 endfunction
205
206 " Function: s:gitFunctions.Log() {{{2
207 function! s:gitFunctions.Log(argList)
208         let resultBuffer=s:DoCommand(join(['log'] + a:argList), 'log', join(a:argList, ' '), {})
209         if resultBuffer > 0
210                 set filetype=gitlog
211         endif
212         return resultBuffer
213 endfunction
214
215 " Function: s:gitFunctions.Revert(argList) {{{2
216 function! s:gitFunctions.Revert(argList)
217         return s:DoCommand('checkout', 'revert', '', {})
218 endfunction
219
220 " Function: s:gitFunctions.Review(argList) {{{2
221 function! s:gitFunctions.Review(argList)
222         if len(a:argList) == 0
223                 let revision = 'HEAD'
224         else
225                 let revision = a:argList[0]
226         endif
227
228         let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(VCSCommandGetOriginalBuffer('%'))))
229         try
230                 let prefix = system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' rev-parse --show-prefix')
231         finally
232                 call VCSCommandChdir(oldCwd)
233         endtry
234
235         let prefix = substitute(prefix, '\n$', '', '')
236         let blob = '"' . revision . ':' . prefix . '<VCSCOMMANDFILE>"'
237         let resultBuffer = s:DoCommand('show ' . blob, 'review', revision, {})
238         if resultBuffer > 0
239                 let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype')
240         endif
241         return resultBuffer
242 endfunction
243
244 " Function: s:gitFunctions.Status(argList) {{{2
245 function! s:gitFunctions.Status(argList)
246         return s:DoCommand(join(['status'] + a:argList), 'status', join(a:argList), {'allowNonZeroExit': 1})
247 endfunction
248
249 " Function: s:gitFunctions.Update(argList) {{{2
250 function! s:gitFunctions.Update(argList)
251         throw "This command is not implemented for git because file-by-file update doesn't make much sense in that context.  If you have an idea for what it should do, please let me know."
252 endfunction
253
254
255 " Section: Plugin Registration {{{1
256 call VCSCommandRegisterModule('git', expand('<sfile>'), s:gitFunctions, [])
257
258 let &cpo = s:save_cpo