fsck: add stress tests for fsck.skipList
[gitweb.git] / fetch-pack.c
index 0b4a9f288f973a13ab8c55b420d52143ee1d026d..aea2f6cf263b56ec392745764cddf24ddcd88a69 100644 (file)
@@ -19,6 +19,9 @@
 #include "sha1-array.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-store.h"
+#include "connected.h"
+#include "fsck.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -33,6 +36,7 @@ static int agent_supported;
 static int server_supports_filtering;
 static struct lock_file shallow_lock;
 static const char *alternate_shallow_file;
+static struct strbuf fsck_msg_types = STRBUF_INIT;
 
 /* Remember to update object flag allocation in object.h */
 #define COMPLETE       (1U << 0)
@@ -396,7 +400,7 @@ static int find_common(struct fetch_pack_args *args,
                return 1;
        }
 
-       if (is_repository_shallow())
+       if (is_repository_shallow(the_repository))
                write_shallow_commits(&req_buf, 1, NULL);
        if (args->depth > 0)
                packet_buf_write(&req_buf, "deepen %d", args->depth);
@@ -427,7 +431,7 @@ static int find_common(struct fetch_pack_args *args,
                        if (skip_prefix(line, "shallow ", &arg)) {
                                if (get_oid_hex(arg, &oid))
                                        die(_("invalid shallow line: %s"), line);
-                               register_shallow(&oid);
+                               register_shallow(the_repository, &oid);
                                continue;
                        }
                        if (skip_prefix(line, "unshallow ", &arg)) {
@@ -657,11 +661,11 @@ static void filter_refs(struct fetch_pack_args *args,
                                }
                                i++;
                        }
-               }
 
-               if (!keep && args->fetch_all &&
-                   (!args->deepen || !starts_with(ref->name, "refs/tags/")))
-                       keep = 1;
+                       if (!keep && args->fetch_all &&
+                           (!args->deepen || !starts_with(ref->name, "refs/tags/")))
+                               keep = 1;
+               }
 
                if (keep) {
                        *newtail = ref;
@@ -935,7 +939,8 @@ static int get_pack(struct fetch_pack_args *args,
                         */
                        argv_array_push(&cmd.args, "--fsck-objects");
                else
-                       argv_array_push(&cmd.args, "--strict");
+                       argv_array_pushf(&cmd.args, "--strict%s",
+                                        fsck_msg_types.buf);
        }
 
        cmd.in = demux.out;
@@ -985,7 +990,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        sort_ref_list(&ref, ref_compare_name);
        QSORT(sought, nr_sought, cmp_ref_by_name);
 
-       if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow"))
+       if ((args->depth > 0 || is_repository_shallow(the_repository)) && !server_supports("shallow"))
                die(_("Server does not support shallow clients"));
        if (args->depth > 0 || args->deepen_since || args->deepen_not)
                args->deepen = 1;
@@ -1083,7 +1088,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 static void add_shallow_requests(struct strbuf *req_buf,
                                 const struct fetch_pack_args *args)
 {
-       if (is_repository_shallow())
+       if (is_repository_shallow(the_repository))
                write_shallow_commits(req_buf, 1, NULL);
        if (args->depth > 0)
                packet_buf_write(req_buf, "deepen %d", args->depth);
@@ -1198,7 +1203,7 @@ static int send_fetch_request(int fd_out, const struct fetch_pack_args *args,
        /* Add shallow-info and deepen request */
        if (server_supports_feature("fetch", "shallow", 0))
                add_shallow_requests(&req_buf, args);
-       else if (is_repository_shallow() || args->deepen)
+       else if (is_repository_shallow(the_repository) || args->deepen)
                die(_("Server does not support shallow requests"));
 
        /* Add filter */
@@ -1311,7 +1316,7 @@ static void receive_shallow_info(struct fetch_pack_args *args,
                if (skip_prefix(reader->line, "shallow ", &arg)) {
                        if (get_oid_hex(arg, &oid))
                                die(_("invalid shallow line: %s"), reader->line);
-                       register_shallow(&oid);
+                       register_shallow(the_repository, &oid);
                        continue;
                }
                if (skip_prefix(reader->line, "unshallow ", &arg)) {
@@ -1456,6 +1461,31 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
        return ref;
 }
 
+static int fetch_pack_config_cb(const char *var, const char *value, void *cb)
+{
+       if (strcmp(var, "fetch.fsck.skiplist") == 0) {
+               const char *path;
+
+               if (git_config_pathname(&path, var, value))
+                       return 1;
+               strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
+                       fsck_msg_types.len ? ',' : '=', path);
+               free((char *)path);
+               return 0;
+       }
+
+       if (skip_prefix(var, "fetch.fsck.", &var)) {
+               if (is_valid_msg_type(var, value))
+                       strbuf_addf(&fsck_msg_types, "%c%s=%s",
+                               fsck_msg_types.len ? ',' : '=', var, value);
+               else
+                       warning("Skipping unknown msg id '%s'", var);
+               return 0;
+       }
+
+       return git_default_config(var, value, cb);
+}
+
 static void fetch_pack_config(void)
 {
        git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit);
@@ -1464,7 +1494,7 @@ static void fetch_pack_config(void)
        git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
        git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
 
-       git_config(git_default_config, NULL);
+       git_config(fetch_pack_config_cb, NULL);
 }
 
 static void fetch_pack_setup(void)
@@ -1512,7 +1542,7 @@ static void update_shallow(struct fetch_pack_args *args,
 
        if (args->deepen && alternate_shallow_file) {
                if (*alternate_shallow_file == '\0') { /* --unshallow */
-                       unlink_or_warn(git_path_shallow());
+                       unlink_or_warn(git_path_shallow(the_repository));
                        rollback_lock_file(&shallow_lock);
                } else
                        commit_lock_file(&shallow_lock);
@@ -1596,6 +1626,18 @@ static void update_shallow(struct fetch_pack_args *args,
        oid_array_clear(&ref);
 }
 
+static int iterate_ref_map(void *cb_data, struct object_id *oid)
+{
+       struct ref **rm = cb_data;
+       struct ref *ref = *rm;
+
+       if (!ref)
+               return -1; /* end of the list */
+       *rm = ref->next;
+       oidcpy(oid, &ref->old_oid);
+       return 0;
+}
+
 struct ref *fetch_pack(struct fetch_pack_args *args,
                       int fd[], struct child_process *conn,
                       const struct ref *ref,
@@ -1624,7 +1666,25 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
                ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
                                        &si, pack_lockfile);
        reprepare_packed_git(the_repository);
+
+       if (!args->cloning && args->deepen) {
+               struct check_connected_options opt = CHECK_CONNECTED_INIT;
+               struct ref *iterator = ref_cpy;
+               opt.shallow_file = alternate_shallow_file;
+               if (args->deepen)
+                       opt.is_deepening_fetch = 1;
+               if (check_connected(iterate_ref_map, &iterator, &opt)) {
+                       error(_("remote did not send all necessary objects"));
+                       free_refs(ref_cpy);
+                       ref_cpy = NULL;
+                       rollback_lock_file(&shallow_lock);
+                       goto cleanup;
+               }
+               args->connectivity_checked = 1;
+       }
+
        update_shallow(args, ref_cpy, &si);
+cleanup:
        clear_shallow_info(&si);
        return ref_cpy;
 }