-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only query the requested path in the file API #1868
base: master
Are you sure you want to change the base?
Conversation
autoload/fugitive.vim
Outdated
return [-1, '000000', '', '', -1] | ||
endif | ||
let newftime = getftime(fugitive#Find('.git/index', dir)) | ||
let [info, filename] = split(lines[0], "\t") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filename
here might be the input path, or it might look like path/child
, because the original input was a directory name. In the latter case, we need to instead return [newftime, '040000', 'tree', '', 0]
. Basically, we're replacing this functionality:
vim-fugitive/autoload/fugitive.vim
Lines 2039 to 2042 in 4d29c1d
while filename =~# '/' | |
let filename = substitute(filename, '/[^/]*$', '', '') | |
let s:indexes[a:dir][1][stage][filename] = [newftime, '040000', 'tree', '', 0] | |
endwhile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! And it looks like it giving a directory can lead to lots of results as all files under that directory are listed. Hmm. For now I'll try the assumption that if ls-files
returns more than one line for a path, that path represents a directory. I can't get ls-files
to report on an empty directory though so it might work, though I don't know enough yet to be confident that this assumption holds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't stage an empty directory. But you can stage a directory containing exactly one file. So "more than one line" is insufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ach, sorry! Somewhere in there while tinkering with the output of ls-files
and ls-tree
I somehow convinced myself that the directory would also be listed by ls-files
as well as its contents. I'll take another crack at it.
autoload/fugitive.vim
Outdated
let [_, ftime] = s:TreeInfo(dir, commit) | ||
let entry = [ftime, '040000', 'tree', '', -1] | ||
elseif commit =~# '^:\=[0-3]$' | ||
let [lines, exec_error] = s:LinesError([dir, 'ls-files', '--stage', '--', path]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let result = fugitive#Execute(['--literal-pathspecs', 'ls-files', '--stage', '--', path])
let line = result.stdout[0]
if result.exit_status || empty(line)
The --literal-pathspecs
is a necessary change. The rest is just modernization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
13f3b39
to
c9c40c1
Compare
Okay I've pushed a new attempt that just reuses the while-loop approach from |
You're building a whole data structure just to pluck one value out of it and throw the rest away. This is not a good approach, least of all from a code readability perspective. You should need little more than |
c9c40c1
to
d708f0b
Compare
Good point, thanks! I was overthinking things. |
This is going to return the wrong information during merge conflicts, since it will always grab the first line, regardless of which stage was actually requested. Is there a way to only request one stage? I can't find it, and if not, we'll have to loop over the lines. I might take a stab at adding some caching back in at the same time. |
Good catch. I don't see anything in git-ls-files(1) about selecting a particular stage. But iterating seems straightforward. |
d708f0b
to
1391d30
Compare
Okay, how does that look? Is the caching fine? In the original dicussion you suggested a more granular caching approach would be appropriate. I took that to mean using the repo and path as the cache key, giving a flatter structure overall. It's a bit awkward having to fill in all four stages in the cache for tree objects- is there a better way to handle that? |
At least throw a How is performance without caching? Caching was basically mandatory back when we used
Supporting |
Fetching an uncached entry:
Cached:
So roughly 6x to 7x faster. I don't have the experience to know what's generally acceptable for plugins. Personally I think 7 extra milliseconds isn't a big deal, so I'd honestly be fine with ditching the caching after all given the increased risk of bugs. |
Remind me, why doesn't it apply to |
Sorry I deleted that part of the message. I wrote it down and then realized it sounded weird, tested it, found that actually it was just a bug in |
7ms is nigh imperceptible on its own, but that's going to be multiplied by number of checks, which in turn will be multiplied by levels of nesting. This can get out of hand quick. Even with caching this could amount to a pretty big setback for smaller repos. The Projectionist stuff isn't super high value and can even be confusing in some cases. I'm starting to get tempted to change it to opt-in rather than opt-out. |
Only support stage '0' for tree objects
1391d30
to
32e2cd9
Compare
Sorry for taking a while to get back to this! That makes sense that it wouldn't just be 7ms, I forgot that this is going to be hit repeatedly. That makes it sound like caching will be crucial to minimize the cost. Here's what I've changed:
Turning this functionality off by default seems reasonable to me. |
This is to follow up on discussion #1866
Currently this is still just the first step as discussed, but I figured a PR is a better place to look at and discuss actual code than a discussion post.
I basically just extracted the relevant lines from the body of
TreeInfo
. I did also leave in a call toTreeInfo
for theif empty(path)
case though, since it seemed to me like the commit could still be either a regular hash or a stage number in that case, which get the ftime in different ways.