From 791cd2a53210cb74e5ef49ca208fd81ad9a9c339 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Tue, 22 Mar 2022 15:46:01 -0500 Subject: [PATCH] Initial Commit Signed-off-by: jolheiser --- .gitignore | 1 + .woodpecker.yml | 10 +++++++ LICENSE | 19 ++++++++++++ README.md | 9 ++++++ gitinfo.go | 66 +++++++++++++++++++++++++++++++++++++++++ gitinfo_test.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 5 ++++ go.sum | 2 ++ 8 files changed, 191 insertions(+) create mode 100644 .gitignore create mode 100644 .woodpecker.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 gitinfo.go create mode 100644 gitinfo_test.go create mode 100644 go.mod create mode 100644 go.sum diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..e16513c --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,10 @@ +clone: + git: + image: woodpeckerci/plugin-git:next + +pipeline: + compliance: + image: golang:1.18 + commands: + - go test -race ./... + - go vet ./... \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ec2045e --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2022 John Olheiser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..46124cc --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# gitinfo + +[![Go Reference](https://pkg.go.dev/badge/go.jolheiser.com/gitinfo.svg)](https://pkg.go.dev/go.jolheiser.com/gitinfo) + +A tiny shim over [debug.BuildInfo](https://pkg.go.dev/runtime/debug#BuildInfo) that extracts Git-specific VCS information. + +## License + +[MIT](LICENSE) \ No newline at end of file diff --git a/gitinfo.go b/gitinfo.go new file mode 100644 index 0000000..5f3001d --- /dev/null +++ b/gitinfo.go @@ -0,0 +1,66 @@ +package gitinfo + +import ( + "errors" + "runtime/debug" + "time" +) + +// GitInfo is the git info for a build +type GitInfo struct { + Revision string + Time time.Time + Modified bool +} + +// MustReadGitInfo returns GitInfo, or dev info when encountering an error +func MustReadGitInfo() *GitInfo { + info, err := ReadGitInfo() + if err != nil { + return &GitInfo{ + Revision: "develop", + Time: time.Now(), + Modified: true, + } + } + return info +} + +// ReadGitInfo returns the GitInfo for a build +func ReadGitInfo() (*GitInfo, error) { + info, ok := readBuildInfo() + if !ok { + return nil, ErrNoBuildInfo + } + + git := &GitInfo{} + var vcs string + for _, setting := range info.Settings { + switch setting.Key { + case "vcs": + vcs = setting.Value + case "vcs.revision": + git.Revision = setting.Value + case "vcs.time": + t, err := time.Parse(time.RFC3339, setting.Value) + if err != nil { + return nil, err + } + git.Time = t + case "vcs.modified": + git.Modified = setting.Value == "true" + } + } + if vcs != "git" { + return nil, ErrNoGit + } + + return git, nil +} + +var ( + readBuildInfo = debug.ReadBuildInfo + + ErrNoBuildInfo = errors.New("could not read build info") + ErrNoGit = errors.New("vcs is not git") +) diff --git a/gitinfo_test.go b/gitinfo_test.go new file mode 100644 index 0000000..7b25e60 --- /dev/null +++ b/gitinfo_test.go @@ -0,0 +1,79 @@ +package gitinfo + +import ( + "errors" + "runtime/debug" + "testing" + "time" + + "github.com/matryer/is" +) + +func TestReadGitInfo(t *testing.T) { + assert := is.New(t) + + readBuildInfo = func() (*debug.BuildInfo, bool) { + return &debug.BuildInfo{ + Settings: []debug.BuildSetting{ + {Key: "vcs", Value: "git"}, + {Key: "vcs.revision", Value: "ad1aef070cf1fd5f2f16701f84703ff1e1dd6738"}, + {Key: "vcs.time", Value: "2022-03-22T19:56:47Z"}, + {Key: "vcs.modified", Value: "true"}, + }, + }, true + } + + expected := &GitInfo{ + Revision: "ad1aef070cf1fd5f2f16701f84703ff1e1dd6738", + Time: time.Date(2022, 3, 22, 19, 56, 47, 0, time.UTC), + Modified: true, + } + + info, err := ReadGitInfo() + assert.NoErr(err) // Should read build info + assert.Equal(info, expected) // GitInfo should match expected +} + +func TestNoBuildInfo(t *testing.T) { + assert := is.New(t) + + readBuildInfo = func() (*debug.BuildInfo, bool) { + return nil, false + } + + _, err := ReadGitInfo() + assert.True(errors.Is(err, ErrNoBuildInfo)) // Should not read build info +} + +func TestNoGit(t *testing.T) { + assert := is.New(t) + + readBuildInfo = func() (*debug.BuildInfo, bool) { + return &debug.BuildInfo{ + Settings: []debug.BuildSetting{ + {Key: "vcs", Value: "svn"}, + }, + }, true + } + + _, err := ReadGitInfo() + assert.True(errors.Is(err, ErrNoGit)) // Should not have git info + + readBuildInfo = func() (*debug.BuildInfo, bool) { + return &debug.BuildInfo{}, true + } + + _, err = ReadGitInfo() + assert.True(errors.Is(err, ErrNoGit)) // Should not have git info +} + +func TestMustReadGitInfo(t *testing.T) { + assert := is.New(t) + + readBuildInfo = func() (*debug.BuildInfo, bool) { + return nil, false + } + + info := MustReadGitInfo() + assert.Equal(info.Revision, "develop") // revision should be "develop" +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..03f6bde --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module go.jolheiser.com/gitinfo + +go 1.18 + +require github.com/matryer/is v1.4.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ddd6bbf --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=