Skip to content

Commit

Permalink
feat: add rough separation of concerns
Browse files Browse the repository at this point in the history
In the earlier version, the same function updated the repo and reported
the result.  In this version, we separate updating from reporting.  I am
not sure whether this is the best way to do it.  To be continued...
  • Loading branch information
telemachus committed Oct 14, 2024
1 parent 3bcd0b9 commit 9fccd9d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
linters-settings:
copyloopvar:
check-alias: true
depguard:
rules:
main:
Expand Down
34 changes: 23 additions & 11 deletions cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,34 +98,46 @@ func (app *App) Unmarshal(configFile string, isDefault bool) *Wanted {
return &wanted
}

// MirrorRepos runs git push --mirror on a group of repositories.
func (app *App) MirrorRepos(wanted *Wanted) {
// MirrorRepos runs git push --mirror on a group of repositories and returns
// a slice of results.
func (app *App) MirrorRepos(wanted *Wanted) []Publisher {
if app.NoOp() || len(wanted.Repos) == 0 {
return
return nil
}
wanted.Repos = slices.DeleteFunc(wanted.Repos, func(r *Repo) bool {
return r == nil || r.Dir == ""
})
var wg sync.WaitGroup
wg.Add(len(wanted.Repos))
for _, repo := range wanted.Repos {
go func(r *Repo) {
results := make([]Publisher, len(wanted.Repos))
for i, r := range wanted.Repos {
go func(i int, r *Repo) {
defer wg.Done()
updateRepo(r)
}(repo)
res := updateRepo(r)
results[i] = res
}(i, r)
}
wg.Wait()
return results
}

func (app *App) DisplayResults(results []Publisher) {
if app.NoOp() || len(results) == 0 {
return
}
for _, r := range results {
r.Publish()
}
}

func updateRepo(r *Repo) {
func updateRepo(r *Repo) Publisher {
args := []string{"push", "--mirror", r.Remote}
cmd := exec.Command("git", args...)
cmd.Dir = r.Dir
cmdString := fmt.Sprintf("`git %s` (in %s)", strings.Join(args, " "), cmd.Dir)
err := cmd.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "%s: problem with %s: %s\n", appName, cmdString, err)
return
return Failure{msg: fmt.Sprintf("%s: problem with %s: %s", appName, cmdString, err)}
}
fmt.Printf("%s: %s\n", appName, cmdString)
return Success{msg: fmt.Sprintf("%s: %s", appName, cmdString)}
}
27 changes: 27 additions & 0 deletions cli/result.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package cli

import (
"fmt"
"os"
)

// Publisher is the interface that wraps the Publish method.
type Publisher interface {
Publish()
}

type Success struct {
msg string
}

type Failure struct {
msg string
}

func (s Success) Publish() {
fmt.Fprintln(os.Stdout, s.msg)
}

func (f Failure) Publish() {
fmt.Fprintln(os.Stderr, f.msg)
}
3 changes: 2 additions & 1 deletion cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func Run(args []string) int {
app := &App{ExitValue: exitSuccess}
configFile, isDefault := app.ParseFlags(args)
wanted := app.Unmarshal(configFile, isDefault)
app.MirrorRepos(wanted)
results := app.MirrorRepos(wanted)
app.DisplayResults(results)
return app.ExitValue
}

0 comments on commit 9fccd9d

Please sign in to comment.