Skip to content

Commit

Permalink
Refactor to make no side-effect in logic function
Browse files Browse the repository at this point in the history
  • Loading branch information
kachick committed Apr 24, 2024
1 parent 56572d9 commit 80388f8
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 52 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ You can check the running plans with `list` subcommand
> selfup list .github/workflows/*.yml
.github/workflows/lint.yml:17: 0.40.2
✓ .github/workflows/release.yml:37: 1.20.0 => 1.42.9
.github/workflows/lint.yml:24: 1.16.12
.github/workflows/release.yml:50: 3.3.1

1/3 items will be replaced
```
Expand Down
61 changes: 49 additions & 12 deletions cmd/selfup/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"strings"
"sync"

updater "github.com/kachick/selfup/internal"
"github.com/fatih/color"
selfup "github.com/kachick/selfup/internal"
"golang.org/x/term"
"golang.org/x/xerrors"
)
Expand All @@ -21,6 +22,11 @@ var (
revision = "rev"
)

type Result struct {
Path string
FileResult selfup.Result
}

func main() {
versionFlag := flag.Bool("version", false, "print the version of this program")

Expand Down Expand Up @@ -85,33 +91,64 @@ $ selfup --version
}

wg := &sync.WaitGroup{}
results := make(chan updater.Result, len(paths))
results := make(chan Result, len(paths))
for _, path := range paths {
wg.Add(1)
go func(path string) {
defer wg.Done()
result, err := updater.Update(path, prefix, skipBy, isColor)
if err != nil {
log.Fatalf("%+v", err)
}
results <- result
isDirty := result.Changed > 0

fileResult := func() selfup.Result {
file, err := os.Open(path)
if err != nil {
log.Fatalf("%s: %+v", path, err)
}
defer file.Close()

fr, err := selfup.DryRun(file, prefix, skipBy)
if err != nil {
log.Fatalf("%s: %+v", path, err)
}
return fr
}()

isDirty := fileResult.ChangedCount > 0

if isRunMode && isDirty {
err := os.WriteFile(path, []byte(strings.Join(result.Lines, "\n")+"\n"), os.ModePerm)
err := os.WriteFile(path, []byte(strings.Join(fileResult.Lines, "\n")+"\n"), os.ModePerm)
if err != nil {
log.Fatalf("%+v", xerrors.Errorf("%s: %w", path, err))
log.Fatalf("%s: %+v", path, err)
}
}

results <- Result{
Path: path,
FileResult: fileResult,
}
}(path)
}
wg.Wait()
close(results)
total := 0
changed := 0
for r := range results {
total += r.Total
changed += r.Changed
fr := r.FileResult
total += fr.Total
changed += fr.ChangedCount
for _, t := range fr.Targets {
estimation := " "
suffix := ""
replacer := t.Replacer
if t.IsChanged {
estimation = "✓"
if isColor {
green := color.New(color.FgGreen).SprintFunc()
estimation = green(estimation)
replacer = green(t.Replacer)
}
suffix = fmt.Sprintf(" => %s", replacer)
}
fmt.Printf("%s %s:%d: %s%s\n", estimation, r.Path, t.LineNumber, t.Extracted, suffix)
}
}
fmt.Println()
if isListMode {
Expand Down
78 changes: 39 additions & 39 deletions internal/selfup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package updater
import (
"bufio"
"encoding/json"
"fmt"
"os"
"io"
"os/exec"
"regexp"
"strings"

"github.com/fatih/color"
"golang.org/x/xerrors"
)

Expand All @@ -20,28 +18,28 @@ type Definition struct {
Delimiter string `json:"delimiter"`
}

type Target struct {
LineNumber int
Extracted string
Replacer string
IsChanged bool
}

type Result struct {
Lines []string
Changed int
Total int
Lines []string
Targets []Target
ChangedCount int
Total int
}

// Returns new body and true if it is changed
func Update(path string, prefix string, skipBy string, isColor bool) (Result, error) {
green := color.New(color.FgGreen).SprintFunc()
func DryRun(r io.Reader, prefix string, skipBy string) (Result, error) {
newLines := []string{}
isChanged := false

file, err := os.Open(path)
if err != nil {
return Result{}, xerrors.Errorf("%s: %w", path, err)
}
defer file.Close()
targets := []Target{}

scanner := bufio.NewScanner(file)
scanner := bufio.NewScanner(r)
lineNumber := 0
totalCount := 0
replacedCount := 0
changedCount := 0

for scanner.Scan() {
lineNumber += 1
Expand All @@ -60,19 +58,19 @@ func Update(path string, prefix string, skipBy string, isColor bool) (Result, er
def := &Definition{}
totalCount += 1

err = json.Unmarshal([]byte(tail), def)
err := json.Unmarshal([]byte(tail), def)
if err != nil {
return Result{}, xerrors.Errorf("%s:%d: Unmarsharing `%s` as JSON has been failed, check the given prefix: %w", path, lineNumber, tail, err)
return Result{}, xerrors.Errorf("%d: Unmarsharing `%s` as JSON has been failed, check the given prefix: %w", lineNumber, tail, err)
}
re := regexp.MustCompile(def.Extract)
if len(def.Command) < 1 {
return Result{}, xerrors.Errorf("%s:%d: Given JSON `%s` does not include commands", path, lineNumber, tail)
return Result{}, xerrors.Errorf("%d: Given JSON `%s` does not include commands", lineNumber, tail)
}
cmd := def.Command[0]
args := def.Command[1:]
out, err := exec.Command(cmd, args...).Output()
if err != nil {
return Result{}, xerrors.Errorf("%s:%d: Executing %s has been failed: %w", path, lineNumber, cmd, err)
return Result{}, xerrors.Errorf("%d: Executing %s has been failed: %w", lineNumber, cmd, err)
}
cmdResult := strings.TrimSuffix(string(out), "\n")
replacer := cmdResult
Expand All @@ -87,31 +85,33 @@ func Update(path string, prefix string, skipBy string, isColor bool) (Result, er
}
extracted := re.FindString(head)
replaced := strings.Replace(head, extracted, replacer, 1)
if !isChanged {
isChanged = replaced != head
}
isChanged := false
extractedToEnsure := re.FindString(replaced)
if replacer != extractedToEnsure {
return Result{}, xerrors.Errorf("%s:%d: The result of updater command has malformed format: %s", path, lineNumber, replacer)
return Result{}, xerrors.Errorf("%d: The result of updater command has malformed format: %s", lineNumber, replacer)
}
estimation := " "
suffix := ""
if replaced != head {
replacedCount += 1
estimation = "✓"
if isColor {
replacer = green(replacer)
estimation = green(estimation)
}
suffix = fmt.Sprintf(" => %s", replacer)
isChanged = true
changedCount++
}
newLines = append(newLines, replaced+prefix+tail)
fmt.Println(fmt.Sprintf("%s %s:%d: %s", estimation, path, lineNumber, extracted) + suffix)
targets = append(targets, Target{
LineNumber: lineNumber,
Extracted: extracted,
Replacer: replacer,
IsChanged: isChanged,
})
}

err := scanner.Err()
if err != nil {
return Result{}, err
}

return Result{
Lines: newLines,
Changed: replacedCount,
Total: totalCount,
Lines: newLines,
Targets: targets,
Total: totalCount,
ChangedCount: changedCount,
}, nil
}

0 comments on commit 80388f8

Please sign in to comment.