-static char *resolve_symref(const char *src, const char *prefix)
-{
- unsigned char sha1[20];
- int flag;
- const char *dst;
-
- dst = resolve_ref_unsafe(src, 0, sha1, &flag);
- if (!(dst && (flag & REF_ISSYMREF)))
- return NULL;
- if (prefix)
- skip_prefix(dst, prefix, &dst);
- return xstrdup(dst);
-}
-
-static int match_patterns(const char **pattern, const char *refname)
-{
- if (!*pattern)
- return 1; /* no pattern always matches */
- while (*pattern) {
- if (!wildmatch(*pattern, refname, 0, NULL))
- return 1;
- pattern++;
- }
- return 0;
-}
-
-/*
- * Allocate memory for a new ref_array_item and insert that into the
- * given ref_array. Doesn't take the objectname unlike
- * new_ref_array_item(). This is a temporary function which will be
- * removed when we port branch.c to use ref-filter APIs.
- */
-static struct ref_array_item *ref_array_append(struct ref_array *array, const char *refname)
-{
- size_t len = strlen(refname);
- struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + len + 1);
- memcpy(ref->refname, refname, len);
- ref->refname[len] = '\0';
- REALLOC_ARRAY(array->items, array->nr + 1);
- array->items[array->nr++] = ref;
- return ref;
-}
-
-static int append_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data)
-{
- struct ref_filter_cbdata *cb = (struct ref_filter_cbdata *)(cb_data);
- struct ref_filter *filter = cb->filter;
- struct ref_array *array = cb->array;
- struct ref_array_item *item;
- struct commit *commit;
- int kind, i;
- const char *prefix, *orig_refname = refname;
-
- static struct {
- int kind;
- const char *prefix;
- } ref_kind[] = {
- { FILTER_REFS_BRANCHES, "refs/heads/" },
- { FILTER_REFS_REMOTES, "refs/remotes/" },
- };
-
- /* Detect kind */
- for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
- prefix = ref_kind[i].prefix;
- if (skip_prefix(refname, prefix, &refname)) {
- kind = ref_kind[i].kind;
- break;
- }
- }
- if (ARRAY_SIZE(ref_kind) <= i) {
- if (!strcmp(refname, "HEAD"))
- kind = FILTER_REFS_DETACHED_HEAD;
- else
- return 0;
- }
-
- /* Don't add types the caller doesn't want */
- if ((kind & filter->kind) == 0)
- return 0;
-
- if (!match_patterns(filter->name_patterns, refname))
- return 0;
-
- commit = NULL;
- if (filter->verbose || filter->with_commit || filter->merge != REF_FILTER_MERGED_NONE) {
- commit = lookup_commit_reference_gently(oid->hash, 1);
- if (!commit)
- return 0;
-
- /* Filter with with_commit if specified */
- if (!is_descendant_of(commit, filter->with_commit))
- return 0;
-
- if (filter->merge != REF_FILTER_MERGED_NONE)
- add_pending_object(array->revs,
- (struct object *)commit, refname);
- }
-
- item = ref_array_append(array, refname);
-
- /* Record the new item */
- item->kind = kind;
- item->commit = commit;
- item->symref = resolve_symref(orig_refname, prefix);
- item->ignore = 0;
-
- return 0;
-}
-
-static int ref_cmp(const void *r1, const void *r2)
-{
- struct ref_array_item *c1 = *((struct ref_array_item **)r1);
- struct ref_array_item *c2 = *((struct ref_array_item **)r2);
-
- if (c1->kind != c2->kind)
- return c1->kind - c2->kind;
- return strcmp(c1->refname, c2->refname);
-}
-