@@ -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