ref-filter.con commit ref-filter: add support for %(contents:lines=X) (1bb38e5)
   1#include "builtin.h"
   2#include "cache.h"
   3#include "parse-options.h"
   4#include "refs.h"
   5#include "wildmatch.h"
   6#include "commit.h"
   7#include "remote.h"
   8#include "color.h"
   9#include "tag.h"
  10#include "quote.h"
  11#include "ref-filter.h"
  12#include "revision.h"
  13#include "utf8.h"
  14
  15typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
  16
  17static struct {
  18        const char *name;
  19        cmp_type cmp_type;
  20} valid_atom[] = {
  21        { "refname" },
  22        { "objecttype" },
  23        { "objectsize", FIELD_ULONG },
  24        { "objectname" },
  25        { "tree" },
  26        { "parent" },
  27        { "numparent", FIELD_ULONG },
  28        { "object" },
  29        { "type" },
  30        { "tag" },
  31        { "author" },
  32        { "authorname" },
  33        { "authoremail" },
  34        { "authordate", FIELD_TIME },
  35        { "committer" },
  36        { "committername" },
  37        { "committeremail" },
  38        { "committerdate", FIELD_TIME },
  39        { "tagger" },
  40        { "taggername" },
  41        { "taggeremail" },
  42        { "taggerdate", FIELD_TIME },
  43        { "creator" },
  44        { "creatordate", FIELD_TIME },
  45        { "subject" },
  46        { "body" },
  47        { "contents" },
  48        { "upstream" },
  49        { "push" },
  50        { "symref" },
  51        { "flag" },
  52        { "HEAD" },
  53        { "color" },
  54        { "align" },
  55        { "end" },
  56};
  57
  58#define REF_FORMATTING_STATE_INIT  { 0, NULL }
  59
  60struct align {
  61        align_type position;
  62        unsigned int width;
  63};
  64
  65struct contents {
  66        unsigned int lines;
  67        struct object_id oid;
  68};
  69
  70struct ref_formatting_stack {
  71        struct ref_formatting_stack *prev;
  72        struct strbuf output;
  73        void (*at_end)(struct ref_formatting_stack *stack);
  74        void *at_end_data;
  75};
  76
  77struct ref_formatting_state {
  78        int quote_style;
  79        struct ref_formatting_stack *stack;
  80};
  81
  82struct atom_value {
  83        const char *s;
  84        union {
  85                struct align align;
  86                struct contents contents;
  87        } u;
  88        void (*handler)(struct atom_value *atomv, struct ref_formatting_state *state);
  89        unsigned long ul; /* used for sorting when not FIELD_STR */
  90};
  91
  92/*
  93 * An atom is a valid field atom listed above, possibly prefixed with
  94 * a "*" to denote deref_tag().
  95 *
  96 * We parse given format string and sort specifiers, and make a list
  97 * of properties that we need to extract out of objects.  ref_array_item
  98 * structure will hold an array of values extracted that can be
  99 * indexed with the "atom number", which is an index into this
 100 * array.
 101 */
 102static const char **used_atom;
 103static cmp_type *used_atom_type;
 104static int used_atom_cnt, need_tagged, need_symref;
 105static int need_color_reset_at_eol;
 106
 107/*
 108 * Used to parse format string and sort specifiers
 109 */
 110int parse_ref_filter_atom(const char *atom, const char *ep)
 111{
 112        const char *sp;
 113        int i, at;
 114
 115        sp = atom;
 116        if (*sp == '*' && sp < ep)
 117                sp++; /* deref */
 118        if (ep <= sp)
 119                die("malformed field name: %.*s", (int)(ep-atom), atom);
 120
 121        /* Do we have the atom already used elsewhere? */
 122        for (i = 0; i < used_atom_cnt; i++) {
 123                int len = strlen(used_atom[i]);
 124                if (len == ep - atom && !memcmp(used_atom[i], atom, len))
 125                        return i;
 126        }
 127
 128        /* Is the atom a valid one? */
 129        for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
 130                int len = strlen(valid_atom[i].name);
 131                /*
 132                 * If the atom name has a colon, strip it and everything after
 133                 * it off - it specifies the format for this entry, and
 134                 * shouldn't be used for checking against the valid_atom
 135                 * table.
 136                 */
 137                const char *formatp = strchr(sp, ':');
 138                if (!formatp || ep < formatp)
 139                        formatp = ep;
 140                if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
 141                        break;
 142        }
 143
 144        if (ARRAY_SIZE(valid_atom) <= i)
 145                die("unknown field name: %.*s", (int)(ep-atom), atom);
 146
 147        /* Add it in, including the deref prefix */
 148        at = used_atom_cnt;
 149        used_atom_cnt++;
 150        REALLOC_ARRAY(used_atom, used_atom_cnt);
 151        REALLOC_ARRAY(used_atom_type, used_atom_cnt);
 152        used_atom[at] = xmemdupz(atom, ep - atom);
 153        used_atom_type[at] = valid_atom[i].cmp_type;
 154        if (*atom == '*')
 155                need_tagged = 1;
 156        if (!strcmp(used_atom[at], "symref"))
 157                need_symref = 1;
 158        return at;
 159}
 160
 161static void quote_formatting(struct strbuf *s, const char *str, int quote_style)
 162{
 163        switch (quote_style) {
 164        case QUOTE_NONE:
 165                strbuf_addstr(s, str);
 166                break;
 167        case QUOTE_SHELL:
 168                sq_quote_buf(s, str);
 169                break;
 170        case QUOTE_PERL:
 171                perl_quote_buf(s, str);
 172                break;
 173        case QUOTE_PYTHON:
 174                python_quote_buf(s, str);
 175                break;
 176        case QUOTE_TCL:
 177                tcl_quote_buf(s, str);
 178                break;
 179        }
 180}
 181
 182static void append_atom(struct atom_value *v, struct ref_formatting_state *state)
 183{
 184        /*
 185         * Quote formatting is only done when the stack has a single
 186         * element. Otherwise quote formatting is done on the
 187         * element's entire output strbuf when the %(end) atom is
 188         * encountered.
 189         */
 190        if (!state->stack->prev)
 191                quote_formatting(&state->stack->output, v->s, state->quote_style);
 192        else
 193                strbuf_addstr(&state->stack->output, v->s);
 194}
 195
 196static void push_stack_element(struct ref_formatting_stack **stack)
 197{
 198        struct ref_formatting_stack *s = xcalloc(1, sizeof(struct ref_formatting_stack));
 199
 200        strbuf_init(&s->output, 0);
 201        s->prev = *stack;
 202        *stack = s;
 203}
 204
 205static void pop_stack_element(struct ref_formatting_stack **stack)
 206{
 207        struct ref_formatting_stack *current = *stack;
 208        struct ref_formatting_stack *prev = current->prev;
 209
 210        if (prev)
 211                strbuf_addbuf(&prev->output, &current->output);
 212        strbuf_release(&current->output);
 213        free(current);
 214        *stack = prev;
 215}
 216
 217static void end_align_handler(struct ref_formatting_stack *stack)
 218{
 219        struct align *align = (struct align *)stack->at_end_data;
 220        struct strbuf s = STRBUF_INIT;
 221
 222        strbuf_utf8_align(&s, align->position, align->width, stack->output.buf);
 223        strbuf_swap(&stack->output, &s);
 224        strbuf_release(&s);
 225}
 226
 227static void align_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state)
 228{
 229        struct ref_formatting_stack *new;
 230
 231        push_stack_element(&state->stack);
 232        new = state->stack;
 233        new->at_end = end_align_handler;
 234        new->at_end_data = &atomv->u.align;
 235}
 236
 237static void end_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state)
 238{
 239        struct ref_formatting_stack *current = state->stack;
 240        struct strbuf s = STRBUF_INIT;
 241
 242        if (!current->at_end)
 243                die(_("format: %%(end) atom used without corresponding atom"));
 244        current->at_end(current);
 245
 246        /*
 247         * Perform quote formatting when the stack element is that of
 248         * a supporting atom. If nested then perform quote formatting
 249         * only on the topmost supporting atom.
 250         */
 251        if (!state->stack->prev->prev) {
 252                quote_formatting(&s, current->output.buf, state->quote_style);
 253                strbuf_swap(&current->output, &s);
 254        }
 255        strbuf_release(&s);
 256        pop_stack_element(&state->stack);
 257}
 258
 259static int match_atom_name(const char *name, const char *atom_name, const char **val)
 260{
 261        const char *body;
 262
 263        if (!skip_prefix(name, atom_name, &body))
 264                return 0; /* doesn't even begin with "atom_name" */
 265        if (!body[0]) {
 266                *val = NULL; /* %(atom_name) and no customization */
 267                return 1;
 268        }
 269        if (body[0] != ':')
 270                return 0; /* "atom_namefoo" is not "atom_name" or "atom_name:..." */
 271        *val = body + 1; /* "atom_name:val" */
 272        return 1;
 273}
 274
 275/*
 276 * In a format string, find the next occurrence of %(atom).
 277 */
 278static const char *find_next(const char *cp)
 279{
 280        while (*cp) {
 281                if (*cp == '%') {
 282                        /*
 283                         * %( is the start of an atom;
 284                         * %% is a quoted per-cent.
 285                         */
 286                        if (cp[1] == '(')
 287                                return cp;
 288                        else if (cp[1] == '%')
 289                                cp++; /* skip over two % */
 290                        /* otherwise this is a singleton, literal % */
 291                }
 292                cp++;
 293        }
 294        return NULL;
 295}
 296
 297/*
 298 * Make sure the format string is well formed, and parse out
 299 * the used atoms.
 300 */
 301int verify_ref_format(const char *format)
 302{
 303        const char *cp, *sp;
 304
 305        need_color_reset_at_eol = 0;
 306        for (cp = format; *cp && (sp = find_next(cp)); ) {
 307                const char *color, *ep = strchr(sp, ')');
 308                int at;
 309
 310                if (!ep)
 311                        return error("malformed format string %s", sp);
 312                /* sp points at "%(" and ep points at the closing ")" */
 313                at = parse_ref_filter_atom(sp + 2, ep);
 314                cp = ep + 1;
 315
 316                if (skip_prefix(used_atom[at], "color:", &color))
 317                        need_color_reset_at_eol = !!strcmp(color, "reset");
 318        }
 319        return 0;
 320}
 321
 322/*
 323 * Given an object name, read the object data and size, and return a
 324 * "struct object".  If the object data we are returning is also borrowed
 325 * by the "struct object" representation, set *eaten as well---it is a
 326 * signal from parse_object_buffer to us not to free the buffer.
 327 */
 328static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
 329{
 330        enum object_type type;
 331        void *buf = read_sha1_file(sha1, &type, sz);
 332
 333        if (buf)
 334                *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
 335        else
 336                *obj = NULL;
 337        return buf;
 338}
 339
 340static int grab_objectname(const char *name, const unsigned char *sha1,
 341                            struct atom_value *v)
 342{
 343        if (!strcmp(name, "objectname")) {
 344                char *s = xmalloc(41);
 345                strcpy(s, sha1_to_hex(sha1));
 346                v->s = s;
 347                return 1;
 348        }
 349        if (!strcmp(name, "objectname:short")) {
 350                v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
 351                return 1;
 352        }
 353        return 0;
 354}
 355
 356/* See grab_values */
 357static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 358{
 359        int i;
 360
 361        for (i = 0; i < used_atom_cnt; i++) {
 362                const char *name = used_atom[i];
 363                struct atom_value *v = &val[i];
 364                if (!!deref != (*name == '*'))
 365                        continue;
 366                if (deref)
 367                        name++;
 368                if (!strcmp(name, "objecttype"))
 369                        v->s = typename(obj->type);
 370                else if (!strcmp(name, "objectsize")) {
 371                        char *s = xmalloc(40);
 372                        sprintf(s, "%lu", sz);
 373                        v->ul = sz;
 374                        v->s = s;
 375                }
 376                else if (deref)
 377                        grab_objectname(name, obj->sha1, v);
 378        }
 379}
 380
 381/* See grab_values */
 382static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 383{
 384        int i;
 385        struct tag *tag = (struct tag *) obj;
 386
 387        for (i = 0; i < used_atom_cnt; i++) {
 388                const char *name = used_atom[i];
 389                struct atom_value *v = &val[i];
 390                if (!!deref != (*name == '*'))
 391                        continue;
 392                if (deref)
 393                        name++;
 394                if (!strcmp(name, "tag"))
 395                        v->s = tag->tag;
 396                else if (!strcmp(name, "type") && tag->tagged)
 397                        v->s = typename(tag->tagged->type);
 398                else if (!strcmp(name, "object") && tag->tagged) {
 399                        char *s = xmalloc(41);
 400                        strcpy(s, sha1_to_hex(tag->tagged->sha1));
 401                        v->s = s;
 402                }
 403        }
 404}
 405
 406/* See grab_values */
 407static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 408{
 409        int i;
 410        struct commit *commit = (struct commit *) obj;
 411
 412        for (i = 0; i < used_atom_cnt; i++) {
 413                const char *name = used_atom[i];
 414                struct atom_value *v = &val[i];
 415                if (!!deref != (*name == '*'))
 416                        continue;
 417                if (deref)
 418                        name++;
 419                if (!strcmp(name, "tree")) {
 420                        char *s = xmalloc(41);
 421                        strcpy(s, sha1_to_hex(commit->tree->object.sha1));
 422                        v->s = s;
 423                }
 424                if (!strcmp(name, "numparent")) {
 425                        char *s = xmalloc(40);
 426                        v->ul = commit_list_count(commit->parents);
 427                        sprintf(s, "%lu", v->ul);
 428                        v->s = s;
 429                }
 430                else if (!strcmp(name, "parent")) {
 431                        int num = commit_list_count(commit->parents);
 432                        int i;
 433                        struct commit_list *parents;
 434                        char *s = xmalloc(41 * num + 1);
 435                        v->s = s;
 436                        for (i = 0, parents = commit->parents;
 437                             parents;
 438                             parents = parents->next, i = i + 41) {
 439                                struct commit *parent = parents->item;
 440                                strcpy(s+i, sha1_to_hex(parent->object.sha1));
 441                                if (parents->next)
 442                                        s[i+40] = ' ';
 443                        }
 444                        if (!i)
 445                                *s = '\0';
 446                }
 447        }
 448}
 449
 450static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
 451{
 452        const char *eol;
 453        while (*buf) {
 454                if (!strncmp(buf, who, wholen) &&
 455                    buf[wholen] == ' ')
 456                        return buf + wholen + 1;
 457                eol = strchr(buf, '\n');
 458                if (!eol)
 459                        return "";
 460                eol++;
 461                if (*eol == '\n')
 462                        return ""; /* end of header */
 463                buf = eol;
 464        }
 465        return "";
 466}
 467
 468static const char *copy_line(const char *buf)
 469{
 470        const char *eol = strchrnul(buf, '\n');
 471        return xmemdupz(buf, eol - buf);
 472}
 473
 474static const char *copy_name(const char *buf)
 475{
 476        const char *cp;
 477        for (cp = buf; *cp && *cp != '\n'; cp++) {
 478                if (!strncmp(cp, " <", 2))
 479                        return xmemdupz(buf, cp - buf);
 480        }
 481        return "";
 482}
 483
 484static const char *copy_email(const char *buf)
 485{
 486        const char *email = strchr(buf, '<');
 487        const char *eoemail;
 488        if (!email)
 489                return "";
 490        eoemail = strchr(email, '>');
 491        if (!eoemail)
 492                return "";
 493        return xmemdupz(email, eoemail + 1 - email);
 494}
 495
 496static char *copy_subject(const char *buf, unsigned long len)
 497{
 498        char *r = xmemdupz(buf, len);
 499        int i;
 500
 501        for (i = 0; i < len; i++)
 502                if (r[i] == '\n')
 503                        r[i] = ' ';
 504
 505        return r;
 506}
 507
 508static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
 509{
 510        const char *eoemail = strstr(buf, "> ");
 511        char *zone;
 512        unsigned long timestamp;
 513        long tz;
 514        struct date_mode date_mode = { DATE_NORMAL };
 515        const char *formatp;
 516
 517        /*
 518         * We got here because atomname ends in "date" or "date<something>";
 519         * it's not possible that <something> is not ":<format>" because
 520         * parse_ref_filter_atom() wouldn't have allowed it, so we can assume that no
 521         * ":" means no format is specified, and use the default.
 522         */
 523        formatp = strchr(atomname, ':');
 524        if (formatp != NULL) {
 525                formatp++;
 526                parse_date_format(formatp, &date_mode);
 527        }
 528
 529        if (!eoemail)
 530                goto bad;
 531        timestamp = strtoul(eoemail + 2, &zone, 10);
 532        if (timestamp == ULONG_MAX)
 533                goto bad;
 534        tz = strtol(zone, NULL, 10);
 535        if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
 536                goto bad;
 537        v->s = xstrdup(show_date(timestamp, tz, &date_mode));
 538        v->ul = timestamp;
 539        return;
 540 bad:
 541        v->s = "";
 542        v->ul = 0;
 543}
 544
 545/* See grab_values */
 546static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 547{
 548        int i;
 549        int wholen = strlen(who);
 550        const char *wholine = NULL;
 551
 552        for (i = 0; i < used_atom_cnt; i++) {
 553                const char *name = used_atom[i];
 554                struct atom_value *v = &val[i];
 555                if (!!deref != (*name == '*'))
 556                        continue;
 557                if (deref)
 558                        name++;
 559                if (strncmp(who, name, wholen))
 560                        continue;
 561                if (name[wholen] != 0 &&
 562                    strcmp(name + wholen, "name") &&
 563                    strcmp(name + wholen, "email") &&
 564                    !starts_with(name + wholen, "date"))
 565                        continue;
 566                if (!wholine)
 567                        wholine = find_wholine(who, wholen, buf, sz);
 568                if (!wholine)
 569                        return; /* no point looking for it */
 570                if (name[wholen] == 0)
 571                        v->s = copy_line(wholine);
 572                else if (!strcmp(name + wholen, "name"))
 573                        v->s = copy_name(wholine);
 574                else if (!strcmp(name + wholen, "email"))
 575                        v->s = copy_email(wholine);
 576                else if (starts_with(name + wholen, "date"))
 577                        grab_date(wholine, v, name);
 578        }
 579
 580        /*
 581         * For a tag or a commit object, if "creator" or "creatordate" is
 582         * requested, do something special.
 583         */
 584        if (strcmp(who, "tagger") && strcmp(who, "committer"))
 585                return; /* "author" for commit object is not wanted */
 586        if (!wholine)
 587                wholine = find_wholine(who, wholen, buf, sz);
 588        if (!wholine)
 589                return;
 590        for (i = 0; i < used_atom_cnt; i++) {
 591                const char *name = used_atom[i];
 592                struct atom_value *v = &val[i];
 593                if (!!deref != (*name == '*'))
 594                        continue;
 595                if (deref)
 596                        name++;
 597
 598                if (starts_with(name, "creatordate"))
 599                        grab_date(wholine, v, name);
 600                else if (!strcmp(name, "creator"))
 601                        v->s = copy_line(wholine);
 602        }
 603}
 604
 605static void find_subpos(const char *buf, unsigned long sz,
 606                        const char **sub, unsigned long *sublen,
 607                        const char **body, unsigned long *bodylen,
 608                        unsigned long *nonsiglen,
 609                        const char **sig, unsigned long *siglen)
 610{
 611        const char *eol;
 612        /* skip past header until we hit empty line */
 613        while (*buf && *buf != '\n') {
 614                eol = strchrnul(buf, '\n');
 615                if (*eol)
 616                        eol++;
 617                buf = eol;
 618        }
 619        /* skip any empty lines */
 620        while (*buf == '\n')
 621                buf++;
 622
 623        /* parse signature first; we might not even have a subject line */
 624        *sig = buf + parse_signature(buf, strlen(buf));
 625        *siglen = strlen(*sig);
 626
 627        /* subject is first non-empty line */
 628        *sub = buf;
 629        /* subject goes to first empty line */
 630        while (buf < *sig && *buf && *buf != '\n') {
 631                eol = strchrnul(buf, '\n');
 632                if (*eol)
 633                        eol++;
 634                buf = eol;
 635        }
 636        *sublen = buf - *sub;
 637        /* drop trailing newline, if present */
 638        if (*sublen && (*sub)[*sublen - 1] == '\n')
 639                *sublen -= 1;
 640
 641        /* skip any empty lines */
 642        while (*buf == '\n')
 643                buf++;
 644        *body = buf;
 645        *bodylen = strlen(buf);
 646        *nonsiglen = *sig - buf;
 647}
 648
 649/*
 650 * If 'lines' is greater than 0, append that many lines from the given
 651 * 'buf' of length 'size' to the given strbuf.
 652 */
 653static void append_lines(struct strbuf *out, const char *buf, unsigned long size, int lines)
 654{
 655        int i;
 656        const char *sp, *eol;
 657        size_t len;
 658
 659        sp = buf;
 660
 661        for (i = 0; i < lines && sp < buf + size; i++) {
 662                if (i)
 663                        strbuf_addstr(out, "\n    ");
 664                eol = memchr(sp, '\n', size - (sp - buf));
 665                len = eol ? eol - sp : size - (sp - buf);
 666                strbuf_add(out, sp, len);
 667                if (!eol)
 668                        break;
 669                sp = eol + 1;
 670        }
 671}
 672
 673/* See grab_values */
 674static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 675{
 676        int i;
 677        const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL;
 678        unsigned long sublen = 0, bodylen = 0, nonsiglen = 0, siglen = 0;
 679
 680        for (i = 0; i < used_atom_cnt; i++) {
 681                const char *name = used_atom[i];
 682                struct atom_value *v = &val[i];
 683                const char *valp = NULL;
 684                if (!!deref != (*name == '*'))
 685                        continue;
 686                if (deref)
 687                        name++;
 688                if (strcmp(name, "subject") &&
 689                    strcmp(name, "body") &&
 690                    strcmp(name, "contents") &&
 691                    strcmp(name, "contents:subject") &&
 692                    strcmp(name, "contents:body") &&
 693                    strcmp(name, "contents:signature") &&
 694                    !starts_with(name, "contents:lines="))
 695                        continue;
 696                if (!subpos)
 697                        find_subpos(buf, sz,
 698                                    &subpos, &sublen,
 699                                    &bodypos, &bodylen, &nonsiglen,
 700                                    &sigpos, &siglen);
 701
 702                if (!strcmp(name, "subject"))
 703                        v->s = copy_subject(subpos, sublen);
 704                else if (!strcmp(name, "contents:subject"))
 705                        v->s = copy_subject(subpos, sublen);
 706                else if (!strcmp(name, "body"))
 707                        v->s = xmemdupz(bodypos, bodylen);
 708                else if (!strcmp(name, "contents:body"))
 709                        v->s = xmemdupz(bodypos, nonsiglen);
 710                else if (!strcmp(name, "contents:signature"))
 711                        v->s = xmemdupz(sigpos, siglen);
 712                else if (!strcmp(name, "contents"))
 713                        v->s = xstrdup(subpos);
 714                else if (skip_prefix(name, "contents:lines=", &valp)) {
 715                        struct strbuf s = STRBUF_INIT;
 716                        const char *contents_end = bodylen + bodypos - siglen;
 717
 718                        if (strtoul_ui(valp, 10, &v->u.contents.lines))
 719                                die(_("positive value expected contents:lines=%s"), valp);
 720                        /*  Size is the length of the message after removing the signature */
 721                        append_lines(&s, subpos, contents_end - subpos, v->u.contents.lines);
 722                        v->s = strbuf_detach(&s, NULL);
 723                }
 724        }
 725}
 726
 727/*
 728 * We want to have empty print-string for field requests
 729 * that do not apply (e.g. "authordate" for a tag object)
 730 */
 731static void fill_missing_values(struct atom_value *val)
 732{
 733        int i;
 734        for (i = 0; i < used_atom_cnt; i++) {
 735                struct atom_value *v = &val[i];
 736                if (v->s == NULL)
 737                        v->s = "";
 738        }
 739}
 740
 741/*
 742 * val is a list of atom_value to hold returned values.  Extract
 743 * the values for atoms in used_atom array out of (obj, buf, sz).
 744 * when deref is false, (obj, buf, sz) is the object that is
 745 * pointed at by the ref itself; otherwise it is the object the
 746 * ref (which is a tag) refers to.
 747 */
 748static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 749{
 750        grab_common_values(val, deref, obj, buf, sz);
 751        switch (obj->type) {
 752        case OBJ_TAG:
 753                grab_tag_values(val, deref, obj, buf, sz);
 754                grab_sub_body_contents(val, deref, obj, buf, sz);
 755                grab_person("tagger", val, deref, obj, buf, sz);
 756                break;
 757        case OBJ_COMMIT:
 758                grab_commit_values(val, deref, obj, buf, sz);
 759                grab_sub_body_contents(val, deref, obj, buf, sz);
 760                grab_person("author", val, deref, obj, buf, sz);
 761                grab_person("committer", val, deref, obj, buf, sz);
 762                break;
 763        case OBJ_TREE:
 764                /* grab_tree_values(val, deref, obj, buf, sz); */
 765                break;
 766        case OBJ_BLOB:
 767                /* grab_blob_values(val, deref, obj, buf, sz); */
 768                break;
 769        default:
 770                die("Eh?  Object of type %d?", obj->type);
 771        }
 772}
 773
 774static inline char *copy_advance(char *dst, const char *src)
 775{
 776        while (*src)
 777                *dst++ = *src++;
 778        return dst;
 779}
 780
 781/*
 782 * Parse the object referred by ref, and grab needed value.
 783 */
 784static void populate_value(struct ref_array_item *ref)
 785{
 786        void *buf;
 787        struct object *obj;
 788        int eaten, i;
 789        unsigned long size;
 790        const unsigned char *tagged;
 791
 792        ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 793
 794        if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
 795                unsigned char unused1[20];
 796                ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
 797                                             unused1, NULL);
 798                if (!ref->symref)
 799                        ref->symref = "";
 800        }
 801
 802        /* Fill in specials first */
 803        for (i = 0; i < used_atom_cnt; i++) {
 804                const char *name = used_atom[i];
 805                struct atom_value *v = &ref->value[i];
 806                int deref = 0;
 807                const char *refname;
 808                const char *formatp;
 809                const char *valp;
 810                struct branch *branch = NULL;
 811
 812                v->handler = append_atom;
 813
 814                if (*name == '*') {
 815                        deref = 1;
 816                        name++;
 817                }
 818
 819                if (starts_with(name, "refname"))
 820                        refname = ref->refname;
 821                else if (starts_with(name, "symref"))
 822                        refname = ref->symref ? ref->symref : "";
 823                else if (starts_with(name, "upstream")) {
 824                        const char *branch_name;
 825                        /* only local branches may have an upstream */
 826                        if (!skip_prefix(ref->refname, "refs/heads/",
 827                                         &branch_name))
 828                                continue;
 829                        branch = branch_get(branch_name);
 830
 831                        refname = branch_get_upstream(branch, NULL);
 832                        if (!refname)
 833                                continue;
 834                } else if (starts_with(name, "push")) {
 835                        const char *branch_name;
 836                        if (!skip_prefix(ref->refname, "refs/heads/",
 837                                         &branch_name))
 838                                continue;
 839                        branch = branch_get(branch_name);
 840
 841                        refname = branch_get_push(branch, NULL);
 842                        if (!refname)
 843                                continue;
 844                } else if (match_atom_name(name, "color", &valp)) {
 845                        char color[COLOR_MAXLEN] = "";
 846
 847                        if (!valp)
 848                                die(_("expected format: %%(color:<color>)"));
 849                        if (color_parse(valp, color) < 0)
 850                                die(_("unable to parse format"));
 851                        v->s = xstrdup(color);
 852                        continue;
 853                } else if (!strcmp(name, "flag")) {
 854                        char buf[256], *cp = buf;
 855                        if (ref->flag & REF_ISSYMREF)
 856                                cp = copy_advance(cp, ",symref");
 857                        if (ref->flag & REF_ISPACKED)
 858                                cp = copy_advance(cp, ",packed");
 859                        if (cp == buf)
 860                                v->s = "";
 861                        else {
 862                                *cp = '\0';
 863                                v->s = xstrdup(buf + 1);
 864                        }
 865                        continue;
 866                } else if (!deref && grab_objectname(name, ref->objectname, v)) {
 867                        continue;
 868                } else if (!strcmp(name, "HEAD")) {
 869                        const char *head;
 870                        unsigned char sha1[20];
 871
 872                        head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
 873                                                  sha1, NULL);
 874                        if (!strcmp(ref->refname, head))
 875                                v->s = "*";
 876                        else
 877                                v->s = " ";
 878                        continue;
 879                } else if (match_atom_name(name, "align", &valp)) {
 880                        struct align *align = &v->u.align;
 881                        struct strbuf **s, **to_free;
 882                        int width = -1;
 883
 884                        if (!valp)
 885                                die(_("expected format: %%(align:<width>,<position>)"));
 886
 887                        /*
 888                         * TODO: Implement a function similar to strbuf_split_str()
 889                         * which would omit the separator from the end of each value.
 890                         */
 891                        s = to_free = strbuf_split_str(valp, ',', 0);
 892
 893                        align->position = ALIGN_LEFT;
 894
 895                        while (*s) {
 896                                /*  Strip trailing comma */
 897                                if (s[1])
 898                                        strbuf_setlen(s[0], s[0]->len - 1);
 899                                if (!strtoul_ui(s[0]->buf, 10, (unsigned int *)&width))
 900                                        ;
 901                                else if (!strcmp(s[0]->buf, "left"))
 902                                        align->position = ALIGN_LEFT;
 903                                else if (!strcmp(s[0]->buf, "right"))
 904                                        align->position = ALIGN_RIGHT;
 905                                else if (!strcmp(s[0]->buf, "middle"))
 906                                        align->position = ALIGN_MIDDLE;
 907                                else
 908                                        die(_("improper format entered align:%s"), s[0]->buf);
 909                                s++;
 910                        }
 911
 912                        if (width < 0)
 913                                die(_("positive width expected with the %%(align) atom"));
 914                        align->width = width;
 915                        strbuf_list_free(to_free);
 916                        v->handler = align_atom_handler;
 917                        continue;
 918                } else if (!strcmp(name, "end")) {
 919                        v->handler = end_atom_handler;
 920                        continue;
 921                } else
 922                        continue;
 923
 924                formatp = strchr(name, ':');
 925                if (formatp) {
 926                        int num_ours, num_theirs;
 927
 928                        formatp++;
 929                        if (!strcmp(formatp, "short"))
 930                                refname = shorten_unambiguous_ref(refname,
 931                                                      warn_ambiguous_refs);
 932                        else if (!strcmp(formatp, "track") &&
 933                                 (starts_with(name, "upstream") ||
 934                                  starts_with(name, "push"))) {
 935                                char buf[40];
 936
 937                                if (stat_tracking_info(branch, &num_ours,
 938                                                       &num_theirs, NULL))
 939                                        continue;
 940
 941                                if (!num_ours && !num_theirs)
 942                                        v->s = "";
 943                                else if (!num_ours) {
 944                                        sprintf(buf, "[behind %d]", num_theirs);
 945                                        v->s = xstrdup(buf);
 946                                } else if (!num_theirs) {
 947                                        sprintf(buf, "[ahead %d]", num_ours);
 948                                        v->s = xstrdup(buf);
 949                                } else {
 950                                        sprintf(buf, "[ahead %d, behind %d]",
 951                                                num_ours, num_theirs);
 952                                        v->s = xstrdup(buf);
 953                                }
 954                                continue;
 955                        } else if (!strcmp(formatp, "trackshort") &&
 956                                   (starts_with(name, "upstream") ||
 957                                    starts_with(name, "push"))) {
 958                                assert(branch);
 959
 960                                if (stat_tracking_info(branch, &num_ours,
 961                                                        &num_theirs, NULL))
 962                                        continue;
 963
 964                                if (!num_ours && !num_theirs)
 965                                        v->s = "=";
 966                                else if (!num_ours)
 967                                        v->s = "<";
 968                                else if (!num_theirs)
 969                                        v->s = ">";
 970                                else
 971                                        v->s = "<>";
 972                                continue;
 973                        } else
 974                                die("unknown %.*s format %s",
 975                                    (int)(formatp - name), name, formatp);
 976                }
 977
 978                if (!deref)
 979                        v->s = refname;
 980                else {
 981                        int len = strlen(refname);
 982                        char *s = xmalloc(len + 4);
 983                        sprintf(s, "%s^{}", refname);
 984                        v->s = s;
 985                }
 986        }
 987
 988        for (i = 0; i < used_atom_cnt; i++) {
 989                struct atom_value *v = &ref->value[i];
 990                if (v->s == NULL)
 991                        goto need_obj;
 992        }
 993        return;
 994
 995 need_obj:
 996        buf = get_obj(ref->objectname, &obj, &size, &eaten);
 997        if (!buf)
 998                die("missing object %s for %s",
 999                    sha1_to_hex(ref->objectname), ref->refname);
