Skip to content

Commit

Permalink
exec: full argument logging
Browse files Browse the repository at this point in the history
  • Loading branch information
rsteube committed Jan 11, 2024
1 parent 69aa9d6 commit 690c69c
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 34 deletions.
8 changes: 4 additions & 4 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (

"github.com/rsteube/carapace/internal/env"
"github.com/rsteube/carapace/internal/shell/zsh"
"github.com/rsteube/carapace/pkg/execlog"
"github.com/rsteube/carapace/pkg/util"
"github.com/rsteube/carapace/third_party/github.com/drone/envsubst"
"github.com/rsteube/carapace/third_party/golang.org/x/sys/execabs"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -88,16 +88,16 @@ func (c Context) Envsubst(s string) (string, error) {
// Command returns the Cmd struct to execute the named program with the given arguments.
// Env and Dir are set using the Context.
// See exec.Command for most details.
func (c Context) Command(name string, arg ...string) *execabs.Cmd {
func (c Context) Command(name string, arg ...string) *execlog.Cmd {
if c.mockedReplies != nil {
if m, err := json.Marshal(append([]string{name}, arg...)); err == nil {
if reply, exists := c.mockedReplies[string(m)]; exists {
return execabs.Command("echo", reply)
return execlog.Command("echo", reply) // TODO use mock
}
}
}

cmd := execabs.Command(name, arg...)
cmd := execlog.Command(name, arg...)
cmd.Env = c.Env
cmd.Dir = c.Dir
return cmd
Expand Down
1 change: 0 additions & 1 deletion defaultActions.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ func ActionExecCommandE(name string, arg ...string) func(f func(output []byte, e
cmd := c.Command(name, arg...)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
LOG.Printf("executing %#v", cmd.String())
if err := cmd.Run(); err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
exitErr.Stderr = stderr.Bytes() // seems this needs to be set manually due to stdout being collected?
Expand Down
32 changes: 32 additions & 0 deletions internal/log/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package log

import (
"fmt"
"io/ioutil"
"log"
"os"

"github.com/rsteube/carapace/internal/env"
"github.com/rsteube/carapace/internal/uid"
"github.com/rsteube/carapace/pkg/ps"
)

var LOG = log.New(ioutil.Discard, "", log.Flags())

func init() {
if !env.Log() {
return
}

tmpdir := fmt.Sprintf("%v/carapace", os.TempDir())
if err := os.MkdirAll(tmpdir, os.ModePerm); err != nil {
log.Fatal(err.Error())
}

file := fmt.Sprintf("%v/%v.log", tmpdir, uid.Executable())
if logfileWriter, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o666); err != nil {
log.Fatal(err.Error())
} else {
LOG = log.New(logfileWriter, ps.DetermineShell()+" ", log.Flags()|log.Lmsgprefix|log.Lmicroseconds)
}
}
31 changes: 2 additions & 29 deletions log.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,5 @@
package carapace

import (
"fmt"
"io/ioutil"
"log"
"os"
import "github.com/rsteube/carapace/internal/log"

"github.com/rsteube/carapace/internal/env"
"github.com/rsteube/carapace/internal/uid"
"github.com/rsteube/carapace/pkg/ps"
)

var LOG = log.New(ioutil.Discard, "", log.Flags())

func init() {
if !env.Log() {
return
}

tmpdir := fmt.Sprintf("%v/carapace", os.TempDir())
if err := os.MkdirAll(tmpdir, os.ModePerm); err != nil {
log.Fatal(err.Error())
}

file := fmt.Sprintf("%v/%v.log", tmpdir, uid.Executable())
if logfileWriter, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o666); err != nil {
log.Fatal(err.Error())
} else {
LOG = log.New(logfileWriter, ps.DetermineShell()+" ", log.Flags()|log.Lmsgprefix|log.Lmicroseconds)
}
}
var LOG = log.LOG
33 changes: 33 additions & 0 deletions pkg/execlog/execlog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package execlog

import (
"github.com/rsteube/carapace/internal/log"
"github.com/rsteube/carapace/pkg/util"
"github.com/rsteube/carapace/third_party/golang.org/x/sys/execabs"
)

type Cmd struct {
*execabs.Cmd
}

// Command is like exec.Command but logs args on execution.
func Command(name string, arg ...string) *Cmd {
cmd := &Cmd{
execabs.Command(name, arg...),
}
return cmd
}

func (c *Cmd) Run() error {
log.LOG.Printf("executing %#v", util.FormatCmd(c.Args...))
return c.Cmd.Run()
}

func (c *Cmd) Start() error {
log.LOG.Printf("executing %#v", util.FormatCmd(c.Args...))
return c.Cmd.Start()
}

func LookPath(file string) (string, error) {
return execabs.LookPath(file)
}
24 changes: 24 additions & 0 deletions pkg/util/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package util

import (
"fmt"
"strings"
)

func FormatCmd(args ...string) string {
replacer := strings.NewReplacer(
"$", "\\$",
"`", "\\`",
)

formatted := make([]string, 0, len(args))
for _, arg := range args {
switch {
case strings.ContainsAny(arg, `"' `+"\n\r\t"):
formatted = append(formatted, replacer.Replace(fmt.Sprintf("%#v", arg)))
default:
formatted = append(formatted, arg)
}
}
return strings.Join(formatted, " ")
}

0 comments on commit 690c69c

Please sign in to comment.