From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"Jonathan Tan" <jonathantanmy@google.com>,
"Josh Steadmon" <steadmon@google.com>,
"Bruno Albuquerque" <bga@google.com>, "Jeff King" <peff@peff.net>,
"Eric Sunshine" <sunshine@sunshineco.com>,
"Christian Couder" <chriscool@tuxfamily.org>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH v2 8/8] upload-pack.c: convert to new serve.c "startup" config cb
Date: Mon, 28 Jun 2021 21:19:25 +0200 [thread overview]
Message-ID: <patch-8.8-9fd6138aa62-20210628T191634Z-avarab@gmail.com> (raw)
In-Reply-To: <cover-0.8-00000000000-20210628T191634Z-avarab@gmail.com>
Convert the config reading code in upload-pack.c to use the new
"startup_config" callback when we're using the v2 protocol, and
lightly fake up the same when we're using v0 and v1.
Before the series that fixed 08450ef7918 (upload-pack: clear
filter_options for each v2 fetch command, 2020-05-08) landed, most of
what's now "struct upload_pack_data" used to be static variables at
the top of this file.
This moves some of them back. See f203a88cf14 (upload-pack: move
keepalive to upload_pack_data, 2020-06-04), f1514c6aad0 (upload-pack:
move allow_unadvertised_object_request to upload_pack_data,
2020-06-11) etc.
I think this makes it easier to understand the this code, as we're now
clearly separating data and config that changes on a
request-to-request basis (see 08450ef7918), and the sort of config
that serve.c's "startup_config" is aimed at.
Thus it's clear that the "allow_uor" passed to functions like
"is_our_ref()" is constant after startup (usually it'll never change
for a given server's configuration, or change once).
This requires a very light compatibly layer with the serve.c callback
mechanism in the form of "upload_pack" for the v0 and v1 protocols.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
serve.c | 1 +
upload-pack.c | 139 ++++++++++++++++++++++++++++++--------------------
upload-pack.h | 2 +
3 files changed, 86 insertions(+), 56 deletions(-)
diff --git a/serve.c b/serve.c
index cce96dd5a81..1054d1459c9 100644
--- a/serve.c
+++ b/serve.c
@@ -112,6 +112,7 @@ static struct protocol_capability capabilities[] = {
},
{
.name = "fetch",
+ .startup_config = serve_upload_pack_startup_config,
.advertise = upload_pack_advertise,
.command = upload_pack_v2,
},
diff --git a/upload-pack.c b/upload-pack.c
index 297b76fcb43..6c0d566e9e0 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -52,6 +52,19 @@ enum allow_uor {
ALLOW_ANY_SHA1 = 0x07
};
+/*
+ * "Global" configuration that won't be affected by the type of
+ * request we're doing, or by other request data in "struct
+ * upload_pack_data" below.
+ */
+static int v1_have_startup_config;
+static int config_keepalive = 5;
+static enum allow_uor config_allow_uor;
+static unsigned config_advertise_sid;
+static const char *config_pack_objects_hook;
+static unsigned config_v2_allow_ref_in_want;
+static unsigned config_v2_allow_sideband_all;
+
/*
* Please annotate, and if possible group together, fields used only
* for protocol v0 or only for protocol v2.
@@ -70,7 +83,6 @@ struct upload_pack_data {
timestamp_t deepen_since;
int deepen_rev_list;
int deepen_relative;
- int keepalive;
int shallow_nr;
timestamp_t oldest_have;
@@ -85,15 +97,12 @@ struct upload_pack_data {
int use_sideband;
struct string_list uri_protocols;
- enum allow_uor allow_uor;
struct list_objects_filter_options filter_options;
struct string_list allowed_filters;
struct packet_writer writer;
- const char *pack_objects_hook;
-
unsigned stateless_rpc : 1; /* v0 only */
unsigned no_done : 1; /* v0 only */
unsigned daemon_mode : 1; /* v0 only */
@@ -109,9 +118,6 @@ struct upload_pack_data {
unsigned long tree_filter_max_depth;
unsigned done : 1; /* v2 only */
- unsigned allow_ref_in_want : 1; /* v2 only */
- unsigned allow_sideband_all : 1; /* v2 only */
- unsigned advertise_sid : 1;
};
static void upload_pack_data_init(struct upload_pack_data *data)
@@ -141,9 +147,6 @@ static void upload_pack_data_init(struct upload_pack_data *data)
data->allow_filter_fallback = 1;
data->tree_filter_max_depth = ULONG_MAX;
packet_writer_init(&data->writer, 1);
-
- data->keepalive = 5;
- data->advertise_sid = 0;
}
static void upload_pack_data_clear(struct upload_pack_data *data)
@@ -158,8 +161,6 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
object_array_clear(&data->extra_edge_obj);
list_objects_filter_release(&data->filter_options);
string_list_clear(&data->allowed_filters, 0);
-
- free((char *)data->pack_objects_hook);
}
static void reset_timeout(unsigned int timeout)
@@ -277,10 +278,10 @@ static void create_pack_file(struct upload_pack_data *pack_data,
int i;
FILE *pipe_fd;
- if (!pack_data->pack_objects_hook)
+ if (!config_pack_objects_hook)
pack_objects.git_cmd = 1;
else {
- strvec_push(&pack_objects.args, pack_data->pack_objects_hook);
+ strvec_push(&pack_objects.args, config_pack_objects_hook);
strvec_push(&pack_objects.args, "git");
pack_objects.use_shell = 1;
}
@@ -371,9 +372,9 @@ static void create_pack_file(struct upload_pack_data *pack_data,
if (!pollsize)
break;
- polltimeout = pack_data->keepalive < 0
+ polltimeout = config_keepalive < 0
? -1
- : 1000 * pack_data->keepalive;
+ : 1000 * config_keepalive;
ret = poll(pfd, pollsize, polltimeout);
@@ -581,9 +582,9 @@ static int get_common_commits(struct upload_pack_data *data,
}
}
-static int is_our_ref(struct object *o, enum allow_uor allow_uor)
+static int is_our_ref(struct object *o)
{
- int allow_hidden_ref = (allow_uor &
+ int allow_hidden_ref = (config_allow_uor &
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1));
return o->flags & ((allow_hidden_ref ? HIDDEN_REF : 0) | OUR_REF);
}
@@ -593,8 +594,7 @@ static int is_our_ref(struct object *o, enum allow_uor allow_uor)
*/
static int do_reachable_revlist(struct child_process *cmd,
struct object_array *src,
- struct object_array *reachable,
- enum allow_uor allow_uor)
+ struct object_array *reachable)
{
static const char *argv[] = {
"rev-list", "--stdin", NULL,
@@ -627,14 +627,14 @@ static int do_reachable_revlist(struct child_process *cmd,
continue;
if (reachable && o->type == OBJ_COMMIT)
o->flags &= ~TMP_MARK;
- if (!is_our_ref(o, allow_uor))
+ if (!is_our_ref(o))
continue;
if (fprintf(cmd_in, "^%s\n", oid_to_hex(&o->oid)) < 0)
goto error;
}
for (i = 0; i < src->nr; i++) {
o = src->objects[i].item;
- if (is_our_ref(o, allow_uor)) {
+ if (is_our_ref(o)) {
if (reachable)
add_object_array(o, NULL, reachable);
continue;
@@ -671,8 +671,7 @@ static int get_reachable_list(struct upload_pack_data *data,
char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
const unsigned hexsz = the_hash_algo->hexsz;
- if (do_reachable_revlist(&cmd, &data->shallows, reachable,
- data->allow_uor) < 0)
+ if (do_reachable_revlist(&cmd, &data->shallows, reachable) < 0)
return -1;
while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
@@ -703,13 +702,13 @@ static int get_reachable_list(struct upload_pack_data *data,
return 0;
}
-static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
+static int has_unreachable(struct object_array *src)
{
struct child_process cmd = CHILD_PROCESS_INIT;
char buf[1];
int i;
- if (do_reachable_revlist(&cmd, src, NULL, allow_uor) < 0)
+ if (do_reachable_revlist(&cmd, src, NULL) < 0)
return 1;
/*
@@ -748,9 +747,9 @@ static void check_non_tip(struct upload_pack_data *data)
* uploadpack.allowReachableSHA1InWant,
* non-tip requests can never happen.
*/
- if (!data->stateless_rpc && !(data->allow_uor & ALLOW_REACHABLE_SHA1))
+ if (!data->stateless_rpc && !(config_allow_uor & ALLOW_REACHABLE_SHA1))
goto error;
- if (!has_unreachable(&data->want_obj, data->allow_uor))
+ if (!has_unreachable(&data->want_obj))
/* All the non-tip ones are ancestors of what we advertised */
return;
@@ -758,7 +757,7 @@ static void check_non_tip(struct upload_pack_data *data)
/* Pick one of them (we know there at least is one) */
for (i = 0; i < data->want_obj.nr; i++) {
struct object *o = data->want_obj.objects[i].item;
- if (!is_our_ref(o, data->allow_uor)) {
+ if (!is_our_ref(o)) {
packet_writer_error(&data->writer,
"upload-pack: not our ref %s",
oid_to_hex(&o->oid));
@@ -1123,8 +1122,8 @@ static void receive_needs(struct upload_pack_data *data,
}
if (!(o->flags & WANTED)) {
o->flags |= WANTED;
- if (!((data->allow_uor & ALLOW_ANY_SHA1) == ALLOW_ANY_SHA1
- || is_our_ref(o, data->allow_uor)))
+ if (!((config_allow_uor & ALLOW_ANY_SHA1) == ALLOW_ANY_SHA1
+ || is_our_ref(o)))
has_non_tip = 1;
add_object_array(o, NULL, &data->want_obj);
}
@@ -1184,7 +1183,7 @@ static void format_symref_info(struct strbuf *buf, struct string_list *symref)
}
static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
- if (d->advertise_sid)
+ if (config_advertise_sid)
strbuf_addf(buf, " session-id=%s", trace2_session_id());
}
@@ -1210,9 +1209,9 @@ static int send_ref(const char *refname, const struct object_id *oid,
packet_write_fmt(1, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
oid_to_hex(oid), refname_nons,
0, capabilities,
- (data->allow_uor & ALLOW_TIP_SHA1) ?
+ (config_allow_uor & ALLOW_TIP_SHA1) ?
" allow-tip-sha1-in-want" : "",
- (data->allow_uor & ALLOW_REACHABLE_SHA1) ?
+ (config_allow_uor & ALLOW_REACHABLE_SHA1) ?
" allow-reachable-sha1-in-want" : "",
data->stateless_rpc ? " no-done" : "",
symref_info.buf,
@@ -1282,45 +1281,71 @@ static int parse_object_filter_config(const char *var, const char *value,
return 0;
}
-static int upload_pack_config(const char *var, const char *value, void *cb_data)
+static int upload_pack_startup_config(const char *var, const char *value,
+ void *cb_data)
{
- struct upload_pack_data *data = cb_data;
-
if (!strcmp("uploadpack.allowtipsha1inwant", var)) {
if (git_config_bool(var, value))
- data->allow_uor |= ALLOW_TIP_SHA1;
+ config_allow_uor |= ALLOW_TIP_SHA1;
else
- data->allow_uor &= ~ALLOW_TIP_SHA1;
+ config_allow_uor &= ~ALLOW_TIP_SHA1;
} else if (!strcmp("uploadpack.allowreachablesha1inwant", var)) {
if (git_config_bool(var, value))
- data->allow_uor |= ALLOW_REACHABLE_SHA1;
+ config_allow_uor |= ALLOW_REACHABLE_SHA1;
else
- data->allow_uor &= ~ALLOW_REACHABLE_SHA1;
+ config_allow_uor &= ~ALLOW_REACHABLE_SHA1;
} else if (!strcmp("uploadpack.allowanysha1inwant", var)) {
if (git_config_bool(var, value))
- data->allow_uor |= ALLOW_ANY_SHA1;
+ config_allow_uor |= ALLOW_ANY_SHA1;
else
- data->allow_uor &= ~ALLOW_ANY_SHA1;
+ config_allow_uor &= ~ALLOW_ANY_SHA1;
} else if (!strcmp("uploadpack.keepalive", var)) {
- data->keepalive = git_config_int(var, value);
- if (!data->keepalive)
- data->keepalive = -1;
- } else if (!strcmp("uploadpack.allowfilter", var)) {
- data->allow_filter = git_config_bool(var, value);
- } else if (!strcmp("uploadpack.allowrefinwant", var)) {
- data->allow_ref_in_want = git_config_bool(var, value);
- } else if (!strcmp("uploadpack.allowsidebandall", var)) {
- data->allow_sideband_all = git_config_bool(var, value);
+ config_keepalive = git_config_int(var, value);
+ if (!config_keepalive)
+ config_keepalive = -1;
} else if (!strcmp("core.precomposeunicode", var)) {
precomposed_unicode = git_config_bool(var, value);
} else if (!strcmp("transfer.advertisesid", var)) {
- data->advertise_sid = git_config_bool(var, value);
+ config_advertise_sid = git_config_bool(var, value);
}
if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
current_config_scope() != CONFIG_SCOPE_WORKTREE) {
if (!strcmp("uploadpack.packobjectshook", var))
- return git_config_string(&data->pack_objects_hook, var, value);
+ return git_config_string(&config_pack_objects_hook, var, value);
+ }
+ return 0;
+}
+
+static int upload_pack_startup_config_v2_only(const char *var,
+ const char *value, void *cb_data)
+{
+ if (!strcmp("uploadpack.allowrefinwant", var))
+ config_v2_allow_ref_in_want = git_config_bool(var, value);
+ else if (!strcmp("uploadpack.allowsidebandall", var))
+ config_v2_allow_sideband_all = git_config_bool(var, value);
+ return 0;
+}
+
+int serve_upload_pack_startup_config(const char *var, const char *value, void *data)
+{
+ int ret;
+ ret = upload_pack_startup_config(var, value, data);
+ if (ret)
+ return ret;
+ ret = upload_pack_startup_config_v2_only(var, value, data);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static int upload_pack_config(const char *var, const char *value,
+ void *cb_data)
+{
+ struct upload_pack_data *data = cb_data;
+
+ if (!strcmp("uploadpack.allowfilter", var)) {
+ data->allow_filter = git_config_bool(var, value);
}
if (parse_object_filter_config(var, value, data) < 0)
@@ -1336,6 +1361,8 @@ void upload_pack(struct upload_pack_options *options)
upload_pack_data_init(&data);
+ if (!v1_have_startup_config++)
+ git_config(upload_pack_startup_config, NULL);
git_config(upload_pack_config, &data);
data.stateless_rpc = options->stateless_rpc;
@@ -1468,7 +1495,7 @@ static void process_args(struct packet_reader *request,
/* process want */
if (parse_want(&data->writer, arg, &data->want_obj))
continue;
- if (data->allow_ref_in_want &&
+ if (config_v2_allow_ref_in_want &&
parse_want_ref(&data->writer, arg, &data->wanted_refs,
&data->want_obj))
continue;
@@ -1526,7 +1553,7 @@ static void process_args(struct packet_reader *request,
}
if ((git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
- data->allow_sideband_all) &&
+ config_v2_allow_sideband_all) &&
!strcmp(arg, "sideband-all")) {
data->writer.use_sideband = 1;
continue;
diff --git a/upload-pack.h b/upload-pack.h
index 27ddcdc6cb0..bd8b1ec5b3e 100644
--- a/upload-pack.h
+++ b/upload-pack.h
@@ -19,5 +19,7 @@ int upload_pack_v2(struct repository *r, struct strvec *keys,
struct strbuf;
int upload_pack_advertise(struct repository *r,
struct strbuf *value);
+int serve_upload_pack_startup_config(const char *var, const char *value,
+ void *data);
#endif /* UPLOAD_PACK_H */
--
2.32.0.611.gd4a17395dfa
next prev parent reply other threads:[~2021-06-28 19:19 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-16 14:16 [PATCH 0/5] serve: add "configure" callback Ævar Arnfjörð Bjarmason
2021-06-16 14:16 ` [PATCH 1/5] serve: mark has_capability() as static Ævar Arnfjörð Bjarmason
2021-06-16 16:28 ` Eric Sunshine
2021-06-17 0:45 ` Junio C Hamano
2021-06-16 14:16 ` [PATCH 2/5] transport: rename "fetch" in transport_vtable to "fetch_refs" Ævar Arnfjörð Bjarmason
2021-06-16 14:16 ` [PATCH 3/5] transport: use designated initializers Ævar Arnfjörð Bjarmason
2021-06-16 14:16 ` [PATCH 4/5] serve: " Ævar Arnfjörð Bjarmason
2021-06-16 14:16 ` [PATCH 5/5] serve: add support for a git_config() callback Ævar Arnfjörð Bjarmason
2021-06-16 16:22 ` Jeff King
2021-06-16 16:23 ` [PATCH 0/5] serve: add "configure" callback Jeff King
2021-06-17 0:49 ` Junio C Hamano
2021-06-28 19:19 ` [PATCH v2 0/8] serve: add "startup_config" callback Ævar Arnfjörð Bjarmason
2021-06-28 19:19 ` [PATCH v2 1/8] serve: mark has_capability() as static Ævar Arnfjörð Bjarmason
2021-06-28 19:19 ` [PATCH v2 2/8] transport: rename "fetch" in transport_vtable to "fetch_refs" Ævar Arnfjörð Bjarmason
2021-06-28 19:19 ` [PATCH v2 3/8] transport: use designated initializers Ævar Arnfjörð Bjarmason
2021-06-28 19:19 ` [PATCH v2 4/8] serve: " Ævar Arnfjörð Bjarmason
2021-06-28 19:19 ` [PATCH v2 5/8] serve.c: add call_{advertise,command}() indirection Ævar Arnfjörð Bjarmason
2021-06-28 19:19 ` [PATCH v2 6/8] serve.c: add trace2 regions for advertise & command Ævar Arnfjörð Bjarmason
2021-07-01 16:30 ` Jeff King
2021-07-02 12:54 ` Ævar Arnfjörð Bjarmason
2021-07-05 12:24 ` Han-Wen Nienhuys
2021-06-28 19:19 ` [PATCH v2 7/8] serve: add support for a "startup" git_config() callback Ævar Arnfjörð Bjarmason
2021-07-01 16:43 ` Jeff King
2021-07-01 16:47 ` Jeff King
2021-07-02 12:55 ` Ævar Arnfjörð Bjarmason
2021-07-02 21:13 ` Jeff King
2021-07-05 12:23 ` Han-Wen Nienhuys
2021-07-05 12:34 ` Han-Wen Nienhuys
2021-06-28 19:19 ` Ævar Arnfjörð Bjarmason [this message]
2021-07-05 14:00 ` [PATCH v2 8/8] upload-pack.c: convert to new serve.c "startup" config cb Han-Wen Nienhuys
2021-07-21 23:40 ` [PATCH v3 00/12] serve.[ch]: general API cleanup Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 01/12] serve: mark has_capability() as static Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 02/12] transport: rename "fetch" in transport_vtable to "fetch_refs" Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 03/12] transport: use designated initializers Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 04/12] serve: " Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 05/12] serve.c: add call_{advertise,command}() indirection Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 06/12] serve: add support for a "startup" git_config() callback Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 07/12] serve.c: move version line to advertise_capabilities() Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 08/12] serve.[ch]: remove "serve_options", split up --advertise-refs code Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 09/12] {upload,receive}-pack tests: add --advertise-refs tests Ævar Arnfjörð Bjarmason
2021-08-03 6:00 ` [PATCH] fixup! " Carlo Marcelo Arenas Belón
2021-07-21 23:40 ` [PATCH v3 10/12] upload-pack: document and rename --advertise-refs Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 11/12] upload-pack.c: convert to new serve.c "startup" config cb Ævar Arnfjörð Bjarmason
2021-07-21 23:40 ` [PATCH v3 12/12] serve.[ch]: don't pass "struct strvec *keys" to commands Ævar Arnfjörð Bjarmason
2021-08-02 21:07 ` [PATCH v3 00/12] serve.[ch]: general API cleanup Josh Steadmon
2021-08-05 1:25 ` [PATCH v4 00/10] serve.[ch]: general API cleanup + --advertise-refs cleanup Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 01/10] serve: mark has_capability() as static Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 02/10] transport: rename "fetch" in transport_vtable to "fetch_refs" Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 03/10] transport: use designated initializers Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 04/10] serve: " Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 05/10] serve.[ch]: don't pass "struct strvec *keys" to commands Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 06/10] serve: move transfer.advertiseSID check into session_id_advertise() Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 07/10] serve.c: move version line to advertise_capabilities() Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 08/10] {upload,receive}-pack tests: add --advertise-refs tests Ævar Arnfjörð Bjarmason
2021-08-05 1:25 ` [PATCH v4 09/10] serve.[ch]: remove "serve_options", split up --advertise-refs code Ævar Arnfjörð Bjarmason
2021-08-24 16:52 ` Derrick Stolee
2021-08-05 1:25 ` [PATCH v4 10/10] upload-pack: document and rename --advertise-refs Ævar Arnfjörð Bjarmason
2021-08-24 16:55 ` [PATCH v4 00/10] serve.[ch]: general API cleanup + --advertise-refs cleanup Derrick Stolee
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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=patch-8.8-9fd6138aa62-20210628T191634Z-avarab@gmail.com \
--to=avarab@gmail.com \
--cc=bga@google.com \
--cc=chriscool@tuxfamily.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jonathantanmy@google.com \
--cc=peff@peff.net \
--cc=steadmon@google.com \
--cc=sunshine@sunshineco.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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).