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