Masterminds / glide

Package Management for Golang
https://glide.sh
Other
8.15k stars 540 forks source link

glide -> gps transition #565

Open sdboyer opened 8 years ago

sdboyer commented 8 years ago

As discussed in #384, there's a number of things to consider about transitioning glide onto gps. I figured I'd open this issue as a place to start just enumerating them, and we can decide where/how to split them all out later.

I intend to edit and update this list as I go, though, so probably better to think of this as a meta-TODO list, where we can check things off as we talk through them and agree on something, implement something, or whatever other solution we come to.

(This list is unlikely to be exhaustive until everything's actually checked, as it's a running checklist that I'll add to as we discover more things)

sdboyer commented 8 years ago

@ches - this is the closest thing to that outline you'd asked about in #384

mattfarina commented 8 years ago

@sdboyer going to start asking some questions as I dig through these. Here's a start:

  1. Is the detection in Masterminds/vcs the level of detection supported or is there more? If there's more can you give me a pointer. I ask because the vcs property is used regularly by some big Glide users. I ended up needing to use it this morning.
  2. If the name is changing from s/import/dependencies what's the handling for backwards compatibility? There are thousands of glide.yaml files in existence.
  3. Did you work it out so varying locations can point to the same package and this work cross projects? So project A could pull package C from its source and project B could pull package C from a fork and the resolution just works.
sdboyer commented 8 years ago

Is the detection in Masterminds/vcs the level of detection supported or is there more? If there's more can you give me a pointer. I ask because the vcs property is used regularly by some big Glide users. I ended up needing to use it this morning.

Yes, there's considerably more (Masterminds/vcs detection isn't used at all). It's wrapped up in a larger system, contained within the SourceManager. There are several public-facing entry points, but they unify at SourceMgr.deducePathAndProcess, and hten SourceMgr.deduceFromPath(). The latter's internals will look more familiar to you; the former is basically just negotiating the futures returned from the latter.

There's a lot of logic here, all there for considered reasons, but not all necessarily germane to the question of a vcs property. So, to focus this discussion, the key question that I haven't had an answer for is, "what use case is there for an explicit vcs property that can't be satisfied by having the vcs extension literally written in the import path?"

If I have a clear view on what that use case is, then I can figure out where it's appropriate to incorporate that control.

If the name is changing from s/import/dependencies what's the handling for backwards compatibility? There are thousands of glide.yaml files in existence.

Yep, there's a checkbox for this on #384 right now, and it's my currently in-progress code on my local. Basically, my approach is to have structs for the new version of the manifest and lock files, and structs for the old version. ConfigFromYaml() and LockfileFromYaml() then attempt the new versions first, and if they don't work, try the legacy version, and (if possible) automatically convert them into the new version. A third return value is added, indicating whether the legacy autoconversion took place, so that the user can be notified. (messages are not printed directly from the function, as we don't want those funcs printing when autoconversions are done on yaml/lock files in deps - only the root project).

Did you work it out so varying locations can point to the same package and this work cross projects? So project A could pull package C from its source and project B could pull package C from a fork and the resolution just works.

There are three answers to this: "No", "Yes," and "I'd like to but it's hard. All are true, depending on the specific constraints.

The "Yes" is because it's possible for the root project to indicate an override, which unilaterally chooses the location from which to source C. It could be what A says, or what B says, or something else entirely. This is a workable solution that gives the user the control they need to proceed with their own work, but it's not a scalable or healthy solution, because:

  1. That override has to be restated by every root project that encounters the conflict
  2. Once that override is written into a manifest, it's likely to stay around for much longer than it may be needed - (say, once B goes back to being fine with using the canonical source of C)

The "No" refers to the general case: given that "one import path, one package" is (at least for now) a requirement of the system, if A and B indicate that C should be sourced from a different location/URL, that is, at base, an irreconcilable conflict. There may be ways we can squirrel around that, but that brings us to...

"I'd like to, but it's hard"; while there are a bunch of strategies we could use to make this work in some common cases, they involve doing some acrobatics, and I want to tease out the specific constraints of those cases more before investing the necessary time.

For example, in the use case you gave, I think the ideal solution would be that if we treated A's request for the canonical C as a 'default', which could later be superceded by B's request for sourcing C from a fork, then that might work well. However, with the way the solver is currently designed, depending on ordering, things could look different:

So, yeah - we have at least a short-term solution, but more use case exploration and refinement is needed.

mattfarina commented 8 years ago

"what use case is there for an explicit vcs property that can't be satisfied by having the vcs extension literally written in the import path?"

How would you handle a location on the filesystem? People use those right now for a handful of things. I didn't consider the file:// based locations until others brought it up from their use.

sdboyer commented 8 years ago

How would you handle a location on the filesystem? People use those right now for a handful of things. I didn't consider the file:// based locations until others brought it up from their use.

As in the mirroring idea implemented in #547? Or as in "there's code, but no vcs to manipulate, at file://path/to/source - use that for import path x/y/z"?

My answers are quite different, depending on which one you're curious about.

mattfarina commented 8 years ago

@sdboyer I have a hard time thinking I could go to the Glide power users, such as @akutz, and tell them that in glide.yaml files and mirror settings they could not use file:// paths. Something they can do, and some already do, today.

What would you suggest telling these folks that they would accept?

sdboyer commented 8 years ago

I have a hard time thinking I could go to the Glide power users, such as @akutz, and tell them that in glide.yaml files and mirror settings they could not use file:// paths. Something they can do, and some already do, today.

What would you suggest telling these folks that they would accept?

...??

