@@ -40,7 +40,7 @@ const DefaultLocale = "C"
40
40
41
41
// Command represents a command with its subcommands or arguments.
42
42
type Command struct {
43
- name string
43
+ prog string
44
44
args []string
45
45
parentContext context.Context
46
46
desc string
@@ -49,10 +49,28 @@ type Command struct {
49
49
}
50
50
51
51
func (c * Command ) String () string {
52
- if len (c .args ) == 0 {
53
- return c .name
52
+ return c .toString (false )
53
+ }
54
+
55
+ func (c * Command ) toString (sanitizing bool ) string {
56
+ // WARNING: this function is for debugging purposes only. It's much better than old code (which only joins args with space),
57
+ // It's impossible to make a simple and 100% correct implementation of argument quoting for different platforms.
58
+ debugQuote := func (s string ) string {
59
+ if strings .ContainsAny (s , " `'\" \t \r \n " ) {
60
+ return fmt .Sprintf ("%q" , s )
61
+ }
62
+ return s
63
+ }
64
+ a := make ([]string , 0 , len (c .args )+ 1 )
65
+ a = append (a , debugQuote (c .prog ))
66
+ for _ , arg := range c .args {
67
+ if sanitizing && (strings .Contains (arg , "://" ) && strings .Contains (arg , "@" )) {
68
+ a = append (a , debugQuote (util .SanitizeCredentialURLs (arg )))
69
+ } else {
70
+ a = append (a , debugQuote (arg ))
71
+ }
54
72
}
55
- return fmt . Sprintf ( "%s %s" , c . name , strings .Join (c . args , " " ) )
73
+ return strings .Join (a , " " )
56
74
}
57
75
58
76
// NewCommand creates and returns a new Git Command based on given command and arguments.
@@ -67,7 +85,7 @@ func NewCommand(ctx context.Context, args ...internal.CmdArg) *Command {
67
85
cargs = append (cargs , string (arg ))
68
86
}
69
87
return & Command {
70
- name : GitExecutable ,
88
+ prog : GitExecutable ,
71
89
args : cargs ,
72
90
parentContext : ctx ,
73
91
globalArgsLength : len (globalCommandArgs ),
@@ -82,7 +100,7 @@ func NewCommandContextNoGlobals(ctx context.Context, args ...internal.CmdArg) *C
82
100
cargs = append (cargs , string (arg ))
83
101
}
84
102
return & Command {
85
- name : GitExecutable ,
103
+ prog : GitExecutable ,
86
104
args : cargs ,
87
105
parentContext : ctx ,
88
106
}
@@ -250,28 +268,18 @@ func (c *Command) Run(opts *RunOpts) error {
250
268
}
251
269
252
270
if len (opts .Dir ) == 0 {
253
- log .Debug ("%s" , c )
271
+ log .Debug ("git.Command.Run: %s" , c )
254
272
} else {
255
- log .Debug ("%s : %v " , opts .Dir , c )
273
+ log .Debug ("git.Command.RunDir(%s) : %s " , opts .Dir , c )
256
274
}
257
275
258
276
desc := c .desc
259
277
if desc == "" {
260
- args := c .args [c .globalArgsLength :]
261
- var argSensitiveURLIndexes []int
262
- for i , arg := range c .args {
263
- if strings .Contains (arg , "://" ) && strings .Contains (arg , "@" ) {
264
- argSensitiveURLIndexes = append (argSensitiveURLIndexes , i )
265
- }
266
- }
267
- if len (argSensitiveURLIndexes ) > 0 {
268
- args = make ([]string , len (c .args ))
269
- copy (args , c .args )
270
- for _ , urlArgIndex := range argSensitiveURLIndexes {
271
- args [urlArgIndex ] = util .SanitizeCredentialURLs (args [urlArgIndex ])
272
- }
278
+ if opts .Dir == "" {
279
+ desc = fmt .Sprintf ("git: %s" , c .toString (true ))
280
+ } else {
281
+ desc = fmt .Sprintf ("git(dir:%s): %s" , opts .Dir , c .toString (true ))
273
282
}
274
- desc = fmt .Sprintf ("%s %s [repo_path: %s]" , c .name , strings .Join (args , " " ), opts .Dir )
275
283
}
276
284
277
285
var ctx context.Context
@@ -285,7 +293,7 @@ func (c *Command) Run(opts *RunOpts) error {
285
293
}
286
294
defer finished ()
287
295
288
- cmd := exec .CommandContext (ctx , c .name , c .args ... )
296
+ cmd := exec .CommandContext (ctx , c .prog , c .args ... )
289
297
if opts .Env == nil {
290
298
cmd .Env = os .Environ ()
291
299
} else {
0 commit comments