github.com/szyn/goreleaser@v0.76.1-0.20180517112710-333da09a1297/pipeline/git/git.go (about)

     1  package git
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"regexp"
     7  	"strings"
     8  	"text/template"
     9  	"time"
    10  
    11  	"github.com/apex/log"
    12  	"github.com/goreleaser/goreleaser/context"
    13  	"github.com/goreleaser/goreleaser/internal/git"
    14  	"github.com/goreleaser/goreleaser/pipeline"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  // Pipe for brew deployment
    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  	info, err := getInfo(ctx)
    28  	if err != nil {
    29  		return err
    30  	}
    31  	ctx.Git = info
    32  	log.Infof("releasing %s, commit %s", info.CurrentTag, info.Commit)
    33  	if err := setVersion(ctx); err != nil {
    34  		return err
    35  	}
    36  	return validate(ctx)
    37  }
    38  
    39  var fakeInfo = context.GitInfo{
    40  	CurrentTag: "v0.0.0",
    41  	Commit:     "none",
    42  }
    43  
    44  func getInfo(ctx *context.Context) (context.GitInfo, error) {
    45  	if !git.IsRepo() && ctx.Snapshot {
    46  		log.Warn("accepting to run without a git repo because this is a snapshot")
    47  		return fakeInfo, nil
    48  	}
    49  	if !git.IsRepo() {
    50  		return context.GitInfo{}, ErrNotRepository
    51  	}
    52  	info, err := getGitInfo(ctx)
    53  	if err != nil && ctx.Snapshot {
    54  		log.WithError(err).Warn("ignoring errors because this is a snapshot")
    55  		if info.Commit == "" {
    56  			info = fakeInfo
    57  		}
    58  		return info, nil
    59  	}
    60  	return info, err
    61  }
    62  
    63  func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
    64  	commit, err := getCommit(ctx)
    65  	if err != nil {
    66  		return context.GitInfo{}, errors.Wrap(err, "couldn't get current commit")
    67  	}
    68  	tag, err := getTag()
    69  	if err != nil {
    70  		return context.GitInfo{
    71  			Commit:     commit,
    72  			CurrentTag: "v0.0.0",
    73  		}, ErrNoTag
    74  	}
    75  	return context.GitInfo{
    76  		CurrentTag: tag,
    77  		Commit:     commit,
    78  	}, nil
    79  }
    80  
    81  func setVersion(ctx *context.Context) error {
    82  	if ctx.Snapshot {
    83  		snapshotName, err := getSnapshotName(ctx)
    84  		if err != nil {
    85  			return errors.Wrap(err, "failed to generate snapshot name")
    86  		}
    87  		ctx.Version = snapshotName
    88  		return nil
    89  	}
    90  	// removes usual `v` prefix
    91  	ctx.Version = strings.TrimPrefix(ctx.Git.CurrentTag, "v")
    92  	return nil
    93  }
    94  
    95  type snapshotNameData struct {
    96  	Commit    string
    97  	Tag       string
    98  	Timestamp int64
    99  }
   100  
   101  func getSnapshotName(ctx *context.Context) (string, error) {
   102  	tmpl, err := template.New("snapshot").Parse(ctx.Config.Snapshot.NameTemplate)
   103  	var out bytes.Buffer
   104  	if err != nil {
   105  		return "", err
   106  	}
   107  	var data = snapshotNameData{
   108  		Commit:    ctx.Git.Commit,
   109  		Tag:       ctx.Git.CurrentTag,
   110  		Timestamp: time.Now().Unix(),
   111  	}
   112  	err = tmpl.Execute(&out, data)
   113  	return out.String(), err
   114  }
   115  
   116  func validate(ctx *context.Context) error {
   117  	if ctx.Snapshot {
   118  		return pipeline.ErrSnapshotEnabled
   119  	}
   120  	if ctx.SkipValidate {
   121  		return pipeline.ErrSkipValidateEnabled
   122  	}
   123  	out, err := git.Run("status", "--porcelain")
   124  	if strings.TrimSpace(out) != "" || err != nil {
   125  		return ErrDirty{out}
   126  	}
   127  	if !regexp.MustCompile("^[0-9.]+").MatchString(ctx.Version) {
   128  		return ErrInvalidVersionFormat{ctx.Version}
   129  	}
   130  	_, err = git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag))
   131  	if err != nil {
   132  		return ErrWrongRef{ctx.Git.Commit, ctx.Git.CurrentTag}
   133  	}
   134  	return nil
   135  }
   136  
   137  func getCommit(ctx *context.Context) (string, error) {
   138  	format := "%H"
   139  	if ctx.Config.Git.ShortHash {
   140  		format = "%h"
   141  	}
   142  	return git.Clean(git.Run("show", fmt.Sprintf("--format='%s'", format), "HEAD"))
   143  }
   144  
   145  func getTag() (string, error) {
   146  	return git.Clean(git.Run("describe", "--tags", "--abbrev=0"))
   147  }