Merge branch 'jh/partial-clone'
[gitweb.git] / fetch-pack.c
index 9f6b07ad91f8c2c17e85004a0e71a8b69752d120..8253d746e0c40492e05360fe6f27bfa85bb39fbc 100644 (file)
@@ -29,6 +29,7 @@ static int deepen_not_ok;
 static int fetch_fsck_objects = -1;
 static int transfer_fsck_objects = -1;
 static int agent_supported;
+static int server_supports_filtering;
 static struct lock_file shallow_lock;
 static const char *alternate_shallow_file;
 
@@ -379,6 +380,8 @@ static int find_common(struct fetch_pack_args *args,
                        if (deepen_not_ok)      strbuf_addstr(&c, " deepen-not");
                        if (agent_supported)    strbuf_addf(&c, " agent=%s",
                                                            git_user_agent_sanitized());
+                       if (args->filter_options.choice)
+                               strbuf_addstr(&c, " filter");
                        packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
                        strbuf_release(&c);
                } else
@@ -407,6 +410,9 @@ static int find_common(struct fetch_pack_args *args,
                        packet_buf_write(&req_buf, "deepen-not %s", s->string);
                }
        }
+       if (server_supports_filtering && args->filter_options.choice)
+               packet_buf_write(&req_buf, "filter %s",
+                                args->filter_options.filter_spec);
        packet_buf_flush(&req_buf);
        state_len = req_buf.len;
 
@@ -450,6 +456,8 @@ static int find_common(struct fetch_pack_args *args,
 
        flushes = 0;
        retval = -1;
+       if (args->no_dependents)
+               goto done;
        while ((oid = get_rev())) {
                packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid));
                print_verbose(args, "have %s", oid_to_hex(oid));
@@ -709,6 +717,7 @@ static int everything_local(struct fetch_pack_args *args,
 {
        struct ref *ref;
        int retval;
+       int old_save_commit_buffer = save_commit_buffer;
        timestamp_t cutoff = 0;
 
        save_commit_buffer = 0;
@@ -735,29 +744,31 @@ static int everything_local(struct fetch_pack_args *args,
                }
        }
 
-       if (!args->deepen) {
-               for_each_ref(mark_complete_oid, NULL);
-               for_each_cached_alternate(mark_alternate_complete);
-               commit_list_sort_by_date(&complete);
-               if (cutoff)
-                       mark_recent_complete_commits(args, cutoff);
-       }
+       if (!args->no_dependents) {
+               if (!args->deepen) {
+                       for_each_ref(mark_complete_oid, NULL);
+                       for_each_cached_alternate(mark_alternate_complete);
+                       commit_list_sort_by_date(&complete);
+                       if (cutoff)
+                               mark_recent_complete_commits(args, cutoff);
+               }
 
-       /*
-        * Mark all complete remote refs as common refs.
-        * Don't mark them common yet; the server has to be told so first.
-        */
-       for (ref = *refs; ref; ref = ref->next) {
-               struct object *o = deref_tag(lookup_object(ref->old_oid.hash),
-                                            NULL, 0);
+               /*
+                * Mark all complete remote refs as common refs.
+                * Don't mark them common yet; the server has to be told so first.
+                */
+               for (ref = *refs; ref; ref = ref->next) {
+                       struct object *o = deref_tag(lookup_object(ref->old_oid.hash),
+                                                    NULL, 0);
 
-               if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
-                       continue;
+                       if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
+                               continue;
 
-               if (!(o->flags & SEEN)) {
-                       rev_list_push((struct commit *)o, COMMON_REF | SEEN);
+                       if (!(o->flags & SEEN)) {
+                               rev_list_push((struct commit *)o, COMMON_REF | SEEN);
 
-                       mark_common((struct commit *)o, 1, 1);
+                               mark_common((struct commit *)o, 1, 1);
+                       }
                }
        }
 
@@ -777,6 +788,9 @@ static int everything_local(struct fetch_pack_args *args,
                print_verbose(args, _("already have %s (%s)"), oid_to_hex(remote),
                              ref->name);
        }
+
+       save_commit_buffer = old_save_commit_buffer;
+
        return retval;
 }
 
@@ -833,7 +847,7 @@ static int get_pack(struct fetch_pack_args *args,
                argv_array_push(&cmd.args, alternate_shallow_file);
        }
 
-       if (do_keep) {
+       if (do_keep || args->from_promisor) {
                if (pack_lockfile)
                        cmd.out = -1;
                cmd_name = "index-pack";
@@ -843,7 +857,7 @@ static int get_pack(struct fetch_pack_args *args,
                        argv_array_push(&cmd.args, "-v");
                if (args->use_thin_pack)
                        argv_array_push(&cmd.args, "--fix-thin");
-               if (args->lock_pack || unpack_limit) {
+               if (do_keep && (args->lock_pack || unpack_limit)) {
                        char hostname[HOST_NAME_MAX + 1];
                        if (xgethostname(hostname, sizeof(hostname)))
                                xsnprintf(hostname, sizeof(hostname), "localhost");
@@ -853,6 +867,8 @@ static int get_pack(struct fetch_pack_args *args,
                }
                if (args->check_self_contained_and_connected)
                        argv_array_push(&cmd.args, "--check-self-contained-and-connected");
+               if (args->from_promisor)
+                       argv_array_push(&cmd.args, "--promisor");
        }
        else {
                cmd_name = "unpack-objects";
@@ -964,6 +980,13 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        else
                prefer_ofs_delta = 0;
 
+       if (server_supports("filter")) {
+               server_supports_filtering = 1;
+               print_verbose(args, _("Server supports filter"));
+       } else if (args->filter_options.choice) {
+               warning("filtering not recognized by server, ignoring");
+       }
+
        if ((agent_feature = server_feature_value("agent", &agent_len))) {
                agent_supported = 1;
                if (agent_len)