зеркало из https://github.com/microsoft/git.git
Merge branch 'bw/ref-prefix-for-configured-refspec'
"git fetch $there $refspec" that talks over protocol v2 can take advantage of server-side ref filtering; the code has been extended so that this mechanism triggers also when fetching with configured refspec. * bw/ref-prefix-for-configured-refspec: (38 commits) fetch: generate ref-prefixes when using a configured refspec refspec: consolidate ref-prefix generation logic submodule: convert push_unpushed_submodules to take a struct refspec remote: convert check_push_refs to take a struct refspec remote: convert match_push_refs to take a struct refspec http-push: store refspecs in a struct refspec transport: remove transport_verify_remote_names send-pack: store refspecs in a struct refspec transport: convert transport_push to take a struct refspec push: convert to use struct refspec push: check for errors earlier remote: convert match_explicit_refs to take a struct refspec remote: convert get_ref_match to take a struct refspec remote: convert query_refspecs to take a struct refspec remote: convert apply_refspecs to take a struct refspec remote: convert get_stale_heads to take a struct refspec fetch: convert prune_refs to take a struct refspec fetch: convert get_ref_map to take a struct refspec fetch: convert do_fetch to take a struct refspec refspec: remove the deprecated functions ...
This commit is contained in:
Коммит
e12cbeaa62
1
Makefile
1
Makefile
|
@ -928,6 +928,7 @@ LIB_OBJS += refs/files-backend.o
|
|||
LIB_OBJS += refs/iterator.o
|
||||
LIB_OBJS += refs/packed-backend.o
|
||||
LIB_OBJS += refs/ref-cache.o
|
||||
LIB_OBJS += refspec.o
|
||||
LIB_OBJS += ref-filter.o
|
||||
LIB_OBJS += remote.o
|
||||
LIB_OBJS += replace-object.o
|
||||
|
|
7
branch.c
7
branch.c
|
@ -3,12 +3,13 @@
|
|||
#include "config.h"
|
||||
#include "branch.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "remote.h"
|
||||
#include "commit.h"
|
||||
#include "worktree.h"
|
||||
|
||||
struct tracking {
|
||||
struct refspec spec;
|
||||
struct refspec_item spec;
|
||||
char *src;
|
||||
const char *remote;
|
||||
int matches;
|
||||
|
@ -218,8 +219,8 @@ int validate_new_branchname(const char *name, struct strbuf *ref, int force)
|
|||
static int check_tracking_branch(struct remote *remote, void *cb_data)
|
||||
{
|
||||
char *tracking_branch = cb_data;
|
||||
struct refspec query;
|
||||
memset(&query, 0, sizeof(struct refspec));
|
||||
struct refspec_item query;
|
||||
memset(&query, 0, sizeof(struct refspec_item));
|
||||
query.dst = tracking_branch;
|
||||
return !remote_find_tracking(remote, &query);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "parse-options.h"
|
||||
#include "fetch-pack.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "tree.h"
|
||||
#include "tree-walk.h"
|
||||
#include "unpack-trees.h"
|
||||
|
@ -546,7 +547,7 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
|
|||
}
|
||||
|
||||
static struct ref *wanted_peer_refs(const struct ref *refs,
|
||||
struct refspec *refspec)
|
||||
struct refspec_item *refspec)
|
||||
{
|
||||
struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
|
||||
struct ref *local_refs = head;
|
||||
|
@ -894,8 +895,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
int err = 0, complete_refs_before_fetch = 1;
|
||||
int submodule_progress;
|
||||
|
||||
struct refspec *refspec;
|
||||
const char *fetch_pattern;
|
||||
struct refspec_item refspec;
|
||||
|
||||
fetch_if_missing = 0;
|
||||
|
||||
|
@ -1077,8 +1077,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
if (option_required_reference.nr || option_optional_reference.nr)
|
||||
setup_reference();
|
||||
|
||||
fetch_pattern = value.buf;
|
||||
refspec = parse_fetch_refspec(1, &fetch_pattern);
|
||||
refspec_item_init(&refspec, value.buf, REFSPEC_FETCH);
|
||||
|
||||
strbuf_reset(&value);
|
||||
|
||||
|
@ -1138,7 +1137,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
refs = transport_get_remote_refs(transport, NULL);
|
||||
|
||||
if (refs) {
|
||||
mapped_refs = wanted_peer_refs(refs, refspec);
|
||||
mapped_refs = wanted_peer_refs(refs, &refspec);
|
||||
/*
|
||||
* transport_get_remote_refs() may return refs with null sha-1
|
||||
* in mapped_refs (see struct transport->get_refs_list
|
||||
|
@ -1232,6 +1231,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
strbuf_release(&value);
|
||||
junk_mode = JUNK_LEAVE_ALL;
|
||||
|
||||
free(refspec);
|
||||
refspec_item_clear(&refspec);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "commit.h"
|
||||
#include "object.h"
|
||||
#include "tag.h"
|
||||
|
@ -35,8 +36,7 @@ static int use_done_feature;
|
|||
static int no_data;
|
||||
static int full_tree;
|
||||
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
|
||||
static struct refspec *refspecs;
|
||||
static int refspecs_nr;
|
||||
static struct refspec refspecs = REFSPEC_INIT_FETCH;
|
||||
static int anonymize;
|
||||
|
||||
static int parse_opt_signed_tag_mode(const struct option *opt,
|
||||
|
@ -828,9 +828,9 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
|
|||
if (dwim_ref(e->name, strlen(e->name), &oid, &full_name) != 1)
|
||||
continue;
|
||||
|
||||
if (refspecs) {
|
||||
if (refspecs.nr) {
|
||||
char *private;
|
||||
private = apply_refspecs(refspecs, refspecs_nr, full_name);
|
||||
private = apply_refspecs(&refspecs, full_name);
|
||||
if (private) {
|
||||
free(full_name);
|
||||
full_name = private;
|
||||
|
@ -976,8 +976,8 @@ static void import_marks(char *input_file)
|
|||
static void handle_deletes(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < refspecs_nr; i++) {
|
||||
struct refspec *refspec = &refspecs[i];
|
||||
for (i = 0; i < refspecs.nr; i++) {
|
||||
struct refspec_item *refspec = &refspecs.items[i];
|
||||
if (*refspec->src)
|
||||
continue;
|
||||
|
||||
|
@ -1038,18 +1038,12 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
|||
usage_with_options (fast_export_usage, options);
|
||||
|
||||
if (refspecs_list.nr) {
|
||||
const char **refspecs_str;
|
||||
int i;
|
||||
|
||||
ALLOC_ARRAY(refspecs_str, refspecs_list.nr);
|
||||
for (i = 0; i < refspecs_list.nr; i++)
|
||||
refspecs_str[i] = refspecs_list.items[i].string;
|
||||
|
||||
refspecs_nr = refspecs_list.nr;
|
||||
refspecs = parse_fetch_refspec(refspecs_nr, refspecs_str);
|
||||
refspec_append(&refspecs, refspecs_list.items[i].string);
|
||||
|
||||
string_list_clear(&refspecs_list, 1);
|
||||
free(refspecs_str);
|
||||
}
|
||||
|
||||
if (use_done_feature)
|
||||
|
@ -1088,7 +1082,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
|||
if (use_done_feature)
|
||||
printf("done\n");
|
||||
|
||||
free_refspec(refspecs_nr, refspecs);
|
||||
refspec_clear(&refspecs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
135
builtin/fetch.c
135
builtin/fetch.c
|
@ -5,6 +5,7 @@
|
|||
#include "config.h"
|
||||
#include "repository.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "commit.h"
|
||||
#include "builtin.h"
|
||||
#include "string-list.h"
|
||||
|
@ -59,8 +60,7 @@ static const char *submodule_prefix = "";
|
|||
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;
|
||||
|
||||
|
@ -108,14 +108,12 @@ static int gitmodules_fetch_config(const char *var, const char *value, 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;
|
||||
}
|
||||
|
||||
|
@ -204,7 +202,7 @@ static void add_merge_config(struct ref **head,
|
|||
|
||||
for (i = 0; i < branch->merge_nr; i++) {
|
||||
struct ref *rm, **old_tail = *tail;
|
||||
struct refspec refspec;
|
||||
struct refspec_item refspec;
|
||||
|
||||
for (rm = *head; rm; rm = rm->next) {
|
||||
if (branch_merge_matches(branch, i, rm->name)) {
|
||||
|
@ -341,7 +339,7 @@ static void find_non_local_tags(struct transport *transport,
|
|||
}
|
||||
|
||||
static struct ref *get_ref_map(struct transport *transport,
|
||||
struct refspec *refspecs, int refspec_count,
|
||||
struct refspec *rs,
|
||||
int tags, int *autotags)
|
||||
{
|
||||
int i;
|
||||
|
@ -355,29 +353,26 @@ static struct ref *get_ref_map(struct transport *transport,
|
|||
|
||||
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) {
|
||||
if (rs->nr) {
|
||||
struct refspec *fetch_refspec;
|
||||
int fetch_refspec_nr;
|
||||
|
||||
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) */
|
||||
|
@ -404,17 +399,14 @@ static struct ref *get_ref_map(struct transport *transport,
|
|||
* 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;
|
||||
fetch_refspec_nr = transport->remote->fetch_refspec_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 */
|
||||
|
@ -422,16 +414,16 @@ static struct ref *get_ref_map(struct transport *transport,
|
|||
struct branch *branch = branch_get(NULL);
|
||||
int has_merge = branch_has_merge_config(branch);
|
||||
if (remote &&
|
||||
(remote->fetch_refspec_nr ||
|
||||
(remote->fetch.nr ||
|
||||
/* Note: has_merge implies non-NULL branch->remote_name */
|
||||
(has_merge && !strcmp(branch->remote_name, remote->name)))) {
|
||||
for (i = 0; i < remote->fetch_refspec_nr; i++) {
|
||||
get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0);
|
||||
if (remote->fetch[i].dst &&
|
||||
remote->fetch[i].dst[0])
|
||||
for (i = 0; i < remote->fetch.nr; i++) {
|
||||
get_fetch_map(remote_refs, &remote->fetch.items[i], &tail, 0);
|
||||
if (remote->fetch.items[i].dst &&
|
||||
remote->fetch.items[i].dst[0])
|
||||
*autotags = 1;
|
||||
if (!i && !has_merge && ref_map &&
|
||||
!remote->fetch[0].pattern)
|
||||
!remote->fetch.items[0].pattern)
|
||||
ref_map->fetch_head_status = FETCH_HEAD_MERGE;
|
||||
}
|
||||
/*
|
||||
|
@ -966,11 +958,11 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int prune_refs(struct refspec *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
|
||||
|
@ -1116,7 +1108,7 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
|
|||
}
|
||||
|
||||
static int do_fetch(struct transport *transport,
|
||||
struct refspec *refs, int ref_count)
|
||||
struct refspec *rs)
|
||||
{
|
||||
struct string_list existing_refs = STRING_LIST_INIT_DUP;
|
||||
struct ref *ref_map;
|
||||
|
@ -1140,7 +1132,7 @@ static int do_fetch(struct transport *transport,
|
|||
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);
|
||||
|
||||
|
@ -1164,11 +1156,10 @@ static int do_fetch(struct transport *transport,
|
|||
* 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,
|
||||
transport->remote->fetch_refspec_nr,
|
||||
prune_refs(&transport->remote->fetch,
|
||||
ref_map,
|
||||
transport->url);
|
||||
}
|
||||
|
@ -1357,10 +1348,8 @@ static inline void fetch_one_setup_partial(struct remote *remote)
|
|||
|
||||
static int fetch_one(struct remote *remote, int argc, const char **argv, int prune_tags_ok)
|
||||
{
|
||||
static const char **refs = NULL;
|
||||
struct refspec *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);
|
||||
|
@ -1393,29 +1382,24 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int pru
|
|||
|
||||
maybe_prune_tags = prune_tags_ok && prune_tags;
|
||||
if (maybe_prune_tags && remote_via_config)
|
||||
add_prune_tags_to_fetch_refspec(remote);
|
||||
refspec_append(&remote->fetch, TAG_REFSPEC);
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
if (maybe_prune_tags && (argc || !remote_via_config))
|
||||
refspec_append(&rs, TAG_REFSPEC);
|
||||
|
||||
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++;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1424,9 +1408,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int pru
|
|||
|
||||
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;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "run-command.h"
|
||||
#include "diff.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "commit.h"
|
||||
#include "diffcore.h"
|
||||
#include "revision.h"
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "remote.h"
|
||||
#include "dir.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "revision.h"
|
||||
#include "submodule.h"
|
||||
#include "submodule-config.h"
|
||||
|
@ -679,12 +680,12 @@ static const char *get_upstream_branch(const char *remote)
|
|||
*/
|
||||
static const char *get_tracking_branch(const char *remote, const char *refspec)
|
||||
{
|
||||
struct refspec *spec;
|
||||
struct refspec_item spec;
|
||||
const char *spec_src;
|
||||
const char *merge_branch;
|
||||
|
||||
spec = parse_fetch_refspec(1, &refspec);
|
||||
spec_src = spec->src;
|
||||
refspec_item_init(&spec, refspec, REFSPEC_FETCH);
|
||||
spec_src = spec.src;
|
||||
if (!*spec_src || !strcmp(spec_src, "HEAD"))
|
||||
spec_src = "HEAD";
|
||||
else if (skip_prefix(spec_src, "heads/", &spec_src))
|
||||
|
@ -704,7 +705,7 @@ static const char *get_tracking_branch(const char *remote, const char *refspec)
|
|||
} else
|
||||
merge_branch = NULL;
|
||||
|
||||
free_refspec(1, spec);
|
||||
refspec_item_clear(&spec);
|
||||
return merge_branch;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "cache.h"
|
||||
#include "config.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "run-command.h"
|
||||
#include "builtin.h"
|
||||
#include "remote.h"
|
||||
|
@ -56,19 +57,10 @@ static enum transport_family family;
|
|||
|
||||
static struct push_cas_option cas;
|
||||
|
||||
static const char **refspec;
|
||||
static int refspec_nr;
|
||||
static int refspec_alloc;
|
||||
static struct refspec rs = REFSPEC_INIT_PUSH;
|
||||
|
||||
static struct string_list push_options_config = STRING_LIST_INIT_DUP;
|
||||
|
||||
static void add_refspec(const char *ref)
|
||||
{
|
||||
refspec_nr++;
|
||||
ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
|
||||
refspec[refspec_nr-1] = ref;
|
||||
}
|
||||
|
||||
static const char *map_refspec(const char *ref,
|
||||
struct remote *remote, struct ref *local_refs)
|
||||
{
|
||||
|
@ -78,12 +70,11 @@ static const char *map_refspec(const char *ref,
|
|||
if (count_refspec_match(ref, local_refs, &matched) != 1)
|
||||
return ref;
|
||||
|
||||
if (remote->push) {
|
||||
struct refspec query;
|
||||
memset(&query, 0, sizeof(struct refspec));
|
||||
if (remote->push.nr) {
|
||||
struct refspec_item query;
|
||||
memset(&query, 0, sizeof(struct refspec_item));
|
||||
query.src = matched->name;
|
||||
if (!query_refspecs(remote->push, remote->push_refspec_nr, &query) &&
|
||||
query.dst) {
|
||||
if (!query_refspecs(&remote->push, &query) && query.dst) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addf(&buf, "%s%s:%s",
|
||||
query.force ? "+" : "",
|
||||
|
@ -138,7 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
|
|||
}
|
||||
ref = map_refspec(ref, remote, local_refs);
|
||||
}
|
||||
add_refspec(ref);
|
||||
refspec_append(&rs, ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +217,7 @@ static void setup_push_upstream(struct remote *remote, struct branch *branch,
|
|||
}
|
||||
|
||||
strbuf_addf(&refspec, "%s:%s", branch->refname, branch->merge[0]->src);
|
||||
add_refspec(refspec.buf);
|
||||
refspec_append(&rs, refspec.buf);
|
||||
}
|
||||
|
||||
static void setup_push_current(struct remote *remote, struct branch *branch)
|
||||
|
@ -236,7 +227,7 @@ static void setup_push_current(struct remote *remote, struct branch *branch)
|
|||
if (!branch)
|
||||
die(_(message_detached_head_die), remote->name);
|
||||
strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname);
|
||||
add_refspec(refspec.buf);
|
||||
refspec_append(&rs, refspec.buf);
|
||||
}
|
||||
|
||||
static int is_workflow_triangular(struct remote *remote)
|
||||
|
@ -253,7 +244,7 @@ static void setup_default_push_refspecs(struct remote *remote)
|
|||
switch (push_default) {
|
||||
default:
|
||||
case PUSH_DEFAULT_MATCHING:
|
||||
add_refspec(":");
|
||||
refspec_append(&rs, ":");
|
||||
break;
|
||||
|
||||
case PUSH_DEFAULT_UNSPECIFIED:
|
||||
|
@ -341,7 +332,8 @@ static void advise_ref_needs_force(void)
|
|||
advise(_(message_advice_ref_needs_force));
|
||||
}
|
||||
|
||||
static int push_with_options(struct transport *transport, int flags)
|
||||
static int push_with_options(struct transport *transport, struct refspec *rs,
|
||||
int flags)
|
||||
{
|
||||
int err;
|
||||
unsigned int reject_reasons;
|
||||
|
@ -363,8 +355,7 @@ static int push_with_options(struct transport *transport, int flags)
|
|||
|
||||
if (verbosity > 0)
|
||||
fprintf(stderr, _("Pushing to %s\n"), transport->url);
|
||||
err = transport_push(transport, refspec_nr, refspec, flags,
|
||||
&reject_reasons);
|
||||
err = transport_push(transport, rs, flags, &reject_reasons);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR));
|
||||
error(_("failed to push some refs to '%s'"), transport->url);
|
||||
|
@ -397,6 +388,7 @@ static int do_push(const char *repo, int flags,
|
|||
struct remote *remote = pushremote_get(repo);
|
||||
const char **url;
|
||||
int url_nr;
|
||||
struct refspec *push_refspec = &rs;
|
||||
|
||||
if (!remote) {
|
||||
if (repo)
|
||||
|
@ -417,27 +409,9 @@ static int do_push(const char *repo, int flags,
|
|||
if (push_options->nr)
|
||||
flags |= TRANSPORT_PUSH_OPTIONS;
|
||||
|
||||
if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
|
||||
if (!strcmp(*refspec, "refs/tags/*"))
|
||||
return error(_("--all and --tags are incompatible"));
|
||||
return error(_("--all can't be combined with refspecs"));
|
||||
}
|
||||
|
||||
if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
|
||||
if (!strcmp(*refspec, "refs/tags/*"))
|
||||
return error(_("--mirror and --tags are incompatible"));
|
||||
return error(_("--mirror can't be combined with refspecs"));
|
||||
}
|
||||
|
||||
if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
|
||||
(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
|
||||
return error(_("--all and --mirror are incompatible"));
|
||||
}
|
||||
|
||||
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
|
||||
if (remote->push_refspec_nr) {
|
||||
refspec = remote->push_refspec;
|
||||
refspec_nr = remote->push_refspec_nr;
|
||||
if (!push_refspec->nr && !(flags & TRANSPORT_PUSH_ALL)) {
|
||||
if (remote->push.nr) {
|
||||
push_refspec = &remote->push;
|
||||
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
|
||||
setup_default_push_refspecs(remote);
|
||||
}
|
||||
|
@ -449,7 +423,7 @@ static int do_push(const char *repo, int flags,
|
|||
transport_get(remote, url[i]);
|
||||
if (flags & TRANSPORT_PUSH_OPTIONS)
|
||||
transport->push_options = push_options;
|
||||
if (push_with_options(transport, flags))
|
||||
if (push_with_options(transport, push_refspec, flags))
|
||||
errs++;
|
||||
}
|
||||
} else {
|
||||
|
@ -457,7 +431,7 @@ static int do_push(const char *repo, int flags,
|
|||
transport_get(remote, NULL);
|
||||
if (flags & TRANSPORT_PUSH_OPTIONS)
|
||||
transport->push_options = push_options;
|
||||
if (push_with_options(transport, flags))
|
||||
if (push_with_options(transport, push_refspec, flags))
|
||||
errs++;
|
||||
}
|
||||
return !!errs;
|
||||
|
@ -625,6 +599,20 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
|||
die(_("--delete is incompatible with --all, --mirror and --tags"));
|
||||
if (deleterefs && argc < 2)
|
||||
die(_("--delete doesn't make sense without any refs"));
|
||||
if (flags & TRANSPORT_PUSH_ALL) {
|
||||
if (tags)
|
||||
die(_("--all and --tags are incompatible"));
|
||||
if (argc >= 2)
|
||||
die(_("--all can't be combined with refspecs"));
|
||||
}
|
||||
if (flags & TRANSPORT_PUSH_MIRROR) {
|
||||
if (tags)
|
||||
die(_("--mirror and --tags are incompatible"));
|
||||
if (argc >= 2)
|
||||
die(_("--mirror can't be combined with refspecs"));
|
||||
}
|
||||
if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
|
||||
die(_("--all and --mirror are incompatible"));
|
||||
|
||||
if (recurse_submodules == RECURSE_SUBMODULES_CHECK)
|
||||
flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
|
||||
|
@ -634,7 +622,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
|||
flags |= TRANSPORT_RECURSE_SUBMODULES_ONLY;
|
||||
|
||||
if (tags)
|
||||
add_refspec("refs/tags/*");
|
||||
refspec_append(&rs, "refs/tags/*");
|
||||
|
||||
if (argc > 0) {
|
||||
repo = argv[0];
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "strbuf.h"
|
||||
#include "run-command.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "argv-array.h"
|
||||
|
||||
static const char * const builtin_remote_usage[] = {
|
||||
|
@ -336,10 +337,10 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
|
|||
struct ref *ref, *stale_refs;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < states->remote->fetch_refspec_nr; i++)
|
||||
if (get_fetch_map(remote_refs, states->remote->fetch + i, &tail, 1))
|
||||
for (i = 0; i < states->remote->fetch.nr; i++)
|
||||
if (get_fetch_map(remote_refs, &states->remote->fetch.items[i], &tail, 1))
|
||||
die(_("Could not get fetch map for refspec %s"),
|
||||
states->remote->fetch_refspec[i]);
|
||||
states->remote->fetch.raw[i]);
|
||||
|
||||
states->new_refs.strdup_strings = 1;
|
||||
states->tracked.strdup_strings = 1;
|
||||
|
@ -350,8 +351,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
|
|||
else
|
||||
string_list_append(&states->tracked, abbrev_branch(ref->name));
|
||||
}
|
||||
stale_refs = get_stale_heads(states->remote->fetch,
|
||||
states->remote->fetch_refspec_nr, fetch_map);
|
||||
stale_refs = get_stale_heads(&states->remote->fetch, fetch_map);
|
||||
for (ref = stale_refs; ref; ref = ref->next) {
|
||||
struct string_list_item *item =
|
||||
string_list_append(&states->stale, abbrev_branch(ref->name));
|
||||
|
@ -391,8 +391,7 @@ static int get_push_ref_states(const struct ref *remote_refs,
|
|||
local_refs = get_local_heads();
|
||||
push_map = copy_ref_list(remote_refs);
|
||||
|
||||
match_push_refs(local_refs, &push_map, remote->push_refspec_nr,
|
||||
remote->push_refspec, MATCH_REFS_NONE);
|
||||
match_push_refs(local_refs, &push_map, &remote->push, MATCH_REFS_NONE);
|
||||
|
||||
states->push.strdup_strings = 1;
|
||||
for (ref = push_map; ref; ref = ref->next) {
|
||||
|
@ -438,14 +437,14 @@ static int get_push_ref_states_noquery(struct ref_states *states)
|
|||
return 0;
|
||||
|
||||
states->push.strdup_strings = 1;
|
||||
if (!remote->push_refspec_nr) {
|
||||
if (!remote->push.nr) {
|
||||
item = string_list_append(&states->push, _("(matching)"));
|
||||
info = item->util = xcalloc(1, sizeof(struct push_info));
|
||||
info->status = PUSH_STATUS_NOTQUERIED;
|
||||
info->dest = xstrdup(item->string);
|
||||
}
|
||||
for (i = 0; i < remote->push_refspec_nr; i++) {
|
||||
struct refspec *spec = remote->push + i;
|
||||
for (i = 0; i < remote->push.nr; i++) {
|
||||
const struct refspec_item *spec = &remote->push.items[i];
|
||||
if (spec->matching)
|
||||
item = string_list_append(&states->push, _("(matching)"));
|
||||
else if (strlen(spec->src))
|
||||
|
@ -465,7 +464,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat
|
|||
{
|
||||
struct ref *ref, *matches;
|
||||
struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
|
||||
struct refspec refspec;
|
||||
struct refspec_item refspec;
|
||||
|
||||
refspec.force = 0;
|
||||
refspec.pattern = 1;
|
||||
|
@ -518,7 +517,7 @@ static int add_branch_for_removal(const char *refname,
|
|||
const struct object_id *oid, int flags, void *cb_data)
|
||||
{
|
||||
struct branches_for_remote *branches = cb_data;
|
||||
struct refspec refspec;
|
||||
struct refspec_item refspec;
|
||||
struct known_remote *kr;
|
||||
|
||||
memset(&refspec, 0, sizeof(refspec));
|
||||
|
@ -589,12 +588,12 @@ static int migrate_file(struct remote *remote)
|
|||
git_config_set_multivar(buf.buf, remote->url[i], "^$", 0);
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "remote.%s.push", remote->name);
|
||||
for (i = 0; i < remote->push_refspec_nr; i++)
|
||||
git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0);
|
||||
for (i = 0; i < remote->push.raw_nr; i++)
|
||||
git_config_set_multivar(buf.buf, remote->push.raw[i], "^$", 0);
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "remote.%s.fetch", remote->name);
|
||||
for (i = 0; i < remote->fetch_refspec_nr; i++)
|
||||
git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0);
|
||||
for (i = 0; i < remote->fetch.raw_nr; i++)
|
||||
git_config_set_multivar(buf.buf, remote->fetch.raw[i], "^$", 0);
|
||||
if (remote->origin == REMOTE_REMOTES)
|
||||
unlink_or_warn(git_path("remotes/%s", remote->name));
|
||||
else if (remote->origin == REMOTE_BRANCHES)
|
||||
|
@ -649,11 +648,11 @@ static int mv(int argc, const char **argv)
|
|||
strbuf_addf(&buf, "remote.%s.fetch", rename.new_name);
|
||||
git_config_set_multivar(buf.buf, NULL, NULL, 1);
|
||||
strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
|
||||
for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
|
||||
for (i = 0; i < oldremote->fetch.raw_nr; i++) {
|
||||
char *ptr;
|
||||
|
||||
strbuf_reset(&buf2);
|
||||
strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
|
||||
strbuf_addstr(&buf2, oldremote->fetch.raw[i]);
|
||||
ptr = strstr(buf2.buf, old_remote_context.buf);
|
||||
if (ptr) {
|
||||
refspec_updated = 1;
|
||||
|
@ -837,7 +836,7 @@ static int append_ref_to_tracked_list(const char *refname,
|
|||
const struct object_id *oid, int flags, void *cb_data)
|
||||
{
|
||||
struct ref_states *states = cb_data;
|
||||
struct refspec refspec;
|
||||
struct refspec_item refspec;
|
||||
|
||||
if (flags & REF_ISSYMREF)
|
||||
return 0;
|
||||
|
|
|
@ -126,8 +126,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
|
|||
|
||||
int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i, nr_refspecs = 0;
|
||||
const char **refspecs = NULL;
|
||||
struct refspec rs = REFSPEC_INIT_PUSH;
|
||||
const char *remote_name = NULL;
|
||||
struct remote *remote = NULL;
|
||||
const char *dest = NULL;
|
||||
|
@ -189,8 +188,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
|||
argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
|
||||
if (argc > 0) {
|
||||
dest = argv[0];
|
||||
refspecs = (const char **)(argv + 1);
|
||||
nr_refspecs = argc - 1;
|
||||
refspec_appendn(&rs, argv + 1, argc - 1);
|
||||
}
|
||||
|
||||
if (!dest)
|
||||
|
@ -209,31 +207,23 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
|||
args.push_options = push_options.nr ? &push_options : NULL;
|
||||
|
||||
if (from_stdin) {
|
||||
struct argv_array all_refspecs = ARGV_ARRAY_INIT;
|
||||
|
||||
for (i = 0; i < nr_refspecs; i++)
|
||||
argv_array_push(&all_refspecs, refspecs[i]);
|
||||
|
||||
if (args.stateless_rpc) {
|
||||
const char *buf;
|
||||
while ((buf = packet_read_line(0, NULL)))
|
||||
argv_array_push(&all_refspecs, buf);
|
||||
refspec_append(&rs, buf);
|
||||
} else {
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
while (strbuf_getline(&line, stdin) != EOF)
|
||||
argv_array_push(&all_refspecs, line.buf);
|
||||
refspec_append(&rs, line.buf);
|
||||
strbuf_release(&line);
|
||||
}
|
||||
|
||||
refspecs = all_refspecs.argv;
|
||||
nr_refspecs = all_refspecs.argc;
|
||||
}
|
||||
|
||||
/*
|
||||
* --all and --mirror are incompatible; neither makes sense
|
||||
* with any refspecs.
|
||||
*/
|
||||
if ((nr_refspecs > 0 && (send_all || args.send_mirror)) ||
|
||||
if ((rs.nr > 0 && (send_all || args.send_mirror)) ||
|
||||
(send_all && args.send_mirror))
|
||||
usage_with_options(send_pack_usage, options);
|
||||
|
||||
|
@ -275,8 +265,6 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
|||
BUG("unknown protocol version");
|
||||
}
|
||||
|
||||
transport_verify_remote_names(nr_refspecs, refspecs);
|
||||
|
||||
local_refs = get_local_heads();
|
||||
|
||||
flags = MATCH_REFS_NONE;
|
||||
|
@ -287,7 +275,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
|||
flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
/* match them up */
|
||||
if (match_push_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
|
||||
if (match_push_refs(local_refs, &remote_refs, &rs, flags))
|
||||
return -1;
|
||||
|
||||
if (!is_empty_cas(&cas))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "run-command.h"
|
||||
#include "remote.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "connect.h"
|
||||
#include "revision.h"
|
||||
#include "diffcore.h"
|
||||
|
@ -1753,13 +1754,14 @@ static int push_check(int argc, const char **argv, const char *prefix)
|
|||
|
||||
/* Check the refspec */
|
||||
if (argc > 2) {
|
||||
int i, refspec_nr = argc - 2;
|
||||
int i;
|
||||
struct ref *local_refs = get_local_heads();
|
||||
struct refspec *refspec = parse_push_refspec(refspec_nr,
|
||||
argv + 2);
|
||||
struct refspec refspec = REFSPEC_INIT_PUSH;
|
||||
|
||||
for (i = 0; i < refspec_nr; i++) {
|
||||
struct refspec *rs = refspec + i;
|
||||
refspec_appendn(&refspec, argv + 2, argc - 2);
|
||||
|
||||
for (i = 0; i < refspec.nr; i++) {
|
||||
const struct refspec_item *rs = &refspec.items[i];
|
||||
|
||||
if (rs->pattern || rs->matching)
|
||||
continue;
|
||||
|
@ -1786,7 +1788,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
|
|||
rs->src);
|
||||
}
|
||||
}
|
||||
free_refspec(refspec_nr, refspec);
|
||||
refspec_clear(&refspec);
|
||||
}
|
||||
free(head);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "cache.h"
|
||||
#include "remote.h"
|
||||
#include "refspec.h"
|
||||
#include "checkout.h"
|
||||
|
||||
struct tracking_name_data {
|
||||
|
@ -12,8 +13,8 @@ struct tracking_name_data {
|
|||
static int check_tracking_name(struct remote *remote, void *cb_data)
|
||||
{
|
||||
struct tracking_name_data *cb = cb_data;
|
||||
struct refspec query;
|
||||
memset(&query, 0, sizeof(struct refspec));
|
||||
struct refspec_item query;
|
||||
memset(&query, 0, sizeof(struct refspec_item));
|
||||
query.src = cb->src_ref;
|
||||
if (remote_find_tracking(remote, &query) ||
|
||||
get_oid(query.dst, cb->dst_oid)) {
|
||||
|
|
18
http-push.c
18
http-push.c
|
@ -1692,8 +1692,7 @@ int cmd_main(int argc, const char **argv)
|
|||
{
|
||||
struct transfer_request *request;
|
||||
struct transfer_request *next_request;
|
||||
int nr_refspec = 0;
|
||||
const char **refspec = NULL;
|
||||
struct refspec rs = REFSPEC_INIT_PUSH;
|
||||
struct remote_lock *ref_lock = NULL;
|
||||
struct remote_lock *info_ref_lock = NULL;
|
||||
struct rev_info revs;
|
||||
|
@ -1756,8 +1755,7 @@ int cmd_main(int argc, const char **argv)
|
|||
}
|
||||
continue;
|
||||
}
|
||||
refspec = argv;
|
||||
nr_refspec = argc - i;
|
||||
refspec_appendn(&rs, argv, argc - i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1768,7 +1766,7 @@ int cmd_main(int argc, const char **argv)
|
|||
if (!repo->url)
|
||||
usage(http_push_usage);
|
||||
|
||||
if (delete_branch && nr_refspec != 1)
|
||||
if (delete_branch && rs.nr != 1)
|
||||
die("You must specify only one branch name when deleting a remote branch");
|
||||
|
||||
setup_git_directory();
|
||||
|
@ -1814,18 +1812,18 @@ int cmd_main(int argc, const char **argv)
|
|||
|
||||
/* Remove a remote branch if -d or -D was specified */
|
||||
if (delete_branch) {
|
||||
if (delete_remote_branch(refspec[0], force_delete) == -1) {
|
||||
const char *branch = rs.items[i].src;
|
||||
if (delete_remote_branch(branch, force_delete) == -1) {
|
||||
fprintf(stderr, "Unable to delete remote branch %s\n",
|
||||
refspec[0]);
|
||||
branch);
|
||||
if (helper_status)
|
||||
printf("error %s cannot remove\n", refspec[0]);
|
||||
printf("error %s cannot remove\n", branch);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* match them up */
|
||||
if (match_push_refs(local_refs, &remote_refs,
|
||||
nr_refspec, (const char **) refspec, push_all)) {
|
||||
if (match_push_refs(local_refs, &remote_refs, &rs, push_all)) {
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
#include "cache.h"
|
||||
#include "argv-array.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
|
||||
static struct refspec_item s_tag_refspec = {
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
"refs/tags/*",
|
||||
"refs/tags/*"
|
||||
};
|
||||
|
||||
/* See TAG_REFSPEC for the string version */
|
||||
const struct refspec_item *tag_refspec = &s_tag_refspec;
|
||||
|
||||
/*
|
||||
* Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
|
||||
* Returns 1 if successful and 0 if the refspec is invalid.
|
||||
*/
|
||||
static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch)
|
||||
{
|
||||
size_t llen;
|
||||
int is_glob;
|
||||
const char *lhs, *rhs;
|
||||
int flags;
|
||||
|
||||
is_glob = 0;
|
||||
|
||||
lhs = refspec;
|
||||
if (*lhs == '+') {
|
||||
item->force = 1;
|
||||
lhs++;
|
||||
}
|
||||
|
||||
rhs = strrchr(lhs, ':');
|
||||
|
||||
/*
|
||||
* Before going on, special case ":" (or "+:") as a refspec
|
||||
* for pushing matching refs.
|
||||
*/
|
||||
if (!fetch && rhs == lhs && rhs[1] == '\0') {
|
||||
item->matching = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (rhs) {
|
||||
size_t rlen = strlen(++rhs);
|
||||
is_glob = (1 <= rlen && strchr(rhs, '*'));
|
||||
item->dst = xstrndup(rhs, rlen);
|
||||
}
|
||||
|
||||
llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
|
||||
if (1 <= llen && memchr(lhs, '*', llen)) {
|
||||
if ((rhs && !is_glob) || (!rhs && fetch))
|
||||
return 0;
|
||||
is_glob = 1;
|
||||
} else if (rhs && is_glob) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
item->pattern = is_glob;
|
||||
item->src = xstrndup(lhs, llen);
|
||||
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
|
||||
|
||||
if (fetch) {
|
||||
struct object_id unused;
|
||||
|
||||
/* LHS */
|
||||
if (!*item->src)
|
||||
; /* empty is ok; it means "HEAD" */
|
||||
else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(item->src, &unused))
|
||||
item->exact_sha1 = 1; /* ok */
|
||||
else if (!check_refname_format(item->src, flags))
|
||||
; /* valid looking ref is ok */
|
||||
else
|
||||
return 0;
|
||||
/* RHS */
|
||||
if (!item->dst)
|
||||
; /* missing is ok; it is the same as empty */
|
||||
else if (!*item->dst)
|
||||
; /* empty is ok; it means "do not store" */
|
||||
else if (!check_refname_format(item->dst, flags))
|
||||
; /* valid looking ref is ok */
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
/*
|
||||
* LHS
|
||||
* - empty is allowed; it means delete.
|
||||
* - when wildcarded, it must be a valid looking ref.
|
||||
* - otherwise, it must be an extended SHA-1, but
|
||||
* there is no existing way to validate this.
|
||||
*/
|
||||
if (!*item->src)
|
||||
; /* empty is ok */
|
||||
else if (is_glob) {
|
||||
if (check_refname_format(item->src, flags))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
; /* anything goes, for now */
|
||||
/*
|
||||
* RHS
|
||||
* - missing is allowed, but LHS then must be a
|
||||
* valid looking ref.
|
||||
* - empty is not allowed.
|
||||
* - otherwise it must be a valid looking ref.
|
||||
*/
|
||||
if (!item->dst) {
|
||||
if (check_refname_format(item->src, flags))
|
||||
return 0;
|
||||
} else if (!*item->dst) {
|
||||
return 0;
|
||||
} else {
|
||||
if (check_refname_format(item->dst, flags))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void refspec_item_init(struct refspec_item *item, const char *refspec, int fetch)
|
||||
{
|
||||
memset(item, 0, sizeof(*item));
|
||||
|
||||
if (!parse_refspec(item, refspec, fetch))
|
||||
die("Invalid refspec '%s'", refspec);
|
||||
}
|
||||
|
||||
void refspec_item_clear(struct refspec_item *item)
|
||||
{
|
||||
FREE_AND_NULL(item->src);
|
||||
FREE_AND_NULL(item->dst);
|
||||
item->force = 0;
|
||||
item->pattern = 0;
|
||||
item->matching = 0;
|
||||
item->exact_sha1 = 0;
|
||||
}
|
||||
|
||||
void refspec_init(struct refspec *rs, int fetch)
|
||||
{
|
||||
memset(rs, 0, sizeof(*rs));
|
||||
rs->fetch = fetch;
|
||||
}
|
||||
|
||||
void refspec_append(struct refspec *rs, const char *refspec)
|
||||
{
|
||||
struct refspec_item item;
|
||||
|
||||
refspec_item_init(&item, refspec, rs->fetch);
|
||||
|
||||
ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc);
|
||||
rs->items[rs->nr++] = item;
|
||||
|
||||
ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc);
|
||||
rs->raw[rs->raw_nr++] = xstrdup(refspec);
|
||||
}
|
||||
|
||||
void refspec_appendn(struct refspec *rs, const char **refspecs, int nr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nr; i++)
|
||||
refspec_append(rs, refspecs[i]);
|
||||
}
|
||||
|
||||
void refspec_clear(struct refspec *rs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rs->nr; i++)
|
||||
refspec_item_clear(&rs->items[i]);
|
||||
|
||||
FREE_AND_NULL(rs->items);
|
||||
rs->alloc = 0;
|
||||
rs->nr = 0;
|
||||
|
||||
for (i = 0; i < rs->raw_nr; i++)
|
||||
free((char *)rs->raw[i]);
|
||||
FREE_AND_NULL(rs->raw);
|
||||
rs->raw_alloc = 0;
|
||||
rs->raw_nr = 0;
|
||||
|
||||
rs->fetch = 0;
|
||||
}
|
||||
|
||||
int valid_fetch_refspec(const char *fetch_refspec_str)
|
||||
{
|
||||
struct refspec_item refspec;
|
||||
int ret = parse_refspec(&refspec, fetch_refspec_str, REFSPEC_FETCH);
|
||||
refspec_item_clear(&refspec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void refspec_ref_prefixes(const struct refspec *rs,
|
||||
struct argv_array *ref_prefixes)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < rs->nr; i++) {
|
||||
const struct refspec_item *item = &rs->items[i];
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (rs->fetch == REFSPEC_FETCH)
|
||||
prefix = item->src;
|
||||
else if (item->dst)
|
||||
prefix = item->dst;
|
||||
else if (item->src && !item->exact_sha1)
|
||||
prefix = item->src;
|
||||
|
||||
if (prefix) {
|
||||
if (item->pattern) {
|
||||
const char *glob = strchr(prefix, '*');
|
||||
argv_array_pushf(ref_prefixes, "%.*s",
|
||||
(int)(glob - prefix),
|
||||
prefix);
|
||||
} else {
|
||||
expand_ref_prefix(ref_prefixes, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef REFSPEC_H
|
||||
#define REFSPEC_H
|
||||
|
||||
#define TAG_REFSPEC "refs/tags/*:refs/tags/*"
|
||||
extern const struct refspec_item *tag_refspec;
|
||||
|
||||
struct refspec_item {
|
||||
unsigned force : 1;
|
||||
unsigned pattern : 1;
|
||||
unsigned matching : 1;
|
||||
unsigned exact_sha1 : 1;
|
||||
|
||||
char *src;
|
||||
char *dst;
|
||||
};
|
||||
|
||||
#define REFSPEC_FETCH 1
|
||||
#define REFSPEC_PUSH 0
|
||||
|
||||
#define REFSPEC_INIT_FETCH { .fetch = REFSPEC_FETCH }
|
||||
#define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH }
|
||||
|
||||
struct refspec {
|
||||
struct refspec_item *items;
|
||||
int alloc;
|
||||
int nr;
|
||||
|
||||
const char **raw;
|
||||
int raw_alloc;
|
||||
int raw_nr;
|
||||
|
||||
int fetch;
|
||||
};
|
||||
|
||||
void refspec_item_init(struct refspec_item *item, const char *refspec, int fetch);
|
||||
void refspec_item_clear(struct refspec_item *item);
|
||||
void refspec_init(struct refspec *rs, int fetch);
|
||||
void refspec_append(struct refspec *rs, const char *refspec);
|
||||
void refspec_appendn(struct refspec *rs, const char **refspecs, int nr);
|
||||
void refspec_clear(struct refspec *rs);
|
||||
|
||||
int valid_fetch_refspec(const char *refspec);
|
||||
|
||||
struct argv_array;
|
||||
void refspec_ref_prefixes(const struct refspec *rs,
|
||||
struct argv_array *ref_prefixes);
|
||||
|
||||
#endif /* REFSPEC_H */
|
353
remote.c
353
remote.c
|
@ -2,6 +2,7 @@
|
|||
#include "config.h"
|
||||
#include "remote.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
|
@ -13,18 +14,6 @@
|
|||
|
||||
enum map_direction { FROM_SRC, FROM_DST };
|
||||
|
||||
static struct refspec s_tag_refspec = {
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
"refs/tags/*",
|
||||
"refs/tags/*"
|
||||
};
|
||||
|
||||
/* See TAG_REFSPEC for the string version */
|
||||
const struct refspec *tag_refspec = &s_tag_refspec;
|
||||
|
||||
struct counted_string {
|
||||
size_t len;
|
||||
const char *s;
|
||||
|
@ -88,33 +77,6 @@ static const char *alias_url(const char *url, struct rewrites *r)
|
|||
return xstrfmt("%s%s", r->rewrite[longest_i]->base, url + longest->len);
|
||||
}
|
||||
|
||||
static void add_push_refspec(struct remote *remote, const char *ref)
|
||||
{
|
||||
ALLOC_GROW(remote->push_refspec,
|
||||
remote->push_refspec_nr + 1,
|
||||
remote->push_refspec_alloc);
|
||||
remote->push_refspec[remote->push_refspec_nr++] = ref;
|
||||
}
|
||||
|
||||
static void add_fetch_refspec(struct remote *remote, const char *ref)
|
||||
{
|
||||
ALLOC_GROW(remote->fetch_refspec,
|
||||
remote->fetch_refspec_nr + 1,
|
||||
remote->fetch_refspec_alloc);
|
||||
remote->fetch_refspec[remote->fetch_refspec_nr++] = ref;
|
||||
}
|
||||
|
||||
void add_prune_tags_to_fetch_refspec(struct remote *remote)
|
||||
{
|
||||
int nr = remote->fetch_refspec_nr;
|
||||
int bufsize = nr + 1;
|
||||
int size = sizeof(struct refspec);
|
||||
|
||||
remote->fetch = xrealloc(remote->fetch, size * bufsize);
|
||||
memcpy(&remote->fetch[nr], tag_refspec, size);
|
||||
add_fetch_refspec(remote, xstrdup(TAG_REFSPEC));
|
||||
}
|
||||
|
||||
static void add_url(struct remote *remote, const char *url)
|
||||
{
|
||||
ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
|
||||
|
@ -186,9 +148,12 @@ static struct remote *make_remote(const char *name, int len)
|
|||
ret = xcalloc(1, sizeof(struct remote));
|
||||
ret->prune = -1; /* unspecified */
|
||||
ret->prune_tags = -1; /* unspecified */
|
||||
ret->name = xstrndup(name, len);
|
||||
refspec_init(&ret->push, REFSPEC_PUSH);
|
||||
refspec_init(&ret->fetch, REFSPEC_FETCH);
|
||||
|
||||
ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
|
||||
remotes[remotes_nr++] = ret;
|
||||
ret->name = xstrndup(name, len);
|
||||
|
||||
hashmap_entry_init(ret, lookup_entry.hash);
|
||||
replaced = hashmap_put(&remotes_hash, ret);
|
||||
|
@ -286,9 +251,9 @@ static void read_remotes_file(struct remote *remote)
|
|||
if (skip_prefix(buf.buf, "URL:", &v))
|
||||
add_url_alias(remote, xstrdup(skip_spaces(v)));
|
||||
else if (skip_prefix(buf.buf, "Push:", &v))
|
||||
add_push_refspec(remote, xstrdup(skip_spaces(v)));
|
||||
refspec_append(&remote->push, skip_spaces(v));
|
||||
else if (skip_prefix(buf.buf, "Pull:", &v))
|
||||
add_fetch_refspec(remote, xstrdup(skip_spaces(v)));
|
||||
refspec_append(&remote->fetch, skip_spaces(v));
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
fclose(f);
|
||||
|
@ -327,15 +292,19 @@ static void read_branches_file(struct remote *remote)
|
|||
frag = "master";
|
||||
|
||||
add_url_alias(remote, strbuf_detach(&buf, NULL));
|
||||
add_fetch_refspec(remote, xstrfmt("refs/heads/%s:refs/heads/%s",
|
||||
frag, remote->name));
|
||||
strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s",
|
||||
frag, remote->name);
|
||||
refspec_append(&remote->fetch, buf.buf);
|
||||
|
||||
/*
|
||||
* Cogito compatible push: push current HEAD to remote #branch
|
||||
* (master if missing)
|
||||
*/
|
||||
add_push_refspec(remote, xstrfmt("HEAD:refs/heads/%s", frag));
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
|
||||
refspec_append(&remote->push, buf.buf);
|
||||
remote->fetch_tags = 1; /* always auto-follow */
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
static int handle_config(const char *key, const char *value, void *cb)
|
||||
|
@ -420,12 +389,14 @@ static int handle_config(const char *key, const char *value, void *cb)
|
|||
const char *v;
|
||||
if (git_config_string(&v, key, value))
|
||||
return -1;
|
||||
add_push_refspec(remote, v);
|
||||
refspec_append(&remote->push, v);
|
||||
free((char *)v);
|
||||
} else if (!strcmp(subkey, "fetch")) {
|
||||
const char *v;
|
||||
if (git_config_string(&v, key, value))
|
||||
return -1;
|
||||
add_fetch_refspec(remote, v);
|
||||
refspec_append(&remote->fetch, v);
|
||||
free((char *)v);
|
||||
} else if (!strcmp(subkey, "receivepack")) {
|
||||
const char *v;
|
||||
if (git_config_string(&v, key, value))
|
||||
|
@ -499,158 +470,6 @@ static void read_config(void)
|
|||
alias_all_urls();
|
||||
}
|
||||
|
||||
static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
|
||||
{
|
||||
int i;
|
||||
struct refspec *rs = xcalloc(nr_refspec, sizeof(*rs));
|
||||
|
||||
for (i = 0; i < nr_refspec; i++) {
|
||||
size_t llen;
|
||||
int is_glob;
|
||||
const char *lhs, *rhs;
|
||||
int flags;
|
||||
|
||||
is_glob = 0;
|
||||
|
||||
lhs = refspec[i];
|
||||
if (*lhs == '+') {
|
||||
rs[i].force = 1;
|
||||
lhs++;
|
||||
}
|
||||
|
||||
rhs = strrchr(lhs, ':');
|
||||
|
||||
/*
|
||||
* Before going on, special case ":" (or "+:") as a refspec
|
||||
* for pushing matching refs.
|
||||
*/
|
||||
if (!fetch && rhs == lhs && rhs[1] == '\0') {
|
||||
rs[i].matching = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rhs) {
|
||||
size_t rlen = strlen(++rhs);
|
||||
is_glob = (1 <= rlen && strchr(rhs, '*'));
|
||||
rs[i].dst = xstrndup(rhs, rlen);
|
||||
}
|
||||
|
||||
llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
|
||||
if (1 <= llen && memchr(lhs, '*', llen)) {
|
||||
if ((rhs && !is_glob) || (!rhs && fetch))
|
||||
goto invalid;
|
||||
is_glob = 1;
|
||||
} else if (rhs && is_glob) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
rs[i].pattern = is_glob;
|
||||
rs[i].src = xstrndup(lhs, llen);
|
||||
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
|
||||
|
||||
if (fetch) {
|
||||
struct object_id unused;
|
||||
|
||||
/* LHS */
|
||||
if (!*rs[i].src)
|
||||
; /* empty is ok; it means "HEAD" */
|
||||
else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(rs[i].src, &unused))
|
||||
rs[i].exact_sha1 = 1; /* ok */
|
||||
else if (!check_refname_format(rs[i].src, flags))
|
||||
; /* valid looking ref is ok */
|
||||
else
|
||||
goto invalid;
|
||||
/* RHS */
|
||||
if (!rs[i].dst)
|
||||
; /* missing is ok; it is the same as empty */
|
||||
else if (!*rs[i].dst)
|
||||
; /* empty is ok; it means "do not store" */
|
||||
else if (!check_refname_format(rs[i].dst, flags))
|
||||
; /* valid looking ref is ok */
|
||||
else
|
||||
goto invalid;
|
||||
} else {
|
||||
/*
|
||||
* LHS
|
||||
* - empty is allowed; it means delete.
|
||||
* - when wildcarded, it must be a valid looking ref.
|
||||
* - otherwise, it must be an extended SHA-1, but
|
||||
* there is no existing way to validate this.
|
||||
*/
|
||||
if (!*rs[i].src)
|
||||
; /* empty is ok */
|
||||
else if (is_glob) {
|
||||
if (check_refname_format(rs[i].src, flags))
|
||||
goto invalid;
|
||||
}
|
||||
else
|
||||
; /* anything goes, for now */
|
||||
/*
|
||||
* RHS
|
||||
* - missing is allowed, but LHS then must be a
|
||||
* valid looking ref.
|
||||
* - empty is not allowed.
|
||||
* - otherwise it must be a valid looking ref.
|
||||
*/
|
||||
if (!rs[i].dst) {
|
||||
if (check_refname_format(rs[i].src, flags))
|
||||
goto invalid;
|
||||
} else if (!*rs[i].dst) {
|
||||
goto invalid;
|
||||
} else {
|
||||
if (check_refname_format(rs[i].dst, flags))
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
|
||||
invalid:
|
||||
if (verify) {
|
||||
/*
|
||||
* nr_refspec must be greater than zero and i must be valid
|
||||
* since it is only possible to reach this point from within
|
||||
* the for loop above.
|
||||
*/
|
||||
free_refspec(i+1, rs);
|
||||
return NULL;
|
||||
}
|
||||
die("Invalid refspec '%s'", refspec[i]);
|
||||
}
|
||||
|
||||
int valid_fetch_refspec(const char *fetch_refspec_str)
|
||||
{
|
||||
struct refspec *refspec;
|
||||
|
||||
refspec = parse_refspec_internal(1, &fetch_refspec_str, 1, 1);
|
||||
free_refspec(1, refspec);
|
||||
return !!refspec;
|
||||
}
|
||||
|
||||
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec)
|
||||
{
|
||||
return parse_refspec_internal(nr_refspec, refspec, 1, 0);
|
||||
}
|
||||
|
||||
struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
|
||||
{
|
||||
return parse_refspec_internal(nr_refspec, refspec, 0, 0);
|
||||
}
|
||||
|
||||
void free_refspec(int nr_refspec, struct refspec *refspec)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!refspec)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nr_refspec; i++) {
|
||||
free(refspec[i].src);
|
||||
free(refspec[i].dst);
|
||||
}
|
||||
free(refspec);
|
||||
}
|
||||
|
||||
static int valid_remote_nick(const char *name)
|
||||
{
|
||||
if (!name[0] || is_dot_or_dotdot(name))
|
||||
|
@ -705,9 +524,8 @@ const char *remote_ref_for_branch(struct branch *branch, int for_push,
|
|||
pushremote_for_branch(branch, NULL);
|
||||
struct remote *remote = remote_get(remote_name);
|
||||
|
||||
if (remote && remote->push_refspec_nr &&
|
||||
(dst = apply_refspecs(remote->push,
|
||||
remote->push_refspec_nr,
|
||||
if (remote && remote->push.nr &&
|
||||
(dst = apply_refspecs(&remote->push,
|
||||
branch->refname))) {
|
||||
if (explicit)
|
||||
*explicit = 1;
|
||||
|
@ -744,8 +562,6 @@ static struct remote *remote_get_1(const char *name,
|
|||
add_url_alias(ret, name);
|
||||
if (!valid_remote(ret))
|
||||
return NULL;
|
||||
ret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec);
|
||||
ret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -776,12 +592,6 @@ int for_each_remote(each_remote_fn fn, void *priv)
|
|||
struct remote *r = remotes[i];
|
||||
if (!r)
|
||||
continue;
|
||||
if (!r->fetch)
|
||||
r->fetch = parse_fetch_refspec(r->fetch_refspec_nr,
|
||||
r->fetch_refspec);
|
||||
if (!r->push)
|
||||
r->push = parse_push_refspec(r->push_refspec_nr,
|
||||
r->push_refspec);
|
||||
result = fn(r, priv);
|
||||
}
|
||||
return result;
|
||||
|
@ -887,7 +697,9 @@ static int match_name_with_pattern(const char *key, const char *name,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct refspec *query, struct string_list *results)
|
||||
static void query_refspecs_multiple(struct refspec *rs,
|
||||
struct refspec_item *query,
|
||||
struct string_list *results)
|
||||
{
|
||||
int i;
|
||||
int find_src = !query->src;
|
||||
|
@ -895,8 +707,8 @@ static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct
|
|||
if (find_src && !query->dst)
|
||||
error("query_refspecs_multiple: need either src or dst");
|
||||
|
||||
for (i = 0; i < ref_count; i++) {
|
||||
struct refspec *refspec = &refs[i];
|
||||
for (i = 0; i < rs->nr; i++) {
|
||||
struct refspec_item *refspec = &rs->items[i];
|
||||
const char *key = find_src ? refspec->dst : refspec->src;
|
||||
const char *value = find_src ? refspec->src : refspec->dst;
|
||||
const char *needle = find_src ? query->dst : query->src;
|
||||
|
@ -913,7 +725,7 @@ static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct
|
|||
}
|
||||
}
|
||||
|
||||
int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
|
||||
int query_refspecs(struct refspec *rs, struct refspec_item *query)
|
||||
{
|
||||
int i;
|
||||
int find_src = !query->src;
|
||||
|
@ -923,8 +735,8 @@ int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
|
|||
if (find_src && !query->dst)
|
||||
return error("query_refspecs: need either src or dst");
|
||||
|
||||
for (i = 0; i < ref_count; i++) {
|
||||
struct refspec *refspec = &refs[i];
|
||||
for (i = 0; i < rs->nr; i++) {
|
||||
struct refspec_item *refspec = &rs->items[i];
|
||||
const char *key = find_src ? refspec->dst : refspec->src;
|
||||
const char *value = find_src ? refspec->src : refspec->dst;
|
||||
|
||||
|
@ -944,23 +756,22 @@ int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
|
|||
return -1;
|
||||
}
|
||||
|
||||
char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
|
||||
const char *name)
|
||||
char *apply_refspecs(struct refspec *rs, const char *name)
|
||||
{
|
||||
struct refspec query;
|
||||
struct refspec_item query;
|
||||
|
||||
memset(&query, 0, sizeof(struct refspec));
|
||||
memset(&query, 0, sizeof(struct refspec_item));
|
||||
query.src = (char *)name;
|
||||
|
||||
if (query_refspecs(refspecs, nr_refspec, &query))
|
||||
if (query_refspecs(rs, &query))
|
||||
return NULL;
|
||||
|
||||
return query.dst;
|
||||
}
|
||||
|
||||
int remote_find_tracking(struct remote *remote, struct refspec *refspec)
|
||||
int remote_find_tracking(struct remote *remote, struct refspec_item *refspec)
|
||||
{
|
||||
return query_refspecs(remote->fetch, remote->fetch_refspec_nr, refspec);
|
||||
return query_refspecs(&remote->fetch, refspec);
|
||||
}
|
||||
|
||||
static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen,
|
||||
|
@ -1167,7 +978,7 @@ static char *guess_ref(const char *name, struct ref *peer)
|
|||
}
|
||||
|
||||
static int match_explicit_lhs(struct ref *src,
|
||||
struct refspec *rs,
|
||||
struct refspec_item *rs,
|
||||
struct ref **match,
|
||||
int *allocated_match)
|
||||
{
|
||||
|
@ -1193,7 +1004,7 @@ static int match_explicit_lhs(struct ref *src,
|
|||
|
||||
static int match_explicit(struct ref *src, struct ref *dst,
|
||||
struct ref ***dst_tail,
|
||||
struct refspec *rs)
|
||||
struct refspec_item *rs)
|
||||
{
|
||||
struct ref *matched_src, *matched_dst;
|
||||
int allocated_src;
|
||||
|
@ -1262,36 +1073,37 @@ static int match_explicit(struct ref *src, struct ref *dst,
|
|||
}
|
||||
|
||||
static int match_explicit_refs(struct ref *src, struct ref *dst,
|
||||
struct ref ***dst_tail, struct refspec *rs,
|
||||
int rs_nr)
|
||||
struct ref ***dst_tail, struct refspec *rs)
|
||||
{
|
||||
int i, errs;
|
||||
for (i = errs = 0; i < rs_nr; i++)
|
||||
errs += match_explicit(src, dst, dst_tail, &rs[i]);
|
||||
for (i = errs = 0; i < rs->nr; i++)
|
||||
errs += match_explicit(src, dst, dst_tail, &rs->items[i]);
|
||||
return errs;
|
||||
}
|
||||
|
||||
static char *get_ref_match(const struct refspec *rs, int rs_nr, const struct ref *ref,
|
||||
int send_mirror, int direction, const struct refspec **ret_pat)
|
||||
static char *get_ref_match(const struct refspec *rs, const struct ref *ref,
|
||||
int send_mirror, int direction,
|
||||
const struct refspec_item **ret_pat)
|
||||
{
|
||||
const struct refspec *pat;
|
||||
const struct refspec_item *pat;
|
||||
char *name;
|
||||
int i;
|
||||
int matching_refs = -1;
|
||||
for (i = 0; i < rs_nr; i++) {
|
||||
if (rs[i].matching &&
|
||||
(matching_refs == -1 || rs[i].force)) {
|
||||
for (i = 0; i < rs->nr; i++) {
|
||||
const struct refspec_item *item = &rs->items[i];
|
||||
if (item->matching &&
|
||||
(matching_refs == -1 || item->force)) {
|
||||
matching_refs = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rs[i].pattern) {
|
||||
const char *dst_side = rs[i].dst ? rs[i].dst : rs[i].src;
|
||||
if (item->pattern) {
|
||||
const char *dst_side = item->dst ? item->dst : item->src;
|
||||
int match;
|
||||
if (direction == FROM_SRC)
|
||||
match = match_name_with_pattern(rs[i].src, ref->name, dst_side, &name);
|
||||
match = match_name_with_pattern(item->src, ref->name, dst_side, &name);
|
||||
else
|
||||
match = match_name_with_pattern(dst_side, ref->name, rs[i].src, &name);
|
||||
match = match_name_with_pattern(dst_side, ref->name, item->src, &name);
|
||||
if (match) {
|
||||
matching_refs = i;
|
||||
break;
|
||||
|
@ -1301,7 +1113,7 @@ static char *get_ref_match(const struct refspec *rs, int rs_nr, const struct ref
|
|||
if (matching_refs == -1)
|
||||
return NULL;
|
||||
|
||||
pat = rs + matching_refs;
|
||||
pat = &rs->items[matching_refs];
|
||||
if (pat->matching) {
|
||||
/*
|
||||
* "matching refs"; traditionally we pushed everything
|
||||
|
@ -1443,22 +1255,20 @@ static void prepare_ref_index(struct string_list *ref_index, struct ref *ref)
|
|||
* but we can catch some errors early before even talking to the
|
||||
* remote side.
|
||||
*/
|
||||
int check_push_refs(struct ref *src, int nr_refspec, const char **refspec_names)
|
||||
int check_push_refs(struct ref *src, struct refspec *rs)
|
||||
{
|
||||
struct refspec *refspec = parse_push_refspec(nr_refspec, refspec_names);
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_refspec; i++) {
|
||||
struct refspec *rs = refspec + i;
|
||||
for (i = 0; i < rs->nr; i++) {
|
||||
struct refspec_item *item = &rs->items[i];
|
||||
|
||||
if (rs->pattern || rs->matching)
|
||||
if (item->pattern || item->matching)
|
||||
continue;
|
||||
|
||||
ret |= match_explicit_lhs(src, rs, NULL, NULL);
|
||||
ret |= match_explicit_lhs(src, item, NULL, NULL);
|
||||
}
|
||||
|
||||
free_refspec(nr_refspec, refspec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1471,32 +1281,29 @@ int check_push_refs(struct ref *src, int nr_refspec, const char **refspec_names)
|
|||
* dst (e.g. pushing to a new branch, done in match_explicit_refs).
|
||||
*/
|
||||
int match_push_refs(struct ref *src, struct ref **dst,
|
||||
int nr_refspec, const char **refspec, int flags)
|
||||
struct refspec *rs, int flags)
|
||||
{
|
||||
struct refspec *rs;
|
||||
int send_all = flags & MATCH_REFS_ALL;
|
||||
int send_mirror = flags & MATCH_REFS_MIRROR;
|
||||
int send_prune = flags & MATCH_REFS_PRUNE;
|
||||
int errs;
|
||||
static const char *default_refspec[] = { ":", NULL };
|
||||
struct ref *ref, **dst_tail = tail_ref(dst);
|
||||
struct string_list dst_ref_index = STRING_LIST_INIT_NODUP;
|
||||
|
||||
if (!nr_refspec) {
|
||||
nr_refspec = 1;
|
||||
refspec = default_refspec;
|
||||
}
|
||||
rs = parse_push_refspec(nr_refspec, (const char **) refspec);
|
||||
errs = match_explicit_refs(src, *dst, &dst_tail, rs, nr_refspec);
|
||||
/* If no refspec is provided, use the default ":" */
|
||||
if (!rs->nr)
|
||||
refspec_append(rs, ":");
|
||||
|
||||
errs = match_explicit_refs(src, *dst, &dst_tail, rs);
|
||||
|
||||
/* pick the remainder */
|
||||
for (ref = src; ref; ref = ref->next) {
|
||||
struct string_list_item *dst_item;
|
||||
struct ref *dst_peer;
|
||||
const struct refspec *pat = NULL;
|
||||
const struct refspec_item *pat = NULL;
|
||||
char *dst_name;
|
||||
|
||||
dst_name = get_ref_match(rs, nr_refspec, ref, send_mirror, FROM_SRC, &pat);
|
||||
dst_name = get_ref_match(rs, ref, send_mirror, FROM_SRC, &pat);
|
||||
if (!dst_name)
|
||||
continue;
|
||||
|
||||
|
@ -1545,7 +1352,7 @@ int match_push_refs(struct ref *src, struct ref **dst,
|
|||
/* We're already sending something to this ref. */
|
||||
continue;
|
||||
|
||||
src_name = get_ref_match(rs, nr_refspec, ref, send_mirror, FROM_DST, NULL);
|
||||
src_name = get_ref_match(rs, ref, send_mirror, FROM_DST, NULL);
|
||||
if (src_name) {
|
||||
if (!src_ref_index.nr)
|
||||
prepare_ref_index(&src_ref_index, src);
|
||||
|
@ -1557,6 +1364,7 @@ int match_push_refs(struct ref *src, struct ref **dst,
|
|||
}
|
||||
string_list_clear(&src_ref_index, 0);
|
||||
}
|
||||
|
||||
if (errs)
|
||||
return -1;
|
||||
return 0;
|
||||
|
@ -1753,7 +1561,7 @@ static const char *tracking_for_push_dest(struct remote *remote,
|
|||
{
|
||||
char *ret;
|
||||
|
||||
ret = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, refname);
|
||||
ret = apply_refspecs(&remote->fetch, refname);
|
||||
if (!ret)
|
||||
return error_buf(err,
|
||||
_("push destination '%s' on remote '%s' has no local tracking branch"),
|
||||
|
@ -1771,12 +1579,11 @@ static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
|
|||
_("branch '%s' has no remote for pushing"),
|
||||
branch->name);
|
||||
|
||||
if (remote->push_refspec_nr) {
|
||||
if (remote->push.nr) {
|
||||
char *dst;
|
||||
const char *ret;
|
||||
|
||||
dst = apply_refspecs(remote->push, remote->push_refspec_nr,
|
||||
branch->refname);
|
||||
dst = apply_refspecs(&remote->push, branch->refname);
|
||||
if (!dst)
|
||||
return error_buf(err,
|
||||
_("push refspecs for '%s' do not include '%s'"),
|
||||
|
@ -1849,7 +1656,7 @@ static int ignore_symref_update(const char *refname)
|
|||
* local symbolic ref.
|
||||
*/
|
||||
static struct ref *get_expanded_map(const struct ref *remote_refs,
|
||||
const struct refspec *refspec)
|
||||
const struct refspec_item *refspec)
|
||||
{
|
||||
const struct ref *ref;
|
||||
struct ref *ret = NULL;
|
||||
|
@ -1914,7 +1721,7 @@ static struct ref *get_local_ref(const char *name)
|
|||
}
|
||||
|
||||
int get_fetch_map(const struct ref *remote_refs,
|
||||
const struct refspec *refspec,
|
||||
const struct refspec_item *refspec,
|
||||
struct ref ***tail,
|
||||
int missing_ok)
|
||||
{
|
||||
|
@ -2252,8 +2059,7 @@ struct ref *guess_remote_head(const struct ref *head,
|
|||
struct stale_heads_info {
|
||||
struct string_list *ref_names;
|
||||
struct ref **stale_refs_tail;
|
||||
struct refspec *refs;
|
||||
int ref_count;
|
||||
struct refspec *rs;
|
||||
};
|
||||
|
||||
static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
|
||||
|
@ -2261,12 +2067,12 @@ static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
|
|||
{
|
||||
struct stale_heads_info *info = cb_data;
|
||||
struct string_list matches = STRING_LIST_INIT_DUP;
|
||||
struct refspec query;
|
||||
struct refspec_item query;
|
||||
int i, stale = 1;
|
||||
memset(&query, 0, sizeof(struct refspec));
|
||||
memset(&query, 0, sizeof(struct refspec_item));
|
||||
query.dst = (char *)refname;
|
||||
|
||||
query_refspecs_multiple(info->refs, info->ref_count, &query, &matches);
|
||||
query_refspecs_multiple(info->rs, &query, &matches);
|
||||
if (matches.nr == 0)
|
||||
goto clean_exit; /* No matches */
|
||||
|
||||
|
@ -2294,7 +2100,7 @@ clean_exit:
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fetch_map)
|
||||
struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map)
|
||||
{
|
||||
struct ref *ref, *stale_refs = NULL;
|
||||
struct string_list ref_names = STRING_LIST_INIT_NODUP;
|
||||
|
@ -2302,8 +2108,7 @@ struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fet
|
|||
|
||||
info.ref_names = &ref_names;
|
||||
info.stale_refs_tail = &stale_refs;
|
||||
info.refs = refs;
|
||||
info.ref_count = ref_count;
|
||||
info.rs = rs;
|
||||
for (ref = fetch_map; ref; ref = ref->next)
|
||||
string_list_append(&ref_names, ref->name);
|
||||
string_list_sort(&ref_names);
|
||||
|
@ -2387,7 +2192,7 @@ static int remote_tracking(struct remote *remote, const char *refname,
|
|||
{
|
||||
char *dst;
|
||||
|
||||
dst = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, refname);
|
||||
dst = apply_refspecs(&remote->fetch, refname);
|
||||
if (!dst)
|
||||
return -1; /* no tracking ref for refname at remote */
|
||||
if (read_ref(dst, oid))
|
||||
|
|
50
remote.h
50
remote.h
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "parse-options.h"
|
||||
#include "hashmap.h"
|
||||
#include "refspec.h"
|
||||
|
||||
enum {
|
||||
REMOTE_UNCONFIGURED = 0,
|
||||
|
@ -27,15 +28,9 @@ struct remote {
|
|||
int pushurl_nr;
|
||||
int pushurl_alloc;
|
||||
|
||||
const char **push_refspec;
|
||||
struct refspec *push;
|
||||
int push_refspec_nr;
|
||||
int push_refspec_alloc;
|
||||
struct refspec push;
|
||||
|
||||
const char **fetch_refspec;
|
||||
struct refspec *fetch;
|
||||
int fetch_refspec_nr;
|
||||
int fetch_refspec_alloc;
|
||||
struct refspec fetch;
|
||||
|
||||
/*
|
||||
* -1 to never fetch tags
|
||||
|
@ -68,18 +63,6 @@ int for_each_remote(each_remote_fn fn, void *priv);
|
|||
|
||||
int remote_has_url(struct remote *remote, const char *url);
|
||||
|
||||
struct refspec {
|
||||
unsigned force : 1;
|
||||
unsigned pattern : 1;
|
||||
unsigned matching : 1;
|
||||
unsigned exact_sha1 : 1;
|
||||
|
||||
char *src;
|
||||
char *dst;
|
||||
};
|
||||
|
||||
extern const struct refspec *tag_refspec;
|
||||
|
||||
struct ref {
|
||||
struct ref *next;
|
||||
struct object_id old_oid;
|
||||
|
@ -177,19 +160,12 @@ int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid);
|
|||
*/
|
||||
struct ref *ref_remove_duplicates(struct ref *ref_map);
|
||||
|
||||
int valid_fetch_refspec(const char *refspec);
|
||||
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
|
||||
extern struct refspec *parse_push_refspec(int nr_refspec, const char **refspec);
|
||||
int query_refspecs(struct refspec *rs, struct refspec_item *query);
|
||||
char *apply_refspecs(struct refspec *rs, const char *name);
|
||||
|
||||
void free_refspec(int nr_refspec, struct refspec *refspec);
|
||||
|
||||
extern int query_refspecs(struct refspec *specs, int nr, struct refspec *query);
|
||||
char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
|
||||
const char *name);
|
||||
|
||||
int check_push_refs(struct ref *src, int nr_refspec, const char **refspec);
|
||||
int check_push_refs(struct ref *src, struct refspec *rs);
|
||||
int match_push_refs(struct ref *src, struct ref **dst,
|
||||
int nr_refspec, const char **refspec, int all);
|
||||
struct refspec *rs, int flags);
|
||||
void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
|
||||
int force_update);
|
||||
|
||||
|
@ -205,7 +181,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
|
|||
* missing_ok is usually false, but when we are adding branch.$name.merge
|
||||
* it is Ok if the branch is not at the remote anymore.
|
||||
*/
|
||||
int get_fetch_map(const struct ref *remote_refs, const struct refspec *refspec,
|
||||
int get_fetch_map(const struct ref *remote_refs, const struct refspec_item *refspec,
|
||||
struct ref ***tail, int missing_ok);
|
||||
|
||||
struct ref *get_remote_ref(const struct ref *remote_refs, const char *name);
|
||||
|
@ -213,7 +189,7 @@ struct ref *get_remote_ref(const struct ref *remote_refs, const char *name);
|
|||
/*
|
||||
* For the given remote, reads the refspec's src and sets the other fields.
|
||||
*/
|
||||
int remote_find_tracking(struct remote *remote, struct refspec *refspec);
|
||||
int remote_find_tracking(struct remote *remote, struct refspec_item *refspec);
|
||||
|
||||
struct branch {
|
||||
const char *name;
|
||||
|
@ -223,7 +199,7 @@ struct branch {
|
|||
const char *pushremote_name;
|
||||
|
||||
const char **merge_name;
|
||||
struct refspec **merge;
|
||||
struct refspec_item **merge;
|
||||
int merge_nr;
|
||||
int merge_alloc;
|
||||
|
||||
|
@ -292,7 +268,7 @@ struct ref *guess_remote_head(const struct ref *head,
|
|||
int all);
|
||||
|
||||
/* Return refs which no longer exist on remote */
|
||||
struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fetch_map);
|
||||
struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map);
|
||||
|
||||
/*
|
||||
* Compare-and-swap
|
||||
|
@ -315,8 +291,4 @@ extern int parseopt_push_cas_option(const struct option *, const char *arg, int
|
|||
extern int is_empty_cas(const struct push_cas_option *);
|
||||
void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *);
|
||||
|
||||
#define TAG_REFSPEC "refs/tags/*:refs/tags/*"
|
||||
|
||||
void add_prune_tags_to_fetch_refspec(struct remote *remote);
|
||||
|
||||
#endif
|
||||
|
|
19
submodule.c
19
submodule.c
|
@ -968,7 +968,7 @@ int find_unpushed_submodules(struct oid_array *commits,
|
|||
|
||||
static int push_submodule(const char *path,
|
||||
const struct remote *remote,
|
||||
const char **refspec, int refspec_nr,
|
||||
const struct refspec *rs,
|
||||
const struct string_list *push_options,
|
||||
int dry_run)
|
||||
{
|
||||
|
@ -991,8 +991,8 @@ static int push_submodule(const char *path,
|
|||
if (remote->origin != REMOTE_UNCONFIGURED) {
|
||||
int i;
|
||||
argv_array_push(&cp.args, remote->name);
|
||||
for (i = 0; i < refspec_nr; i++)
|
||||
argv_array_push(&cp.args, refspec[i]);
|
||||
for (i = 0; i < rs->raw_nr; i++)
|
||||
argv_array_push(&cp.args, rs->raw[i]);
|
||||
}
|
||||
|
||||
prepare_submodule_repo_env(&cp.env_array);
|
||||
|
@ -1013,7 +1013,7 @@ static int push_submodule(const char *path,
|
|||
*/
|
||||
static void submodule_push_check(const char *path, const char *head,
|
||||
const struct remote *remote,
|
||||
const char **refspec, int refspec_nr)
|
||||
const struct refspec *rs)
|
||||
{
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
int i;
|
||||
|
@ -1023,8 +1023,8 @@ static void submodule_push_check(const char *path, const char *head,
|
|||
argv_array_push(&cp.args, head);
|
||||
argv_array_push(&cp.args, remote->name);
|
||||
|
||||
for (i = 0; i < refspec_nr; i++)
|
||||
argv_array_push(&cp.args, refspec[i]);
|
||||
for (i = 0; i < rs->raw_nr; i++)
|
||||
argv_array_push(&cp.args, rs->raw[i]);
|
||||
|
||||
prepare_submodule_repo_env(&cp.env_array);
|
||||
cp.git_cmd = 1;
|
||||
|
@ -1043,7 +1043,7 @@ static void submodule_push_check(const char *path, const char *head,
|
|||
|
||||
int push_unpushed_submodules(struct oid_array *commits,
|
||||
const struct remote *remote,
|
||||
const char **refspec, int refspec_nr,
|
||||
const struct refspec *rs,
|
||||
const struct string_list *push_options,
|
||||
int dry_run)
|
||||
{
|
||||
|
@ -1069,8 +1069,7 @@ int push_unpushed_submodules(struct oid_array *commits,
|
|||
|
||||
for (i = 0; i < needs_pushing.nr; i++)
|
||||
submodule_push_check(needs_pushing.items[i].string,
|
||||
head, remote,
|
||||
refspec, refspec_nr);
|
||||
head, remote, rs);
|
||||
free(head);
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1077,7 @@ int push_unpushed_submodules(struct oid_array *commits,
|
|||
for (i = 0; i < needs_pushing.nr; i++) {
|
||||
const char *path = needs_pushing.items[i].string;
|
||||
fprintf(stderr, "Pushing submodule '%s'\n", path);
|
||||
if (!push_submodule(path, remote, refspec, refspec_nr,
|
||||
if (!push_submodule(path, remote, rs,
|
||||
push_options, dry_run)) {
|
||||
fprintf(stderr, "Unable to push submodule '%s'\n", path);
|
||||
ret = 0;
|
||||
|
|
|
@ -100,9 +100,10 @@ extern int submodule_touches_in_range(struct object_id *a,
|
|||
extern int find_unpushed_submodules(struct oid_array *commits,
|
||||
const char *remotes_name,
|
||||
struct string_list *needs_pushing);
|
||||
struct refspec;
|
||||
extern int push_unpushed_submodules(struct oid_array *commits,
|
||||
const struct remote *remote,
|
||||
const char **refspec, int refspec_nr,
|
||||
const struct refspec *rs,
|
||||
const struct string_list *push_options,
|
||||
int dry_run);
|
||||
/*
|
||||
|
|
|
@ -345,6 +345,20 @@ test_expect_success 'even with handcrafted request, filter does not work if not
|
|||
git -C server serve --stateless-rpc <in >/dev/null
|
||||
'
|
||||
|
||||
test_expect_success 'default refspec is used to filter ref when fetchcing' '
|
||||
test_when_finished "rm -f log" &&
|
||||
|
||||
GIT_TRACE_PACKET="$(pwd)/log" git -C file_child -c protocol.version=2 \
|
||||
fetch origin &&
|
||||
|
||||
git -C file_child log -1 --format=%s three >actual &&
|
||||
git -C file_parent log -1 --format=%s three >expect &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
grep "ref-prefix refs/heads/" log &&
|
||||
grep "ref-prefix refs/tags/" log
|
||||
'
|
||||
|
||||
# Test protocol v2 with 'http://' transport
|
||||
#
|
||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "sigchain.h"
|
||||
#include "argv-array.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "transport-internal.h"
|
||||
#include "protocol.h"
|
||||
|
||||
|
@ -35,8 +36,7 @@ struct helper_data {
|
|||
char *export_marks;
|
||||
char *import_marks;
|
||||
/* These go from remote name (as in "list") to private name */
|
||||
struct refspec *refspecs;
|
||||
int refspec_nr;
|
||||
struct refspec rs;
|
||||
/* Transport options for fetch-pack/send-pack (should one of
|
||||
* those be invoked).
|
||||
*/
|
||||
|
@ -106,9 +106,6 @@ static struct child_process *get_helper(struct transport *transport)
|
|||
struct helper_data *data = transport->data;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct child_process *helper;
|
||||
const char **refspecs = NULL;
|
||||
int refspec_nr = 0;
|
||||
int refspec_alloc = 0;
|
||||
int duped;
|
||||
int code;
|
||||
|
||||
|
@ -138,6 +135,7 @@ static struct child_process *get_helper(struct transport *transport)
|
|||
|
||||
data->helper = helper;
|
||||
data->no_disconnect_req = 0;
|
||||
refspec_init(&data->rs, REFSPEC_FETCH);
|
||||
|
||||
/*
|
||||
* Open the output as FILE* so strbuf_getline_*() family of
|
||||
|
@ -183,11 +181,8 @@ static struct child_process *get_helper(struct transport *transport)
|
|||
data->export = 1;
|
||||
else if (!strcmp(capname, "check-connectivity"))
|
||||
data->check_connectivity = 1;
|
||||
else if (!data->refspecs && skip_prefix(capname, "refspec ", &arg)) {
|
||||
ALLOC_GROW(refspecs,
|
||||
refspec_nr + 1,
|
||||
refspec_alloc);
|
||||
refspecs[refspec_nr++] = xstrdup(arg);
|
||||
else if (skip_prefix(capname, "refspec ", &arg)) {
|
||||
refspec_append(&data->rs, arg);
|
||||
} else if (!strcmp(capname, "connect")) {
|
||||
data->connect = 1;
|
||||
} else if (!strcmp(capname, "stateless-connect")) {
|
||||
|
@ -206,14 +201,7 @@ static struct child_process *get_helper(struct transport *transport)
|
|||
capname);
|
||||
}
|
||||
}
|
||||
if (refspecs) {
|
||||
int i;
|
||||
data->refspec_nr = refspec_nr;
|
||||
data->refspecs = parse_fetch_refspec(refspec_nr, refspecs);
|
||||
for (i = 0; i < refspec_nr; i++)
|
||||
free((char *)refspecs[i]);
|
||||
free(refspecs);
|
||||
} else if (data->import || data->bidi_import || data->export) {
|
||||
if (!data->rs.nr && (data->import || data->bidi_import || data->export)) {
|
||||
warning("This remote helper should implement refspec capability.");
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
|
@ -377,8 +365,7 @@ static int release_helper(struct transport *transport)
|
|||
{
|
||||
int res = 0;
|
||||
struct helper_data *data = transport->data;
|
||||
free_refspec(data->refspec_nr, data->refspecs);
|
||||
data->refspecs = NULL;
|
||||
refspec_clear(&data->rs);
|
||||
res = disconnect_helper(transport);
|
||||
free(transport->data);
|
||||
return res;
|
||||
|
@ -535,8 +522,8 @@ static int fetch_with_import(struct transport *transport,
|
|||
if (posn->status & REF_STATUS_UPTODATE)
|
||||
continue;
|
||||
name = posn->symref ? posn->symref : posn->name;
|
||||
if (data->refspecs)
|
||||
private = apply_refspecs(data->refspecs, data->refspec_nr, name);
|
||||
if (data->rs.nr)
|
||||
private = apply_refspecs(&data->rs, name);
|
||||
else
|
||||
private = xstrdup(name);
|
||||
if (private) {
|
||||
|
@ -814,11 +801,11 @@ static int push_update_refs_status(struct helper_data *data,
|
|||
if (push_update_ref_status(&buf, &ref, remote_refs))
|
||||
continue;
|
||||
|
||||
if (flags & TRANSPORT_PUSH_DRY_RUN || !data->refspecs || data->no_private_update)
|
||||
if (flags & TRANSPORT_PUSH_DRY_RUN || !data->rs.nr || data->no_private_update)
|
||||
continue;
|
||||
|
||||
/* propagate back the update to the remote namespace */
|
||||
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
|
||||
private = apply_refspecs(&data->rs, ref->name);
|
||||
if (!private)
|
||||
continue;
|
||||
update_ref("update by helper", private, &ref->new_oid, NULL,
|
||||
|
@ -938,7 +925,7 @@ static int push_refs_with_export(struct transport *transport,
|
|||
struct string_list revlist_args = STRING_LIST_INIT_DUP;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (!data->refspecs)
|
||||
if (!data->rs.nr)
|
||||
die("remote-helper doesn't support push; refspec needed");
|
||||
|
||||
set_common_push_options(transport, data->name, flags);
|
||||
|
@ -955,7 +942,7 @@ static int push_refs_with_export(struct transport *transport,
|
|||
char *private;
|
||||
struct object_id oid;
|
||||
|
||||
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
|
||||
private = apply_refspecs(&data->rs, ref->name);
|
||||
if (private && !get_oid(private, &oid)) {
|
||||
strbuf_addf(&buf, "^%s", private);
|
||||
string_list_append_nodup(&revlist_args,
|
||||
|
|
60
transport.c
60
transport.c
|
@ -11,6 +11,7 @@
|
|||
#include "bundle.h"
|
||||
#include "dir.h"
|
||||
#include "refs.h"
|
||||
#include "refspec.h"
|
||||
#include "branch.h"
|
||||
#include "url.h"
|
||||
#include "submodule.h"
|
||||
|
@ -390,7 +391,7 @@ int transport_refs_pushed(struct ref *ref)
|
|||
|
||||
void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
|
||||
{
|
||||
struct refspec rs;
|
||||
struct refspec_item rs;
|
||||
|
||||
if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
|
||||
return;
|
||||
|
@ -619,29 +620,6 @@ void transport_print_push_status(const char *dest, struct ref *refs,
|
|||
free(head);
|
||||
}
|
||||
|
||||
void transport_verify_remote_names(int nr_heads, const char **heads)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_heads; i++) {
|
||||
const char *local = heads[i];
|
||||
const char *remote = strrchr(heads[i], ':');
|
||||
|
||||
if (*local == '+')
|
||||
local++;
|
||||
|
||||
/* A matching refspec is okay. */
|
||||
if (remote == local && remote[1] == '\0')
|
||||
continue;
|
||||
|
||||
remote = remote ? (remote + 1) : local;
|
||||
if (check_refname_format(remote,
|
||||
REFNAME_ALLOW_ONELEVEL|REFNAME_REFSPEC_PATTERN))
|
||||
die("remote part of refspec is not a valid name in %s",
|
||||
heads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
|
||||
{
|
||||
struct git_transport_data *data = transport->data;
|
||||
|
@ -1093,11 +1071,10 @@ static int run_pre_push_hook(struct transport *transport,
|
|||
}
|
||||
|
||||
int transport_push(struct transport *transport,
|
||||
int refspec_nr, const char **refspec, int flags,
|
||||
struct refspec *rs, int flags,
|
||||
unsigned int *reject_reasons)
|
||||
{
|
||||
*reject_reasons = 0;
|
||||
transport_verify_remote_names(refspec_nr, refspec);
|
||||
|
||||
if (transport_color_config() < 0)
|
||||
return -1;
|
||||
|
@ -1111,38 +1088,17 @@ int transport_push(struct transport *transport,
|
|||
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
|
||||
int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
|
||||
int push_ret, ret, err;
|
||||
struct refspec *tmp_rs;
|
||||
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
|
||||
int i;
|
||||
|
||||
if (check_push_refs(local_refs, refspec_nr, refspec) < 0)
|
||||
if (check_push_refs(local_refs, rs) < 0)
|
||||
return -1;
|
||||
|
||||
tmp_rs = parse_push_refspec(refspec_nr, refspec);
|
||||
for (i = 0; i < refspec_nr; i++) {
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (tmp_rs[i].dst)
|
||||
prefix = tmp_rs[i].dst;
|
||||
else if (tmp_rs[i].src && !tmp_rs[i].exact_sha1)
|
||||
prefix = tmp_rs[i].src;
|
||||
|
||||
if (prefix) {
|
||||
const char *glob = strchr(prefix, '*');
|
||||
if (glob)
|
||||
argv_array_pushf(&ref_prefixes, "%.*s",
|
||||
(int)(glob - prefix),
|
||||
prefix);
|
||||
else
|
||||
expand_ref_prefix(&ref_prefixes, prefix);
|
||||
}
|
||||
}
|
||||
refspec_ref_prefixes(rs, &ref_prefixes);
|
||||
|
||||
remote_refs = transport->vtable->get_refs_list(transport, 1,
|
||||
&ref_prefixes);
|
||||
|
||||
argv_array_clear(&ref_prefixes);
|
||||
free_refspec(refspec_nr, tmp_rs);
|
||||
|
||||
if (flags & TRANSPORT_PUSH_ALL)
|
||||
match_flags |= MATCH_REFS_ALL;
|
||||
|
@ -1153,10 +1109,8 @@ int transport_push(struct transport *transport,
|
|||
if (flags & TRANSPORT_PUSH_FOLLOW_TAGS)
|
||||
match_flags |= MATCH_REFS_FOLLOW_TAGS;
|
||||
|
||||
if (match_push_refs(local_refs, &remote_refs,
|
||||
refspec_nr, refspec, match_flags)) {
|
||||
if (match_push_refs(local_refs, &remote_refs, rs, match_flags))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (transport->smart_options &&
|
||||
transport->smart_options->cas &&
|
||||
|
@ -1185,7 +1139,7 @@ int transport_push(struct transport *transport,
|
|||
|
||||
if (!push_unpushed_submodules(&commits,
|
||||
transport->remote,
|
||||
refspec, refspec_nr,
|
||||
rs,
|
||||
transport->push_options,
|
||||
pretend)) {
|
||||
oid_array_clear(&commits);
|
||||
|
|
|
@ -203,7 +203,7 @@ void transport_set_verbosity(struct transport *transport, int verbosity,
|
|||
#define REJECT_NEEDS_FORCE 0x10
|
||||
|
||||
int transport_push(struct transport *connection,
|
||||
int refspec_nr, const char **refspec, int flags,
|
||||
struct refspec *rs, int flags,
|
||||
unsigned int * reject_reasons);
|
||||
|
||||
/*
|
||||
|
@ -233,8 +233,6 @@ int transport_helper_init(struct transport *transport, const char *name);
|
|||
int bidirectional_transfer_loop(int input, int output);
|
||||
|
||||
/* common methods used by transport.c and builtin/send-pack.c */
|
||||
void transport_verify_remote_names(int nr_heads, const char **heads);
|
||||
|
||||
void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose);
|
||||
|
||||
int transport_refs_pushed(struct ref *ref);
|
||||
|
|
Загрузка…
Ссылка в новой задаче