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