bundle: dup() output descriptor closer to point-of-use
[gitweb.git] / fetch-pack.c
index 0a9d184adb1ef9d82bed175a1155a0aacdc75f09..88a078e9befd281cf5f03e9e64615b14ca768a35 100644 (file)
@@ -21,6 +21,7 @@
 #include "object-store.h"
 #include "connected.h"
 #include "fetch-negotiator.h"
+#include "fsck.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -35,6 +36,8 @@ static int agent_supported;
 static int server_supports_filtering;
 static struct lock_file shallow_lock;
 static const char *alternate_shallow_file;
+static char *negotiation_algorithm;
+static struct strbuf fsck_msg_types = STRBUF_INIT;
 
 /* Remember to update object flag allocation in object.h */
 #define COMPLETE       (1U << 0)
@@ -866,7 +869,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;
@@ -913,7 +917,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        const char *agent_feature;
        int agent_len;
        struct fetch_negotiator negotiator;
-       fetch_negotiator_init(&negotiator);
+       fetch_negotiator_init(&negotiator, negotiation_algorithm);
 
        sort_ref_list(&ref, ref_compare_name);
        QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -1184,13 +1188,13 @@ static int process_section_header(struct packet_reader *reader,
        int ret;
 
        if (packet_reader_peek(reader) != PACKET_READ_NORMAL)
-               die("error reading section header '%s'", section);
+               die(_("error reading section header '%s'"), section);
 
        ret = !strcmp(reader->line, section);
 
        if (!peek) {
                if (!ret)
-                       die("expected '%s', received '%s'",
+                       die(_("expected '%s', received '%s'"),
                            section, reader->line);
                packet_reader_read(reader);
        }
@@ -1229,12 +1233,12 @@ static int process_acks(struct fetch_negotiator *negotiator,
                        continue;
                }
 
-               die("unexpected acknowledgment line: '%s'", reader->line);
+               die(_("unexpected acknowledgment line: '%s'"), reader->line);
        }
 
        if (reader->status != PACKET_READ_FLUSH &&
            reader->status != PACKET_READ_DELIM)
-               die("error processing acks: %d", reader->status);
+               die(_("error processing acks: %d"), reader->status);
 
        /* return 0 if no common, 1 if there are common, or 2 if ready */
        return received_ready ? 2 : (received_ack ? 1 : 0);
@@ -1271,36 +1275,37 @@ static void receive_shallow_info(struct fetch_pack_args *args,
 
        if (reader->status != PACKET_READ_FLUSH &&
            reader->status != PACKET_READ_DELIM)
-               die("error processing shallow info: %d", reader->status);
+               die(_("error processing shallow info: %d"), reader->status);
 
        setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, NULL);
        args->deepen = 1;
 }
 
-static void receive_wanted_refs(struct packet_reader *reader, struct ref *refs)
+static void receive_wanted_refs(struct packet_reader *reader,
+                               struct ref **sought, int nr_sought)
 {
        process_section_header(reader, "wanted-refs", 0);
        while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
                struct object_id oid;
                const char *end;
-               struct ref *r = NULL;
+               int i;
 
                if (parse_oid_hex(reader->line, &oid, &end) || *end++ != ' ')
-                       die("expected wanted-ref, got '%s'", reader->line);
+                       die(_("expected wanted-ref, got '%s'"), reader->line);
 
-               for (r = refs; r; r = r->next) {
-                       if (!strcmp(end, r->name)) {
-                               oidcpy(&r->old_oid, &oid);
+               for (i = 0; i < nr_sought; i++) {
+                       if (!strcmp(end, sought[i]->name)) {
+                               oidcpy(&sought[i]->old_oid, &oid);
                                break;
                        }
                }
 
-               if (!r)
-                       die("unexpected wanted-ref: '%s'", reader->line);
+               if (i == nr_sought)
+                       die(_("unexpected wanted-ref: '%s'"), reader->line);
        }
 
        if (reader->status != PACKET_READ_DELIM)
-               die("error processing wanted refs: %d", reader->status);
+               die(_("error processing wanted refs: %d"), reader->status);
 }
 
 enum fetch_state {
@@ -1324,7 +1329,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
        int in_vain = 0;
        int haves_to_send = INITIAL_FLUSH;
        struct fetch_negotiator negotiator;
-       fetch_negotiator_init(&negotiator);
+       fetch_negotiator_init(&negotiator, negotiation_algorithm);
        packet_reader_init(&reader, fd[0], NULL, 0,
                           PACKET_READ_CHOMP_NEWLINE);
 
@@ -1380,7 +1385,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
                                receive_shallow_info(args, &reader);
 
                        if (process_section_header(&reader, "wanted-refs", 1))
-                               receive_wanted_refs(&reader, ref);
+                               receive_wanted_refs(&reader, sought, nr_sought);
 
                        /* get the pack */
                        process_section_header(&reader, "packfile", 0);
@@ -1399,6 +1404,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);
@@ -1406,8 +1436,10 @@ static void fetch_pack_config(void)
        git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
        git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
        git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
+       git_config_get_string("fetch.negotiationalgorithm",
+                             &negotiation_algorithm);
 
-       git_config(git_default_config, NULL);
+       git_config(fetch_pack_config_cb, NULL);
 }
 
 static void fetch_pack_setup(void)
@@ -1445,13 +1477,12 @@ static int remove_duplicates_in_refs(struct ref **ref, int nr)
 }
 
 static void update_shallow(struct fetch_pack_args *args,
-                          struct ref *refs,
+                          struct ref **sought, int nr_sought,
                           struct shallow_info *si)
 {
        struct oid_array ref = OID_ARRAY_INIT;
        int *status;
        int i;
-       struct ref *r;
 
        if (args->deepen && alternate_shallow_file) {
                if (*alternate_shallow_file == '\0') { /* --unshallow */
@@ -1493,8 +1524,8 @@ static void update_shallow(struct fetch_pack_args *args,
        remove_nonexistent_theirs_shallow(si);
        if (!si->nr_ours && !si->nr_theirs)
                return;
-       for (r = refs; r; r = r->next)
-               oid_array_append(&ref, &r->old_oid);
+       for (i = 0; i < nr_sought; i++)
+               oid_array_append(&ref, &sought[i]->old_oid);
        si->ref = &ref;
 
        if (args->update_shallow) {
@@ -1528,12 +1559,12 @@ static void update_shallow(struct fetch_pack_args *args,
         * remote is also shallow, check what ref is safe to update
         * without updating .git/shallow
         */
-       status = xcalloc(ref.nr, sizeof(*status));
+       status = xcalloc(nr_sought, sizeof(*status));
        assign_shallow_commits_to_refs(si, NULL, status);
        if (si->nr_ours || si->nr_theirs) {
-               for (r = refs, i = 0; r; r = r->next, i++)
+               for (i = 0; i < nr_sought; i++)
                        if (status[i])
-                               r->status = REF_STATUS_REJECT_SHALLOW;
+                               sought[i]->status = REF_STATUS_REJECT_SHALLOW;
        }
        free(status);
        oid_array_clear(&ref);
@@ -1596,7 +1627,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
                args->connectivity_checked = 1;
        }
 
-       update_shallow(args, ref_cpy, &si);
+       update_shallow(args, sought, nr_sought, &si);
 cleanup:
        clear_shallow_info(&si);
        return ref_cpy;