cache-tree: use is_empty_tree_oid
[gitweb.git] / upload-pack.c
index e6d38b9ca06797ab369b0f583a79ced3ecdbf128..1fb4942235ee07e65c388989d0cfa38ba68b9777 100644 (file)
@@ -20,6 +20,7 @@
 #include "parse-options.h"
 #include "argv-array.h"
 #include "prio-queue.h"
+#include "protocol.h"
 #include "quote.h"
 
 static const char * const upload_pack_usage[] = {
@@ -68,7 +69,7 @@ static int stateless_rpc;
 static const char *pack_objects_hook;
 
 static int filter_capability_requested;
-static int filter_advertise;
+static int allow_filter;
 static struct list_objects_filter_options filter_options;
 
 static void reset_timeout(void)
@@ -139,10 +140,15 @@ static void create_pack_file(void)
        if (use_include_tag)
                argv_array_push(&pack_objects.args, "--include-tag");
        if (filter_options.filter_spec) {
-               struct strbuf buf = STRBUF_INIT;
-               sq_quote_buf(&buf, filter_options.filter_spec);
-               argv_array_pushf(&pack_objects.args, "--filter=%s", buf.buf);
-               strbuf_release(&buf);
+               if (pack_objects.use_shell) {
+                       struct strbuf buf = STRBUF_INIT;
+                       sq_quote_buf(&buf, filter_options.filter_spec);
+                       argv_array_pushf(&pack_objects.args, "--filter=%s", buf.buf);
+                       strbuf_release(&buf);
+               } else {
+                       argv_array_pushf(&pack_objects.args, "--filter=%s",
+                                        filter_options.filter_spec);
+               }
        }
 
        pack_objects.in = -1;
@@ -444,7 +450,7 @@ static int get_common_commits(void)
                                break;
                        default:
                                got_common = 1;
-                               memcpy(last_hex, oid_to_hex(&oid), 41);
+                               oid_to_hex_r(last_hex, &oid);
                                if (multi_ack == 2)
                                        packet_write_fmt(1, "ACK %s common\n", last_hex);
                                else if (multi_ack)
@@ -486,7 +492,7 @@ static int do_reachable_revlist(struct child_process *cmd,
                "rev-list", "--stdin", NULL,
        };
        struct object *o;
-       char namebuf[42]; /* ^ + SHA-1 + LF */
+       char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
        int i;
 
        cmd->argv = argv;
@@ -555,15 +561,17 @@ static int get_reachable_list(struct object_array *src,
        struct child_process cmd = CHILD_PROCESS_INIT;
        int i;
        struct object *o;
-       char namebuf[42]; /* ^ + SHA-1 + LF */
+       char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
+       const unsigned hexsz = the_hash_algo->hexsz;
 
        if (do_reachable_revlist(&cmd, src, reachable) < 0)
                return -1;
 
-       while ((i = read_in_full(cmd.out, namebuf, 41)) == 41) {
+       while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
                struct object_id sha1;
+               const char *p;
 
-               if (namebuf[40] != '\n' || get_oid_hex(namebuf, &sha1))
+               if (parse_oid_hex(namebuf, &sha1, &p) || *p != '\n')
                        break;
 
                o = lookup_object(sha1.hash);
@@ -800,7 +808,7 @@ static void receive_needs(void)
                if (skip_prefix(line, "deepen-not ", &arg)) {
                        char *ref = NULL;
                        struct object_id oid;
-                       if (expand_ref(arg, strlen(arg), oid.hash, &ref) != 1)
+                       if (expand_ref(arg, strlen(arg), &oid, &ref) != 1)
                                die("git upload-pack: ambiguous deepen-not: %s", line);
                        string_list_append(&deepen_not, ref);
                        free(ref);
@@ -814,11 +822,9 @@ static void receive_needs(void)
                        continue;
                }
                if (!skip_prefix(line, "want ", &arg) ||
-                   get_oid_hex(arg, &oid_buf))
+                   parse_oid_hex(arg, &oid_buf, &features))
                        die("git upload-pack: protocol error, "
-                           "expected to get sha, not '%s'", line);
-
-               features = arg + 40;
+                           "expected to get object ID, not '%s'", line);
 
                if (parse_feature_request(features, "deepen-relative"))
                        deepen_relative = 1;
@@ -840,7 +846,7 @@ static void receive_needs(void)
                        no_progress = 1;
                if (parse_feature_request(features, "include-tag"))
                        use_include_tag = 1;
-               if (parse_feature_request(features, "filter"))
+               if (allow_filter && parse_feature_request(features, "filter"))
                        filter_capability_requested = 1;
 
                o = parse_object(&oid_buf);
@@ -970,14 +976,14 @@ static int send_ref(const char *refname, const struct object_id *oid,
                                     " allow-reachable-sha1-in-want" : "",
                             stateless_rpc ? " no-done" : "",
                             symref_info.buf,
-                            filter_advertise ? " filter" : "",
+                            allow_filter ? " filter" : "",
                             git_user_agent_sanitized());
                strbuf_release(&symref_info);
        } else {
                packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), refname_nons);
        }
        capabilities = NULL;
-       if (!peel_ref(refname, peeled.hash))
+       if (!peel_ref(refname, &peeled))
                packet_write_fmt(1, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
        return 0;
 }
@@ -1050,7 +1056,7 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
                if (!strcmp("uploadpack.packobjectshook", var))
                        return git_config_string(&pack_objects_hook, var, value);
        } else if (!strcmp("uploadpack.allowfilter", var)) {
-               filter_advertise = git_config_bool(var, value);
+               allow_filter = git_config_bool(var, value);
        }
        return parse_hide_refs_config(var, value, "uploadpack");
 }
@@ -1090,6 +1096,23 @@ int cmd_main(int argc, const char **argv)
                die("'%s' does not appear to be a git repository", dir);
 
        git_config(upload_pack_config, NULL);
-       upload_pack();
+
+       switch (determine_protocol_version_server()) {
+       case protocol_v1:
+               /*
+                * v1 is just the original protocol with a version string,
+                * so just fall through after writing the version string.
+                */
+               if (advertise_refs || !stateless_rpc)
+                       packet_write_fmt(1, "version 1\n");
+
+               /* fallthrough */
+       case protocol_v0:
+               upload_pack();
+               break;
+       case protocol_unknown_version:
+               BUG("unknown protocol version");
+       }
+
        return 0;
 }