# code review cleanup

`ba637db`→[main](/content/gh/entireio/git-sync/commits/main/index.html)· Soph·1mo ago·7 files·+216 added/-297 removed

\- Drop internal basicAuth duplicate; use transporthttp.BasicAuth directly in the gitproto retry path (the package already pulls in go-git types via the AuthMethod interface contract).
\- Collapse GitCredentialHelper.Approve/Reject into a single signal() helper; they only differed in the op string.
\- Type the credential op as auth.CredentialOp with named constants (CredentialOpFill / Approve / Reject), removing magic strings from production code and the integration test switch.
\- Collapse fakeCredentialHelper's six counters/last-X fields into a single calls []credCall slice with count(op)/last(op) accessors.
\- Add a newTestConn(t, rt) helper to deduplicate the 8 new tests.
\- Trim narrating comments throughout (per code review). Kept the CredentialHelper interface contract, the GIT_TERMINAL_PROMPT=0 rationale, the 403-Cloudflare anecdote, and the explicit-auth-wins invariant — these encode non-obvious WHY. Trimmed the rest.

No behaviour change; full test suite + race detector + golangci-lint pass clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

## Sessions

4f0fc9b99fdcView transcript

## Changes

7

- internal

- auth

- Mauth.go+42/-55

- Mauth_test.go+17/-23

- gitproto

- Msmarthttp.go+12/-36

- Msmarthttp_test.go+140/-174

- syncer

- Mauth_test.go+2/-2

- Mintegration_test.go+3/-4

- Msyncer.go-3

```
43 unmodified lines

```

return &transporthttp.BasicAuth{Username: username, Password: password}, nil
    }
    // Note: we deliberately do not consult the git credential helper here.
    // Doing so eagerly would leak stored credentials to public repos that
    // don't require auth, and previously caused interactive prompts when
    // no helper had credentials (issue #63). The credential helper is now
    // consulted on demand when an HTTP request returns 401 — see
    // GitCredentialHelper, wired up by the HTTP connection layer.
    return nil, nil //nolint:nilnil // nil signals no auth method found at this stage
}

return nil
}

// newGitCredentialCmd builds the `git credential <op>` invocation used by
// GitCredentialCommand. Extracted so tests can inspect the command's
// environment without exec'ing git.
func newGitCredentialCmd(ctx context.Context, op, input string) *exec.Cmd {
    cmd := exec.CommandContext(ctx, "git", "credential", op)
    // CredentialOp identifies a `git credential` subcommand.
type CredentialOp string

const (
    CredentialOpFill    CredentialOp = "fill"
    CredentialOpApprove CredentialOp = "approve"
    CredentialOpReject  CredentialOp = "reject"
)

// newGitCredentialCmd builds the `git credential <op>` invocation. Extracted
// so tests can inspect the command's environment without exec'ing git.
func newGitCredentialCmd(ctx context.Context, op CredentialOp, input string) *exec.Cmd {
    cmd := exec.CommandContext(ctx, "git", "credential", string(op))
    cmd.Stdin = strings.NewReader(input)
    // Disable git's interactive terminal prompt fallback. When no credential
    // helper has credentials for the host (e.g. a public repo on a server
    // the user has never authenticated against), git would otherwise drop
    // to an interactive username/password prompt on /dev/tty. git-sync is a
    // non-interactive tool — failing here lets us cleanly surface a 401
    // rather than block waiting for input. See issue #63.
    // Suppress git's interactive username/password fallback. Without this,
    // a host with no configured helper drops to a /dev/tty prompt and turns
    // git-sync into an interactive command (issue #63).
    cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
    return cmd
}

// GitCredentialCommand invokes `git credential <op>` with the given input
// (in the git-credential text format). op is one of "fill", "approve", or
// "reject". Replaceable for testing.
var GitCredentialCommand = func(ctx context.Context, op, input string) ([]byte, error) {
    return newGitCredentialCmd(ctx, op, input).Output()
}

// GitCredentialHelper bridges Git's credential helper protocol to HTTP auth.
// It looks up credentials on demand (typically in response to a 401) and
// signals back to the helper whether the credentials worked.
// 
// Implementations are best-effort: a missing or misbehaving helper must not
// fail the surrounding sync, only deny credentials. Errors from approve/reject
// are silently swallowed since those steps are advisory.
// Best-effort: a missing or misbehaving helper denies credentials rather
// than failing the surrounding sync.
type GitCredentialHelper struct{}

// Lookup queries the git credential helper for credentials for ep. Returns
// ok=false if no credentials are available (so the caller can surface a
// clean 401 rather than block).
// ok=false if no credentials are available so the caller can surface a
// clean 401 rather than block.
//nolint:unparam // err is always nil today but kept for the CredentialHelper interface.
func (GitCredentialHelper) Lookup(ctx context.Context, ep *url.URL) (username, password string, ok bool, err error) {
    if !isHTTPEndpoint(ep) {
        // git's credential helper protocol only knows about HTTP.
        return "", "", false, nil
    }
    input := credentialInput(ep, "", "")
    if input == "" {
        return "", "", false, nil
    }
    output, helperErr := GitCredentialCommand(ctx, "fill", input)
    if helperErr != nil {
        // Helper exited non-zero — typically means "no credentials found"
        // or "terminal prompts disabled" (when no helper has creds). Treat
        // both as "no credentials available" so the original 401 surfaces.
        return "", "", false, nil //nolint:nilerr // intentional: swallow helper failure as "no credentials"
    }
    values := parseCredentialOutput(output)
    password = values["password"]
    return username, password, true, nil
}

// isHTTPEndpoint reports whether ep is a non-nil HTTP or HTTPS endpoint.
// Approve tells the helper the credentials worked.
func (h GitCredentialHelper) Approve(ctx context.Context, ep *url.URL, username, password string) {
    h.signal(ctx, CredentialOpApprove, ep, username, password)
}

// Reject tells the helper the credentials failed.
func (h GitCredentialHelper) Reject(ctx context.Context, ep *url.URL, username, password string) {
    h.signal(ctx, CredentialOpReject, ep, username, password)
}

func (GitCredentialHelper) signal(ctx context.Context, op CredentialOp, ep *url.URL, username, password string) {
    input := credentialInput(ep, username, password)
    if input == "" {
        return
    }
    _, _ = GitCredentialCommand(ctx, op, input) //nolint:errcheck // advisory signal; helper failures swallowed
}

func isHTTPEndpoint(ep *url.URL) bool {
    return ep != nil && (ep.Scheme == "http" || ep.Scheme == "https")
}

// Approve tells the helper the credentials worked, so it can persist them.
// Best-effort: helper failures are swallowed.
func (GitCredentialHelper) Approve(ctx context.Context, ep *url.URL, username, password string) {
    input := credentialInput(ep, username, password)
    if input == "" {
        return
    }
    _, _ = GitCredentialCommand(ctx, "approve", input) //nolint:errcheck // best-effort signal
}

// Reject tells the helper the credentials failed, so it can forget them.
// Best-effort: helper failures are swallowed.
func (GitCredentialHelper) Reject(ctx context.Context, ep *url.URL, username, password string) {
    input := credentialInput(ep, username, password)
    if input == "" {
        return
    }
    _, _ = GitCredentialCommand(ctx, "reject", input) //nolint:errcheck // best-effort signal
}

// credentialInput builds a git-credential format request body for the given
// endpoint. When username/password are set, they are appended (for use with
// `git credential approve`/`reject`). When both are empty, the result is a
