diff options
Diffstat (limited to 'attr.c')
-rw-r--r-- | attr.c | 97 |
1 files changed, 70 insertions, 27 deletions
@@ -13,6 +13,8 @@ #include "dir.h" #include "utf8.h" #include "quote.h" +#include "revision.h" +#include "object-store.h" #include "thread-utils.h" const char git_attr__true[] = "(builtin)true"; @@ -729,14 +731,62 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags) return res; } -static struct attr_stack *read_attr_from_index(struct index_state *istate, - const char *path, - unsigned flags) +static struct attr_stack *read_attr_from_buf(char *buf, const char *path, + unsigned flags) { struct attr_stack *res; - char *buf, *sp; + char *sp; int lineno = 0; + if (!buf) + return NULL; + + CALLOC_ARRAY(res, 1); + for (sp = buf; *sp;) { + char *ep; + int more; + + ep = strchrnul(sp, '\n'); + more = (*ep == '\n'); + *ep = '\0'; + handle_attr_line(res, sp, path, ++lineno, flags); + sp = ep + more; + } + free(buf); + + return res; +} + +static struct attr_stack *read_attr_from_blob(struct index_state *istate, + const struct object_id *tree_oid, + const char *path, unsigned flags) +{ + struct object_id oid; + unsigned long sz; + enum object_type type; + void *buf; + unsigned short mode; + + if (!tree_oid) + return NULL; + + if (get_tree_entry(istate->repo, tree_oid, path, &oid, &mode)) + return NULL; + + buf = repo_read_object_file(istate->repo, &oid, &type, &sz); + if (!buf || type != OBJ_BLOB) { + free(buf); + return NULL; + } + + return read_attr_from_buf(buf, path, flags); +} + +static struct attr_stack *read_attr_from_index(struct index_state *istate, + const char *path, unsigned flags) +{ + char *buf; + if (!istate) return NULL; @@ -758,28 +808,19 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate, if (!buf) return NULL; - CALLOC_ARRAY(res, 1); - for (sp = buf; *sp; ) { - char *ep; - int more; - - ep = strchrnul(sp, '\n'); - more = (*ep == '\n'); - *ep = '\0'; - handle_attr_line(res, sp, path, ++lineno, flags); - sp = ep + more; - } - free(buf); - return res; + return read_attr_from_buf(buf, path, flags); } static struct attr_stack *read_attr(struct index_state *istate, + const struct object_id *tree_oid, const char *path, unsigned flags) { struct attr_stack *res = NULL; if (direction == GIT_ATTR_INDEX) { res = read_attr_from_index(istate, path, flags); + } else if (tree_oid) { + res = read_attr_from_blob(istate, tree_oid, path, flags); } else if (!is_bare_repository()) { if (direction == GIT_ATTR_CHECKOUT) { res = read_attr_from_index(istate, path, flags); @@ -839,6 +880,7 @@ static void push_stack(struct attr_stack **attr_stack_p, } static void bootstrap_attr_stack(struct index_state *istate, + const struct object_id *tree_oid, struct attr_stack **stack) { struct attr_stack *e; @@ -864,7 +906,7 @@ static void bootstrap_attr_stack(struct index_state *istate, } /* root directory */ - e = read_attr(istate, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW); + e = read_attr(istate, tree_oid, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW); push_stack(stack, e, xstrdup(""), 0); /* info frame */ @@ -878,6 +920,7 @@ static void bootstrap_attr_stack(struct index_state *istate, } static void prepare_attr_stack(struct index_state *istate, + const struct object_id *tree_oid, const char *path, int dirlen, struct attr_stack **stack) { @@ -899,7 +942,7 @@ static void prepare_attr_stack(struct index_state *istate, * .gitattributes in deeper directories to shallower ones, * and finally use the built-in set as the default. */ - bootstrap_attr_stack(istate, stack); + bootstrap_attr_stack(istate, tree_oid, stack); /* * Pop the "info" one that is always at the top of the stack. @@ -954,7 +997,7 @@ static void prepare_attr_stack(struct index_state *istate, strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len)); strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE); - next = read_attr(istate, pathbuf.buf, READ_ATTR_NOFOLLOW); + next = read_attr(istate, tree_oid, pathbuf.buf, READ_ATTR_NOFOLLOW); /* reset the pathbuf to not include "/.gitattributes" */ strbuf_setlen(&pathbuf, len); @@ -1074,8 +1117,8 @@ static void determine_macros(struct all_attrs_item *all_attrs, * Otherwise all attributes are collected. */ static void collect_some_attrs(struct index_state *istate, - const char *path, - struct attr_check *check) + const struct object_id *tree_oid, + const char *path, struct attr_check *check) { int pathlen, rem, dirlen; const char *cp, *last_slash = NULL; @@ -1094,7 +1137,7 @@ static void collect_some_attrs(struct index_state *istate, dirlen = 0; } - prepare_attr_stack(istate, path, dirlen, &check->stack); + prepare_attr_stack(istate, tree_oid, path, dirlen, &check->stack); all_attrs_init(&g_attr_hashmap, check); determine_macros(check->all_attrs, check->stack); @@ -1103,12 +1146,12 @@ static void collect_some_attrs(struct index_state *istate, } void git_check_attr(struct index_state *istate, - const char *path, + const struct object_id *tree_oid, const char *path, struct attr_check *check) { int i; - collect_some_attrs(istate, path, check); + collect_some_attrs(istate, tree_oid, path, check); for (i = 0; i < check->nr; i++) { size_t n = check->items[i].attr->attr_nr; @@ -1119,13 +1162,13 @@ void git_check_attr(struct index_state *istate, } } -void git_all_attrs(struct index_state *istate, +void git_all_attrs(struct index_state *istate, const struct object_id *tree_oid, const char *path, struct attr_check *check) { int i; attr_check_reset(check); - collect_some_attrs(istate, path, check); + collect_some_attrs(istate, tree_oid, path, check); for (i = 0; i < check->all_attrs_nr; i++) { const char *name = check->all_attrs[i].attr->name; |