+
+/*
+ * Repository references
+ */
+
+static struct ref *refs;
+size_t refs_size;
+
+static struct ref **
+get_refs(char *id)
+{
+ struct ref **id_refs = NULL;
+ size_t id_refs_size = 0;
+ size_t i;
+
+ for (i = 0; i < refs_size; i++) {
+ struct ref **tmp;
+
+ if (strcmp(id, refs[i].id))
+ continue;
+
+ tmp = realloc(id_refs, (id_refs_size + 1) * sizeof(*id_refs));
+ if (!tmp) {
+ if (id_refs)
+ free(id_refs);
+ return NULL;
+ }
+
+ id_refs = tmp;
+ id_refs[id_refs_size++] = &refs[i];
+ if (id_refs_size > 1)
+ id_refs[id_refs_size - 1]->next = 1;
+ }
+
+ return id_refs;
+}
+
+static int
+load_refs(void)
+{
+ char *cmd_env = getenv("TIG_LS_REMOTE");
+ char *cmd = cmd_env ? cmd_env : TIG_LS_REMOTE;
+ FILE *pipe = popen(cmd, "r");
+ char buffer[BUFSIZ];
+ char *line;
+
+ if (!pipe)
+ return ERR;
+
+ while ((line = fgets(buffer, sizeof(buffer), pipe))) {
+ char *name = strchr(line, '\t');
+ struct ref *ref;
+ int namelen;
+ bool tag = FALSE;
+
+ if (!name)
+ continue;
+
+ *name++ = 0;
+ namelen = strlen(name) - 1;
+ if (name[namelen - 1] == '}') {
+ while (namelen > 0 && name[namelen] != '^')
+ namelen--;
+ }
+ name[namelen] = 0;
+
+ if (!strncmp(name, "refs/tags/", STRING_SIZE("refs/tags/"))) {
+ name += STRING_SIZE("refs/tags/");
+ tag = TRUE;
+ }
+
+ refs = realloc(refs, sizeof(*refs) * (refs_size + 1));
+ if (!refs)
+ return ERR;
+
+ ref = &refs[refs_size++];
+ ref->tag = tag;
+ ref->name = strdup(name);
+ if (!ref->name)
+ return ERR;
+
+ string_copy(ref->id, line);
+ }
+
+ if (ferror(pipe))
+ return ERR;
+
+ pclose(pipe);
+
+ return OK;
+}
+