1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 23:50:05 +08:00
SpaceVim/bundle/gina.vim/autoload/gina/core/treeish.vim

90 lines
2.8 KiB
VimL
Raw Normal View History

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