static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
static int shown_url = 0;
-static int refmap_alloc, refmap_nr;
-static const char **refmap_array;
+static struct refspec refmap = REFSPEC_INIT_FETCH;
static struct list_objects_filter_options filter_options;
+static struct string_list server_options = STRING_LIST_INIT_DUP;
static int git_fetch_config(const char *k, const char *v, void *cb)
{
static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
{
- ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
-
/*
* "git fetch --refmap='' origin foo"
* can be used to tell the command not to store anywhere
*/
- if (*arg)
- refmap_array[refmap_nr++] = arg;
+ refspec_append(&refmap, arg);
+
return 0;
}
N_("deepen history of shallow clone, 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 },
+ OPT_SET_INT_F(0, "unshallow", &unshallow,
+ N_("convert to a complete repository"),
+ 1, PARSE_OPT_NONEG),
{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
{ OPTION_CALLBACK, 0, "recurse-submodules-default",
N_("accept refs that update .git/shallow")),
{ OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
+ OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
}
static struct ref *get_ref_map(struct transport *transport,
- struct refspec_item *refspecs, int refspec_count,
+ struct refspec *rs,
int tags, int *autotags)
{
int i;
const struct ref *remote_refs;
- for (i = 0; i < refspec_count; i++) {
- if (!refspecs[i].exact_sha1) {
- const char *glob = strchr(refspecs[i].src, '*');
- if (glob)
- argv_array_pushf(&ref_prefixes, "%.*s",
- (int)(glob - refspecs[i].src),
- refspecs[i].src);
- else
- expand_ref_prefix(&ref_prefixes, refspecs[i].src);
- }
+ if (rs->nr)
+ refspec_ref_prefixes(rs, &ref_prefixes);
+ else if (transport->remote && transport->remote->fetch.nr)
+ refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
+
+ if (ref_prefixes.argc &&
+ (tags == TAGS_SET || (tags == TAGS_DEFAULT && !rs->nr))) {
+ argv_array_push(&ref_prefixes, "refs/tags/");
}
remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
argv_array_clear(&ref_prefixes);
- if (refspec_count) {
- struct refspec_item *fetch_refspec;
- int fetch_refspec_nr;
+ if (rs->nr) {
+ struct refspec *fetch_refspec;
- for (i = 0; i < refspec_count; i++) {
- get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
- if (refspecs[i].dst && refspecs[i].dst[0])
+ for (i = 0; i < rs->nr; i++) {
+ get_fetch_map(remote_refs, &rs->items[i], &tail, 0);
+ if (rs->items[i].dst && rs->items[i].dst[0])
*autotags = 1;
}
/* Merge everything on the command line (but not --tags) */
* by ref_remove_duplicates() in favor of one of these
* opportunistic entries with FETCH_HEAD_IGNORE.
*/
- if (refmap_array) {
- fetch_refspec = parse_fetch_refspec(refmap_nr, refmap_array);
- fetch_refspec_nr = refmap_nr;
- } else {
- fetch_refspec = transport->remote->fetch.items;
- fetch_refspec_nr = transport->remote->fetch.nr;
- }
+ if (refmap.nr)
+ fetch_refspec = &refmap;
+ else
+ fetch_refspec = &transport->remote->fetch;
- for (i = 0; i < fetch_refspec_nr; i++)
- get_fetch_map(ref_map, &fetch_refspec[i], &oref_tail, 1);
- } else if (refmap_array) {
+ for (i = 0; i < fetch_refspec->nr; i++)
+ get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1);
+ } else if (refmap.nr) {
die("--refmap option is only meaningful with command-line refspec(s).");
} else {
/* Use the defaults */
struct branch *current_branch = branch_get(NULL);
const char *pretty_ref = prettify_refname(ref->name);
- type = oid_object_info(&ref->new_oid, NULL);
+ type = oid_object_info(the_repository, &ref->new_oid, NULL);
if (type < 0)
die(_("object %s not found"), oid_to_hex(&ref->new_oid));
return ret;
}
-static int prune_refs(struct refspec_item *refs, int ref_count, struct ref *ref_map,
- const char *raw_url)
+static int prune_refs(struct refspec *rs, struct ref *ref_map,
+ const char *raw_url)
{
int url_len, i, result = 0;
- struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map);
+ struct ref *ref, *stale_refs = get_stale_heads(rs, ref_map);
char *url;
int summary_width = transport_summary_width(stale_refs);
const char *dangling_msg = dry_run
}
static int do_fetch(struct transport *transport,
- struct refspec_item *refs, int ref_count)
+ struct refspec *rs)
{
struct string_list existing_refs = STRING_LIST_INIT_DUP;
struct ref *ref_map;
goto cleanup;
}
- ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
+ ref_map = get_ref_map(transport, rs, tags, &autotags);
if (!update_head_ok)
check_not_current_branch(ref_map);
* explicitly (via command line or configuration); we
* don't care whether --tags was specified.
*/
- if (ref_count) {
- prune_refs(refs, ref_count, ref_map, transport->url);
+ if (rs->nr) {
+ prune_refs(rs, ref_map, transport->url);
} else {
- prune_refs(transport->remote->fetch.items,
- transport->remote->fetch.nr,
+ prune_refs(&transport->remote->fetch,
ref_map,
transport->url);
}
static int fetch_one(struct remote *remote, int argc, const char **argv, int prune_tags_ok)
{
- static const char **refs = NULL;
- struct refspec_item *refspec;
- int ref_nr = 0;
- int j = 0;
+ struct refspec rs = REFSPEC_INIT_FETCH;
+ int i;
int exit_code;
int maybe_prune_tags;
int remote_via_config = remote_is_configured(remote, 0);
maybe_prune_tags = prune_tags_ok && prune_tags;
if (maybe_prune_tags && remote_via_config)
- add_prune_tags_to_fetch_refspec(remote);
-
- if (argc > 0 || (maybe_prune_tags && !remote_via_config)) {
- size_t nr_alloc = st_add3(argc, maybe_prune_tags, 1);
- refs = xcalloc(nr_alloc, sizeof(const char *));
- if (maybe_prune_tags) {
- refs[j++] = xstrdup("refs/tags/*:refs/tags/*");
- ref_nr++;
+ refspec_append(&remote->fetch, TAG_REFSPEC);
+
+ if (maybe_prune_tags && (argc || !remote_via_config))
+ refspec_append(&rs, TAG_REFSPEC);
+
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "tag")) {
+ char *tag;
+ i++;
+ if (i >= argc)
+ die(_("You need to specify a tag name."));
+
+ tag = xstrfmt("refs/tags/%s:refs/tags/%s",
+ argv[i], argv[i]);
+ refspec_append(&rs, tag);
+ free(tag);
+ } else {
+ refspec_append(&rs, argv[i]);
}
}
- if (argc > 0) {
- int i;
- for (i = 0; i < argc; i++) {
- if (!strcmp(argv[i], "tag")) {
- i++;
- if (i >= argc)
- die(_("You need to specify a tag name."));
- refs[j++] = xstrfmt("refs/tags/%s:refs/tags/%s",
- argv[i], argv[i]);
- } else
- refs[j++] = argv[i];
- ref_nr++;
- }
- }
+ if (server_options.nr)
+ gtransport->server_options = &server_options;
sigchain_push_common(unlock_pack_on_signal);
atexit(unlock_pack);
- refspec = parse_fetch_refspec(ref_nr, refs);
- exit_code = do_fetch(gtransport, refspec, ref_nr);
- free_refspec(ref_nr, refspec);
+ exit_code = do_fetch(gtransport, &rs);
+ refspec_clear(&rs);
transport_disconnect(gtransport);
gtransport = NULL;
return exit_code;