github.phpd.cn/goreleaser/goreleaser@v0.92.0/internal/pipe/git/git.go (about) 1 package git 2 3 import ( 4 "os/exec" 5 "regexp" 6 "strings" 7 8 "github.com/apex/log" 9 "github.com/goreleaser/goreleaser/internal/deprecate" 10 "github.com/goreleaser/goreleaser/internal/git" 11 "github.com/goreleaser/goreleaser/internal/pipe" 12 "github.com/goreleaser/goreleaser/internal/tmpl" 13 "github.com/goreleaser/goreleaser/pkg/context" 14 "github.com/pkg/errors" 15 ) 16 17 // Pipe for brew deployment 18 type Pipe struct{} 19 20 func (Pipe) String() string { 21 return "getting and validating git state" 22 } 23 24 // Run the pipe 25 func (Pipe) Run(ctx *context.Context) error { 26 if _, err := exec.LookPath("git"); err != nil { 27 return ErrNoGit 28 } 29 if ctx.Config.Git.ShortHash { 30 deprecate.Notice("git.short_hash") 31 } 32 info, err := getInfo(ctx) 33 if err != nil { 34 return err 35 } 36 ctx.Git = info 37 log.Infof("releasing %s, commit %s", info.CurrentTag, info.Commit) 38 if err := setVersion(ctx); err != nil { 39 return err 40 } 41 return validate(ctx) 42 } 43 44 var fakeInfo = context.GitInfo{ 45 CurrentTag: "v0.0.0", 46 Commit: "none", 47 ShortCommit: "none", 48 FullCommit: "none", 49 } 50 51 func getInfo(ctx *context.Context) (context.GitInfo, error) { 52 if !git.IsRepo() && ctx.Snapshot { 53 log.Warn("accepting to run without a git repo because this is a snapshot") 54 return fakeInfo, nil 55 } 56 if !git.IsRepo() { 57 return context.GitInfo{}, ErrNotRepository 58 } 59 info, err := getGitInfo(ctx) 60 if err != nil && ctx.Snapshot { 61 log.WithError(err).Warn("ignoring errors because this is a snapshot") 62 if info.Commit == "" { 63 info = fakeInfo 64 } 65 return info, nil 66 } 67 return info, err 68 } 69 70 func getGitInfo(ctx *context.Context) (context.GitInfo, error) { 71 short, err := getShortCommit() 72 if err != nil { 73 return context.GitInfo{}, errors.Wrap(err, "couldn't get current commit") 74 } 75 full, err := getFullCommit() 76 if err != nil { 77 return context.GitInfo{}, errors.Wrap(err, "couldn't get current commit") 78 } 79 var commit = full 80 if ctx.Config.Git.ShortHash { 81 commit = short 82 } 83 url, err := getURL() 84 if err != nil { 85 return context.GitInfo{}, errors.Wrap(err, "couldn't get remote URL") 86 } 87 tag, err := getTag() 88 if err != nil { 89 return context.GitInfo{ 90 Commit: commit, 91 FullCommit: full, 92 ShortCommit: short, 93 URL: url, 94 CurrentTag: "v0.0.0", 95 }, ErrNoTag 96 } 97 return context.GitInfo{ 98 CurrentTag: tag, 99 Commit: commit, 100 FullCommit: full, 101 ShortCommit: short, 102 URL: url, 103 }, nil 104 } 105 106 func setVersion(ctx *context.Context) error { 107 if ctx.Snapshot { 108 snapshotName, err := tmpl.New(ctx).Apply(ctx.Config.Snapshot.NameTemplate) 109 if err != nil { 110 return errors.Wrap(err, "failed to generate snapshot name") 111 } 112 ctx.Version = snapshotName 113 return nil 114 } 115 // removes usual `v` prefix 116 ctx.Version = strings.TrimPrefix(ctx.Git.CurrentTag, "v") 117 return nil 118 } 119 120 func validate(ctx *context.Context) error { 121 if ctx.Snapshot { 122 return pipe.ErrSnapshotEnabled 123 } 124 if ctx.SkipValidate { 125 return pipe.ErrSkipValidateEnabled 126 } 127 out, err := git.Run("status", "--porcelain") 128 if strings.TrimSpace(out) != "" || err != nil { 129 return ErrDirty{status: out} 130 } 131 if !regexp.MustCompile("^[0-9.]+").MatchString(ctx.Version) { 132 return ErrInvalidVersionFormat{version: ctx.Version} 133 } 134 _, err = git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag)) 135 if err != nil { 136 return ErrWrongRef{ 137 commit: ctx.Git.Commit, 138 tag: ctx.Git.CurrentTag, 139 } 140 } 141 return nil 142 } 143 144 func getShortCommit() (string, error) { 145 return git.Clean(git.Run("show", "--format='%h'", "HEAD")) 146 } 147 148 func getFullCommit() (string, error) { 149 return git.Clean(git.Run("show", "--format='%H'", "HEAD")) 150 } 151 152 func getTag() (string, error) { 153 return git.Clean(git.Run("describe", "--tags", "--abbrev=0")) 154 } 155 156 func getURL() (string, error) { 157 return git.Clean(git.Run("ls-remote", "--get-url")) 158 }