static struct remote **remotes;
static int remotes_alloc;
static int remotes_nr;
+static struct hashmap remotes_hash;
static struct branch **branches;
static int branches_alloc;
add_pushurl_alias(remote, url);
}
+struct remotes_hash_key {
+ const char *str;
+ int len;
+};
+
+static int remotes_hash_cmp(const struct remote *a, const struct remote *b, const struct remotes_hash_key *key)
+{
+ if (key)
+ return strncmp(a->name, key->str, key->len) || a->name[key->len];
+ else
+ return strcmp(a->name, b->name);
+}
+
+static inline void init_remotes_hash(void)
+{
+ if (!remotes_hash.cmpfn)
+ hashmap_init(&remotes_hash, (hashmap_cmp_fn)remotes_hash_cmp, 0);
+}
+
static struct remote *make_remote(const char *name, int len)
{
- struct remote *ret;
- int i;
+ struct remote *ret, *replaced;
+ struct remotes_hash_key lookup;
+ struct hashmap_entry lookup_entry;
- for (i = 0; i < remotes_nr; i++) {
- if (len ? (!strncmp(name, remotes[i]->name, len) &&
- !remotes[i]->name[len]) :
- !strcmp(name, remotes[i]->name))
- return remotes[i];
- }
+ if (!len)
+ len = strlen(name);
+
+ init_remotes_hash();
+ lookup.str = name;
+ lookup.len = len;
+ hashmap_entry_init(&lookup_entry, memhash(name, len));
+
+ if ((ret = hashmap_get(&remotes_hash, &lookup_entry, &lookup)) != NULL)
+ return ret;
ret = xcalloc(1, sizeof(struct remote));
ret->prune = -1; /* unspecified */
ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
remotes[remotes_nr++] = ret;
- if (len)
- ret->name = xstrndup(name, len);
- else
- ret->name = xstrdup(name);
+ ret->name = xstrndup(name, len);
+
+ hashmap_entry_init(ret, lookup_entry.hash);
+ replaced = hashmap_put(&remotes_hash, ret);
+ assert(replaced == NULL); /* no previous entry overwritten */
return ret;
}
int remote_is_configured(const char *name)
{
- int i;
+ struct remotes_hash_key lookup;
+ struct hashmap_entry lookup_entry;
read_config();
- for (i = 0; i < remotes_nr; i++)
- if (!strcmp(name, remotes[i]->name))
- return 1;
- return 0;
+ init_remotes_hash();
+ lookup.str = name;
+ lookup.len = strlen(name);
+ hashmap_entry_init(&lookup_entry, memhash(name, lookup.len));
+
+ return hashmap_get(&remotes_hash, &lookup_entry, &lookup) != NULL;
}
int for_each_remote(each_remote_fn fn, void *priv)
init_revisions(&revs, NULL);
setup_revisions(rev_argc, rev_argv, &revs, NULL);
- prepare_revision_walk(&revs);
+ if (prepare_revision_walk(&revs))
+ die("revision walk setup failed");
/* ... and count the commits on each side. */
*num_ours = 0;
int format_tracking_info(struct branch *branch, struct strbuf *sb)
{
int ours, theirs;
- const char *base;
+ char *base;
int upstream_is_gone = 0;
switch (stat_tracking_info(branch, &ours, &theirs)) {
break;
}
- base = branch->merge[0]->dst;
- base = shorten_unambiguous_ref(base, 0);
+ base = shorten_unambiguous_ref(branch->merge[0]->dst, 0);
if (upstream_is_gone) {
strbuf_addf(sb,
_("Your branch is based on '%s', but the upstream is gone.\n"),
strbuf_addf(sb,
_(" (use \"git pull\" to merge the remote branch into yours)\n"));
}
+ free(base);
return 1;
}