From 0d789a5bc1aeef2d6d0d3120efc4b85766a0a327 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 12 Jun 2016 17:53:54 +0700 Subject: fetch-pack: use a common function for verbose printing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces the number of "if (verbose)" which makes it a bit easier to read imo. It also makes it easier to redirect all these printouts, to a file for example. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- fetch-pack.c | 88 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 42 insertions(+), 46 deletions(-) (limited to 'fetch-pack.c') diff --git a/fetch-pack.c b/fetch-pack.c index 01e34b689b..4020744a1d 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -50,6 +50,21 @@ static int non_common_revs, multi_ack, use_sideband; #define ALLOW_REACHABLE_SHA1 02 static unsigned int allow_unadvertised_object_request; +__attribute__((format (printf, 2, 3))) +static inline void print_verbose(const struct fetch_pack_args *args, + const char *fmt, ...) +{ + va_list params; + + if (!args->verbose) + return; + + va_start(params, fmt); + vfprintf(stderr, fmt, params); + va_end(params); + fputc('\n', stderr); +} + static void rev_list_push(struct commit *commit, int mark) { if (!(commit->object.flags & mark)) { @@ -375,8 +390,7 @@ static int find_common(struct fetch_pack_args *args, retval = -1; while ((sha1 = get_rev())) { packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1)); - if (args->verbose) - fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); + print_verbose(args, "have %s", sha1_to_hex(sha1)); in_vain++; if (flush_at <= ++count) { int ack; @@ -397,9 +411,9 @@ static int find_common(struct fetch_pack_args *args, consume_shallow_list(args, fd[0]); do { ack = get_ack(fd[0], result_sha1); - if (args->verbose && ack) - fprintf(stderr, "got ack %d %s\n", ack, - sha1_to_hex(result_sha1)); + if (ack) + print_verbose(args, "got ack %d %s", ack, + sha1_to_hex(result_sha1)); switch (ack) { case ACK: flushes = 0; @@ -438,8 +452,7 @@ static int find_common(struct fetch_pack_args *args, } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { - if (args->verbose) - fprintf(stderr, "giving up\n"); + print_verbose(args, "giving up"); break; /* give up */ } } @@ -449,8 +462,7 @@ static int find_common(struct fetch_pack_args *args, packet_buf_write(&req_buf, "done\n"); send_request(args, fd[1], &req_buf); } - if (args->verbose) - fprintf(stderr, "done\n"); + print_verbose(args, "done"); if (retval != 0) { multi_ack = 0; flushes++; @@ -462,9 +474,8 @@ static int find_common(struct fetch_pack_args *args, while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { - if (args->verbose) - fprintf(stderr, "got ack (%d) %s\n", ack, - sha1_to_hex(result_sha1)); + print_verbose(args, "got ack (%d) %s", ack, + sha1_to_hex(result_sha1)); if (ack == ACK) return 0; multi_ack = 1; @@ -509,9 +520,8 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args, unsigned long cutoff) { while (complete && cutoff <= complete->item->date) { - if (args->verbose) - fprintf(stderr, "Marking %s as complete\n", - oid_to_hex(&complete->item->object.oid)); + print_verbose(args, "Marking %s as complete", + oid_to_hex(&complete->item->object.oid)); pop_most_recent_commit(&complete, COMPLETE); } } @@ -652,18 +662,12 @@ static int everything_local(struct fetch_pack_args *args, o = lookup_object(remote); if (!o || !(o->flags & COMPLETE)) { retval = 0; - if (!args->verbose) - continue; - fprintf(stderr, - "want %s (%s)\n", sha1_to_hex(remote), - ref->name); + print_verbose(args, "want %s (%s)", sha1_to_hex(remote), + ref->name); continue; } - if (!args->verbose) - continue; - fprintf(stderr, - "already have %s (%s)\n", sha1_to_hex(remote), - ref->name); + print_verbose(args, "already have %s (%s)", sha1_to_hex(remote), + ref->name); } return retval; } @@ -810,39 +814,32 @@ 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 (server_supports("multi_ack_detailed")) { - if (args->verbose) - fprintf(stderr, "Server supports multi_ack_detailed\n"); + print_verbose(args, "Server supports multi_ack_detailed"); multi_ack = 2; if (server_supports("no-done")) { - if (args->verbose) - fprintf(stderr, "Server supports no-done\n"); + print_verbose(args, "Server supports no-done"); if (args->stateless_rpc) no_done = 1; } } else if (server_supports("multi_ack")) { - if (args->verbose) - fprintf(stderr, "Server supports multi_ack\n"); + print_verbose(args, "Server supports multi_ack"); multi_ack = 1; } if (server_supports("side-band-64k")) { - if (args->verbose) - fprintf(stderr, "Server supports side-band-64k\n"); + print_verbose(args, "Server supports side-band-64k"); use_sideband = 2; } else if (server_supports("side-band")) { - if (args->verbose) - fprintf(stderr, "Server supports side-band\n"); + print_verbose(args, "Server supports side-band"); use_sideband = 1; } if (server_supports("allow-tip-sha1-in-want")) { - if (args->verbose) - fprintf(stderr, "Server supports allow-tip-sha1-in-want\n"); + print_verbose(args, "Server supports allow-tip-sha1-in-want"); allow_unadvertised_object_request |= ALLOW_TIP_SHA1; } if (server_supports("allow-reachable-sha1-in-want")) { - if (args->verbose) - fprintf(stderr, "Server supports allow-reachable-sha1-in-want\n"); + print_verbose(args, "Server supports allow-reachable-sha1-in-want"); allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; } if (!server_supports("thin-pack")) @@ -851,17 +848,16 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, args->no_progress = 0; if (!server_supports("include-tag")) args->include_tag = 0; - if (server_supports("ofs-delta")) { - if (args->verbose) - fprintf(stderr, "Server supports ofs-delta\n"); - } else + if (server_supports("ofs-delta")) + print_verbose(args, "Server supports ofs-delta"); + else prefer_ofs_delta = 0; if ((agent_feature = server_feature_value("agent", &agent_len))) { agent_supported = 1; - if (args->verbose && agent_len) - fprintf(stderr, "Server version is %.*s\n", - agent_len, agent_feature); + if (agent_len) + print_verbose(args, "Server version is %.*s", + agent_len, agent_feature); } if (everything_local(args, &ref, sought, nr_sought)) { -- cgit 1.2.3-korg From 1dd73e20d72921fe81a881a9f6cff6d02eca8146 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 12 Jun 2016 17:53:55 +0700 Subject: fetch-pack.c: mark strings for translating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- fetch-pack.c | 75 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 38 deletions(-) (limited to 'fetch-pack.c') diff --git a/fetch-pack.c b/fetch-pack.c index 4020744a1d..08caf1dc91 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -208,7 +208,7 @@ static void consume_shallow_list(struct fetch_pack_args *args, int fd) continue; if (starts_with(line, "unshallow ")) continue; - die("git fetch-pack: expected shallow list"); + die(_("git fetch-pack: expected shallow list")); } } } @@ -220,7 +220,7 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1) const char *arg; if (!len) - die("git fetch-pack: expected ACK/NAK, got EOF"); + die(_("git fetch-pack: expected ACK/NAK, got EOF")); if (!strcmp(line, "NAK")) return NAK; if (skip_prefix(line, "ACK ", &arg)) { @@ -238,7 +238,7 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1) return ACK; } } - die("git fetch_pack: expected ACK/NAK, got '%s'", line); + die(_("git fetch_pack: expected ACK/NAK, got '%s'"), line); } static void send_request(struct fetch_pack_args *args, @@ -285,7 +285,7 @@ static int find_common(struct fetch_pack_args *args, size_t state_len = 0; if (args->stateless_rpc && multi_ack == 1) - die("--stateless-rpc requires multi_ack_detailed"); + die(_("--stateless-rpc requires multi_ack_detailed")); if (marked) for_each_ref(clear_marks, NULL); marked = 1; @@ -357,23 +357,23 @@ static int find_common(struct fetch_pack_args *args, while ((line = packet_read_line(fd[0], NULL))) { if (skip_prefix(line, "shallow ", &arg)) { if (get_sha1_hex(arg, sha1)) - die("invalid shallow line: %s", line); + die(_("invalid shallow line: %s"), line); register_shallow(sha1); continue; } if (skip_prefix(line, "unshallow ", &arg)) { if (get_sha1_hex(arg, sha1)) - die("invalid unshallow line: %s", line); + die(_("invalid unshallow line: %s"), line); if (!lookup_object(sha1)) - die("object not found: %s", line); + die(_("object not found: %s"), line); /* make sure that it is parsed as shallow */ if (!parse_object(sha1)) - die("error in object: %s", line); + die(_("error in object: %s"), line); if (unregister_shallow(sha1)) - die("no shallow found: %s", line); + die(_("no shallow found: %s"), line); continue; } - die("expected shallow/unshallow, got %s", line); + die(_("expected shallow/unshallow, got %s"), line); } } else if (!args->stateless_rpc) send_request(args, fd[1], &req_buf); @@ -412,8 +412,8 @@ static int find_common(struct fetch_pack_args *args, do { ack = get_ack(fd[0], result_sha1); if (ack) - print_verbose(args, "got ack %d %s", ack, - sha1_to_hex(result_sha1)); + print_verbose(args, _("got %s %d %s"), "ack", + ack, sha1_to_hex(result_sha1)); switch (ack) { case ACK: flushes = 0; @@ -426,7 +426,7 @@ static int find_common(struct fetch_pack_args *args, struct commit *commit = lookup_commit(result_sha1); if (!commit) - die("invalid commit %s", sha1_to_hex(result_sha1)); + die(_("invalid commit %s"), sha1_to_hex(result_sha1)); if (args->stateless_rpc && ack == ACK_common && !(commit->object.flags & COMMON)) { @@ -452,7 +452,7 @@ static int find_common(struct fetch_pack_args *args, } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { - print_verbose(args, "giving up"); + print_verbose(args, _("giving up")); break; /* give up */ } } @@ -462,7 +462,7 @@ static int find_common(struct fetch_pack_args *args, packet_buf_write(&req_buf, "done\n"); send_request(args, fd[1], &req_buf); } - print_verbose(args, "done"); + print_verbose(args, _("done")); if (retval != 0) { multi_ack = 0; flushes++; @@ -474,8 +474,8 @@ static int find_common(struct fetch_pack_args *args, while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { - print_verbose(args, "got ack (%d) %s", ack, - sha1_to_hex(result_sha1)); + print_verbose(args, _("got %s (%d) %s"), "ack", + ack, sha1_to_hex(result_sha1)); if (ack == ACK) return 0; multi_ack = 1; @@ -520,7 +520,7 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args, unsigned long cutoff) { while (complete && cutoff <= complete->item->date) { - print_verbose(args, "Marking %s as complete", + print_verbose(args, _("Marking %s as complete"), oid_to_hex(&complete->item->object.oid)); pop_most_recent_commit(&complete, COMPLETE); } @@ -666,7 +666,7 @@ static int everything_local(struct fetch_pack_args *args, ref->name); continue; } - print_verbose(args, "already have %s (%s)", sha1_to_hex(remote), + print_verbose(args, _("already have %s (%s)"), sha1_to_hex(remote), ref->name); } return retval; @@ -702,8 +702,7 @@ static int get_pack(struct fetch_pack_args *args, demux.data = xd; demux.out = -1; if (start_async(&demux)) - die("fetch-pack: unable to fork off sideband" - " demultiplexer"); + die(_("fetch-pack: unable to fork off sideband demultiplexer")); } else demux.out = xd[0]; @@ -711,7 +710,7 @@ static int get_pack(struct fetch_pack_args *args, if (!args->keep_pack && unpack_limit) { if (read_pack_header(demux.out, &header)) - die("protocol error: bad pack header"); + die(_("protocol error: bad pack header")); pass_header = 1; if (ntohl(header.hdr_entries) < unpack_limit) do_keep = 0; @@ -767,7 +766,7 @@ static int get_pack(struct fetch_pack_args *args, cmd.in = demux.out; cmd.git_cmd = 1; if (start_command(&cmd)) - die("fetch-pack: unable to fork off %s", cmd_name); + die(_("fetch-pack: unable to fork off %s"), cmd_name); if (do_keep && pack_lockfile) { *pack_lockfile = index_pack_lockfile(cmd.out); close(cmd.out); @@ -783,9 +782,9 @@ static int get_pack(struct fetch_pack_args *args, args->check_self_contained_and_connected && ret == 0; else - die("%s failed", cmd_name); + die(_("%s failed"), cmd_name); if (use_sideband && finish_async(&demux)) - die("error in sideband demultiplexer"); + die(_("error in sideband demultiplexer")); return 0; } @@ -812,34 +811,34 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name); if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow")) - die("Server does not support shallow clients"); + die(_("Server does not support shallow clients")); if (server_supports("multi_ack_detailed")) { - print_verbose(args, "Server supports multi_ack_detailed"); + print_verbose(args, _("Server supports multi_ack_detailed")); multi_ack = 2; if (server_supports("no-done")) { - print_verbose(args, "Server supports no-done"); + print_verbose(args, _("Server supports no-done")); if (args->stateless_rpc) no_done = 1; } } else if (server_supports("multi_ack")) { - print_verbose(args, "Server supports multi_ack"); + print_verbose(args, _("Server supports multi_ack")); multi_ack = 1; } if (server_supports("side-band-64k")) { - print_verbose(args, "Server supports side-band-64k"); + print_verbose(args, _("Server supports side-band-64k")); use_sideband = 2; } else if (server_supports("side-band")) { - print_verbose(args, "Server supports side-band"); + print_verbose(args, _("Server supports side-band")); use_sideband = 1; } if (server_supports("allow-tip-sha1-in-want")) { - print_verbose(args, "Server supports allow-tip-sha1-in-want"); + print_verbose(args, _("Server supports allow-tip-sha1-in-want")); allow_unadvertised_object_request |= ALLOW_TIP_SHA1; } if (server_supports("allow-reachable-sha1-in-want")) { - print_verbose(args, "Server supports allow-reachable-sha1-in-want"); + print_verbose(args, _("Server supports allow-reachable-sha1-in-want")); allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; } if (!server_supports("thin-pack")) @@ -849,14 +848,14 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, if (!server_supports("include-tag")) args->include_tag = 0; if (server_supports("ofs-delta")) - print_verbose(args, "Server supports ofs-delta"); + print_verbose(args, _("Server supports ofs-delta")); else prefer_ofs_delta = 0; if ((agent_feature = server_feature_value("agent", &agent_len))) { agent_supported = 1; if (agent_len) - print_verbose(args, "Server version is %.*s", + print_verbose(args, _("Server version is %.*s"), agent_len, agent_feature); } @@ -869,7 +868,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, /* When cloning, it is not unusual to have * no common commit. */ - warning("no common commits"); + warning(_("no common commits")); if (args->stateless_rpc) packet_flush(fd[1]); @@ -881,7 +880,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, else alternate_shallow_file = NULL; if (get_pack(args, fd, pack_lockfile)) - die("git fetch-pack: fetch failed."); + die(_("git fetch-pack: fetch failed.")); all_done: return ref; @@ -1043,7 +1042,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args, if (!ref) { packet_flush(fd[1]); - die("no matching remote head"); + die(_("no matching remote head")); } prepare_shallow_info(&si, shallow); ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, -- cgit 1.2.3-korg From 79891cb90a4e5b2680308ba2b757a218b9aaa14c Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 12 Jun 2016 17:53:56 +0700 Subject: fetch-pack: use a separate flag for fetch in deepening mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shallow repo could be deepened or shortened when then user gives --depth. But in future that won't be the only way to deepen/shorten a repo. Stop relying on args->depth in this mode. Future deepening methods can simply set this flag on instead of updating all these if expressions. The new name "deepen" was chosen after the command to define shallow boundary in pack protocol. New commands also follow this tradition. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- fetch-pack.c | 14 ++++++++------ fetch-pack.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'fetch-pack.c') diff --git a/fetch-pack.c b/fetch-pack.c index 08caf1dc91..a14d24a52f 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -197,7 +197,7 @@ enum ack_type { static void consume_shallow_list(struct fetch_pack_args *args, int fd) { - if (args->stateless_rpc && args->depth > 0) { + if (args->stateless_rpc && args->deepen) { /* If we sent a depth we will get back "duplicate" * shallow and unshallow commands every time there * is a block of have lines exchanged. @@ -348,7 +348,7 @@ static int find_common(struct fetch_pack_args *args, packet_buf_flush(&req_buf); state_len = req_buf.len; - if (args->depth > 0) { + if (args->deepen) { char *line; const char *arg; unsigned char sha1[20]; @@ -557,7 +557,7 @@ static void filter_refs(struct fetch_pack_args *args, } if (!keep && args->fetch_all && - (!args->depth || !starts_with(ref->name, "refs/tags/"))) + (!args->deepen || !starts_with(ref->name, "refs/tags/"))) keep = 1; if (keep) { @@ -627,7 +627,7 @@ static int everything_local(struct fetch_pack_args *args, } } - if (!args->depth) { + if (!args->deepen) { for_each_ref(mark_complete_oid, NULL); for_each_alternate_ref(mark_alternate_complete, NULL); commit_list_sort_by_date(&complete); @@ -812,6 +812,8 @@ 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 = 1; if (server_supports("multi_ack_detailed")) { print_verbose(args, _("Server supports multi_ack_detailed")); multi_ack = 2; @@ -872,7 +874,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, if (args->stateless_rpc) packet_flush(fd[1]); - if (args->depth > 0) + if (args->deepen) setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, NULL); else if (si->nr_ours || si->nr_theirs) @@ -939,7 +941,7 @@ static void update_shallow(struct fetch_pack_args *args, int *status; int i; - if (args->depth > 0 && alternate_shallow_file) { + if (args->deepen && alternate_shallow_file) { if (*alternate_shallow_file == '\0') { /* --unshallow */ unlink_or_warn(git_path_shallow()); rollback_lock_file(&shallow_lock); diff --git a/fetch-pack.h b/fetch-pack.h index bb7fd76e59..4d0adb0b97 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -25,6 +25,7 @@ struct fetch_pack_args { unsigned self_contained_and_connected:1; unsigned cloning:1; unsigned update_shallow:1; + unsigned deepen:1; }; /* -- cgit 1.2.3-korg From 508ea88226bbdd25ac0aac4f9c8a65a2c3b5be5c Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 12 Jun 2016 17:53:59 +0700 Subject: fetch: define shallow boundary with --shallow-since MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- Documentation/fetch-options.txt | 4 ++++ Documentation/git-fetch-pack.txt | 4 ++++ Documentation/gitremote-helpers.txt | 3 +++ builtin/fetch-pack.c | 4 ++++ builtin/fetch.c | 29 +++++++++++++++++++++++------ fetch-pack.c | 12 +++++++++++- fetch-pack.h | 1 + remote-curl.c | 11 +++++++++-- transport.c | 4 ++++ transport.h | 4 ++++ 10 files changed, 67 insertions(+), 9 deletions(-) (limited to 'fetch-pack.c') diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 952dfdfef0..8738d3dc36 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -14,6 +14,10 @@ linkgit:git-clone[1]), deepen or shorten the history to the specified number of commits. Tags for the deepened commits are not fetched. +--shallow-since=:: + Deepen or shorten the history of a shallow repository to + include all reachable commits after . + --unshallow:: If the source repository is complete, convert a shallow repository to a complete one, removing all the limitations diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 8680f45f8d..99e6257475 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -87,6 +87,10 @@ be in a separate packet, and the list must end with a flush packet. 'git-upload-pack' treats the special depth 2147483647 as infinite even if there is an ancestor-chain that long. +--shallow-since=:: + Deepen or shorten the history of a shallow'repository to + include all reachable commits after . + --no-progress:: Do not show the progress. diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index 78e0b27c18..9971d9a2b6 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -415,6 +415,9 @@ set by Git if the remote helper has the 'option' capability. 'option depth' :: Deepens the history of a shallow repository. +'option deepen-since :: + Deepens the history of a shallow repository based on time. + 'option followtags' {'true'|'false'}:: If enabled the helper should automatically fetch annotated tag objects if the object the tag points at was transferred diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 8332d3d520..0402e2756b 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -104,6 +104,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) args.depth = strtol(arg, NULL, 0); continue; } + if (skip_prefix(arg, "--shallow-since=", &arg)) { + args.deepen_since = xstrdup(arg); + continue; + } if (!strcmp("--no-progress", arg)) { args.no_progress = 1; continue; diff --git a/builtin/fetch.c b/builtin/fetch.c index 8e742135f0..283aa95aec 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -36,9 +36,10 @@ static int prune = -1; /* unspecified */ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity; static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; -static int tags = TAGS_DEFAULT, unshallow, update_shallow; +static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen; static int max_children = 1; static const char *depth; +static const char *deepen_since; static const char *upload_pack; static struct strbuf default_rla = STRBUF_INIT; static struct transport *gtransport; @@ -115,6 +116,8 @@ static struct option builtin_fetch_options[] = { OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_STRING(0, "depth", &depth, N_("depth"), N_("deepen history of shallow clone")), + OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), + N_("deepen history of shallow repository based on time")), { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL, N_("convert to a complete repository"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 }, @@ -754,7 +757,7 @@ static int quickfetch(struct ref *ref_map) * really need to perform. Claiming failure now will ensure * we perform the network exchange to deepen our history. */ - if (depth) + if (deepen) return -1; return check_everything_connected(iterate_ref_map, 1, &rm); } @@ -859,7 +862,7 @@ static void set_option(struct transport *transport, const char *name, const char name, transport->url); } -static struct transport *prepare_transport(struct remote *remote) +static struct transport *prepare_transport(struct remote *remote, int deepen) { struct transport *transport; transport = transport_get(remote, NULL); @@ -870,6 +873,8 @@ static struct transport *prepare_transport(struct remote *remote) set_option(transport, TRANS_OPT_KEEP, "yes"); if (depth) set_option(transport, TRANS_OPT_DEPTH, depth); + if (deepen && deepen_since) + set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since); if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); return transport; @@ -877,8 +882,18 @@ static struct transport *prepare_transport(struct remote *remote) static void backfill_tags(struct transport *transport, struct ref *ref_map) { - if (transport->cannot_reuse) { - gsecondary = prepare_transport(transport->remote); + int cannot_reuse; + + /* + * Once we have set TRANS_OPT_DEEPEN_SINCE, we can't unset it + * 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. + */ + cannot_reuse = transport->cannot_reuse || deepen_since; + if (cannot_reuse) { + gsecondary = prepare_transport(transport->remote, 0); transport = gsecondary; } @@ -1095,7 +1110,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv) die(_("No remote repository specified. Please, specify either a URL or a\n" "remote name from which new revisions should be fetched.")); - gtransport = prepare_transport(remote); + gtransport = prepare_transport(remote, 1); if (prune < 0) { /* no command line request */ @@ -1167,6 +1182,8 @@ 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) + deepen = 1; if (recurse_submodules != RECURSE_SUBMODULES_OFF) { if (recurse_submodules_default) { diff --git a/fetch-pack.c b/fetch-pack.c index a14d24a52f..a2f25c1849 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -21,6 +21,7 @@ static int fetch_unpack_limit = -1; static int unpack_limit = 100; static int prefer_ofs_delta = 1; static int no_done; +static int deepen_since_ok; static int fetch_fsck_objects = -1; static int transfer_fsck_objects = -1; static int agent_supported; @@ -326,6 +327,7 @@ static int find_common(struct fetch_pack_args *args, if (args->no_progress) strbuf_addstr(&c, " no-progress"); 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 (agent_supported) strbuf_addf(&c, " agent=%s", git_user_agent_sanitized()); packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); @@ -345,6 +347,10 @@ static int find_common(struct fetch_pack_args *args, write_shallow_commits(&req_buf, 1, NULL); if (args->depth > 0) packet_buf_write(&req_buf, "deepen %d", args->depth); + if (args->deepen_since) { + unsigned long max_age = approxidate(args->deepen_since); + packet_buf_write(&req_buf, "deepen-since %lu", max_age); + } packet_buf_flush(&req_buf); state_len = req_buf.len; @@ -812,7 +818,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) + if (args->depth > 0 || args->deepen_since) args->deepen = 1; if (server_supports("multi_ack_detailed")) { print_verbose(args, _("Server supports multi_ack_detailed")); @@ -860,6 +866,10 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, print_verbose(args, _("Server version is %.*s"), agent_len, agent_feature); } + if (server_supports("deepen-since")) + deepen_since_ok = 1; + else if (args->deepen_since) + die(_("Server does not support --shallow-since")); if (everything_local(args, &ref, sought, nr_sought)) { packet_flush(fd[1]); diff --git a/fetch-pack.h b/fetch-pack.h index 4d0adb0b97..f7eadb21eb 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -10,6 +10,7 @@ struct fetch_pack_args { const char *uploadpack; int unpacklimit; int depth; + const char *deepen_since; unsigned quiet:1; unsigned keep_pack:1; unsigned lock_pack:1; diff --git a/remote-curl.c b/remote-curl.c index fd030c13c8..5876f24023 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -20,6 +20,7 @@ static struct strbuf url = STRBUF_INIT; struct options { int verbosity; unsigned long depth; + char *deepen_since; unsigned progress : 1, check_self_contained_and_connected : 1, cloning : 1, @@ -60,6 +61,10 @@ static int set_option(const char *name, const char *value) options.depth = v; return 0; } + else if (!strcmp(name, "deepen-since")) { + options.deepen_since = xstrdup(value); + return 0; + } else if (!strcmp(name, "followtags")) { if (!strcmp(value, "true")) options.followtags = 1; @@ -699,8 +704,8 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch) char **targets = xmalloc(nr_heads * sizeof(char*)); int ret, i; - if (options.depth) - die("dumb http transport does not support --depth"); + if (options.depth || options.deepen_since) + die("dumb http transport does not support shallow capabilities"); for (i = 0; i < nr_heads; i++) targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid)); @@ -746,6 +751,8 @@ static int fetch_git(struct discovery *heads, argv_array_push(&args, "--no-progress"); if (options.depth) argv_array_pushf(&args, "--depth=%lu", options.depth); + if (options.deepen_since) + argv_array_pushf(&args, "--shallow-since=%s", options.deepen_since); argv_array_push(&args, url.buf); for (i = 0; i < nr_heads; i++) { diff --git a/transport.c b/transport.c index c92f8ae705..f04a302237 100644 --- a/transport.c +++ b/transport.c @@ -151,6 +151,9 @@ static int set_git_option(struct git_transport_options *opts, die("transport: invalid depth option '%s'", value); } return 0; + } else if (!strcmp(name, TRANS_OPT_DEEPEN_SINCE)) { + opts->deepen_since = value; + return 0; } return 1; } @@ -205,6 +208,7 @@ static int fetch_refs_via_pack(struct transport *transport, args.quiet = (transport->verbose < 0); args.no_progress = !transport->progress; args.depth = data->options.depth; + args.deepen_since = data->options.deepen_since; args.check_self_contained_and_connected = data->options.check_self_contained_and_connected; args.cloning = transport->cloning; diff --git a/transport.h b/transport.h index 8ebaaf2cae..9c10a4410b 100644 --- a/transport.h +++ b/transport.h @@ -13,6 +13,7 @@ struct git_transport_options { unsigned self_contained_and_connected : 1; unsigned update_shallow : 1; int depth; + const char *deepen_since; const char *uploadpack; const char *receivepack; struct push_cas_option *cas; @@ -171,6 +172,9 @@ int transport_restrict_protocols(void); /* Limit the depth of the fetch if not null */ #define TRANS_OPT_DEPTH "depth" +/* Limit the depth of the fetch based on time if not null */ +#define TRANS_OPT_DEEPEN_SINCE "deepen-since" + /* Aggressively fetch annotated tags if possible */ #define TRANS_OPT_FOLLOWTAGS "followtags" -- cgit 1.2.3-korg From a45a260086b395729e3c26c9680602e1352184b5 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 12 Jun 2016 17:54:04 +0700 Subject: fetch: define shallow boundary with --shallow-exclude MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- Documentation/fetch-options.txt | 5 +++++ Documentation/git-fetch-pack.txt | 5 +++++ Documentation/gitremote-helpers.txt | 4 ++++ builtin/fetch-pack.c | 7 +++++++ builtin/fetch.c | 13 ++++++++++--- fetch-pack.c | 15 ++++++++++++++- fetch-pack.h | 1 + remote-curl.c | 9 +++++++++ transport-helper.c | 24 ++++++++++++++++++++++++ transport.c | 4 ++++ transport.h | 6 ++++++ 11 files changed, 89 insertions(+), 4 deletions(-) (limited to 'fetch-pack.c') diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 8738d3dc36..7aa1285fc9 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -18,6 +18,11 @@ Deepen or shorten the history of a shallow repository to include all reachable commits after . +--shallow-exclude=:: + 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 diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 99e6257475..4d15b0469c 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -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 . +--shallow-exclude=:: + 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. diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index 9971d9a2b6..75bb6381f6 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -418,6 +418,10 @@ set by Git if the remote helper has the 'option' capability. 'option deepen-since :: Deepens the history of a shallow repository based on time. +'option deepen-not :: + 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 diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 0402e2756b..07570bee2d 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -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++]; diff --git a/builtin/fetch.c b/builtin/fetch.c index 283aa95aec..147504dd51 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -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) { diff --git a/fetch-pack.c b/fetch-pack.c index a2f25c1849..ad7d00f09c 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -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]); diff --git a/fetch-pack.h b/fetch-pack.h index f7eadb21eb..144301fbcd 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -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; diff --git a/remote-curl.c b/remote-curl.c index 5876f24023..1406e6a4eb 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -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]); diff --git a/transport-helper.c b/transport-helper.c index 27a34e9d4e..cc1a396c25 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -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; diff --git a/transport.c b/transport.c index f04a302237..3e6f3aa117 100644 --- a/transport.c +++ b/transport.c @@ -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; diff --git a/transport.h b/transport.h index 9c10a4410b..ab61932b5b 100644 --- a/transport.h +++ b/transport.h @@ -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" -- cgit 1.2.3-korg From cccf74e2da85808478c784e403a69bbfe2b9f518 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sun, 12 Jun 2016 17:54:09 +0700 Subject: fetch, upload-pack: --deepen=N extends shallow boundary by N commits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In git-fetch, --depth argument is always relative with the latest remote refs. This makes it a bit difficult to cover this use case, where the user wants to make the shallow history, say 3 levels deeper. It would work if remote refs have not moved yet, but nobody can guarantee that, especially when that use case is performed a couple months after the last clone or "git fetch --depth". Also, modifying shallow boundary using --depth does not work well with clones created by --since or --not. This patch fixes that. A new argument --deepen= will add more (*) parent commits to the current history regardless of where remote refs are. Have/Want negotiation is still respected. So if remote refs move, the server will send two chunks: one between "have" and "want" and another to extend shallow history. In theory, the client could send no "want"s in order to get the second chunk only. But the protocol does not allow that. Either you send no want lines, which means ls-remote; or you have to send at least one want line that carries deep-relative to the server.. The main work was done by Dongcan Jiang. I fixed it up here and there. And of course all the bugs belong to me. (*) We could even support --deepen= where is negative. In that case we can cut some history from the shallow clone. This operation (and --depth=) does not require interaction with remote side (and more complicated to implement as a result). Helped-by: Duy Nguyen Helped-by: Eric Sunshine Helped-by: Junio C Hamano Signed-off-by: Dongcan Jiang Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- Documentation/fetch-options.txt | 5 +++++ Documentation/git-fetch-pack.txt | 5 +++++ Documentation/gitremote-helpers.txt | 4 ++++ Documentation/technical/protocol-capabilities.txt | 7 ++++++ builtin/fetch-pack.c | 4 ++++ builtin/fetch.c | 14 +++++++++++- fetch-pack.c | 3 +++ fetch-pack.h | 1 + remote-curl.c | 14 +++++++++++- t/t5500-fetch-pack.sh | 23 ++++++++++++++++++++ t/t5539-fetch-http-shallow.sh | 26 +++++++++++++++++++++++ transport-helper.c | 1 + transport.c | 4 ++++ transport.h | 4 ++++ upload-pack.c | 23 ++++++++++++++++---- 15 files changed, 132 insertions(+), 6 deletions(-) (limited to 'fetch-pack.c') diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 7aa1285fc9..3b91f1528e 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -14,6 +14,11 @@ linkgit:git-clone[1]), deepen or shorten the history to the specified number of commits. Tags for the deepened commits are not fetched. +--deepen=:: + Similar to --depth, except it specifies the number of commits + from the current shallow boundary instead of from the tip of + each remote branch history. + --shallow-since=:: Deepen or shorten the history of a shallow repository to include all reachable commits after . diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 4d15b0469c..c20958f58f 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -96,6 +96,11 @@ be in a separate packet, and the list must end with a flush packet. exclude commits reachable from a specified remote branch or tag. This option can be specified multiple times. +--deepen-relative:: + Argument --depth specifies the number of commits from the + current shallow boundary instead of from the tip of each + remote branch history. + --no-progress:: Do not show the progress. diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index 75bb6381f6..6fca268742 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -422,6 +422,10 @@ set by Git if the remote helper has the 'option' capability. Deepens the history of a shallow repository excluding ref. Multiple options add up. +'option deepen-relative {'true'|'false'}:: + Deepens the history of a shallow repository relative to + current boundary. Only valid when used with "option depth". + 'option followtags' {'true'|'false'}:: If enabled the helper should automatically fetch annotated tag objects if the object the tag points at was transferred diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt index 0e6b57df75..4fd6dccdb5 100644 --- a/Documentation/technical/protocol-capabilities.txt +++ b/Documentation/technical/protocol-capabilities.txt @@ -197,6 +197,13 @@ specific revision, instead of depth. Internally it's equivalent of doing "rev-list --not " on the server side. "deepen-not" cannot be used with "deepen", but can be used with "deepen-since". +deepen-relative +--------------- + +If this capability is requested by the client, the semantics of +"deepen" command is changed. The "depth" argument is the depth from +the current shallow boundary, instead of the depth from remote refs. + no-progress ----------- diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 07570bee2d..82653487f8 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -113,6 +113,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) string_list_append(&deepen_not, arg); continue; } + if (!strcmp(arg, "--deepen-relative")) { + args.deepen_relative = 1; + continue; + } if (!strcmp("--no-progress", arg)) { args.no_progress = 1; continue; diff --git a/builtin/fetch.c b/builtin/fetch.c index 147504dd51..7b0ea1c86e 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -34,7 +34,7 @@ static int fetch_prune_config = -1; /* unspecified */ static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ -static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity; +static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative; static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen; static int max_children = 1; @@ -121,6 +121,8 @@ static struct option builtin_fetch_options[] = { 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")), + OPT_INTEGER(0, "deepen", &deepen_relative, + N_("deepen history of shallow clone")), { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL, N_("convert to a complete repository"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 }, @@ -881,6 +883,8 @@ static struct transport *prepare_transport(struct remote *remote, int deepen) if (deepen && deepen_not.nr) set_option(transport, TRANS_OPT_DEEPEN_NOT, (const char *)&deepen_not); + if (deepen_relative) + set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes"); if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); return transport; @@ -906,6 +910,7 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map) transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); + transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL); fetch_refs(transport, ref_map); if (gsecondary) { @@ -1177,6 +1182,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_fetch_options, builtin_fetch_usage, 0); + if (deepen_relative) { + if (deepen_relative < 0) + die(_("Negative depth in --deepen is not supported")); + if (depth) + die(_("--deepen and --depth are mutually exclusive")); + depth = xstrfmt("%d", deepen_relative); + } if (unshallow) { if (depth) die(_("--depth and --unshallow cannot be used together")); diff --git a/fetch-pack.c b/fetch-pack.c index ad7d00f09c..e2a235f536 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -324,6 +324,7 @@ static int find_common(struct fetch_pack_args *args, if (no_done) strbuf_addstr(&c, " no-done"); if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k"); if (use_sideband == 1) strbuf_addstr(&c, " side-band"); + if (args->deepen_relative) strbuf_addstr(&c, " deepen-relative"); if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack"); if (args->no_progress) strbuf_addstr(&c, " no-progress"); if (args->include_tag) strbuf_addstr(&c, " include-tag"); @@ -883,6 +884,8 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, deepen_not_ok = 1; else if (args->deepen_not) die(_("Server does not support --shallow-exclude")); + if (!server_supports("deepen-relative") && args->deepen_relative) + die(_("Server does not support --deepen")); if (everything_local(args, &ref, sought, nr_sought)) { packet_flush(fd[1]); diff --git a/fetch-pack.h b/fetch-pack.h index 144301fbcd..c912e3d321 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -12,6 +12,7 @@ struct fetch_pack_args { int depth; const char *deepen_since; const struct string_list *deepen_not; + unsigned deepen_relative:1; unsigned quiet:1; unsigned keep_pack:1; unsigned lock_pack:1; diff --git a/remote-curl.c b/remote-curl.c index 1406e6a4eb..d56412deb1 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -30,7 +30,8 @@ struct options { dry_run : 1, thin : 1, /* One of the SEND_PACK_PUSH_CERT_* constants. */ - push_cert : 2; + push_cert : 2, + deepen_relative : 1; }; static struct options options; static struct string_list cas_options = STRING_LIST_INIT_DUP; @@ -70,6 +71,15 @@ static int set_option(const char *name, const char *value) string_list_append(&options.deepen_not, value); return 0; } + else if (!strcmp(name, "deepen-relative")) { + if (!strcmp(value, "true")) + options.deepen_relative = 1; + else if (!strcmp(value, "false")) + options.deepen_relative = 0; + else + return -1; + return 0; + } else if (!strcmp(name, "followtags")) { if (!strcmp(value, "true")) options.followtags = 1; @@ -761,6 +771,8 @@ static int fetch_git(struct discovery *heads, for (i = 0; i < options.deepen_not.nr; i++) argv_array_pushf(&args, "--shallow-exclude=%s", options.deepen_not.items[i].string); + if (options.deepen_relative && options.depth) + argv_array_push(&args, "--deepen-relative"); argv_array_push(&args, url.buf); for (i = 0; i < nr_heads; i++) { diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 145b370768..a908036be7 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -682,4 +682,27 @@ test_expect_success 'fetch exclude tag one' ' test_cmp expected actual ' +test_expect_success 'fetching deepen' ' + test_create_repo shallow-deepen && + ( + cd shallow-deepen && + test_commit one && + test_commit two && + test_commit three && + git clone --depth 1 "file://$(pwd)/." deepen && + test_commit four && + git -C deepen log --pretty=tformat:%s master >actual && + echo three >expected && + test_cmp expected actual && + git -C deepen fetch --deepen=1 && + git -C deepen log --pretty=tformat:%s origin/master >actual && + cat >expected <<-\EOF && + four + three + two + EOF + test_cmp expected actual + ) +' + test_done diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh index 8e38c1be65..5fbf67c446 100755 --- a/t/t5539-fetch-http-shallow.sh +++ b/t/t5539-fetch-http-shallow.sh @@ -120,5 +120,31 @@ test_expect_success 'fetch exclude tag one' ' test_cmp expected actual ' +test_expect_success 'fetching deepen' ' + test_create_repo shallow-deepen && + ( + cd shallow-deepen && + test_commit one && + test_commit two && + test_commit three && + mv .git "$HTTPD_DOCUMENT_ROOT_PATH/shallow-deepen.git" && + git clone --depth 1 $HTTPD_URL/smart/shallow-deepen.git deepen && + mv "$HTTPD_DOCUMENT_ROOT_PATH/shallow-deepen.git" .git && + test_commit four && + git -C deepen log --pretty=tformat:%s master >actual && + echo three >expected && + test_cmp expected actual && + mv .git "$HTTPD_DOCUMENT_ROOT_PATH/shallow-deepen.git" && + git -C deepen fetch --deepen=1 && + git -C deepen log --pretty=tformat:%s origin/master >actual && + cat >expected <<-\EOF && + four + three + two + EOF + test_cmp expected actual + ) +' + stop_httpd test_done diff --git a/transport-helper.c b/transport-helper.c index cc1a396c25..a5cdd7730c 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -258,6 +258,7 @@ static const char *boolean_options[] = { TRANS_OPT_THIN, TRANS_OPT_KEEP, TRANS_OPT_FOLLOWTAGS, + TRANS_OPT_DEEPEN_RELATIVE }; static int strbuf_set_helper_option(struct helper_data *data, diff --git a/transport.c b/transport.c index 3e6f3aa117..3e76a9af4d 100644 --- a/transport.c +++ b/transport.c @@ -157,6 +157,9 @@ static int set_git_option(struct git_transport_options *opts, } else if (!strcmp(name, TRANS_OPT_DEEPEN_NOT)) { opts->deepen_not = (const struct string_list *)value; return 0; + } else if (!strcmp(name, TRANS_OPT_DEEPEN_RELATIVE)) { + opts->deepen_relative = !!value; + return 0; } return 1; } @@ -213,6 +216,7 @@ static int fetch_refs_via_pack(struct transport *transport, args.depth = data->options.depth; args.deepen_since = data->options.deepen_since; args.deepen_not = data->options.deepen_not; + args.deepen_relative = data->options.deepen_relative; args.check_self_contained_and_connected = data->options.check_self_contained_and_connected; args.cloning = transport->cloning; diff --git a/transport.h b/transport.h index ab61932b5b..bdc35181c3 100644 --- a/transport.h +++ b/transport.h @@ -14,6 +14,7 @@ struct git_transport_options { unsigned check_self_contained_and_connected : 1; unsigned self_contained_and_connected : 1; unsigned update_shallow : 1; + unsigned deepen_relative : 1; int depth; const char *deepen_since; const struct string_list *deepen_not; @@ -181,6 +182,9 @@ int transport_restrict_protocols(void); /* Limit the depth of the fetch based on revs if not null */ #define TRANS_OPT_DEEPEN_NOT "deepen-not" +/* Limit the deepen of the fetch if not null */ +#define TRANS_OPT_DEEPEN_RELATIVE "deepen-relative" + /* Aggressively fetch annotated tags if possible */ #define TRANS_OPT_FOLLOWTAGS "followtags" diff --git a/upload-pack.c b/upload-pack.c index 3227df872c..e40d15adaf 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -32,6 +32,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=< static unsigned long oldest_have; +static int deepen_relative; static int multi_ack; static int no_done; static int use_thin_pack, use_ofs_delta, use_include_tag; @@ -674,7 +675,8 @@ static void send_unshallow(const struct object_array *shallows) } } -static void deepen(int depth, const struct object_array *shallows) +static void deepen(int depth, int deepen_relative, + struct object_array *shallows) { if (depth == INFINITE_DEPTH && !is_repository_shallow()) { int i; @@ -683,6 +685,17 @@ static void deepen(int depth, const struct object_array *shallows) struct object *object = shallows->objects[i].item; object->flags |= NOT_SHALLOW; } + } else if (deepen_relative) { + struct object_array reachable_shallows = OBJECT_ARRAY_INIT; + struct commit_list *result; + + get_reachable_list(shallows, &reachable_shallows); + result = get_shallow_commits(&reachable_shallows, + depth + 1, + SHALLOW, NOT_SHALLOW); + send_shallow(result); + free_commit_list(result); + object_array_clear(&reachable_shallows); } else { struct commit_list *result; @@ -779,6 +792,8 @@ static void receive_needs(void) features = arg + 40; + if (parse_feature_request(features, "deepen-relative")) + deepen_relative = 1; if (parse_feature_request(features, "multi_ack_detailed")) multi_ack = 2; else if (parse_feature_request(features, "multi_ack")) @@ -828,7 +843,7 @@ static void receive_needs(void) if (depth > 0 && deepen_rev_list) die("git upload-pack: deepen and deepen-since (or deepen-not) cannot be used together"); if (depth > 0) - deepen(depth, &shallows); + deepen(depth, deepen_relative, &shallows); else if (deepen_rev_list) { struct argv_array av = ARGV_ARRAY_INIT; int i; @@ -899,8 +914,8 @@ static int send_ref(const char *refname, const struct object_id *oid, int flag, void *cb_data) { static const char *capabilities = "multi_ack thin-pack side-band" - " side-band-64k ofs-delta shallow deepen-since deepen-not no-progress" - " include-tag multi_ack_detailed"; + " side-band-64k ofs-delta shallow deepen-since deepen-not" + " deepen-relative no-progress include-tag multi_ack_detailed"; const char *refname_nons = strip_namespace(refname); struct object_id peeled; -- cgit 1.2.3-korg