OSDN Git Service

fetch: define shallow boundary with --shallow-exclude
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sun, 12 Jun 2016 10:54:04 +0000 (17:54 +0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 13 Jun 2016 21:38:16 +0000 (14:38 -0700)
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/fetch-options.txt
Documentation/git-fetch-pack.txt
Documentation/gitremote-helpers.txt
builtin/fetch-pack.c
builtin/fetch.c
fetch-pack.c
fetch-pack.h
remote-curl.c
transport-helper.c
transport.c
transport.h

index 8738d3d..7aa1285 100644 (file)
        Deepen or shorten the history of a shallow repository to
        include all reachable commits after <date>.
 
+--shallow-exclude=<revision>::
+       Deepen or shorten the history of a shallow repository to
+       exclude commits reachable from a specified remote branch or tag.
+       This option can be specified multiple times.
+
 --unshallow::
        If the source repository is complete, convert a shallow
        repository to a complete one, removing all the limitations
index 99e6257..4d15b04 100644 (file)
@@ -91,6 +91,11 @@ be in a separate packet, and the list must end with a flush packet.
        Deepen or shorten the history of a shallow'repository to
        include all reachable commits after <date>.
 
+--shallow-exclude=<revision>::
+       Deepen or shorten the history of a shallow repository to
+       exclude commits reachable from a specified remote branch or tag.
+       This option can be specified multiple times.
+
 --no-progress::
        Do not show the progress.
 
index 9971d9a..75bb638 100644 (file)
@@ -418,6 +418,10 @@ set by Git if the remote helper has the 'option' capability.
 'option deepen-since <timestamp>::
        Deepens the history of a shallow repository based on time.
 
+'option deepen-not <ref>::
+       Deepens the history of a shallow repository excluding ref.
+       Multiple options add up.
+
 'option followtags' {'true'|'false'}::
        If enabled the helper should automatically fetch annotated
        tag objects if the object the tag points at was transferred
index 0402e27..07570be 100644 (file)
@@ -50,6 +50,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        struct child_process *conn;
        struct fetch_pack_args args;
        struct sha1_array shallow = SHA1_ARRAY_INIT;
+       struct string_list deepen_not = STRING_LIST_INIT_DUP;
 
        packet_trace_identity("fetch-pack");
 
@@ -108,6 +109,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
                        args.deepen_since = xstrdup(arg);
                        continue;
                }
+               if (skip_prefix(arg, "--shallow-exclude=", &arg)) {
+                       string_list_append(&deepen_not, arg);
+                       continue;
+               }
                if (!strcmp("--no-progress", arg)) {
                        args.no_progress = 1;
                        continue;
@@ -135,6 +140,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
                }
                usage(fetch_pack_usage);
        }
+       if (deepen_not.nr)
+               args.deepen_not = &deepen_not;
 
        if (i < argc)
                dest = argv[i++];
index 283aa95..147504d 100644 (file)
@@ -41,6 +41,7 @@ static int max_children = 1;
 static const char *depth;
 static const char *deepen_since;
 static const char *upload_pack;
+static struct string_list deepen_not = STRING_LIST_INIT_NODUP;
 static struct strbuf default_rla = STRBUF_INIT;
 static struct transport *gtransport;
 static struct transport *gsecondary;
@@ -118,6 +119,8 @@ static struct option builtin_fetch_options[] = {
                   N_("deepen history of shallow clone")),
        OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
                   N_("deepen history of shallow repository based on time")),
+       OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"),
+                       N_("deepen history of shallow clone by excluding rev")),
        { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL,
                   N_("convert to a complete repository"),
                   PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },
@@ -875,6 +878,9 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
                set_option(transport, TRANS_OPT_DEPTH, depth);
        if (deepen && deepen_since)
                set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since);
+       if (deepen && deepen_not.nr)
+               set_option(transport, TRANS_OPT_DEEPEN_NOT,
+                          (const char *)&deepen_not);
        if (update_shallow)
                set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
        return transport;
@@ -889,9 +895,10 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
         * when remote helper is used (setting it to an empty string
         * is not unsetting). We could extend the remote helper
         * protocol for that, but for now, just force a new connection
