builtin-am: extract patch and commit info with git-mailinfo
[gitweb.git] / ref-filter.c
index cfc0e8a89249fbe2b16aa5f29c26355b206a81b8..f38dee4f605df344315e0202487aeebc623f6582 100644 (file)
@@ -362,7 +362,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
        char *zone;
        unsigned long timestamp;
        long tz;
-       enum date_mode date_mode = DATE_NORMAL;
+       struct date_mode date_mode = { DATE_NORMAL };
        const char *formatp;
 
        /*
@@ -374,7 +374,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
        formatp = strchr(atomname, ':');
        if (formatp != NULL) {
                formatp++;
-               date_mode = parse_date_format(formatp);
+               parse_date_format(formatp, &date_mode);
        }
 
        if (!eoemail)
@@ -385,7 +385,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
        tz = strtol(zone, NULL, 10);
        if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
                goto bad;
-       v->s = xstrdup(show_date(timestamp, tz, date_mode));
+       v->s = xstrdup(show_date(timestamp, tz, &date_mode));
        v->ul = timestamp;
        return;
  bad:
@@ -847,8 +847,10 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
                                                 const unsigned char *objectname,
                                                 int flag)
 {
-       struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item));
-       ref->refname = xstrdup(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';
        hashcpy(ref->objectname, objectname);
        ref->flag = flag;
 
@@ -859,10 +861,10 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
  * A call-back given to for_each_ref().  Filter refs and keep them for
  * later object processing.
  */
-int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data)
 {
        struct ref_filter_cbdata *ref_cbdata = cb_data;
-       struct ref_filter *filter = &ref_cbdata->filter;
+       struct ref_filter *filter = ref_cbdata->filter;
        struct ref_array_item *ref;
 
        if (flag & REF_BAD_NAME) {
@@ -870,6 +872,11 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla
                return 0;
        }
 
+       if (flag & REF_ISBROKEN) {
+               warning("ignoring broken ref %s", refname);
+               return 0;
+       }
+
        if (*filter->name_patterns && !match_name_as_path(filter->name_patterns, refname))
                return 0;
 
@@ -880,8 +887,8 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla
         */
        ref = new_ref_array_item(refname, oid->hash, flag);
 
-       REALLOC_ARRAY(ref_cbdata->array.items, ref_cbdata->array.nr + 1);
-       ref_cbdata->array.items[ref_cbdata->array.nr++] = ref;
+       REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
+       ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
        return 0;
 }
 
@@ -889,7 +896,6 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla
 static void free_array_item(struct ref_array_item *item)
 {
        free((char *)item->symref);
-       free(item->refname);
        free(item);
 }
 
@@ -905,6 +911,28 @@ void ref_array_clear(struct ref_array *array)
        array->nr = array->alloc = 0;
 }
 
+/*
+ * API for filtering a set of refs. Based on the type of refs the user
+ * has requested, we iterate through those refs and apply filters
+ * as per the given ref_filter structure and finally store the
+ * filtered refs in the ref_array structure.
+ */
+int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
+{
+       struct ref_filter_cbdata ref_cbdata;
+
+       ref_cbdata.array = array;
+       ref_cbdata.filter = filter;
+
+       if (type & (FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN))
+               return for_each_rawref(ref_filter_handler, &ref_cbdata);
+       else if (type & FILTER_REFS_ALL)
+               return for_each_ref(ref_filter_handler, &ref_cbdata);
+       else
+               die("filter_refs: invalid type");
+       return 0;
+}
+
 static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
 {
        struct atom_value *va, *vb;