mirror of
https://github.com/therootcompany/go-gitver.git
synced 2024-11-16 17:08:59 +00:00
Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
1638772379 | |||
752451d77b | |||
3409d5f2e4 | |||
cfbbc73f48 | |||
1ee983f56d | |||
a745735392 | |||
b667843a2b | |||
37c1fd4b56 | |||
a45a154eaf | |||
d5c2342f76 | |||
6dace8255b | |||
82ec670e8a | |||
d4628bd751 | |||
a3af8e6c5b | |||
0921ed1e60 | |||
039b465b75 | |||
ef45a8a999 | |||
0b8c2d86df | |||
639a7e246f | |||
2da59efd62 | |||
84130f846a | |||
9f05e2304c | |||
47b8ec43ae |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,4 +1,9 @@
|
|||||||
generated-version.go
|
xversion.go
|
||||||
|
zversion.go
|
||||||
|
|
||||||
|
/go-gitver
|
||||||
|
hello
|
||||||
|
examples/*/*.sum
|
||||||
|
|
||||||
# ---> Go
|
# ---> Go
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
|
1
.prettierrc
Normal file
1
.prettierrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
168
README.md
168
README.md
@ -1,36 +1,117 @@
|
|||||||
# git-version.go
|
# [Go GitVer](https://git.rootprojects.org/root/go-gitver)
|
||||||
|
|
||||||
Use git tags to add semver to your go package.
|
Use **git tags** to add (GoReleaser-compatible) [**semver**](https://semver.org/)
|
||||||
|
to your go package in under 150
|
||||||
|
[lines of code](https://git.rootprojects.org/root/go-gitver/src/branch/master/gitver/gitver.go).
|
||||||
|
|
||||||
> Goal: Either use an exact version like v1.0.0
|
```txt
|
||||||
> or translate the git version like v1.0.0-4-g0000000
|
Goals:
|
||||||
> to a semver like v1.0.1-pre4+g0000000
|
|
||||||
>
|
1. Use an exact `git tag` version, like v1.0.0, when clean
|
||||||
> Fail gracefully when git repo isn't available.
|
2. Translate the `git describe` version (v1.0.0-4-g0000000)
|
||||||
|
to semver (1.0.1-pre4+g0000000) in between releases
|
||||||
|
3. Note when `dirty` (and have build timestamp)
|
||||||
|
|
||||||
|
Fail gracefully when git repo isn't available.
|
||||||
|
```
|
||||||
|
|
||||||
|
# GoDoc
|
||||||
|
|
||||||
|
See <https://pkg.go.dev/git.rootprojects.org/root/go-gitver/v2>.
|
||||||
|
|
||||||
|
# How it works
|
||||||
|
|
||||||
|
1. You define the fallback version and version printing in `main.go`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
//go:generate go run git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
commit = "0000000"
|
||||||
|
version = "0.0.0-pre0+0000000"
|
||||||
|
date = "0000-00-00T00:00:00+0000"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if (len(os.Args) > 1 && "version" == strings.TrimLeft(os.Args[1], "-")) {
|
||||||
|
fmt.Printf("Foobar v%s (%s) %s\n", version, commit[:7], date)
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. You `go generate` or `go run git.rootprojects.org/root/go-gitver/v2` to generate `xversion.go`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commit = "0921ed1e"
|
||||||
|
version = "1.1.2"
|
||||||
|
date = "2019-07-01T02:32:58-06:00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
# Demo
|
# Demo
|
||||||
|
|
||||||
|
Generate an `xversion.go` file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run git.rootprojects.org/root/go-gitver
|
go run git.rootprojects.org/root/go-gitver/v2
|
||||||
|
cat xversion.go
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
|
package main
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commit = "6dace8255b52e123297a44629bc32c015add310a"
|
||||||
|
version = "1.1.4-pre2+g6dace82"
|
||||||
|
date = "2020-07-16T20:48:15-06:00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<small>**Note**: The file is named `xversion.go` by default so that the
|
||||||
|
generated file's `init()` will come later, and thus take priority, over
|
||||||
|
most other files.</small>
|
||||||
|
|
||||||
|
See `go-gitver`s self-generated version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run git.rootprojects.org/root/go-gitver/v2 version
|
||||||
|
```
|
||||||
|
|
||||||
|
```txt
|
||||||
|
6dace8255b52e123297a44629bc32c015add310a
|
||||||
|
v1.1.4-pre2+g6dace82
|
||||||
|
2020-07-16T20:48:15-06:00
|
||||||
```
|
```
|
||||||
|
|
||||||
# QuickStart
|
# QuickStart
|
||||||
|
|
||||||
Add this to the top of your main file:
|
Add this to the top of your main file, so that it runs with `go generate`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Add a file that imports go-gitver (for versioning)
|
Add a file that imports go-gitver (for versioning)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// build +tools
|
// +build tools
|
||||||
|
|
||||||
package example
|
package example
|
||||||
|
|
||||||
import _ "git.rootprojects.org/root/go-gitver"
|
import _ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
```
|
```
|
||||||
|
|
||||||
Change you build instructions to be something like this:
|
Change you build instructions to be something like this:
|
||||||
@ -41,18 +122,20 @@ go generate -mod=vendor ./...
|
|||||||
go build -mod=vendor -o example cmd/example/*.go
|
go build -mod=vendor -o example cmd/example/*.go
|
||||||
```
|
```
|
||||||
|
|
||||||
You don't have to use `mod vendor`, but I highly recommend it.
|
You don't have to use `-mod=vendor`, but I highly recommend it (just `go mod tidy; go mod vendor` to start).
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
|
|
||||||
```
|
```txt
|
||||||
version print version and exit
|
version print version and exit
|
||||||
--fail will cause non-zero exit status on failure
|
--fail exit with non-zero status code on failure
|
||||||
|
--package <name> will set the package name
|
||||||
|
--outfile <name> will replace `xversion.go` with the given file path
|
||||||
```
|
```
|
||||||
|
|
||||||
ENVs
|
ENVs
|
||||||
|
|
||||||
```
|
```bash
|
||||||
# Alias for --fail
|
# Alias for --fail
|
||||||
GITVER_FAIL=true
|
GITVER_FAIL=true
|
||||||
```
|
```
|
||||||
@ -60,12 +143,12 @@ GITVER_FAIL=true
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run -mod=vendor git.rootprojects.org/root/go-gitver version
|
go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 version
|
||||||
```
|
```
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
@ -73,43 +156,43 @@ go run -mod=vendor git.rootprojects.org/root/go-gitver version
|
|||||||
See `examples/basic`
|
See `examples/basic`
|
||||||
|
|
||||||
1. Create a `tools` package in your project
|
1. Create a `tools` package in your project
|
||||||
2. Guard it against regular builds with `// build +tools`
|
2. Guard it against regular builds with `// +build tools`
|
||||||
3. Include `_ "git.rootprojects.org/root/go-gitver"` in the imports
|
3. Include `_ "git.rootprojects.org/root/go-gitver/v2"` in the imports
|
||||||
4. Declare `var GitRev, GitVersion, GitTimestamp string` in your `package main`
|
4. Declare `var commit, version, date string` in your `package main`
|
||||||
5. Include `//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver` as well
|
5. Include `//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2` as well
|
||||||
|
|
||||||
`tools/tools.go`:
|
`tools/tools.go`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// build +tools
|
// +build tools
|
||||||
|
|
||||||
// This is a dummy package for build tooling
|
// This is a dummy package for build tooling
|
||||||
package tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "git.rootprojects.org/root/go-gitver"
|
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
`main.go`:
|
`main.go`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GitRev = "0000000"
|
commit = "0000000"
|
||||||
GitVersion = "v0.0.0-pre0+0000000"
|
version = "0.0.0-pre0+0000000"
|
||||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
date = "0000-00-00T00:00:00+0000"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println(GitRev)
|
fmt.Println(commit)
|
||||||
fmt.Println(GitVersion)
|
fmt.Println(version)
|
||||||
fmt.Println(GitTimestamp)
|
fmt.Println(date)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -117,7 +200,7 @@ If you're using `go mod vendor` (which I highly recommend that you do),
|
|||||||
you'd modify the `go:generate` ever so slightly:
|
you'd modify the `go:generate` ever so slightly:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
```
|
```
|
||||||
|
|
||||||
The only reason I didn't do that in the example is that I'd be included
|
The only reason I didn't do that in the example is that I'd be included
|
||||||
@ -125,7 +208,7 @@ the repository in itself and that would be... weird.
|
|||||||
|
|
||||||
# Why a tools package?
|
# Why a tools package?
|
||||||
|
|
||||||
> import "git.rootprojects.org/root/go-gitver" is a program, not an importable package
|
> import "git.rootprojects.org/root/go-gitver/v2" is a program, not an importable package
|
||||||
|
|
||||||
Having a tools package with a build tag that you don't use is a nice way to add exact
|
Having a tools package with a build tag that you don't use is a nice way to add exact
|
||||||
versions of a command package used for tooling to your `go.mod` with `go mod tidy`,
|
versions of a command package used for tooling to your `go.mod` with `go mod tidy`,
|
||||||
@ -159,3 +242,20 @@ Shows the most recent commit.
|
|||||||
git rev-parse HEAD
|
git rev-parse HEAD
|
||||||
# 0000000000000000000000000000000000000000
|
# 0000000000000000000000000000000000000000
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Errors
|
||||||
|
|
||||||
|
### cannot find package "."
|
||||||
|
|
||||||
|
```txt
|
||||||
|
package git.rootprojects.org/root/go-gitver/v2: cannot find package "." in:
|
||||||
|
/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver/v2
|
||||||
|
cmd/example/example.go:1: running "go": exit status 1
|
||||||
|
```
|
||||||
|
|
||||||
|
You forgot to update deps and re-vendor:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy
|
||||||
|
go mod vendor
|
||||||
|
```
|
||||||
|
@ -20,10 +20,12 @@ These are the instructions that someone cloning the repo might use.
|
|||||||
```bash
|
```bash
|
||||||
go generate -mod=vendor ./...
|
go generate -mod=vendor ./...
|
||||||
go build -mod=vendor -o hello *.go
|
go build -mod=vendor -o hello *.go
|
||||||
|
./hello
|
||||||
|
./hello --version
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: If the source is distributed in a non-git tarball then
|
Note: If the source is distributed in a non-git tarball then
|
||||||
`generated-version.go` will not be output, and whatever
|
`version-generated.go` will not be output, and whatever
|
||||||
version info is in `package main` will remain as-is.
|
version info is in `package main` will remain as-is.
|
||||||
|
|
||||||
If you would prefer the build process to fail (i.e. in a CI/CD pipeline),
|
If you would prefer the build process to fail (i.e. in a CI/CD pipeline),
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
module example.com/hello
|
module example.com/hello
|
||||||
|
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
|
require git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -8,9 +8,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GitRev = "0000000"
|
commit = "0000000"
|
||||||
GitVersion = "v0.0.0-pre0+0000000"
|
version = "0.0.0-pre0+0000000"
|
||||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
date = "0000-00-00T00:00:00+0000"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -18,9 +18,9 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *showVersion {
|
if *showVersion {
|
||||||
fmt.Println(GitRev)
|
fmt.Println(commit)
|
||||||
fmt.Println(GitVersion)
|
fmt.Println(version)
|
||||||
fmt.Println(GitTimestamp)
|
fmt.Println(date)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// build +tools
|
// +build tools
|
||||||
|
|
||||||
// This is a dummy package for build tooling
|
// This is a dummy package for build tooling
|
||||||
package tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "git.rootprojects.org/root/go-gitver"
|
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
)
|
)
|
||||||
|
25
examples/no-tools/README.md
Normal file
25
examples/no-tools/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Example
|
||||||
|
|
||||||
|
Prints the version or a nice message
|
||||||
|
|
||||||
|
# Doesn't have a separate tools package
|
||||||
|
|
||||||
|
This is just like `examples/basic`,
|
||||||
|
but it uses a normal file with a build tag
|
||||||
|
rather than a tools package.
|
||||||
|
|
||||||
|
See `examples/basic` for more details.
|
||||||
|
|
||||||
|
# Demo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy
|
||||||
|
go mod vendor
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate -mod=vendor ./...
|
||||||
|
go build -mod=vendor -o hello *.go
|
||||||
|
./hello
|
||||||
|
./hello --version
|
||||||
|
```
|
5
examples/no-tools/go.mod
Normal file
5
examples/no-tools/go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module example.com/hello
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
28
examples/no-tools/main.go
Normal file
28
examples/no-tools/main.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
commit = "0000000"
|
||||||
|
version = "0.0.0-pre0+0000000"
|
||||||
|
date = "0000-00-00T00:00:00+0000"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
showVersion := flag.Bool("version", false, "Print version and exit")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *showVersion {
|
||||||
|
fmt.Println(commit)
|
||||||
|
fmt.Println(version)
|
||||||
|
fmt.Println(date)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
}
|
6
examples/no-tools/tools.go
Normal file
6
examples/no-tools/tools.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// +build tools
|
||||||
|
|
||||||
|
// This is a dummy file for build tooling
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "git.rootprojects.org/root/go-gitver/v2"
|
24
examples/special-name/README.md
Normal file
24
examples/special-name/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Example
|
||||||
|
|
||||||
|
Prints the version or a nice message
|
||||||
|
|
||||||
|
# Doesn't have a separate tools package
|
||||||
|
|
||||||
|
This is just like `examples/sub-package` except that its `//go:generate` is in `main.go`
|
||||||
|
and it outputs `./version/zversion.go` instead of `xversion.go`.
|
||||||
|
|
||||||
|
See `examples/basic` for more details.
|
||||||
|
|
||||||
|
# Demo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy
|
||||||
|
go mod vendor
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate -mod=vendor ./...
|
||||||
|
go build -mod=vendor -o hello *.go
|
||||||
|
./hello
|
||||||
|
./hello --version
|
||||||
|
```
|
5
examples/special-name/go.mod
Normal file
5
examples/special-name/go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module example.com/hello
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
24
examples/special-name/main.go
Normal file
24
examples/special-name/main.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --package version --outfile ./version/zversion.go
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"example.com/hello/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
showVersion := flag.Bool("version", false, "Print version and exit")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *showVersion {
|
||||||
|
fmt.Println(version.Commit())
|
||||||
|
fmt.Println(version.Version())
|
||||||
|
fmt.Println(version.Date())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
}
|
8
examples/special-name/tools/tools.go
Normal file
8
examples/special-name/tools/tools.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// +build tools
|
||||||
|
|
||||||
|
// This is a dummy package for build tooling
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
|
)
|
22
examples/special-name/version/version.go
Normal file
22
examples/special-name/version/version.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
var (
|
||||||
|
commit = "0000000"
|
||||||
|
version = "0.0.0-pre0+0000000"
|
||||||
|
date = "0000-00-00T00:00:00+0000"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Commit returns the git commit reference
|
||||||
|
func Commit() string {
|
||||||
|
return commit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the git version, without the leading 'v'
|
||||||
|
func Version() string {
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Date returns the ISO-formatted date string
|
||||||
|
func Date() string {
|
||||||
|
return date
|
||||||
|
}
|
24
examples/sub-package/README.md
Normal file
24
examples/sub-package/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Example
|
||||||
|
|
||||||
|
Prints the version or a nice message
|
||||||
|
|
||||||
|
# Put version in its own packge
|
||||||
|
|
||||||
|
This is just like `examples/basic`,
|
||||||
|
but it uses the package name `version` instead of `main`.
|
||||||
|
|
||||||
|
See `examples/basic` for more details.
|
||||||
|
|
||||||
|
# Demo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy
|
||||||
|
go mod vendor
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate -mod=vendor ./...
|
||||||
|
go build -mod=vendor -o hello *.go
|
||||||
|
./hello
|
||||||
|
./hello --version
|
||||||
|
```
|
5
examples/sub-package/go.mod
Normal file
5
examples/sub-package/go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module example.com/hello
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
22
examples/sub-package/main.go
Normal file
22
examples/sub-package/main.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"example.com/hello/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
showVersion := flag.Bool("version", false, "Print version and exit")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *showVersion {
|
||||||
|
fmt.Println(version.Commit())
|
||||||
|
fmt.Println(version.Version())
|
||||||
|
fmt.Println(version.Date())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
}
|
8
examples/sub-package/tools/tools.go
Normal file
8
examples/sub-package/tools/tools.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// +build tools
|
||||||
|
|
||||||
|
// This is a dummy package for build tooling
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
|
)
|
24
examples/sub-package/version/version.go
Normal file
24
examples/sub-package/version/version.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --package version
|
||||||
|
|
||||||
|
package version
|
||||||
|
|
||||||
|
var (
|
||||||
|
commit = "0000000"
|
||||||
|
version = "0.0.0-pre0+0000000"
|
||||||
|
date = "0000-00-00T00:00:00+0000"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Commit returns the git commit reference
|
||||||
|
func Commit() string {
|
||||||
|
return commit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the git version, without the leading 'v'
|
||||||
|
func Version() string {
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Date returns the ISO-formatted date string
|
||||||
|
func Date() string {
|
||||||
|
return date
|
||||||
|
}
|
189
gitver.go
189
gitver.go
@ -1,4 +1,4 @@
|
|||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -6,46 +6,35 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/format"
|
"go/format"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.rootprojects.org/root/go-gitver/v2/gitver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var commit, version, date string
|
||||||
var exitCode int
|
var exitCode int
|
||||||
var exactVer *regexp.Regexp
|
var verFile = "xversion.go"
|
||||||
var gitVer *regexp.Regexp
|
|
||||||
var verFile = "generated-version.go"
|
|
||||||
|
|
||||||
var (
|
|
||||||
GitRev = "0000000"
|
|
||||||
GitVersion = "v0.0.0-pre0+g0000000"
|
|
||||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// exactly vX.Y.Z (go-compatible semver)
|
|
||||||
exactVer = regexp.MustCompile(`^v\d+\.\d+\.\d+$`)
|
|
||||||
|
|
||||||
// vX.Y.Z-n-g0000000 git post-release, semver prerelease
|
|
||||||
// vX.Y.Z-dirty git post-release, semver prerelease
|
|
||||||
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
pkg := "main"
|
||||||
|
|
||||||
args := os.Args[1:]
|
args := os.Args[1:]
|
||||||
for i := range args {
|
for i := range args {
|
||||||
arg := args[i]
|
arg := args[i]
|
||||||
if "-f" == arg || "--fail" == arg {
|
if "-f" == arg || "--fail" == arg {
|
||||||
exitCode = 1
|
exitCode = 1
|
||||||
|
} else if ("--outfile" == arg || "-o" == arg) && len(args) > i+1 {
|
||||||
|
verFile = args[i+1]
|
||||||
|
args[i+1] = ""
|
||||||
|
} else if "--package" == arg && len(args) > i+1 {
|
||||||
|
pkg = args[i+1]
|
||||||
|
args[i+1] = ""
|
||||||
} else if "-V" == arg || "version" == arg || "-version" == arg || "--version" == arg {
|
} else if "-V" == arg || "version" == arg || "-version" == arg || "--version" == arg {
|
||||||
fmt.Println(GitRev)
|
fmt.Println(commit)
|
||||||
fmt.Println(GitVersion)
|
fmt.Println(version)
|
||||||
fmt.Println(GitTimestamp)
|
fmt.Println(date)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,31 +42,30 @@ func main() {
|
|||||||
exitCode = 1
|
exitCode = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
desc, err := gitDesc()
|
v, err := gitver.ExecAndParse()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
log.Fatalf("Failed to get git version: %s\n", err)
|
fmt.Fprintf(os.Stderr, "Failed to get git version: %s\n", err)
|
||||||
os.Exit(exitCode)
|
if exitCode > 0 {
|
||||||
}
|
os.Exit(exitCode)
|
||||||
rev := gitRev()
|
}
|
||||||
ver := semVer(desc)
|
v = &gitver.Versions{
|
||||||
ts, err := gitTimestamp(desc)
|
Timestamp: time.Now(),
|
||||||
if nil != err {
|
}
|
||||||
ts = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
v := struct {
|
|
||||||
Timestamp string
|
|
||||||
Version string
|
|
||||||
GitRev string
|
|
||||||
}{
|
|
||||||
Timestamp: ts.Format(time.RFC3339),
|
|
||||||
Version: ver,
|
|
||||||
GitRev: rev,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create or overwrite the go file from template
|
// Create or overwrite the go file from template
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := versionTpl.Execute(&buf, v); nil != err {
|
if err := versionTpl.Execute(&buf, struct {
|
||||||
|
Package string
|
||||||
|
Timestamp string
|
||||||
|
Version string
|
||||||
|
Commit string
|
||||||
|
}{
|
||||||
|
Package: pkg,
|
||||||
|
Timestamp: v.Timestamp.Format(time.RFC3339),
|
||||||
|
Version: v.Version,
|
||||||
|
Commit: v.Rev,
|
||||||
|
}); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,110 +86,19 @@ func main() {
|
|||||||
if err := f.Close(); nil != err {
|
if err := f.Close(); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func gitDesc() (string, error) {
|
|
||||||
args := strings.Split("git describe --tags --dirty --always", " ")
|
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if nil != err {
|
|
||||||
// Don't panic, just carry on
|
|
||||||
//out = []byte("v0.0.0-0-g0000000")
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(out)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func gitRev() string {
|
|
||||||
args := strings.Split("git rev-parse HEAD", " ")
|
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if nil != err {
|
|
||||||
fmt.Fprintf(os.Stderr,
|
|
||||||
"\nUnexpected Error\n\n"+
|
|
||||||
"Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+
|
|
||||||
"Please include the following:\n\n"+
|
|
||||||
"Command: %s\n"+
|
|
||||||
"Output: %s\n"+
|
|
||||||
"Error: %s\n"+
|
|
||||||
"\nPlease and Thank You.\n\n", strings.Join(args, " "), out, err)
|
|
||||||
os.Exit(exitCode)
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
func semVer(desc string) string {
|
|
||||||
if exactVer.MatchString(desc) {
|
|
||||||
// v1.0.0
|
|
||||||
return desc
|
|
||||||
}
|
|
||||||
|
|
||||||
if !gitVer.MatchString(desc) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// (v1.0).(0)(-(1))(-(g0000000))(-(dirty))
|
|
||||||
vers := gitVer.FindStringSubmatch(desc)
|
|
||||||
patch, err := strconv.Atoi(vers[2])
|
|
||||||
if nil != err {
|
|
||||||
fmt.Fprintf(os.Stderr,
|
|
||||||
"\nUnexpected Error\n\n"+
|
|
||||||
"Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+
|
|
||||||
"Please include the following:\n\n"+
|
|
||||||
"git description: %s\n"+
|
|
||||||
"RegExp: %#v\n"+
|
|
||||||
"Error: %s\n"+
|
|
||||||
"\nPlease and Thank You.\n\n", desc, gitVer, err)
|
|
||||||
os.Exit(exitCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1.0.1-pre1
|
|
||||||
// v1.0.1-pre1+g0000000
|
|
||||||
// v1.0.1-pre0+dirty
|
|
||||||
// v1.0.1-pre0+g0000000-dirty
|
|
||||||
if "" == vers[4] {
|
|
||||||
vers[4] = "0"
|
|
||||||
}
|
|
||||||
ver := fmt.Sprintf("%s.%d-pre%s", vers[1], patch+1, vers[4])
|
|
||||||
if "" != vers[6] || "dirty" == vers[8] {
|
|
||||||
ver += "+"
|
|
||||||
if "" != vers[6] {
|
|
||||||
ver += vers[6]
|
|
||||||
if "" != vers[8] {
|
|
||||||
ver += "-"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ver += vers[8]
|
|
||||||
}
|
|
||||||
|
|
||||||
return ver
|
|
||||||
}
|
|
||||||
|
|
||||||
func gitTimestamp(desc string) (time.Time, error) {
|
|
||||||
args := []string{
|
|
||||||
"git",
|
|
||||||
"show", desc,
|
|
||||||
"--format=%cd",
|
|
||||||
"--date=format:%Y-%m-%dT%H:%M:%SZ%z",
|
|
||||||
"--no-patch",
|
|
||||||
}
|
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if nil != err {
|
|
||||||
// a dirty desc was probably used
|
|
||||||
return time.Time{}, err
|
|
||||||
}
|
|
||||||
return time.Parse(time.RFC3339, strings.TrimSpace(string(out)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var versionTpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
|
var versionTpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
|
||||||
package main
|
package {{ .Package }}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
GitRev = "{{ .GitRev }}"
|
{{ if .Commit -}}
|
||||||
if "" != "{{ .Version }}" {
|
commit = "{{ .Commit }}"
|
||||||
GitVersion = "{{ .Version }}"
|
{{ end -}}
|
||||||
}
|
{{ if .Version -}}
|
||||||
GitTimestamp = "{{ .Timestamp }}"
|
version = "{{ .Version }}"
|
||||||
|
{{ end -}}
|
||||||
|
date = "{{ .Timestamp }}"
|
||||||
}
|
}
|
||||||
`))
|
`))
|
||||||
|
154
gitver/gitver.go
Normal file
154
gitver/gitver.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package gitver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var exactVer *regexp.Regexp
|
||||||
|
var gitVer *regexp.Regexp
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// exactly vX.Y.Z (go-compatible semver)
|
||||||
|
exactVer = regexp.MustCompile(`^v\d+\.\d+\.\d+$`)
|
||||||
|
|
||||||
|
// vX.Y.Z-n-g0000000 git post-release, semver prerelease
|
||||||
|
// vX.Y.Z-dirty git post-release, semver prerelease
|
||||||
|
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Versions describes the various version properties
|
||||||
|
type Versions struct {
|
||||||
|
Timestamp time.Time
|
||||||
|
Version string
|
||||||
|
Rev string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecAndParse will run git and parse the output
|
||||||
|
func ExecAndParse() (*Versions, error) {
|
||||||
|
desc, err := gitDesc()
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rev, err := gitRev()
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ver, err := semVer(desc)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ts, err := gitTimestamp(desc)
|
||||||
|
if nil != err {
|
||||||
|
ts = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Versions{
|
||||||
|
Timestamp: ts,
|
||||||
|
Version: ver,
|
||||||
|
Rev: rev,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitDesc() (string, error) {
|
||||||
|
args := strings.Split("git describe --tags --dirty --always", " ")
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if nil != err {
|
||||||
|
// Don't panic, just carry on
|
||||||
|
//out = []byte("0.0.0-0-g0000000")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(out)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitRev() (string, error) {
|
||||||
|
args := strings.Split("git rev-parse HEAD", " ")
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if nil != err {
|
||||||
|
return "", fmt.Errorf("\nUnexpected Error\n\n"+
|
||||||
|
"Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+
|
||||||
|
"Please include the following:\n\n"+
|
||||||
|
"Command: %s\n"+
|
||||||
|
"Output: %s\n"+
|
||||||
|
"Error: %s\n"+
|
||||||
|
"\nPlease and Thank You.\n\n", strings.Join(args, " "), out, err)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(out)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func semVer(desc string) (string, error) {
|
||||||
|
if exactVer.MatchString(desc) {
|
||||||
|
// v1.0.0
|
||||||
|
return strings.TrimPrefix(desc, "v"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !gitVer.MatchString(desc) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// (v1.0).(0)(-(1))(-(g0000000))(-(dirty))
|
||||||
|
vers := gitVer.FindStringSubmatch(desc)
|
||||||
|
patch, err := strconv.Atoi(vers[2])
|
||||||
|
if nil != err {
|
||||||
|
return "", fmt.Errorf("\nUnexpected Error\n\n"+
|
||||||
|
"Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+
|
||||||
|
"Please include the following:\n\n"+
|
||||||
|
"git description: %s\n"+
|
||||||
|
"RegExp: %#v\n"+
|
||||||
|
"Error: %s\n"+
|
||||||
|
"\nPlease and Thank You.\n\n", desc, gitVer, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// v1.0.1-pre1
|
||||||
|
// v1.0.1-pre1+g0000000
|
||||||
|
// v1.0.1-pre0+dirty
|
||||||
|
// v1.0.1-pre0+g0000000-dirty
|
||||||
|
if "" == vers[4] {
|
||||||
|
vers[4] = "0"
|
||||||
|
}
|
||||||
|
ver := fmt.Sprintf("%s.%d-pre%s", vers[1], patch+1, vers[4])
|
||||||
|
if "" != vers[6] || "dirty" == vers[8] {
|
||||||
|
ver += "+"
|
||||||
|
if "" != vers[6] {
|
||||||
|
ver += vers[6]
|
||||||
|
if "" != vers[8] {
|
||||||
|
ver += "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ver += vers[8]
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimPrefix(ver, "v"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gitTimestamp(desc string) (time.Time, error) {
|
||||||
|
// Other options:
|
||||||
|
//
|
||||||
|
// Commit Date
|
||||||
|
// git log -1 --format=%cd --date=format:%Y-%m-%dT%H:%M:%SZ%z
|
||||||
|
//
|
||||||
|
// Author Date
|
||||||
|
// git log -1 --format=%ad --date=format:%Y-%m-%dT%H:%M:%SZ%z
|
||||||
|
//
|
||||||
|
// I think I chose this because it would account for dirty-ness better... maybe?
|
||||||
|
args := []string{
|
||||||
|
"git",
|
||||||
|
"show", desc,
|
||||||
|
"--format=%cd",
|
||||||
|
"--date=format:%Y-%m-%dT%H:%M:%SZ%z",
|
||||||
|
"--no-patch",
|
||||||
|
}
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if nil != err {
|
||||||
|
// a dirty desc was probably used
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
return time.Parse(time.RFC3339, strings.TrimSpace(string(out)))
|
||||||
|
}
|
2
go.mod
2
go.mod
@ -1,3 +1,3 @@
|
|||||||
module git.rootprojects.org/root/go-gitver
|
module git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
go 1.12
|
go 1.12
|
||||||
|
9
version.go
Normal file
9
version.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// use recently generated version info as a fallback
|
||||||
|
// for when git isn't present (i.e. go run <url>)
|
||||||
|
func init() {
|
||||||
|
commit = "37c1fd4b5694fd62c9f0d6ad1df47d938accbeec"
|
||||||
|
version = "2.0.0-pre1-dirty"
|
||||||
|
date = "2020-10-10T16:05:59-06:00"
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user