summaryrefslogtreecommitdiff
path: root/remote.c
diff options
context:
space:
mode:
Diffstat (limited to 'remote.c')
-rw-r--r--remote.c105
1 files changed, 95 insertions, 10 deletions
diff --git a/remote.c b/remote.c
index b979a9642b..afbba47460 100644
--- a/remote.c
+++ b/remote.c
@@ -53,6 +53,11 @@ static struct rewrites rewrites_push;
#define BUF_SIZE (2048)
static char buffer[BUF_SIZE];
+static int valid_remote(const struct remote *remote)
+{
+ return (!!remote->url) || (!!remote->foreign_vcs);
+}
+
static const char *alias_url(const char *url, struct rewrites *r)
{
int i, j;
@@ -438,9 +443,13 @@ static int handle_config(const char *key, const char *value, void *cb)
} else if (!strcmp(subkey, ".tagopt")) {
if (!strcmp(value, "--no-tags"))
remote->fetch_tags = -1;
+ else if (!strcmp(value, "--tags"))
+ remote->fetch_tags = 2;
} else if (!strcmp(subkey, ".proxy")) {
return git_config_string((const char **)&remote->http_proxy,
key, value);
+ } else if (!strcmp(subkey, ".vcs")) {
+ return git_config_string(&remote->foreign_vcs, key, value);
}
return 0;
}
@@ -469,7 +478,7 @@ static void read_config(void)
unsigned char sha1[20];
const char *head_ref;
int flag;
- if (default_remote_name) // did this already
+ if (default_remote_name) /* did this already */
return;
default_remote_name = xstrdup("origin");
current_branch = NULL;
@@ -650,10 +659,9 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
int valid_fetch_refspec(const char *fetch_refspec_str)
{
- const char *fetch_refspec[] = { fetch_refspec_str };
struct refspec *refspec;
- refspec = parse_refspec_internal(1, fetch_refspec, 1, 1);
+ refspec = parse_refspec_internal(1, &fetch_refspec_str, 1, 1);
free_refspecs(refspec, 1);
return !!refspec;
}
@@ -668,6 +676,16 @@ static 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;
+ 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))
@@ -690,14 +708,14 @@ struct remote *remote_get(const char *name)
ret = make_remote(name, 0);
if (valid_remote_nick(name)) {
- if (!ret->url)
+ if (!valid_remote(ret))
read_remotes_file(ret);
- if (!ret->url)
+ if (!valid_remote(ret))
read_branches_file(ret);
}
- if (name_given && !ret->url)
+ if (name_given && !valid_remote(ret))
add_url_alias(ret, name);
- if (!ret->url)
+ 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);
@@ -744,7 +762,7 @@ void ref_remove_duplicates(struct ref *ref_map)
if (!ref_map->peer_ref)
continue;
- item = string_list_lookup(ref_map->peer_ref->name, &refs);
+ item = string_list_lookup(&refs, ref_map->peer_ref->name);
if (item) {
if (strcmp(((struct ref *)item->util)->name,
ref_map->name))
@@ -759,7 +777,7 @@ void ref_remove_duplicates(struct ref *ref_map)
continue;
}
- item = string_list_insert(ref_map->peer_ref->name, &refs);
+ item = string_list_insert(&refs, ref_map->peer_ref->name);
item->util = ref_map;
}
string_list_clear(&refs, 0);
@@ -810,6 +828,23 @@ static int match_name_with_pattern(const char *key, const char *name,
return ret;
}
+char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
+ const char *name)
+{
+ int i;
+ char *ret = NULL;
+ for (i = 0; i < nr_refspec; i++) {
+ struct refspec *refspec = refspecs + i;
+ if (refspec->pattern) {
+ if (match_name_with_pattern(refspec->src, name,
+ refspec->dst, &ret))
+ return ret;
+ } else if (!strcmp(refspec->src, name))
+ return strdup(refspec->dst);
+ }
+ return NULL;
+}
+
int remote_find_tracking(struct remote *remote, struct refspec *refspec)
{
int find_src = refspec->src == NULL;
@@ -1213,6 +1248,56 @@ int match_refs(struct ref *src, struct ref **dst,
return 0;
}
+void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
+ int force_update)
+{
+ struct ref *ref;
+
+ for (ref = remote_refs; ref; ref = ref->next) {
+ if (ref->peer_ref)
+ hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+ else if (!send_mirror)
+ continue;
+
+ ref->deletion = is_null_sha1(ref->new_sha1);
+ if (!ref->deletion &&
+ !hashcmp(ref->old_sha1, ref->new_sha1)) {
+ ref->status = REF_STATUS_UPTODATE;
+ continue;
+ }
+
+ /* This part determines what can overwrite what.
+ * The rules are:
+ *
+ * (0) you can always use --force or +A:B notation to
+ * selectively force individual ref pairs.
+ *
+ * (1) if the old thing does not exist, it is OK.
+ *
+ * (2) if you do not have the old thing, you are not allowed
+ * to overwrite it; you would not know what you are losing
+ * otherwise.
+ *
+ * (3) if both new and old are commit-ish, and new is a
+ * descendant of old, it is OK.
+ *
+ * (4) regardless of all of the above, removing :B is
+ * always allowed.
+ */
+
+ ref->nonfastforward =
+ !ref->deletion &&
+ !is_null_sha1(ref->old_sha1) &&
+ (!has_sha1_file(ref->old_sha1)
+ || !ref_newer(ref->new_sha1, ref->old_sha1));
+
+ if (ref->nonfastforward && !ref->force && !force_update) {
+ ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+ continue;
+ }
+ }
+}
+
struct branch *branch_get(const char *name)
{
struct branch *ret;
@@ -1625,7 +1710,7 @@ struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
info.ref_names = &ref_names;
info.stale_refs_tail = &stale_refs;
for (ref = fetch_map; ref; ref = ref->next)
- string_list_append(ref->name, &ref_names);
+ string_list_append(&ref_names, ref->name);
sort_string_list(&ref_names);
for_each_ref(get_stale_heads_cb, &info);
string_list_clear(&ref_names, 0);