I don't understand why you wrote this. The question I asked was, "are you referring to the mirrors feature you just shipped, or to this other thing?" You responded with, "mirrors are an important feature, how do I tell people they don't get them?" Could you please answer the question I ask, particularly when it's a straight up either/or? Or, if it's not clear what I'm talking about (which I know happens often, and I'm sorry), ask for a clarification?

In any case, I take it that you want to discuss mirrors, not the other thing.

I didn't say that mirrors are something gps can't/won't support. Not at all. I was only referring to that vcs property. But, I'm guessing you jumped ahead to mirroring because, in glide's current approach, that vcs prop is necessary to discover the vcs type of the local "mirror." Right? If there's a different or additional reason(s), please tell me.

mattfarina commented 8 years ago

@sdboyer I have some questions/comments...

  1. I've tried using the code on the PR to update Glide itself and Helm. In both cases it failed with a panic. The panic on helm was panic: canary - *should* be impossible to have a pkg-only selection here which came right after ← backtrack: no more versions of gopkg.in/yaml.v2 to try.
  2. Does this have anything to do with lacking a default version when one is not specified? Right now Glide tracks the default branch for a repo. When no version is specified that is used. This is a cached piece of information.
  3. Can you share why cache key names use a different strategy than what Glide uses today? I'm curious of the reason(s).
  4. When I try to run glide install with a legacy lock file I see it failing to make the conversion it says it's trying...
[WARN]  glide.yaml was in a legacy format. An attempt will be made to automatically update it.
[WARN]  glide.lock was in a legacy format. An attempt will be made to automatically update it.
panic: interface conversion: gps.Revision is not gps.PairedVersion: missing method Underlying

I keep running into trouble when I go to try it. Can you give me some pointers to help get up to speed more quickly?

sdboyer commented 8 years ago

(I've pushed a commit that should fix this panic: panic: interface conversion: gps.Revision is not gps.PairedVersion: missing method Underlying - glide is now updating for me)

It's indeed possible that the panic with Helm there may be tied to issues with gopkg.in - I'll have to investigate more later. I've just opened up sdboyer/gps#97, which is about pre-filtering acceptable versions based on what the import path looks like - effectively, respecting gopkg.in's semantics. As much as that's possible, anyway.

Can you share why cache key names use a different strategy than what Glide uses today? I'm curious of the reason(s).

I actually wasn't looking at glide when I wrote it. It's based on simple string replacement - https://github.com/sdboyer/gps/blob/master/source_manager.go#L17, which is run on the results of url.String().

as the TODO notes, i'm not the happiest with it. looking at output, though, it seems to look like packagist's (while glide's looks a bit more like npm's).

Does this have anything to do with lacking a default version when one is not specified? Right now Glide tracks the default branch for a repo. When no version is specified that is used. This is a cached piece of information.

So, there's a few pieces, here. First is the background context - whenever we talk about version selection, defaults, etc. in gps, we're ultimately talking about the relative order of versions inside a queue. The order of versions in that queue is the order in which we "try" a version. "Trying" means checking it against version constraints (among other things), so it's not a problem if the correct version to pick isn't first in the queue - only that it's the first in the queue that satisfies constraints.

The way these queues get populated is a little complicated, but in the general case, gps uses this sort ordering on the set of versions returned from interrogating the vcs. That means, absent any constraint information, semver will always be tried first, then plain tags, then branches.

Now, the tool is in full control of the constraints that are used, so glide could effectively alter that behavior to prefer branches: whenever returning a manifest (whether for the root or a dep), if glide sees there's no constraint declared, it could put in a gps.AnyBranch() (not yet implemented, but pretty easy - sdboyer/gps#72). I'd also have to do sdboyer/gps#65 for that to work, but it's not terrible.

That said, I'd like to suggest that it might be better for glide to prefer selecting a semver tag if one is available, and if not, then taking the default branch. That seems to me to be the world we want to nudge towards. (For that, I'd need to do sdboyer/gps#65 and sdboyer/gps#98)

sdboyer commented 8 years ago

sdboyer/gps#65 and sdboyer/gps#98 are now complete. I've rolled v0.11.0 now, after pushing back a couple of the things that were in it to v0.12.0. The only thing that's of immediate relevance here that I bumped is the the pre-filtering of available versions from gopkg.in ticket, sdboyer/gps#97.

There's a couple API changes in v0.11.0 that I'll need to resync into #384 before it'll work. Nothing huge, though.

silasdavis commented 7 years ago

Is there anything that I could pick up to help with this effort? I don't have a huge amount of time to dedicate to it, but if there was something I've got a chance of writing a reasonable PR for I'd be up for it.

sdboyer commented 7 years ago

@silasdavis sorry, i've been very swamped this week - but i'm thrilled that you're interested in helping! i'll try to find a bite-size chunk for you over the weekend.

silasdavis commented 7 years ago

@sdboyer bump (though no rush - I'm not going anywhere)

sdboyer commented 7 years ago

@silasdavis thanks for the bump. sorry, my work in this general domain has been really focused towards the new official tooling, gps, and semver - between that and the holidays, it's been hard to find time for glide directly.

The most useful thing to start with would be building glide from the gps-integration branch, trying some things you're used to doing with glide, and providing feedback on what does/doesn't work, and where you're surprised by the tool's new behavior. Ideally, just keep a running stream-of-consciousness diary of everything you do as you do it, and your thoughts when you notice/run into things.

silasdavis commented 7 years ago

@sdboyer perhaps you could use me on gps?

sdboyer commented 7 years ago

@silasdavis i most surely could :)

i'm not sure that i can promise any particularly low-hanging fruit issues, but here's a starting list: