<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/remote-curl.c, branch jch</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=jch</id>
<link rel='self' href='https://git.shady.money/git/atom?h=jch'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2026-04-01T17:28:19Z</updated>
<entry>
<title>Merge branch 'kj/refspec-parsing-outside-repository'</title>
<updated>2026-04-01T17:28:19Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2026-04-01T17:28:19Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=949f59e96311dc85bc4b00a70f74ec0dfa2e37e0'/>
<id>urn:sha1:949f59e96311dc85bc4b00a70f74ec0dfa2e37e0</id>
<content type='text'>
"git ls-remote '+refs/tags/*:refs/tags/*' https://..." run outside a
repository would dereference a NULL while trying to see if the given
refspec is a single-object refspec, which has been corrected.

* kj/refspec-parsing-outside-repository:
  refspec: fix typo in comment
  remote-curl: fall back to default hash outside repo
</content>
</entry>
<entry>
<title>Merge branch 'vp/http-rate-limit-retries'</title>
<updated>2026-04-01T17:28:18Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2026-04-01T17:28:18Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=0a39ec283cadafeae5f542a26569e4cec6f36fae'/>
<id>urn:sha1:0a39ec283cadafeae5f542a26569e4cec6f36fae</id>
<content type='text'>
The HTTP transport learned to react to "429 Too Many Requests".

* vp/http-rate-limit-retries:
  http: add support for HTTP 429 rate limit retries
  strbuf_attach: fix call sites to pass correct alloc
  strbuf: pass correct alloc to strbuf_attach() in strbuf_reencode()
</content>
</entry>
<entry>
<title>remote-curl: fall back to default hash outside repo</title>
<updated>2026-03-24T04:27:17Z</updated>
<author>
<name>K Jayatheerth</name>
<email>jayatheerthkulkarni2005@gmail.com</email>
</author>
<published>2026-03-24T01:57:33Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=649c768a25b191dbea72c7bacaed5b81ef195bf5'/>
<id>urn:sha1:649c768a25b191dbea72c7bacaed5b81ef195bf5</id>
<content type='text'>
When a remote helper like git-remote-http is invoked outside of a
repository (for example, by running git ls-remote in a non-git
directory), setup_git_directory_gently() leaves the_hash_algo
uninitialized as NULL.

If the user has a globally configured fetch refspec, remote-curl
attempts to parse it during initialization. Inside parse_refspec(),
it checks whether the LHS of the refspec is an exact OID by evaluating
llen == the_hash_algo-&gt;hexsz. Because the_hash_algo is NULL, this
results in a segmentation fault.

In 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside of a repo,
2024-08-02), we added a workaround to ls-remote to fall back to the
default hash algorithm to prevent exactly this type of crash when
parsing refspec capabilities. However, because remote-curl runs as a
separate process, it does not inherit that fallback and crashes anyway.

Instead of pushing a NULL-guard workaround down into parse_refspec(),
fix this by mirroring the ls-remote workaround directly in
remote-curl.c. If we are operating outside a repository, initialize
the_hash_algo to GIT_HASH_DEFAULT. This keeps the HTTP transport
consistent with non-HTTP transports that execute in-process, preventing
crashes without altering the generic refspec parsing logic.

Reported-by: Jo Liss &lt;joliss@gmail.com&gt;
Helped-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: K Jayatheerth &lt;jayatheerthkulkarni2005@gmail.com&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>http: add support for HTTP 429 rate limit retries</title>
<updated>2026-03-17T16:14:19Z</updated>
<author>
<name>Vaidas Pilkauskas</name>
<email>vaidas.pilkauskas@shopify.com</email>
</author>
<published>2026-03-17T13:00:35Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=640657ffd06999ec1ec3b1d030b7f5aac6b7f57b'/>
<id>urn:sha1:640657ffd06999ec1ec3b1d030b7f5aac6b7f57b</id>
<content type='text'>
Add retry logic for HTTP 429 (Too Many Requests) responses to handle
server-side rate limiting gracefully. When Git's HTTP client receives
a 429 response, it can now automatically retry the request after an
appropriate delay, respecting the server's rate limits.

The implementation supports the RFC-compliant Retry-After header in
both delay-seconds (integer) and HTTP-date (RFC 2822) formats. If a
past date is provided, Git retries immediately without waiting.

Retry behavior is controlled by three new configuration options
(http.maxRetries, http.retryAfter, and http.maxRetryTime) which are
documented in git-config(1).

The retry logic implements a fail-fast approach: if any delay
(whether from server header or configuration) exceeds maxRetryTime,
Git fails immediately with a clear error message rather than capping
the delay. This provides better visibility into rate limiting issues.

The implementation includes extensive test coverage for basic retry
behavior, Retry-After header formats (integer and HTTP-date),
configuration combinations, maxRetryTime limits, invalid header
handling, environment variable overrides, and edge cases.

