When you walk away from "go get", things suddenly become smaller, simpler and more flexible.
gbdoes nothing more thanGOPATH=$PROJECT/src:$PROJECT/vendor/src go build
Now imagine a way to pull code from any DVCS right inside your project without the need to rewrite import paths or worry about the code being somewhere else and potentially accessible. Then imagine all import paths being relative to the project. It is referenced like "vendor/github.com/goinggo/work".
Thanks to gb, the import statement for the vendored code inside the project uses the canonical path. There is no need to rewrite the import paths of the vendored code.
I really like how Dave managed to side-step the whole dependency metadata file that Brad Fitzpatrick was asking for and nobody could agree on.
One of the coolest things about Go is that it doesn't need a project file to build or analyze code. The next biggest thing is in a package; package main can live anywhere. In fact, LiteIDE used to have a project file, however I think it was a great improvement when it was removed.
Package rewriting can also be super easy and reversible; all you have to keep track of is the canonical path and tools can do really intelligent things when combined with GOPATH.
I just can’t find a way to vendor code without rewriting import paths and keep “go get”.
This idea of a vendor file really has me confused. If the idea is to list the commit or tag you want “go get” to fetch, and that code is still being placed inside the GOPATH as it works today, I’m not sure how this solves the problem. If “go get” via this vendor file is going to vendor the code, based on the location of the vendor file, then the GOPATH still needs to adjusted on the fly when building or the imports needs to be re-written.
2. A number of version pinning tools require a separate GOPATH per project. This is very similar to how python and ruby work I believe.
I would consider this a hack and cannot recommend it for Go.
3. [...] None of this requires modifying GOPATH.
4. Import path rewriting by default loses information. It loses repository information and it loses the canonical path information. There are two approaches: a) always keep the entire repository of all dependencies and never move the location of the dependencies so nothing ever gets lost, b) write down what you need to know.
I'd like you to consider the following three methods of "taking in code". This of course omits legal and technical reviews, so insert them as needed:A. The company you work for uses an internal repository of all external code, including Go code. When code is "taken in", it is rewritten under an internal name space. All projects never reference github.com, they reference the internal name space.B. The company you work for uses location for external code that is used by some of their projects. When code is "taken in" it is rewritten under an internal name space. A portion of projects in that department all reference that code.C. The company you work for stores dependencies with each project. When code is "taken in" it is rewritten under an internal project name space and that project will use that code.Option A has the least trouble from legal and technical reviews; all projects use the same dependencies. But Option C is also an option if the need arrises. This is made possible with import path rewriting. The vendor file just notes relevant information so it can be effectively managed by tools.I will note gb support C and maybe B. Side note, could gb compile Go itself? What would it take to compile Go with gb? The Go project uses the "go" tool to compile Go (after a bootstrap). I don't see technical issues with import path rewriting. If fact when taking in code, the process of copying them is easy and 100% mechanical (if the canonical path is written down, reversible). The technical review and legal should be your biggest concern.
I would consider this a hack and cannot recommend it for Go.Why do you consider this a hack???
Could you give examples of import path for A, B and C, to clarify?
On May 15, 2015, at 9:24 AM, Daniel Theophanes <kard...@gmail.com> wrote:Hi Bill,
I'm hearing you say:1. Some of the existing code helpers only work when GOPATH=PATHA, but don't work with GOPATH=PATHA:PATHB.
2. You'd like to set a separate GOPATH per project.
3. Import path rewriting doesn't work with "go get”.
3. You don't understand the role of a vendor file. How will that help anything? Won't the GOPATH still need adjustment on the fly?
If I misinterpreted your questions let me know. Otherwise I'll work on answering them.1. Every tool I've used works with a combined GOPATH *if* I'm using it correctly. Making a separate GOPATH entry per project is bound to result in problems. If a plugin doesn't actually handle multiple GOPATH entries correctly, I'm sure they would welcome a PR.
2. A number of version pinning tools require a separate GOPATH per project. This is very similar to how python and ruby work I believe. I would consider this a hack and cannot recommend it for Go.
3. The tool "go get" works very well for what it does. It was never meant to be a replacement for a legal and technical department to decide what code can be used by a company. My particular vendor tool expect someone to arrange the version they want to use on disk, then it pull is from disk, not network, and notes the version. In later version if I add a network fetch update option I can do a shallow fetch at that revision into a temporary folder, rewrite the import paths, and copy in the final location. These is good will to modify "go get" to support versions. None of this requires modifying GOPATH.
4. Import path rewriting by default loses information. It loses repository information and it loses the canonical path information. There are two approaches: a) always keep the entire repository of all dependencies and never move the location of the dependencies so nothing ever gets lost, b) write down what you need to know.
...I'd like you to consider the following three methods of "taking in code". This of course omits legal and technical reviews, so insert them as needed:A. The company you work for uses an internal repository of all external code, including Go code. When code is "taken in", it is rewritten under an internal name space. All projects never reference github.com, they reference the internal name space.
B. The company you work for uses location for external code that is used by some of their projects. When code is "taken in" it is rewritten under an internal name space. A portion of projects in that department all reference that code.
C. The company you work for stores dependencies with each project. When code is "taken in" it is rewritten under an internal project name space and that project will use that code.
Option A has the least trouble from legal and technical reviews; all projects use the same dependencies. But Option C is also an option if the need arrises. This is made possible with import path rewriting. The vendor file just notes relevant information so it can be effectively managed by tools.
I will note gb support C and maybe B.
Side note, could gb compile Go itself? What would it take to compile Go with gb?
The Go project uses the "go" tool to compile Go (after a bootstrap). I don't see technical issues with import path rewriting. If fact when taking in code, the process of copying them is easy and 100% mechanical (if the canonical path is written down, reversible). The technical review and legal should be your biggest concern.
On 16 May 2015 5:13 pm, "Peter Bourgon" <pe...@bourgon.org> wrote:
>
> >> 2. A number of version pinning tools require a separate GOPATH per project.
> >> This is very similar to how python and ruby work I believe. I would consider
> >> this a hack and cannot recommend it for Go.
> >
> > Agree.
>
> After watching these discussions for a very long time, it is
> increasingly becoming my opinion that this might be the least bad
> option. Maybe it's worth revisiting these categorical dismissals?
>
I'm sorry, I've completely lost context here, so I don't know which position you are for. Could you clarify please.
Thanks for clarifying. My next question is obviously, do you categorise gb under the GOPATH per project category?
I consider not needing a project file a good thing because I can just create a folder and then a file anywhere in the GOPATH and I'm coding. Done. My other foot is in Java, C# where devs are constantly stepping on toes in the project file and before you do a new thing, you have to create a new project.
I've used a single (or near single) GOPATH for years. It just works. It is how it was designed. Kinda like using car keys to open a bottle, it works, but you are more liable to cut yourself.
Could you give examples of import path for A, B and C, to clarify?A) This is what Google does and a number of other companies. You might rewrite the context package from "golang.org/x/net/context" and store it under "$GOPATH/src/third_party/context" or maybe "$GOPATH/src/theid_party/golang.org/x/net/context".
B) Let's take an open source project, say coreos and related tools and use that as an example. Say they create a repo "github.com/coreos/third_party/{context,html,...}"Then the packages "github.com/coreos/etcd" and "github.com/coreos/rkt" both reference packages from the "third_party" repo.C) This is what "github.com/coreos/etcd" does today. The vendor packages for that command is stored within that same repo. This is what gb supports.
2b) I also don’t believe re-writing the import path for the vendored code, alters the code in any way. The import path is a directive to tell the compiler where the code for the package is, since the source of truth now exists inside the project, that is the code I want.
“gb” is the only tool I have seen to solve this problem because it basically removes GOPATH from the equation. It is no longer a point of configuration, therefore no longer an issue or stumbling block.
Ok, this is not a fully rational argument, but now I understand what you meant by "hack" :-)
I think I get it now. Let me rephrase to make sure I understand:A) The company uses a single monolithic company-wide repository which contains everything, including the vendored dependencies. (This is what I do by the way)B) The company uses one repository for each app and a "shared" repository containing all the vendored dependencies.C) The company uses one repository for each, which includes the vendored dependencies of the app.Correct? ;-)