fetch: define shallow boundary with --shallow-since

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2016-06-12 17:53:59 +07:00 committed by Junio C Hamano
parent 569e554be9
commit 508ea88226
10 changed files with 67 additions and 9 deletions

View File

@ -14,6 +14,10 @@
linkgit:git-clone[1]), deepen or shorten the history to the specified linkgit:git-clone[1]), deepen or shorten the history to the specified
number of commits. Tags for the deepened commits are not fetched. number of commits. Tags for the deepened commits are not fetched.
--shallow-since=<date>::
Deepen or shorten the history of a shallow repository to
include all reachable commits after <date>.
--unshallow:: --unshallow::
If the source repository is complete, convert a shallow If the source repository is complete, convert a shallow
repository to a complete one, removing all the limitations repository to a complete one, removing all the limitations

View File

@ -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 'git-upload-pack' treats the special depth 2147483647 as
infinite even if there is an ancestor-chain that long. infinite even if there is an ancestor-chain that long.
--shallow-since=<date>::
Deepen or shorten the history of a shallow'repository to
include all reachable commits after <date>.
--no-progress:: --no-progress::
Do not show the progress. Do not show the progress.

View File

@ -415,6 +415,9 @@ set by Git if the remote helper has the 'option' capability.
'option depth' <depth>:: 'option depth' <depth>::
Deepens the history of a shallow repository. Deepens the history of a shallow repository.
'option deepen-since <timestamp>::
Deepens the history of a shallow repository based on time.
'option followtags' {'true'|'false'}:: 'option followtags' {'true'|'false'}::
If enabled the helper should automatically fetch annotated If enabled the helper should automatically fetch annotated
tag objects if the object the tag points at was transferred tag objects if the object the tag points at was transferred

View File

