]> git.ipfire.org Git - thirdparty/git.git/blobdiff - connect.c
Merge branch 'bc/sha-256-part-2'
[thirdparty/git.git] / connect.c
index eaa13b41bbeb9d0a170baf044ae52d85c63fc85f..e0d5b9fee05fc5db4c329d4825600020dce8910a 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -18,7 +18,6 @@
 
 static char *server_capabilities_v1;
 static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
-static const char *parse_feature_value(const char *, const char *, int *, int *);
 static const char *next_server_feature_value(const char *feature, int *len, int *offset);
 
 static int check_ref(const char *name, unsigned int flags)
@@ -143,6 +142,7 @@ enum protocol_version discover_version(struct packet_reader *reader)
                die_initial_contact(0);
        case PACKET_READ_FLUSH:
        case PACKET_READ_DELIM:
+       case PACKET_READ_RESPONSE_END:
                version = protocol_v0;
                break;
        case PACKET_READ_NORMAL:
@@ -221,12 +221,25 @@ static void annotate_refs_with_symref_info(struct ref *ref)
 
 static void process_capabilities(struct packet_reader *reader, int *linelen)
 {
+       const char *feat_val;
+       int feat_len;
        const char *line = reader->line;
        int nul_location = strlen(line);
        if (nul_location == *linelen)
                return;
        server_capabilities_v1 = xstrdup(line + nul_location + 1);
        *linelen = nul_location;
+
+       feat_val = server_feature_value("object-format", &feat_len);
+       if (feat_val) {
+               char *hash_name = xstrndup(feat_val, feat_len);
+               int hash_algo = hash_algo_by_name(hash_name);
+               if (hash_algo != GIT_HASH_UNKNOWN)
+                       reader->hash_algo = &hash_algos[hash_algo];
+               free(hash_name);
+       } else {
+               reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
+       }
 }
 
 static int process_dummy_ref(const struct packet_reader *reader)
@@ -235,7 +248,7 @@ static int process_dummy_ref(const struct packet_reader *reader)
        struct object_id oid;
        const char *name;
 
-       if (parse_oid_hex(line, &oid, &name))
+       if (parse_oid_hex_algop(line, &oid, &name, reader->hash_algo))
                return 0;
        if (*name != ' ')
                return 0;
