Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions autoload/gitmessenger/blame.vim
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ function! s:blame__after_blame(git) dict abort
endfunction

function! s:blame__spawn_git(args, callback) dict abort
let git = gitmessenger#git#new(g:git_messenger_git_command, self.git_root)
let git = gitmessenger#git#new(g:git_messenger_git_command, self.gitdir, self.worktree)
let CB = a:callback
if type(CB) == v:t_string
let CB = funcref(CB, [], self)
Expand All @@ -465,7 +465,8 @@ let s:blame.start = funcref('s:blame__start')
" interface Blame {
" state: BlameHistory;
" line: number;
" git_root: string;
" gitdir: string;
" worktree: string;
" blame_file: string;
" prev_commit?: string;
" oldest_commit?: string;
Expand All @@ -490,10 +491,12 @@ function! gitmessenger#blame#new(file, line, opts) abort
let b.opts = a:opts

let dir = fnamemodify(file, ':p:h')
let b.git_root = gitmessenger#git#root_dir(dir)
let gitdir = gitmessenger#git#gitdir(dir)
let b.gitdir = gitdir !=# '' ? gitdir : $GIT_DIR
let b.worktree = $GIT_WORK_TREE !=# '' ? fnamemodify($GIT_WORK_TREE, ':p') : fnamemodify(gitdir, ':h')

" Validations
if b.git_root ==# ''
if b.gitdir ==# ''
call b.error("git-messenger: Directory '" . dir . "' is not inside a Git repository")
return v:null
endif
Expand Down
35 changes: 16 additions & 19 deletions autoload/gitmessenger/git.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
let s:SEP = has('win32') ? '\' : '/'

function! s:find_dotgit(from) abort
function! s:find_gitdir(from) abort
let dir = finddir('.git', a:from . ';')
let file = findfile('.git', a:from . ';')

Expand All @@ -22,42 +22,38 @@ function! s:find_dotgit(from) abort
" chosen.
" When `dir` or `file` is empty, the other is chosen so we don't need to
" care about empty string here.
let dotgit = len(dir) > len(file) ? dir : file
let gitdir = len(dir) > len(file) ? dir : file

" Inside .git directory is outside repository
" This check must be done before chopping last path separator otherwise it
" matches to directory like /path/to/.github/ (#70)
if stridx(a:from, dotgit) == 0
if stridx(a:from, gitdir) == 0
return ''
endif

if dotgit[-1:] ==# s:SEP
if gitdir[-1:] ==# s:SEP
" [:-2] chops last path separator (/path/to/.git/ => /path/to/.git)
let dotgit = dotgit[:-2]
let gitdir = gitdir[:-2]
endif

return dotgit
return gitdir
endfunction

" Params:
" path: string
" base path to find .git in ancestor directories
" Returns:
" string
" empty string means root directory was not found
function! gitmessenger#git#root_dir(from) abort
" empty string means git dir was not found
function! gitmessenger#git#gitdir(from) abort
let from = fnameescape(fnamemodify(a:from, ':p'))
if from[-1:] ==# s:SEP
" [:-2] chops last path separator
let from = from[:-2]
endif
let dotgit = s:find_dotgit(from)
if dotgit ==# ''
return ''
endif
let gitdir = s:find_gitdir(from)

" /path/to/.git => /path/to
return fnamemodify(dotgit, ':h')
return gitdir
endfunction

let s:git = {}
Expand Down Expand Up @@ -124,12 +120,12 @@ endif
" Returns:
" Job ID of the spawned process
function! s:git__spawn(args, on_exit) dict abort
let cmdline = [self.cmd, '-C', self.dir] + a:args
let cmdline = [self.cmd, '--git-dir', self.gitdir, '--work-tree', self.worktree] + a:args
if has('nvim')
let self.stdout = ['']
let self.stderr = ['']
let job_id = jobstart(cmdline, {
\ 'cwd': self.dir,
\ 'cwd': self.worktree,
\ 'on_stdout' : funcref('s:on_output_nvim', [], self),
\ 'on_stderr' : funcref('s:on_output_nvim', [], self),
\ 'on_exit' : funcref('s:on_exit_nvim', [], self),
Expand All @@ -143,7 +139,7 @@ function! s:git__spawn(args, on_exit) dict abort
let self.stdout = []
let self.stderr = []
let job_id = job_start(cmdline, {
\ 'cwd': self.dir,
\ 'cwd': self.worktree,
\ 'out_cb' : funcref('s:on_output_vim', ['stdout'], self),
\ 'err_cb' : funcref('s:on_output_vim', ['stderr'], self),
\ 'exit_cb' : funcref('s:on_exit_vim', [], self),
Expand All @@ -166,9 +162,10 @@ let s:git.spawn = funcref('s:git__spawn')
" Directory path to run Git
" Returns:
" Git object
function! gitmessenger#git#new(cmd, dir) abort
function! gitmessenger#git#new(cmd, gitdir, worktree) abort
let g = deepcopy(s:git)
let g.cmd = a:cmd
let g.dir = a:dir
let g.gitdir = a:gitdir
let g.worktree = a:worktree
return g
endfunction
16 changes: 8 additions & 8 deletions test/all.vimspec
Original file line number Diff line number Diff line change
Expand Up @@ -1290,7 +1290,7 @@ Describe git-messenger.vim
End
End

Describe gitmessenger#git#root_dir()
Describe gitmessenger#git#gitdir()
Before all
let root_dir = './my git root with space'
let file = 'file.txt'
Expand All @@ -1314,12 +1314,12 @@ Describe git-messenger.vim
" call fnamemodify here the same way
" gitmessenger#blame#new() does to get our absolute path
let file = './my git root with space/file.txt'
let expected_root_dir = fnamemodify(file, ':p:h')
let actual_root_dir = gitmessenger#git#root_dir(file)
let expected_gitdir = fnamemodify(file, ':p:h') .. '/.git'
let actual_gitdir = gitmessenger#git#gitdir(file)

" Failure will return the repo root instead of our created
" ad-hoc root directory
Assert Equal(actual_root_dir, expected_root_dir)
Assert Equal(actual_gitdir, expected_gitdir)
End
End

Expand Down Expand Up @@ -1441,8 +1441,8 @@ Describe git-messenger.vim
End

Describe gitmessenger#git#new
It runs Git command at specified directory using -C
let git = gitmessenger#git#new('echo', '.')
It runs Git command at specified directory using --git-dir and --work-tree
let git = gitmessenger#git#new('echo', '.', '.')
let state = {}
let OnExit = {g -> extend(state, {'exit': g.exit_status})}

Expand All @@ -1451,11 +1451,11 @@ Describe git-messenger.vim

Assert True(len(git.stdout) > 0, string(git.stdout))
let stdout = git.stdout[0]
Assert True(stridx(stdout, '-C .') >= 0, string(stdout))
Assert True(stridx(stdout, '--git-dir . --work-tree .') >= 0, string(stdout))
End

It trims trailing \r (#75)
let git = gitmessenger#git#new('echo', '.')
let git = gitmessenger#git#new('echo', '.', '.')
let state = {}
let OnExit = {g -> extend(state, {'exit': g.exit_status})}

Expand Down
Loading