mirror of
https://github.com/thegeeklab/git-sv.git
synced 2024-11-22 08:20:39 +00:00
221 lines
4.7 KiB
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
|
|
}
|