@@ -259,7 +272,7 @@ static int process_ref(const struct packet_reader *reader, int len,
        struct object_id old_oid;
        const char *name;
 
-       if (parse_oid_hex(line, &old_oid, &name))
+       if (parse_oid_hex_algop(line, &old_oid, &name, reader->hash_algo))
                return 0;
        if (*name != ' ')
                return 0;
@@ -289,7 +302,7 @@ static int process_shallow(const struct packet_reader *reader, int len,
        if (!skip_prefix(line, "shallow ", &arg))
                return 0;
 
-       if (get_oid_hex(arg, &old_oid))
+       if (get_oid_hex_algop(arg, &old_oid, reader->hash_algo))
                die(_("protocol error: expected shallow sha-1, got '%s'"), arg);
        if (!shallow_points)
                die(_("repository on the other end cannot be shallow"));
@@ -330,6 +343,7 @@ struct ref **get_remote_heads(struct packet_reader *reader,
                        state = EXPECTING_DONE;
                        break;
                case PACKET_READ_DELIM:
+               case PACKET_READ_RESPONSE_END:
                        die(_("invalid packet"));
                }
 
@@ -362,7 +376,7 @@ struct ref **get_remote_heads(struct packet_reader *reader,
 }
 
 /* Returns 1 when a valid ref has been added to `list`, 0 otherwise */
-static int process_ref_v2(const char *line, struct ref ***list)
+static int process_ref_v2(struct packet_reader *reader, struct ref ***list)
 {
        int ret = 1;
        int i = 0;
@@ -370,6 +384,7 @@ static int process_ref_v2(const char *line, struct ref ***list)
        struct ref *ref;
        struct string_list line_sections = STRING_LIST_INIT_DUP;
        const char *end;
+       const char *line = reader->line;
 
        /*
         * Ref lines have a number of fields which are space deliminated.  The
@@ -382,7 +397,7 @@ static int process_ref_v2(const char *line, struct ref ***list)
                goto out;
        }
 
-       if (parse_oid_hex(line_sections.items[i++].string, &old_oid, &end) ||
+       if (parse_oid_hex_algop(line_sections.items[i++].string, &old_oid, &end, reader->hash_algo) ||
            *end) {
                ret = 0;
                goto out;
@@ -390,7 +405,7 @@ static int process_ref_v2(const char *line, struct ref ***list)
 
        ref = alloc_ref(line_sections.items[i++].string);
 
-       oidcpy(&ref->old_oid, &old_oid);
+       memcpy(ref->old_oid.hash, old_oid.hash, reader->hash_algo->rawsz);
        **list = ref;
        *list = &ref->next;
 
@@ -403,7 +418,8 @@ static int process_ref_v2(const char *line, struct ref ***list)
                        struct object_id peeled_oid;
                        char *peeled_name;
                        struct ref *peeled;
-                       if (parse_oid_hex(arg, &peeled_oid, &end) || *end) {
+                       if (parse_oid_hex_algop(arg, &peeled_oid, &end,
+                                               reader->hash_algo) || *end) {
                                ret = 0;
                                goto out;
                        }
@@ -411,7 +427,8 @@ static int process_ref_v2(const char *line, struct ref ***list)
                        peeled_name = xstrfmt("%s^{}", ref->name);
                        peeled = alloc_ref(peeled_name);
 
-                       oidcpy(&peeled->old_oid, &peeled_oid);
+                       memcpy(peeled->old_oid.hash, peeled_oid.hash,
+                              reader->hash_algo->rawsz);
                        **list = peeled;
                        *list = &peeled->next;
 
@@ -424,12 +441,24 @@ out:
        return ret;
 }
 
+void check_stateless_delimiter(int stateless_rpc,
+                             struct packet_reader *reader,
+                             const char *error)
+{
+       if (!stateless_rpc)
+               return; /* not in stateless mode, no delimiter expected */
+       if (packet_reader_read(reader) != PACKET_READ_RESPONSE_END)
+               die("%s", error);
+}
+
 struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
                             struct ref **list, int for_push,
                             const struct argv_array *ref_prefixes,
-                            const struct string_list *server_options)
+                            const struct string_list *server_options,
+                            int stateless_rpc)
 {
        int i;
+       const char *hash_name;
        *list = NULL;
 
        if (server_supports_v2("ls-refs", 1))
@@ -438,6 +467,16 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
        if (server_supports_v2("agent", 0))
                packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
 
+       if (server_feature_v2("object-format", &hash_name)) {
+               int hash_algo = hash_algo_by_name(hash_name);
+               if (hash_algo == GIT_HASH_UNKNOWN)
+                       die(_("unknown object format '%s' specified by server"), hash_name);
+               reader->hash_algo = &hash_algos[hash_algo];
+               packet_write_fmt(fd_out, "object-format=%s", reader->hash_algo->name);
+       } else {
+               reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
+       }
+
        if (server_options && server_options->nr &&
            server_supports_v2("server-option", 1))
                for (i = 0; i < server_options->nr; i++)
@@ -457,17 +496,20 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
 
        /* Process response from server */
        while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
-               if (!process_ref_v2(reader->line, &list))
+               if (!process_ref_v2(reader, &list))
                        die(_("invalid ls-refs response: %s"), reader->line);
        }
 
        if (reader->status != PACKET_READ_FLUSH)
                die(_("expected flush after ref listing"));
 
+       check_stateless_delimiter(stateless_rpc, reader,
+                                 _("expected response end packet after ref listing"));
+
        return list;
 }
 
-static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
+const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
 {
        int len;