1000        if (!obj)
1001                die("parse_object_buffer failed on %s for %s",
1002                    sha1_to_hex(ref->objectname), ref->refname);
1003
1004        grab_values(ref->value, 0, obj, buf, size);
1005        if (!eaten)
1006                free(buf);
1007
1008        /*
1009         * If there is no atom that wants to know about tagged
1010         * object, we are done.
1011         */
1012        if (!need_tagged || (obj->type != OBJ_TAG))
1013                return;
1014
1015        /*
1016         * If it is a tag object, see if we use a value that derefs
1017         * the object, and if we do grab the object it refers to.
1018         */
1019        tagged = ((struct tag *)obj)->tagged->sha1;
1020
1021        /*
1022         * NEEDSWORK: This derefs tag only once, which
1023         * is good to deal with chains of trust, but
1024         * is not consistent with what deref_tag() does
1025         * which peels the onion to the core.
1026         */
1027        buf = get_obj(tagged, &obj, &size, &eaten);
1028        if (!buf)
1029                die("missing object %s for %s",
1030                    sha1_to_hex(tagged), ref->refname);
1031        if (!obj)
1032                die("parse_object_buffer failed on %s for %s",
1033                    sha1_to_hex(tagged), ref->refname);
1034        grab_values(ref->value, 1, obj, buf, size);
1035        if (!eaten)
1036                free(buf);
1037}
1038
1039/*
1040 * Given a ref, return the value for the atom.  This lazily gets value
1041 * out of the object by calling populate value.
1042 */
1043static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom_value **v)
1044{
1045        if (!ref->value) {
1046                populate_value(ref);
1047                fill_missing_values(ref->value);
1048        }
1049        *v = &ref->value[atom];
1050}
1051
1052enum contains_result {
1053        CONTAINS_UNKNOWN = -1,
1054        CONTAINS_NO = 0,
1055        CONTAINS_YES = 1
1056};
1057
1058/*
1059 * Mimicking the real stack, this stack lives on the heap, avoiding stack
1060 * overflows.
1061 *
1062 * At each recursion step, the stack items points to the commits whose
1063 * ancestors are to be inspected.
1064 */
1065struct contains_stack {
1066        int nr, alloc;
1067        struct contains_stack_entry {
1068                struct commit *commit;
1069                struct commit_list *parents;
1070        } *contains_stack;
1071};
1072
1073static int in_commit_list(const struct commit_list *want, struct commit *c)
1074{
1075        for (; want; want = want->next)
1076                if (!hashcmp(want->item->object.sha1, c->object.sha1))
1077                        return 1;
1078        return 0;
1079}
1080
1081/*
1082 * Test whether the candidate or one of its parents is contained in the list.
1083 * Do not recurse to find out, though, but return -1 if inconclusive.
1084 */
1085static enum contains_result contains_test(struct commit *candidate,
1086                            const struct commit_list *want)
1087{
1088        /* was it previously marked as containing a want commit? */
1089        if (candidate->object.flags & TMP_MARK)
1090                return 1;
1091        /* or marked as not possibly containing a want commit? */
1092        if (candidate->object.flags & UNINTERESTING)
1093                return 0;
1094        /* or are we it? */
1095        if (in_commit_list(want, candidate)) {
1096                candidate->object.flags |= TMP_MARK;
1097                return 1;
1098        }
1099
1100        if (parse_commit(candidate) < 0)
1101                return 0;
1102
1103        return -1;
1104}
1105
1106static void push_to_contains_stack(struct commit *candidate, struct contains_stack *contains_stack)
1107{
1108        ALLOC_GROW(contains_stack->contains_stack, contains_stack->nr + 1, contains_stack->alloc);
1109        contains_stack->contains_stack[contains_stack->nr].commit = candidate;
1110        contains_stack->contains_stack[contains_stack->nr++].parents = candidate->parents;
1111}
1112
1113static enum contains_result contains_tag_algo(struct commit *candidate,
1114                const struct commit_list *want)
1115{
1116        struct contains_stack contains_stack = { 0, 0, NULL };
1117        int result = contains_test(candidate, want);
1118
1119        if (result != CONTAINS_UNKNOWN)
1120                return result;
1121
1122        push_to_contains_stack(candidate, &contains_stack);
1123        while (contains_stack.nr) {
1124                struct contains_stack_entry *entry = &contains_stack.contains_stack[contains_stack.nr - 1];
1125                struct commit *commit = entry->commit;
1126                struct commit_list *parents = entry->parents;
1127
1128                if (!parents) {
1129                        commit->object.flags |= UNINTERESTING;
1130                        contains_stack.nr--;
1131                }
1132                /*
1133                 * If we just popped the stack, parents->item has been marked,
1134                 * therefore contains_test will return a meaningful 0 or 1.
1135                 */
1136                else switch (contains_test(parents->item, want)) {
1137                case CONTAINS_YES:
1138                        commit->object.flags |= TMP_MARK;
1139                        contains_stack.nr--;
1140                        break;
1141                case CONTAINS_NO:
1142                        entry->parents = parents->next;
1143                        break;
1144                case CONTAINS_UNKNOWN:
1145                        push_to_contains_stack(parents->item, &contains_stack);
1146                        break;
1147                }
1148        }
1149        free(contains_stack.contains_stack);
1150        return contains_test(candidate, want);
1151}
1152
1153static int commit_contains(struct ref_filter *filter, struct commit *commit)
1154{
1155        if (filter->with_commit_tag_algo)
1156                return contains_tag_algo(commit, filter->with_commit);
1157        return is_descendant_of(commit, filter->with_commit);
1158}
1159
1160/*
1161 * Return 1 if the refname matches one of the patterns, otherwise 0.
1162 * A pattern can be path prefix (e.g. a refname "refs/heads/master"
1163 * matches a pattern "refs/heads/") or a wildcard (e.g. the same ref
1164 * matches "refs/heads/m*",too).
1165 */
1166static int match_name_as_path(const char **pattern, const char *refname)
1167{
1168        int namelen = strlen(refname);
1169        for (; *pattern; pattern++) {
1170                const char *p = *pattern;
1171                int plen = strlen(p);
1172
1173                if ((plen <= namelen) &&
1174                    !strncmp(refname, p, plen) &&
1175                    (refname[plen] == '\0' ||
1176                     refname[plen] == '/' ||
1177                     p[plen-1] == '/'))
1178                        return 1;
1179                if (!wildmatch(p, refname, WM_PATHNAME, NULL))
1180                        return 1;
1181        }
1182        return 0;
1183}
1184
1185/*
1186 * Given a ref (sha1, refname), check if the ref belongs to the array
1187 * of sha1s. If the given ref is a tag, check if the given tag points
1188 * at one of the sha1s in the given sha1 array.
1189 * the given sha1_array.
1190 * NEEDSWORK:
1191 * 1. Only a single level of inderection is obtained, we might want to
1192 * change this to account for multiple levels (e.g. annotated tags
1193 * pointing to annotated tags pointing to a commit.)
1194 * 2. As the refs are cached we might know what refname peels to without
1195 * the need to parse the object via parse_object(). peel_ref() might be a
1196 * more efficient alternative to obtain the pointee.
1197 */
1198static const unsigned char *match_points_at(struct sha1_array *points_at,
1199                                            const unsigned char *sha1,
1200                                            const char *refname)
1201{
1202        const unsigned char *tagged_sha1 = NULL;
1203        struct object *obj;
1204
1205        if (sha1_array_lookup(points_at, sha1) >= 0)
1206                return sha1;
1207        obj = parse_object(sha1);
1208        if (!obj)
1209                die(_("malformed object at '%s'"), refname);
1210        if (obj->type == OBJ_TAG)
1211                tagged_sha1 = ((struct tag *)obj)->tagged->sha1;
1212        if (tagged_sha1 && sha1_array_lookup(points_at, tagged_sha1) >= 0)
1213                return tagged_sha1;
1214        return NULL;
1215}
1216
1217/* Allocate space for a new ref_array_item and copy the objectname and flag to it */
1218static struct ref_array_item *new_ref_array_item(const char *refname,
1219                                                 const unsigned char *objectname,
1220                                                 int flag)
1221{
1222        size_t len = strlen(refname);
1223        struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + len + 1);
1224        memcpy(ref->refname, refname, len);
1225        ref->refname[len] = '\0';
1226        hashcpy(ref->objectname, objectname);
1227        ref->flag = flag;
1228
1229        return ref;
1230}
1231
1232static int filter_ref_kind(struct ref_filter *filter, const char *refname)
1233{
1234        unsigned int i;
1235
1236        static struct {
1237                const char *prefix;
1238                unsigned int kind;
1239        } ref_kind[] = {
1240                { "refs/heads/" , FILTER_REFS_BRANCHES },
1241                { "refs/remotes/" , FILTER_REFS_REMOTES },
1242                { "refs/tags/", FILTER_REFS_TAGS}
1243        };
1244
1245        if (filter->kind == FILTER_REFS_BRANCHES ||
1246            filter->kind == FILTER_REFS_REMOTES ||
1247            filter->kind == FILTER_REFS_TAGS)
1248                return filter->kind;
1249        else if (!strcmp(refname, "HEAD"))
1250                return FILTER_REFS_DETACHED_HEAD;
1251
1252        for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
1253                if (starts_with(refname, ref_kind[i].prefix))
1254                        return ref_kind[i].kind;
1255        }
1256
1257        return FILTER_REFS_OTHERS;
1258}
1259
1260/*
1261 * A call-back given to for_each_ref().  Filter refs and keep them for
1262 * later object processing.
1263 */
1264static int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data)
1265{
1266        struct ref_filter_cbdata *ref_cbdata = cb_data;
1267        struct ref_filter *filter = ref_cbdata->filter;
1268        struct ref_array_item *ref;
1269        struct commit *commit = NULL;
1270        unsigned int kind;
1271
1272        if (flag & REF_BAD_NAME) {
1273                warning("ignoring ref with broken name %s", refname);
1274                return 0;
1275        }
1276
1277        if (flag & REF_ISBROKEN) {
1278                warning("ignoring broken ref %s", refname);
1279                return 0;
1280        }
1281
1282        /* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
1283        kind = filter_ref_kind(filter, refname);
1284        if (!(kind & filter->kind))
1285                return 0;
1286
1287        if (*filter->name_patterns && !match_name_as_path(filter->name_patterns, refname))
1288                return 0;
1289
1290        if (filter->points_at.nr && !match_points_at(&filter->points_at, oid->hash, refname))
1291                return 0;
1292
1293        /*
1294         * A merge filter is applied on refs pointing to commits. Hence
1295         * obtain the commit using the 'oid' available and discard all
1296         * non-commits early. The actual filtering is done later.
1297         */
1298        if (filter->merge_commit || filter->with_commit) {
1299                commit = lookup_commit_reference_gently(oid->hash, 1);
1300                if (!commit)
1301                        return 0;
1302                /* We perform the filtering for the '--contains' option */
1303                if (filter->with_commit &&
1304                    !commit_contains(filter, commit))
1305                        return 0;
1306        }
1307
1308        /*
1309         * We do not open the object yet; sort may only need refname
1310         * to do its job and the resulting list may yet to be pruned
1311         * by maxcount logic.
1312         */
1313        ref = new_ref_array_item(refname, oid->hash, flag);
1314        ref->commit = commit;
1315
1316        REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
1317        ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
1318        ref->kind = kind;
1319        return 0;
1320}
1321
1322/*  Free memory allocated for a ref_array_item */
1323static void free_array_item(struct ref_array_item *item)
1324{
1325        free((char *)item->symref);
1326        free(item);
1327}
1328
1329/* Free all memory allocated for ref_array */
1330void ref_array_clear(struct ref_array *array)
1331{
1332        int i;
1333
1334        for (i = 0; i < array->nr; i++)
1335                free_array_item(array->items[i]);
1336        free(array->items);
1337        array->items = NULL;
1338        array->nr = array->alloc = 0;
1339}
1340
1341static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
1342{
1343        struct rev_info revs;
1344        int i, old_nr;
1345        struct ref_filter *filter = ref_cbdata->filter;
1346        struct ref_array *array = ref_cbdata->array;
1347        struct commit **to_clear = xcalloc(sizeof(struct commit *), array->nr);
1348
1349        init_revisions(&revs, NULL);
1350
1351        for (i = 0; i < array->nr; i++) {
1352                struct ref_array_item *item = array->items[i];
1353                add_pending_object(&revs, &item->commit->object, item->refname);
1354                to_clear[i] = item->commit;
1355        }
1356
1357        filter->merge_commit->object.flags |= UNINTERESTING;
1358        add_pending_object(&revs, &filter->merge_commit->object, "");
1359
1360        revs.limited = 1;
1361        if (prepare_revision_walk(&revs))
1362                die(_("revision walk setup failed"));
1363
1364        old_nr = array->nr;
1365        array->nr = 0;
1366
1367        for (i = 0; i < old_nr; i++) {
1368                struct ref_array_item *item = array->items[i];
1369                struct commit *commit = item->commit;
1370
1371                int is_merged = !!(commit->object.flags & UNINTERESTING);
1372
1373                if (is_merged == (filter->merge == REF_FILTER_MERGED_INCLUDE))
1374                        array->items[array->nr++] = array->items[i];
1375                else
1376                        free_array_item(item);
1377        }
1378
1379        for (i = 0; i < old_nr; i++)
1380                clear_commit_marks(to_clear[i], ALL_REV_FLAGS);
1381        clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
1382        free(to_clear);
1383}
1384
1385/*
1386 * API for filtering a set of refs. Based on the type of refs the user
1387 * has requested, we iterate through those refs and apply filters
1388 * as per the given ref_filter structure and finally store the
1389 * filtered refs in the ref_array structure.
1390 */
1391int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
1392{
1393        struct ref_filter_cbdata ref_cbdata;
1394        int ret = 0;
1395        unsigned int broken = 0;
1396
1397        ref_cbdata.array = array;
1398        ref_cbdata.filter = filter;
1399
1400        if (type & FILTER_REFS_INCLUDE_BROKEN)
1401                broken = 1;
1402        filter->kind = type & FILTER_REFS_KIND_MASK;
1403
1404        /*  Simple per-ref filtering */
1405        if (!filter->kind)
1406                die("filter_refs: invalid type");
1407        else {
1408                /*
1409                 * For common cases where we need only branches or remotes or tags,
1410                 * we only iterate through those refs. If a mix of refs is needed,
1411                 * we iterate over all refs and filter out required refs with the help
1412                 * of filter_ref_kind().
1413                 */
1414                if (filter->kind == FILTER_REFS_BRANCHES)
1415                        ret = for_each_fullref_in("refs/heads/", ref_filter_handler, &ref_cbdata, broken);
1416                else if (filter->kind == FILTER_REFS_REMOTES)
1417                        ret = for_each_fullref_in("refs/remotes/", ref_filter_handler, &ref_cbdata, broken);
1418                else if (filter->kind == FILTER_REFS_TAGS)
1419                        ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata, broken);
1420                else if (filter->kind & FILTER_REFS_ALL)
1421                        ret = for_each_fullref_in("", ref_filter_handler, &ref_cbdata, broken);
1422                if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
1423                        head_ref(ref_filter_handler, &ref_cbdata);
1424        }
1425
1426
1427        /*  Filters that need revision walking */
1428        if (filter->merge_commit)
1429                do_merge_filter(&ref_cbdata);
1430
1431        return ret;
1432}
1433
1434static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
1435{
1436        struct atom_value *va, *vb;
1437        int cmp;
1438        cmp_type cmp_type = used_atom_type[s->atom];
1439
1440        get_ref_atom_value(a, s->atom, &va);
1441        get_ref_atom_value(b, s->atom, &vb);
1442        switch (cmp_type) {
1443        case FIELD_STR:
1444                cmp = strcmp(va->s, vb->s);
1445                break;
1446        default:
1447                if (va->ul < vb->ul)
1448                        cmp = -1;
1449                else if (va->ul == vb->ul)
1450                        cmp = 0;
1451                else
1452                        cmp = 1;
1453                break;
1454        }
1455        return (s->reverse) ? -cmp : cmp;
1456}
1457
1458static struct ref_sorting *ref_sorting;
1459static int compare_refs(const void *a_, const void *b_)
1460{
1461        struct ref_array_item *a = *((struct ref_array_item **)a_);
1462        struct ref_array_item *b = *((struct ref_array_item **)b_);
1463        struct ref_sorting *s;
1464
1465        for (s = ref_sorting; s; s = s->next) {
1466                int cmp = cmp_ref_sorting(s, a, b);
1467                if (cmp)
1468                        return cmp;
1469        }
1470        return 0;
1471}
1472
1473void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array)
1474{
1475        ref_sorting = sorting;
1476        qsort(array->items, array->nr, sizeof(struct ref_array_item *), compare_refs);
1477}
1478
1479static int hex1(char ch)
1480{
1481        if ('0' <= ch && ch <= '9')
1482                return ch - '0';
1483        else if ('a' <= ch && ch <= 'f')
1484                return ch - 'a' + 10;
1485        else if ('A' <= ch && ch <= 'F')
1486                return ch - 'A' + 10;
1487        return -1;
1488}
1489static int hex2(const char *cp)
1490{
1491        if (cp[0] && cp[1])
1492                return (hex1(cp[0]) << 4) | hex1(cp[1]);
1493        else
1494                return -1;
1495}
1496
1497static void append_literal(const char *cp, const char *ep, struct ref_formatting_state *state)
1498{
1499        struct strbuf *s = &state->stack->output;
1500
1501        while (*cp && (!ep || cp < ep)) {
1502                if (*cp == '%') {
1503                        if (cp[1] == '%')
1504                                cp++;
1505                        else {
1506                                int ch = hex2(cp + 1);
1507                                if (0 <= ch) {
1508                                        strbuf_addch(s, ch);
1509                                        cp += 3;
1510                                        continue;
1511                                }
1512                        }
1513                }
1514                strbuf_addch(s, *cp);
1515                cp++;
1516        }
1517}
1518
1519void show_ref_array_item(struct ref_array_item *info, const char *format, int quote_style)
1520{
1521        const char *cp, *sp, *ep;
1522        struct strbuf *final_buf;
1523        struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
1524
1525        state.quote_style = quote_style;
1526        push_stack_element(&state.stack);
1527
1528        for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
1529                struct atom_value *atomv;
1530
1531                ep = strchr(sp, ')');
1532                if (cp < sp)
1533                        append_literal(cp, sp, &state);
1534                get_ref_atom_value(info, parse_ref_filter_atom(sp + 2, ep), &atomv);
1535                atomv->handler(atomv, &state);
1536        }
1537        if (*cp) {
1538                sp = cp + strlen(cp);
1539                append_literal(cp, sp, &state);
1540        }
1541        if (need_color_reset_at_eol) {
1542                struct atom_value resetv;
1543                char color[COLOR_MAXLEN] = "";
1544
1545                if (color_parse("reset", color) < 0)
1546                        die("BUG: couldn't parse 'reset' as a color");
1547                resetv.s = color;
1548                append_atom(&resetv, &state);
1549        }
1550        if (state.stack->prev)
1551                die(_("format: %%(end) atom missing"));
1552        final_buf = &state.stack->output;
1553        fwrite(final_buf->buf, 1, final_buf->len, stdout);
1554        pop_stack_element(&state.stack);
1555        putchar('\n');
1556}
1557
1558/*  If no sorting option is given, use refname to sort as default */
1559struct ref_sorting *ref_default_sorting(void)
1560{
1561        static const char cstr_name[] = "refname";
1562
1563        struct ref_sorting *sorting = xcalloc(1, sizeof(*sorting));
1564
1565        sorting->next = NULL;
1566        sorting->atom = parse_ref_filter_atom(cstr_name, cstr_name + strlen(cstr_name));
1567        return sorting;
1568}
1569
1570int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset)
1571{
1572        struct ref_sorting **sorting_tail = opt->value;
1573        struct ref_sorting *s;
1574        int len;
1575
1576        if (!arg) /* should --no-sort void the list ? */
1577                return -1;
1578
1579        s = xcalloc(1, sizeof(*s));
1580        s->next = *sorting_tail;
1581        *sorting_tail = s;
1582
1583        if (*arg == '-') {
1584                s->reverse = 1;
1585                arg++;
1586        }
1587        len = strlen(arg);
1588        s->atom = parse_ref_filter_atom(arg, arg+len);
1589        return 0;
1590}
1591
1592int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
1593{
1594        struct ref_filter *rf = opt->value;
1595        unsigned char sha1[20];
1596
1597        rf->merge = starts_with(opt->long_name, "no")
1598                ? REF_FILTER_MERGED_OMIT
1599                : REF_FILTER_MERGED_INCLUDE;
1600
1601        if (get_sha1(arg, sha1))
1602                die(_("malformed object name %s"), arg);
1603
1604        rf->merge_commit = lookup_commit_reference_gently(sha1, 0);
1605        if (!rf->merge_commit)
1606                return opterror(opt, "must point to a commit", 0);
1607
1608        return 0;
1609}