Incomplete commondir support#4967
Conversation
|
Oops, should've checked whether the #4671 is being referenced already by a PR. I've started running down the rabbit hole with our attrs code to fix this exact issue. Anyway, I'll upload it later and then we can see how to proceed -- at least we ran into the different directions after doing the obvious immediate fix to the attrs code :)
Well, right now our support for So first step here would be to actually implement it at all, and then afterwards we may implement the fallback mechanism. I don't remember right now whether this was part of #4856 or not.
Personally, I'd wait until we see somebody requesting it. Until now, nobody has complained about our lacking API here. I just fear that as soon as we do that, people try to change those variables half-way through the repo's lifetime, which may lead to inconsistencies. That being said, I could easily see us adding an extended API to create repos. As you say,
Yup, definitely agreed. I've also fixed this in a local branch already.
That'd be rad. Git has grown increasingly complex over time, making the precedence and lookup rules non-trivial. So I'd be very eager to see some tests, even though I can imagine it being quite hard for some parts of libgit2. |
Strongly agree here, I think that there's vast opportunity to increase our complexity and potentially do this "wrong" from the standpoint of a consumer if we eagerly try to implement it without a use case. As a concrete example of the existing complexity: I was just creating an inmemory repository over the weekend and got caught up in a few issues that are not obvious and make assumptions about gitdir/commondir existing. (I'll open up a PR when I have a moment). |
Note that I was referring to this kinda-gitlink way, which we're already supporting : https://github.com/libgit2/libgit2/blob/master/src/repository.c#L193 I'm completely okay with not adding custom commondir support, because it might not make any sense. @pks-t suggestion of finding an API to provide those attributes is arguably more in-memory-ish. I was going the way that creating the file would make it pick it up, but it would act sanely if it's missing. |
That's definitely the right thing to do and is completely independent of improved commondir or in-memory attributes support. It's also the same thing that I've been doing in #4995 (which crossed work, as I initially didn't spot this PR as fixing the same issue due to the different title). I'm mighty annoyed though that it's impossible to write a test without either in-memory gitattributes or commondir mangling. But yeah, that's the way it is. |
|
I've pushed my current WIPs on top of that branch, which should have a working |
There was a problem hiding this comment.
Rebased, I've pulled in #4995 for DRY reasons (apart for its failing test, which I'm tracking a rebase of in my fork), but kept piling on the new issue. I've commented on the WIP parts I'd like some insight on.
Note that I'm refraining from adding a git_repository_new(&repo, path), or an _opts variant, because all the "low-level" setters are already present, and right now works in an in-memory repository can be quite surprising (but that's #4995 + its ignore counterpart, I think).
@kcsaul Do you have a moment to give a spin to that (OP is #4671), see if the behavior is at least equivalent to v27 ?
| * sense, and will thus be disabled. Passing "objects" here is thus | ||
| * reserved to backends that can make sense of its contents. | ||
| */ | ||
| const char *location; |
There was a problem hiding this comment.
Do not mind this too much. I have a hunch it would be nice to have (as in, allows us to tell in-memory from not, while providing them with a dedicated location). But it's only used as a somewhat-lock to also identify if the odb stack is only default backends. Useful, but unused 😉.
There was a problem hiding this comment.
I feel like this is assuming just too much about possible ODB backend implementations. The location belongs into loose/packed objects for sure, but it doesn't make any sense for e.g. in-memory or database-backed backends. As such I'd vote to not include such a field, as most backends except for Git's own cannot make any sense of it.
There was a problem hiding this comment.
I was attempting something with that, but I'm not quite sure now. I felt that knowing that we're using our own "standard" backends was something generally useful. And I felt that knowing if a backend has or has no filesystem location was as well, and that this aspect could be used as part of the definition of what is an in-memory repository. You could well imagine a backend that uses the filesystem, but it's not ".git/objects"-compatible: how can you signal that to the repository, so that it knows to report that its GIT_REPOSITORY_ITEM_OBJECTS contents is non-standard ? Not sure where I was going with this though…
There was a problem hiding this comment.
I agree that this would be useful. But that'd require a new callback in the backends, as we generally shouldn't assume anything of backends. Might very well be (well, probably not) that somebody has implemented his own implementation of a ".git/objects" backend that is uber fast due to it using platform-specific things.
| * | ||
| * @return 0 on success, or an error code | ||
| */ | ||
| GIT_EXTERN(int) git_repository_set_path(git_repository *repo, const char *path); |
There was a problem hiding this comment.
That allows giving a repository a filesystem location. It's not quite clear what will happen to it, but at least that should fix the "cannot exist in repository", if a user choses to do so.
There was a problem hiding this comment.
I hate that we started using path in the past. There's so many different paths, and this name doesn't tell at all which one we're referring to. Gitdir? Commondir? Working dir? Anyway, we're stuck with it and use it in different places already, so let's bite the bullet and stick with it :/ Or is it another API for deprecation, @ethomson?
That being said, the comment should say which of these paths we're actually referring to.
There was a problem hiding this comment.
👍 on the naming issue, and I can take care of the deprecation here if we decide for it.
There was a problem hiding this comment.
Mh. Dunno -- I think it would be easier to do in another PR to keep the code churn low and keep this reviewable. The deprecation things always require to make a sweep through all of our code, and I bet that git_repository_path is used in quite a lot of places.
|
|
||
| *out = NULL; | ||
|
|
||
| if ((error = git_repository_item_path(&objects_dir, repo, |
There was a problem hiding this comment.
This function got extracted because it's the interface point between them, and normally the place where the odb would initialize its backends' filesystem locations (hence it was more logical in odb). That's still in flux though.
|
@tiennou I'm getting some build errors in regards the new constant, do I need to change a compiler setting? (using MSVC). C2099 initializer is not a constant \libgit2\src\repository.c Line 50 |
|
Hmm, I'm confused as well, and can't take a look right now. Maybe it doesn't see a definition for |
|
@tiennou For now, I've been able to fix the build error by moving the 'none' constant to the enumeration in the header. Happy to confirm I'm no longer getting the 'path cannot exist in repository' error (#4671) and things seem to be working as they were previously now 😄 |
f1e285a to
5d1ab21
Compare
|
Rebased, I've made the fallback value public since it can't be "hidden". Note that I've seen to have messed up my brain when writing the PR, so let's recap the issues:
I think not much is missing from it, it just needs some thought about whether we should do 3), or if the first two are enough, and 3) can wait for a "repository backend" interface. In other words, I'm happy to drop the test and the setter for now (or make it private and keep them). |
pks-t
left a comment
There was a problem hiding this comment.
Sorry for taking so long to review. Most of the PR looks very good to me, especially all those refactorings make the code a lot easier to read.
I'm not really convinced of having location and the is_default things. It's a heavy layering violation and is really only applicable to the loose/packed ODB backends, which is why we should avoid adding such fields.
| * sense, and will thus be disabled. Passing "objects" here is thus | ||
| * reserved to backends that can make sense of its contents. | ||
| */ | ||
| const char *location; |
There was a problem hiding this comment.
I feel like this is assuming just too much about possible ODB backend implementations. The location belongs into loose/packed objects for sure, but it doesn't make any sense for e.g. in-memory or database-backed backends. As such I'd vote to not include such a field, as most backends except for Git's own cannot make any sense of it.
| * | ||
| * @return 0 on success, or an error code | ||
| */ | ||
| GIT_EXTERN(int) git_repository_set_path(git_repository *repo, const char *path); |
There was a problem hiding this comment.
I hate that we started using path in the past. There's so many different paths, and this name doesn't tell at all which one we're referring to. Gitdir? Commondir? Working dir? Anyway, we're stuck with it and use it in different places already, so let's bite the bullet and stick with it :/ Or is it another API for deprecation, @ethomson?
That being said, the comment should say which of these paths we're actually referring to.
| if ((error = git_repository_item_path(&path, | ||
| repo, GIT_REPOSITORY_ITEM_INFO)) < 0) | ||
| if ((error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, | ||
| NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0) |
There was a problem hiding this comment.
I know we previously didn't check for it, but what about GIT_ENOTFOUND here? Just wondering aloud
There was a problem hiding this comment.
That's true. I have not really read that code, but I'll check what it expects.
There was a problem hiding this comment.
preload_attr_file calls git_attr_cache__get, which swallows GIT_ENOTFOUND already, so this looks fine:
Lines 236 to 250 in c544850
There was a problem hiding this comment.
Huh, confusing. But well, fair enough, thanks for digging in
The code in the `attr_setup` function is not really matching our current coding style. Besides alignment issues, it's also hard to see what functions calls depend on one another because they're split up over multiple conditional statements. Fix these issues by grouping together dependent function calls and adjusting the alignment.
If creating a repository without a common directory (e.g. by using `git_repository_new`), then `git_repository_item_path` will return `GIT_ENOTFOUND` for every file that's usually located in this directory. While we do not care for this case when looking up the "info/attributes" file, we fail to properly ignore these errors when setting up or collecting attributes files. Thus, the gitattributes lookup is broken and will only ever return `GIT_ENOTFOUND`. Fix this issue by properly ignoring `GIT_ENOTFOUND` returned by `git_repository_item_path`.
As with the preceding commit, the ignore code tries to load code from info/exclude, and we fail to ignore a non-existent file here.
For example, https://git-scm.com/docs/gitrepository-layout says: info Additional information about the repository is recorded in this directory. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/info" will be used instead. So when looking for `info/attributes`, we need to check the commondir first, or fallback to "our" `info/attributes`.
|
Rebased, I've separated out all my experiments to
I'm kinda bummed that we don't have that many tests for those kind of ODB backend issues… I've looked at our libgit2-backend repository but it's not in a good shape. Would integrating at least one of the simpler ones as part of our CI "examples" runs or something would be good ? SQLite backend maybe, as it still needs a "locally discoverable" file — say |
| if ((error = git_repository_item_path(&path, | ||
| repo, GIT_REPOSITORY_ITEM_INFO)) < 0) | ||
| if ((error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, | ||
| NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0) |
There was a problem hiding this comment.
Huh, confusing. But well, fair enough, thanks for digging in
|
Thanks @tiennou! |
|
This PR breaks various tests in TortoiseGit and changes the output of libgit2 (cf. https://ci.appveyor.com/project/TortoiseGit/tortoisegit-06nst/builds/25633104?fullLog=true). I bisected the libgit2 commit history and the first faulty commit it 5452e49. One case is: Fix is in PR #5152. |
This comes from #4671, but I'd like to discuss the problem because I think it's a shortcoming of our "item locator" (and/or repository initialization), thus my initial fix is only papering over the underlying issue.
What happens is that you can (easily) get yourself a repository (using
git_repository_new) that has an unsetcommondirmember, which would cause failures in the locator, as it has no fallback mechanism if this member is not set (it reportsGIT_ENOTFOUND).AFAICS there's a bunch of things we can do:
add a fallback system to the locator.
As per gitrepository-layout,
$GIT_DIR/infois shadowed by$GIT_COMMON_DIR/infoif it's set (set meaning envvar, or a$GIT_DIR/commondir"gitlink".add some API to change the
commondir.Right now there's no way to do this, it's initialized on
neworopen, and set in stone at that time. I'm not sure if that's really needed, but to me it seems like some kind of shortcoming (since we allow swapping out ODBs and things, even if it's kinda crazy).make the relevant users of the item locator ignore issues.
This is the approach I started here, before I took a look at the layout document and noticed the discrepancy. The layout doc seems to imply that missing those directories is fine, thus we're just being overzealous.
introduce some layout-validity tests
@pks-t I'd like your opinion on these points before tackling them, as my gut feeling is that it's some kind of regression introduced by the worktree support (at least users that use
git_repository_newnow have an unfixable half-working repository, as per #4671).Helpful audit regex: