@@ -40,7 +40,7 @@ const DefaultLocale = "C"
4040
4141// Command represents a command with its subcommands or arguments.
4242type Command struct {
43- name string
43+ prog string
4444 args []string
4545 parentContext context.Context
4646 desc string
@@ -49,10 +49,28 @@ type Command struct {
4949}
5050
5151func (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+ }
5472 }
55- return fmt . Sprintf ( "%s %s" , c . name , strings .Join (c . args , " " ) )
73+ return strings .Join (a , " " )
5674}
5775
5876// 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 {
6785 cargs = append (cargs , string (arg ))
6886 }
6987 return & Command {
70- name : GitExecutable ,
88+ prog : GitExecutable ,
7189 args : cargs ,
7290 parentContext : ctx ,
7391 globalArgsLength : len (globalCommandArgs ),
@@ -82,7 +100,7 @@ func NewCommandContextNoGlobals(ctx context.Context, args ...internal.CmdArg) *C
82100 cargs = append (cargs , string (arg ))
83101 }
84102 return & Command {
85- name : GitExecutable ,
103+ prog : GitExecutable ,
86104 args : cargs ,
87105 parentContext : ctx ,
88106 }
@@ -250,28 +268,18 @@ func (c *Command) Run(opts *RunOpts) error {
250268 }
251269
252270 if len (opts .Dir ) == 0 {
253- log .Debug ("%s" , c )
271+ log .Debug ("git.Command.Run: %s" , c )
254272 } else {
255- log .Debug ("%s : %v " , opts .Dir , c )
273+ log .Debug ("git.Command.RunDir(%s) : %s " , opts .Dir , c )
256274 }
257275
258276 desc := c .desc
259277 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 ))
273282 }
274- desc = fmt .Sprintf ("%s %s [repo_path: %s]" , c .name , strings .Join (args , " " ), opts .Dir )
275283 }
276284
277285 var ctx context.Context
@@ -285,7 +293,7 @@ func (c *Command) Run(opts *RunOpts) error {
285293 }
286294 defer finished ()
287295
288- cmd := exec .CommandContext (ctx , c .name , c .args ... )
296+ cmd := exec .CommandContext (ctx , c .prog , c .args ... )
289297 if opts .Env == nil {
290298 cmd .Env = os .Environ ()
291299 } else {
0 commit comments