Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Give full output of git command on errors #2054

Merged
merged 2 commits into from
May 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 33 additions & 23 deletions git/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ package git
import (
"bufio"
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"strings"

"context"
"sync"

"github.com/pkg/errors"
)
Expand Down Expand Up @@ -303,7 +302,7 @@ func changed(ctx context.Context, workingDir, ref string, subPaths []string) ([]
}

// traceGitCommand returns a log line that can be useful when debugging and developing git activity
func traceGitCommand(args []string, config gitCmdConfig, stdout string, stderr string) string {
func traceGitCommand(args []string, config gitCmdConfig, stdOutAndStdErr string) string {
for _, exemptedCommand := range exemptedTraceCommands {
if exemptedCommand == args[0] {
return ""
Expand All @@ -318,19 +317,34 @@ func traceGitCommand(args []string, config gitCmdConfig, stdout string, stderr s
}

command := `git ` + strings.Join(args, " ")
out := prepare(stdout)
err := prepare(stderr)
out := prepare(stdOutAndStdErr)

return fmt.Sprintf(
"TRACE: command=%q out=%q err=%q dir=%q env=%q",
"TRACE: command=%q out=%q dir=%q env=%q",
command,
out,
err,
config.dir,
strings.Join(config.env, ","),
)
}

type threadSafeBuffer struct {
bytes.Buffer
sync.Mutex
}

func (b *threadSafeBuffer) Write(p []byte) (n int, err error) {
b.Lock()
defer b.Unlock()
return b.Buffer.Write(p)
}

func (b *threadSafeBuffer) ReadFrom(r io.Reader) (n int64, err error) {
b.Lock()
defer b.Unlock()
return b.Buffer.ReadFrom(r)
}

// execGitCmd runs a `git` command with the supplied arguments.
func execGitCmd(ctx context.Context, args []string, config gitCmdConfig) error {
c := exec.CommandContext(ctx, "git", args...)
Expand All @@ -339,30 +353,26 @@ func execGitCmd(ctx context.Context, args []string, config gitCmdConfig) error {
c.Dir = config.dir
}
c.Env = append(env(), config.env...)
c.Stdout = ioutil.Discard
stdOutAndStdErr := &threadSafeBuffer{}
c.Stdout = stdOutAndStdErr
c.Stderr = stdOutAndStdErr
if config.out != nil {
c.Stdout = config.out
}
errOut := &bytes.Buffer{}
c.Stderr = errOut

traceStdout := &bytes.Buffer{}
traceStderr := &bytes.Buffer{}
if trace {
c.Stdout = io.MultiWriter(c.Stdout, traceStdout)
c.Stderr = io.MultiWriter(c.Stderr, traceStderr)
c.Stdout = io.MultiWriter(c.Stdout, config.out)
}

err := c.Run()
if err != nil {
msg := findErrorMessage(errOut)
if msg != "" {
err = errors.New(msg)
if len(stdOutAndStdErr.Bytes()) > 0 {
err = errors.New(stdOutAndStdErr.String())
msg := findErrorMessage(stdOutAndStdErr)
squaremo marked this conversation as resolved.
Show resolved Hide resolved
if msg != "" {
err = fmt.Errorf("%s, full output:\n %s", msg, err.Error())
squaremo marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

if trace {
if traceCommand := traceGitCommand(args, config, traceStdout.String(), traceStderr.String()); traceCommand != "" {
if traceCommand := traceGitCommand(args, config, stdOutAndStdErr.String()); traceCommand != "" {
println(traceCommand)
}
}
Expand Down
9 changes: 4 additions & 5 deletions git/operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ func TestTraceGitCommand(t *testing.T) {
dir: "/tmp/flux-working628880789",
},
},
expected: `TRACE: command="git clone --branch master /tmp/flux-gitclone239583443 /tmp/flux-working628880789" out="" err="" dir="/tmp/flux-working628880789" env=""`,
expected: `TRACE: command="git clone --branch master /tmp/flux-gitclone239583443 /tmp/flux-working628880789" out="" dir="/tmp/flux-working628880789" env=""`,
},
{
name: "git rev-list",
Expand All @@ -333,7 +333,7 @@ func TestTraceGitCommand(t *testing.T) {
dir: "/tmp/flux-gitclone239583443",
},
},
expected: `TRACE: command="git rev-list --max-count 1 flux-sync --" out="b9d6a543acf8085ff6bed23fac17f8dc71bfcb66" err="" dir="/tmp/flux-gitclone239583443" env=""`,
expected: `TRACE: command="git rev-list --max-count 1 flux-sync --" out="b9d6a543acf8085ff6bed23fac17f8dc71bfcb66" dir="/tmp/flux-gitclone239583443" env=""`,
},
{
name: "git config email",
Expand All @@ -347,7 +347,7 @@ func TestTraceGitCommand(t *testing.T) {
dir: "/tmp/flux-working056923691",
},
},
expected: `TRACE: command="git config user.email [email protected]" out="" err="" dir="/tmp/flux-working056923691" env=""`,
expected: `TRACE: command="git config user.email [email protected]" out="" dir="/tmp/flux-working056923691" env=""`,
},
{
name: "git notes",
Expand All @@ -363,15 +363,14 @@ func TestTraceGitCommand(t *testing.T) {
},
out: "refs/notes/flux",
},
expected: `TRACE: command="git notes --ref flux get-ref" out="refs/notes/flux" err="" dir="/tmp/flux-working647148942" env=""`,
expected: `TRACE: command="git notes --ref flux get-ref" out="refs/notes/flux" dir="/tmp/flux-working647148942" env=""`,
},
}
for _, example := range examples {
actual := traceGitCommand(
example.input.args,
example.input.config,
example.input.out,
example.input.err,
)
assert.Equal(t, example.expected, actual)
}
Expand Down