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