-
-
Notifications
You must be signed in to change notification settings - Fork 230
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
Feature: git submodule support via path selection #1802
Feature: git submodule support via path selection #1802
Conversation
Thanks for your pull request and interest in making D better, @FeepingCreature! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. |
515bf24
to
d3b7954
Compare
source/dub/package_.d
Outdated
if (!existsFile(git_dir) || !isDir(git_dir.toNativeString)) return null; | ||
if (!existsFile(git_dir)) return null; | ||
if (!isDir(git_dir.toNativeString)) { | ||
auto gitredirect = readText(git_dir.toNativeString).strip(); |
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 want .chomp
not .strip
, but really, you should not be parsing git's files by hand. The correct way is to invoke git to query information.
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.
If invoking git
is not viable (e.g. too slow on Windows), then code that messes with git's internals ought to be encapsulated in its own module.
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.
Commit message should say that this is for absorbed submodules (i.e. those for which .git
is a 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.
Could you please paste your IRC comment for how to do this here? My backlog doesn't go that far.
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 think this is the relevant line: [2019-11-22 16:07:24.606] <CyberShadow> git -C path/to/submodule rev-parse --git-dir
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.
Fixed? It now uses git rev-parse
on non-Windows. I've left the previous code behind version(Windows)
inside the module because I don't think that that refactoring is in-scope for this PR, though I agree it should be done. The Windows implementation should probably be split out completely so it doesn't confuse up the code. Raise an issue please?
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.
Fixed via separate PR.
vspec = vspec.merge(selection); | ||
enforce(vspec != Dependency.invalid, format( | ||
"Selected package %s doesn't match %s(%s) of %s", | ||
selection, dep.name, dep.spec, pack.name)); |
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.
If I understand this correctly, this will probably break the way I use Dub + submodules where I bind-mount the submodule to its "real" location (i.e. bindfs -n ~/work/ae lib/ae
) - since the main directory is on master, it won't match the dub.selections.json
version. That's probably fine though. If there isn't a way to override it (local dub.selections.json
override?) then maybe it would be nice if there was a way.
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.
Commit message should conform to git conventions (first line under 60-80 characters).
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.
Should work. Branches are excluded from the override, for pretty much that reason that it would make incremental development impossible, which is exactly the thing submodules/bind mounts are for.
Thanks!
I guess a user would expect |
The question is largely whether it should be smart enough to upgrade git submodules. Since submodules are a form of externally tracked selection, IMO |
I don't think I saw a reply to a similar question I asked in the last PR: why is this needed when using git submodules works today by specifying a path instead of a version number? |
Submodules "work" today with dub, in that you can include submodules and build running code. Submodules don't work in the sense that if you include submodules via |
Would it be appropriate for |
Put that on the list of "why is |
I see. I think that's just fine if the dependency is in a submodule, as Git already holds the exact version of the dependency, so copying it in As such, I think simply doing nothing / printing a message like |
But I mean, just to put it from my perspective again - we're not using submodules because we want dub to leave them alone, we're using submodules because it's the only viable way of simultaneously co-developing two repositories with dub in a CI-capable fashion unless I manage to convince whoever did it to un-deprecate branches. So this kind of "this is a submodule, I'm going to tactfully ignore it because I assume you know what version you've checked out" logic is actively at odds with what we are actually interested in dub for. For that matter, I'm not sure that anybody has a workflow that relies on using submodules to force dub to ignore versions, one of its core competencies. I hope the notion to have |
Shouldn't |
I think a plugin system, which is what this would amount to, is kind of a big task. So like, "should" maybe? Though I can't imagine how it'd work. But that's something I personally have no use for with dub, and would probably push the task into "too big to bother" for me. |
Nah, just a regular command like dub already supports e.g. preGenerateCommands, let them return a JSON string which has the paths ext. all specified via stdout. No need to make it complicated :) |
Would need a command to switch to a new state too. Does get a bit complicated. Are there even other VCS that have submodule equivalents? |
Mercurial has something similar: https://www.mercurial-scm.org/wiki/Subrepository I don't like the idea of baking a specific VCS behavior into dub itself. Hence the command support. Sadly we have to bake into the registry specific providers because of no common API provided. Without it understanding specific VCS systems. |
Well, that's a matter for that PR if/when I end up making it. Let's table that idea for this PR. |
Why would one need version checking logic for a git submodule? Their versions are pinned by commit and have to be changed manually. |
We need some way to decide the question "which release version can we pull the submodule up to". Right now, this question is answered by the mechanism of "update the submodule to the newest version and see if you get compilation errors." This is a terrible mechanism for many reasons. We would like a better one. Dub is the mechanism by which D projects are supposed to verify dependencies. The logical, 2+2=4 tier, response is to ask "can we make dub work for submodules too?" Hence this PR. The alternative is for us to straight up ditch submodules and go back to development branches. Branches are deprecated in dub. I don't see how we're supposed to move forward with dub in any situation where we have to co-develop two repositories in a way that has to build on CI. (Branches would be a step down from submodules, as we'd no longer have reproducibility. But still a step up from the current 'just pull it up and see if it works, lol.') |
I don't understand why we need that. Either one uses a version specification as usual, or one uses a git submodule. If said submodule had version tags, one could already just use it normally.
How is it worse than "
I don't see how that follows.
The way I do it now - change the dependency on a version to a path dependency, commit, change the dependency until things work, |
Having said all this, I remember now that when I tried adding a git submodule to a dub package, it worked, but not if any other dub package depended on it. That I'd be in favour of fixing. |
As a dub dependency? Yes, but again - not with branches, unless one was to specifically use a deprecated dub feature. Which realistically isn't going to ever go away, but it's still bad workflow. So, again, the problem arises when you have two repos that have to coevolve, for instance because you're trying to introduce some library functionality that is only meaningful in the context of the other repository. (But you still want dependency checking the rest of the time.)
Sorry, to restate - I didn't mean "we as in the D community", I meant specifically "us at Funkwerk, who use submodules pretty widely."
Entire point of dub version checking is that if you did semver correctly, you don't need to build to see if it works because dub will select versions that are known to work via dependency information! That's one of dub's major value adds over rdmd... I think part of the confusion is that there's two separate major usecases here. The first is "We want the newest versions of those seven repos that are intercompatible." That's The second is "We want this repo to be available from a branch, and we want to incrementally change it and use those changes in another repo, and validate that other repo on CI." That's The problem is unifying those two usecases, without having to continually switch between submodules and Basically, I want to use submodules as a committable, repository-specific, equivalent of If I pull up some dependency, my versions won't work. The goal is: I want D tooling to tell me this in the form of "Package X required Dependency Y>9.1.0, but Y 8.7.0 is selected." I don't want D tooling to tell me this in the form of "{three pages of linker errors}", or "{cryptic template invocation error}". Or, God forbid, a crash on a customer system due to incompatible runtime behavior. My impression was that dub was a tool that attempted to give me this. So I don't understand all the questions of "why do you need version checking with this?" What would I even want dub for if not for version checking? |
I have the feeling that we're not understanding each other. I'm trying my best to understand what you want to enable that doesn't work now. I noticed now rereading that I may have understood completely what you're trying to do - I thought we were talking about git submodules, not dub ones. I suggest adding a test case enabled by the diff - even after rereading everything I don't quite get what it's supposed to do. |
We are. Okay, let's give a practical example. All names and project versions are fake, but this is structurally equivalent to problems that have come up in practice with the serial numbers filed off. Note that all of these projects are simultaneously their own freestanding projects and act as submodules in five to ten other projects. So say we have "utilities" (the obligatory "internal utilities lib" every organization accumulates) at 5.2.3 and our event-store client is at 1.0.3. So "utilities" is a submodule in "event-store", because we needed to develop and test this fix in the context of event-store's source code, so we've just tagged utilities as 5.2.3 and set a dub dependency in "event-store" on Now, say we have a project that tracks the position of a train and enforces invariants such as that positions shouldn't change more than a hundred km between position updates, or whatever. And this is the project that originally triggered the work on event-store, which is a submodule in train-position, which has a submodule for utilities but the actual submodule used to link train-position is the submodule of utilities placed directly in train-position (because obviously train-position needs its own copy). And this is now implicitly However, train-position also exposes a library subproject, because other services need to know how to talk to it and how to read events from its domain. So How does the user get informed, when building train-arrival ~master where he just updated the train-position submodule to 2.1.3, that utilities 3.4.4 is too old? With this patch, what happens is simply exactly that. Dub determines the version of
Without this patch, dub just shrugs its shoulders and goes "eh, I guess they're all |
…ons.json specified versions actually match the dependency requirements. For path selections, get the required version from the SCM if it's a tag.
…lly interpreting the `.git` file, except on Windows.
473d69c
to
844c9fa
Compare
@atilaneves Does that make it clearer? |
I think so. Thanks! |
Do we still need this, now that support was added ? |
Yeah, gonna close it. Whether this needs doing or not, nothing else is likely to come of this PR. Thanks for reminding. :) |
Second try! (ping @wilzbach @atilaneves )
This approach relies on hardcoding the submodules in
dub.selections.json
and thus requires some more user intervention. The idea here is to extend dependencies to include both path and version, and fordub.selections.json
determine the version from the SCM. Then, instead of overwriting the dependencies withdub.selections.json
we check if the selected package actually matches the version requirements, which is probably something we should do anyways - ifdub.selections.json
says2.3.4
but the package requires>=2.4.0
it's highly questionable to continue with2.3.4
anyways.Open question: how does this interact with
dub upgrade
? How should it?Open task: write test for it.
See #1780 for previous debate.