-
-
Notifications
You must be signed in to change notification settings - Fork 151
refactor: Refactor git module into vcs-type agnostic module #235
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
Conversation
sindrets
left a comment
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.
EDIT: I started typing out this comment before you pushed the latest changes, but I think most of it still applies.
I think we should probably create a VCS adapter interface that all the VCS adapters implement. The VCS module should not return an adapter on require. The appropriate adapter needs to be determined from a set of paths. Which is why i referred to the find_git_toplevel() function previously. I think the way we implement adapter acquisition should be similar to how this function works: we give it an ordered list of paths that might indicate what repository we are part of, and then it goes through the list and checks if any of these paths are part of a repository of any of the supported VCS'.
Making the adapters more object oriented than what the current git module is, is a good call I think. Currently pretty much all the git functions requires a reference to either one, or both of the git top-level and the git dir. These are context variables that I think we can safely assume will not change for the lifetime of a view, and thus we would benefit from storing these in the adapter instances (I don't know if Mercurial uses the equivalent of a git dir, but it necessarily needs the top-level path regardless).
This change is going to require a fair amount of refactoring. We need to instantiate the adapters when we create views in lib.lua, and then pass these adapters to the view constructors. All the subcomponents of a view will acquire the adapter through their parent view.
Refactoring the project to use this model should be the focus of this first PR I think. From there it seems pretty straight forward to implement other VCS adapters.
|
So, instead of local vcs = require("diffview.vcs")
local adapter = vcs.get_adapter(path)once, and pass that created For example, in |
|
The views are already passing around a -- Instantiate adapter:
local adapter = require("diffview.vcs").get_adapter(paths)
-- Now the adapter instance would have access to all the necessary context data
-- for the repo derived from the given paths:
adapter.ctx.toplevel
adapter.ctx.git_dir
The git stuff in So instead of doing this: local toplevel = lib.find_git_toplevel(paths)
if toplevel then
local git_dir = git.git_dir(toplevel)
if git_dir then
git.thing_we_actually_need(toplevel, git_dir)
end
endWe would do this: local adapter = vcs.get_adapter(paths)
if adapter then
adapter.thing_we_actually_need()
end |
|
I see, I was missing the scale of the refactoring here :) So to summarize:
I'll be pushing some commits whenever I find some time, when I have something worth reviewing I'll ping you again. |
|
@sindrets The merge view also seems to work, but I'm not sure about the cleanest implementation there. I found 2 functions that don't seem to be called anywhere:
I've removed these, but maybe you were planning to use these for some new features? Currently I have a I want to do a final pass through the code to make sure I've updated all old function calls and clean up the annotations. |
|
@zegervdv Brilliant! I'll see if I can find the time to review this soon.
Yes, it does :)
I believe they are just left over from previous refactors, so removing them is probably the right thing to do. But I'll take a closer look. |
sindrets
left a comment
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.
Great work!
A lot of the comments I made are requesting changes to address diagnostics. I highly recommend that you use a recent version of the lua-language-server, as that is what's driving the typing system here, and the reason why I'm strict about using accurate annotations.
There was one particularly nasty performance regression to the file history rendering, that was caused by - what I assume was - a left over debug line. Easily addressed of course, but take a look at the comment I left in file_history/render.lua :)
| local success | ||
| if item.kind == "working" or item.kind == "conflicting" then | ||
| _, code = git.exec_sync({ "add", item.path }, view.git_ctx.toplevel) | ||
| success = view.adapter:add_file(item.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.
You defined this API to take a list of paths, but that is not what's passed here. It's also not what the implementation expects in the GitAdapter. Suggestion: make the implementation handle lists of paths.
| success = view.adapter:add_file(item.path) | ||
| elseif item.kind == "staged" then | ||
| _, code = git.exec_sync({ "reset", "--", item.path }, view.git_ctx.toplevel) | ||
| success = view.adapter:reset_file(item.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.
Same as add_file.
| end, | ||
| unstage_all = function() | ||
| local _, code = git.exec_sync({ "reset" }, view.git_ctx.toplevel) | ||
| local success = view.adapter:reset_file() |
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.
reset_file: If this API should support no arguments; this needs to be reflected in its annotations.
|
Thanks for the thorough review, I think I fixed all of the points, but those I wasn't sure about I left unresolved. After properly setting up lua-language-server (I probably had a old or broken install) I am still seeing some diagnostic warnings in |
|
I think I've cleaned up the last diagnostic issues and expanded the type definitions for the flags and ctx a bit more. I've updated the implementation for |
sindrets
left a comment
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.
Great! I updated the API for plugins that integrate diffview (currently only Neogit), and I made a few other small changes. I'll have to give the Neogit guys a heads up because we have now changed one of the require paths that they use. Other than that, I reckon this PR is ready!
I'm gonna test a few more things over the weekend to make sure that everything is in order, just because this is such a big refactor.
|
Alright, thanks! I made a lot of intermediate commits, do you want me to push a single squashed commit or will you do that via the merge? I ran stylua on the code, but noticed that a lot of files/regions I did not touch also changed. I'm using stylua 0.15.1. You want me to only format the files this PR touches or just leave it as is? |
sindrets
left a comment
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.
I made a lot of intermediate commits, do you want me to push a single squashed commit or will you do that via the merge?
Don't worry about it; I squash all PR's on merge.
I ran stylua on the code, but noticed that a lot of files/regions I did not touch also changed. I'm using stylua 0.15.1. You want me to only format the files this PR touches or just leave it as is?
Yeah, I haven't been using stylua in a while. I don't really like any of the lua formatters I've tried. It particularly bothers me how stylua will collapse multiple lines into one when I've explicitly broken it into multiple lines for better readability. And to my knowledge there's no way around this other than to litter your code with -- stylua: ignore. And at that point I feel like the effort of circumventing the formatter outweighs its utility.
Sorry about the rant. TLDR: Don't worry about it, just leave it as is :)
In my testing over the weekend the only issues I found were with cases of passing invalid options to the commands. We should handle these cases gracefully instead of waiting until the program runs into a runtime error.
sindrets
left a comment
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.
Alright, let's merge this :)
Thank you for your hard work!
|
Thanks for being so supportive! It was a bit daunting at first, doing such a refactor on someone else’s code :). I’ve already started implementing the hg adapter so I hope to have a next PR in a couple of weeks. |
Part 1 of adding support for other VCS'es (#233).
This creates a
vcsmodule, which replaces thegit.utilsmodule. Upon requiring it, the vcs type is determined and the right module is returned (currently hardcoded to always returngit).I've changed the
Commitclass into a base class and made aGitCommitclass for git-specific stuff.The
revmodule will also need to be split, but this will probably will have to be done similarly to how thevcsmodule automagically returns the correct implementation.Still to do:
git.utilstovcs.utls(all the job handling etc)@sindrets is this in line with your expectations?