Signed-off-by: Vaidas Pilkauskas &lt;vaidas.pilkauskas@shopify.com&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>remote-curl: use auth for probe_rpc() requests too</title>
<updated>2026-01-14T17:44:30Z</updated>
<author>
<name>Aaron Plattner</name>
<email>aplattner@nvidia.com</email>
</author>
<published>2026-01-14T16:36:19Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ed0f7a62f75232896eccb622bfaf9fe56903a261'/>
<id>urn:sha1:ed0f7a62f75232896eccb622bfaf9fe56903a261</id>
<content type='text'>
If a large request requires post_rpc() to call probe_rpc(), the latter
does not use the authorization credentials used for other requests. If
this fails with an HTTP 401 error and http_auth.multistage isn't set,
then the whole request just fails.

For example, using git-credential-msal [1], the following attempt to clone a
large repository fails partway through because the initial request to download
the commit history and promisor packs succeeds, but the
subsequent request to download the blobs needed to construct the working
tree fails with a 401 error and the checkout fails.

(lines removed for brevity)

  git clone --filter=blob:none https://secure-server.example/repo
  11:03:26.855369 git.c:502               trace: built-in: git clone --filter=blob:none https://secure-server.example/repo
  Cloning into 'sw'...
  warning: templates not found in /home/aaron/share/git-core/templates
  11:03:26.857169 run-command.c:673       trace: run_command: git remote-https origin https://secure-server.example/repo
  11:03:27.012104 http.c:849              =&gt; Send header: GET repo/info/refs?service=git-upload-pack HTTP/1.1
  11:03:27.049243 http.c:849              &lt;= Recv header: HTTP/1.1 401 Unauthorized
  11:03:27.049270 http.c:849              &lt;= Recv header: WWW-Authenticate: Bearer error="invalid_request", error_description="No bearer token found in the request", msal-tenant-id="&lt;tenant&gt;", msal-client-id="&lt;client&gt;"
  11:03:27.053786 run-command.c:673       trace: run_command: 'git credential-msal get'
  11:03:27.952830 http.c:849              =&gt; Send header: GET repo/info/refs?service=git-upload-pack HTTP/1.1
  11:03:27.952849 http.c:849              =&gt; Send header: Authorization: Bearer &lt;redacted&gt;
  11:03:27.995419 http.c:849              &lt;= Recv header: HTTP/1.1 200 OK
  11:03:28.230039 http.c:890              == Info: Reusing existing https: connection with host secure-server.example
  11:03:28.230208 http.c:849              =&gt; Send header: POST repo/git-upload-pack HTTP/1.1
  11:03:28.230216 http.c:849              =&gt; Send header: Content-Type: application/x-git-upload-pack-request
  11:03:28.230221 http.c:849              =&gt; Send header: Authorization: Bearer &lt;redacted&gt;
  11:03:28.269085 http.c:849              &lt;= Recv header: HTTP/1.1 200 OK
  11:03:28.684163 http.c:890              == Info: Reusing existing https: connection with host secure-server.example
  11:03:28.684379 http.c:849              =&gt; Send header: POST repo/git-upload-pack HTTP/1.1
  11:03:28.684391 http.c:849              =&gt; Send header: Accept: application/x-git-upload-pack-result
  11:03:28.684393 http.c:849              =&gt; Send header: Authorization: Bearer &lt;redacted&gt;
  11:03:28.869546 run-command.c:673       trace: run_command: git index-pack --stdin --fix-thin '--keep=fetch-pack 43856 on dgx-spark' --promisor
  11:06:39.861237 run-command.c:673       trace: run_command: git -c fetch.negotiationAlgorithm=noop fetch origin --no-tags --no-write-fetch-head --recurse-submodules=no --filter=blob:none --stdin
  11:06:39.865981 run-command.c:673       trace: run_command: git remote-https origin https://secure-server.example/repo
  11:06:39.868039 run-command.c:673       trace: run_command: git-remote-https origin https://secure-server.example/repo
  11:07:30.412575 http.c:849              =&gt; Send header: GET repo/info/refs?service=git-upload-pack HTTP/1.1
  11:07:30.456285 http.c:849              &lt;= Recv header: HTTP/1.1 401 Unauthorized
  11:07:30.456318 http.c:849              &lt;= Recv header: WWW-Authenticate: Bearer error="invalid_request", error_description="No bearer token found in the request", msal-tenant-id="&lt;tenant&gt;", msal-client-id="&lt;client&gt;"
  11:07:30.456439 run-command.c:673       trace: run_command: 'git credential-cache get'
  11:07:30.461266 http.c:849              =&gt; Send header: GET repo/info/refs?service=git-upload-pack HTTP/1.1
  11:07:30.461282 http.c:849              =&gt; Send header: Authorization: Bearer &lt;redacted&gt;
  11:07:30.501628 http.c:849              &lt;= Recv header: HTTP/1.1 200 OK
  11:07:34.725262 http.c:849              =&gt; Send header: POST repo/git-upload-pack HTTP/1.1
  11:07:34.725279 http.c:849              =&gt; Send header: Content-Type: application/x-git-upload-pack-request
  11:07:34.761407 http.c:849              &lt;= Recv header: HTTP/1.1 401 Unauthorized
  11:07:34.761443 http.c:890              == Info: Bearer authentication problem, ignoring.
  11:07:34.761453 http.c:849              &lt;= Recv header: WWW-Authenticate: Bearer error="invalid_request", error_description="No bearer token found in the request", msal-tenant-id="&lt;tenant&gt;", msal-client-id="&lt;client&gt;"
  11:07:34.761509 http.c:890              == Info: The requested URL returned error: 401
  11:07:34.761530 http.c:890              == Info: closing connection #0
  11:07:34.761913 run-command.c:673       trace: run_command: 'git credential-cache erase'
  11:07:34.761927 run-command.c:765       trace: start_command: /bin/sh -c 'git credential-cache erase' 'git credential-cache erase'
  11:07:34.768069 git.c:502               trace: built-in: git credential-cache erase
  11:07:34.768690 run-command.c:673       trace: run_command: 'git credential-msal erase'
  11:07:34.768713 run-command.c:765       trace: start_command: /bin/sh -c 'git credential-msal erase' 'git credential-msal erase'
  11:07:34.772742 git.c:808               trace: exec: git-credential-msal erase
  11:07:34.772783 run-command.c:673       trace: run_command: git-credential-msal erase
  11:07:34.772819 run-command.c:765       trace: start_command: /usr/bin/git-credential-msal erase
  error: RPC failed; HTTP 401 curl 22 The requested URL returned error: 401
  fatal: unable to write request to remote: Broken pipe
  fatal: could not fetch c4fff0229c9be06ecf576356a4d39a8a755b8d81 from promisor remote
  warning: Clone succeeded, but checkout failed.
  You can inspect what was checked out with 'git status'
  and retry with 'git restore --source=HEAD :/'

