From: "Vaidas Pilkauskas via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Taylor Blau <me@ttaylorr.com>, Jeff King <peff@peff.net>,
Junio C Hamano <gitster@pobox.com>,
Vaidas Pilkauskas <vaidas.pilkauskas@shopify.com>
Subject: [PATCH v6 0/3] http: add support for HTTP 429 rate limit retries
Date: Tue, 17 Mar 2026 13:00:32 +0000 [thread overview]
Message-ID: <pull.2008.v6.git.1773752435.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2008.v5.git.1771856405.gitgitgadget@gmail.com>
Changes since v5:
* drop show_http_message_fatal() preparation patch
* drop fwrite_headers, restore fwrite_wwwauth
* move CURLINFO_RETRY_AFTER from finish_active_slot to http_request
* move retry_after=-1 init from run_one_slot to http_request
* replace retry_after_out param with http_get_options field
* fix loop counter: separate REAUTH and RATE_LIMITED counters
* fix racy -lt 2 timing bounds in tests
Changes since v4:
* fix only strbuf_attach() calls which don't need reallocation
* remove patch, which enforces strbuf_attach() contract via BUG()
Changes since v3:
* Clean up of all strbuf_attach() call sites
* Add strbuf_attach() contract enforcement via BUG()
Changes since v2:
* New preparatory patch: Introduced show_http_message_fatal() helper
function to reduce code duplication in remote-curl.c (suggested by Taylor
Blau)
* Removed specific HTTP_RATE_LIMITED error handling from http-push.c and
http-walker.c for the obsolete "dumb" protocol, allowing generic error
handling to take over (suggested by Jeff King)
* Added support for CURLINFO_RETRY_AFTER on curl >= 7.66.0, falling back to
manual header parsing on older versions
* Simplified retry/delay architecture: replaced complex non-blocking
"delayed slot" mechanism with simple blocking sleep() call in the retry
loop, removing ~66 lines of timing logic (suggested by Jeff King)
* Fixed Retry-After: 0 handling to allow immediate retry as specified by
RFC 9110
* Changed http.retryAfter default from -1 to 0, so Git will retry
immediately when encountering HTTP 429 without a Retry-After header,
rather than failing with a configuration error
* Improved error messages: shortened to be more concise
* Fixed coding style issues: removed unnecessary curly braces, changed x ==
0 to !x (per CodingGuidelines)
* Improved test portability: replaced non-portable date(1) commands with
test-tool date, added nanosecond-precision timing with getnanos, replaced
cut(1) with POSIX shell parameter expansion
* Split out strbuf.c bugfix into separate preparatory patch (the
strbuf_reencode alloc size fix is unrelated to HTTP 429 support)
* Squashed separate trace2 logging patch into main HTTP 429 retry support
commit
* Kept header_is_last_match assignment for Retry-After to prevent incorrect
handling of HTTP header continuation lines
The implementation includes:
1. A bug fix in strbuf_reencode() that corrects the allocation size passed
to strbuf_attach(), passing len+1 instead of len so that the existing
buffer is reused rather than immediately reallocated.
2. A cleanup of strbuf_attach() call sites that were passing alloc == len,
leaving no room for the NUL terminator. Sites with a
known-NUL-terminated buffer now pass len+1; sites where the source
buffer has no trailing NUL (ll_merge output) are converted to use
strbuf_add() instead.
3. The main feature: HTTP 429 retry logic with support for the Retry-After
header (both delay-seconds and HTTP-date formats), configurable via
http.maxRetries, http.retryAfter, and http.maxRetryTime options. If any
computed delay exceeds maxRetryTime the request fails immediately with a
clear diagnostic rather than capping and retrying silently.
Vaidas Pilkauskas (3):
strbuf: pass correct alloc to strbuf_attach() in strbuf_reencode()
strbuf_attach: fix call sites to pass correct alloc
http: add support for HTTP 429 rate limit retries
Documentation/config/http.adoc | 26 ++++
builtin/am.c | 2 +-
builtin/fast-import.c | 2 +-
git-curl-compat.h | 8 +
http.c | 144 +++++++++++++++---
http.h | 9 ++
mailinfo.c | 2 +-
refs/files-backend.c | 2 +-
remote-curl.c | 11 ++
strbuf.c | 2 +-
t/lib-httpd.sh | 1 +
t/lib-httpd/apache.conf | 8 +
t/lib-httpd/http-429.sh | 98 ++++++++++++
t/meson.build | 1 +
t/t5584-http-429-retry.sh | 266 +++++++++++++++++++++++++++++++++
trailer.c | 2 +-
16 files changed, 557 insertions(+), 27 deletions(-)
create mode 100644 t/lib-httpd/http-429.sh
create mode 100755 t/t5584-http-429-retry.sh
base-commit: ca1db8a0f7dc0dbea892e99f5b37c5fe5861be71
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2008%2Fvaidas-shopify%2Fretry-after-v6
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2008/vaidas-shopify/retry-after-v6
Pull-Request: https://github.com/gitgitgadget/git/pull/2008
Range-diff vs v5:
1: 7ec2d66447 = 1: 6e76be1d85 strbuf: pass correct alloc to strbuf_attach() in strbuf_reencode()
2: 3e0b78cfb6 = 2: 0dc214d3c2 strbuf_attach: fix call sites to pass correct alloc
3: 973703e9dd < -: ---------- remote-curl: introduce show_http_message_fatal() helper
4: bfee1f10c0 ! 3: 3418f4553d http: add support for HTTP 429 rate limit retries
@@ Documentation/config/http.adoc: http.keepAliveCount::
+ Default wait time in seconds before retrying when a server returns
+ HTTP 429 (Too Many Requests) without a Retry-After header.
+ Defaults to 0 (retry immediately). When a Retry-After header is
-+ present, its value takes precedence over this setting. Can be
-+ overridden by the `GIT_HTTP_RETRY_AFTER` environment variable.
++ present, its value takes precedence over this setting; however,
++ automatic use of the server-provided `Retry-After` header requires
++ libcurl 7.66.0 or later. On older versions, configure this setting
++ manually to control the retry delay. Can be overridden by the
++ `GIT_HTTP_RETRY_AFTER` environment variable.
+ See also `http.maxRetries` and `http.maxRetryTime`.
+
+http.maxRetries::
@@ http.c: static inline int is_hdr_continuation(const char *ptr, const size_t size
}
-static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p UNUSED)
-+static size_t fwrite_headers(char *ptr, size_t eltsize, size_t nmemb, void *p MAYBE_UNUSED)
++static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p MAYBE_UNUSED)
{
size_t size = eltsize * nmemb;
struct strvec *values = &http_auth.wwwauth_headers;
-@@ http.c: static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p UN
- goto exit;
- }
-
-+#ifndef GIT_CURL_HAVE_CURLINFO_RETRY_AFTER
-+ /* Parse Retry-After header for rate limiting (for curl < 7.66.0) */
-+ if (skip_iprefix_mem(ptr, size, "retry-after:", &val, &val_len)) {
-+ struct active_request_slot *slot = (struct active_request_slot *)p;
-+
-+ strbuf_add(&buf, val, val_len);
-+ strbuf_trim(&buf);
-+
-+ if (slot && slot->results) {
-+ /* Parse the retry-after value (delay-seconds or HTTP-date) */
-+ char *endptr;
-+ long retry_after;
-+
-+ errno = 0;
-+ retry_after = strtol(buf.buf, &endptr, 10);
-+
-+ /* Check if it's a valid integer (delay-seconds format) */
-+ if (endptr != buf.buf && *endptr == '\0' &&
-+ errno != ERANGE && retry_after >= 0) {
-+ slot->results->retry_after = retry_after;
-+ } else {
-+ /* Try parsing as HTTP-date format */
-+ timestamp_t timestamp;
-+ int offset;
-+ if (!parse_date_basic(buf.buf, ×tamp, &offset)) {
-+ /* Successfully parsed as date, calculate delay from now */
-+ timestamp_t now = time(NULL);
-+ if (timestamp > now) {
-+ slot->results->retry_after = (long)(timestamp - now);
-+ } else {
-+ /* Past date means retry immediately */
-+ slot->results->retry_after = 0;
-+ }
-+ } else {
-+ /* Failed to parse as either delay-seconds or HTTP-date */
-+ warning(_("unable to parse Retry-After header value: '%s'"), buf.buf);
-+ }
-+ }
-+ }
-+
-+ goto exit;
-+ }
-+#endif
-+
- /*
- * This line could be a continuation of the previously matched header
- * field. If this is the case then we should append this value to the
-@@ http.c: static void finish_active_slot(struct active_request_slot *slot)
-
- curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CONNECTCODE,
- &slot->results->http_connectcode);
-+
-+#ifdef GIT_CURL_HAVE_CURLINFO_RETRY_AFTER
-+ if (slot->results->http_code == 429) {
-+ curl_off_t retry_after;
-+ CURLcode res = curl_easy_getinfo(slot->curl,
-+ CURLINFO_RETRY_AFTER,
-+ &retry_after);
-+ if (res == CURLE_OK && retry_after > 0)
-+ slot->results->retry_after = (long)retry_after;
-+ }
-+#endif
- }
-
- /* Run callback if appropriate */
@@ http.c: static int http_options(const char *var, const char *value,
return 0;
}
@@ http.c: int run_one_slot(struct active_request_slot *slot,
struct slot_results *results)
{
slot->results = results;
-+ /* Initialize retry_after to -1 (not set) */
-+ results->retry_after = -1;
+
if (!start_active_slot(slot)) {
xsnprintf(curl_errorstr, sizeof(curl_errorstr),
@@ http.c: static void http_opt_request_remainder(CURL *curl, off_t pos)
static int http_request(const char *url,
void *result, int target,
- const struct http_get_options *options)
-+ const struct http_get_options *options,
-+ long *retry_after_out)
++ struct http_get_options *options)
{
struct active_request_slot *slot;
- struct slot_results results;
+- struct slot_results results;
++ struct slot_results results = { .retry_after = -1 };
+ struct curl_slist *headers = http_copy_default_headers();
+ struct strbuf buf = STRBUF_INIT;
+ const char *accept_language;
@@ http.c: static int http_request(const char *url,
- fwrite_buffer);
- }
+ headers = curl_slist_append(headers, accept_language);
-- curl_easy_setopt(slot->curl, CURLOPT_HEADERFUNCTION, fwrite_wwwauth);
-+ curl_easy_setopt(slot->curl, CURLOPT_HEADERFUNCTION, fwrite_headers);
-+ curl_easy_setopt(slot->curl, CURLOPT_HEADERDATA, slot);
+ strbuf_addstr(&buf, "Pragma:");
+- if (options && options->no_cache)
++ if (options->no_cache)
+ strbuf_addstr(&buf, " no-cache");
+- if (options && options->initial_request &&
++ if (options->initial_request &&
+ http_follow_config == HTTP_FOLLOW_INITIAL)
+ curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L);
- accept_language = http_get_accept_language_header();
+ headers = curl_slist_append(headers, buf.buf);
+ /* Add additional headers here */
+- if (options && options->extra_headers) {
++ if (options->extra_headers) {
+ const struct string_list_item *item;
+- if (options && options->extra_headers) {
+- for_each_string_list_item(item, options->extra_headers) {
+- headers = curl_slist_append(headers, item->string);
+- }
+- }
++ for_each_string_list_item(item, options->extra_headers)
++ headers = curl_slist_append(headers, item->string);
+ }
+
+ headers = http_append_auth_header(&http_auth, headers);
@@ http.c: static int http_request(const char *url,
ret = run_one_slot(slot, &results);
-+ /* Store retry_after from slot results if output parameter provided */
-+ if (retry_after_out)
-+ *retry_after_out = results.retry_after;
+- if (options && options->content_type) {
++#ifdef GIT_CURL_HAVE_CURLINFO_RETRY_AFTER
++ if (ret == HTTP_RATE_LIMITED) {
++ curl_off_t retry_after;
++ if (curl_easy_getinfo(slot->curl, CURLINFO_RETRY_AFTER,
++ &retry_after) == CURLE_OK && retry_after > 0)
++ results.retry_after = (long)retry_after;
++ }
++#endif
++
++ options->retry_after = results.retry_after;
+
- if (options && options->content_type) {
++ if (options->content_type) {
struct strbuf raw = STRBUF_INIT;
curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, &raw);
+ extract_content_type(&raw, options->content_type,
+@@ http.c: static int http_request(const char *url,
+ strbuf_release(&raw);
+ }
+
+- if (options && options->effective_url)
++ if (options->effective_url)
+ curlinfo_strbuf(slot->curl, CURLINFO_EFFECTIVE_URL,
+ options->effective_url);
+
@@ http.c: static int update_url_from_redirect(struct strbuf *base,
return 1;
}
-static int http_request_reauth(const char *url,
+/*
-+ * Handle rate limiting retry logic for HTTP 429 responses.
-+ * Returns a negative value if retries are exhausted or configuration is invalid,
-+ * otherwise returns the delay value (>= 0) to indicate the retry should proceed.
++ * Compute the retry delay for an HTTP 429 response.
++ * Returns a negative value if configuration is invalid (delay exceeds
++ * http.maxRetryTime), otherwise returns the delay in seconds (>= 0).
+ */
-+static long handle_rate_limit_retry(int *rate_limit_retries, long slot_retry_after)
++static long handle_rate_limit_retry(long slot_retry_after)
+{
-+ int retry_attempt = http_max_retries - *rate_limit_retries + 1;
-+
-+ trace2_data_intmax("http", the_repository, "http/429-retry-attempt",
-+ retry_attempt);
-+
-+ if (*rate_limit_retries <= 0) {
-+ /* Retries are disabled or exhausted */
-+ if (http_max_retries > 0) {
-+ error(_("too many rate limit retries, giving up"));
-+ trace2_data_string("http", the_repository,
-+ "http/429-error", "retries-exhausted");
-+ }
-+ return -1;
-+ }
-+
-+ (*rate_limit_retries)--;
-+
+ /* Use the slot-specific retry_after value or configured default */
+ if (slot_retry_after >= 0) {
+ /* Check if retry delay exceeds maximum allowed */
@@ http.c: static int update_url_from_redirect(struct strbuf *base,
void *result, int target,
struct http_get_options *options)
{
++ static struct http_get_options empty_opts;
int i = 3;
int ret;
+ int rate_limit_retries = http_max_retries;
-+ long slot_retry_after = -1; /* Per-slot retry_after value */
++
++ if (!options)
++ options = &empty_opts;
if (always_auth_proactively())
credential_fill(the_repository, &http_auth, 1);
-- ret = http_request(url, result, target, options);
-+ ret = http_request(url, result, target, options, &slot_retry_after);
+ ret = http_request(url, result, target, options);
- if (ret != HTTP_OK && ret != HTTP_REAUTH)
+ if (ret != HTTP_OK && ret != HTTP_REAUTH && ret != HTTP_RATE_LIMITED)
return ret;
+- if (options && options->effective_url && options->base_url) {
+ /* If retries are disabled and we got a 429, fail immediately */
+ if (ret == HTTP_RATE_LIMITED && !http_max_retries)
+ return HTTP_ERROR;
+
- if (options && options->effective_url && options->base_url) {
++ if (options->effective_url && options->base_url) {
if (update_url_from_redirect(options->base_url,
url, options->effective_url)) {
+ credential_from_url(&http_auth, options->base_url->buf);
@@ http.c: static int http_request_reauth(const char *url,
}
}
- while (ret == HTTP_REAUTH && --i) {
-+ while ((ret == HTTP_REAUTH || ret == HTTP_RATE_LIMITED) && --i) {
++ while ((ret == HTTP_REAUTH && --i) ||
++ (ret == HTTP_RATE_LIMITED && --rate_limit_retries)) {
+ long retry_delay = -1;
/*
* The previous request may have put cruft into our output stream; we
@@ http.c: static int http_request_reauth(const char *url,
default:
BUG("Unknown http_request target");
}
+-
+- credential_fill(the_repository, &http_auth, 1);
+ if (ret == HTTP_RATE_LIMITED) {
-+ retry_delay = handle_rate_limit_retry(&rate_limit_retries, slot_retry_after);
++ retry_delay = handle_rate_limit_retry(options->retry_after);
+ if (retry_delay < 0)
+ return HTTP_ERROR;
+
@@ http.c: static int http_request_reauth(const char *url,
+ "http/retry-sleep-seconds", retry_delay);
+ sleep(retry_delay);
+ }
-+ slot_retry_after = -1; /* Reset after use */
+ } else if (ret == HTTP_REAUTH) {
+ credential_fill(the_repository, &http_auth, 1);
+ }
-- credential_fill(the_repository, &http_auth, 1);
--
-- ret = http_request(url, result, target, options);
-+ ret = http_request(url, result, target, options, &slot_retry_after);
+ ret = http_request(url, result, target, options);
}
++ if (ret == HTTP_RATE_LIMITED) {
++ trace2_data_string("http", the_repository,
++ "http/429-error", "retries-exhausted");
++ return HTTP_RATE_LIMITED;
++ }
return ret;
}
+
@@ http.c: int http_get_strbuf(const char *url,
struct strbuf *result,
struct http_get_options *options)
@@ http.h: struct slot_results {
};
struct active_request_slot {
+@@ http.h: struct http_get_options {
+ * request has completed.
+ */
+ struct string_list *extra_headers;
++
++ /*
++ * After a request completes, contains the Retry-After delay in seconds
++ * if the server returned HTTP 429 with a Retry-After header (requires
++ * libcurl 7.66.0 or later), or -1 if no such header was present.
++ */
++ long retry_after;
+ };
+
+ /* Return values for http_get_*() */
@@ http.h: struct http_get_options {
#define HTTP_REAUTH 4
#define HTTP_NOAUTH 5
@@ http.h: struct http_get_options {
## remote-curl.c ##
@@ remote-curl.c: static struct discovery *discover_refs(const char *service, int for_push)
- show_http_message_fatal(&type, &charset, &buffer,
- _("unable to access '%s' with http.pinnedPubkey configuration: %s"),
- transport_anonymize_url(url.buf), curl_errorstr);
+ show_http_message(&type, &charset, &buffer);
+ die(_("unable to access '%s' with http.pinnedPubkey configuration: %s"),
+ transport_anonymize_url(url.buf), curl_errorstr);
+ case HTTP_RATE_LIMITED:
-+ show_http_message_fatal(&type, &charset, &buffer,
-+ _("rate limited by '%s', please try again later"),
-+ transport_anonymize_url(url.buf));
++ if (http_options.retry_after > 0) {
++ show_http_message(&type, &charset, &buffer);
++ die(_("rate limited by '%s', please try again in %ld seconds"),
++ transport_anonymize_url(url.buf),
++ http_options.retry_after);
++ } else {
++ show_http_message(&type, &charset, &buffer);
++ die(_("rate limited by '%s', please try again later"),
++ transport_anonymize_url(url.buf));
++ }
default:
- show_http_message_fatal(&type, &charset, &buffer,
- _("unable to access '%s': %s"),
+ show_http_message(&type, &charset, &buffer);
+ die(_("unable to access '%s': %s"),
## t/lib-httpd.sh ##
@@ t/lib-httpd.sh: prepare_httpd() {
@@ t/t5584-http-429-retry.sh (new)
+ test_must_fail git ls-remote "$HTTPD_URL/http_429/retry-after-exceeds-max-time/100/repo.git" 2>err &&
+ duration=$(test-tool date getnanos $start) &&
+
-+ # Should fail quickly (less than 2 seconds, no 100 second wait)
++ # Should fail quickly (no 100 second wait)
+ duration_int=${duration%.*} &&
-+ test "$duration_int" -lt 2 &&
++ test "$duration_int" -lt 99 &&
+ test_grep "greater than http.maxRetryTime" err
+'
+
@@ t/t5584-http-429-retry.sh (new)
+ test_must_fail git ls-remote "$HTTPD_URL/http_429/config-retry-after-exceeds-max-time/none/repo.git" 2>err &&
+ duration=$(test-tool date getnanos $start) &&
+
-+ # Should fail quickly
++ # Should fail quickly (no 100 second wait)
+ duration_int=${duration%.*} &&
-+ test "$duration_int" -lt 2 &&
++ test "$duration_int" -lt 99 &&
+ test_grep "configured http.retryAfter.*exceeds.*http.maxRetryTime" err
+'
+
@@ t/t5584-http-429-retry.sh (new)
+
+ # Should fail quickly (not wait 200 seconds)
+ duration_int=${duration%.*} &&
-+ test "$duration_int" -lt 2 &&
++ test "$duration_int" -lt 199 &&
+ test_grep "http.maxRetryTime" err
+'
+
@@ t/t5584-http-429-retry.sh (new)
+ git ls-remote "$HTTPD_URL/http_429/past-http-date/$past_date_encoded/repo.git" >output 2>err &&
+ duration=$(test-tool date getnanos $start) &&
+
-+ # Should complete quickly (less than 2 seconds)
++ # Should complete quickly (no wait for a past-date Retry-After)
+ duration_int=${duration%.*} &&
-+ test "$duration_int" -lt 2 &&
++ test "$duration_int" -lt 5 &&
+ test_grep "refs/heads/" output
+'
+
@@ t/t5584-http-429-retry.sh (new)
+
+ # Should fail quickly (not wait 50 seconds) because env var limits to 10
+ duration_int=${duration%.*} &&
-+ test "$duration_int" -lt 5 &&
++ test "$duration_int" -lt 49 &&
+ test_grep "greater than http.maxRetryTime" err
+'
+
--
gitgitgadget
next prev parent reply other threads:[~2026-03-17 13:00 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-26 12:30 [PATCH 0/3] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2025-11-26 12:30 ` [PATCH 1/3] " Vaidas Pilkauskas via GitGitGadget
2025-12-09 23:15 ` Taylor Blau
2025-12-12 12:36 ` Vaidas Pilkauskas
2025-11-26 12:30 ` [PATCH 2/3] remote-curl: fix memory leak in show_http_message() Vaidas Pilkauskas via GitGitGadget
2025-12-09 23:52 ` Taylor Blau
2025-11-26 12:30 ` [PATCH 3/3] http: add trace2 logging for retry operations Vaidas Pilkauskas via GitGitGadget
2025-12-18 14:44 ` [PATCH v2 0/2] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2025-12-18 14:44 ` [PATCH v2 1/2] " Vaidas Pilkauskas via GitGitGadget
2026-02-11 1:05 ` Taylor Blau
2026-02-11 9:13 ` Jeff King
2026-02-13 13:41 ` Vaidas Pilkauskas
2026-02-15 9:13 ` Jeff King
2026-02-13 13:30 ` Vaidas Pilkauskas
2025-12-18 14:44 ` [PATCH v2 2/2] http: add trace2 logging for retry operations Vaidas Pilkauskas via GitGitGadget
2026-02-11 1:06 ` Taylor Blau
2026-02-17 11:08 ` [PATCH v3 0/3] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2026-02-17 11:08 ` [PATCH v3 1/3] strbuf: fix incorrect alloc size in strbuf_reencode() Vaidas Pilkauskas via GitGitGadget
2026-02-17 20:51 ` Junio C Hamano
2026-02-18 13:43 ` Vaidas Pilkauskas
2026-02-17 11:08 ` [PATCH v3 2/3] remote-curl: introduce show_http_message_fatal() helper Vaidas Pilkauskas via GitGitGadget
2026-02-17 11:08 ` [PATCH v3 3/3] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2026-02-18 14:09 ` [PATCH v4 0/5] " Vaidas Pilkauskas via GitGitGadget
2026-02-18 14:09 ` [PATCH v4 1/5] strbuf: pass correct alloc to strbuf_attach() in strbuf_reencode() Vaidas Pilkauskas via GitGitGadget
2026-02-18 14:09 ` [PATCH v4 2/5] strbuf_attach: fix all call sites to pass correct alloc Vaidas Pilkauskas via GitGitGadget
2026-02-20 22:55 ` Junio C Hamano
2026-02-23 12:49 ` Vaidas Pilkauskas
2026-02-18 14:09 ` [PATCH v4 3/5] strbuf: replace strbuf_grow() in strbuf_attach() with BUG() check Vaidas Pilkauskas via GitGitGadget
2026-02-18 14:09 ` [PATCH v4 4/5] remote-curl: introduce show_http_message_fatal() helper Vaidas Pilkauskas via GitGitGadget
2026-02-18 14:09 ` [PATCH v4 5/5] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2026-02-23 14:20 ` [PATCH v5 0/4] " Vaidas Pilkauskas via GitGitGadget
2026-02-23 14:20 ` [PATCH v5 1/4] strbuf: pass correct alloc to strbuf_attach() in strbuf_reencode() Vaidas Pilkauskas via GitGitGadget
2026-02-23 14:20 ` [PATCH v5 2/4] strbuf_attach: fix call sites to pass correct alloc Vaidas Pilkauskas via GitGitGadget
2026-02-23 14:20 ` [PATCH v5 3/4] remote-curl: introduce show_http_message_fatal() helper Vaidas Pilkauskas via GitGitGadget
2026-03-10 17:44 ` Jeff King
2026-02-23 14:20 ` [PATCH v5 4/4] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2026-03-10 19:07 ` Jeff King
2026-02-24 0:07 ` [PATCH v5 0/4] " Junio C Hamano
2026-03-09 23:34 ` Junio C Hamano
2026-03-10 19:10 ` Jeff King
2026-03-10 19:19 ` Junio C Hamano
2026-03-17 13:00 ` Vaidas Pilkauskas via GitGitGadget [this message]
2026-03-17 13:00 ` [PATCH v6 1/3] strbuf: pass correct alloc to strbuf_attach() in strbuf_reencode() Vaidas Pilkauskas via GitGitGadget
2026-03-17 13:00 ` [PATCH v6 2/3] strbuf_attach: fix call sites to pass correct alloc Vaidas Pilkauskas via GitGitGadget
2026-03-17 13:00 ` [PATCH v6 3/3] http: add support for HTTP 429 rate limit retries Vaidas Pilkauskas via GitGitGadget
2026-03-21 3:30 ` Taylor Blau
2026-03-21 3:31 ` [PATCH v6 0/3] " Taylor Blau
2026-03-21 4:57 ` Junio C Hamano
2026-03-23 6:58 ` Vaidas Pilkauskas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.2008.v6.git.1773752435.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=me@ttaylorr.com \
--cc=peff@peff.net \
--cc=vaidas.pilkauskas@shopify.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox