Hide credentials in Git endpoint diagnostics

This commit is contained in:
2026-11-02 03:19:16 +00:00
parent 595745c7b1
commit 92c95ef031
12 changed files with 184 additions and 23 deletions

View File

@@ -60,14 +60,14 @@ type Snapshot struct {
// command-scoped remote whose read and push URLs resolve to that same endpoint.
func Resolve(ctx context.Context, repositoryDir, remoteName string) (Endpoint, error) {
if strings.TrimSpace(remoteName) == "" || strings.HasPrefix(remoteName, "-") {
return Endpoint{}, fmt.Errorf("%w: %q", ErrInvalidRemote, remoteName)
return Endpoint{}, fmt.Errorf("%w: %q", ErrInvalidRemote, DisplayURL(remoteName))
}
urls, err := pushURLs(ctx, repositoryDir, remoteName)
if err != nil {
return Endpoint{}, err
}
if len(urls) != 1 {
return Endpoint{}, fmt.Errorf("%w: %s resolves to %d distinct destinations", ErrMultiplePushURLs, remoteName, len(urls))
return Endpoint{}, fmt.Errorf("%w: %s resolves to %d distinct destinations", ErrMultiplePushURLs, DisplayURL(remoteName), len(urls))
}
scopedName, err := newScopedName()
if err != nil {
@@ -89,10 +89,10 @@ func Resolve(ctx context.Context, repositoryDir, remoteName string) (Endpoint, e
func (endpoint Endpoint) Recheck(ctx context.Context, repositoryDir string) error {
urls, err := pushURLs(ctx, repositoryDir, endpoint.RemoteName)
if err != nil {
return fmt.Errorf("re-resolve remote %q: %w", endpoint.RemoteName, err)
return fmt.Errorf("re-resolve remote %q: %w", DisplayURL(endpoint.RemoteName), err)
}
if len(urls) != 1 || urls[0] != endpoint.PushURL {
return fmt.Errorf("%w: remote %q now resolves to %q", ErrEndpointChanged, endpoint.RemoteName, strings.Join(urls, ", "))
return fmt.Errorf("%w: remote %q now resolves to %q", ErrEndpointChanged, DisplayURL(endpoint.RemoteName), displayDiagnostic(strings.Join(urls, ", ")))
}
return endpoint.verifyScopedURLs(ctx, repositoryDir)
}
@@ -109,7 +109,7 @@ func (endpoint Endpoint) Query(ctx context.Context, repositoryDir, tag string) (
output, err := run(ctx, repositoryDir, endpoint.scopedConfig(), "ls-remote", endpoint.ScopedName, mainRef, tagRef, peeledRef)
if err != nil {
snapshot := Snapshot{Main: RemoteRef{State: RefUnreadable}, Tag: RemoteRef{State: RefUnreadable}}
return snapshot, fmt.Errorf("%w: query authoritative refs at %s: %w", ErrRemoteStateUnreadable, endpoint.PushURL, err)
return snapshot, fmt.Errorf("%w: query authoritative refs at %s: %w", ErrRemoteStateUnreadable, DisplayURL(endpoint.PushURL), err)
}
main := RemoteRef{State: RefAbsent}
remoteTag := RemoteRef{State: RefAbsent}
@@ -119,7 +119,7 @@ func (endpoint Endpoint) Query(ctx context.Context, repositoryDir, tag string) (
}
object, name, ok := strings.Cut(line, "\t")
if !ok || !validObjectID(object) {
return Snapshot{Main: RemoteRef{State: RefUnreadable}, Tag: RemoteRef{State: RefUnreadable}}, fmt.Errorf("%w: malformed ls-remote output %q", ErrRemoteStateUnreadable, line)
return Snapshot{Main: RemoteRef{State: RefUnreadable}, Tag: RemoteRef{State: RefUnreadable}}, fmt.Errorf("%w: malformed ls-remote output %q", ErrRemoteStateUnreadable, displayDiagnostic(line))
}
switch name {
case mainRef:
@@ -165,7 +165,7 @@ func (endpoint Endpoint) verifyScopedURLs(ctx context.Context, repositoryDir str
}
resolved := outputLines(readURL)
if len(resolved) != 1 || resolved[0] != endpoint.PushURL {
return fmt.Errorf("%w: scoped URL resolves to %q, expected %q", ErrEndpointChanged, resolved, endpoint.PushURL)
return fmt.Errorf("%w: scoped URL resolves to %q, expected %q", ErrEndpointChanged, displayDiagnostic(strings.Join(resolved, ", ")), DisplayURL(endpoint.PushURL))
}
// The scoped remote sets its push URL explicitly to the same captured value.
// Git applies the same insteadOf rules to both explicit URLs; pushInsteadOf
@@ -197,7 +197,7 @@ func transportConfig(ctx context.Context, repositoryDir, remoteName, scopedName
if errors.As(err, &exitErr) && exitErr.ExitCode() == 1 {
continue
}
return nil, fmt.Errorf("read transport setting remote.%s.%s: %w", remoteName, key, err)
return nil, fmt.Errorf("read transport setting remote.%s.%s: %w", DisplayURL(remoteName), key, err)
}
for _, value := range outputLines(output) {
config = append(config, "remote."+scopedName+"."+key+"="+value)
@@ -209,7 +209,7 @@ func transportConfig(ctx context.Context, repositoryDir, remoteName, scopedName
func pushURLs(ctx context.Context, repositoryDir, remoteName string) ([]string, error) {
output, err := run(ctx, repositoryDir, nil, "remote", "get-url", "--push", "--all", remoteName)
if err != nil {
return nil, fmt.Errorf("resolve push URL for remote %q: %w", remoteName, err)
return nil, fmt.Errorf("resolve push URL for remote %q: %w", DisplayURL(remoteName), err)
}
values := outputLines(output)
unique := make([]string, 0, len(values))
@@ -239,9 +239,10 @@ func run(ctx context.Context, dir string, config []string, args ...string) (stri
Stderr: &stderr,
})
if err != nil {
err = displayError{cause: err}
message := strings.TrimSpace(stderr.String())
if message != "" {
return stdout.String(), fmt.Errorf("%w: %s", err, message)
return stdout.String(), fmt.Errorf("%w: %s", err, displayDiagnostic(message))
}
return stdout.String(), err
}