@ -104,6 +104,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
args.depth = strtol(arg, NULL, 0); args.depth = strtol(arg, NULL, 0);
continue; continue;
} }
if (skip_prefix(arg, "--shallow-since=", &arg)) {
args.deepen_since = xstrdup(arg);
continue;
}
if (!strcmp("--no-progress", arg)) { if (!strcmp("--no-progress", arg)) {
args.no_progress = 1; args.no_progress = 1;
continue; continue;

View File

@ -36,9 +36,10 @@ static int prune = -1; /* unspecified */
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;
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; 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 int max_children = 1;
static const char *depth; static const char *depth;
static const char *deepen_since;
static const char *upload_pack; static const char *upload_pack;
static struct strbuf default_rla = STRBUF_INIT; static struct strbuf default_rla = STRBUF_INIT;
static struct transport *gtransport; static struct transport *gtransport;
@ -115,6 +116,8 @@ static struct option builtin_fetch_options[] = {
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
OPT_STRING(0, "depth", &depth, N_("depth"), OPT_STRING(0, "depth", &depth, N_("depth"),
N_("deepen history of shallow clone")), 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, { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL,
N_("convert to a complete repository"), N_("convert to a complete repository"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 }, 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 * really need to perform. Claiming failure now will ensure
* we perform the network exchange to deepen our history. * we perform the network exchange to deepen our history.
*/ */
if (depth) if (deepen)
return -1; return -1;
return check_everything_connected(iterate_ref_map, 1, &rm); 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); name, transport->url);
} }
static struct transport *prepare_transport(struct remote *remote) static struct transport *prepare_transport(struct remote *remote, int deepen)
{ {
struct transport *transport; struct transport *transport;
transport = transport_get(remote, NULL); transport = transport_get(remote, NULL);
@ -870,6 +873,8 @@ static struct transport *prepare_transport(struct remote *remote)
set_option(transport, TRANS_OPT_KEEP, "yes"); set_option(transport, TRANS_OPT_KEEP, "yes");
if (depth) if (depth)
set_option(transport, TRANS_OPT_DEPTH, depth); set_option(transport, TRANS_OPT_DEPTH, depth);
if (deepen && deepen_since)
set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since);
if (update_shallow) if (update_shallow)
set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
return transport; 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) static void backfill_tags(struct transport *transport, struct ref *ref_map)
{ {
if (transport->cannot_reuse) { int cannot_reuse;
gsecondary = prepare_transport(transport->remote);
/*
* 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; 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" die(_("No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched.")); "remote name from which new revisions should be fetched."));
gtransport = prepare_transport(remote); gtransport = prepare_transport(remote, 1);
if (prune < 0) { if (prune < 0) {
/* no command line request */ /* 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 */ /* no need to be strict, transport_set_option() will validate it again */
if (depth && atoi(depth) < 1) if (depth && atoi(depth) < 1)
die(_("depth %s is not a positive number"), depth); die(_("depth %s is not a positive number"), depth);
if (depth || deepen_since)
deepen = 1;
if (recurse_submodules != RECURSE_SUBMODULES_OFF) { if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
if (recurse_submodules_default) { if (recurse_submodules_default) {

View File

@ -21,6 +21,7 @@ static int fetch_unpack_limit = -1;
static int unpack_limit = 100; static int unpack_limit = 100;
static int prefer_ofs_delta = 1; static int prefer_ofs_delta = 1;
static int no_done; static int no_done;
static int deepen_since_ok;
static int fetch_fsck_objects = -1; static int fetch_fsck_objects = -1;
static int transfer_fsck_objects = -1; static int transfer_fsck_objects = -1;
static int agent_supported; 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->no_progress) strbuf_addstr(&c, " no-progress");
if (args->include_tag) strbuf_addstr(&c, " include-tag"); if (args->include_tag) strbuf_addstr(&c, " include-tag");
if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta"); 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", if (agent_supported) strbuf_addf(&c, " agent=%s",
git_user_agent_sanitized()); git_user_agent_sanitized());
packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); 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); write_shallow_commits(&req_buf, 1, NULL);
if (args->depth > 0) if (args->depth > 0)
packet_buf_write(&req_buf, "deepen %d", args->depth); 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); packet_buf_flush(&req_buf);
state_len = req_buf.len; 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")) 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 (args->depth > 0) if (args->depth > 0 || args->deepen_since)
args->deepen = 1; args->deepen = 1;
if (server_supports("multi_ack_detailed")) { if (server_supports("multi_ack_detailed")) {
print_verbose(args, _("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"), print_verbose(args, _("Server version is %.*s"),
agent_len, agent_feature); 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)) { if (everything_local(args, &ref, sought, nr_sought)) {
packet_flush(fd[1]); packet_flush(fd[1]);

View File

@ -10,6 +10,7 @@ struct fetch_pack_args {
const char *uploadpack; const char *uploadpack;
int unpacklimit; int unpacklimit;
int depth; int depth;
const char *deepen_since;
unsigned quiet:1; unsigned quiet:1;
unsigned keep_pack:1; unsigned keep_pack:1;
unsigned lock_pack:1; unsigned lock_pack:1;

View File

@ -20,6 +20,7 @@ static struct strbuf url = STRBUF_INIT;
struct options { struct options {
int verbosity; int verbosity;
unsigned long depth; unsigned long depth;
char *deepen_since;
unsigned progress : 1, unsigned progress : 1,
check_self_contained_and_connected : 1, check_self_contained_and_connected : 1,
cloning : 1, cloning : 1,
@ -60,6 +61,10 @@ static int set_option(const char *name, const char *value)
options.depth = v; options.depth = v;
return 0; return 0;
} }
else if (!strcmp(name, "deepen-since")) {
options.deepen_since = xstrdup(value);
return 0;
}
else if (!strcmp(name, "followtags")) { else if (!strcmp(name, "followtags")) {
if (!strcmp(value, "true")) if (!strcmp(value, "true"))
options.followtags = 1; 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*)); char **targets = xmalloc(nr_heads * sizeof(char*));
int ret, i; int ret, i;
if (options.depth) if (options.depth || options.deepen_since)
die("dumb http transport does not support --depth"); die("dumb http transport does not support shallow capabilities");
for (i = 0; i < nr_heads; i++) for (i = 0; i < nr_heads; i++)
targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid)); 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"); argv_array_push(&args, "--no-progress");
if (options.depth) if (options.depth)
argv_array_pushf(&args, "--depth=%lu", 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); argv_array_push(&args, url.buf);
for (i = 0; i < nr_heads; i++) { for (i = 0; i < nr_heads; i++) {

View File

@ -151,6 +151,9 @@ static int set_git_option(struct git_transport_options *opts,
die("transport: invalid depth option '%s'", value); die("transport: invalid depth option '%s'", value);
} }
return 0; return 0;
} else if (!strcmp(name, TRANS_OPT_DEEPEN_SINCE)) {
opts->deepen_since = value;
return 0;
} }
return 1; return 1;
} }
@ -205,6 +208,7 @@ static int fetch_refs_via_pack(struct transport *transport,
args.quiet = (transport->verbose < 0); args.quiet = (transport->verbose < 0);
args.no_progress = !transport->progress; args.no_progress = !transport->progress;
args.depth = data->options.depth; args.depth = data->options.depth;
args.deepen_since = data->options.deepen_since;
args.check_self_contained_and_connected = args.check_self_contained_and_connected =
data->options.check_self_contained_and_connected; data->options.check_self_contained_and_connected;
args.cloning = transport->cloning; args.cloning = transport->cloning;

View File

@ -13,6 +13,7 @@ struct git_transport_options {
unsigned self_contained_and_connected : 1; unsigned self_contained_and_connected : 1;
unsigned update_shallow : 1; unsigned update_shallow : 1;
int depth; int depth;
const char *deepen_since;
const char *uploadpack; const char *uploadpack;
const char *receivepack; const char *receivepack;
struct push_cas_option *cas; struct push_cas_option *cas;
@ -171,6 +172,9 @@ int transport_restrict_protocols(void);
/* Limit the depth of the fetch if not null */ /* Limit the depth of the fetch if not null */
#define TRANS_OPT_DEPTH "depth" #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 */ /* Aggressively fetch annotated tags if possible */
#define TRANS_OPT_FOLLOWTAGS "followtags" #define TRANS_OPT_FOLLOWTAGS "followtags"