git-sv/app/commands/utils.go

221 lines
4.7 KiB
Go

package commands
import (
"fmt"
"io/fs"
"os"
"strings"
"time"
"github.com/Masterminds/semver/v3"
"github.com/thegeeklab/git-sv/app"
"github.com/thegeeklab/git-sv/sv"
)
func getTagCommits(gsv app.GitSV, tag string) ([]sv.CommitLog, error) {
prev, _, err := getTags(gsv, tag)
if err != nil {
return nil, err
}
return gsv.Log(app.NewLogRange(app.TagRange, prev, tag))
}
func getTags(gsv app.GitSV, tag string) (string, app.Tag, error) {
tags, err := gsv.Tags()
if err != nil {
return "", app.Tag{}, err
}
index := find(tag, tags)
if index < 0 {
return "", app.Tag{}, fmt.Errorf("%w: %s not found, check tag filter", errUnknownTag, tag)
}
previousTag := ""
if index > 0 {
previousTag = tags[index-1].Name
}
return previousTag, tags[index], nil
}
func find(tag string, tags []app.Tag) int {
for i := 0; i < len(tags); i++ {
if tag == tags[i].Name {
return i
}
}
return -1
}
func logRange(gsv app.GitSV, rangeFlag, startFlag, endFlag string) (app.LogRange, error) {
switch rangeFlag {
case string(app.TagRange):
return app.NewLogRange(app.TagRange, str(startFlag, gsv.LastTag()), endFlag), nil
case string(app.DateRange):
return app.NewLogRange(app.DateRange, startFlag, endFlag), nil
case string(app.HashRange):
return app.NewLogRange(app.HashRange, startFlag, endFlag), nil
default:
return app.LogRange{}, fmt.Errorf(
"%w: %s, expected: %s, %s or %s",
errInvalidRange,
rangeFlag,
app.TagRange,
app.DateRange,
app.HashRange,
)
}
}
func str(value, defaultValue string) string {
if value != "" {
return value
}
return defaultValue
}
func getTagVersionInfo(gsv app.GitSV, tag string) (*semver.Version, time.Time, []sv.CommitLog, error) {
tagVersion, _ := sv.ToVersion(tag)
previousTag, currentTag, err := getTags(gsv, tag)
if err != nil {
return nil, time.Time{}, nil, fmt.Errorf("error listing tags: %w", err)
}
commits, err := gsv.Log(app.NewLogRange(app.TagRange, previousTag, tag))
if err != nil {
return nil, time.Time{}, nil, fmt.Errorf("error getting git log from tag: %s: %w", tag, err)
}
return tagVersion, currentTag.Date, commits, nil
}
func getNextVersionInfo(
gsv app.GitSV, semverProcessor sv.CommitProcessor,
) (*semver.Version, bool, time.Time, []sv.CommitLog, error) {
lastTag := gsv.LastTag()
commits, err := gsv.Log(app.NewLogRange(app.TagRange, lastTag, ""))
if err != nil {
return nil, false, time.Time{}, nil, fmt.Errorf("error getting git log: %w", err)
}
currentVer, _ := sv.ToVersion(lastTag)
version, updated := semverProcessor.NextVersion(currentVer, commits)
return version, updated, time.Now(), commits, nil
}
func getCommitType(cfg *app.Config, p sv.MessageProcessor, input string) (string, error) {
if input == "" {
t, err := promptType(cfg.CommitMessage.Types)
return t.Type, err
}
return input, p.ValidateType(input)
}
func getCommitScope(cfg *app.Config, p sv.MessageProcessor, input string, noScope bool) (string, error) {
if input == "" && !noScope {
return promptScope(cfg.CommitMessage.Scope.Values)
}
return input, p.ValidateScope(input)
}
func getCommitDescription(p sv.MessageProcessor, input string) (string, error) {
if input == "" {
return promptSubject()
}
return input, p.ValidateDescription(input)
}
func getCommitBody(noBody bool) (string, error) {
if noBody {
return "", nil
}
var fullBody strings.Builder
for body, err := promptBody(); body != "" || err != nil; body, err = promptBody() {
if err != nil {
return "", err
}
if fullBody.Len() > 0 {
fullBody.WriteString("\n")
}
if body != "" {
fullBody.WriteString(body)
}
}
return fullBody.String(), nil
}
func getCommitIssue(cfg *app.Config, p sv.MessageProcessor, branch string, noIssue bool) (string, error) {
branchIssue, err := p.IssueID(branch)
if err != nil {
return "", err
}
if cfg.CommitMessage.IssueFooterConfig().Key == "" || cfg.CommitMessage.Issue.Regex == "" {
return "", nil
}
if noIssue {
return branchIssue, nil
}
return promptIssueID("issue id", cfg.CommitMessage.Issue.Regex, branchIssue)
}
func getCommitBreakingChange(noBreaking bool, input string) (string, error) {
if noBreaking {
return "", nil
}
if strings.TrimSpace(input) != "" {
return input, nil
}
hasBreakingChanges, err := promptConfirm("has breaking change?")
if err != nil {
return "", err
}
if !hasBreakingChanges {
return "", nil
}
return promptBreakingChanges()
}
func readFile(filepath string) (string, error) {
f, err := os.ReadFile(filepath)
if err != nil {
return "", err
}
return string(f), nil
}
func appendOnFile(message, filepath string, permissions fs.FileMode) error {
f, err := os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY, permissions)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(message)
return err
}