mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 23:50:05 +08:00
90 lines
2.8 KiB
VimL
90 lines
2.8 KiB
VimL
|
let s:Path = vital#gina#import('System.Filepath')
|
||
|
let s:Git = vital#gina#import('Git')
|
||
|
|
||
|
|
||
|
function! gina#core#treeish#parse(treeish) abort
|
||
|
" Ref: https://git-scm.com/docs/gitrevisions
|
||
|
if a:treeish =~# '^:/' || a:treeish =~# '^[^:]*^{/' || a:treeish !~# ':'
|
||
|
return [a:treeish, v:null]
|
||
|
endif
|
||
|
let m = matchlist(a:treeish, '^\(:[0-3]\|[^:]*\)\%(:\(.*\)\)\?$')
|
||
|
return [m[1], m[2]]
|
||
|
endfunction
|
||
|
|
||
|
function! gina#core#treeish#build(rev, path) abort
|
||
|
let rev = a:rev is# v:null ? ':0' : a:rev
|
||
|
if a:path is# v:null
|
||
|
return rev
|
||
|
endif
|
||
|
return printf('%s:%s', rev, s:Path.unixpath(a:path))
|
||
|
endfunction
|
||
|
|
||
|
function! gina#core#treeish#split(rev) abort
|
||
|
if a:rev =~# '^.\{-}\.\.\..*$'
|
||
|
let [lhs, rhs] = matchlist(a:rev, '^\(.\{-}\)\.\.\.\(.*\)$')[1 : 2]
|
||
|
let lhs = empty(lhs) ? 'HEAD' : lhs
|
||
|
let rhs = empty(rhs) ? 'HEAD' : rhs
|
||
|
return [lhs . '...' . rhs, rhs]
|
||
|
elseif a:rev =~# '^.\{-}\.\..*$'
|
||
|
let [lhs, rhs] = matchlist(a:rev, '^\(.\{-}\)\.\.\(.*\)$')[1 : 2]
|
||
|
let lhs = empty(lhs) ? 'HEAD' : lhs
|
||
|
let rhs = empty(rhs) ? 'HEAD' : rhs
|
||
|
return [lhs, rhs]
|
||
|
else
|
||
|
return [a:rev, '']
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! gina#core#treeish#sha1(git, rev) abort
|
||
|
let ref = s:Git.ref(a:git, a:rev)
|
||
|
if !empty(ref)
|
||
|
return ref.hash
|
||
|
endif
|
||
|
" Fallback to rev-parse (e.g. HEAD@{2.days.ago})
|
||
|
let result = gina#process#call_or_fail(a:git, ['rev-parse', a:rev])
|
||
|
return get(result.stdout, 0, '')
|
||
|
endfunction
|
||
|
|
||
|
function! gina#core#treeish#resolve(git, rev, ...) abort
|
||
|
let aggressive = a:0 ? a:1 : 0
|
||
|
if a:rev =~# '^.\{-}\.\.\..*$'
|
||
|
let [lhs, rhs] = matchlist(a:rev, '^\(.\{-}\)\.\.\.\(.*\)$')[1 : 2]
|
||
|
let lhs = empty(lhs) ? 'HEAD' : lhs
|
||
|
let rhs = empty(rhs) ? 'HEAD' : rhs
|
||
|
return s:find_common_ancestor(a:git, lhs, rhs)
|
||
|
elseif a:rev =~# '^.\{-}\.\..*$'
|
||
|
let [lhs, _] = matchlist(a:rev, '^\(.\{-}\)\.\.\(.*\)$')[1 : 2]
|
||
|
let lhs = empty(lhs) ? 'HEAD' : lhs
|
||
|
if aggressive
|
||
|
let ref = s:Git.ref(a:git, lhs)
|
||
|
return get(ref, 'name', lhs)
|
||
|
else
|
||
|
return lhs
|
||
|
endif
|
||
|
elseif aggressive
|
||
|
let ref = s:Git.ref(a:git, a:rev)
|
||
|
return get(ref, 'name', a:rev)
|
||
|
else
|
||
|
return a:rev
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! gina#core#treeish#validate(git, rev, path, ...) abort
|
||
|
let treeish = gina#core#treeish#build(a:rev, a:path)
|
||
|
let result = gina#process#call(a:git, ['rev-parse', treeish])
|
||
|
if result.status
|
||
|
throw gina#core#revelator#warning(a:0 ? a:1 : join(result.stderr, "\n"))
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
|
||
|
" Private --------------------------------------------------------------------
|
||
|
function! s:find_common_ancestor(git, rev1, rev2) abort
|
||
|
let lhs = empty(a:rev1) ? 'HEAD' : a:rev1
|
||
|
let rhs = empty(a:rev2) ? 'HEAD' : a:rev2
|
||
|
let result = gina#process#call_or_fail(a:git, [
|
||
|
\ 'merge-base', lhs, rhs
|
||
|
\])
|
||
|
return get(result.stdout, 0, '')
|
||
|
endfunction
|