Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to handle go import absolute paths and github forks?

Tags:

go

There are plenty of questions around this, including why you shouldn't use import "./my/path" and why it only works because some legacy go code requires it.

If this is correct, how do you handle encapsulation of a project and by extension github forks? In every other lang, I can do a github fork of a project, or git clone, and everything is encapsulated there. How do I get the same behaviour out of a go project?

Simple example using the go "hello world" example.

hello.go

package main

import ("fmt"
    "github.com/golang/examples/stringutil")

func main() {
    fmt.Printf(stringutil.Reverse("hello, world")+"\n")
}

The above works great. But if I want to use my own stringutil which is in a subdirectory and will compile to a single binary, I still need the complete path:

package main

import ("fmt"
    "github.com/myrepo/examples/util/stringutil")

func main() {
    fmt.Printf(stringutil.Reverse("hello, world")+"\n")
}

Now, if someone copies or forks my repo, it has a direct dependency on "github.com/myrepo/", even though this is used entirely internally!

What if there are 20 different files that import utils/? I need to change each one each time someone forks? That is a lot of extraneous changes and a nonsensical git commit.

What am I missing here? Why are relative paths such a bad thing? How do I fork a project that refers to its own subsidiary directories (and their packages) without changing dozens of files?

like image 847
deitch Avatar asked Aug 23 '15 12:08

deitch


1 Answers

As for the reasoning behind not allowing relative imports, you can read this discussion for some perspective: https://groups.google.com/forum/#!msg/golang-nuts/n9d8RzVnadk/07f9RDlwLsYJ

Personally I'd rather have them enabled, at least for internal imports, exactly for the reason you are describing.

Now, how to deal with the situation?

  1. If your fork is just a small fix from another project that will probably be accepted as a PR soon - just manually edit the git remotes for it to refer to your own git repo and not the original one. If you're using a vendoring solution like godep, it will work smoothly since saving it will just vendor your forked code, and go get is never used directly.

  2. If your fork is a big change and you intend to remain forked, rewrite all the import paths. You can automate it with sed or you can use gofmt -r that supports rewriting of the code being formatted.

[EDIT] I also found this tool which is designed to help with that situation: https://github.com/rogpeppe/govers

I've done both 1 and 2 - when I just had a small bugfix to some library I just changed the remote and verndored it. When I actually forked a library without intent of merging my changes back, I changed all the import paths and continued to use my repo only.

I can also think of an addition to vendoring tools allowing automation of this stuff, but I don't think any of them support it currently.

like image 56
Not_a_Golfer Avatar answered Oct 05 '22 09:10

Not_a_Golfer