-
Notifications
You must be signed in to change notification settings - Fork 1k
Support vendor directory as $GOPATH/src/vendor #313
Conversation
LGTM! |
context.go
Outdated
@@ -124,6 +124,11 @@ func (c *Ctx) LoadProject(path string) (*Project, error) { | |||
// | |||
// The second returned string indicates which GOPATH value was used. | |||
func (c *Ctx) SplitAbsoluteProjectRoot(path string) (string, error) { | |||
// allow vendor directry to be directly under GOPATH/src |
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.
directory
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.
done!
context.go
Outdated
@@ -124,6 +124,11 @@ func (c *Ctx) LoadProject(path string) (*Project, error) { | |||
// | |||
// The second returned string indicates which GOPATH value was used. | |||
func (c *Ctx) SplitAbsoluteProjectRoot(path string) (string, error) { | |||
// allow vendor directry to be directly under GOPATH/src |
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.
nit: s/directry/directory/
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.
done
So on the one hand YAAY 👏 welcome @campoy 😄 On the other...I'm actually not sure what the effects are of trying to do it this way. I think it'll be one of two things:
Unless I've totally misimagined how it would handle this case, and it...somehow works out? I need to test a bit locally and see how it behaves. And we'll also probably want tests to verify behavior. |
So it seems to work out as some weird combination of the two - nothing is considered to be internal, but dep still doesn't write anything to the lock/vendor. I think we need a specification about what we actually want the behavior to be. dep/gps are built around the idea that there is a non-empty import path that is the "project root," and that all packages within the project are the lexical children of that root in a slash-delimited import path hierarchy. If that root is Note that this has nothing to do with what's actually on your GOPATH - we abstract from that, interacting symbolically with import paths. (Without doing that, the behavior of dep would be entirely driven by folks' local GOPATH setup, which is the opposite of what we want). That's maybe bigger than the scope of this PR, though - I think maybe here, if the goal is just to write |
My case is a bit strange, so let me document this. I have a project that uses many languages, Go is one of them.
In this case calling |
I can't share my code yet but this does work, it generates this lock.json: {
"memo": "93f2c886cd1a50ba14c0af5b308587b66c1faae7cdd52cfe3bd05f576707b392",
"projects": [
{
"name": "github.com/Sirupsen/logrus",
"version": "v0.11.4",
"revision": "0208149b40d863d2c1a2f8fe5753096a9cf2cc8b",
"packages": [
"."
]
},
{
"name": "github.com/golang/glog",
"branch": "master",
"revision": "23def4e6c14b4da8ac2ed8007337bc5eb5007998",
"packages": [
"."
]
},
{
"name": "github.com/golang/protobuf",
"branch": "master",
"revision": "c9c7427a2a70d2eb3bafa0ab2dc163e45f143317",
"packages": [
"jsonpb",
"proto",
"protoc-gen-go/descriptor"
]
},
{
"name": "github.com/grpc-ecosystem/grpc-gateway",
"version": "v1.1.0",
"revision": "a8f25bd1ab549f8b87afd48aa9181221e9d439bb",
"packages": [
"runtime",
"third_party/googleapis/google/api",
"utilities"
]
},
{
"name": "golang.org/x/net",
"branch": "master",
"revision": "a6577fac2d73be281a500b310739095313165611",
"packages": [
"context",
"http2",
"http2/hpack",
"trace"
]
},
{
"name": "golang.org/x/sys",
"branch": "master",
"revision": "99f16d856c9836c42d24e7ab64ea72916925fa97",
"packages": [
"unix"
]
},
{
"name": "google.golang.org/grpc",
"version": "v1.0.5",
"revision": "708a7f9f3283aa2d4f6132d287d78683babe55c8",
"packages": [
".",
"codes",
"grpclog",
"metadata"
]
}
]
} and populates the |
We went through this quite extensively in the past — put |
So, what do you recommend for my usecase where I need to have GOPATH inside of my repo, @peterbourgon? 😕 |
Huh. Weird. I wonder how the environment I set up is different. Let me try... Ah! I put my @campoy to my mind, we should think of this as a case where we're actually trying to use the tool without a GOPATH: "This dir and below is a bunch of Go source; work out the deps for it." Of course, a world without GOPATH does not exist (right now), but it's the behavior we're trying to simulate here, no? @peterbourgon re: locating the |
Yeah, at this stage, @campoy, I'm afraid |
How is $GOPATH/src not under GOPATH? |
A I'm 👍 on this change. @campoy The only thing I would like to see is a test for this behavior to make sure it's not broken in the future. |
Thanks for your input, @freeformz |
When we say "under GOPATH", we really mean "under $GOPATH/src"; |
Note: this ended up longer than I'd intended. But this is part of a knotty set of problems that IMO will require elbow grease; thus, I'm hoping this writeup will be a useful reference more generally. My concerns here are that this all works more or less by accident, and only in a somewhat restricted case. We COULD decide this is fine. But I'd rather not just blindly step into that decision; my preference is to take advantage of this experimental stage as a way of trying out deeper solutions to this problem. Now that I've had some time to really dig at this, I can be more concrete about what the problems are. Say that, instead of the path structure @campoy originally proposed, you have this structure:
Maybe not the most normal thing, but not crazy, either. (Mentally substitute If there are any imports between the local packages (which it would be wildly uncommon for there NOT to be), init/ensure will currently fail with something like:
If, instead of {
"memo": "1542339c5bb5ce57680a30b9ef308b6d822fe634c38dcf33458cfdfd354b0050",
"projects": [
{
"name": "github.com/kr/pretty",
"branch": "master",
"revision": "cfb55aafdaf3ec08f0db22699ab822c50091b1c4",
"packages": [
"."
]
},
{
"name": "github.com/kr/text",
"branch": "master",
"revision": "7cafcd837844e784b526369c9bce262804aebc60",
"packages": [
"."
]
}
]
} Note that the versions of those libs on the GOPATH have no effect on what's selected in the The basic problem here has to do with how gps classifies import paths. For that, some background is needed. When running either Here's some visuals, to help explain. Imagine we have three projects, The orange packages are the ones that were scanned in by When we call Grey arrows indicate tree-internal import statements, and black arrows indicate tree-external import statements. (I've also dropped the groupings around The problem with the change introduced by this patch is that it breaks a basic assumption of the model - that the packages scanned in to the current project's The OK, that's the first part. Part two is how gps treats internal vs. external imports. Internal imports are given cursory checks for correctness (e.g., does an internal import name a path without a corresponding package? like if This is the "door carefully left ajar" I mentioned, because it allows people to use a project root that isn't deducible - like
External paths, however, DO induce a requirement, because that's literally the point of this exercise - to find external dependency requirements, and ensure they're satisfied. There is, however, an exception - if one of those "external" imports is in stdlib, then we also ignore it as a requirement. This is a reasonable thing to do because the Go 1 guarantee promises us backwards-compatibility, and by definition, imports into stdlib never escape stdlib. This exception for stdlib is why @campoy's example works; this function decides if an import path points to stdlib. If you have a look at it, you'll see why it's mistaking everything under So, it works...for now. I don't really anticipate a change to the To reiterate, I believe this is an important use case, and I want to address it. But I'd really prefer it worked because we designed for it, rather than by accident with weird edge cases. In writing this up, it's seemed increasingly reasonable to me that we could accommodate an explicitly empty |
Wow, that's a great explanation @sdboyer! Looking forward to this on your keynote at GopherCon too It is interesting that this will work only because I'm not using any The solution for my case is, for now, to create a directory containing all of my packages. It's not a huge pain, but it could be blocking adoption for existing codebases that use this directory structure. If I recall correctly, that is the structure promoted by gdb, so I expect some friction there. Thanks again for the analysis, I agree my PR does not solve the deeper problem, and I'm OK with you closing it. I'll have to fix some typo on the docs to become a contributor now ... 😄 |
Thanks! sorry for delayed response - busy week :) I do think it would be worth it to have explicit support for an empty |
Updates #148