}
if (!prefixcmp(key, "url.")) {
struct rewrite *rewrite;
- name = key + 5;
+ name = key + 4;
subkey = strrchr(name, '.');
if (!subkey)
return 0;
return 0;
}
remote = make_remote(name, subkey - name);
- if (!value) {
- /* if we ever have a boolean variable, e.g. "remote.*.disabled"
- * [remote "frotz"]
- * disabled
- * is a valid way to set it to true; we get NULL in value so
- * we need to handle it here.
- *
- * if (!strcmp(subkey, ".disabled")) {
- * val = git_config_bool(key, value);
- * return 0;
- * } else
- *
- */
- return 0; /* ignore unknown booleans */
- }
- if (!strcmp(subkey, ".url")) {
- add_url(remote, xstrdup(value));
+ if (!strcmp(subkey, ".mirror"))
+ remote->mirror = git_config_bool(key, value);
+ else if (!strcmp(subkey, ".skipdefaultupdate"))
+ remote->skip_default_update = git_config_bool(key, value);
+
+ else if (!strcmp(subkey, ".url")) {
+ const char *v;
+ if (git_config_string(&v, key, value))
+ return -1;
+ add_url(remote, v);
} else if (!strcmp(subkey, ".push")) {
- add_push_refspec(remote, xstrdup(value));
+ const char *v;
+ if (git_config_string(&v, key, value))
+ return -1;
+ add_push_refspec(remote, v);
} else if (!strcmp(subkey, ".fetch")) {
- add_fetch_refspec(remote, xstrdup(value));
+ const char *v;
+ if (git_config_string(&v, key, value))
+ return -1;
+ add_fetch_refspec(remote, v);
} else if (!strcmp(subkey, ".receivepack")) {
+ const char *v;
+ if (git_config_string(&v, key, value))
+ return -1;
if (!remote->receivepack)
- remote->receivepack = xstrdup(value);
+ remote->receivepack = v;
else
error("more than one receivepack given, using the first");
} else if (!strcmp(subkey, ".uploadpack")) {
+ const char *v;
+ if (git_config_string(&v, key, value))
+ return -1;
if (!remote->uploadpack)
- remote->uploadpack = xstrdup(value);
+ remote->uploadpack = v;
else
error("more than one uploadpack given, using the first");
} else if (!strcmp(subkey, ".tagopt")) {
if (!strcmp(value, "--no-tags"))
remote->fetch_tags = -1;
} else if (!strcmp(subkey, ".proxy")) {
- remote->http_proxy = xstrdup(value);
- } else if (!strcmp(subkey, ".skipdefaultupdate"))
- remote->skip_default_update = 1;
+ return git_config_string((const char **)&remote->http_proxy,
+ key, value);
+ }
return 0;
}
alias_all_urls();
}
-static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch)
+static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
{
int i;
int st;
return rs;
invalid:
+ if (verify) {
+ free(rs);
+ return NULL;
+ }
die("Invalid refspec '%s'", refspec[i]);
}
+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);
+ if (refspec)
+ free(refspec);
+ return !!refspec;
+}
+
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec)
{
- return parse_refspec_internal(nr_refspec, refspec, 1);
+ 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);
+ return parse_refspec_internal(nr_refspec, refspec, 0, 0);
}
static int valid_remote_nick(const char *name)
return ret;
}
+struct ref *alloc_ref_from_str(const char* str)
+{
+ struct ref *ret = alloc_ref(strlen(str) + 1);
+ strcpy(ret->name, str);
+ return ret;
+}
+
static struct ref *copy_ref(const struct ref *ref)
{
struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1);
return ret;
}
+void free_ref(struct ref *ref)
+{
+ if (!ref)
+ return;
+ free(ref->remote_status);
+ free(ref->symref);
+ free(ref);
+}
+
void free_refs(struct ref *ref)
{
struct ref *next;
while (ref) {
next = ref->next;
free(ref->peer_ref);
- free(ref);
+ free_ref(ref);
ref = next;
}
}
{
unsigned char sha1[20];
struct ref *ref;
- int len;
if (!*name) {
ref = alloc_ref(20);
}
if (get_sha1(name, sha1))
return NULL;
- len = strlen(name) + 1;
- ref = alloc_ref(len);
- memcpy(ref->name, name, len);
+ ref = alloc_ref_from_str(name);
hashcpy(ref->new_sha1, sha1);
return ref;
}
static struct ref *make_linked_ref(const char *name, struct ref ***tail)
{
- struct ref *ret;
- size_t len;
-
- len = strlen(name) + 1;
- ret = alloc_ref(len);
- memcpy(ret->name, name, len);
+ struct ref *ret = alloc_ref_from_str(name);
tail_link_ref(ret, tail);
return ret;
}
+static char *guess_ref(const char *name, struct ref *peer)
+{
+ struct strbuf buf = STRBUF_INIT;
+ unsigned char sha1[20];
+
+ const char *r = resolve_ref(peer->name, sha1, 1, NULL);
+ if (!r)
+ return NULL;
+
+ if (!prefixcmp(r, "refs/heads/"))
+ strbuf_addstr(&buf, "refs/heads/");
+ else if (!prefixcmp(r, "refs/tags/"))
+ strbuf_addstr(&buf, "refs/tags/");
+ else
+ return NULL;
+
+ strbuf_addstr(&buf, name);
+ return strbuf_detach(&buf, NULL);
+}
+
static int match_explicit(struct ref *src, struct ref *dst,
struct ref ***dst_tail,
struct refspec *rs,
struct ref *matched_src, *matched_dst;
const char *dst_value = rs->dst;
+ char *dst_guess;
if (rs->pattern)
return errs;
case 0:
if (!memcmp(dst_value, "refs/", 5))
matched_dst = make_linked_ref(dst_value, dst_tail);
+ else if((dst_guess = guess_ref(dst_value, matched_src)))
+ matched_dst = make_linked_ref(dst_guess, dst_tail);
else
- error("dst refspec %s does not match any "
- "existing ref on the remote and does "
- "not start with refs/.", dst_value);
+ error("unable to push to unqualified destination: %s\n"
+ "The destination refspec neither matches an "
+ "existing ref on the remote nor\n"
+ "begins with refs/, and we are unable to "
+ "guess a prefix based on the source ref.",
+ dst_value);
break;
default:
matched_dst = NULL;
return NULL;
if (!prefixcmp(name, "refs/")) {
- ret = alloc_ref(strlen(name) + 1);
- strcpy(ret->name, name);
- return ret;
+ return alloc_ref_from_str(name);
}
if (!prefixcmp(name, "heads/") ||
return 0;
}
+
+int resolve_remote_symref(struct ref *ref, struct ref *list)
+{
+ if (!ref->symref)
+ return 0;
+ for (; list; list = list->next)
+ if (!strcmp(ref->symref, list->name)) {
+ hashcpy(ref->old_sha1, list->old_sha1);
+ return 0;
+ }
+ return 1;
+}