I have a go.mod looks like
require(
...
github.com/google/wire v0.3.1-0.20190716160000-66f78fc84606
...
)
Based on my understanding, if a package looks like that (yyyymmddMMSS-commit_id), which version should be v0.0.0 but not v0.3.1 as this example.
Could someone guide me how should I explain this? Does go mod ignore the v0.3.1- prefix?
It's the result of go get'ing a specific commit that exists in the tree after a semantic version tag:
go get github.com/google/wire#66f78fc84606
Pseudo versions are used not only when there is no version tag.
As the official documentation about pseudo versions shows:
Pseudo-versions may refer to revisions for which no semantic version tags are available. They may be used to test commits before creating version tags, for example, on a development branch.
...
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the base version is a release version like vX.Y.Z.
In this case, the repository does have semantic version tags. The base version here is v0.3.0, and by getting a specific commit (66f78fc84606) that exists after v0.3.0 and before the next one v0.4.0, you end up with:
github.com/google/wire v0.3.1-0.20190716160000-66f78fc84606
In fact there are 3 acceptable forms of pseudo-version:
vX.0.0-yyyymmddhhmmss-abcdefxyz.
when no earlier versioned commit with an appropriate major version before target commit
vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefxyz
when most recent versioned commit before the target commit is vX.Y.Z-pre
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefxyz
when most recent versioned commit before the target commit is vX.Y.Z
Some more details about Managing Go Module Pseudo-Versions:
https://hackernoon.com/managing-go-module-pseudo-versions-in-go-113-412h30lw
Related
I read everywhere that packages have to have a tag of v0 or v1. Why can't a tag be v2020 or something other than v0 or v1. I have tried this personal and is get the following error with I use v2020.
Scotts-Mac-mini:seeding syacko$ go mod tidy
go: errors parsing go.mod:
/Users/syacko/workspace/sotesoft/src/utils/seeding/go.mod:10: require gitlab.com/soteapps/packages: version "v2020.2.0" invalid: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2020
Scotts-Mac-mini:seeding syacko$
It's a convention, a convenience for everyone. Go modules chose to use the widely accepted Semantic Versioning v2.
Go Modules Wiki:
What happens if I create a go.mod but do not apply semver tags to my repository?
semver is a foundation of the modules system. In order to provide the best experience for consumers, module authors are encouraged to apply semver VCS tags (e.g., v0.1.0 or v1.2.3-rc.1), but semver VCS tags are not strictly required:
Modules are required to follow the semver specification in order for the go command to behave as documented. This includes following the semver specification regarding how and when breaking changes are allowed.
Modules that do not have semver VCS tags are recorded by consumers using a semver version in the form of a pseudo-version. Typically this will be a v0 major version, unless the module author constructed a v2+ module following the "Major Subdirectory" approach.
Therefore, modules that do not apply semver VCS tags and have not created a "Major Subdirectory" are effectively declaring themselves to be in the semver v0 major version series, and a module-based consumer will treat them as having a semver v0 major version.
An interesting and relevant blog post from Dave Cheney that predates Go modules: Gophers, please tag your releases
What do we want? Version management for Go packages! When do we want it? Yesterday!
[...] We want our Go build tool of choice to fetch the latest stable version when you start using the package in your project.[...]
But as it stands, today, in 2016, there is no way for a human, or a tool, to look at an arbitrary git (or mercurial, or bzr, etc) repository of Go code and ask questions like:
What versions of this project have been released?
What is the latest stable release of this software?
If I have version 1.2.3, is there a bugfix or security update that I should apply?
The reason for this is Go projects (repositories of Go packages) do not have versions, at least not in the way that our friends in other languages use that word. Go projects do not have versions because there is no formalised release process.
[...] I recommend that Go projects adopt SemVer 2.0.0. It’s a sound standard, it is well understood by many, not just Go programmers, and semantic versioning will let people write tools to build a dependency management ecosystem on top of a minimal release process.
After re-reading github.com/golang/go/wiki/…, I see the issue is not with the v2020.y.z, it is with the directory structure not matching the version number. path abc/def/v2020 v2020.y.z should work. Thank you for the various links. A good working example is github.com/jackc/pgx/v4
Here are the steps for the item you are going version:
When you get to the point where you want to change the version to V2 or higher, these are the steps that need to be followed.
Sample go.mod file before version change
module gitlab.com/soteapps/packages
go 1.14
require (
github.com/aws/aws-sdk-go v1.32.4
github.com/jackc/pgconn v1.5.0
github.com/jackc/pgx/v4 v4.6.0
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect
golang.org/x/text v0.3.3 // indirect
)
Sample go.mod file after version change
module gitlab.com/soteapps/packages/v2100
go 1.14
require (
github.com/aws/aws-sdk-go v1.32.4
github.com/jackc/pgconn v1.5.0
github.com/jackc/pgx/v4 v4.6.0
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect
golang.org/x/text v0.3.3 // indirect
)
Sample Golang file import before change
package sDatabase
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
"gitlab.com/soteapps/packages/sError"
"gitlab.com/soteapps/packages/sLogger"
)
const (
Sample Golang file import after change
package sDatabase
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
"gitlab.com/soteapps/packages/v2020/sError"
"gitlab.com/soteapps/packages/v2020/sLogger"
)
const (
Item having a version v2+ number:
Edit the go.mod module line to include the major version number at the end of the existing module path. So, the above module line module gitlab.com/soteapps/packages would change too module gitlab.com/soteapps/packages/v2100.
All import references to gitlab.com/soteapps/packages in all the *.go files in the project must be updated to gitlab.com/soteapps/packages/{version}. In our example, this would the following, gitlab.com/soteapps/packages/v2100.
Commit the change to source control.
If you are using master, then commit to master.
After you commit to master, create a branch from master with the version name. v2100 in the above example.
If you are using branch, then commit to a branch with the version name. v2100 in the above example.
The last step is to create a tag using semantic versioning format (vX.Y.Z) that point to the version branch. v2100.1.0 would be the tag for this example.
I have two code repository A and B in Go, A depends on B using gomod management. For example, the latest tag version of B is v1.0.1 and the same version in A's go.mod, and then some new commits are merged into B, but without upgrade tag. Can I get the latest changes just by go get -u A_GIT_PATH? I try some times, but I can't get the newest B into my local workplace, may gomod's cache causes this problem?
Looking forward for any suggest, thanks so much~
You will need to set up your go.mod to source from local project.
replace "github.com/userName/otherModule" v0.0.0 => "local/path/the/module"
eg: here
I have a go.mod file that looks like this:
module someName
go 1.13
require (
.
.
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4
localpackage v0.0.0
)
replace localpackage => ../localpackage
This works just as expected! What I can't figure out is how can I add a certain version or commit hash to the replace directive!
For example:
replace localpackage => ../localpackage v1.0.0
or
replace localpackage => ../localpackage v0.0.0-20190731182444-35453ccff3d6
Doing this results in an error:
replacement module directory path "../localpackage" cannot have version
The error is quite clear that I shouldn't add a version to a local replace. I checked the wiki but I couldn't find an answer!
The question:
Is it possible to add this kind of replacement and how? What am I missing here?
As the error says: you cannot specify a version when the replace directive is pointed at a local folder. There is no guarantee and it is not a requirement that the replacement folder contains files of a versioning system, it is perfectly valid to just have "snaphots" of the Go sources. So in many cases it would have no meaning to specify a version.
However, if your local folder is a clone of a git repository for example, you may simply switch that to your intended version. E.g. execute a git checkout v1.0.0 in that local folder to switch to that version, and that version will be used.
Using go modules, I would like to replace labix.org/v2/mgo with github.com/globalsign/mgo. The http://labix.org/mgo repository is unmaintained and has been forked to https://github.com/globalsign/mgo
my code is stored outside $GOPATH in the directory ~/git/foo
I'm using go1.11
other go modules are working (for example go list -m all lists other modules, the files go.mod and go.sum are updating automatically. See the full file below)
I've tried the following in the go.mod file:
replace labix.org/v2/mgo => github.com/globalsign/mgo v0.0.0-20181015145952-eeefdecb41b842af6dc652aaea4026e8403e62df
Running go build gives the following error:
build github.com/foo/bar: cannot find module for path labix.org/v2/mgo
The documentation in go help modules discusses Pseudo-Versions eg v0.0.0-yyy.., which I'm trying to use because the tags on https://github.com/globalsign/mgo are of the form r2018.06.15 and not v1.2.3 (semantic versioning).
In addition go help modules says:
Pseudo-versions never need to be typed by hand: the go command will accept
the plain commit hash and translate it into a pseudo-version (or a tagged
version if available) automatically. This conversion is an example of a
module query.
However I can't work out the command for generating a pseudo-version when I'm in the cloned github.com/globalsign/mgo (located at $GOPATH/src/github.com/globalsign/mgo). Hence the pseudo-version I've manually generated may be wrong.
The full go.mod file looks like:
module github.com/foo/bar
replace labix.org/v2/mgo => github.com/globalsign/mgo v0.0.0-20181015145952-eeefdecb41b842af6dc652aaea4026e8403e62df
require (
github.com/DATA-DOG/godog v0.7.8
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 // indirect
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 // indirect
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 // indirect
...
)
Try the go edit -replace command, without modifying the line of the original package.
This way you don't need to know the exact pseudo version beforehand, just the commit hash id.
So in your case, don't manually modify go.mod require section of "labix.org/v2/mgo", and run this command to append your commit "eeefdec" of your fork, on top of labix version:
$ GO111MODULE="on" go mod edit -replace=labix.org/v2/mgo=github.com/globalsign/mgo#eeefdec
After the first time you build or test your module, GO will try to pull the new commit, and then will generate the "replace" line with the correct pseudo version for you. So then you'll see on the bottom of go.mod:
replace labix.org/v2/mgo => github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
When using the replace directive, leave the pseudo-version out.
It's also stated here, which points to an open issue.
Probably off-topic, but I've mostly used replace when I wanted to use a local version of some dependency. Why not import the forked lib which you'd like to use (instead of the original non-maintained one) and have mod resolve it properly?
The source being replaced (in this case labix.org/v2/mgo) also needs to be added to the require list with a version of v0.0.0 (even though it won't be downloaded). In the replace the source doesn't need a version but the target does.
However I haven't worked out how to auto-generate the pseudo version for the target (github.com/globalsign/mgo in this case), so I still needed to manually generate it.
Here's a better go.mod file:
1 module foo.bar/qux
2
3 replace labix.org/v2/mgo => github.com/globalsign/mgo v0.0.0-20181015145952-eeefdecb41b842af6dc652aaea4026e8403e62df
4
5 require (
6 github.com/DATA-DOG/godog v0.7.8
7 github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 // indirect
<snip>
21 golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b // indirect
22 labix.org/v2/mgo v0.0.0
23 )
Notice the require of labix.org on line 22; go mod tidy accepts this.
However I now come up against a different issue, the use of internal packages (referred to in issues like this: https://github.com/golang/go/issues/23970). I still haven't solved this new problem.
% go build main.go
/home/sonia/go/pkg/mod/github.com/globalsign/mgo#v0.0.0-20181015145952-eeefdecb41b842af6dc652aaea4026e8403e62df/auth.go:38:2:
use of internal package github.com/globalsign/mgo/internal/scram not allowed
Following the release of Go 1.11, I have been trying to move my repositories to Go modules, by adding a go.mod file at their root.
One of my root libraries my.host/root is in its version 17.0.1, so I wrote in its go.mod file:
module my.host/root/v17
I tagged that version v17.0.1 as documented in the Go modules manual.
When I try to make a new Go project that uses my root library, like:
package main
import root "my.host/root/v17"
func main() {
root.DoSomething()
}
And try to compile it, I get the following error:
go: my.host/root#v0.0.0-20180828034419-6bc78016491a: go.mod has post-v0 module path "my.host/root/v17" at revision 6bc78016491a
I am at loss figuring out why this happens. I explicitly added v17.0.1 in the go.mod file, yet every attempt at go build replaces the entry with a v0.0.0-20180828034419-6bc78016491a version which then fails because at that commit, the go.mod file module entry of my root library indeed ends with a v17, as it should.
For the record, this commit is the same as the tagged v17.0.1 version.
What am I doing wrong here? How can I debug this situation?
I had make two mistakes:
My initial v17.0.0 tag would point to a commit where go.mod did not contain the v17 import path suffix. As a result, it seems Go tooling considers the whole v17 major version as a v0/v1 instead, even if later v17 tags point to a commit with a correct go.mod directive, hence the commit ID "translation".
In my dependent projects, in the go.mod file, I mistakenly specified
require my.host/root v17.0.1 instead of
require my.host/root/v17 v17.0.1.
After fixing both those issues, everything seems back to normal and it works perfectly. I wish the documentation had been clearer about this but I guess this is a good opportunity to make a contribution!
The error I got was: github.com/emicklei/go-restful#v0.0.0-20180531035034-3658237ded10: go.mod has post-v0 module path "github.com/emicklei/go-restful/v2" at revision 3658237ded10
Appending github.com/emicklei/go-restful with v2 like so: github.com/emicklei/go-restful/v2 in my go.mod file fixed it for me.