can you take a look at https://github.com/entireio/git-sync/issues/63 · Entire
Summary of Changes
All tests pass. Here's the summary:
Bug: When git-sync sync is run against a public source repo (e.g. https://gitlab.baylibre.com/...), it would interactively prompt for username/password on a host the user had never authenticated against.
Root cause (internal/auth/auth.go:69): git credential fill falls back to an interactive terminal prompt on /dev/tty when no configured helper has credentials. git-sync is non-interactive, so this prompt shouldn't happen — anonymous access should be attempted instead.
Fix: Set GIT_TERMINAL_PROMPT=0 on the git credential fill invocation. With this, when no helper has credentials, git exits non-zero, our existing code treats that as "no credentials found", and we proceed anonymously. I also extracted newCredentialFillCmd so the env-var contract is unit-testable (TestCredentialFillCmdDisablesTerminalPrompt).
Proposed Options
So you have two options:
Option A — ship the current fix. Bug #63 (interactive prompt) is fixed. Cost: we still call git credential fill proactively, so if you have stored credentials for a host, we'll attach them on requests that didn't need auth. For most users this is harmless, but it does mean we send a token to a public repo we didn't need to.
Option B — match git's actual behaviour. Change Resolve() to skip the helper lookup, then make HTTPConn retry on 401 by consulting the helper at that point. Outline:
auth.Resolve()returns nil when only the helper would have credentials (don't call it eagerly)- Add a
CredentialProvidercallback onHTTPConnthat callsgit credential fill - In
RequestInfoRefsandPostRPC, on a 401 response, call the provider, retry once with the returned creds - On retry success, also call
git credential approve; on persistent 401,git credential reject
That's roughly a 100-line change touching auth/, gitproto/smarthttp.go, and a few tests. Slightly more if we want to handle 401s mid-stream during the pack post (which we should, since some servers only challenge on git-upload-pack not /info/refs).
User Discussion
My instinct: the bug filer just wants the prompt to stop. Option A solves that today. Option B is the better long-term shape and worth filing as a follow-up, but I'd rather propose it cleanly than wedge it into this PR. Want me to:
- Ship Option A and open a follow-up issue for Option B, or
- Do Option B now as part of this fix?
Behavior Changes
Here's the summary of what we built:
Behaviour change: git-sync now matches git's own HTTP auth behaviour — try anonymous first, only consult the credential helper on a 401 response from the server.
Files changed:
internal/auth/auth.go—Resolve()no longer eagerly callsgit credential fill. NewGitCredentialHelpertype withLookup/Approve/Rejectmethods that shell out togit credentialwithGIT_TERMINAL_PROMPT=0so it never prompts.internal/gitproto/smarthttp.go— NewCredentialHelperinterface onHTTPConn.RequestInfoRefsretries once on 401, stores resolved auth for subsequent calls (e.g.PostRPC), and signals approve/reject back to the helper.internal/syncer/syncer.go— Wiresauth.GitCredentialHelper{}onto HTTP conns when no explicit auth was configured.- Tests: 7 new HTTPConn 401-retry tests + 8 new auth helper tests + updated
TestResolveto assert the helper is never consulted up-front. The pre-existingTestRun_IntegrationUsesGitCredentialHelperFallbackend-to-end test still passes — it now exercises the new 401-retry path against a realhttptestserver.
The net effect: For the user in issue #63, syncing from a public GitLab repo now works without prompting — git-sync makes the request anonymously, the server returns 200, no helper is ever consulted. For users with private repos and a configured helper, the helper is consulted only when needed.
Further Considerations
Here’s one thing we could add here: Let's say I talked to a host that needs credentials and I enter the right ones, then it's saved in the helper. If they expire, the next time I run git-sync I get a 403.
Implementation Plan
Where to wire it in git-sync:
- lookupGitCredential returns a func() error (the "reject closure") alongside the username/password, capturing the input it sent to fill
- The session-level code wraps the AuthMethod with that closure
- On 401, the session calls the closure (which runs git credential reject for the same input).
Conclusion
In summary, based on the detailed review and the changes suggested, I will go ahead and create a PR for #63 now, as proposed.
Additional Cleanup Summary
- Dropped duplicate struct; use utility directly in the retry path
- Enhanced approval/rejection methods
- Introduced helper to consolidate tests and reduce redundant logic