diff --git a/autoload/gitmessenger/blame.vim b/autoload/gitmessenger/blame.vim index d42e7bc..423ee6c 100644 --- a/autoload/gitmessenger/blame.vim +++ b/autoload/gitmessenger/blame.vim @@ -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) @@ -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; @@ -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 diff --git a/autoload/gitmessenger/git.vim b/autoload/gitmessenger/git.vim index b79ad9f..6cc465e 100644 --- a/autoload/gitmessenger/git.vim +++ b/autoload/gitmessenger/git.vim @@ -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 . ';') @@ -22,21 +22,21 @@ 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: @@ -44,20 +44,16 @@ endfunction " 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 = {} @@ -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), @@ -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), @@ -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 diff --git a/test/all.vimspec b/test/all.vimspec index 426e9c2..b4fcad8 100644 --- a/test/all.vimspec +++ b/test/all.vimspec @@ -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' @@ -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 @@ -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})} @@ -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})}