-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored run methods to support multiple options
- Loading branch information
Showing
6 changed files
with
241 additions
and
132 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/roemer/gotaskr" | ||
"github.com/roemer/gotaskr/goext" | ||
"github.com/roemer/gotaskr/log" | ||
) | ||
|
||
func init() { | ||
gotaskr.Task("Run-In-Directory", func() error { | ||
pwd, _ := os.Getwd() | ||
log.Informationf("Path before: %s", pwd) | ||
|
||
err := goext.RunInDirectory("subdir", func() error { | ||
pwd, _ = os.Getwd() | ||
log.Informationf("Path inside: %s", pwd) | ||
return nil | ||
}) | ||
|
||
pwd, _ = os.Getwd() | ||
log.Informationf("Path after : %s", pwd) | ||
|
||
return err | ||
}) | ||
|
||
gotaskr.Task("Run-With-Variables", func() error { | ||
log.Informationf("Variable before: %s", os.Getenv("TEST")) | ||
|
||
err := goext.RunWithEnvs(map[string]string{"TEST": "foo"}, func() error { | ||
log.Informationf("Variable inside: %s", os.Getenv("TEST")) | ||
return nil | ||
}) | ||
|
||
log.Informationf("Variable after : %s", os.Getenv("TEST")) | ||
|
||
return err | ||
}) | ||
|
||
gotaskr.Task("Run-With-Multiple-Options", func() error { | ||
return goext.RunWithOptions(func() error { | ||
return nil | ||
}, goext.RunOptionInDirectory("subdir"), goext.RunOptionWithEnvs(map[string]string{"TEST": "foo"})) | ||
}) | ||
} | ||
|
||
func main() { | ||
os.Exit(gotaskr.Execute()) | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package goext | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
) | ||
|
||
// An option that can be used to run which is applied before the run and reverted after. | ||
type RunOption interface { | ||
// The method that is applied before the run. | ||
apply() error | ||
// The method that is applied after the run. | ||
revert() error | ||
} | ||
|
||
// Runs a given method with addiitional options. | ||
func RunWithOptions(f func() error, options ...RunOption) (err error) { | ||
// Apply the options | ||
for _, option := range options { | ||
err = errors.Join(err, option.apply()) | ||
} | ||
// Make sure to revert all options, in reverse order | ||
defer func() { | ||
for index := len(options) - 1; index >= 0; index-- { | ||
option := options[index] | ||
err = errors.Join(err, option.revert()) | ||
} | ||
}() | ||
// Execute the function | ||
methodErr := f() | ||
if methodErr != nil { | ||
err = errors.Join(err, fmt.Errorf("inner method failed: %v", methodErr)) | ||
} | ||
return | ||
} | ||
|
||
// Runs a given method with returns one parameter with addiitional options. | ||
func RunWithOptions1P[P1 any](f func() (P1, error), options ...RunOption) (P1, error) { | ||
var p1 P1 | ||
return p1, RunWithOptions(func() error { | ||
var err error | ||
p1, err = f() | ||
return err | ||
}, options...) | ||
} | ||
|
||
// Runs a given method with returns two parameters with addiitional options. | ||
func RunWithOptions2P[P1 any, P2 any](f func() (P1, P2, error), options ...RunOption) (P1, P2, error) { | ||
var p1 P1 | ||
var p2 P2 | ||
return p1, p2, RunWithOptions(func() error { | ||
var err error | ||
p1, p2, err = f() | ||
return err | ||
}, options...) | ||
} | ||
|
||
// Runs a given method with returns three parameters with addiitional options. | ||
func RunWithOptions3P[P1 any, P2 any, P3 any](f func() (P1, P2, P3, error), options ...RunOption) (P1, P2, P3, error) { | ||
var p1 P1 | ||
var p2 P2 | ||
var p3 P3 | ||
return p1, p2, p3, RunWithOptions(func() error { | ||
var err error | ||
p1, p2, p3, err = f() | ||
return err | ||
}, options...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package goext | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
////////////////////////////// | ||
// Public Interface | ||
////////////////////////////// | ||
|
||
// Option that allows changing the working directory during a run. | ||
func RunOptionInDirectory(path string) RunOption { | ||
return &runInDirectoryOption{path: path} | ||
} | ||
|
||
// Option that allows setting/overriding environment variables during a run. | ||
func RunOptionWithEnvs(envVariables map[string]string) RunOption { | ||
return &runWithEnvsOption{envs: envVariables} | ||
} | ||
|
||
func RunInDirectory(path string, f func() error) (err error) { | ||
return RunWithOptions(f, RunOptionInDirectory(path)) | ||
} | ||
func RunInDirectory1P[P1 any](path string, f func() (P1, error)) (P1, error) { | ||
return RunWithOptions1P(f, RunOptionInDirectory(path)) | ||
} | ||
func RunInDirectory2P[P1 any, P2 any](path string, f func() (P1, P2, error)) (P1, P2, error) { | ||
return RunWithOptions2P(f, RunOptionInDirectory(path)) | ||
} | ||
func RunInDirectory3P[P1 any, P2 any, P3 any](path string, f func() (P1, P2, P3, error)) (P1, P2, P3, error) { | ||
return RunWithOptions3P(f, RunOptionInDirectory(path)) | ||
} | ||
|
||
func RunWithEnvs(envVariables map[string]string, f func() error) error { | ||
return RunWithOptions(f, RunOptionWithEnvs(envVariables)) | ||
} | ||
func RunWithEnvs1P[P1 any](envVariables map[string]string, f func() (P1, error)) (P1, error) { | ||
return RunWithOptions1P(f, RunOptionWithEnvs(envVariables)) | ||
} | ||
func RunWithEnvs2P[P1 any, P2 any](envVariables map[string]string, f func() (P1, P2, error)) (P1, P2, error) { | ||
return RunWithOptions2P(f, RunOptionWithEnvs(envVariables)) | ||
} | ||
func RunWithEnvs3P[P1 any, P2 any, P3 any](envVariables map[string]string, f func() (P1, P2, P3, error)) (P1, P2, P3, error) { | ||
return RunWithOptions3P(f, RunOptionWithEnvs(envVariables)) | ||
} | ||
|
||
////////////////////////////// | ||
// Run In Directory | ||
////////////////////////////// | ||
|
||
// Option that allows changing the working directory during a run. | ||
type runInDirectoryOption struct { | ||
path string | ||
origPath string | ||
} | ||
|
||
func (r *runInDirectoryOption) apply() error { | ||
// Get the current directory | ||
pwd, err := os.Getwd() | ||
if err != nil { | ||
return fmt.Errorf("cannot get current directory: %v", err) | ||
} | ||
r.origPath = pwd | ||
// Change the path | ||
err = os.Chdir(r.path) | ||
if err != nil { | ||
return fmt.Errorf("cannot change to directory %s: %v", strconv.Quote(r.path), err) | ||
} | ||
return nil | ||
} | ||
|
||
func (r *runInDirectoryOption) revert() error { | ||
// Reset to the previous folder | ||
err := os.Chdir(r.origPath) | ||
if err != nil { | ||
return fmt.Errorf("cannot change back to directory %s: %v", strconv.Quote(r.origPath), err) | ||
} | ||
return nil | ||
} | ||
|
||
////////////////////////////// | ||
// Run With Envs | ||
////////////////////////////// | ||
|
||
// Option that allows setting/overriding environment variables during a run. | ||
type runWithEnvsOption struct { | ||
envs map[string]string | ||
origEnvs map[string]string | ||
} | ||
|
||
func (r *runWithEnvsOption) apply() (err error) { | ||
r.origEnvs = map[string]string{} | ||
for name, value := range r.envs { | ||
// Read and store original value | ||
if originalValue, ok := os.LookupEnv(name); ok { | ||
r.origEnvs[name] = originalValue | ||
} | ||
// Set the new value | ||
err = errors.Join(err, os.Setenv(name, value)) | ||
} | ||
return | ||
} | ||
|
||
func (r *runWithEnvsOption) revert() (err error) { | ||
for name := range r.envs { | ||
origValue, ok := r.origEnvs[name] | ||
if ok { | ||
err = errors.Join(err, os.Setenv(name, origValue)) | ||
} else { | ||
err = errors.Join(err, os.Unsetenv(name)) | ||
} | ||
} | ||
return | ||
} |
Oops, something went wrong.