fetch: define shallow boundary with --shallow-exclude

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Nguyễn Thái Ngọc Duy 2016-06-12 17:54:04 +07:00 committed by Junio C Hamano
parent 269a7a8316
commit a45a260086
11 changed files with 89 additions and 4 deletions

View File

@ -18,6 +18,11 @@
Deepen or shorten the history of a shallow repository to Deepen or shorten the history of a shallow repository to
include all reachable commits after <date>. 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:: --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

@ -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 Deepen or shorten the history of a shallow'repository to
include all reachable commits after <date>. 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:: --no-progress::
Do not show the progress. Do not show the progress.



View File

@ -418,6 +418,10 @@ set by Git if the remote helper has the 'option' capability.
'option deepen-since <timestamp>:: 'option deepen-since <timestamp>::
Deepens the history of a shallow repository based on time. 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'}:: '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

@ -50,6 +50,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
struct child_process *conn; struct child_process *conn;
struct fetch_pack_args args; struct fetch_pack_args args;
struct sha1_array shallow = SHA1_ARRAY_INIT; struct sha1_array shallow = SHA1_ARRAY_INIT;
struct string_list deepen_not = STRING_LIST_INIT_DUP;


packet_trace_identity("fetch-pack"); 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); args.deepen_since = xstrdup(arg);
continue; continue;
} }
if (skip_prefix(arg, "--shallow-exclude=", &arg)) {
string_list_append(&deepen_not, arg);
continue;
}
if (!strcmp("--no-progress", arg)) { if (!strcmp("--no-progress", arg)) {
args.no_progress = 1; args.no_progress = 1;
continue; continue;
@ -135,6 +140,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
} }
usage(fetch_pack_usage); usage(fetch_pack_usage);
} }
if (deepen_not.nr)
args.deepen_not = &deepen_not;


if (i < argc) if (i < argc)
dest = argv[i++]; dest = argv[i++];

View File