-        * without deepen-since.
+        * without deepen-since. Similar story for deepen-not.
         */
-       cannot_reuse = transport->cannot_reuse || deepen_since;
+       cannot_reuse = transport->cannot_reuse ||
+               deepen_since || deepen_not.nr;
        if (cannot_reuse) {
                gsecondary = prepare_transport(transport->remote, 0);
                transport = gsecondary;
@@ -1182,7 +1189,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        /* no need to be strict, transport_set_option() will validate it again */
        if (depth && atoi(depth) < 1)
                die(_("depth %s is not a positive number"), depth);
-       if (depth || deepen_since)
+       if (depth || deepen_since || deepen_not.nr)
                deepen = 1;
 
        if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
index a2f25c1..ad7d00f 100644 (file)
@@ -22,6 +22,7 @@ static int unpack_limit = 100;
 static int prefer_ofs_delta = 1;
 static int no_done;
 static int deepen_since_ok;
+static int deepen_not_ok;
 static int fetch_fsck_objects = -1;
 static int transfer_fsck_objects = -1;
 static int agent_supported;
@@ -328,6 +329,7 @@ static int find_common(struct fetch_pack_args *args,
                        if (args->include_tag)   strbuf_addstr(&c, " include-tag");
                        if (prefer_ofs_delta)   strbuf_addstr(&c, " ofs-delta");
                        if (deepen_since_ok)    strbuf_addstr(&c, " deepen-since");
+                       if (deepen_not_ok)      strbuf_addstr(&c, " deepen-not");
                        if (agent_supported)    strbuf_addf(&c, " agent=%s",
                                                            git_user_agent_sanitized());
                        packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
@@ -351,6 +353,13 @@ static int find_common(struct fetch_pack_args *args,
                unsigned long max_age = approxidate(args->deepen_since);
                packet_buf_write(&req_buf, "deepen-since %lu", max_age);
        }
+       if (args->deepen_not) {
+               int i;
+               for (i = 0; i < args->deepen_not->nr; i++) {
+                       struct string_list_item *s = args->deepen_not->items + i;
+                       packet_buf_write(&req_buf, "deepen-not %s", s->string);
+               }
+       }
        packet_buf_flush(&req_buf);
        state_len = req_buf.len;
 
@@ -818,7 +827,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 
        if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow"))
                die(_("Server does not support shallow clients"));
-       if (args->depth > 0 || args->deepen_since)
+       if (args->depth > 0 || args->deepen_since || args->deepen_not)
                args->deepen = 1;
        if (server_supports("multi_ack_detailed")) {
                print_verbose(args, _("Server supports multi_ack_detailed"));
@@ -870,6 +879,10 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                deepen_since_ok = 1;
        else if (args->deepen_since)
                die(_("Server does not support --shallow-since"));
+       if (server_supports("deepen-not"))
+               deepen_not_ok = 1;
+       else if (args->deepen_not)
+               die(_("Server does not support --shallow-exclude"));
 
        if (everything_local(args, &ref, sought, nr_sought)) {
                packet_flush(fd[1]);
index f7eadb2..144301f 100644 (file)
@@ -11,6 +11,7 @@ struct fetch_pack_args {
        int unpacklimit;
        int depth;
        const char *deepen_since;
+       const struct string_list *deepen_not;
        unsigned quiet:1;
        unsigned keep_pack:1;
        unsigned lock_pack:1;
index 5876f24..1406e6a 100644 (file)
@@ -21,6 +21,7 @@ struct options {
        int verbosity;
        unsigned long depth;
        char *deepen_since;
+       struct string_list deepen_not;
        unsigned progress : 1,
                check_self_contained_and_connected : 1,
                cloning : 1,
@@ -65,6 +66,10 @@ static int set_option(const char *name, const char *value)
                options.deepen_since = xstrdup(value);
                return 0;
        }
+       else if (!strcmp(name, "deepen-not")) {
+               string_list_append(&options.deepen_not, value);
+               return 0;
+       }
        else if (!strcmp(name, "followtags")) {
                if (!strcmp(value, "true"))
                        options.followtags = 1;
@@ -753,6 +758,9 @@ static int fetch_git(struct discovery *heads,
                argv_array_pushf(&args, "--depth=%lu", options.depth);
        if (options.deepen_since)
                argv_array_pushf(&args, "--shallow-since=%s", options.deepen_since);
+       for (i = 0; i < options.deepen_not.nr; i++)
+               argv_array_pushf(&args, "--shallow-exclude=%s",
+                                options.deepen_not.items[i].string);
        argv_array_push(&args, url.buf);
 
        for (i = 0; i < nr_heads; i++) {
@@ -973,6 +981,7 @@ int main(int argc, const char **argv)
        options.verbosity = 1;
        options.progress = !!isatty(2);
        options.thin = 1;
+       string_list_init(&options.deepen_not, 1);
 
        remote = remote_get(argv[1]);
 
index 27a34e9..cc1a396 100644 (file)
@@ -282,6 +282,26 @@ static int strbuf_set_helper_option(struct helper_data *data,
        return ret;
 }
 
+static int string_list_set_helper_option(struct helper_data *data,
+                                        const char *name,
+                                        struct string_list *list)
+{
+       struct strbuf buf = STRBUF_INIT;
+       int i, ret = 0;
+
+       for (i = 0; i < list->nr; i++) {
+               strbuf_addf(&buf, "option %s ", name);
+               quote_c_style(list->items[i].string, &buf, NULL, 0);
+               strbuf_addch(&buf, '\n');
+
+               if ((ret = strbuf_set_helper_option(data, &buf)))
+                       break;
+               strbuf_reset(&buf);
+       }
+       strbuf_release(&buf);
+       return ret;
+}
+
 static int set_helper_option(struct transport *transport,
                          const char *name, const char *value)
 {
@@ -294,6 +314,10 @@ static int set_helper_option(struct transport *transport,
        if (!data->option)
                return 1;
 
+       if (!strcmp(name, "deepen-not"))
+               return string_list_set_helper_option(data, name,
+                                                    (struct string_list *)value);
+
        for (i = 0; i < ARRAY_SIZE(unsupported_options); i++) {
                if (!strcmp(name, unsupported_options[i]))
                        return 1;
index f04a302..3e6f3aa 100644 (file)
@@ -154,6 +154,9 @@ static int set_git_option(struct git_transport_options *opts,
        } else if (!strcmp(name, TRANS_OPT_DEEPEN_SINCE)) {
                opts->deepen_since = value;
                return 0;
+       } else if (!strcmp(name, TRANS_OPT_DEEPEN_NOT)) {
+               opts->deepen_not = (const struct string_list *)value;
+               return 0;
        }
        return 1;
 }
@@ -209,6 +212,7 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.no_progress = !transport->progress;
        args.depth = data->options.depth;
        args.deepen_since = data->options.deepen_since;
+       args.deepen_not = data->options.deepen_not;
        args.check_self_contained_and_connected =
                data->options.check_self_contained_and_connected;
        args.cloning = transport->cloning;
index 9c10a44..ab61932 100644 (file)
@@ -5,6 +5,8 @@
 #include "run-command.h"
 #include "remote.h"
 
+struct string_list;
+
 struct git_transport_options {
        unsigned thin : 1;
        unsigned keep : 1;
@@ -14,6 +16,7 @@ struct git_transport_options {
        unsigned update_shallow : 1;
        int depth;
        const char *deepen_since;
+       const struct string_list *deepen_not;
        const char *uploadpack;
        const char *receivepack;
        struct push_cas_option *cas;
@@ -175,6 +178,9 @@ int transport_restrict_protocols(void);
 /* Limit the depth of the fetch based on time if not null */
 #define TRANS_OPT_DEEPEN_SINCE "deepen-since"
 
+/* Limit the depth of the fetch based on revs if not null */
+#define TRANS_OPT_DEEPEN_NOT "deepen-not"
+
 /* Aggressively fetch annotated tags if possible */
 #define TRANS_OPT_FOLLOWTAGS "followtags"