#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;
} 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;
}
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;
}
/*
- * We need to make sure the tracking branches are well formed, but a
+ * We need to make sure the remote-tracking branches are well formed, but a
* wildcard refspec in "struct refspec" must have a trailing slash. We
* temporarily drop the trailing '/' while calling check_ref_format(),
* and put it back. The caller knows that a CHECK_REF_FORMAT_ONELEVEL
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;
}
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))
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);
void ref_remove_duplicates(struct ref *ref_map)
{
- struct string_list refs = { NULL, 0, 0, 0 };
+ struct string_list refs = STRING_LIST_INIT_NODUP;
struct string_list_item *item = NULL;
struct ref *prev = NULL, *next = NULL;
for (; ref_map; prev = ref_map, ref_map = next) {
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))
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);
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;
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;
struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
{
struct ref *ref, *stale_refs = NULL;
- struct string_list ref_names = { NULL, 0, 0, 0 };
+ struct string_list ref_names = STRING_LIST_INIT_NODUP;
struct stale_heads_info info;
info.remote = remote;
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);