Open tummychow opened 10 years ago
Hey @tummychow, thanks for taking the time to put your thoughts down. I'm currently out of town, but I'll be back in on sunday so I'll go through and really read your posts then, so I can give them as much time as you did :P
No problem, @mediocregopher.
While I'm here, let me also point out another use case for the ref key on goget types. This is a real use case that I just crashed into while experimenting with another dependency manager.
My current project depends on the official client for InfluxDB, a time-series database written in Go. The client lives in a subfolder of the influxdb repository itself. To incorporate the client as a dependency, I have two basic options:
path: github.com/influxdb/influxdb/client
with type: goget
.path: github.com/influxdb/influxdb
with type: git
. I can't specify the client itself because the client is not its own repository.Now at the moment, either option works. But if I were to invoke the imaginary command goat gen
, it would only behave correctly in the first case.
In the second case, goat gen
thinks that my dependency is on all of influxdb. Influx happens to be a big project with a nontrivial dependency tree, so goat gen
would add all those entries to my .go.yaml
as well, which is incorrect because I only need the client.
On the other hand, in the first case, goat gen
checks the code for the client and sees there are zero dependencies (client only needs stdlib, fortunately) so it doesn't have to add anything.
The problem with the first case is that it's not version-locked. If the client underwent a breaking API change, my code would break because the client is using type: goget
. The fix would be to provide a ref on that type: goget
entry so that I can check out a specific version of the influx repo and use that version's client code.
Another option would be to add a rel
option to the type: git
dependencies, which would allow you to specify just the path within the repo that you care about. This is done in Berkshelf (specified in the Git Location section of their docs), and it works well for picking just a subdirectory within a git package.
@tummychow So what would the ref actually be? Would this be like a git ref, and goat would have to just figure out that this is actually a git repository and handle it as such?
Also, to the first scenario, upon realizing that a dependency is missing you're going to have to run some goat command. Either this is already implemented and you can run deps
, or if gen
(or whatever we call it) is implemented you can call that, and it implicitly calls deps
. Or we bail on everything and you edit .go.yaml
and call deps
. So adding this feature doesn't save the user any more hassle than if we implement gen
(which I'd much prefer).
For your second scenario, I agree with @pib that this could be solved other ways. Instead of a field in .go.yaml
I'd rather just have a flag we can pass in for gen
to specify a directory. The fewer changes to .go.yaml
we make the better; I'd much rather make a breaking change to flags than that in the future.
Yes, ref
on goget
would vary depending on the underlying VCS at play.
I'll have to surrender the other two points because I can see a use case for git
+rel
that would not be satisfied by goget
+ref
. It starts to look pretty ugly if you have multiple subpackages of a single repository (have to reference the same path and ref several times, with a different loc and rel each time), but there's no way around that.
I'll accept @pib's suggestion with two counterpoints of my own:
subfolder
or just sub
or something.rel
will be supported on every type
, including goget
.And possibly a third point for future implementation: being able to list multiple sub
folders on a single dep
, to avoid duplicating the path and ref. But that's a convenience that can be left for another discussion.
Consider this case:
You depend on package X and you have fixed it at version A. Package X depends on package Y, and you don't care about the version of Y.
You have a
deps
that looks like this:Now you bump X to version B. As a side effect of this version bump, X introduces a new dependency on Z. You don't care about the version of Z either. However, the version bump broke your build because you didn't have Z in your
.go.yaml
.Okay, let's imagine that my version of
goat gen
(described on #19) was implemented already. You see that there's a missing dependency in your build, so you immediately know your dep graph is incomplete. You rungoat gen
again and it fills in Z for you. Now you can carry on with your build.Counterpoint: what if you could set the ref on a goget package instead? What this means is "whatever deps this thing has, just get them, but I want the thing itself to be at this version". You end up with this deps instead:
Shorter than the original, and no risk of breakage from a new sub-dependency. I don't know who would really care about the difference between the first option and this second hypothetical one, but I know that the second one is clearly more intuitive than the first and requires less thinking. People who are suspicious of introducing any new subtrees in their depgraph without realizing it can always fall back to the first option to enforce their pedantic-ness.
@mediocregopher what are your thoughts? I'd be willing to take a shot at implementing this. It's something that many other dep managers already implement in some form (ie instead of clone, use go get + checkout). We could always borrow some of their code for this purpose ;)