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  }