@@ -2,19 +2,99 @@ package debugcmd
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"os"
6
7
"os/exec"
8
+ "strings"
9
+ "sync"
7
10
)
8
11
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
13
17
}
14
18
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 ) {
16
88
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
+ }
18
99
}
19
- cmd .Stderr = os .Stderr
20
100
}
0 commit comments