mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Improve git log for debugging (#24095)
This commit is contained in:
		| @@ -40,7 +40,7 @@ const DefaultLocale = "C" | |||||||
|  |  | ||||||
| // Command represents a command with its subcommands or arguments. | // Command represents a command with its subcommands or arguments. | ||||||
| type Command struct { | type Command struct { | ||||||
| 	name             string | 	prog             string | ||||||
| 	args             []string | 	args             []string | ||||||
| 	parentContext    context.Context | 	parentContext    context.Context | ||||||
| 	desc             string | 	desc             string | ||||||
| @@ -49,10 +49,28 @@ type Command struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (c *Command) String() string { | func (c *Command) String() string { | ||||||
| 	if len(c.args) == 0 { | 	return c.toString(false) | ||||||
| 		return c.name |  | ||||||
| } | } | ||||||
| 	return fmt.Sprintf("%s %s", c.name, strings.Join(c.args, " ")) |  | ||||||
|  | func (c *Command) toString(sanitizing bool) string { | ||||||
|  | 	// WARNING: this function is for debugging purposes only. It's much better than old code (which only joins args with space), | ||||||
|  | 	// It's impossible to make a simple and 100% correct implementation of argument quoting for different platforms. | ||||||
|  | 	debugQuote := func(s string) string { | ||||||
|  | 		if strings.ContainsAny(s, " `'\"\t\r\n") { | ||||||
|  | 			return fmt.Sprintf("%q", s) | ||||||
|  | 		} | ||||||
|  | 		return s | ||||||
|  | 	} | ||||||
|  | 	a := make([]string, 0, len(c.args)+1) | ||||||
|  | 	a = append(a, debugQuote(c.prog)) | ||||||
|  | 	for _, arg := range c.args { | ||||||
|  | 		if sanitizing && (strings.Contains(arg, "://") && strings.Contains(arg, "@")) { | ||||||
|  | 			a = append(a, debugQuote(util.SanitizeCredentialURLs(arg))) | ||||||
|  | 		} else { | ||||||
|  | 			a = append(a, debugQuote(arg)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return strings.Join(a, " ") | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewCommand creates and returns a new Git Command based on given command and arguments. | // 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 { | |||||||
| 		cargs = append(cargs, string(arg)) | 		cargs = append(cargs, string(arg)) | ||||||
| 	} | 	} | ||||||
| 	return &Command{ | 	return &Command{ | ||||||
| 		name:             GitExecutable, | 		prog:             GitExecutable, | ||||||
| 		args:             cargs, | 		args:             cargs, | ||||||
| 		parentContext:    ctx, | 		parentContext:    ctx, | ||||||
| 		globalArgsLength: len(globalCommandArgs), | 		globalArgsLength: len(globalCommandArgs), | ||||||
| @@ -82,7 +100,7 @@ func NewCommandContextNoGlobals(ctx context.Context, args ...internal.CmdArg) *C | |||||||
| 		cargs = append(cargs, string(arg)) | 		cargs = append(cargs, string(arg)) | ||||||
| 	} | 	} | ||||||
| 	return &Command{ | 	return &Command{ | ||||||
| 		name:          GitExecutable, | 		prog:          GitExecutable, | ||||||
| 		args:          cargs, | 		args:          cargs, | ||||||
| 		parentContext: ctx, | 		parentContext: ctx, | ||||||
| 	} | 	} | ||||||
| @@ -250,29 +268,19 @@ func (c *Command) Run(opts *RunOpts) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(opts.Dir) == 0 { | 	if len(opts.Dir) == 0 { | ||||||
| 		log.Debug("%s", c) | 		log.Debug("git.Command.Run: %s", c) | ||||||
| 	} else { | 	} else { | ||||||
| 		log.Debug("%s: %v", opts.Dir, c) | 		log.Debug("git.Command.RunDir(%s): %s", opts.Dir, c) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	desc := c.desc | 	desc := c.desc | ||||||
| 	if desc == "" { | 	if desc == "" { | ||||||
| 		args := c.args[c.globalArgsLength:] | 		if opts.Dir == "" { | ||||||
| 		var argSensitiveURLIndexes []int | 			desc = fmt.Sprintf("git: %s", c.toString(true)) | ||||||
| 		for i, arg := range c.args { | 		} else { | ||||||
| 			if strings.Contains(arg, "://") && strings.Contains(arg, "@") { | 			desc = fmt.Sprintf("git(dir:%s): %s", opts.Dir, c.toString(true)) | ||||||
| 				argSensitiveURLIndexes = append(argSensitiveURLIndexes, i) |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 		if len(argSensitiveURLIndexes) > 0 { |  | ||||||
| 			args = make([]string, len(c.args)) |  | ||||||
| 			copy(args, c.args) |  | ||||||
| 			for _, urlArgIndex := range argSensitiveURLIndexes { |  | ||||||
| 				args[urlArgIndex] = util.SanitizeCredentialURLs(args[urlArgIndex]) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		desc = fmt.Sprintf("%s %s [repo_path: %s]", c.name, strings.Join(args, " "), opts.Dir) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var ctx context.Context | 	var ctx context.Context | ||||||
| 	var cancel context.CancelFunc | 	var cancel context.CancelFunc | ||||||
| @@ -285,7 +293,7 @@ func (c *Command) Run(opts *RunOpts) error { | |||||||
| 	} | 	} | ||||||
| 	defer finished() | 	defer finished() | ||||||
|  |  | ||||||
| 	cmd := exec.CommandContext(ctx, c.name, c.args...) | 	cmd := exec.CommandContext(ctx, c.prog, c.args...) | ||||||
| 	if opts.Env == nil { | 	if opts.Env == nil { | ||||||
| 		cmd.Env = os.Environ() | 		cmd.Env = os.Environ() | ||||||
| 	} else { | 	} else { | ||||||
|   | |||||||
| @@ -52,3 +52,11 @@ func TestGitArgument(t *testing.T) { | |||||||
| 	assert.True(t, isSafeArgumentValue("x")) | 	assert.True(t, isSafeArgumentValue("x")) | ||||||
| 	assert.False(t, isSafeArgumentValue("-x")) | 	assert.False(t, isSafeArgumentValue("-x")) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestCommandString(t *testing.T) { | ||||||
|  | 	cmd := NewCommandContextNoGlobals(context.Background(), "a", "-m msg", "it's a test", `say "hello"`) | ||||||
|  | 	assert.EqualValues(t, cmd.prog+` a "-m msg" "it's a test" "say \"hello\""`, cmd.String()) | ||||||
|  |  | ||||||
|  | 	cmd = NewCommandContextNoGlobals(context.Background(), "url: https://a:b@c/") | ||||||
|  | 	assert.EqualValues(t, cmd.prog+` "url: https://sanitized-credential@c/"`, cmd.toString(true)) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -209,49 +209,22 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error { | |||||||
| 	} else { | 	} else { | ||||||
| 		cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, opts.Remote, opts.Force, opts.Mirror)) | 		cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, opts.Remote, opts.Force, opts.Mirror)) | ||||||
| 	} | 	} | ||||||
| 	var outbuf, errbuf strings.Builder |  | ||||||
|  |  | ||||||
| 	if opts.Timeout == 0 { | 	stdout, stderr, err := cmd.RunStdString(&RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath}) | ||||||
| 		opts.Timeout = -1 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	err := cmd.Run(&RunOpts{ |  | ||||||
| 		Env:     opts.Env, |  | ||||||
| 		Timeout: opts.Timeout, |  | ||||||
| 		Dir:     repoPath, |  | ||||||
| 		Stdout:  &outbuf, |  | ||||||
| 		Stderr:  &errbuf, |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if strings.Contains(errbuf.String(), "non-fast-forward") { | 		if strings.Contains(stderr, "non-fast-forward") { | ||||||
| 			return &ErrPushOutOfDate{ | 			return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err} | ||||||
| 				StdOut: outbuf.String(), | 		} else if strings.Contains(stderr, "! [remote rejected]") { | ||||||
| 				StdErr: errbuf.String(), | 			err := &ErrPushRejected{StdOut: stdout, StdErr: stderr, Err: err} | ||||||
| 				Err:    err, |  | ||||||
| 			} |  | ||||||
| 		} else if strings.Contains(errbuf.String(), "! [remote rejected]") { |  | ||||||
| 			err := &ErrPushRejected{ |  | ||||||
| 				StdOut: outbuf.String(), |  | ||||||
| 				StdErr: errbuf.String(), |  | ||||||
| 				Err:    err, |  | ||||||
| 			} |  | ||||||
| 			err.GenerateMessage() | 			err.GenerateMessage() | ||||||
| 			return err | 			return err | ||||||
| 		} else if strings.Contains(errbuf.String(), "matches more than one") { | 		} else if strings.Contains(stderr, "matches more than one") { | ||||||
| 			err := &ErrMoreThanOne{ | 			return &ErrMoreThanOne{StdOut: stdout, StdErr: stderr, Err: err} | ||||||
| 				StdOut: outbuf.String(), |  | ||||||
| 				StdErr: errbuf.String(), |  | ||||||
| 				Err:    err, |  | ||||||
| 			} |  | ||||||
| 			return err |  | ||||||
| 		} | 		} | ||||||
|  | 		return fmt.Errorf("push failed: %w - %s\n%s", err, stderr, stdout) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if errbuf.Len() > 0 && err != nil { | 	return nil | ||||||
| 		return fmt.Errorf("%w - %s", err, errbuf.String()) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return err |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetLatestCommitTime returns time for latest commit in repository (across all branches) | // GetLatestCommitTime returns time for latest commit in repository (across all branches) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 wxiaoguang
					wxiaoguang