Distinguish between uses of Git dir

We use the Git dir for a few purposes:

* Direct filesystem access.
* Passing to Git as --git-dir=.
* Embedding in fugitive:// URLs.
* Referring to the repository without otherwise using it.

As a start to teasing these apart, introduce s:GitDir() to handle the
first 2 cases, s:DirUrlPrefix() for the 3rd case, and keep using s:Dir()
as a generic reference.
This commit is contained in:
Tim Pope
2021-08-22 00:59:39 -04:00
parent 7c0a7727c1
commit 5d1a276b45

View File

@@ -396,7 +396,7 @@ function! s:UserCommandList(...) abort
let flags = get(a:1, 'flags', flags)
let dir = a:1.git_dir
elseif a:0
let dir = a:1
let dir = s:GitDir(a:1)
else
let dir = ''
endif
@@ -465,6 +465,14 @@ function! s:Dir(...) abort
return a:0 ? FugitiveGitDir(a:1) : FugitiveGitDir()
endfunction
function! s:GitDir(...) abort
return a:0 ? FugitiveGitDir(a:1) : FugitiveGitDir()
endfunction
function! s:DirUrlPrefix(...) abort
return 'fugitive://' . call('s:GitDir', a:000) . '//'
endfunction
function! s:Tree(...) abort
return a:0 ? FugitiveWorkTree(a:1) : FugitiveWorkTree()
endfunction
@@ -596,7 +604,7 @@ function! fugitive#PrepareDirEnvGitFlagsArgs(...) abort
call s:PrepareEnv(autoenv, dir)
endif
call s:PreparePathArgs(cmd, dir, !exists('explicit_pathspec_option'))
return [dir, env, extend(autoenv, env), git, cmd[0 : -arg_count-1], arg_count ? cmd[-arg_count : -1] : []]
return [s:GitDir(dir), env, extend(autoenv, env), git, cmd[0 : -arg_count-1], arg_count ? cmd[-arg_count : -1] : []]
endfunction
function! s:BuildEnvPrefix(env) abort
@@ -875,10 +883,10 @@ function! fugitive#Head(...) abort
let ftime = getftime(file)
if ftime == -1
return ''
elseif ftime != get(s:head_cache, dir, [-1])[0]
let s:head_cache[dir] = [ftime, readfile(file)[0]]
elseif ftime != get(s:head_cache, file, [-1])[0]
let s:head_cache[file] = [ftime, readfile(file)[0]]
endif
let head = s:head_cache[dir][1]
let head = s:head_cache[file][1]
if head =~# '^ref: '
return substitute(head, '\C^ref: \%(refs/\%(heads/\|remotes/\|tags/\)\=\)\=', '', '')
elseif head =~# '^\x\{40,\}$'
@@ -945,7 +953,7 @@ function! fugitive#Config(...) abort
let dict = s:config[dir_key][1]
else
let dict = copy(s:config_prototype)
let dict.git_dir = dir
let dict.git_dir = s:GitDir(dir)
let [lines, message, exec_error] = s:NullError([dir, 'config', '--list', '-z', '--'])
if exec_error
return {}
@@ -1171,7 +1179,7 @@ function! fugitive#RemoteUrl(...) abort
let url = remove(args, 0)
endif
if url ==# '.git'
let url = FugitiveGitDir(config)
let url = s:GitDir(config)
elseif url !~# ':\|^/\|^\.\.\=/'
let url = FugitiveConfigGet('remote.' . url . '.url', config)
endif
@@ -1278,7 +1286,7 @@ let s:repo_prototype = {}
let s:repos = {}
function! fugitive#repo(...) abort
let dir = a:0 ? s:Dir(a:1) : (len(s:Dir()) ? s:Dir() : FugitiveExtractGitDir(expand('%:p')))
let dir = a:0 ? s:GitDir(a:1) : (len(s:GitDir()) ? s:GitDir() : FugitiveExtractGitDir(expand('%:p')))
if dir !=# ''
if has_key(s:repos, dir)
let repo = get(s:repos, dir)
@@ -1369,7 +1377,7 @@ function! s:DirCommitFile(path) abort
if empty(vals)
return ['', '', '']
endif
return vals[1:3]
return [s:Dir(vals[1])] + vals[2:3]
endfunction
function! s:DirRev(url) abort
@@ -1378,8 +1386,8 @@ function! s:DirRev(url) abort
endfunction
let s:merge_heads = ['MERGE_HEAD', 'REBASE_HEAD', 'CHERRY_PICK_HEAD', 'REVERT_HEAD']
function! s:MergeHead(...) abort
let dir = fugitive#Find('.git/', a:0 ? a:1 : s:Dir())
function! s:MergeHead(dir) abort
let dir = fugitive#Find('.git/', a:dir)
for head in s:merge_heads
if filereadable(dir . head)
return head
@@ -1389,7 +1397,7 @@ function! s:MergeHead(...) abort
endfunction
function! s:Owner(path, ...) abort
let dir = a:0 ? a:1 : s:Dir()
let dir = a:0 ? s:Dir(a:1) : s:Dir()
if empty(dir)
return ''
endif
@@ -1446,7 +1454,7 @@ function! fugitive#Path(url, ...) abort
if empty(a:url)
return ''
endif
let dir = a:0 > 1 ? a:2 : s:Dir()
let dir = a:0 > 1 ? s:Dir(a:2) : s:Dir()
let tree = s:Tree(dir)
if !a:0
return fugitive#Real(a:url)
@@ -1510,7 +1518,7 @@ function! fugitive#Find(object, ...) abort
elseif rev =~# '^\.\.\=\%(/\|$\)'
return FugitiveVimPath(simplify(getcwd() . '/' . a:object))
endif
let dir = call('FugitiveGitDir', a:000)
let dir = call('s:GitDir', a:000)
if empty(dir)
let file = matchstr(a:object, '^\%(:\d:\|[^:]*:\)\zs\%(\.\.\=$\|\.\.\=/.*\|/.*\|\w:/.*\)')
let dir = FugitiveExtractGitDir(file)
@@ -1519,7 +1527,8 @@ function! fugitive#Find(object, ...) abort
endif
endif
let tree = s:Tree(dir)
let base = len(tree) ? tree : 'fugitive://' . dir . '//0'
let urlprefix = s:DirUrlPrefix(dir)
let base = len(tree) ? tree : urlprefix . '0'
if rev ==# '.git'
let f = len(tree) && len(getftype(tree . '/.git')) ? tree . '/.git' : dir
elseif rev =~# '^\.git/'
@@ -1551,7 +1560,7 @@ function! fugitive#Find(object, ...) abort
elseif rev =~# '^:\%([0-3]:\)\=\.\.\=\%(/\|$\)\|^:[0-3]:\%(/\|\a\+:\)'
let f = rev =~# '^:\%([0-3]:\)\=\.' ? simplify(getcwd() . '/' . matchstr(rev, '\..*')) : rev[3:-1]
if s:cpath(base . '/', (f . '/')[0 : len(base)])
let f = 'fugitive://' . dir . '//' . +matchstr(rev, '^:\zs\d\ze:') . '/' . strpart(f, len(base) + 1)
let f = urlprefix . +matchstr(rev, '^:\zs\d\ze:') . '/' . strpart(f, len(base) + 1)
else
let altdir = FugitiveExtractGitDir(f)
if len(altdir) && !s:cpath(dir, altdir)
@@ -1559,7 +1568,7 @@ function! fugitive#Find(object, ...) abort
endif
endif
elseif rev =~# '^:[0-3]:'
let f = 'fugitive://' . dir . '//' . rev[1] . '/' . rev[3:-1]
let f = urlprefix . rev[1] . '/' . rev[3:-1]
elseif rev ==# ':'
let fdir = dir . '/'
let f = fdir . 'index'
@@ -1579,7 +1588,7 @@ function! fugitive#Find(object, ...) abort
let f = base . '/' . f
endif
elseif rev =~# '^:/\@!'
let f = 'fugitive://' . dir . '//0/' . rev[1:-1]
let f = urlprefix . '0/' . rev[1:-1]
else
if !exists('f')
let commit = matchstr(rev, '^\%([^:.-]\|\.\.[^/:]\)[^:]*\|^:.*')
@@ -1608,7 +1617,7 @@ function! fugitive#Find(object, ...) abort
endif
endif
if len(commit)
let f = 'fugitive://' . dir . '//' . commit . file
let f = urlprefix . commit . file
else
let f = base . '/' . substitute(rev, '^:/:\=\|^[^:]\+:', '', '')
endif
@@ -1623,7 +1632,7 @@ function! s:Generate(object, ...) abort
if !empty(f)
return f
elseif a:object ==# ':/'
return len(dir) ? FugitiveVimPath('fugitive://' . dir . '//0') : '.'
return len(dir) ? FugitiveVimPath(s:DirUrlPrefix(dir) . '0') : '.'
endif
let file = matchstr(a:object, '^\%(:\d:\|[^:]*:\)\zs.*')
return fnamemodify(FugitiveVimPath(len(file) ? file : a:object), ':p')
@@ -1639,7 +1648,7 @@ function! s:DotRelative(path, ...) abort
endfunction
function! fugitive#Object(...) abort
let dir = a:0 > 1 ? a:2 : s:Dir()
let dir = a:0 > 1 ? s:Dir(a:2) : s:Dir()
let [fdir, rev] = s:DirRev(a:0 ? a:1 : @%)
if s:cpath(dir) !=# s:cpath(fdir)
let rev = ''
@@ -2045,7 +2054,7 @@ function! fugitive#glob(url, ...) abort
endif
call map(files, 'v:val[0]')
call filter(files, 'v:val =~# pattern')
let prepend = 'fugitive://' . dir . '//' . substitute(commit, '^:', '', '') . '/'
let prepend = s:DirUrlPrefix(dir) . substitute(commit, '^:', '', '') . '/'
call sort(files)
call map(files, 'FugitiveVimPath(prepend . v:val . append)')
call extend(results, files)
@@ -2133,7 +2142,7 @@ function! fugitive#CompletePath(base, ...) abort
endif
if base =~# '^\.git/' && len(dir)
let pattern = s:gsub(base[5:-1], '/', '*&').'*'
let fdir = fugitive#Find(dir . '/')
let fdir = fugitive#Find('.git/', dir)
let matches = s:GlobComplete(fdir, pattern)
let cdir = fugitive#Find('.git/refs', dir)[0 : -5]
if len(cdir) && s:cpath(fdir) !=# s:cpath(cdir)
@@ -2586,7 +2595,7 @@ function! fugitive#BufReadStatus() abort
if &bufhidden ==# ''
setlocal bufhidden=delete
endif
let b:dispatch = '-dir=' . s:fnameescape(len(s:Tree()) ? s:Tree() : s:Dir()) . ' ' . s:GitShellCmd() . ' fetch --all'
let b:dispatch = '-dir=' . s:fnameescape(len(s:Tree()) ? s:Tree() : s:GitDir()) . ' ' . s:GitShellCmd() . ' fetch --all'
call fugitive#MapJumps()
call s:Map('n', '-', ":<C-U>execute <SID>Do('Toggle',0)<CR>", '<silent>')
call s:Map('x', '-', ":<C-U>execute <SID>Do('Toggle',1)<CR>", '<silent>')
@@ -2719,7 +2728,7 @@ function! fugitive#BufReadCmd(...) abort
if empty(dir)
return 'echo "Invalid Fugitive URL"'
endif
let b:git_dir = dir
let b:git_dir = s:GitDir(dir)
if rev =~# '^:\d$'
let b:fugitive_type = 'stage'
else
@@ -3327,8 +3336,9 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
if no_pager
call add(flags, '--no-pager')
endif
let options = {'git': s:UserCommandList(), 'git_dir': s:GitDir(dir), 'flags': flags}
if empty(args) && pager is# -1
let cmd = s:StatusCommand(a:line1, a:line2, a:range, a:line2, a:bang, a:mods, '', '', [])
let cmd = s:StatusCommand(a:line1, a:line2, a:range, a:line2, a:bang, a:mods, '', '', [], options)
return (empty(cmd) ? 'exe' : cmd) . after
endif
let alias = FugitiveConfigGet('alias.' . get(args, 0, ''), config)
@@ -3338,8 +3348,6 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
call extend(args, split(alias, '\s\+'), 'keep')
endif
let name = substitute(get(args, 0, ''), '\%(^\|-\)\(\l\)', '\u\1', 'g')
let git = s:UserCommandList()
let options = {'git': git, 'dir': dir, 'git_dir': dir, 'flags': flags}
if pager is# -1 && name =~# '^\a\+$' && exists('*s:' . name . 'Subcommand') && get(args, 1, '') !=# '--help'
try
let overrides = s:{name}Subcommand(a:line1, a:line2, a:range, a:bang, a:mods, extend({'subcommand': args[0], 'subcommand_args': args[1:-1]}, options))
@@ -3378,7 +3386,7 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
\ (s:HasOpt(args, ['add', 'checkout', 'commit', 'stage', 'stash', 'reset'], '-p', '--patch') ||
\ s:HasOpt(args, ['add', 'clean', 'stage'], '-i', '--interactive')) && pager is# 0
let mods = substitute(s:Mods(a:mods), '\<tab\>', '-tab', 'g')
let assign = len(dir) ? '|let b:git_dir = ' . string(dir) : ''
let assign = len(dir) ? '|let b:git_dir = ' . string(options.git_dir) : ''
let argv = s:UserCommandList(options) + args
let term_opts = len(env) ? {'env': env} : {}
if has('nvim')
@@ -3393,11 +3401,11 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
endif
endif
let state = {
\ 'git': git,
\ 'git': options.git,
\ 'flags': flags,
\ 'args': args,
\ 'dir': dir,
\ 'git_dir': dir,
\ 'dir': options.git_dir,
\ 'git_dir': options.git_dir,
\ 'cwd': s:UserCommandCwd(dir),
\ 'filetype': 'git',
\ 'mods': s:Mods(a:mods),
@@ -3458,7 +3466,7 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
let tmp.echo = ''
endif
let args = s:disable_colors + flags + ['-c', 'advice.waitingForEditor=false'] + args
let argv = s:UserCommandList({'git': git, 'git_dir': dir}) + args
let argv = s:UserCommandList({'git': options.git, 'git_dir': options.git_dir}) + args
let [argv, jobopts] = s:JobOpts(argv, env)
call fugitive#Autowrite()
call writefile([], state.file, 'b')
@@ -3626,7 +3634,7 @@ function! s:CompletableSubcommands(dir) abort
endfunction
function! fugitive#Complete(lead, ...) abort
let dir = a:0 == 1 ? a:1 : a:0 >= 3 ? a:3 : s:Dir()
let dir = a:0 == 1 ? a:1 : a:0 >= 3 ? s:Dir(a:3) : s:Dir()
let root = a:0 >= 4 ? a:4 : s:Tree(s:Dir())
let pre = a:0 > 1 ? strpart(a:1, 0, a:2) : ''
let subcmd = matchstr(pre, '\u\w*[! ] *\zs[[:alnum:]-]\+\ze ')
@@ -3670,7 +3678,7 @@ endfunction
" Section: :Gstatus
function! s:StatusCommand(line1, line2, range, count, bang, mods, reg, arg, args, ...) abort
let dir = a:0 ? a:1 : s:Dir()
let dir = a:0 ? s:Dir(a:1) : s:Dir()
exe s:DirCheck(dir)
try
let mods = s:Mods(a:mods, &splitbelow ? 'botright' : 'topleft')
@@ -4831,7 +4839,7 @@ endfunction
" Section: :Git commit, :Git revert
function! s:CommitInteractive(line1, line2, range, bang, mods, options, patch) abort
let status = s:StatusCommand(a:line1, a:line2, a:range, a:line2, a:bang, a:mods, '', '', [], a:options.git_dir)
let status = s:StatusCommand(a:line1, a:line2, a:range, a:line2, a:bang, a:mods, '', '', [], a:options)
let status = len(status) ? status . '|' : ''
if a:patch
return status . 'if search("^Unstaged")|exe "normal >"|exe "+"|endif'
@@ -5073,7 +5081,7 @@ function! s:MergetoolSubcommand(line1, line2, range, bang, mods, options) abort
endfunction
function! s:DifftoolSubcommand(line1, line2, range, bang, mods, options) abort
let dir = a:options.git_dir
let dir = s:Dir(a:options)
exe s:DirCheck(dir)
let i = 0
let argv = copy(a:options.subcommand_args)
@@ -5281,7 +5289,7 @@ function! s:GrepSubcommand(line1, line2, range, bang, mods, options) abort
exe s:DirCheck(a:options)
let listnr = a:line1 == 0 ? a:line1 : a:line2
let cmd = ['grep', '-n', '--no-color', '--full-name']
let dir = a:options.git_dir
let dir = s:Dir(a:options)
let options = s:GrepOptions(args, dir)
if listnr > 0
exe listnr 'wincmd w'
@@ -5295,8 +5303,8 @@ function! s:GrepSubcommand(line1, line2, range, bang, mods, options) abort
\ 'git': a:options.git,
\ 'flags': a:options.flags,
\ 'args': cmd + args,
\ 'dir': dir,
\ 'git_dir': dir,
\ 'dir': s:GitDir(a:options),
\ 'git_dir': s:GitDir(a:options),
\ 'cwd': s:UserCommandCwd(dir),
\ 'filetype': 'git',
\ 'mods': s:Mods(a:mods),
@@ -5363,7 +5371,7 @@ function! s:LogFlushQueue(state, dir) abort
return queue
endfunction
function! s:LogParse(state, dir, line) abort
function! s:LogParse(state, dir, prefix, line) abort
if a:state.mode ==# 'hunk' && a:line =~# '^[-+ ]'
return []
endif
@@ -5371,7 +5379,7 @@ function! s:LogParse(state, dir, line) abort
if len(list)
let queue = s:LogFlushQueue(a:state, a:dir)
let a:state.mode = 'commit'
let a:state.base = 'fugitive://' . a:dir . '//' . list[2]
let a:state.base = a:prefix . list[2]
if len(list[1])
let [a:state.base_module; a:state.parents] = split(list[1], ' ')
else
@@ -5516,7 +5524,7 @@ function! fugitive#LogCommand(line1, count, range, bang, mods, args, type) abort
\ args + extra_args + paths + extra_paths)
let state.target = path
let title = titlepre . (listnr < 0 ? 'Gclog ' : 'Gllog ') . s:fnameescape(args + paths)
return s:QuickfixStream(listnr, 'log', title, s:UserCommandList(dir) + cmd, !a:bang, a:mods, s:function('s:LogParse'), state, dir) . after
return s:QuickfixStream(listnr, 'log', title, s:UserCommandList(dir) + cmd, !a:bang, a:mods, s:function('s:LogParse'), state, dir, s:DirUrlPrefix(dir)) . after
endfunction
" Section: :Gedit, :Gpedit, :Gsplit, :Gvsplit, :Gtabedit, :Gread
@@ -6312,7 +6320,7 @@ function! fugitive#BlameComplete(A, L, P) abort
endfunction
function! s:BlameSubcommand(line1, count, range, bang, mods, options) abort
let dir = s:Dir()
let dir = s:Dir(a:options)
exe s:DirCheck(dir)
let flags = copy(a:options.subcommand_args)
let i = 0
@@ -6992,10 +7000,11 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, args) abo
endif
let remote_url = fugitive#RemoteUrl(remote, dir)
let raw = empty(remote_url) ? remote : remote_url
let git_dir = s:GitDir(dir)
let opts = {
\ 'git_dir': dir,
\ 'repo': {'git_dir': dir},
\ 'git_dir': git_dir,
\ 'repo': {'git_dir': git_dir},
\ 'remote': raw,
\ 'remote_name': remote,
\ 'commit': commit,