In this case, the HTTP_REAUTH retry logic is not used because the
credential helper didn't set the 'continue' flag, so
http_auth.multistage is false and handle_curl_result() fails with
HTTP_NOAUTH instead.

Fix the immediate problem by including the authorization headers in the
probe_rpc() request as well.

Add a test for this scenario:

 1. Create a repository with two thousand refs.
 2. Clone that into the web root used by t5563-simple-http-auth.sh.
 3. Configure http.postBuffer to be very small in order to trigger the
    probe_rpc() path that fails.
 4. Clone using a valid Bearer token.

[1] https://github.com/Binary-Eater/git-credential-msal

Tested-by: Lucas De Marchi &lt;demarchi@kernel.org&gt;
Signed-off-by: Aaron Plattner &lt;aplattner@nvidia.com&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'js/curl-off-t-fixes'</title>
<updated>2025-10-07T19:25:27Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2025-10-07T19:25:27Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c2817955674c8cfc217c4ffc1deea8cc8cabe526'/>
<id>urn:sha1:c2817955674c8cfc217c4ffc1deea8cc8cabe526</id>
<content type='text'>
A few places where an size_t value was cast to curl_off_t without
checking has been updated to use the existing helper function.

* js/curl-off-t-fixes:
  http-push: avoid new compile error
  imap-send: be more careful when casting to `curl_off_t`
  http: offer to cast `size_t` to `curl_off_t` safely
</content>
</entry>
<entry>
<title>http: offer to cast `size_t` to `curl_off_t` safely</title>
<updated>2025-09-26T17:38:18Z</updated>
<author>
<name>Johannes Schindelin</name>
<email>johannes.schindelin@gmx.de</email>
</author>
<published>2025-09-26T10:32:50Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=e4efcd70604f2a294e020ec2e1bc38f01892cd19'/>
<id>urn:sha1:e4efcd70604f2a294e020ec2e1bc38f01892cd19</id>
<content type='text'>
This commit moves the `xcurl_off_t()` function, which validates that a
given value fits within the `curl_off_t` data type and then casts it, to
a more central place so that it can be used outside of `remote-curl.c`,
too.

At the same time, this function is renamed to conform better with the
naming convention of the helper functions that safely cast from one data
type to another which has been well established in `git-compat-util.h`.

With this move, `gettext.h` must be `#include`d in `http.h` to allow the
error message to remain translatable.

