@@ -12,6 +12,7 @@ import (
1212	"io" 
1313	"os" 
1414	"os/exec" 
15+ 	"path/filepath" 
1516	"runtime" 
1617	"strings" 
1718	"time" 
@@ -43,18 +44,24 @@ type Command struct {
4344	prog              string 
4445	args              []string 
4546	parentContext     context.Context 
46- 	desc              string 
4747	globalArgsLength  int 
4848	brokenArgs        []string 
4949}
5050
51- func  (c  * Command ) String () string  {
52- 	return  c .toString (false )
51+ func  logArgSanitize (arg  string ) string  {
52+ 	if  strings .Contains (arg , "://" ) &&  strings .Contains (arg , "@" ) {
53+ 		return  util .SanitizeCredentialURLs (arg )
54+ 	} else  if  filepath .IsAbs (arg ) {
55+ 		base  :=  filepath .Base (arg )
56+ 		dir  :=  filepath .Dir (arg )
57+ 		return  filepath .Join (filepath .Base (dir ), base )
58+ 	}
59+ 	return  arg 
5360}
5461
55- func  (c  * Command ) toString ( sanitizing   bool ) string  {
62+ func  (c  * Command ) LogString ( ) string  {
5663	// 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. 
64+ 	// It's impossible to make a simple and 100% correct implementation of argument quoting for different platforms here . 
5865	debugQuote  :=  func (s  string ) string  {
5966		if  strings .ContainsAny (s , " `'\" \t \r \n " ) {
6067			return  fmt .Sprintf ("%q" , s )
@@ -63,12 +70,11 @@ func (c *Command) toString(sanitizing bool) string {
6370	}
6471	a  :=  make ([]string , 0 , len (c .args )+ 1 )
6572	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- 		}
73+ 	if  c .globalArgsLength  >  0  {
74+ 		a  =  append (a , "...global..." )
75+ 	}
76+ 	for  i  :=  c .globalArgsLength ; i  <  len (c .args ); i ++  {
77+ 		a  =  append (a , debugQuote (logArgSanitize (c .args [i ])))
7278	}
7379	return  strings .Join (a , " " )
7480}
@@ -112,12 +118,6 @@ func (c *Command) SetParentContext(ctx context.Context) *Command {
112118	return  c 
113119}
114120
115- // SetDescription sets the description for this command which be returned on c.String() 
116- func  (c  * Command ) SetDescription (desc  string ) * Command  {
117- 	c .desc  =  desc 
118- 	return  c 
119- }
120- 
121121// isSafeArgumentValue checks if the argument is safe to be used as a value (not an option) 
122122func  isSafeArgumentValue (s  string ) bool  {
123123	return  s  ==  ""  ||  s [0 ] !=  '-' 
@@ -271,8 +271,12 @@ var ErrBrokenCommand = errors.New("git command is broken")
271271
272272// Run runs the command with the RunOpts 
273273func  (c  * Command ) Run (opts  * RunOpts ) error  {
274+ 	return  c .run (1 , opts )
275+ }
276+ 
277+ func  (c  * Command ) run (skip  int , opts  * RunOpts ) error  {
274278	if  len (c .brokenArgs ) !=  0  {
275- 		log .Error ("git command is broken: %s, broken args: %s" , c .String (), strings .Join (c .brokenArgs , " " ))
279+ 		log .Error ("git command is broken: %s, broken args: %s" , c .LogString (), strings .Join (c .brokenArgs , " " ))
276280		return  ErrBrokenCommand 
277281	}
278282	if  opts  ==  nil  {
@@ -285,20 +289,14 @@ func (c *Command) Run(opts *RunOpts) error {
285289		timeout  =  defaultCommandExecutionTimeout 
286290	}
287291
288- 	if  len (opts .Dir ) ==  0  {
289- 		log .Debug ("git.Command.Run: %s" , c )
290- 	} else  {
291- 		log .Debug ("git.Command.RunDir(%s): %s" , opts .Dir , c )
292- 	}
293- 
294- 	desc  :=  c .desc 
295- 	if  desc  ==  ""  {
296- 		if  opts .Dir  ==  ""  {
297- 			desc  =  fmt .Sprintf ("git: %s" , c .toString (true ))
298- 		} else  {
299- 			desc  =  fmt .Sprintf ("git(dir:%s): %s" , opts .Dir , c .toString (true ))
300- 		}
292+ 	var  desc  string 
293+ 	callerInfo  :=  util .CallerFuncName (1  /* util */  +  1  /* this */  +  skip  /* parent */ )
294+ 	if  pos  :=  strings .LastIndex (callerInfo , "/" ); pos  >=  0  {
295+ 		callerInfo  =  callerInfo [pos + 1 :]
301296	}
297+ 	// these logs are for debugging purposes only, so no guarantee of correctness or stability 
298+ 	desc  =  fmt .Sprintf ("git.Run(by:%s, repo:%s): %s" , callerInfo , logArgSanitize (opts .Dir ), c .LogString ())
299+ 	log .Debug ("git.Command: %s" , desc )
302300
303301	var  ctx  context.Context 
304302	var  cancel  context.CancelFunc 
@@ -401,7 +399,7 @@ func IsErrorExitCode(err error, code int) bool {
401399
402400// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr). 
403401func  (c  * Command ) RunStdString (opts  * RunOpts ) (stdout , stderr  string , runErr  RunStdError ) {
404- 	stdoutBytes , stderrBytes , err  :=  c .RunStdBytes (opts )
402+ 	stdoutBytes , stderrBytes , err  :=  c .runStdBytes (opts )
405403	stdout  =  util .UnsafeBytesToString (stdoutBytes )
406404	stderr  =  util .UnsafeBytesToString (stderrBytes )
407405	if  err  !=  nil  {
@@ -413,6 +411,10 @@ func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr Run
413411
414412// RunStdBytes runs the command with options and returns stdout/stderr as bytes. and store stderr to returned error (err combined with stderr). 
415413func  (c  * Command ) RunStdBytes (opts  * RunOpts ) (stdout , stderr  []byte , runErr  RunStdError ) {
414+ 	return  c .runStdBytes (opts )
415+ }
416+ 
417+ func  (c  * Command ) runStdBytes (opts  * RunOpts ) (stdout , stderr  []byte , runErr  RunStdError ) {
416418	if  opts  ==  nil  {
417419		opts  =  & RunOpts {}
418420	}
@@ -435,7 +437,7 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
435437		PipelineFunc :      opts .PipelineFunc ,
436438	}
437439
438- 	err  :=  c .Run ( newOpts )
440+ 	err  :=  c .run ( 2 ,  newOpts )
439441	stderr  =  stderrBuf .Bytes ()
440442	if  err  !=  nil  {
441443		return  nil , stderr , & runStdError {err : err , stderr : util .UnsafeBytesToString (stderr )}
0 commit comments