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
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.
'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
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");
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;
}
usage(fetch_pack_usage);
}
+ if (deepen_not.nr)
+ args.deepen_not = &deepen_not;
if (i < argc)
dest = argv[i++];
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;
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 },
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;
* 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;
/* 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) {
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;
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);
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;
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"));
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]);
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;
int verbosity;
unsigned long depth;
char *deepen_since;
+ struct string_list deepen_not;
unsigned progress : 1,
check_self_contained_and_connected : 1,
cloning : 1,
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;
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++) {
options.verbosity = 1;
options.progress = !!isatty(2);
options.thin = 1;
+ string_list_init(&options.deepen_not, 1);
remote = remote_get(argv[1]);
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)
{
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;
} 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;
}
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;
#include "run-command.h"
#include "remote.h"
+struct string_list;
+
struct git_transport_options {
unsigned thin : 1;
unsigned keep : 1;
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;
/* 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"