@ -41,6 +41,7 @@ static int max_children = 1;
static const char *depth; static const char *depth;
static const char *deepen_since; static const char *deepen_since;
static const char *upload_pack; static const char *upload_pack;
static struct string_list deepen_not = STRING_LIST_INIT_NODUP;
static struct strbuf default_rla = STRBUF_INIT; static struct strbuf default_rla = STRBUF_INIT;
static struct transport *gtransport; static struct transport *gtransport;
static struct transport *gsecondary; static struct transport *gsecondary;
@ -118,6 +119,8 @@ static struct option builtin_fetch_options[] = {
N_("deepen history of shallow clone")), N_("deepen history of shallow clone")),
OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
N_("deepen history of shallow repository based on 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, { 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 },
@ -875,6 +878,9 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
set_option(transport, TRANS_OPT_DEPTH, depth); set_option(transport, TRANS_OPT_DEPTH, depth);
if (deepen && deepen_since) if (deepen && deepen_since)
set_option(transport, TRANS_OPT_DEEPEN_SINCE, 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) if (update_shallow)
set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
return transport; 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 * when remote helper is used (setting it to an empty string
* is not unsetting). We could extend the remote helper * is not unsetting). We could extend the remote helper
* protocol for that, but for now, just force a new connection * 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) { if (cannot_reuse) {
gsecondary = prepare_transport(transport->remote, 0); gsecondary = prepare_transport(transport->remote, 0);
transport = gsecondary; 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 */ /* 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) if (depth || deepen_since || deepen_not.nr)
deepen = 1; deepen = 1;


if (recurse_submodules != RECURSE_SUBMODULES_OFF) { if (recurse_submodules != RECURSE_SUBMODULES_OFF) {

View File

@ -22,6 +22,7 @@ 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 deepen_since_ok;
static int deepen_not_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;
@ -328,6 +329,7 @@ static int find_common(struct fetch_pack_args *args,
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 (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", 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);
@ -351,6 +353,13 @@ static int find_common(struct fetch_pack_args *args,
unsigned long max_age = approxidate(args->deepen_since); unsigned long max_age = approxidate(args->deepen_since);
packet_buf_write(&req_buf, "deepen-since %lu", max_age); 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); packet_buf_flush(&req_buf);
state_len = req_buf.len; 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")) 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 || args->deepen_since) if (args->depth > 0 || args->deepen_since || args->deepen_not)
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"));
@ -870,6 +879,10 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
deepen_since_ok = 1; deepen_since_ok = 1;
else if (args->deepen_since) else if (args->deepen_since)
die(_("Server does not support --shallow-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)) { if (everything_local(args, &ref, sought, nr_sought)) {
packet_flush(fd[1]); packet_flush(fd[1]);

View File

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

View File

@ -21,6 +21,7 @@ struct options {
int verbosity; int verbosity;
unsigned long depth; unsigned long depth;
char *deepen_since; char *deepen_since;
struct string_list deepen_not;
unsigned progress : 1, unsigned progress : 1,
check_self_contained_and_connected : 1, check_self_contained_and_connected : 1,
cloning : 1, cloning : 1,
@ -65,6 +66,10 @@ static int set_option(const char *name, const char *value)
options.deepen_since = xstrdup(value); options.deepen_since = xstrdup(value);
return 0; return 0;
} }
else if (!strcmp(name, "deepen-not")) {
string_list_append(&options.deepen_not, 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;
@ -753,6 +758,9 @@ static int fetch_git(struct discovery *heads,
argv_array_pushf(&args, "--depth=%lu", options.depth); argv_array_pushf(&args, "--depth=%lu", options.depth);
if (options.deepen_since) if (options.deepen_since)
argv_array_pushf(&args, "--shallow-since=%s", 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); argv_array_push(&args, url.buf);


for (i = 0; i < nr_heads; i++) { for (i = 0; i < nr_heads; i++) {
@ -973,6 +981,7 @@ int main(int argc, const char **argv)
options.verbosity = 1; options.verbosity = 1;
options.progress = !!isatty(2); options.progress = !!isatty(2);
options.thin = 1; options.thin = 1;
string_list_init(&options.deepen_not, 1);


remote = remote_get(argv[1]); remote = remote_get(argv[1]);



View File

@ -282,6 +282,26 @@ static int strbuf_set_helper_option(struct helper_data *data,
return ret; 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, static int set_helper_option(struct transport *transport,
const char *name, const char *value) const char *name, const char *value)
{ {
@ -294,6 +314,10 @@ static int set_helper_option(struct transport *transport,
if (!data->option) if (!data->option)
return 1; 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++) { for (i = 0; i < ARRAY_SIZE(unsupported_options); i++) {
if (!strcmp(name, unsupported_options[i])) if (!strcmp(name, unsupported_options[i]))
return 1; return 1;

View File

@ -154,6 +154,9 @@ static int set_git_option(struct git_transport_options *opts,
} else if (!strcmp(name, TRANS_OPT_DEEPEN_SINCE)) { } else if (!strcmp(name, TRANS_OPT_DEEPEN_SINCE)) {
opts->deepen_since = value; opts->deepen_since = value;
return 0; return 0;
} else if (!strcmp(name, TRANS_OPT_DEEPEN_NOT)) {
opts->deepen_not = (const struct string_list *)value;
return 0;
} }
return 1; return 1;
} }
@ -209,6 +212,7 @@ static int fetch_refs_via_pack(struct transport *transport,
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.deepen_since = data->options.deepen_since;
args.deepen_not = data->options.deepen_not;
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

@ -5,6 +5,8 @@
#include "run-command.h" #include "run-command.h"
#include "remote.h" #include "remote.h"


struct string_list;

struct git_transport_options { struct git_transport_options {
unsigned thin : 1; unsigned thin : 1;
unsigned keep : 1; unsigned keep : 1;
@ -14,6 +16,7 @@ struct git_transport_options {
unsigned update_shallow : 1; unsigned update_shallow : 1;
int depth; int depth;
const char *deepen_since; const char *deepen_since;
const struct string_list *deepen_not;
const char *uploadpack; const char *uploadpack;
const char *receivepack; const char *receivepack;
struct push_cas_option *cas; 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 */ /* Limit the depth of the fetch based on time if not null */
#define TRANS_OPT_DEEPEN_SINCE "deepen-since" #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 */ /* Aggressively fetch annotated tags if possible */
#define TRANS_OPT_FOLLOWTAGS "followtags" #define TRANS_OPT_FOLLOWTAGS "followtags"