github.com/amane3/goreleaser@v0.182.0/internal/pipe/git/git.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/apex/log" 12 13 "github.com/amane3/goreleaser/internal/git" 14 "github.com/amane3/goreleaser/internal/pipe" 15 "github.com/amane3/goreleaser/pkg/context" 16 ) 17 18 // Pipe that sets up git state. 19 type Pipe struct{} 20 21 func (Pipe) String() string { 22 return "getting and validating git state" 23 } 24 25 // Run the pipe. 26 func (Pipe) Run(ctx *context.Context) error { 27 if _, err := exec.LookPath("git"); err != nil { 28 return ErrNoGit 29 } 30 info, err := getInfo(ctx) 31 if err != nil { 32 return err 33 } 34 ctx.Git = info 35 log.Infof("releasing %s, commit %s", info.CurrentTag, info.Commit) 36 ctx.Version = strings.TrimPrefix(ctx.Git.CurrentTag, "v") 37 return validate(ctx) 38 } 39 40 // nolint: gochecknoglobals 41 var fakeInfo = context.GitInfo{ 42 Branch: "none", 43 CurrentTag: "v0.0.0", 44 Commit: "none", 45 ShortCommit: "none", 46 FullCommit: "none", 47 } 48 49 func getInfo(ctx *context.Context) (context.GitInfo, error) { 50 if !git.IsRepo() && ctx.Snapshot { 51 log.Warn("accepting to run without a git repo because this is a snapshot") 52 return fakeInfo, nil 53 } 54 if !git.IsRepo() { 55 return context.GitInfo{}, ErrNotRepository 56 } 57 info, err := getGitInfo() 58 if err != nil && ctx.Snapshot { 59 log.WithError(err).Warn("ignoring errors because this is a snapshot") 60 if info.Commit == "" { 61 info = fakeInfo 62 } 63 return info, nil 64 } 65 return info, err 66 } 67 68 func getGitInfo() (context.GitInfo, error) { 69 branch, err := getBranch() 70 if err != nil { 71 return context.GitInfo{}, fmt.Errorf("couldn't get current branch: %w", err) 72 } 73 short, err := getShortCommit() 74 if err != nil { 75 return context.GitInfo{}, fmt.Errorf("couldn't get current commit: %w", err) 76 } 77 full, err := getFullCommit() 78 if err != nil { 79 return context.GitInfo{}, fmt.Errorf("couldn't get current commit: %w", err) 80 } 81 date, err := getCommitDate() 82 if err != nil { 83 return context.GitInfo{}, fmt.Errorf("couldn't get commit date: %w", err) 84 } 85 url, err := getURL() 86 if err != nil { 87 return context.GitInfo{}, fmt.Errorf("couldn't get remote URL: %w", err) 88 } 89 tag, err := getTag() 90 if err != nil { 91 return context.GitInfo{ 92 Branch: branch, 93 Commit: full, 94 FullCommit: full, 95 ShortCommit: short, 96 CommitDate: date, 97 URL: url, 98 CurrentTag: "v0.0.0", 99 }, ErrNoTag 100 } 101 return context.GitInfo{ 102 Branch: branch, 103 CurrentTag: tag, 104 Commit: full, 105 FullCommit: full, 106 ShortCommit: short, 107 CommitDate: date, 108 URL: url, 109 }, nil 110 } 111 112 func validate(ctx *context.Context) error { 113 if ctx.Snapshot { 114 return pipe.ErrSnapshotEnabled 115 } 116 if ctx.SkipValidate { 117 return pipe.ErrSkipValidateEnabled 118 } 119 out, err := git.Run("status", "--porcelain") 120 if strings.TrimSpace(out) != "" || err != nil { 121 return ErrDirty{status: out} 122 } 123 _, err = git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag)) 124 if err != nil { 125 return ErrWrongRef{ 126 commit: ctx.Git.Commit, 127 tag: ctx.Git.CurrentTag, 128 } 129 } 130 return nil 131 } 132 133 func getBranch() (string, error) { 134 return git.Clean(git.Run("rev-parse", "--abbrev-ref", "HEAD", "--quiet")) 135 } 136 137 func getCommitDate() (time.Time, error) { 138 ct, err := git.Clean(git.Run("show", "--format='%ct'", "HEAD", "--quiet")) 139 if err != nil { 140 return time.Time{}, err 141 } 142 if ct == "" { 143 return time.Time{}, nil 144 } 145 i, err := strconv.ParseInt(ct, 10, 64) 146 if err != nil { 147 return time.Time{}, err 148 } 149 t := time.Unix(i, 0).UTC() 150 return t, nil 151 } 152 153 func getShortCommit() (string, error) { 154 return git.Clean(git.Run("show", "--format='%h'", "HEAD", "--quiet")) 155 } 156 157 func getFullCommit() (string, error) { 158 return git.Clean(git.Run("show", "--format='%H'", "HEAD", "--quiet")) 159 } 160 161 func getTag() (string, error) { 162 var tag string 163 var err error 164 for _, fn := range []func() (string, error){ 165 func() (string, error) { 166 return os.Getenv("GORELEASER_CURRENT_TAG"), nil 167 }, 168 func() (string, error) { 169 return git.Clean(git.Run("tag", "--points-at", "HEAD", "--sort", "-version:creatordate")) 170 }, 171 func() (string, error) { 172 return git.Clean(git.Run("describe", "--tags", "--abbrev=0")) 173 }, 174 } { 175 tag, err = fn() 176 if tag != "" || err != nil { 177 return tag, err 178 } 179 } 180 181 return tag, err 182 } 183 184 func getURL() (string, error) { 185 return git.Clean(git.Run("ls-remote", "--get-url")) 186 }