diff options
Diffstat (limited to 'remote.c')
| -rw-r--r-- | remote.c | 320 |
1 files changed, 100 insertions, 220 deletions
@@ -1,4 +1,5 @@ #define USE_THE_REPOSITORY_VARIABLE +#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "abspath.h" @@ -24,6 +25,7 @@ #include "advice.h" #include "connect.h" #include "parse-options.h" +#include "transport.h" enum map_direction { FROM_SRC, FROM_DST }; @@ -141,8 +143,9 @@ static struct remote *make_remote(struct remote_state *remote_state, 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); + refspec_init_push(&ret->push); + refspec_init_fetch(&ret->fetch); + string_list_init_dup(&ret->server_options); ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1, remote_state->remotes_alloc); @@ -166,6 +169,7 @@ static void remote_clear(struct remote *remote) free((char *)remote->uploadpack); FREE_AND_NULL(remote->http_proxy); FREE_AND_NULL(remote->http_proxy_authmethod); + string_list_clear(&remote->server_options, 0); } static void add_merge(struct branch *branch, const char *name) @@ -290,6 +294,7 @@ static void add_instead_of(struct rewrite *rewrite, const char *instead_of) rewrite->instead_of_nr++; } +#ifndef WITH_BREAKING_CHANGES static const char *skip_spaces(const char *s) { while (isspace(*s)) @@ -297,14 +302,33 @@ static const char *skip_spaces(const char *s) return s; } +static void warn_about_deprecated_remote_type(const char *type, + const struct remote *remote) +{ + warning(_("reading remote from \"%s/%s\", which is nominated for removal.\n" + "\n" + "If you still use the \"remotes/\" directory it is recommended to\n" + "migrate to config-based remotes:\n" + "\n" + "\tgit remote rename %s %s\n" + "\n" + "If you cannot, please let us know why you still need to use it by\n" + "sending an e-mail to <git@vger.kernel.org>."), + type, remote->name, remote->name, remote->name); +} + static void read_remotes_file(struct remote_state *remote_state, struct remote *remote) { struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "remotes/%s", remote->name), "r"); if (!f) - return; + goto out; + + warn_about_deprecated_remote_type("remotes", remote); + remote->configured_in_repo = 1; remote->origin = REMOTE_REMOTES; while (strbuf_getline(&buf, f) != EOF) { @@ -320,8 +344,10 @@ static void read_remotes_file(struct remote_state *remote_state, else if (skip_prefix(buf.buf, "Pull:", &v)) refspec_append(&remote->fetch, skip_spaces(v)); } - strbuf_release(&buf); fclose(f); + +out: + strbuf_release(&buf); } static void read_branches_file(struct remote_state *remote_state, @@ -329,18 +355,19 @@ static void read_branches_file(struct remote_state *remote_state, { char *frag, *to_free = NULL; struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "branches/%s", remote->name), "r"); if (!f) - return; + goto out; + + warn_about_deprecated_remote_type("branches", remote); strbuf_getline_lf(&buf, f); fclose(f); strbuf_trim(&buf); - if (!buf.len) { - strbuf_release(&buf); - return; - } + if (!buf.len) + goto out; remote->configured_in_repo = 1; remote->origin = REMOTE_BRANCHES; @@ -368,9 +395,11 @@ static void read_branches_file(struct remote_state *remote_state, refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag); remote->fetch_tags = 1; /* always auto-follow */ +out: strbuf_release(&buf); free(to_free); } +#endif /* WITH_BREAKING_CHANGES */ static int handle_config(const char *key, const char *value, const struct config_context *ctx, void *cb) @@ -508,6 +537,27 @@ static int handle_config(const char *key, const char *value, } else if (!strcmp(subkey, "vcs")) { FREE_AND_NULL(remote->foreign_vcs); return git_config_string(&remote->foreign_vcs, key, value); + } else if (!strcmp(subkey, "serveroption")) { + return parse_transport_option(key, value, + &remote->server_options); + } else if (!strcmp(subkey, "followremotehead")) { + const char *no_warn_branch; + if (!strcmp(value, "never")) + remote->follow_remote_head = FOLLOW_REMOTE_NEVER; + else if (!strcmp(value, "create")) + remote->follow_remote_head = FOLLOW_REMOTE_CREATE; + else if (!strcmp(value, "warn")) { + remote->follow_remote_head = FOLLOW_REMOTE_WARN; + remote->no_warn_branch = NULL; + } else if (skip_prefix(value, "warn-if-not-", &no_warn_branch)) { + remote->follow_remote_head = FOLLOW_REMOTE_WARN; + remote->no_warn_branch = no_warn_branch; + } else if (!strcmp(value, "always")) { + remote->follow_remote_head = FOLLOW_REMOTE_ALWAYS; + } else { + warning(_("unrecognized followRemoteHEAD value '%s' ignored"), + value); + } } return 0; } @@ -566,6 +616,7 @@ static void read_config(struct repository *repo, int early) alias_all_urls(repo->remote_state); } +#ifndef WITH_BREAKING_CHANGES static int valid_remote_nick(const char *name) { if (!name[0] || is_dot_or_dotdot(name)) @@ -577,6 +628,7 @@ static int valid_remote_nick(const char *name) return 0; return 1; } +#endif /* WITH_BREAKING_CHANGES */ static const char *remotes_remote_for_branch(struct remote_state *remote_state, struct branch *branch, @@ -719,12 +771,14 @@ remotes_remote_get_1(struct remote_state *remote_state, const char *name, &name_given); ret = make_remote(remote_state, name, 0); +#ifndef WITH_BREAKING_CHANGES if (valid_remote_nick(name) && have_git_dir()) { if (!valid_remote(ret)) read_remotes_file(remote_state, ret); if (!valid_remote(ret)) read_branches_file(remote_state, ret); } +#endif /* WITH_BREAKING_CHANGES */ if (name_given && !valid_remote(ret)) add_url_alias(remote_state, ret, name); if (!valid_remote(ret)) @@ -868,210 +922,23 @@ struct strvec *push_url_of_remote(struct remote *remote) return remote->pushurl.nr ? &remote->pushurl : &remote->url; } -static int match_name_with_pattern(const char *key, const char *name, - const char *value, char **result) -{ - const char *kstar = strchr(key, '*'); - size_t klen; - size_t ksuffixlen; - size_t namelen; - int ret; - if (!kstar) - die(_("key '%s' of pattern had no '*'"), key); - klen = kstar - key; - ksuffixlen = strlen(kstar + 1); - namelen = strlen(name); - ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen && - !memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen); - if (ret && value) { - struct strbuf sb = STRBUF_INIT; - const char *vstar = strchr(value, '*'); - if (!vstar) - die(_("value '%s' of pattern has no '*'"), value); - strbuf_add(&sb, value, vstar - value); - strbuf_add(&sb, name + klen, namelen - klen - ksuffixlen); - strbuf_addstr(&sb, vstar + 1); - *result = strbuf_detach(&sb, NULL); - } - return ret; -} - -static int refspec_match(const struct refspec_item *refspec, - const char *name) +void ref_push_report_free(struct ref_push_report *report) { - if (refspec->pattern) - return match_name_with_pattern(refspec->src, name, NULL, NULL); + while (report) { + struct ref_push_report *next = report->next; - return !strcmp(refspec->src, name); -} + free(report->ref_name); + free(report->old_oid); + free(report->new_oid); + free(report); -int omit_name_by_refspec(const char *name, struct refspec *rs) -{ - int i; - - for (i = 0; i < rs->nr; i++) { - if (rs->items[i].negative && refspec_match(&rs->items[i], name)) - return 1; + report = next; } - return 0; -} - -struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs) -{ - struct ref **tail; - - for (tail = &ref_map; *tail; ) { - struct ref *ref = *tail; - - if (omit_name_by_refspec(ref->name, rs)) { - *tail = ref->next; - free(ref->peer_ref); - free(ref); - } else - tail = &ref->next; - } - - return ref_map; -} - -static int query_matches_negative_refspec(struct refspec *rs, struct refspec_item *query) -{ - int i, matched_negative = 0; - int find_src = !query->src; - struct string_list reversed = STRING_LIST_INIT_DUP; - const char *needle = find_src ? query->dst : query->src; - - /* - * Check whether the queried ref matches any negative refpsec. If so, - * then we should ultimately treat this as not matching the query at - * all. - * - * Note that negative refspecs always match the source, but the query - * item uses the destination. To handle this, we apply pattern - * refspecs in reverse to figure out if the query source matches any - * of the negative refspecs. - * - * The first loop finds and expands all positive refspecs - * matched by the queried ref. - * - * The second loop checks if any of the results of the first loop - * match any negative refspec. - */ - for (i = 0; i < rs->nr; i++) { - struct refspec_item *refspec = &rs->items[i]; - char *expn_name; - - if (refspec->negative) - continue; - - /* Note the reversal of src and dst */ - if (refspec->pattern) { - const char *key = refspec->dst ? refspec->dst : refspec->src; - const char *value = refspec->src; - - if (match_name_with_pattern(key, needle, value, &expn_name)) - string_list_append_nodup(&reversed, expn_name); - } else if (refspec->matching) { - /* For the special matching refspec, any query should match */ - string_list_append(&reversed, needle); - } else if (!refspec->src) { - BUG("refspec->src should not be null here"); - } else if (!strcmp(needle, refspec->src)) { - string_list_append(&reversed, refspec->src); - } - } - - for (i = 0; !matched_negative && i < reversed.nr; i++) { - if (omit_name_by_refspec(reversed.items[i].string, rs)) - matched_negative = 1; - } - - string_list_clear(&reversed, 0); - - return matched_negative; -} - -static void query_refspecs_multiple(struct refspec *rs, - struct refspec_item *query, - struct string_list *results) -{ - int i; - int find_src = !query->src; - - if (find_src && !query->dst) - BUG("query_refspecs_multiple: need either src or dst"); - - if (query_matches_negative_refspec(rs, query)) - return; - - 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; - char **result = find_src ? &query->src : &query->dst; - - if (!refspec->dst || refspec->negative) - continue; - if (refspec->pattern) { - if (match_name_with_pattern(key, needle, value, result)) - string_list_append_nodup(results, *result); - } else if (!strcmp(needle, key)) { - string_list_append(results, value); - } - } -} - -int query_refspecs(struct refspec *rs, struct refspec_item *query) -{ - int i; - int find_src = !query->src; - const char *needle = find_src ? query->dst : query->src; - char **result = find_src ? &query->src : &query->dst; - - if (find_src && !query->dst) - BUG("query_refspecs: need either src or dst"); - - if (query_matches_negative_refspec(rs, query)) - return -1; - - 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; - - if (!refspec->dst || refspec->negative) - continue; - if (refspec->pattern) { - if (match_name_with_pattern(key, needle, value, result)) { - query->force = refspec->force; - return 0; - } - } else if (!strcmp(needle, key)) { - *result = xstrdup(value); - query->force = refspec->force; - return 0; - } - } - return -1; -} - -char *apply_refspecs(struct refspec *rs, const char *name) -{ - struct refspec_item query; - - memset(&query, 0, sizeof(struct refspec_item)); - query.src = (char *)name; - - if (query_refspecs(rs, &query)) - return NULL; - - return query.dst; } int remote_find_tracking(struct remote *remote, struct refspec_item *refspec) { - return query_refspecs(&remote->fetch, refspec); + return refspec_find_match(&remote->fetch, refspec); } static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen, @@ -1122,6 +989,7 @@ void free_one_ref(struct ref *ref) if (!ref) return; free_one_ref(ref->peer_ref); + ref_push_report_free(ref->report); free(ref->remote_status); free(ref->tracking_ref); free(ref->symref); @@ -1194,7 +1062,7 @@ int count_refspec_match(const char *pattern, } } -static void tail_link_ref(struct ref *ref, struct ref ***tail) +void tail_link_ref(struct ref *ref, struct ref ***tail) { **tail = ref; while (ref->next) @@ -1457,9 +1325,9 @@ static char *get_ref_match(const struct refspec *rs, const struct ref *ref, const char *dst_side = item->dst ? item->dst : item->src; int match; if (direction == FROM_SRC) - match = match_name_with_pattern(item->src, ref->name, dst_side, &name); + match = match_refname_with_pattern(item->src, ref->name, dst_side, &name); else - match = match_name_with_pattern(dst_side, ref->name, item->src, &name); + match = match_refname_with_pattern(dst_side, ref->name, item->src, &name); if (match) { matching_refs = i; break; @@ -1495,7 +1363,7 @@ static struct ref **tail_ref(struct ref **head) struct tips { struct commit **tip; - int nr, alloc; + size_t nr, alloc; }; static void add_to_tips(struct tips *tips, const struct object_id *oid) @@ -1562,7 +1430,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds const int reachable_flag = 1; struct commit_list *found_commits; struct commit **src_commits; - int nr_src_commits = 0, alloc_src_commits = 16; + size_t nr_src_commits = 0, alloc_src_commits = 16; ALLOC_ARRAY(src_commits, alloc_src_commits); for_each_string_list_item(item, &src_tag) { @@ -2077,7 +1945,7 @@ static struct ref *get_expanded_map(const struct ref *remote_refs, if (strchr(ref->name, '^')) continue; /* a dereference item */ - if (match_name_with_pattern(refspec->src, ref->name, + if (match_refname_with_pattern(refspec->src, ref->name, refspec->dst, &expn_name) && !ignore_symref_update(expn_name, &scratch)) { struct ref *cpy = copy_ref(ref); @@ -2429,7 +2297,7 @@ struct ref *get_local_heads(void) struct ref *guess_remote_head(const struct ref *head, const struct ref *refs, - int all) + unsigned flags) { const struct ref *r; struct ref *list = NULL; @@ -2447,8 +2315,10 @@ struct ref *guess_remote_head(const struct ref *head, return copy_ref(find_ref_by_name(refs, head->symref)); /* If a remote branch exists with the default branch name, let's use it. */ - if (!all) { - char *default_branch = repo_default_branch_name(the_repository, 0); + if (!(flags & REMOTE_GUESS_HEAD_ALL)) { + char *default_branch = + repo_default_branch_name(the_repository, + flags & REMOTE_GUESS_HEAD_QUIET); char *ref = xstrfmt("refs/heads/%s", default_branch); r = find_ref_by_name(refs, ref); @@ -2471,7 +2341,7 @@ struct ref *guess_remote_head(const struct ref *head, oideq(&r->old_oid, &head->old_oid)) { *tail = copy_ref(r); tail = &((*tail)->next); - if (!all) + if (!(flags & REMOTE_GUESS_HEAD_ALL)) break; } } @@ -2495,7 +2365,7 @@ static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, memset(&query, 0, sizeof(struct refspec_item)); query.dst = (char *)refname; - query_refspecs_multiple(info->rs, &query, &matches); + refspec_find_all_matches(info->rs, &query, &matches); if (matches.nr == 0) goto clean_exit; /* No matches */ @@ -2833,9 +2703,9 @@ void apply_push_cas(struct push_cas_option *cas, struct remote_state *remote_state_new(void) { - struct remote_state *r = xmalloc(sizeof(*r)); + struct remote_state *r; - memset(r, 0, sizeof(*r)); + CALLOC_ARRAY(r, 1); hashmap_init(&r->remotes_hash, remotes_hash_cmp, NULL, 0); hashmap_init(&r->branches_hash, branches_hash_cmp, NULL, 0); @@ -2963,3 +2833,13 @@ char *relative_url(const char *remote_url, const char *url, free(out); return strbuf_detach(&sb, NULL); } + +int valid_remote_name(const char *name) +{ + int result; + struct strbuf refspec = STRBUF_INIT; + strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name); + result = valid_fetch_refspec(refspec.buf); + strbuf_release(&refspec); + return result; +} |
