@@ -2,19 +2,99 @@ package debugcmd
22
33import (
44 "context"
5+ "fmt"
56 "os"
67 "os/exec"
8+ "strings"
9+ "sync"
710)
811
9- func New (ctx context.Context , arg string , args ... string ) * exec.Cmd {
10- cmd := exec .CommandContext (ctx , arg , args ... )
11- SetupDebug (cmd )
12- return cmd
12+ type WrappedCmd struct {
13+ c * exec.Cmd
14+ r recorder
15+ Env []string
16+ Dir string
1317}
1418
15- func SetupDebug (cmd * exec.Cmd ) {
19+ func (w * WrappedCmd ) Run () error {
20+ if len (w .Env ) > 0 {
21+ w .c .Env = w .Env
22+ }
23+ if w .Dir != "" {
24+ w .c .Dir = w .Dir
25+ }
26+ if err := w .c .Run (); err != nil {
27+ msg := w .r .dump ()
28+ if msg != "" {
29+ return fmt .Errorf ("%w: %s" , err , msg )
30+ }
31+ return err
32+ }
33+ return nil
34+ }
35+
36+ func New (ctx context.Context , arg string , args ... string ) * WrappedCmd {
37+ w := & WrappedCmd {
38+ c : exec .CommandContext (ctx , arg , args ... ),
39+ }
40+ setupDebug (w )
41+ return w
42+ }
43+
44+ type entry struct {
45+ err bool
46+ data []byte
47+ }
48+
49+ type recorder struct {
50+ lock sync.Mutex
51+ entries []entry
52+ }
53+
54+ func (r * recorder ) dump () string {
55+ var errMessage strings.Builder
56+ for _ , entry := range r .entries {
57+ if entry .err {
58+ errMessage .Write (entry .data )
59+ _ , _ = os .Stderr .Write (entry .data )
60+ } else {
61+ _ , _ = os .Stdout .Write (entry .data )
62+ }
63+ }
64+ return errMessage .String ()
65+ }
66+
67+ type writer struct {
68+ err bool
69+ r * recorder
70+ }
71+
72+ func (w * writer ) Write (data []byte ) (int , error ) {
73+ w .r .lock .Lock ()
74+ defer w .r .lock .Unlock ()
75+
76+ cp := make ([]byte , len (data ))
77+ copy (cp , data )
78+
79+ w .r .entries = append (w .r .entries , entry {
80+ err : w .err ,
81+ data : cp ,
82+ })
83+
84+ return len (data ), nil
85+ }
86+
87+ func setupDebug (w * WrappedCmd ) {
1688 if log .IsDebug () {
17- cmd .Stdout = os .Stdout
89+ w .c .Stdout = os .Stdout
90+ w .c .Stderr = os .Stderr
91+ } else {
92+ w .c .Stdout = & writer {
93+ r : & w .r ,
94+ }
95+ w .c .Stderr = & writer {
96+ err : true ,
97+ r : & w .r ,
98+ }
1899 }
19- cmd .Stderr = os .Stderr
20100}
0 commit comments