commit 8a0a448f56cd62b1f4b78f60ad6830788ee83ab0 (tree)
parent 004da420e5f67b868d0a35e8cfe5ae77cad1aca8
Author: Tim Pope <code@tpope.net>
Date: Sun, 29 Jul 2018 14:22:33 -0400
Show fake trees when editing directory in index
Diffstat:
2 files changed, 53 insertions(+), 33 deletions(-)
diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim
@@ -1126,15 +1126,29 @@ function! fugitive#BufReadCmd(...) abort
if empty(dir)
return 'echo "Invalid Fugitive URL"'
endif
- let b:fugitive_type = system(s:Prepare(dir, 'cat-file', '-t', rev))[0:-2]
- if v:shell_error
- unlet b:fugitive_type
- return 'silent doautocmd BufNewFile '.s:fnameescape(amatch)
- elseif b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$'
- return "echoerr ".string("fugitive: unrecognized git type '".b:fugitive_type."'")
- endif
- if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob'
- let b:fugitive_display_format = +getbufvar('#','fugitive_display_format')
+ if rev =~# '^:\d$'
+ let b:fugitive_type = 'stage'
+ else
+ let b:fugitive_type = system(s:Prepare(dir, 'cat-file', '-t', rev))[0:-2]
+ if v:shell_error && rev =~# '^:0'
+ let sha = system(s:Prepare(dir, 'write-tree', '--prefix=' . rev[3:-1]))[0:-2]
+ let b:fugitive_type = 'tree'
+ endif
+ if v:shell_error
+ unlet b:fugitive_type
+ if rev =~# '^:\d:'
+ let &readonly = !filewritable(dir . '/index')
+ return 'silent doautocmd BufNewFile '.s:fnameescape(amatch)
+ else
+ setlocal readonly nomodifiable
+ return ''
+ endif
+ elseif b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$'
+ return "echoerr ".string("fugitive: unrecognized git type '".b:fugitive_type."'")
+ endif
+ if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob'
+ let b:fugitive_display_format = +getbufvar('#','fugitive_display_format')
+ endif
endif
if b:fugitive_type !=# 'blob'
@@ -1150,9 +1164,11 @@ function! fugitive#BufReadCmd(...) abort
if b:fugitive_type ==# 'tree'
let b:fugitive_display_format = b:fugitive_display_format % 2
if b:fugitive_display_format
- call s:ReplaceCmd([dir, 'ls-tree', rev])
+ call s:ReplaceCmd([dir, 'ls-tree', exists('sha') ? sha : rev])
else
- let sha = system(s:Prepare(dir, 'rev-parse', '--verify', rev))[0:-2]
+ if !exists('sha')
+ let sha = system(s:Prepare(dir, 'rev-parse', '--verify', rev))[0:-2]
+ endif
call s:ReplaceCmd([dir, 'show', '--no-color', sha])
endif
elseif b:fugitive_type ==# 'tag'
@@ -1181,6 +1197,8 @@ function! fugitive#BufReadCmd(...) abort
silent keepjumps 1,/^diff --git\|\%$/g/\r$/s///
keepjumps 1
endif
+ elseif b:fugitive_type ==# 'stage'
+ call s:ReplaceCmd([dir, 'ls-files', '--stage'])
elseif b:fugitive_type ==# 'blob'
call s:ReplaceCmd([dir, 'cat-file', b:fugitive_type, rev])
setlocal nomodeline
@@ -1188,9 +1206,12 @@ function! fugitive#BufReadCmd(...) abort
finally
keepjumps call setpos('.',pos)
setlocal nomodified noswapfile
- if rev !~# '^:.'
- setlocal readonly nomodifiable
+ if rev !~# '^:.:'
+ setlocal nomodifiable
+ else
+ let &modifiable = b:fugitive_type !=# 'tree'
endif
+ let &readonly = !&modifiable || !filewritable(dir . '/index')
if &bufhidden ==# ''
setlocal bufhidden=delete
endif
@@ -3064,16 +3085,12 @@ function! s:NavigateUp(count) abort
let rev = s:buffer().rev()
let c = a:count
while c
- if rev =~# '^[/:]$'
- let rev = 'HEAD'
+ if rev =~# ':.*/.'
+ let rev = matchstr(rev, '.*\ze/.\+', '')
+ elseif rev =~# '.:.'
+ let rev = matchstr(rev, '^.[^:]*:')
elseif rev =~# '^:'
- let rev = ':'
- elseif rev =~# '^refs/[^^~:]*$\|^[^^~:]*HEAD$'
- let rev .= '^{}'
- elseif rev =~# '^/\|:.*/'
- let rev = s:sub(rev, '.*\zs/.*', '')
- elseif rev =~# ':.'
- let rev = matchstr(rev, '^[^:]*:')
+ let rev = 'HEAD^{}'
elseif rev =~# ':$'
let rev = rev[0:-2]
else
@@ -3155,10 +3172,14 @@ function! s:cfile() abort
let myhash = matchstr(getline(1),'^\w\+ \zs\S\+')
endif
- let treebase = s:DirCommitFile(@%)[1].':'.s:Relative('').(s:Relative('') =~# '^$\|/$' ? '' : '/')
- if treebase !~# '^\d\=:' && getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
+ let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
+
+ let treebase = substitute(s:DirCommitFile(@%)[1], '^\d$', ':&', '') . ':' .
+ \ s:Relative('') . (s:Relative('') =~# '^$\|/$' ? '' : '/')
+
+ if getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
return [treebase . s:sub(matchstr(getline('.'),'\t\zs.*'),'/$','')]
- elseif treebase !~# '^\d\=:' && getline(1) =~# '^tree ' && empty(getline(2)) && line('.') >= 2
+ elseif showtree
return [treebase . s:sub(getline('.'),'/$','')]
else
@@ -3172,8 +3193,6 @@ function! s:cfile() abort
return [file]
endif
- let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
-
if getline('.') =~# '^ref: '
let ref = strpart(getline('.'),5)
@@ -3191,9 +3210,9 @@ function! s:cfile() abort
endwhile
return [ref]
- elseif getline('.') =~ '^tree \x\{40\}$'
+ elseif getline('.') =~# '^tree \x\{40\}$'
let ref = matchstr(getline('.'),'\x\{40\}')
- if s:repo().rev_parse(myhash.':') == ref
+ if len(myhash) && s:repo().rev_parse(myhash.':') ==# ref
let ref = myhash.':'
endif
return [ref]
diff --git a/doc/fugitive.txt b/doc/fugitive.txt
@@ -327,14 +327,15 @@ master: The tree referenced by master
Makefile The file named Makefile in the work tree
@^:Makefile The file named Makefile in the parent of HEAD
:Makefile The file named Makefile in the index (writable)
+@:% The current file in HEAD
- The current file in HEAD
^ The current file in the previous commit
~3 The current file 3 commits ago
: .git/index (Same as |:Gstatus|)
-:0 The current file in the index
-:1 The current file's common ancestor during a conflict
-:2 The current file in the target branch during a conflict
-:3 The current file in the merged branch during a conflict
+:% The current file in the index
+:1:% The current file's common ancestor during a conflict
+:2:% The current file in the target branch during a conflict
+:3:% The current file in the merged branch during a conflict
STATUSLINE *fugitive-statusline*