From 8c62ade3a2e0ca8cb1b5866435481c43ff820fb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:06:34 +0000 Subject: [PATCH] Bump github.com/vladimirvivien/gexe from 0.2.0 to 0.3.0 (#361) Bumps [github.com/vladimirvivien/gexe](https://github.com/vladimirvivien/gexe) from 0.2.0 to 0.3.0. - [Release notes](https://github.com/vladimirvivien/gexe/releases) - [Commits](https://github.com/vladimirvivien/gexe/compare/v0.2.0...v0.3.0) --- updated-dependencies: - dependency-name: github.com/vladimirvivien/gexe dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +- vendor/github.com/vladimirvivien/gexe/TODO.md | 2 +- .../github.com/vladimirvivien/gexe/config.go | 41 ---- vendor/github.com/vladimirvivien/gexe/echo.go | 21 +- .../vladimirvivien/gexe/exec/builder.go | 64 +++++- .../vladimirvivien/gexe/exec/proc.go | 42 +++- .../github.com/vladimirvivien/gexe/filesys.go | 50 ++++- .../vladimirvivien/gexe/fs/file_reader.go | 50 +++-- .../vladimirvivien/gexe/fs/file_writer.go | 62 ++++-- .../vladimirvivien/gexe/fs/fsinfo.go | 51 +++++ .../vladimirvivien/gexe/fs/fspath.go | 115 +++++++++++ .../vladimirvivien/gexe/fs/types.go | 33 ---- .../vladimirvivien/gexe/functions.go | 62 +++++- vendor/github.com/vladimirvivien/gexe/http.go | 24 ++- .../vladimirvivien/gexe/http/http_reader.go | 96 ++++----- .../vladimirvivien/gexe/http/http_response.go | 31 +++ .../vladimirvivien/gexe/http/http_writer.go | 31 ++- vendor/github.com/vladimirvivien/gexe/net.go | 9 + .../vladimirvivien/gexe/net/listener.go | 29 +++ .../github.com/vladimirvivien/gexe/procs.go | 47 ++--- vendor/github.com/vladimirvivien/gexe/prog.go | 8 +- .../vladimirvivien/gexe/prog/prog.go | 1 + vendor/github.com/vladimirvivien/gexe/str.go | 8 + .../vladimirvivien/gexe/str/functions.go | 53 +++++ .../vladimirvivien/gexe/str/strings.go | 185 ++++++++++++++++++ .../vladimirvivien/gexe/variables.go | 7 + .../vladimirvivien/gexe/vars/variables.go | 8 + vendor/modules.txt | 6 +- 29 files changed, 925 insertions(+), 217 deletions(-) delete mode 100644 vendor/github.com/vladimirvivien/gexe/config.go create mode 100644 vendor/github.com/vladimirvivien/gexe/fs/fsinfo.go create mode 100644 vendor/github.com/vladimirvivien/gexe/fs/fspath.go delete mode 100644 vendor/github.com/vladimirvivien/gexe/fs/types.go create mode 100644 vendor/github.com/vladimirvivien/gexe/net.go create mode 100644 vendor/github.com/vladimirvivien/gexe/net/listener.go create mode 100644 vendor/github.com/vladimirvivien/gexe/str.go create mode 100644 vendor/github.com/vladimirvivien/gexe/str/functions.go create mode 100644 vendor/github.com/vladimirvivien/gexe/str/strings.go diff --git a/go.mod b/go.mod index 319179b19..6cdb1b409 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/vishvananda/netlink v1.1.0 github.com/vishvananda/netns v0.0.4 - github.com/vladimirvivien/gexe v0.2.0 + github.com/vladimirvivien/gexe v0.3.0 github.com/vmware/go-ipfix v0.9.0 golang.org/x/sys v0.21.0 google.golang.org/grpc v1.63.0 diff --git a/go.sum b/go.sum index dec66e64d..3c61fbae3 100644 --- a/go.sum +++ b/go.sum @@ -856,8 +856,8 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= -github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= -github.com/vladimirvivien/gexe v0.2.0/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w= +github.com/vladimirvivien/gexe v0.3.0 h1:4xwiOwGrDob5OMR6E92B9olDXYDglXdHhzR1ggYtWJM= +github.com/vladimirvivien/gexe v0.3.0/go.mod h1:fp7cy60ON1xjhtEI/+bfSEIXX35qgmI+iRYlGOqbBFM= github.com/vmware/go-ipfix v0.9.0 h1:4/N5eFliqULEaCUQV0lafOpN/1bItPE9OTAPGhrIXus= github.com/vmware/go-ipfix v0.9.0/go.mod h1:MYEdL6Uel2ufOZyVCKvIAaw9hwnewK8aPr7rnwRbxMY= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= diff --git a/vendor/github.com/vladimirvivien/gexe/TODO.md b/vendor/github.com/vladimirvivien/gexe/TODO.md index 0d9bb6c47..022f44d11 100644 --- a/vendor/github.com/vladimirvivien/gexe/TODO.md +++ b/vendor/github.com/vladimirvivien/gexe/TODO.md @@ -3,7 +3,7 @@ The following are high-level tasks that will be considered for upcoming release * [ ] Support and test on Windows platform (#27) * [ ] Ability to map and access program flags (#20) -* [ ] Provide a simple API to submit HTTP requests and retrieve HTTP documents (think of wget/curl) +* [x] Provide a simple API to submit HTTP requests and retrieve HTTP documents (think of wget/curl) * [x] Support for scatter/gather exec commands * [x] Support for concurrent exec of os commands * [x] Piping/chaining OS exec commands (#29) diff --git a/vendor/github.com/vladimirvivien/gexe/config.go b/vendor/github.com/vladimirvivien/gexe/config.go deleted file mode 100644 index 932f9b875..000000000 --- a/vendor/github.com/vladimirvivien/gexe/config.go +++ /dev/null @@ -1,41 +0,0 @@ -package gexe - -// Config stores configuration -type Config struct { - panicOnErr bool - verbose bool - escapeChar rune -} - -// SetPanicOnErr panics program on any error -func (c *Config) SetPanicOnErr(val bool) *Config { - c.panicOnErr = val - return c -} - -// IsPanicOnErr returns panic-on-error flag -func (c *Config) IsPanicOnErr() bool { - return c.panicOnErr -} - -// SetVerbose sets verbosity -func (c *Config) SetVerbose(val bool) *Config { - c.verbose = val - return c -} - -// IsVerbose returns verbosity flag -func (c *Config) IsVerbose() bool { - return c.verbose -} - -// SetEscapeChar sets the escape char for command-line parsing -func (c *Config) SetEscapeChar(r rune) *Config { - c.escapeChar = r - return c -} - -// GetEscapeChar returns the escape char set for command-line parsing -func (c *Config) GetEscapeChar() rune { - return c.escapeChar -} diff --git a/vendor/github.com/vladimirvivien/gexe/echo.go b/vendor/github.com/vladimirvivien/gexe/echo.go index 53156ca2b..70eac5eb0 100644 --- a/vendor/github.com/vladimirvivien/gexe/echo.go +++ b/vendor/github.com/vladimirvivien/gexe/echo.go @@ -1,6 +1,10 @@ package gexe import ( + "fmt" + "os" + "os/exec" + "github.com/vladimirvivien/gexe/prog" "github.com/vladimirvivien/gexe/vars" ) @@ -16,7 +20,6 @@ type Echo struct { err error vars *vars.Variables // session vars prog *prog.Info - Conf *Config // session config } // New creates a new Echo session @@ -24,7 +27,21 @@ func New() *Echo { e := &Echo{ vars: vars.New(), prog: prog.Prog(), - Conf: &Config{escapeChar: '\\'}, } return e } + +// AddExecPath adds an executable path to PATH +func (e *Echo) AddExecPath(execPath string) { + oldPath := os.Getenv("PATH") + os.Setenv("PATH", fmt.Sprintf("%s%c%s", oldPath, os.PathListSeparator, e.Eval(execPath))) +} + +// ProgAvail returns the full path of the program if found on exec PATH +func (e *Echo) ProgAvail(progName string) string { + path, err := exec.LookPath(e.Eval(progName)) + if err != nil { + return "" + } + return path +} diff --git a/vendor/github.com/vladimirvivien/gexe/exec/builder.go b/vendor/github.com/vladimirvivien/gexe/exec/builder.go index 93709dcde..c1b41f905 100644 --- a/vendor/github.com/vladimirvivien/gexe/exec/builder.go +++ b/vendor/github.com/vladimirvivien/gexe/exec/builder.go @@ -1,7 +1,10 @@ package exec import ( + "fmt" "sync" + + "github.com/vladimirvivien/gexe/vars" ) type CommandPolicy byte @@ -19,29 +22,75 @@ type CommandResult struct { errProcs []*Proc } +// Procs return all executed processes func (cr *CommandResult) Procs() []*Proc { cr.mu.RLock() defer cr.mu.RUnlock() return cr.procs } + +// ErrProcs returns errored processes func (cr *CommandResult) ErrProcs() []*Proc { cr.mu.RLock() defer cr.mu.RUnlock() return cr.errProcs } +// Errs returns all errors +func (cr *CommandResult) Errs() (errs []error) { + cr.mu.RLock() + defer cr.mu.RUnlock() + + for _, proc := range cr.errProcs { + errs = append(errs, fmt.Errorf("%s: %s", proc.Err(), proc.Result())) + } + return +} + +// ErrStrings returns errors as []string +func (cr *CommandResult) ErrStrings() (errStrings []string) { + errs := cr.Errs() + for _, err := range errs { + errStrings = append(errStrings, err.Error()) + } + return +} + +// PipedCommandResult stores results of piped commands type PipedCommandResult struct { procs []*Proc errProcs []*Proc lastProc *Proc } +// Procs return all executed processes in pipe func (cr *PipedCommandResult) Procs() []*Proc { return cr.procs } + +// ErrProcs returns errored piped processes func (cr *PipedCommandResult) ErrProcs() []*Proc { return cr.errProcs } + +// Errs returns all errors +func (cr *PipedCommandResult) Errs() (errs []error) { + for _, proc := range cr.errProcs { + errs = append(errs, fmt.Errorf("%s: %s", proc.Err(), proc.Result())) + } + return +} + +// ErrStrings returns errors as []string +func (cr *PipedCommandResult) ErrStrings() (errStrings []string) { + errs := cr.Errs() + for _, err := range errs { + errStrings = append(errStrings, err.Error()) + } + return +} + +// LastProc executes last executed process func (cr *PipedCommandResult) LastProc() *Proc { procLen := len(cr.procs) if procLen == 0 { @@ -50,21 +99,34 @@ func (cr *PipedCommandResult) LastProc() *Proc { return cr.procs[procLen-1] } +// CommandBuilder is a batch command builder that +// can execute commands using different execution policies (i.e. serial, piped, concurrent) type CommandBuilder struct { cmdPolicy CommandPolicy procs []*Proc + vars *vars.Variables } // Commands creates a *CommandBuilder used to collect // command strings to be executed. func Commands(cmds ...string) *CommandBuilder { cb := new(CommandBuilder) + cb.vars = &vars.Variables{} for _, cmd := range cmds { cb.procs = append(cb.procs, NewProc(cmd)) } return cb } +// CommandsWithVars creates a new CommandBuilder and sets session varialbes for it +func CommandsWithVars(variables *vars.Variables, cmds ...string) *CommandBuilder { + cb := &CommandBuilder{vars: variables} + for _, cmd := range cmds { + cb.procs = append(cb.procs, NewProc(variables.Eval(cmd))) + } + return cb +} + // WithPolicy sets one or more command policy mask values, i.e. (CmdOnErrContinue | CmdExecConcurrent) func (cb *CommandBuilder) WithPolicy(policyMask CommandPolicy) *CommandBuilder { cb.cmdPolicy = policyMask @@ -74,7 +136,7 @@ func (cb *CommandBuilder) WithPolicy(policyMask CommandPolicy) *CommandBuilder { // Add adds a new command string to the builder func (cb *CommandBuilder) Add(cmds ...string) *CommandBuilder { for _, cmd := range cmds { - cb.procs = append(cb.procs, NewProc(cmd)) + cb.procs = append(cb.procs, NewProc(cb.vars.Eval(cmd))) } return cb } diff --git a/vendor/github.com/vladimirvivien/gexe/exec/proc.go b/vendor/github.com/vladimirvivien/gexe/exec/proc.go index 00899a43f..a91db489d 100644 --- a/vendor/github.com/vladimirvivien/gexe/exec/proc.go +++ b/vendor/github.com/vladimirvivien/gexe/exec/proc.go @@ -8,6 +8,8 @@ import ( osexec "os/exec" "strings" "time" + + "github.com/vladimirvivien/gexe/vars" ) // Proc stores process info when running a process @@ -21,6 +23,7 @@ type Proc struct { inputPipe io.WriteCloser cmd *osexec.Cmd process *os.Process + vars *vars.Variables } // NewProc sets up command string to be started as an OS process, however @@ -34,7 +37,6 @@ func NewProc(cmdStr string) *Proc { command := osexec.Command(words[0], words[1:]...) pipeout, outerr := command.StdoutPipe() pipeerr, errerr := command.StderrPipe() - //output := io.MultiReader(pipeout, pipeerr) if outerr != nil || errerr != nil { return &Proc{err: fmt.Errorf("combinedOutput pipe: %s; %s", outerr, errerr)} @@ -51,9 +53,17 @@ func NewProc(cmdStr string) *Proc { errorPipe: pipeerr, inputPipe: pipein, result: new(bytes.Buffer), + vars: &vars.Variables{}, } } +// NewProcWithVars sets up new command string and session variables for a new proc +func NewProcWithVars(cmdStr string, variables *vars.Variables) *Proc { + p := NewProc(variables.Eval(cmdStr)) + p.vars = variables + return p +} + // StartProc starts an OS process (setup a combined output of stdout, stderr) and does not wait for // it to complete. You must follow this with either proc.Wait() to wait for result directly. Otherwise, // call proc.Out() or proc.Result() which automatically waits and gather result. @@ -67,6 +77,13 @@ func StartProc(cmdStr string) *Proc { return proc.Start() } +// StartProcWithVars sets session variables and calls StartProc +func StartProcWithVars(cmdStr string, variables *vars.Variables) *Proc { + proc := StartProc(variables.Eval(cmdStr)) + proc.vars = variables + return proc +} + // RunProc starts a new process and waits for its completion. Use Proc.Out() or Proc.Result() // to access the combined result from stdout and stderr. func RunProc(cmdStr string) *Proc { @@ -78,12 +95,30 @@ func RunProc(cmdStr string) *Proc { return proc } +// RunProcWithVars sets session variables and calls RunProc +func RunProcWithVars(cmdStr string, variables *vars.Variables) *Proc { + proc := RunProc(variables.Eval(cmdStr)) + proc.vars = variables + return proc +} + // Run creates and runs a process and waits for its result (combined stdin,stderr) returned as a string value. // This is equivalent to calling Proc.RunProc() followed by Proc.Result(). func Run(cmdStr string) (result string) { return RunProc(cmdStr).Result() } +// RunWithVars sets session variables and call Run +func RunWithVars(cmdStr string, variables *vars.Variables) string { + return RunProcWithVars(cmdStr, variables).Result() +} + +// SetVars sets session variables for Proc +func (p *Proc) SetVars(variables *vars.Variables) *Proc { + p.vars = variables + return p +} + // Start starts the associated command as an OS process and does not wait for its result. // Ensure proper access to the process' input/output (stdin,stdout,stderr) has been // setup prior to calling p.Start(). @@ -280,3 +315,8 @@ func (p *Proc) GetErrorPipe() io.Reader { func (p *Proc) hasStarted() bool { return (p.cmd.Process != nil && p.cmd.Process.Pid != 0) } + +// Parse parses the command string and returns its tokens +func Parse(cmd string) ([]string, error) { + return parse(cmd) +} diff --git a/vendor/github.com/vladimirvivien/gexe/filesys.go b/vendor/github.com/vladimirvivien/gexe/filesys.go index bc0d91c5a..ca1cde7f7 100644 --- a/vendor/github.com/vladimirvivien/gexe/filesys.go +++ b/vendor/github.com/vladimirvivien/gexe/filesys.go @@ -1,15 +1,53 @@ package gexe import ( + "os" + "github.com/vladimirvivien/gexe/fs" ) -// Read creates an fs.FileReader using the provided path -func (e *Echo) Read(path string) fs.FileReader { - return fs.Read(e.Eval(path)) +// PathExists returns true if path exists. +// All errors causes to return false. +func (e *Echo) PathExists(path string) bool { + return fs.PathWithVars(path, e.vars).Exists() +} + +// MkDir creates a directory at specified path with mode value. +// FSInfo contains information about the path or error if occured +func (e *Echo) MkDir(path string, mode os.FileMode) *fs.FSInfo { + p := fs.PathWithVars(path, e.vars) + return p.MkDir(mode) +} + +// RmPath removes specified path (dir or file). +// Error is returned FSInfo.Err() +func (e *Echo) RmPath(path string) *fs.FSInfo { + p := fs.PathWithVars(path, e.vars) + return p.Remove() +} + +// PathInfo +func (e *Echo) PathInfo(path string) *fs.FSInfo { + return fs.PathWithVars(path, e.vars).Info() +} + +// FileRead provides methods to read file content +// +// FileRead(path).Lines() +func (e *Echo) FileRead(path string) *fs.FileReader { + return fs.PathWithVars(path, e.vars).Read() +} + +// FileWrite provides methods to write content to provided path +// +// FileWrite(path).String("hello world") +func (e *Echo) FileWrite(path string) *fs.FileWriter { + return fs.PathWithVars(path, e.vars).Write() } -// Write creates an fs.FileWriter using the provided path -func (e *Echo) Write(path string) fs.FileWriter { - return fs.Write(e.Eval(path)) +// FileAppend provides methods to append content to provided path +// +// FileAppend(path).String("hello world") +func (e *Echo) FileAppend(path string) *fs.FileWriter { + return fs.PathWithVars(path, e.vars).Append() } diff --git a/vendor/github.com/vladimirvivien/gexe/fs/file_reader.go b/vendor/github.com/vladimirvivien/gexe/fs/file_reader.go index 061700498..8e5be7f4c 100644 --- a/vendor/github.com/vladimirvivien/gexe/fs/file_reader.go +++ b/vendor/github.com/vladimirvivien/gexe/fs/file_reader.go @@ -5,40 +5,54 @@ import ( "bytes" "io" "os" + + "github.com/vladimirvivien/gexe/vars" ) -type fileReader struct { - err error - path string - finfo os.FileInfo +type FileReader struct { + err error + path string + info os.FileInfo + mode os.FileMode + vars *vars.Variables } -// Read creates a FileReader using the provided path. +// Read creates a new FileReader using the provided path. // A non-nil FileReader.Err() is returned if file does not exist // or another error is generated. -func Read(path string) FileReader { - fr := &fileReader{path: path} - info, err := os.Stat(fr.path) +func Read(path string) *FileReader { + info, err := os.Stat(path) if err != nil { - fr.err = err - return fr + return &FileReader{err: err, path: path} } - fr.finfo = info + return &FileReader{path: path, info: info, mode: info.Mode()} +} + +// ReadWithVars creates a new FileReader and sets the reader's session variables +func ReadWithVars(path string, variables *vars.Variables) *FileReader { + reader := Read(variables.Eval(path)) + reader.vars = variables + return reader +} + +// SetVars sets the FileReader's session variables +func (fr *FileReader) SetVars(variables *vars.Variables) *FileReader { + fr.vars = variables return fr } // Err returns an operation error during file read. -func (fr *fileReader) Err() error { +func (fr *FileReader) Err() error { return fr.err } // Info surfaces the os.FileInfo for the associated file -func (fr *fileReader) Info() os.FileInfo { - return fr.finfo +func (fr *FileReader) Info() os.FileInfo { + return fr.info } // String returns the content of the file as a string value -func (fr *fileReader) String() string { +func (fr *FileReader) String() string { file, err := os.Open(fr.path) if err != nil { fr.err = err @@ -56,7 +70,7 @@ func (fr *fileReader) String() string { } // Lines returns the content of the file as slice of string -func (fr *fileReader) Lines() []string { +func (fr *FileReader) Lines() []string { file, err := os.Open(fr.path) if err != nil { fr.err = err @@ -78,7 +92,7 @@ func (fr *fileReader) Lines() []string { } // Bytes returns the content of the file as []byte -func (fr *fileReader) Bytes() []byte { +func (fr *FileReader) Bytes() []byte { file, err := os.Open(fr.path) if err != nil { fr.err = err @@ -98,7 +112,7 @@ func (fr *fileReader) Bytes() []byte { // Into reads the content of the file and writes // it into the specified Writer -func (fr *fileReader) Into(w io.Writer) FileReader { +func (fr *FileReader) Into(w io.Writer) *FileReader { file, err := os.Open(fr.path) if err != nil { fr.err = err diff --git a/vendor/github.com/vladimirvivien/gexe/fs/file_writer.go b/vendor/github.com/vladimirvivien/gexe/fs/file_writer.go index 5b4d3683c..3360669d7 100644 --- a/vendor/github.com/vladimirvivien/gexe/fs/file_writer.go +++ b/vendor/github.com/vladimirvivien/gexe/fs/file_writer.go @@ -3,21 +3,22 @@ package fs import ( "io" "os" + + "github.com/vladimirvivien/gexe/vars" ) -type fileWriter struct { +type FileWriter struct { path string err error finfo os.FileInfo mode os.FileMode flags int + vars *vars.Variables } -// Write creates a new file,or truncates an existing one, -// using the path provided and sets it up for write operations. -// Operation error is returned by FileWriter.Err(). -func Write(path string) FileWriter { - fw := &fileWriter{path: path, flags: os.O_CREATE | os.O_TRUNC | os.O_WRONLY, mode: 0644} +// Write creates a new FileWriter with flags os.O_CREATE | os.O_TRUNC | os.O_WRONLY and mode 0644. +func Write(path string) *FileWriter { + fw := &FileWriter{path: path, flags: os.O_CREATE | os.O_TRUNC | os.O_WRONLY, mode: 0644, vars: &vars.Variables{}} info, err := os.Stat(fw.path) if err == nil { fw.finfo = info @@ -25,11 +26,16 @@ func Write(path string) FileWriter { return fw } -// Append creates a new file, or append to an existing one, -// using the path provided and sets it up for write operation only. -// Any error generated is returned by FileWriter.Err(). -func Append(path string) FileWriter { - fw := &fileWriter{path: path, flags: os.O_CREATE | os.O_APPEND | os.O_WRONLY, mode: 0644} +// WriteWithVars creates a new FileWriter and sets sessions variables +func WriteWithVars(path string, variables *vars.Variables) *FileWriter { + fw := Write(variables.Eval(path)) + fw.vars = variables + return fw +} + +// Append creates a new FileWriter with flags os.O_CREATE | os.O_APPEND | os.O_WRONLY and mode 0644 +func Append(path string) *FileWriter { + fw := &FileWriter{path: path, flags: os.O_CREATE | os.O_APPEND | os.O_WRONLY, mode: 0644} info, err := os.Stat(fw.path) if err == nil { fw.finfo = info @@ -38,19 +44,39 @@ func Append(path string) FileWriter { return fw } -// Err returns an error during execution -func (fw *fileWriter) Err() error { +// AppendWithVars creates a new FileWriter and sets session variables +func AppendWitVars(path string, variables *vars.Variables) *FileWriter { + fw := Append(variables.Eval(path)) + fw.vars = variables + return fw +} + +// SetVars sets session variables for FileWriter +func (fw *FileWriter) SetVars(variables *vars.Variables) *FileWriter { + if variables != nil { + fw.vars = variables + } + return fw +} + +func (fw *FileWriter) WithMode(mode os.FileMode) *FileWriter { + fw.mode = mode + return fw +} + +// Err returns FileWriter error during execution +func (fw *FileWriter) Err() error { return fw.err } // Info returns the os.FileInfo for the associated file -func (fw *fileWriter) Info() os.FileInfo { +func (fw *FileWriter) Info() os.FileInfo { return fw.finfo } // String writes the provided str into the file. Any // error that occurs can be accessed with FileWriter.Err(). -func (fw *fileWriter) String(str string) FileWriter { +func (fw *FileWriter) String(str string) *FileWriter { file, err := os.OpenFile(fw.path, fw.flags, fw.mode) if err != nil { fw.err = err @@ -69,7 +95,7 @@ func (fw *fileWriter) String(str string) FileWriter { // Lines writes the slice of strings into the file. // Any error will be captured and returned via FileWriter.Err(). -func (fw *fileWriter) Lines(lines []string) FileWriter { +func (fw *FileWriter) Lines(lines []string) *FileWriter { file, err := os.OpenFile(fw.path, fw.flags, fw.mode) if err != nil { fw.err = err @@ -98,7 +124,7 @@ func (fw *fileWriter) Lines(lines []string) FileWriter { // Bytes writes the []bytre provided into the file. // Any error can be accessed using FileWriter.Err(). -func (fw *fileWriter) Bytes(data []byte) FileWriter { +func (fw *FileWriter) Bytes(data []byte) *FileWriter { file, err := os.OpenFile(fw.path, fw.flags, fw.mode) if err != nil { fw.err = err @@ -118,7 +144,7 @@ func (fw *fileWriter) Bytes(data []byte) FileWriter { // From streams bytes from the provided io.Reader r and // writes them to the file. Any error will be captured // and returned by fw.Err(). -func (fw *fileWriter) From(r io.Reader) FileWriter { +func (fw *FileWriter) From(r io.Reader) *FileWriter { file, err := os.OpenFile(fw.path, fw.flags, fw.mode) if err != nil { fw.err = err diff --git a/vendor/github.com/vladimirvivien/gexe/fs/fsinfo.go b/vendor/github.com/vladimirvivien/gexe/fs/fsinfo.go new file mode 100644 index 000000000..b51e4470b --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/fs/fsinfo.go @@ -0,0 +1,51 @@ +package fs + +import ( + "io/fs" + "os" + "time" + + "github.com/vladimirvivien/gexe/vars" +) + +type FSInfo struct { + err error + path string + mode os.FileMode + info os.FileInfo + vars *vars.Variables +} + +// Err returns last opertion error on the directory +func (i *FSInfo) Err() error { + return i.err +} + +// Path is the original path for the directory +func (i *FSInfo) Path() string { + return i.path +} + +func (i *FSInfo) Name() string { + return i.info.Name() +} + +// Mode returns the fs.FileMode for the directory +func (i *FSInfo) Mode() fs.FileMode { + return i.mode +} + +// Size returns the directory size or -1 if not known or error +func (i *FSInfo) Size() int64 { + return i.info.Size() +} + +// IsDir returns true if path points to a directory +func (i *FSInfo) IsDir() bool { + return i.info.IsDir() +} + +// ModTime returns the last know modification time. +func (i *FSInfo) ModTime() time.Time { + return i.info.ModTime() +} diff --git a/vendor/github.com/vladimirvivien/gexe/fs/fspath.go b/vendor/github.com/vladimirvivien/gexe/fs/fspath.go new file mode 100644 index 000000000..4215fd4c7 --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/fs/fspath.go @@ -0,0 +1,115 @@ +package fs + +import ( + "errors" + "io/fs" + "os" + + "github.com/vladimirvivien/gexe/vars" +) + +type FSPath struct { + err error + path string + vars *vars.Variables +} + +// Path points to a node path +func Path(path string) *FSPath { + return &FSPath{path: path} +} + +// PathWithVars points to a path and applies variables to the path value +func PathWithVars(path string, variables *vars.Variables) *FSPath { + p := Path(variables.Eval(path)) + p.vars = variables + return p +} + +// Info returns information about the specified path +func (p *FSPath) Info() *FSInfo { + info, err := os.Stat(p.path) + if err != nil { + return &FSInfo{err: err, path: p.path} + } + return &FSInfo{path: p.path, info: info, mode: info.Mode()} +} + +// Exists returns true only if os.Stat nil error. +// Any other scenarios will return false. +func (p *FSPath) Exists() bool { + if _, err := os.Stat(p.path); err != nil { + return false + } + return true +} + +// MkDir creates a directory with file mode at specified +func (p *FSPath) MkDir(mode fs.FileMode) *FSInfo { + if err := os.MkdirAll(p.path, mode); err != nil { + if !errors.Is(err, os.ErrExist) { + return &FSInfo{err: err, path: p.path} + } + } + info, err := os.Stat(p.path) + if err != nil { + return &FSInfo{err: err, path: p.path} + } + return &FSInfo{path: p.path, info: info, mode: info.Mode(), vars: p.vars} +} + +// Remove removes entry at path +func (p *FSPath) Remove() *FSInfo { + info, err := os.Stat(p.path) + if err != nil { + if os.IsNotExist(err) { + return &FSInfo{path: p.path} + } + return &FSInfo{err: err, path: p.path} + } + if err := os.RemoveAll(p.path); err != nil { + return &FSInfo{err: err, path: p.path, info: info} + } + return &FSInfo{path: p.path, info: info, mode: info.Mode()} +} + +// Read wraps call to create a new *FileReader instance +func (p *FSPath) Read() *FileReader { + if p.vars != nil { + return ReadWithVars(p.path, p.vars) + } + return Read(p.path) +} + +// Write wraps call to create a new *FileWriter instance +func (p *FSPath) Write() *FileWriter { + if p.vars != nil { + return WriteWithVars(p.path, p.vars) + } + return Write(p.path) +} + +// Append wraps call to create a new *FileWriter instance for file append operations +func (p *FSPath) Append() *FileWriter { + if p.vars != nil { + return AppendWitVars(p.path, p.vars) + } + return Append(p.path) +} + +// Dirs returns info about dirs in path +func (p *FSPath) Dirs() (infos []*FSInfo) { + entries, err := os.ReadDir(p.path) + if err != nil { + p.err = err + return nil + } + for _, entry := range entries { + info, err := entry.Info() + if err != nil { + infos = append(infos, &FSInfo{err: err}) + } + infos = append(infos, &FSInfo{info: info, mode: info.Mode()}) + } + return +} diff --git a/vendor/github.com/vladimirvivien/gexe/fs/types.go b/vendor/github.com/vladimirvivien/gexe/fs/types.go deleted file mode 100644 index 8ef18d104..000000000 --- a/vendor/github.com/vladimirvivien/gexe/fs/types.go +++ /dev/null @@ -1,33 +0,0 @@ -package fs - -import ( - "io" - "os" -) - -// FileReader aggregates read operations from -// diverse sources into a file -type FileReader interface { - Err() error - Info() os.FileInfo - String() string - Lines() []string - Bytes() []byte - Into(io.Writer) FileReader -} - -// FileWriter aggregates several file-writing operations from -// diverse sources into a provided file. -type FileWriter interface { - Err() error - Info() os.FileInfo - String(string) FileWriter - Lines([]string) FileWriter - Bytes([]byte) FileWriter - From(io.Reader) FileWriter -} - -// FileAppender is FileWriter with append behavior -type FileAppender interface { - FileWriter -} diff --git a/vendor/github.com/vladimirvivien/gexe/functions.go b/vendor/github.com/vladimirvivien/gexe/functions.go index 7f76889c0..22555a8b2 100644 --- a/vendor/github.com/vladimirvivien/gexe/functions.go +++ b/vendor/github.com/vladimirvivien/gexe/functions.go @@ -1,10 +1,13 @@ package gexe import ( + "os" + "github.com/vladimirvivien/gexe/exec" "github.com/vladimirvivien/gexe/fs" "github.com/vladimirvivien/gexe/http" "github.com/vladimirvivien/gexe/prog" + "github.com/vladimirvivien/gexe/str" "github.com/vladimirvivien/gexe/vars" ) @@ -123,16 +126,40 @@ func Pipe(cmdStrs ...string) *exec.PipedCommandResult { return DefaultEcho.Pipe(cmdStrs...) } -// Read creates an fs.FileReader that -// can be used to read content from files. -func Read(path string) fs.FileReader { - return DefaultEcho.Read(path) +// PathExists returns true if specified path exists. +// Any error will cause it to return false. +func PathExists(path string) bool { + return DefaultEcho.PathExists(path) +} + +// PathInfo returns information for specified path (i.e. size, etc) +func PathInfo(path string) *fs.FSInfo { + return DefaultEcho.PathInfo(path) +} + +// MkDirs creates one or more directories along the specified path +func MkDirs(path string, mode os.FileMode) *fs.FSInfo { + return DefaultEcho.MkDir(path, mode) } -// Write creates an fs.FileWriter that -// can be used to write content to files -func Write(path string) fs.FileWriter { - return DefaultEcho.Write(path) +// MkDir creates a directory with default mode 0744 +func MkDir(path string) *fs.FSInfo { + return DefaultEcho.MkDir(path, 0744) +} + +// RmPath removes files or directories along specified path +func RmPath(path string) *fs.FSInfo { + return DefaultEcho.RmPath(path) +} + +// FileRead provides methods to read file content from path +func FileRead(path string) *fs.FileReader { + return DefaultEcho.FileRead(path) +} + +// FileWrite provides methods to write file content to path +func FileWrite(path string) *fs.FileWriter { + return DefaultEcho.FileWrite(path) } // GetUrl creates a *http.ResourceReader to retrieve HTTP content @@ -149,3 +176,22 @@ func PostUrl(url string) *http.ResourceWriter { func Prog() *prog.Info { return DefaultEcho.Prog() } + +// ProgAvail returns the full path of the program if available. +func ProgAvail(program string) string { + return DefaultEcho.ProgAvail(program) +} + +// Workdir returns the current program's working directory +func Workdir() string { + return DefaultEcho.Workdir() +} + +// AddExecPath adds an executable path to PATH +func AddExecPath(execPath string) { + DefaultEcho.AddExecPath(execPath) +} + +func String(s string) *str.Str { + return DefaultEcho.String(s) +} diff --git a/vendor/github.com/vladimirvivien/gexe/http.go b/vendor/github.com/vladimirvivien/gexe/http.go index a22406ee3..95c657cba 100644 --- a/vendor/github.com/vladimirvivien/gexe/http.go +++ b/vendor/github.com/vladimirvivien/gexe/http.go @@ -1,13 +1,27 @@ package gexe -import "github.com/vladimirvivien/gexe/http" +import ( + "strings" + + "github.com/vladimirvivien/gexe/http" +) // Get creates a *http.ResourceReader to read resource content from HTTP server -func (e *Echo) Get(url string) *http.ResourceReader { - return http.Get(url) +func (e *Echo) Get(url string, paths ...string) *http.ResourceReader { + var exapandedUrl strings.Builder + exapandedUrl.WriteString(e.vars.Eval(url)) + for _, path := range paths { + exapandedUrl.WriteString(e.vars.Eval(path)) + } + return http.GetWithVars(exapandedUrl.String(), e.vars) } // Post creates a *http.ResourceWriter to write content to an HTTP server -func (e *Echo) Post(url string) *http.ResourceWriter { - return http.Post(url) +func (e *Echo) Post(url string, paths ...string) *http.ResourceWriter { + var exapandedUrl strings.Builder + exapandedUrl.WriteString(e.vars.Eval(url)) + for _, path := range paths { + exapandedUrl.WriteString(e.vars.Eval(path)) + } + return http.PostWithVars(exapandedUrl.String(), e.vars) } diff --git a/vendor/github.com/vladimirvivien/gexe/http/http_reader.go b/vendor/github.com/vladimirvivien/gexe/http/http_reader.go index 16653bdf1..60db91d03 100644 --- a/vendor/github.com/vladimirvivien/gexe/http/http_reader.go +++ b/vendor/github.com/vladimirvivien/gexe/http/http_reader.go @@ -3,6 +3,9 @@ package http import ( "io" "net/http" + "time" + + "github.com/vladimirvivien/gexe/vars" ) // ResourceReader provides types and methods to read content of resources from a server using HTTP @@ -10,12 +13,25 @@ type ResourceReader struct { client *http.Client err error url string - res *Response + vars *vars.Variables } // Get initiates a "GET" operation for the specified resource func Get(url string) *ResourceReader { - return &ResourceReader{url: url, client: &http.Client{}} + return &ResourceReader{url: url, client: &http.Client{}, vars: &vars.Variables{}} +} + +// Get initiates a "GET" operation and sets session variables +func GetWithVars(url string, variables *vars.Variables) *ResourceReader { + r := Get(variables.Eval(url)) + r.vars = variables + return r +} + +// SetVars sets session variables for ResourceReader +func (r *ResourceReader) SetVars(variables *vars.Variables) *ResourceReader { + r.vars = variables + return r } // Err returns the last known error @@ -23,62 +39,52 @@ func (r *ResourceReader) Err() error { return r.err } -// Response returns the server's response info -func (r *ResourceReader) Response() *Response { - return r.res +// WithTimeout sets the HTTP reader's timeout +func (r *ResourceReader) WithTimeout(to time.Duration) *ResourceReader { + r.client.Timeout = to + return r +} + +// Do invokes the client.Get to "GET" the content from server +// Use Response.Err() to access server response errors +func (r *ResourceReader) Do() *Response { + res, err := r.client.Get(r.url) + if err != nil { + return &Response{err: err} + } + return &Response{stat: res.Status, statCode: res.StatusCode, body: res.Body} } // Bytes returns the server response as a []byte -func (b *ResourceReader) Bytes() []byte { - if err := b.Do().Err(); err != nil { - b.err = err +// This is a shorthad for ResourceReader.Do().Bytes() +func (r *ResourceReader) Bytes() []byte { + resp := r.Do() + if resp.Err() != nil { + r.err = resp.Err() return nil } - return b.read() + return resp.Bytes() } -// String returns the server response as a string -func (b *ResourceReader) String() string { - if err := b.Do().Err(); err != nil { - b.err = err +// String returns the server response as a string. +// It is a shorthad for ResourceReader.Do().String() +func (r *ResourceReader) String() string { + resp := r.Do() + if resp.Err() != nil { + r.err = resp.Err() return "" } - return string(b.read()) + return resp.String() } -// Body returns an io.ReadCloser to stream the server response. +// Body returns the server response body (as io.ReadCloser). +// It is a shorthand for ResourceReader().Do().Body() // NOTE: ensure to close the stream when finished. func (r *ResourceReader) Body() io.ReadCloser { - if err := r.Do().Err(); err != nil { - r.err = err - return nil - } - return r.res.body -} - -// Do invokes the client.Get to "GET" the content from server -func (r *ResourceReader) Do() *ResourceReader { - res, err := r.client.Get(r.url) - if err != nil { - r.err = err - r.res = &Response{} - return r - } - r.res = &Response{stat: res.Status, statCode: res.StatusCode, body: res.Body} - return r -} - -// read reads the content of the response body and returns a []byte -func (r *ResourceReader) read() []byte { - if r.res.body == nil { - return nil - } - - data, err := io.ReadAll(r.res.body) - defer r.res.body.Close() - if err != nil { - r.err = err + resp := r.Do() + if resp.Err() != nil { + r.err = resp.Err() return nil } - return data + return resp.Body() } diff --git a/vendor/github.com/vladimirvivien/gexe/http/http_response.go b/vendor/github.com/vladimirvivien/gexe/http/http_response.go index adf2de977..6ed82450e 100644 --- a/vendor/github.com/vladimirvivien/gexe/http/http_response.go +++ b/vendor/github.com/vladimirvivien/gexe/http/http_response.go @@ -7,6 +7,7 @@ type Response struct { stat string statCode int body io.ReadCloser + err error } // Status returns the standard lib http.Response.Status value from the server @@ -24,3 +25,33 @@ func (res *Response) StatusCode() int { func (res *Response) Body() io.ReadCloser { return res.body } + +// Err returns the response known error +func (r *Response) Err() error { + return r.err +} + +// Bytes returns the server response as a []byte +func (r *Response) Bytes() []byte { + return r.read() +} + +// String returns the server response as a string +func (r *Response) String() string { + return string(r.read()) +} + +// read reads the content of the response body and returns as []byte +func (r *Response) read() []byte { + if r.body == nil { + return nil + } + + data, err := io.ReadAll(r.body) + defer r.body.Close() + if err != nil { + r.err = err + return nil + } + return data +} diff --git a/vendor/github.com/vladimirvivien/gexe/http/http_writer.go b/vendor/github.com/vladimirvivien/gexe/http/http_writer.go index c3ea4acc2..3aa91637c 100644 --- a/vendor/github.com/vladimirvivien/gexe/http/http_writer.go +++ b/vendor/github.com/vladimirvivien/gexe/http/http_writer.go @@ -6,6 +6,9 @@ import ( "net/http" "net/url" "strings" + "time" + + "github.com/vladimirvivien/gexe/vars" ) // ResourceWriter represents types and methods used to post resource data to an HTTP server @@ -16,11 +19,31 @@ type ResourceWriter struct { headers http.Header data io.Reader res *Response + vars *vars.Variables } // Post starts a "POST" HTTP operation to the provided resource. func Post(resource string) *ResourceWriter { - return &ResourceWriter{url: resource, client: &http.Client{}, headers: make(http.Header)} + return &ResourceWriter{url: resource, client: &http.Client{}, headers: make(http.Header), vars: &vars.Variables{}} +} + +// PostWithVars sets up a "POST" operation and sets its session variables +func PostWithVars(resource string, variables *vars.Variables) *ResourceWriter { + w := Post(variables.Eval(resource)) + w.vars = variables + return w +} + +// SetVars sets session variables for the ResourceWriter +func (w *ResourceWriter) SetVars(variables *vars.Variables) *ResourceWriter { + w.vars = variables + return w +} + +// WithTimeout sets the HTTP client's timeout +func (w *ResourceWriter) WithTimeout(to time.Duration) *ResourceWriter { + w.client.Timeout = to + return w } // Err returns the last known error for the post operation @@ -61,19 +84,19 @@ func (w *ResourceWriter) WithHeaders(h http.Header) *ResourceWriter { // AddHeader is a convenience method to add a single header func (w *ResourceWriter) AddHeader(key, value string) *ResourceWriter { - w.headers.Add(key, value) + w.headers.Add(w.vars.Eval(key), w.vars.Eval(value)) return w } // SetHeader is a convenience method to sets a specific header func (w *ResourceWriter) SetHeader(key, value string) *ResourceWriter { - w.headers.Set(key, value) + w.headers.Set(w.vars.Eval(key), w.vars.Eval(value)) return w } // String posts the string value as content to the server func (w *ResourceWriter) String(val string) *ResourceWriter { - w.data = strings.NewReader(val) + w.data = strings.NewReader(w.vars.Eval(val)) return w.Do() } diff --git a/vendor/github.com/vladimirvivien/gexe/net.go b/vendor/github.com/vladimirvivien/gexe/net.go new file mode 100644 index 000000000..641b72667 --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/net.go @@ -0,0 +1,9 @@ +package gexe + +import ( + "github.com/vladimirvivien/gexe/net" +) + +func (e *Echo) AddressUsable(addr string) error { + return net.AddrUsable(e.Eval(addr)) +} diff --git a/vendor/github.com/vladimirvivien/gexe/net/listener.go b/vendor/github.com/vladimirvivien/gexe/net/listener.go new file mode 100644 index 000000000..71a17b59a --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/net/listener.go @@ -0,0 +1,29 @@ +package net + +import ( + "errors" + "fmt" + "net" + "os" + "syscall" +) + +func AddrUsable(address string) error { + addr, err := net.ResolveTCPAddr("tcp", address) + if err != nil { + return fmt.Errorf("net: address parsing: %s", err) + } + + lsnr, err := net.Listen(addr.Network(), addr.String()) + + if err != nil { + sysErr, ok := err.(*os.SyscallError) + if ok && errors.Is(sysErr.Err, syscall.EADDRINUSE) { + return fmt.Errorf("net: addr in use: %s", sysErr.Err) + } + return fmt.Errorf("net: %s", err) + } + + defer lsnr.Close() + return nil +} diff --git a/vendor/github.com/vladimirvivien/gexe/procs.go b/vendor/github.com/vladimirvivien/gexe/procs.go index 251e579ff..ed230675b 100644 --- a/vendor/github.com/vladimirvivien/gexe/procs.go +++ b/vendor/github.com/vladimirvivien/gexe/procs.go @@ -10,25 +10,25 @@ import ( // without starting. Use Proc.Wait to wait for exection and then retrieve process result. // Information about the running process is stored in *exec.Proc. func (e *Echo) NewProc(cmdStr string) *exec.Proc { - return exec.NewProc(cmdStr) + return exec.NewProcWithVars(cmdStr, e.vars) } // StartProc executes the command in cmdStr and returns immediately // without waiting. Use Proc.Wait to wait for exection and then retrieve process result. // Information about the running process is stored in *Proc. func (e *Echo) StartProc(cmdStr string) *exec.Proc { - return exec.StartProc(e.Eval(cmdStr)) + return exec.StartProcWithVars(cmdStr, e.vars) } // RunProc executes command in cmdStr and waits for the result. // It returns a *Proc with information about the executed process. func (e *Echo) RunProc(cmdStr string) *exec.Proc { - return exec.RunProc(e.Eval(cmdStr)) + return exec.RunProcWithVars(cmdStr, e.vars) } // Run executes cmdStr, waits, and returns the result as a string. func (e *Echo) Run(cmdStr string) string { - return exec.Run(e.Eval(cmdStr)) + return exec.RunWithVars(cmdStr, e.vars) } // Runout executes command cmdStr and prints out the result @@ -38,52 +38,45 @@ func (e *Echo) Runout(cmdStr string) { // Commands returns a *exe.CommandBuilder to build a multi-command execution flow. func (e *Echo) Commands(cmdStrs ...string) *exec.CommandBuilder { - for i, cmd := range cmdStrs { - cmdStrs[i] = e.Eval(cmd) - } - return exec.Commands(cmdStrs...) + return exec.CommandsWithVars(e.vars, cmdStrs...) } // StartAll starts the sequential execution of each command, in cmdStrs, and does not // wait for their completion. func (e *Echo) StartAll(cmdStrs ...string) *exec.CommandResult { - for i, cmd := range cmdStrs { - cmdStrs[i] = e.Eval(cmd) - } - return exec.Commands(cmdStrs...).Start() + return exec.CommandsWithVars(e.vars, cmdStrs...).Start() } // RunAll executes each command sequentially, in cmdStrs, and wait for their completion. func (e *Echo) RunAll(cmdStrs ...string) *exec.CommandResult { - for i, cmd := range cmdStrs { - cmdStrs[i] = e.Eval(cmd) - } - return exec.Commands(cmdStrs...).Run() + return exec.CommandsWithVars(e.vars, cmdStrs...).Run() } // StartConcur starts the concurrent execution of each command, in cmdStrs, and does not // wait for their completion. func (e *Echo) StartConcur(cmdStrs ...string) *exec.CommandResult { - for i, cmd := range cmdStrs { - cmdStrs[i] = e.Eval(cmd) - } - return exec.Commands(cmdStrs...).Concurr() + return exec.CommandsWithVars(e.vars, cmdStrs...).Concurr() } // RunConcur executes each command concurrently, in cmdStrs, and waits // their completion. func (e *Echo) RunConcur(cmdStrs ...string) *exec.CommandResult { - for i, cmd := range cmdStrs { - cmdStrs[i] = e.Eval(cmd) - } - return exec.Commands(cmdStrs...).Concurr().Wait() + return exec.CommandsWithVars(e.vars, cmdStrs...).Concurr().Wait() } // Pipe executes each command, in cmdStrs, by piping the result // of the previous command as input to the next command until done. func (e *Echo) Pipe(cmdStrs ...string) *exec.PipedCommandResult { - for i, cmd := range cmdStrs { - cmdStrs[i] = e.Eval(cmd) + return exec.CommandsWithVars(e.vars, cmdStrs...).Pipe() +} + +// ParseCommand parses the string into individual command tokens +func (e *Echo) ParseCommand(cmdStr string) (cmdName string, args []string) { + result, err := exec.Parse(e.vars.Eval(cmdStr)) + if err != nil { + e.err = err } - return exec.Commands(cmdStrs...).Pipe() + cmdName = result[0] + args = result[1:] + return } diff --git a/vendor/github.com/vladimirvivien/gexe/prog.go b/vendor/github.com/vladimirvivien/gexe/prog.go index 2f342ce88..e353a74d6 100644 --- a/vendor/github.com/vladimirvivien/gexe/prog.go +++ b/vendor/github.com/vladimirvivien/gexe/prog.go @@ -4,8 +4,12 @@ import ( "github.com/vladimirvivien/gexe/prog" ) -// Prog creates a new prog.Info to get information -// about the running program +// Prog makes info available about currently executing program func (e *Echo) Prog() *prog.Info { return e.prog } + +// Workdir returns the current program's working directory +func (e *Echo) Workdir() string { + return e.Prog().Workdir() +} diff --git a/vendor/github.com/vladimirvivien/gexe/prog/prog.go b/vendor/github.com/vladimirvivien/gexe/prog/prog.go index 908e0c6db..c7697ca9b 100644 --- a/vendor/github.com/vladimirvivien/gexe/prog/prog.go +++ b/vendor/github.com/vladimirvivien/gexe/prog/prog.go @@ -62,6 +62,7 @@ func (p *Info) Name() string { } // Avail returns full path of binary name if available +// Deprecated: use echo.ProgAvail or gexe.ProgAvail func (p *Info) Avail(progName string) string { path, err := exec.LookPath(progName) if err != nil { diff --git a/vendor/github.com/vladimirvivien/gexe/str.go b/vendor/github.com/vladimirvivien/gexe/str.go new file mode 100644 index 000000000..251dfffc6 --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/str.go @@ -0,0 +1,8 @@ +package gexe + +import "github.com/vladimirvivien/gexe/str" + +// String creates a new str.Str value with string manipulation methods +func (e *Echo) String(s string) *str.Str { + return str.StringWithVars(s, e.vars) +} diff --git a/vendor/github.com/vladimirvivien/gexe/str/functions.go b/vendor/github.com/vladimirvivien/gexe/str/functions.go new file mode 100644 index 000000000..75c779bcd --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/str/functions.go @@ -0,0 +1,53 @@ +package str + +import ( + "fmt" +) + +// IsEmpty tests for str == "" +func IsEmpty(str string) bool { + return String(str).IsEmpty() +} + +// SplitLines splits each line from str into []string +func SplitLines(str string) []string { + return String(str).SplitLines() +} + +// SplitSpaces splits str by blank chars (space,\t,\n) +func SplitSpaces(str string) []string { + return String(str).SplitSpaces() +} + +// Bool returns the bool equivalent of str ("true" = true, etc) +// A parsing error will cause a program panic. +func Bool(str string) bool { + s := String(str) + result := s.Bool() + if s.Err() != nil { + panic(fmt.Sprintf("%s", s.Err())) + } + return result +} + +// Int returns the int representation of str. +// A parsing error will cause a program panic. +func Int(str string) int { + s := String(str) + result := s.Int() + if s.Err() != nil { + panic(fmt.Sprintf("%s", s.Err())) + } + return result +} + +// Float64 returns the float64 representation of str. +// A parsing error will cause a program panic. +func Float64(str string) float64 { + s := String(str) + result := s.Float64() + if s.Err() != nil { + panic(fmt.Sprintf("%s", s.Err())) + } + return result +} diff --git a/vendor/github.com/vladimirvivien/gexe/str/strings.go b/vendor/github.com/vladimirvivien/gexe/str/strings.go new file mode 100644 index 000000000..53e2157df --- /dev/null +++ b/vendor/github.com/vladimirvivien/gexe/str/strings.go @@ -0,0 +1,185 @@ +package str + +import ( + "bytes" + "io" + "regexp" + "strconv" + "strings" + + "github.com/vladimirvivien/gexe/vars" +) + +var ( + notSpaceRegex = regexp.MustCompile(`\S`) +) + +// Str represents a string value +type Str struct { + val string + err error + vars *vars.Variables +} + +// String is constructor function that returns *Str +func String(str string) *Str { + return &Str{val: str, vars: &vars.Variables{}} +} + +// StringWithVars sets session variables and calls func String +func StringWithVars(str string, variables *vars.Variables) *Str { + s := String(variables.Eval(str)) + s.vars = variables + return s +} + +// String returns the string value +func (s *Str) String() string { + return s.val +} + +// Err returns any captured error +func (s *Str) Err() error { + return s.err +} + +// IsEmpty returns true if len(s) == 0 +func (s *Str) IsEmpty() bool { + return s.val == "" +} + +// Eq returns true if both strings are equal +func (s *Str) Eq(val1 string) bool { + return strings.EqualFold(s.val, val1) +} + +// Split s.val using the sep as delimiter +func (s *Str) Split(sep string) []string { + return strings.Split(s.val, sep) +} + +// SplitLines splits s.val using \n as delimiter +func (s *Str) SplitLines() []string { + return strings.Split(s.val, "\n") +} + +// SplitSpaces properly splits s.val into []elements +// separated by one or more Unicode.IsSpace characters +// i.e. SplitSpaces("ab cd e\tf\ng") returns 5 elements +func (s *Str) SplitSpaces() []string { + return notSpaceRegex.Split(s.val, -1) +} + +// SplitRegex uses regular expression exp to split s.val +func (s *Str) SplitRegex(exp string) []string { + return regexp.MustCompile(exp).Split(s.val, -1) +} + +// Bytes returns []byte(s.val) +func (s *Str) Bytes() []byte { + return []byte(s.val) +} + +// Bool converts s.val from string to a bool representation +// Check s.Err() for parsing errors +func (s *Str) Bool() bool { + val, err := strconv.ParseBool(s.val) + if err != nil { + s.err = err + } + return val +} + +// Int converts s.val from string to a int representation +// Check s.Err() for parsing errors +func (s *Str) Int() int { + val, err := strconv.Atoi(s.val) + if err != nil { + s.err = err + } + return val +} + +// Float64 converts s.val from string to a float64 representation +// Check s.Error() for parsing errors +func (s *Str) Float64() float64 { + val, err := strconv.ParseFloat(s.val, 64) + if err != nil { + s.err = err + } + return val +} + +// Reader returns an io.Reader to access the content. +func (s *Str) Reader() io.Reader { + return bytes.NewReader([]byte(s.val)) +} + +// ToLower returns val as lower case +func (s *Str) ToLower() *Str { + s.val = strings.ToLower(s.val) + return s +} + +// ToUpper returns val as upper case +func (s *Str) ToUpper() *Str { + s.val = strings.ToUpper(s.val) + return s +} + +// ToTitle returns strings.ToTitle for s.val +func (s *Str) ToTitle() *Str { + s.val = strings.ToTitle(s.val) + return s +} + +// TrimSpaces removes spaces around a val +func (s *Str) TrimSpaces() *Str { + s.val = strings.TrimSpace(s.val) + return s +} + +// TrimLeft removes each character in cutset at the +// start of s.val +func (s *Str) TrimLeft(cutset string) *Str { + s.val = strings.TrimLeft(s.val, cutset) + return s +} + +// TrimRight removes each character in cutset removed at the +// start of s.val +func (s *Str) TrimRight(cutset string) *Str { + s.val = strings.TrimRight(s.val, cutset) + return s +} + +// Trim removes each character in cutset from around s.val +func (s *Str) Trim(cutset string) *Str { + s.val = strings.Trim(s.val, cutset) + return s +} + +// ReplaceAll replaces all occurrences of old with new in s.val +func (s *Str) ReplaceAll(old, new string) *Str { + s.val = strings.ReplaceAll(s.val, old, new) + return s +} + +// Concat concatenates val1 to s.val +func (s *Str) Concat(vals ...string) *Str { + evals := []string{s.val} + for _, val := range vals { + evals = append(evals, s.vars.Eval(val)) + } + s.val = strings.Join(evals, "") + return s +} + +// CopyTo copies s.val unto dest +// Check s.Error() for copy error. +func (s *Str) CopyTo(dest io.Writer) *Str { + if _, err := io.Copy(dest, bytes.NewBufferString(s.val)); err != nil { + s.err = err + } + return s +} diff --git a/vendor/github.com/vladimirvivien/gexe/variables.go b/vendor/github.com/vladimirvivien/gexe/variables.go index 54230ee0a..657d6d58e 100644 --- a/vendor/github.com/vladimirvivien/gexe/variables.go +++ b/vendor/github.com/vladimirvivien/gexe/variables.go @@ -52,6 +52,13 @@ func (e *Echo) SetVar(name, value string) *Echo { return e } +// UnsetVar removes a session variable. +func (e *Echo) UnsetVar(name string) *Echo { + vars := e.vars.UnsetVar(name) + e.err = vars.Err() + return e +} + // Val retrieves a session or environment variable func (e *Echo) Val(name string) string { return e.vars.Val(name) diff --git a/vendor/github.com/vladimirvivien/gexe/vars/variables.go b/vendor/github.com/vladimirvivien/gexe/vars/variables.go index ae6cdaf65..4d32de8c0 100644 --- a/vendor/github.com/vladimirvivien/gexe/vars/variables.go +++ b/vendor/github.com/vladimirvivien/gexe/vars/variables.go @@ -95,6 +95,14 @@ func (v *Variables) SetVar(name, value string) *Variables { return v } +// UnsetVar removes a previously set local variable. +func (v *Variables) UnsetVar(name string) *Variables { + v.Lock() + defer v.Unlock() + delete(v.vars, name) + return v +} + // Val searches for a Var with provided key, if not found // searches for environment var, for running process, with same key func (v *Variables) Val(name string) string { diff --git a/vendor/modules.txt b/vendor/modules.txt index 746e20448..66cb1e556 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -456,13 +456,15 @@ github.com/vishvananda/netlink/nl # github.com/vishvananda/netns v0.0.4 ## explicit; go 1.17 github.com/vishvananda/netns -# github.com/vladimirvivien/gexe v0.2.0 -## explicit; go 1.16 +# github.com/vladimirvivien/gexe v0.3.0 +## explicit; go 1.22 github.com/vladimirvivien/gexe github.com/vladimirvivien/gexe/exec github.com/vladimirvivien/gexe/fs github.com/vladimirvivien/gexe/http +github.com/vladimirvivien/gexe/net github.com/vladimirvivien/gexe/prog +github.com/vladimirvivien/gexe/str github.com/vladimirvivien/gexe/vars # github.com/vmware/go-ipfix v0.9.0 ## explicit; go 1.21