Skip to content

Commit

Permalink
implement configuration file
Browse files Browse the repository at this point in the history
  • Loading branch information
Songmu committed Aug 20, 2022
1 parent 1649767 commit f316f96
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 24 deletions.
142 changes: 142 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package rcpr

import (
"os"
)

const (
defaultConfigFile = ".rcpr"
defaultConfigContent = `# config file for rcpr in git config format
[rcpr]
`
envReleaseBranch = "RCPR_RELEASE_BRANCH"
envVersionFile = "RCPR_VERSION_FILE"
configReleaseBranch = "rcpr.releaseBranch"
configVersionFile = "rcpr.versionFile"
)

type config struct {
releaseBranch *configValue
versionFile *configValue

c *commander
conf string
}

func newConfig(c *commander) *config {
cfg := &config{conf: defaultConfigFile, c: c}
if rb := os.Getenv(envReleaseBranch); rb != "" {
cfg.releaseBranch = &configValue{
value: rb,
source: srcEnv,
}
} else {
out, _, err := c.gitE("config", "-f", cfg.conf, configReleaseBranch)
if err != nil {
cfg.releaseBranch = &configValue{
value: out,
source: srcConfigFile,
}
}
}

if rb := os.Getenv(envVersionFile); rb != "" {
cfg.releaseBranch = &configValue{
value: rb,
source: srcEnv,
}
} else {
out, _, err := c.gitE("config", "-f", cfg.conf, configVersionFile)
if err != nil {
cfg.releaseBranch = &configValue{
value: out,
source: srcConfigFile,
}
}
}
return cfg
}

func (cfg *config) set(key, value string) error {
if !exists(cfg.conf) {
if err := cfg.initializeFile(); err != nil {
return err
}
}
if value == "" {
value = "-" // value "-" represents null (really?)
}
_, _, err := cfg.c.gitE("config", "-f", cfg.conf, key, value)
if err != nil {
// in this case, config file might be invalid or broken, so retry once.
if err = cfg.initializeFile(); err != nil {
return err
}
_, _, err = cfg.c.gitE("config", "-f", cfg.conf, key, value)
}
return err
}

func (cfg *config) initializeFile() error {
if err := os.RemoveAll(cfg.conf); err != nil {
return err
}
if err := os.WriteFile(cfg.conf, []byte(defaultConfigContent), 0666); err != nil {
return err
}
return nil
}

func (cfg *config) SetRelaseBranch(br string) error {
if err := cfg.set(configReleaseBranch, br); err != nil {
return err
}
cfg.releaseBranch = &configValue{
value: br,
source: srcDetect,
}
return nil
}

func (cfg *config) SetVersionFile(fpath string) error {
if err := cfg.set(configVersionFile, fpath); err != nil {
return err
}
cfg.versionFile = &configValue{
value: fpath,
source: srcDetect,
}
return nil
}

func (cfg *config) RelaseBranch() *configValue {
return cfg.releaseBranch
}

func (cfg *config) VersionFile() *configValue {
return cfg.versionFile
}

type configValue struct {
value string
source configSource
}

func (cv *configValue) String() string {
if cv.value == "-" {
return ""
}
return cv.value
}

func (cv *configValue) Empty() bool {
return cv.String() == ""
}

type configSource int

