protocol-caps: check object existence regardless of the attributes requested
Currently, send_info() only checks for existence when the attribute
'size' is also requested. Requesting a bare OID, without attributes only
echoes back the OID.
Extract the existence check to be done regardless of the number of
attributes requested.
While at it, introduce a wrapper called get_object_info() similar to
odb_read_object_info() that returns OBJ_BAD on fail and adds
OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK flags.
OBJECT_INFO_SKIP_FETCH_OBJECT is so a server with a partial clone
doesn't trigger fetching objects when it gets an object-info request
with an OID that is not available locally. A server should only report
what it has locally.
Tighten the condition used to determine whether an object is
recognized. get_object_info() returns OBJ_BAD for unknown objects,
but OBJ_NONE (0) can also mean "not found". Change the check from '< 0'
to '<= OBJ_NONE' to cover both as unrecognized.
With this patch, a bare OID has two possible responses:
1. Recognized OID: the server answers with "<OID>"
2. Unrecognized OID: the server answers with "<OID> SP"
Update the object-info section in 'gitprotocol-v2.adoc':
- Require full obj-oid explicitly.
- Fix parentheses.
- Define obj-size explicitly.
- Make obj-size optional in obj-info and document the behavior
for unrecognized object IDs.
- Describe the attr header as zero or more pkt-lines, one per attribute,
matching what the server implements. A request with no attributes gets
no header.
Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Pablo Sabater committedJul 24, 2026 at 12:54 UTCe44aca614596d49ca802f1602eaf9a4850c3c07d
3 files changed+115-14
Documentation/gitprotocol-v2.adoc
+13-8
index 2beb70595f..7bf62014c3 100644--- a/Documentation/gitprotocol-v2.adoc+++ b/Documentation/gitprotocol-v2.adoc@@ -568,21 +568,26 @@ An `object-info` request takes the following arguments: oid <oid> Indicates to the server an object which the client wants to obtain- information for.+ information for. They must be full OIDs.-The response of `object-info` is a list of the requested object ids-and associated requested information, each separated by a single space.+The response of `object-info` consists of one pkt-line per requested attribute,+echoing the attributes the server will report, followed by one pkt-line per+requested object id with its information, each field separated by a single+space. output = info flush-pkt- info = PKT-LINE(attrs) LF)- *PKT-LINE(obj-info LF)-- attrs = attr | attrs SP attrs+ info = *PKT-LINE(attr LF)+ *PKT-LINE(obj-info LF) attr = "size"- obj-info = obj-id SP obj-size+ obj-size = 1*DIGIT++ obj-info = obj-id [SP [obj-size]]++If the server does not recognize the OID, the response will be `<oid> SP`+regardless of the number of attributes requested. bundle-uri ~~~~~~~~~~
protocol-caps.c
+39-6
index 8858ea4489..02261be14d 100644--- a/protocol-caps.c+++ b/protocol-caps.c@@ -30,6 +30,32 @@ static int parse_oid(const char *line, struct string_list *oid_str_list) return 1; }+/*+ * odb_read_object_info_extended() wrapper. Similar to odb_read_object_info()+ * but uses the flags:+ *+ * - OBJECT_INFO_SKIP_FETCH_OBJECT so a server won't fetch an object when a+ * object-info request asks for an OID that it doesn't have.+ *+ * - OBJECT_INFO_QUICK to avoid re-scanning packs when the object is not found.+ */+static enum object_type get_object_info(struct object_database *odb,+ const struct object_id *oid,+ size_t *sizep)+{+ enum object_type type;+ struct object_info oi = OBJECT_INFO_INIT;++ oi.typep = &type;+ oi.sizep = sizep;+ if (odb_read_object_info_extended(odb, oid, &oi,+ OBJECT_INFO_LOOKUP_REPLACE |+ OBJECT_INFO_SKIP_FETCH_OBJECT |+ OBJECT_INFO_QUICK) < 0)+ return OBJ_BAD;+ return type;+}+ /* * Validates and send requested info back to the client. Any errors detected * are returned as they are detected.@@ -62,15 +88,22 @@ static void send_info(struct repository *r, struct packet_writer *writer, strbuf_addstr(&send_buffer, oid_str);+ /*+ * Check the existence of the object first.+ * If an object is not recognized by the server append SP to+ * the response.+ */+ if (get_object_info(r->objects, &oid, &object_size) <= OBJ_NONE) {+ strbuf_addstr(&send_buffer, " ");+ goto write;+ }+ if (info->size) {- if (odb_read_object_info(r->objects, &oid, &object_size) < 0) {- strbuf_addstr(&send_buffer, " ");- } else {- strbuf_addf(&send_buffer, " %"PRIuMAX,- (uintmax_t)object_size);- }+ strbuf_addf(&send_buffer, " %"PRIuMAX,+ (uintmax_t)object_size); }+write: packet_writer_write(writer, "%s", send_buffer.buf); strbuf_reset(&send_buffer); }