如何避免使用 `go get` 命令更新自己?

huangapple go评论106阅读模式
英文:

How to avoid updating myself with `go get`

问题

我有一个如下所示的包结构:

GOPATH
   src
      github.com/myname
         mymainproject
            something.go //从github导入东西
            mysubproject
               main.go //导入"github.com/myname/mymainproject" + 其他包

作为构建的一部分,我从主目录运行go get -u -t ./..。如果从主分支构建,这个方法非常好用,但是我已经配置了Jenkins从任何分支构建。

然而,当从另一个分支构建时,当它更新mysubproject的依赖时,它会将整个工作目录更新到主分支,这绝对不是我想要的。

我只有两个可能有效的想法:

  1. 在运行go get之后,检出我想要构建的原始分支。我仍然担心在go-get过程中切换分支可能会导致它跳过一些仅存在于该分支中的依赖项,或者不必要地获取仅存在于主分支中的依赖项,所以我不确定这是否是一个好的解决方案。
  2. 使用魔术的go1标签标记当前分支上的提交。我相信这也必须在远程上完成,这使得它不太吸引人。

有没有办法防止go-get触及我的主要代码库?

英文:

I have a package structure that looks like this:

GOPATH
   src
      github.com/myname
         mymainproject
            something.go //imports things from github
            mysubproject
               main.go //imports "github.com/myname/mymainproject" + others

As part of m build I run, go get -u -t ./.. from the main directory. This works great if building from master, but I have jenkins configured to build from any branch.

When building from another branch though, when it updates dependencies of mysubproject it updates the full working directory to master, which is very much not what I want.

I only have two real ideas that might work:

  1. After I run go get, check out the original branch that I want to build. I still worry that switching branches mid go-get could cause it to skip some dependencies that exist only in the branch, or fetch unnecessarily ones that exist only in master, so I'm not sure this is a good solution.
  2. Tag the current commit on the branch with the magic go1 tag. I believe this would have to be done on the remote as well, which makes it much less appealing.

Is there any way to prevent go-get from touching my main repository?

答案1

得分: 4

虽然我不建议在生产构建中使用go get -u(就像Google一样,我建议使用vendoring来管理软件包,以便能够重现旧的构建并在分支上管理软件包版本),但使用list和一些过滤器编写一个小脚本来实现你想要的功能并不难。类似下面的脚本应该可以工作:

go get -u -t `go list ./... | grep -v mysubproject`

这将排除mysubproject。或者你可以排除mymainproject,或者使用其他过滤器来排除你不想更新的内容。

你还可以查看godep来帮助你管理依赖项并在需要时更新它们。


更新: 你可以进一步列出你导入的所有软件包:

go list -f '{{join .Imports "\n"}}' github.com/mymainproject/mysubproject | sort -u

这将列出mysubproject直接导入的所有软件包。你可以过滤掉mymainproject,然后更新这个列表(不包括mysubprojectmymainproject)。这也包括系统软件包,但它们不会被更新,所以没关系(尽管你也可以过滤它们)。

Godep目前正在添加一个-r选项,用于重写导入路径,这样你可以将依赖项放入你的项目中,并将其导入为github.com/mymainproject/mysubproject/Godeps/_workspace/src/github.com/<package>。这个功能在rewrite分支上。这种方法的优点是,它意味着你的库使用的是你测试过的版本,而不是最终消费者机器上的任意版本。缺点是最终消费者可能会得到多个相同软件包的副本。

在这种情况下,你应该始终问自己是否真的需要在你的库中使用这个依赖项。传递依赖项似乎永无止境地带来问题。你可以解决这些问题,对于你真正重要的依赖项,你应该这样做,但我曾经不止一次地只提取了我实际需要的两个函数并将它们复制到我的软件包中,以避免依赖项。我并不是说重用代码是不好的;只是确保在每种情况下成本是值得的。

英文:

While I don't recommend go get -u as part of a production build (like Google, I recommend vendoring your packages so you can reproduce old builds and manage package versioning on branches), it's not that hard to get what you want with a small script using list and some filtering. Something like this should work:

go get -u -t `go list ./... | grep -v mysubproject`

That would exclude mysubproject. Or you could exclude mymainproject, or otherwise filter to get rid of whatever you don't want to update.

You should also look at godep to help you manage your dependencies and update them when you mean to.


UPDATE: You can take this to another level and explicitly list all the packages that you import:

go list -f &#39;{{join .Imports &quot;\n&quot;}}&#39; github.com/mymainproject/mysubproject | sort -u

This lists everything that mysubproject directly imports. You can filter out mymainproject and then update that list (which won't include mysubproject or mymainproject". This includes system packages, too, but those won't update, so it's ok (though you could filter them if you wanted).

Godep is currently adding a -r option that will rewrite imports, so you can vendor your dependencies into your tree, and import them as github.com/mymainproject/mysubproject/Godeps/_workspace/src/github.com/&lt;package&gt;. This is on the rewrite branch. The advantage of this approach is that it means your library uses the version you tested with rather than whatever version happens to be on the final consumer's machine. The downside is that the final consumer may wind up with multiple copies of the same package.

You should always take times like these to ask yourself if you really need the dependency in your library. Transitive dependencies have seemingly never-ending problems like these. You can work around them, and you should for a dependency that is really important to you, but I've more than once picked up the two functions I actually needed and copied them into my package to avoid a dependency. I'm not saying reusing code is bad; just make sure the cost is worth it in each case.

答案2

得分: 0

对我来说有效的方法是不使用Rob建议的go get -u。相反,在构建之前,我确保完全清理我的gopath,然后可以简单地执行go get -t ./...来获取尚未在磁盘上的所有依赖项。

这需要更长的时间来获取所有依赖项,但它运行良好。

英文:

What appears to work for me is to not use go get -u as Rob suggests. Instead I make sure I fully clean my gopath before a build., then I can simply do a go get -t ./... to fetch all dependencies not already on disk.

This takes lokger to fetch all dependencies, but it works well.

huangapple
  • 本文由 发表于 2014年5月16日 00:03:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/23683359.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定