b80e52b157de61f1d4a22d730e2a9c1cb88caaba
   1/*
   2 * Handle git attributes.  See gitattributes(5) for a description of
   3 * the file syntax, and Documentation/technical/api-gitattributes.txt
   4 * for a description of the API.
   5 *
   6 * One basic design decision here is that we are not going to support
   7 * an insanely large number of attributes.
   8 */
   9
  10#define NO_THE_INDEX_COMPATIBILITY_MACROS
  11#include "cache.h"
  12#include "exec_cmd.h"
  13#include "attr.h"
  14#include "dir.h"
  15
  16const char git_attr__true[] = "(builtin)true";
  17const char git_attr__false[] = "\0(builtin)false";
  18static const char git_attr__unknown[] = "(builtin)unknown";
  19#define ATTR__TRUE git_attr__true
  20#define ATTR__FALSE git_attr__false
  21#define ATTR__UNSET NULL
  22#define ATTR__UNKNOWN git_attr__unknown
  23
  24/* This is a randomly chosen prime. */
  25#define HASHSIZE 257
  26
  27#ifndef DEBUG_ATTR
  28#define DEBUG_ATTR 0
  29#endif
  30
  31struct git_attr {
  32        struct git_attr *next;
  33        unsigned h;
  34        int attr_nr;
  35        int maybe_macro;
  36        char name[FLEX_ARRAY];
  37};
  38static int attr_nr;
  39
  40static struct git_attr_check *check_all_attr;
  41static struct git_attr *(git_attr_hash[HASHSIZE]);
  42
  43char *git_attr_name(struct git_attr *attr)
  44{
  45        return attr->name;
  46}
  47
  48static unsigned hash_name(const char *name, int namelen)
  49{
  50        unsigned val = 0, c;
  51
  52        while (namelen--) {
  53                c = *name++;
  54                val = ((val << 7) | (val >> 22)) ^ c;
  55        }
  56        return val;
  57}
  58
  59static int invalid_attr_name(const char *name, int namelen)
  60{
  61        /*
  62         * Attribute name cannot begin with '-' and must consist of
  63         * characters from [-A-Za-z0-9_.].
  64         */
  65        if (namelen <= 0 || *name == '-')
  66                return -1;
  67        while (namelen--) {
  68                char ch = *name++;
  69                if (! (ch == '-' || ch == '.' || ch == '_' ||
  70                       ('0' <= ch && ch <= '9') ||
  71                       ('a' <= ch && ch <= 'z') ||
  72                       ('A' <= ch && ch <= 'Z')) )
  73                        return -1;
  74        }
  75        return 0;
  76}
  77
  78static struct git_attr *git_attr_internal(const char *name, int len)
  79{
  80        unsigned hval = hash_name(name, len);
  81        unsigned pos = hval % HASHSIZE;
  82        struct git_attr *a;
  83
  84        for (a = git_attr_hash[pos]; a; a = a->next) {
  85                if (a->h == hval &&
  86                    !memcmp(a->name, name, len) && !a->name[len])
  87                        return a;
  88        }
  89
  90        if (invalid_attr_name(name, len))
  91                return NULL;
  92
  93        a = xmalloc(sizeof(*a) + len + 1);
  94        memcpy(a->name, name, len);
  95        a->name[len] = 0;
  96        a->h = hval;
  97        a->next = git_attr_hash[pos];
  98        a->attr_nr = attr_nr++;
  99        a->maybe_macro = 0;
 100        git_attr_hash[pos] = a;
 101
 102        REALLOC_ARRAY(check_all_attr, attr_nr);
 103        check_all_attr[a->attr_nr].attr = a;
 104        check_all_attr[a->attr_nr].value = ATTR__UNKNOWN;
 105        return a;
 106}
 107
 108struct git_attr *git_attr(const char *name)
 109{
 110        return git_attr_internal(name, strlen(name));
 111}
 112
 113/* What does a matched pattern decide? */
 114struct attr_state {
 115        struct git_attr *attr;
 116        const char *setto;
 117};
 118
 119struct pattern {
 120        const char *pattern;
 121        int patternlen;
 122        int nowildcardlen;
 123        int flags;              /* EXC_FLAG_* */
 124};
 125
 126/*
 127 * One rule, as from a .gitattributes file.
 128 *
 129 * If is_macro is true, then u.attr is a pointer to the git_attr being
 130 * defined.
 131 *
 132 * If is_macro is false, then u.pattern points at the filename pattern
 133 * to which the rule applies.  (The memory pointed to is part of the
 134 * memory block allocated for the match_attr instance.)
 135 *
 136 * In either case, num_attr is the number of attributes affected by
 137 * this rule, and state is an array listing them.  The attributes are
 138 * listed as they appear in the file (macros unexpanded).
 139 */
 140struct match_attr {
 141        union {
 142                struct pattern pat;
 143                struct git_attr *attr;
 144        } u;
 145        char is_macro;
 146        unsigned num_attr;
 147        struct attr_state state[FLEX_ARRAY];
 148};
 149
 150static const char blank[] = " \t\r\n";
 151
 152/*
 153 * Parse a whitespace-delimited attribute state (i.e., "attr",
 154 * "-attr", "!attr", or "attr=value") from the string starting at src.
 155 * If e is not NULL, write the results to *e.  Return a pointer to the
 156 * remainder of the string (with leading whitespace removed), or NULL
 157 * if there was an error.
 158 */
 159static const char *parse_attr(const char *src, int lineno, const char *cp,
 160                              struct attr_state *e)
 161{
 162        const char *ep, *equals;
 163        int len;
 164
 165        ep = cp + strcspn(cp, blank);
 166        equals = strchr(cp, '=');
 167        if (equals && ep < equals)
 168                equals = NULL;
 169        if (equals)
 170                len = equals - cp;
 171        else
 172                len = ep - cp;
 173        if (!e) {
 174                if (*cp == '-' || *cp == '!') {
 175                        cp++;
 176                        len--;
 177                }
 178                if (invalid_attr_name(cp, len)) {
 179                        fprintf(stderr,
 180                                "%.*s is not a valid attribute name: %s:%d\n",
 181                                len, cp, src, lineno);
 182                        return NULL;
 183                }
 184        } else {
 185                if (*cp == '-' || *cp == '!') {
 186                        e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET;
 187                        cp++;
 188                        len--;
 189                }
 190                else if (!equals)
 191                        e->setto = ATTR__TRUE;
 192                else {
 193                        e->setto = xmemdupz(equals + 1, ep - equals - 1);
 194                }
 195                e->attr = git_attr_internal(cp, len);
 196        }
 197        return ep + strspn(ep, blank);
 198}
 199
 200static struct match_attr *parse_attr_line(const char *line, const char *src,
 201                                          int lineno, int macro_ok)
 202{
 203        int namelen;
 204        int num_attr, i;
 205        const char *cp, *name, *states;
 206        struct match_attr *res = NULL;
 207        int is_macro;
 208
 209        cp = line + strspn(line, blank);
 210        if (!*cp || *cp == '#')
 211                return NULL;
 212        name = cp;
 213        namelen = strcspn(name, blank);
 214        if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
 215            starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {
 216                if (!macro_ok) {
 217                        fprintf(stderr, "%s not allowed: %s:%d\n",
 218                                name, src, lineno);
 219                        return NULL;
 220                }
 221                is_macro = 1;
 222                name += strlen(ATTRIBUTE_MACRO_PREFIX);
 223                name += strspn(name, blank);
 224                namelen = strcspn(name, blank);
 225                if (invalid_attr_name(name, namelen)) {
 226                        fprintf(stderr,
 227                                "%.*s is not a valid attribute name: %s:%d\n",
 228                                namelen, name, src, lineno);
 229                        return NULL;
 230                }
 231        }
 232        else
 233                is_macro = 0;
 234
 235        states = name + namelen;
 236        states += strspn(states, blank);
 237
 238        /* First pass to count the attr_states */
 239        for (cp = states, num_attr = 0; *cp; num_attr++) {
 240                cp = parse_attr(src, lineno, cp, NULL);
 241                if (!cp)
 242                        return NULL;
 243        }
 244
 245        res = xcalloc(1,
 246                      sizeof(*res) +
 247                      sizeof(struct attr_state) * num_attr +
 248                      (is_macro ? 0 : namelen + 1));
 249        if (is_macro) {
 250                res->u.attr = git_attr_internal(name, namelen);
 251                res->u.attr->maybe_macro = 1;
 252        } else {
 253                char *p = (char *)&(res->state[num_attr]);
 254                memcpy(p, name, namelen);
 255                res->u.pat.pattern = p;
 256                parse_exclude_pattern(&res->u.pat.pattern,
 257                                      &res->u.pat.patternlen,
 258                                      &res->u.pat.flags,
 259                                      &res->u.pat.nowildcardlen);
 260                if (res->u.pat.flags & EXC_FLAG_NEGATIVE) {
 261                        warning(_("Negative patterns are ignored in git attributes\n"
 262                                  "Use '\\!' for literal leading exclamation."));
 263                        return NULL;
 264                }
 265        }
 266        res->is_macro = is_macro;
 267        res->num_attr = num_attr;
 268
 269        /* Second pass to fill the attr_states */
 270        for (cp = states, i = 0; *cp; i++) {
 271                cp = parse_attr(src, lineno, cp, &(res->state[i]));
 272        }
 273
 274        return res;
 275}
 276
 277/*
 278 * Like info/exclude and .gitignore, the attribute information can
 279 * come from many places.
 280 *
 281 * (1) .gitattribute file of the same directory;
 282 * (2) .gitattribute file of the parent directory if (1) does not have
 283 *      any match; this goes recursively upwards, just like .gitignore.
 284 * (3) $GIT_DIR/info/attributes, which overrides both of the above.
 285 *
 286 * In the same file, later entries override the earlier match, so in the
 287 * global list, we would have entries from info/attributes the earliest
 288 * (reading the file from top to bottom), .gitattribute of the root
 289 * directory (again, reading the file from top to bottom) down to the
 290 * current directory, and then scan the list backwards to find the first match.
 291 * This is exactly the same as what is_excluded() does in dir.c to deal with
 292 * .gitignore
 293 */
 294
 295static struct attr_stack {
 296        struct attr_stack *prev;
 297        char *origin;
 298        size_t originlen;
 299        unsigned num_matches;
 300        unsigned alloc;
 301        struct match_attr **attrs;
 302} *attr_stack;
 303
 304static void free_attr_elem(struct attr_stack *e)
 305{
 306        int i;
 307        free(e->origin);
 308        for (i = 0; i < e->num_matches; i++) {
 309                struct match_attr *a = e->attrs[i];
 310                int j;
 311                for (j = 0; j < a->num_attr; j++) {
 312                        const char *setto = a->state[j].setto;
 313                        if (setto == ATTR__TRUE ||
 314                            setto == ATTR__FALSE ||
 315                            setto == ATTR__UNSET ||
 316                            setto == ATTR__UNKNOWN)
 317                                ;
 318                        else
 319                                free((char *) setto);
 320                }
 321                free(a);
 322        }
 323        free(e->attrs);
 324        free(e);
 325}
 326
 327static const char *builtin_attr[] = {
 328        "[attr]binary -diff -merge -text",
 329        NULL,
 330};
 331
 332static void handle_attr_line(struct attr_stack *res,
 333                             const char *line,
 334                             const char *src,
 335                             int lineno,
 336                             int macro_ok)
 337{
 338        struct match_attr *a;
 339
 340        a = parse_attr_line(line, src, lineno, macro_ok);
 341        if (!a)
 342                return;
 343        ALLOC_GROW(res->attrs, res->num_matches + 1, res->alloc);
 344        res->attrs[res->num_matches++] = a;
 345}
 346
 347static struct attr_stack *read_attr_from_array(const char **list)
 348{
 349        struct attr_stack *res;
 350        const char *line;
 351        int lineno = 0;
 352
 353        res = xcalloc(1, sizeof(*res));
 354        while ((line = *(list++)) != NULL)
 355                handle_attr_line(res, line, "[builtin]", ++lineno, 1);
 356        return res;
 357}
 358
 359static enum git_attr_direction direction;
 360static struct index_state *use_index;
 361
 362static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
 363{
 364        FILE *fp = fopen(path, "r");
 365        struct attr_stack *res;
 366        char buf[2048];
 367        int lineno = 0;
 368
 369        if (!fp) {
 370                if (errno != ENOENT && errno != ENOTDIR)
 371                        warn_on_inaccessible(path);
 372                return NULL;
 373        }
 374        res = xcalloc(1, sizeof(*res));
 375        while (fgets(buf, sizeof(buf), fp))
 376                handle_attr_line(res, buf, path, ++lineno, macro_ok);
 377        fclose(fp);
 378        return res;
 379}
 380
 381static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
 382{
 383        struct attr_stack *res;
 384        char *buf, *sp;
 385        int lineno = 0;
 386
 387        buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL);
 388        if (!buf)
 389                return NULL;
 390
 391        res = xcalloc(1, sizeof(*res));
 392        for (sp = buf; *sp; ) {
 393                char *ep;
 394                int more;
 395                for (ep = sp; *ep && *ep != '\n'; ep++)
 396                        ;
 397                more = (*ep == '\n');
 398                *ep = '\0';
 399                handle_attr_line(res, sp, path, ++lineno, macro_ok);
 400                sp = ep + more;
 401        }
 402        free(buf);
 403        return res;
 404}
 405
 406static struct attr_stack *read_attr(const char *path, int macro_ok)
 407{
 408        struct attr_stack *res;
 409
 410        if (direction == GIT_ATTR_CHECKOUT) {
 411                res = read_attr_from_index(path, macro_ok);
 412                if (!res)
 413                        res = read_attr_from_file(path, macro_ok);
 414        }
 415        else if (direction == GIT_ATTR_CHECKIN) {
 416                res = read_attr_from_file(path, macro_ok);
 417                if (!res)
 418                        /*
 419                         * There is no checked out .gitattributes file there, but
 420                         * we might have it in the index.  We allow operation in a
 421                         * sparsely checked out work tree, so read from it.
 422                         */
 423                        res = read_attr_from_index(path, macro_ok);
 424        }
 425        else
 426                res = read_attr_from_index(path, macro_ok);
 427        if (!res)
 428                res = xcalloc(1, sizeof(*res));
 429        return res;
 430}
 431
 432#if DEBUG_ATTR
 433static void debug_info(const char *what, struct attr_stack *elem)
 434{
 435        fprintf(stderr, "%s: %s\n", what, elem->origin ? elem->origin : "()");
 436}
 437static void debug_set(const char *what, const char *match, struct git_attr *attr, const void *v)
 438{
 439        const char *value = v;
 440
 441        if (ATTR_TRUE(value))
 442                value = "set";
 443        else if (ATTR_FALSE(value))
 444                value = "unset";
 445        else if (ATTR_UNSET(value))
 446                value = "unspecified";
 447
 448        fprintf(stderr, "%s: %s => %s (%s)\n",
 449                what, attr->name, (char *) value, match);
 450}
 451#define debug_push(a) debug_info("push", (a))
 452#define debug_pop(a) debug_info("pop", (a))
 453#else
 454#define debug_push(a) do { ; } while (0)
 455#define debug_pop(a) do { ; } while (0)
 456#define debug_set(a,b,c,d) do { ; } while (0)
 457#endif
 458
 459static void drop_attr_stack(void)
 460{
 461        while (attr_stack) {
 462                struct attr_stack *elem = attr_stack;
 463                attr_stack = elem->prev;
 464                free_attr_elem(elem);
 465        }
 466}
 467
 468static const char *git_etc_gitattributes(void)
 469{
 470        static const char *system_wide;
 471        if (!system_wide)
 472                system_wide = system_path(ETC_GITATTRIBUTES);
 473        return system_wide;
 474}
 475
 476static int git_attr_system(void)
 477{
 478        return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
 479}
 480
 481static void bootstrap_attr_stack(void)
 482{
 483        struct attr_stack *elem;
 484        char *xdg_attributes_file;
 485
 486        if (attr_stack)
 487                return;
 488
 489        elem = read_attr_from_array(builtin_attr);
 490        elem->origin = NULL;
 491        elem->prev = attr_stack;
 492        attr_stack = elem;
 493
 494        if (git_attr_system()) {
 495                elem = read_attr_from_file(git_etc_gitattributes(), 1);
 496                if (elem) {
 497                        elem->origin = NULL;
 498                        elem->prev = attr_stack;
 499                        attr_stack = elem;
 500                }
 501        }
 502
 503        if (!git_attributes_file) {
 504                home_config_paths(NULL, &xdg_attributes_file, "attributes");
 505                git_attributes_file = xdg_attributes_file;
 506        }
 507        if (git_attributes_file) {
 508                elem = read_attr_from_file(git_attributes_file, 1);
 509                if (elem) {
 510                        elem->origin = NULL;
 511                        elem->prev = attr_stack;
 512                        attr_stack = elem;
 513                }
 514        }
 515
 516        if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
 517                elem = read_attr(GITATTRIBUTES_FILE, 1);
 518                elem->origin = xstrdup("");
 519                elem->originlen = 0;
 520                elem->prev = attr_stack;
 521                attr_stack = elem;
 522                debug_push(elem);
 523        }
 524
 525        elem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);
 526        if (!elem)
 527                elem = xcalloc(1, sizeof(*elem));
 528        elem->origin = NULL;
 529        elem->prev = attr_stack;
 530        attr_stack = elem;
 531}
 532
 533static void prepare_attr_stack(const char *path, int dirlen)
 534{
 535        struct attr_stack *elem, *info;
 536        int len;
 537        const char *cp;
 538
 539        /*
 540         * At the bottom of the attribute stack is the built-in
 541         * set of attribute definitions, followed by the contents
 542         * of $(prefix)/etc/gitattributes and a file specified by
 543         * core.attributesfile.  Then, contents from
 544         * .gitattribute files from directories closer to the
 545         * root to the ones in deeper directories are pushed
 546         * to the stack.  Finally, at the very top of the stack
 547         * we always keep the contents of $GIT_DIR/info/attributes.
 548         *
 549         * When checking, we use entries from near the top of the
 550         * stack, preferring $GIT_DIR/info/attributes, then
 551         * .gitattributes in deeper directories to shallower ones,
 552         * and finally use the built-in set as the default.
 553         */
 554        bootstrap_attr_stack();
 555
 556        /*
 557         * Pop the "info" one that is always at the top of the stack.
 558         */
 559        info = attr_stack;
 560        attr_stack = info->prev;
 561
 562        /*
 563         * Pop the ones from directories that are not the prefix of
 564         * the path we are checking. Break out of the loop when we see
 565         * the root one (whose origin is an empty string "") or the builtin
 566         * one (whose origin is NULL) without popping it.
 567         */
 568        while (attr_stack->origin) {
 569                int namelen = strlen(attr_stack->origin);
 570
 571                elem = attr_stack;
 572                if (namelen <= dirlen &&
 573                    !strncmp(elem->origin, path, namelen) &&
 574                    (!namelen || path[namelen] == '/'))
 575                        break;
 576
 577                debug_pop(elem);
 578                attr_stack = elem->prev;
 579                free_attr_elem(elem);
 580        }
 581
 582        /*
 583         * Read from parent directories and push them down
 584         */
 585        if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
 586                /*
 587                 * bootstrap_attr_stack() should have added, and the
 588                 * above loop should have stopped before popping, the
 589                 * root element whose attr_stack->origin is set to an
 590                 * empty string.
 591                 */
 592                struct strbuf pathbuf = STRBUF_INIT;
 593
 594                assert(attr_stack->origin);
 595                while (1) {
 596                        len = strlen(attr_stack->origin);
 597                        if (dirlen <= len)
 598                                break;
 599                        cp = memchr(path + len + 1, '/', dirlen - len - 1);
 600                        if (!cp)
 601                                cp = path + dirlen;
 602                        strbuf_add(&pathbuf, path, cp - path);
 603                        strbuf_addch(&pathbuf, '/');
 604                        strbuf_addstr(&pathbuf, GITATTRIBUTES_FILE);
 605                        elem = read_attr(pathbuf.buf, 0);
 606                        strbuf_setlen(&pathbuf, cp - path);
 607                        elem->origin = strbuf_detach(&pathbuf, &elem->originlen);
 608                        elem->prev = attr_stack;
 609                        attr_stack = elem;
 610                        debug_push(elem);
 611                }
 612
 613                strbuf_release(&pathbuf);
 614        }
 615
 616        /*
 617         * Finally push the "info" one at the top of the stack.
 618         */
 619        info->prev = attr_stack;
 620        attr_stack = info;
 621}
 622
 623static int path_matches(const char *pathname, int pathlen,
 624                        int basename_offset,
 625                        const struct pattern *pat,
 626                        const char *base, int baselen)
 627{
 628        const char *pattern = pat->pattern;
 629        int prefix = pat->nowildcardlen;
 630        int isdir = (pathlen && pathname[pathlen - 1] == '/');
 631
 632        if ((pat->flags & EXC_FLAG_MUSTBEDIR) && !isdir)
 633                return 0;
 634
 635        if (pat->flags & EXC_FLAG_NODIR) {
 636                return match_basename(pathname + basename_offset,
 637                                      pathlen - basename_offset - isdir,
 638                                      pattern, prefix,
 639                                      pat->patternlen, pat->flags);
 640        }
 641        return match_pathname(pathname, pathlen - isdir,
 642                              base, baselen,
 643                              pattern, prefix, pat->patternlen, pat->flags);
 644}
 645
 646static int macroexpand_one(int attr_nr, int rem);
 647
 648static int fill_one(const char *what, struct match_attr *a, int rem)
 649{
 650        struct git_attr_check *check = check_all_attr;
 651        int i;
 652
 653        for (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {
 654                struct git_attr *attr = a->state[i].attr;
 655                const char **n = &(check[attr->attr_nr].value);
 656                const char *v = a->state[i].setto;
 657
 658                if (*n == ATTR__UNKNOWN) {
 659                        debug_set(what,
 660                                  a->is_macro ? a->u.attr->name : a->u.pat.pattern,
 661                                  attr, v);
 662                        *n = v;
 663                        rem--;
 664                        rem = macroexpand_one(attr->attr_nr, rem);
 665                }
 666        }
 667        return rem;
 668}
 669
 670static int fill(const char *path, int pathlen, int basename_offset,
 671                struct attr_stack *stk, int rem)
 672{
 673        int i;
 674        const char *base = stk->origin ? stk->origin : "";
 675
 676        for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {
 677                struct match_attr *a = stk->attrs[i];
 678                if (a->is_macro)
 679                        continue;
 680                if (path_matches(path, pathlen, basename_offset,
 681                                 &a->u.pat, base, stk->originlen))
 682                        rem = fill_one("fill", a, rem);
 683        }
 684        return rem;
 685}
 686
 687static int macroexpand_one(int nr, int rem)
 688{
 689        struct attr_stack *stk;
 690        struct match_attr *a = NULL;
 691        int i;
 692
 693        if (check_all_attr[nr].value != ATTR__TRUE ||
 694            !check_all_attr[nr].attr->maybe_macro)
 695                return rem;
 696
 697        for (stk = attr_stack; !a && stk; stk = stk->prev)
 698                for (i = stk->num_matches - 1; !a && 0 <= i; i--) {
 699                        struct match_attr *ma = stk->attrs[i];
 700                        if (!ma->is_macro)
 701                                continue;
 702                        if (ma->u.attr->attr_nr == nr)
 703                                a = ma;
 704                }
 705
 706        if (a)
 707                rem = fill_one("expand", a, rem);
 708
 709        return rem;
 710}
 711
 712/*
 713 * Collect all attributes for path into the array pointed to by
 714 * check_all_attr.
 715 */
 716static void collect_all_attrs(const char *path)
 717{
 718        struct attr_stack *stk;
 719        int i, pathlen, rem, dirlen;
 720        const char *cp, *last_slash = NULL;
 721        int basename_offset;
 722
 723        for (cp = path; *cp; cp++) {
 724                if (*cp == '/' && cp[1])
 725                        last_slash = cp;
 726        }
 727        pathlen = cp - path;
 728        if (last_slash) {
 729                basename_offset = last_slash + 1 - path;
 730                dirlen = last_slash - path;
 731        } else {
 732                basename_offset = 0;
 733                dirlen = 0;
 734        }
 735
 736        prepare_attr_stack(path, dirlen);
 737        for (i = 0; i < attr_nr; i++)
 738                check_all_attr[i].value = ATTR__UNKNOWN;
 739
 740        rem = attr_nr;
 741        for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
 742                rem = fill(path, pathlen, basename_offset, stk, rem);
 743}
 744
 745int git_check_attr(const char *path, int num, struct git_attr_check *check)
 746{
 747        int i;
 748
 749        collect_all_attrs(path);
 750
 751        for (i = 0; i < num; i++) {
 752                const char *value = check_all_attr[check[i].attr->attr_nr].value;
 753                if (value == ATTR__UNKNOWN)
 754                        value = ATTR__UNSET;
 755                check[i].value = value;
 756        }
 757
 758        return 0;
 759}
 760
 761int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
 762{
 763        int i, count, j;
 764
 765        collect_all_attrs(path);
 766
 767        /* Count the number of attributes that are set. */
 768        count = 0;
 769        for (i = 0; i < attr_nr; i++) {
 770                const char *value = check_all_attr[i].value;
 771                if (value != ATTR__UNSET && value != ATTR__UNKNOWN)
 772                        ++count;
 773        }
 774        *num = count;
 775        *check = xmalloc(sizeof(**check) * count);
 776        j = 0;
 777        for (i = 0; i < attr_nr; i++) {
 778                const char *value = check_all_attr[i].value;
 779                if (value != ATTR__UNSET && value != ATTR__UNKNOWN) {
 780                        (*check)[j].attr = check_all_attr[i].attr;
 781                        (*check)[j].value = value;
 782                        ++j;
 783                }
 784        }
 785
 786        return 0;
 787}
 788
 789void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
 790{
 791        enum git_attr_direction old = direction;
 792
 793        if (is_bare_repository() && new != GIT_ATTR_INDEX)
 794                die("BUG: non-INDEX attr direction in a bare repo");
 795
 796        direction = new;
 797        if (new != old)
 798                drop_attr_stack();
 799        use_index = istate;
 800}