Skip to content

Commit

Permalink
cmd: Explicitly handle output errors
Browse files Browse the repository at this point in the history
This commit introduces a new error message, that is triggered whenever
output fails
  • Loading branch information
tkw1536 committed Nov 25, 2024
1 parent 258a2b4 commit 50e03dc
Show file tree
Hide file tree
Showing 21 changed files with 124 additions and 46 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ ggman comes with the following builtin aliases:
- update dependencies to latest
- minor linting updates
- minor performance improvements
- explicitly handle output errors

### 1.22.0 (Released [Sep 22 2024](https://github.com/tkw1536/ggman/releases/tag/v1.22.0))

Expand Down
5 changes: 2 additions & 3 deletions cmd/canon.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ func (c canon) Run(context ggman.Context) error {

// print out the canonical version of the file
canonical := c.Positional.URL.CanonicalWith(file)
context.Println(canonical)

return nil
_, err := context.Println(canonical)
return ggman.ErrGenericOutput.WrapError(err)
}
8 changes: 5 additions & 3 deletions cmd/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,16 @@ func (c clone) Run(context ggman.Context) error {
}

// do the actual cloning!
context.Printf("Cloning %q into %q ...\n", remote, local)
if _, err := context.Printf("Cloning %q into %q ...\n", remote, local); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
switch err := context.Environment.Git.Clone(context.IOStream, remote, local, c.Positional.Args...); err {
case nil:
return nil
case git.ErrCloneAlreadyExists:
if c.Force {
context.Println("Clone already exists in target location, done.")
return nil
_, err := context.Println("Clone already exists in target location, done.")
return ggman.ErrGenericOutput.WrapError(err)
}
return errCloneAlreadyExists
case git.ErrArgumentsUnsupported:
Expand Down
4 changes: 3 additions & 1 deletion cmd/comps.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func (comps) Description() ggman.Description {

func (c comps) Run(context ggman.Context) error {
for _, comp := range c.Positional.URL.Components() {
context.Println(comp)
if _, err := context.Println(comp); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

return nil
Expand Down
16 changes: 12 additions & 4 deletions cmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,22 @@ func (e _env) Run(context ggman.Context) error {
for _, v := range variables {
switch {
case e.List:
context.Println(v.Key)
if _, err := context.Println(v.Key); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
case e.Raw:
context.Println(v.Get(context.Environment, context.Program.Info))
if _, err := context.Println(v.Get(context.Environment, context.Program.Info)); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
case e.Describe:
context.Printf("%s: %s\n", v.Key, v.Description)
if _, err := context.Printf("%s: %s\n", v.Key, v.Description); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
default:
value := shellescape.Quote(v.Get(context.Environment, context.Program.Info))
context.Printf("%s=%s\n", v.Key, value)
if _, err := context.Printf("%s=%s\n", v.Key, value); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}
}

Expand Down
32 changes: 24 additions & 8 deletions cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ func (e exe) runReal(context ggman.Context) error {
}

if !e.NoRepo && !statusIO {
io.EPrintln(repo)
if _, err := io.EPrintln(repo); err != nil {
return err
}
}

return e.runRepo(io, repo)
Expand Down Expand Up @@ -182,24 +184,38 @@ func (e exe) runSimulate(context ggman.Context) (err error) {
}

// print header of the bash script
context.Println("#!/bin/bash")
if _, err := context.Println("#!/bin/bash"); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if !e.Force {
context.Println("set -e")
if _, err := context.Println("set -e"); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}
if _, err := context.Println(""); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
context.Println("")

exec := shellescape.QuoteCommand(append([]string{e.Positionals.Exe}, e.Positionals.Args...))

// iterate over each repository
// then print each of the commands to be run!
for _, repo := range context.Environment.Repos(true) {
context.Printf("cd %s\n", shellescape.Quote(repo))
if _, err := context.Printf("cd %s\n", shellescape.Quote(repo)); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if !e.NoRepo {
context.Printf("echo %s\n", shellescape.Quote(repo))
if _, err := context.Printf("echo %s\n", shellescape.Quote(repo)); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

context.Println(exec)
context.Println("")
if _, err := context.Println(exec); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if _, err := context.Println(""); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

return err
Expand Down
8 changes: 6 additions & 2 deletions cmd/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ func (fetch) Run(context ggman.Context) error {

// iterate over all the repositories, and run git fetch
for _, repo := range context.Environment.Repos(true) {
context.Printf("Fetching %q\n", repo)
if _, err := context.Printf("Fetching %q\n", repo); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if e := context.Environment.Git.Fetch(context.IOStream, repo); e != nil {
context.EPrintln(e.Error())
if _, err := context.EPrintln(e.Error()); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
hasError = true
}
}
Expand Down
4 changes: 3 additions & 1 deletion cmd/find_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ func (f findBranch) Run(context ggman.Context) error {
}

foundRepo = true
context.Println(repo)
if _, err := context.Println(repo); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

// if we have --exit-code set and no results
Expand Down
8 changes: 6 additions & 2 deletions cmd/find_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ func (f findFile) Run(context ggman.Context) error {

foundRepo = true
if f.PrintFilePath {
context.Println(candidate)
if _, err := context.Println(candidate); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
} else {
context.Println(repo)
if _, err := context.Println(repo); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}
}

Expand Down
20 changes: 16 additions & 4 deletions cmd/fix.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func (f fix) Run(context ggman.Context) error {
simulate := f.Simulate

hasError := false

var innerError error
for _, repo := range context.Environment.Repos(true) {
var initialMessage sync.Once // send an initial log message to the user, once

Expand All @@ -56,13 +58,23 @@ func (f fix) Run(context ggman.Context) error {

initialMessage.Do(func() {
if !simulate {
context.Printf("Fixing remote of %q", repo)
if _, err := context.Printf("Fixing remote of %q", repo); err != nil {
innerError = ggman.ErrGenericOutput.WrapError(err)
}
} else {
context.Printf("Simulate fixing remote of %q", repo)
if _, err := context.Printf("Simulate fixing remote of %q", repo); err != nil {
innerError = ggman.ErrGenericOutput.WrapError(err)
}
}
})

context.Printf("Updating %s: %s -> %s\n", remoteName, url, canon)
if innerError != nil {
return "", innerError
}

if _, err := context.Printf("Updating %s: %s -> %s\n", remoteName, url, canon); err != nil {
return "", ggman.ErrGenericOutput.WrapError(err)
}

// either return the canonical url, or (if we're simulating) the old url
if simulate {
Expand All @@ -71,7 +83,7 @@ func (f fix) Run(context ggman.Context) error {

return canon, nil
}); e != nil {
context.EPrintln(e.Error())
_, _ = context.EPrintln(e.Error()) // no way to report error
hasError = true
}
}
Expand Down
8 changes: 6 additions & 2 deletions cmd/here.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ func (h here) Run(context ggman.Context) error {
return err
}

context.Println(root)
if _, err := context.Println(root); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if h.Tree {
context.Println(worktree)
if _, err := context.Println(worktree); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

return nil
Expand Down
4 changes: 2 additions & 2 deletions cmd/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func (license) Description() ggman.Description {
}

func (license) Run(context ggman.Context) error {
context.Printf(stringLicenseInfo, ggman.License, legal.Notices)
return nil
_, err := context.Printf(stringLicenseInfo, ggman.License, legal.Notices)
return ggman.ErrGenericOutput.WrapError(err)
}

const stringLicenseInfo = `
Expand Down
4 changes: 3 additions & 1 deletion cmd/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ func (l link) Run(context ggman.Context) error {
}
}

context.Printf("Linking %q -> %q\n", to, from)
if _, err := context.Printf("Linking %q -> %q\n", to, from); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}

// make the parent folder
if e := os.MkdirAll(parentTo, os.ModePerm); e != nil {
Expand Down
8 changes: 6 additions & 2 deletions cmd/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ func (l ls) Run(context ggman.Context) error {
}
for i, repo := range repos {
if l.Scores {
context.Printf("%f %s\n", scores[i], repo)
if _, err := context.Printf("%f %s\n", scores[i], repo); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
continue
}
context.Println(repo)
if _, err := context.Println(repo); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

// if we have --exit-code set and no results
Expand Down
4 changes: 3 additions & 1 deletion cmd/lsr.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ func (l lsr) Run(context ggman.Context) error {
if l.Canonical {
remote = env.ParseURL(remote).CanonicalWith(lines)
}
context.Println(remote)
if _, err := context.Println(remote); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}

return nil
Expand Down
8 changes: 6 additions & 2 deletions cmd/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ var errPullCustom = exit.Error{
func (pull) Run(context ggman.Context) error {
hasError := false
for _, repo := range context.Environment.Repos(true) {
context.Printf("Pulling %q\n", repo)
if _, err := context.Printf("Pulling %q\n", repo); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if e := context.Environment.Git.Pull(context.IOStream, repo); e != nil {
context.EPrintf("%s\n", e)
if _, err := context.EPrintf("%s\n", e); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
hasError = true
}
}
Expand Down
8 changes: 6 additions & 2 deletions cmd/relocate.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ func (r relocate) Run(context ggman.Context) error {
parentPath := filepath.Dir(shouldPath)

// print what is being done
context.Printf("mkdir -p %s\n", shellescape.Quote(parentPath))
context.Printf("mv %s %s\n", shellescape.Quote(gotPath), shellescape.Quote(shouldPath))
if _, err := context.Printf("mkdir -p %s\n", shellescape.Quote(parentPath)); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if _, err := context.Printf("mv %s %s\n", shellescape.Quote(gotPath), shellescape.Quote(shouldPath)); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
if r.Simulate {
continue
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/shellrc.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ func (shellrc) Description() ggman.Description {
var shellrcSh string

func (shellrc) Run(context ggman.Context) error {
context.Printf("%s", shellrcSh)
return nil
_, err := context.Printf("%s", shellrcSh)
return ggman.ErrGenericOutput.WrapError(err)
}
4 changes: 3 additions & 1 deletion cmd/sweep.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ func (sweep) Run(context ggman.Context) error {
}

for _, r := range results {
context.Println(r)
if _, err := context.Println(r); err != nil {
return ggman.ErrGenericOutput.WrapError(err)
}
}
return nil
}
5 changes: 2 additions & 3 deletions cmd/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,9 @@ func (uw urlweb) Run(context ggman.Context) error {
if uw.isWebCommand {
return browser.OpenURL(weburl)
} else {
context.Println(weburl)
_, err := context.Println(weburl)
return ggman.ErrGenericOutput.WrapError(err)
}

return nil
}

func (uw urlweb) listBases(context ggman.Context) {
Expand Down
7 changes: 7 additions & 0 deletions ggman.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package ggman
import (
"github.com/tkw1536/ggman/env"
"github.com/tkw1536/goprogram"
"github.com/tkw1536/goprogram/exit"
)

type ggmanEnv = env.Env
Expand All @@ -36,3 +37,9 @@ type Arguments = goprogram.Arguments[ggmanFlags]

// Description is the type of descriptions of a ggman command
type Description = goprogram.Description[ggmanFlags, ggmanRequirements]

// ErrGenericOutput indicates that a generic output error occurred
var ErrGenericOutput = exit.Error{
ExitCode: exit.ExitGeneric,
Message: "Unknown Output Error",
}

0 comments on commit 50e03dc

Please sign in to comment.