Signed-off-by: Johannes Schindelin &lt;johannes.schindelin@gmx.de&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Use legacy hash for legacy formats</title>
<updated>2025-07-01T21:58:24Z</updated>
<author>
<name>brian m. carlson</name>
<email>sandals@crustytoothpaste.net</email>
</author>
<published>2025-07-01T21:22:30Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=667d251a04c1dd769fb5a71bbe94d6d15ae594f1'/>
<id>urn:sha1:667d251a04c1dd769fb5a71bbe94d6d15ae594f1</id>
<content type='text'>
We have a large variety of data formats and protocols where no hash
algorithm was defined and the default was assumed to always be SHA-1.
Instead of explicitly stating SHA-1, let's use the constant to represent
the legacy hash algorithm (which is still SHA-1) so that it's clear
for documentary purposes that it's a legacy fallback option and not an
intentional choice to use SHA-1.

Signed-off-by: brian m. carlson &lt;sandals@crustytoothpaste.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>curl: pass `long` values where expected</title>
<updated>2025-06-06T15:12:24Z</updated>
<author>
<name>Johannes Schindelin</name>
<email>johannes.schindelin@gmx.de</email>
</author>
<published>2025-06-06T09:29:24Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=229d12665edb555df26653cf4a4731ae71c71a6d'/>
<id>urn:sha1:229d12665edb555df26653cf4a4731ae71c71a6d</id>
<content type='text'>
As of Homebrew's update to cURL v8.14.0, there are new compile errors to
be observed in the `osx-gcc` job of Git's CI builds:

  In file included from http.h:8,
                   from imap-send.c:36:
  In function 'setup_curl',
      inlined from 'curl_append_msgs_to_imap' at imap-send.c:1460:9,
      inlined from 'cmd_main' at imap-send.c:1581:9:
  /usr/local/Cellar/curl/8.14.0/include/curl/typecheck-gcc.h:50:15: error: call to '_curl_easy_setopt_err_long' declared with attribute warning: curl_easy_setopt expects a long argument [-Werror=attribute-warning]
     50 |               _curl_easy_setopt_err_long();                             \
        |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/local/Cellar/curl/8.14.0/include/curl/curl.h:54:7: note: in definition of macro 'CURL_IGNORE_DEPRECATION'
     54 |       statements \
        |       ^~~~~~~~~~
  imap-send.c:1423:9: note: in expansion of macro 'curl_easy_setopt'
   1423 |         curl_easy_setopt(curl, CURLOPT_PORT, srvc-&gt;port);
        |         ^~~~~~~~~~~~~~~~
  [... many more instances of nearly identical warnings...]

See for example this CI workflow run:
https://github.com/git/git/actions/runs/15454602308/job/43504278284#step:4:307

The most likely explanation is the entry "typecheck-gcc.h: fix the
typechecks" in cURL's release notes (https://curl.se/ch/8.14.0.html).

Nearly identical compile errors afflicted recently-updated Debian
setups, which have been addressed by `jk/curl-easy-setopt-typefix`.

However, on macOS Git is built with different build options, which
uncovered more instances of `int` values that need to be cast to
constants, which were not covered by 6f11c42e8edc (curl: fix integer
constant typechecks with curl_easy_setopt(), 2025-06-04). Let's
explicitly convert even those remaining `int` constants in
`curl_easy_setopt()` calls to `long` parameters.

In addition to looking at the compile errors of the `osx-gcc` job, I
verified that there are no other instances of the same issue that need
to be handled in this manner (and that might not be caught by our CI
builds because of yet other build options that might skip those code
parts), I ran the following command and inspected all 23 results
manually to ensure that the fix is now actually complete:

  git grep -n curl_easy_setopt |
  grep -ve ',.*, *[A-Za-z_"&amp;]' \
    -e ',.*, *[-0-9]*L)' \
    -e ',.*,.* (long)'

Signed-off-by: Johannes Schindelin &lt;johannes.schindelin@gmx.de&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>curl: fix integer constant typechecks with curl_easy_setopt()</title>
<updated>2025-06-04T21:17:53Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2025-06-04T20:55:13Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=6f11c42e8edc5cf7d65156c9dd68e720f1b92229'/>
<id>urn:sha1:6f11c42e8edc5cf7d65156c9dd68e720f1b92229</id>
<content type='text'>
The curl documentation specifies that curl_easy_setopt() takes either:

  ...a long, a function pointer, an object pointer or a curl_off_t,
  depending on what the specific option expects.

But when we pass an integer constant like "0", it will by default be a
regular non-long int. This has always been wrong, but seemed to work in
practice (I didn't dig into curl's implementation to see whether this
might actually be triggering undefined behavior, but it seems likely and
regardless we should do what the docs say).

This is especially important since curl has a type-checking macro that
causes building against curl 8.14 to produce many warnings. The specific
commit is due to their 79b4e56b3 (typecheck-gcc.h: fix the typechecks,
2025-04-22). Curiously, it does only seem to trigger when compiled with
-O2 for me.

We can fix it by just marking the constants with a long "L".

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
</feed>
