refs.c: allow listing and deleting badly named refs
[gitweb.git] / upload-pack.c
index 43342ac161952f5c03c7b737231c4c664b7513a7..ac9ac1592d818da5ae90ec065581e3bf218ffc39 100644 (file)
@@ -17,7 +17,7 @@
 
 static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>";
 
-/* bits #0..7 in revision.h, #8..10 in commit.c */
+/* Remember to update object flag allocation in object.h */
 #define THEY_HAVE      (1u << 11)
 #define OUR_REF                (1u << 12)
 #define WANTED         (1u << 13)
@@ -70,9 +70,17 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
        return sz;
 }
 
+static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
+{
+       FILE *fp = cb_data;
+       if (graft->nr_parent == -1)
+               fprintf(fp, "--shallow %s\n", sha1_to_hex(graft->sha1));
+       return 0;
+}
+
 static void create_pack_file(void)
 {
-       struct child_process pack_objects;
+       struct child_process pack_objects = CHILD_PROCESS_INIT;
        char data[8193], progress[128];
        char abort_msg[] = "aborting due to possible repository "
                "corruption on the remote side.";
@@ -81,12 +89,10 @@ static void create_pack_file(void)
        const char *argv[12];
        int i, arg = 0;
        FILE *pipe_fd;
-       char *shallow_file = NULL;
 
        if (shallow_nr) {
-               shallow_file = setup_temporary_shallow();
                argv[arg++] = "--shallow-file";
-               argv[arg++] = shallow_file;
+               argv[arg++] = "";
        }
        argv[arg++] = "pack-objects";
        argv[arg++] = "--revs";
@@ -102,7 +108,6 @@ static void create_pack_file(void)
                argv[arg++] = "--include-tag";
        argv[arg++] = NULL;
 
-       memset(&pack_objects, 0, sizeof(pack_objects));
        pack_objects.in = -1;
        pack_objects.out = -1;
        pack_objects.err = -1;
@@ -114,6 +119,9 @@ static void create_pack_file(void)
 
        pipe_fd = xfdopen(pack_objects.in, "w");
 
+       if (shallow_nr)
+               for_each_commit_graft(write_one_shallow, pipe_fd);
+
        for (i = 0; i < want_obj.nr; i++)
                fprintf(pipe_fd, "%s\n",
                        sha1_to_hex(want_obj.objects[i].item->sha1));
@@ -158,7 +166,9 @@ static void create_pack_file(void)
                if (!pollsize)
                        break;
 
-               ret = poll(pfd, pollsize, 1000 * keepalive);
+               ret = poll(pfd, pollsize,
+                       keepalive < 0 ? -1 : 1000 * keepalive);
+
                if (ret < 0) {
                        if (errno != EINTR) {
                                error("poll failed, resuming: %s",
@@ -242,11 +252,6 @@ static void create_pack_file(void)
                error("git upload-pack: git-pack-objects died with error.");
                goto fail;
        }
-       if (shallow_file) {
-               if (*shallow_file)
-                       unlink(shallow_file);
-               free(shallow_file);
-       }
 
        /* flush the data */
        if (0 <= buffered) {
@@ -394,7 +399,7 @@ static int get_common_commits(void)
                        got_other = 0;
                        continue;
                }
-               if (!prefixcmp(line, "have ")) {
+               if (starts_with(line, "have ")) {
                        switch (got_sha1(line+5, sha1)) {
                        case -1: /* they have what we do not */
                                got_other = 1;
@@ -444,7 +449,7 @@ static void check_non_tip(void)
        static const char *argv[] = {
                "rev-list", "--stdin", NULL,
        };
-       static struct child_process cmd;
+       static struct child_process cmd = CHILD_PROCESS_INIT;
        struct object *o;
        char namebuf[42]; /* ^ + SHA-1 + LF */
        int i;
@@ -540,7 +545,7 @@ static void receive_needs(void)
                if (!line)
                        break;
 
-               if (!prefixcmp(line, "shallow ")) {
+               if (starts_with(line, "shallow ")) {
                        unsigned char sha1[20];
                        struct object *object;
                        if (get_sha1_hex(line + 8, sha1))
@@ -556,14 +561,14 @@ static void receive_needs(void)
                        }
                        continue;
                }
-               if (!prefixcmp(line, "deepen ")) {
+               if (starts_with(line, "deepen ")) {
                        char *end;
                        depth = strtol(line + 7, &end, 0);
                        if (end == line + 7 || depth <= 0)
                                die("Invalid deepen: %s", line);
                        continue;
                }
-               if (prefixcmp(line, "want ") ||
+               if (!starts_with(line, "want ") ||
                    get_sha1_hex(line+5, sha1_buf))
                        die("git upload-pack: protocol error, "
                            "expected to get sha, not '%s'", line);
@@ -619,7 +624,7 @@ static void receive_needs(void)
        if (depth > 0) {
                struct commit_list *result = NULL, *backup = NULL;
                int i;
-               if (depth == INFINITE_DEPTH)
+               if (depth == INFINITE_DEPTH && !is_repository_shallow())
                        for (i = 0; i < shallows.nr; i++) {
                                struct object *object = shallows.objects[i].item;
                                object->flags |= NOT_SHALLOW;
@@ -649,8 +654,7 @@ static void receive_needs(void)
                                /* make sure the real parents are parsed */
                                unregister_shallow(object->sha1);
                                object->parsed = 0;
-                               if (parse_commit((struct commit *)object))
-                                       die("invalid commit");
+                               parse_commit_or_die((struct commit *)object);
                                parents = ((struct commit *)object)->parents;
                                while (parents) {
                                        add_object_array(&parents->item->object,
@@ -740,7 +744,7 @@ static int find_symref(const char *refname, const unsigned char *sha1, int flag,
 
        if ((flag & REF_ISSYMREF) == 0)
                return 0;
-       symref_target = resolve_ref_unsafe(refname, unused, 0, &flag);
+       symref_target = resolve_ref_unsafe(refname, 0, unused, &flag);
        if (!symref_target || (flag & REF_ISSYMREF) == 0)
                die("'%s' is a symref but it is not?", refname);
        item = string_list_append(cb_data, refname);
@@ -753,12 +757,12 @@ static void upload_pack(void)
        struct string_list symref = STRING_LIST_INIT_DUP;
 
        head_ref_namespaced(find_symref, &symref);
-       for_each_namespaced_ref(find_symref, &symref);
 
        if (advertise_refs || !stateless_rpc) {
                reset_timeout();
                head_ref_namespaced(send_ref, &symref);
                for_each_namespaced_ref(send_ref, &symref);
+               advertise_shallow_grafts(1);
                packet_flush(1);
        } else {
                head_ref_namespaced(mark_our_ref, NULL);
@@ -797,7 +801,7 @@ int main(int argc, char **argv)
 
        packet_trace_identity("upload-pack");
        git_extract_argv0_path(argv[0]);
-       read_replace_refs = 0;
+       check_replace_refs = 0;
 
        for (i = 1; i < argc; i++) {
                char *arg = argv[i];
@@ -816,7 +820,7 @@ int main(int argc, char **argv)
                        strict = 1;
                        continue;
                }
-               if (!prefixcmp(arg, "--timeout=")) {
+               if (starts_with(arg, "--timeout=")) {
                        timeout = atoi(arg+10);
                        daemon_mode = 1;
                        continue;
@@ -836,8 +840,7 @@ int main(int argc, char **argv)
 
        if (!enter_repo(dir, strict))
                die("'%s' does not appear to be a git repository", dir);
-       if (is_repository_shallow())
-               die("attempt to fetch/clone from a shallow repository");
+
        git_config(upload_pack_config, NULL);
        upload_pack();
        return 0;