aboutsummaryrefslogtreecommitdiffstats
path: root/remote.c
diff options
context:
space:
mode:
Diffstat (limited to 'remote.c')
-rw-r--r--remote.c128
1 files changed, 104 insertions, 24 deletions
diff --git a/remote.c b/remote.c
index f43cf5e7a4..10104d11e3 100644
--- a/remote.c
+++ b/remote.c
@@ -24,6 +24,7 @@
#include "advice.h"
#include "connect.h"
#include "parse-options.h"
+#include "transport.h"
enum map_direction { FROM_SRC, FROM_DST };
@@ -143,6 +144,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
ret->name = xstrndup(name, len);
refspec_init(&ret->push, REFSPEC_PUSH);
refspec_init(&ret->fetch, REFSPEC_FETCH);
+ string_list_init_dup(&ret->server_options);
ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
remote_state->remotes_alloc);
@@ -166,6 +168,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)
@@ -243,6 +246,17 @@ static struct branch *make_branch(struct remote_state *remote_state,
return ret;
}
+static void branch_release(struct branch *branch)
+{
+ free((char *)branch->name);
+ free((char *)branch->refname);
+ free(branch->remote_name);
+ free(branch->pushremote_name);
+ for (int i = 0; i < branch->merge_nr; i++)
+ refspec_item_clear(branch->merge[i]);
+ free(branch->merge);
+}
+
static struct rewrite *make_rewrite(struct rewrites *r,
const char *base, size_t len)
{
@@ -263,6 +277,14 @@ static struct rewrite *make_rewrite(struct rewrites *r,
return ret;
}
+static void rewrites_release(struct rewrites *r)
+{
+ for (int i = 0; i < r->rewrite_nr; i++)
+ free((char *)r->rewrite[i]->base);
+ free(r->rewrite);
+ memset(r, 0, sizeof(*r));
+}
+
static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
{
ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc);
@@ -373,8 +395,10 @@ static int handle_config(const char *key, const char *value,
return -1;
branch = make_branch(remote_state, name, namelen);
if (!strcmp(subkey, "remote")) {
+ FREE_AND_NULL(branch->remote_name);
return git_config_string(&branch->remote_name, key, value);
} else if (!strcmp(subkey, "pushremote")) {
+ FREE_AND_NULL(branch->pushremote_name);
return git_config_string(&branch->pushremote_name, key, value);
} else if (!strcmp(subkey, "merge")) {
if (!value)
@@ -406,9 +430,11 @@ static int handle_config(const char *key, const char *value,
return 0;
/* Handle remote.* variables */
- if (!name && !strcmp(subkey, "pushdefault"))
+ if (!name && !strcmp(subkey, "pushdefault")) {
+ FREE_AND_NULL(remote_state->pushremote_name);
return git_config_string(&remote_state->pushremote_name, key,
value);
+ }
if (!name)
return 0;
@@ -475,13 +501,19 @@ static int handle_config(const char *key, const char *value,
else if (!strcmp(value, "--tags"))
remote->fetch_tags = 2;
} else if (!strcmp(subkey, "proxy")) {
+ FREE_AND_NULL(remote->http_proxy);
return git_config_string(&remote->http_proxy,
key, value);
} else if (!strcmp(subkey, "proxyauthmethod")) {
+ FREE_AND_NULL(remote->http_proxy_authmethod);
return git_config_string(&remote->http_proxy_authmethod,
key, 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);
}
return 0;
}
@@ -499,6 +531,7 @@ static void alias_all_urls(struct remote_state *remote_state)
if (alias)
strvec_replace(&remote_state->remotes[i]->pushurl,
j, alias);
+ free(alias);
}
add_pushurl_aliases = remote_state->remotes[i]->pushurl.nr == 0;
for (j = 0; j < remote_state->remotes[i]->url.nr; j++) {
@@ -512,6 +545,7 @@ static void alias_all_urls(struct remote_state *remote_state)
if (alias)
strvec_replace(&remote_state->remotes[i]->url,
j, alias);
+ free(alias);
}
}
}
@@ -604,7 +638,7 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
static struct remote *remotes_remote_get(struct remote_state *remote_state,
const char *name);
-const char *remote_ref_for_branch(struct branch *branch, int for_push)
+char *remote_ref_for_branch(struct branch *branch, int for_push)
{
read_config(the_repository, 0);
die_on_missing_branch(the_repository, branch);
@@ -612,11 +646,11 @@ const char *remote_ref_for_branch(struct branch *branch, int for_push)
if (branch) {
if (!for_push) {
if (branch->merge_nr) {
- return branch->merge_name[0];
+ return xstrdup(branch->merge_name[0]);
}
} else {
- const char *dst,
- *remote_name = remotes_pushremote_for_branch(
+ char *dst;
+ const char *remote_name = remotes_pushremote_for_branch(
the_repository->remote_state, branch,
NULL);
struct remote *remote = remotes_remote_get(
@@ -840,6 +874,20 @@ struct strvec *push_url_of_remote(struct remote *remote)
return remote->pushurl.nr ? &remote->pushurl : &remote->url;
}
+void ref_push_report_free(struct ref_push_report *report)
+{
+ while (report) {
+ struct ref_push_report *next = report->next;
+
+ free(report->ref_name);
+ free(report->old_oid);
+ free(report->new_oid);
+ free(report);
+
+ report = next;
+ }
+}
+
static int match_name_with_pattern(const char *key, const char *name,
const char *value, char **result)
{
@@ -1094,7 +1142,9 @@ 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);
free(ref);
}
@@ -1316,18 +1366,21 @@ static int match_explicit(struct ref *src, struct ref *dst,
struct ref ***dst_tail,
struct refspec_item *rs)
{
- struct ref *matched_src, *matched_dst;
- int allocated_src;
+ struct ref *matched_src = NULL, *matched_dst = NULL;
+ int allocated_src = 0, ret;
const char *dst_value = rs->dst;
char *dst_guess;
- if (rs->pattern || rs->matching || rs->negative)
- return 0;
+ if (rs->pattern || rs->matching || rs->negative) {
+ ret = 0;
+ goto out;
+ }
- matched_src = matched_dst = NULL;
- if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0)
- return -1;
+ if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0) {
+ ret = -1;
+ goto out;
+ }
if (!dst_value) {
int flag;
@@ -1366,18 +1419,30 @@ static int match_explicit(struct ref *src, struct ref *dst,
dst_value);
break;
}
- if (!matched_dst)
- return -1;
- if (matched_dst->peer_ref)
- return error(_("dst ref %s receives from more than one src"),
- matched_dst->name);
- else {
+
+ if (!matched_dst) {
+ ret = -1;
+ goto out;
+ }
+
+ if (matched_dst->peer_ref) {
+ ret = error(_("dst ref %s receives from more than one src"),
+ matched_dst->name);
+ goto out;
+ } else {
matched_dst->peer_ref = allocated_src ?
matched_src :
copy_ref(matched_src);
matched_dst->force = rs->force;
+ matched_src = NULL;
}
- return 0;
+
+ ret = 0;
+
+out:
+ if (allocated_src)
+ free_one_ref(matched_src);
+ return ret;
}
static int match_explicit_refs(struct ref *src, struct ref *dst,
@@ -2038,6 +2103,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
!ignore_symref_update(expn_name, &scratch)) {
struct ref *cpy = copy_ref(ref);
+ if (cpy->peer_ref)
+ free_one_ref(cpy->peer_ref);
cpy->peer_ref = alloc_ref(expn_name);
if (refspec->force)
cpy->peer_ref->force = 1;
@@ -2354,7 +2421,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
return 1;
}
-static int one_local_ref(const char *refname, const struct object_id *oid,
+static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
@@ -2439,7 +2506,7 @@ struct stale_heads_info {
struct refspec *rs;
};
-static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
+static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct stale_heads_info *info = cb_data;
@@ -2498,7 +2565,7 @@ struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map)
/*
* Compare-and-swap
*/
-static void clear_cas_option(struct push_cas_option *cas)
+void clear_cas_option(struct push_cas_option *cas)
{
int i;
@@ -2575,8 +2642,10 @@ static int remote_tracking(struct remote *remote, const char *refname,
dst = apply_refspecs(&remote->fetch, refname);
if (!dst)
return -1; /* no tracking ref for refname at remote */
- if (refs_read_ref(get_main_ref_store(the_repository), dst, oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), dst, oid)) {
+ free(dst);
return -1; /* we know what the tracking ref is but we cannot read it */
+ }
*dst_refname = dst;
return 0;
@@ -2726,6 +2795,7 @@ static void check_if_includes_upstream(struct ref *remote)
if (is_reachable_in_reflog(local->name, remote) <= 0)
remote->unreachable = 1;
+ free_one_ref(local);
}
static void apply_cas(struct push_cas_option *cas,
@@ -2795,16 +2865,26 @@ struct remote_state *remote_state_new(void)
void remote_state_clear(struct remote_state *remote_state)
{
+ struct hashmap_iter iter;
+ struct branch *b;
int i;
for (i = 0; i < remote_state->remotes_nr; i++)
remote_clear(remote_state->remotes[i]);
FREE_AND_NULL(remote_state->remotes);
+ FREE_AND_NULL(remote_state->pushremote_name);
remote_state->remotes_alloc = 0;
remote_state->remotes_nr = 0;
+ rewrites_release(&remote_state->rewrites);
+ rewrites_release(&remote_state->rewrites_push);
+
hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent);
- hashmap_clear_and_free(&remote_state->branches_hash, struct remote, ent);
+ hashmap_for_each_entry(&remote_state->branches_hash, &iter, b, ent) {
+ branch_release(b);
+ free(b);
+ }
+ hashmap_clear(&remote_state->branches_hash);
}
/*