const (
srcEnv configSource = iota
srcConfigFile
srcDetect
)
75 changes: 51 additions & 24 deletions rcpr.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func printVersion(out io.Writer) error {
type rcpr struct {
c *commander
gh *github.Client
cfg *config
remoteName, owner, repo string
}

Expand All @@ -47,23 +48,25 @@ func (rp *rcpr) latestSemverTag() string {
return ""
}

func (rp *rcpr) initialize(ctx context.Context) error {
func newRcpr(ctx context.Context, c *commander) (*rcpr, error) {
rp := &rcpr{c: c}

var err error
rp.remoteName, err = rp.detectRemote()
if err != nil {
return err
return nil, err
}
remoteURL, _, err := rp.c.gitE("config", "remote."+rp.remoteName+".url")
if err != nil {
return err
return nil, err
}
u, err := parseGitURL(remoteURL)
if err != nil {
return fmt.Errorf("failed to parse remote")
return nil, fmt.Errorf("failed to parse remote")
}
m := strings.Split(strings.TrimPrefix(u.Path, "/"), "/")
if len(m) < 2 {
return fmt.Errorf("failed to detect owner and repo from remote URL")
return nil, fmt.Errorf("failed to detect owner and repo from remote URL")
}
rp.owner = m[0]
repo := m[1]
Expand All @@ -74,20 +77,21 @@ func (rp *rcpr) initialize(ctx context.Context) error {

cli, err := ghClient(ctx, "", u.Hostname())
if err != nil {
return err
return nil, err
}
rp.gh = cli

isShallow, _, err := rp.c.gitE("rev-parse", "--is-shallow-repository")
if err != nil {
return err
return nil, err
}
if isShallow == "true" {
if _, _, err := rp.c.gitE("fetch", "--unshallow"); err != nil {
return err
return nil, err
}
}
return nil
rp.cfg = newConfig(rp.c)
return rp, nil
}

func isRcpr(pr *github.PullRequest) bool {
Expand All @@ -114,10 +118,8 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer) err
}

// main logic follows
rp := &rcpr{
c: &commander{outStream: outStream, errStream: errStream, dir: "."},
}
if err := rp.initialize(ctx); err != nil {
rp, err := newRcpr(ctx, &commander{outStream: outStream, errStream: errStream, dir: "."})
if err != nil {
return err
}

Expand All @@ -133,10 +135,20 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer) err
// XXX: Do I need to take care of past tags with and without v-prefixes?
// It might be good to be able to enforce presence or absence in a configuration file item.

releaseBranch, _ := rp.defaultBranch() // TODO: make release branch configable
var releaseBranch string
if rp.cfg.releaseBranch != nil {
releaseBranch = rp.cfg.releaseBranch.String()
}
if releaseBranch == "" {
releaseBranch = defaultReleaseBranch
releaseBranch, _ := rp.defaultBranch()
if releaseBranch == "" {
releaseBranch = defaultReleaseBranch
}
if err := rp.cfg.SetRelaseBranch(releaseBranch); err != nil {
return err
}
}

branch, _, err := rp.c.gitE("symbolic-ref", "--short", "HEAD")
if err != nil {
return fmt.Errorf("failed to git symbolic-ref: %w", err)
Expand Down Expand Up @@ -166,12 +178,17 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer) err
return err
}
if len(pulls) > 0 && isRcpr(pulls[0]) {
rp.c.git("checkout", "HEAD~")
vfile, err := detectVersionFile(".", currVer)
if err != nil {
return err
var vfile string
if rp.cfg.versionFile == nil {
rp.c.git("checkout", "HEAD~")
vfile, err = detectVersionFile(".", currVer)
if err != nil {
return err
}
rp.c.git("checkout", releaseBranch)
} else {
vfile = rp.cfg.versionFile.String()
}
rp.c.git("checkout", releaseBranch)

var nextTag string
if vfile != "" {
Expand Down Expand Up @@ -252,16 +269,26 @@ func Run(ctx context.Context, argv []string, outStream, errStream io.Writer) err

nextVer := guessNextSemver(currVer, currRcpr)

// TODO: make configurable version file
vfile, err := detectVersionFile(".", currVer)
if err != nil {
return err
var vfile string
if rp.cfg.versionFile == nil {
vfile, err = detectVersionFile(".", currVer)
if err != nil {
return err
}
if vfile != "" {
if err := rp.cfg.SetVersionFile(vfile); err != nil {
return err
}
}
} else {
vfile = rp.cfg.versionFile.String()
}
if vfile != "" {
if err := bumpVersionFile(vfile, currVer, nextVer); err != nil {
return err
}
}
rp.c.gitE("add", "-f", rp.cfg.conf) // ignore any errors

// TODO To be able to run some kind of change script set by configuration in advance.

Expand Down

0 comments on commit f316f96

Please sign in to comment.