1313#include "dir.h"
1414#include "utf8.h"
1515#include "quote.h"
16+ #include "revision.h"
17+ #include "object-store.h"
1618#include "thread-utils.h"
1719
1820const char git_attr__true[] = "(builtin)true";
@@ -744,13 +746,61 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
744746 return res;
745747}
746748
747- static struct attr_stack *read_attr_from_index(struct index_state *istate,
748- const char *path,
749- unsigned flags)
749+ static struct attr_stack *read_attr_from_buf(char *buf, const char *path,
750+ unsigned flags)
750751{
751752 struct attr_stack *res;
752- char *buf, * sp;
753+ char *sp;
753754 int lineno = 0;
755+
756+ if (!buf)
757+ return NULL;
758+
759+ CALLOC_ARRAY(res, 1);
760+ for (sp = buf; *sp;) {
761+ char *ep;
762+ int more;
763+
764+ ep = strchrnul(sp, '\n');
765+ more = (*ep == '\n');
766+ *ep = '\0';
767+ handle_attr_line(res, sp, path, ++lineno, flags);
768+ sp = ep + more;
769+ }
770+ free(buf);
771+
772+ return res;
773+ }
774+
775+ static struct attr_stack *read_attr_from_blob(struct index_state *istate,
776+ const struct object_id *tree_oid,
777+ const char *path, unsigned flags)
778+ {
779+ struct object_id oid;
780+ unsigned long sz;
781+ enum object_type type;
782+ void *buf;
783+ unsigned short mode;
784+
785+ if (!tree_oid)
786+ return NULL;
787+
788+ if (get_tree_entry(istate->repo, tree_oid, path, &oid, &mode))
789+ return NULL;
790+
791+ buf = repo_read_object_file(istate->repo, &oid, &type, &sz);
792+ if (!buf || type != OBJ_BLOB) {
793+ free(buf);
794+ return NULL;
795+ }
796+
797+ return read_attr_from_buf(buf, path, flags);
798+ }
799+
800+ static struct attr_stack *read_attr_from_index(struct index_state *istate,
801+ const char *path, unsigned flags)
802+ {
803+ char *buf;
754804 unsigned long size;
755805
756806 if (!istate)
@@ -778,28 +828,19 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
778828 return NULL;
779829 }
780830
781- CALLOC_ARRAY(res, 1);
782- for (sp = buf; *sp; ) {
783- char *ep;
784- int more;
785-
786- ep = strchrnul(sp, '\n');
787- more = (*ep == '\n');
788- *ep = '\0';
789- handle_attr_line(res, sp, path, ++lineno, flags);
790- sp = ep + more;
791- }
792- free(buf);
793- return res;
831+ return read_attr_from_buf(buf, path, flags);
794832}
795833
796834static struct attr_stack *read_attr(struct index_state *istate,
835+ const struct object_id *tree_oid,
797836 const char *path, unsigned flags)
798837{
799838 struct attr_stack *res = NULL;
800839
801840 if (direction == GIT_ATTR_INDEX) {
802841 res = read_attr_from_index(istate, path, flags);
842+ } else if (tree_oid) {
843+ res = read_attr_from_blob(istate, tree_oid, path, flags);
803844 } else if (!is_bare_repository()) {
804845 if (direction == GIT_ATTR_CHECKOUT) {
805846 res = read_attr_from_index(istate, path, flags);
@@ -859,6 +900,7 @@ static void push_stack(struct attr_stack **attr_stack_p,
859900}
860901
861902static void bootstrap_attr_stack(struct index_state *istate,
903+ const struct object_id *tree_oid,
862904 struct attr_stack **stack)
863905{
864906 struct attr_stack *e;
@@ -884,7 +926,7 @@ static void bootstrap_attr_stack(struct index_state *istate,
884926 }
885927
886928 /* root directory */
887- e = read_attr(istate, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW);
929+ e = read_attr(istate, tree_oid, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW);
888930 push_stack(stack, e, xstrdup(""), 0);
889931
890932 /* info frame */
@@ -898,6 +940,7 @@ static void bootstrap_attr_stack(struct index_state *istate,
898940}
899941
900942static void prepare_attr_stack(struct index_state *istate,
943+ const struct object_id *tree_oid,
901944 const char *path, int dirlen,
902945 struct attr_stack **stack)
903946{
@@ -919,7 +962,7 @@ static void prepare_attr_stack(struct index_state *istate,
919962 * .gitattributes in deeper directories to shallower ones,
920963 * and finally use the built-in set as the default.
921964 */
922- bootstrap_attr_stack(istate, stack);
965+ bootstrap_attr_stack(istate, tree_oid, stack);
923966
924967 /*
925968 * Pop the "info" one that is always at the top of the stack.
@@ -974,7 +1017,7 @@ static void prepare_attr_stack(struct index_state *istate,
9741017 strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len));
9751018 strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE);
9761019
977- next = read_attr(istate, pathbuf.buf, READ_ATTR_NOFOLLOW);
1020+ next = read_attr(istate, tree_oid, pathbuf.buf, READ_ATTR_NOFOLLOW);
9781021
9791022 /* reset the pathbuf to not include "/.gitattributes" */
9801023 strbuf_setlen(&pathbuf, len);
@@ -1094,8 +1137,8 @@ static void determine_macros(struct all_attrs_item *all_attrs,
10941137 * Otherwise all attributes are collected.
10951138 */
10961139static void collect_some_attrs(struct index_state *istate,
1097- const char *path ,
1098- struct attr_check *check)
1140+ const struct object_id *tree_oid ,
1141+ const char *path, struct attr_check *check)
10991142{
11001143 int pathlen, rem, dirlen;
11011144 const char *cp, *last_slash = NULL;
@@ -1114,7 +1157,7 @@ static void collect_some_attrs(struct index_state *istate,
11141157 dirlen = 0;
11151158 }
11161159
1117- prepare_attr_stack(istate, path, dirlen, &check->stack);
1160+ prepare_attr_stack(istate, tree_oid, path, dirlen, &check->stack);
11181161 all_attrs_init(&g_attr_hashmap, check);
11191162 determine_macros(check->all_attrs, check->stack);
11201163
@@ -1123,12 +1166,12 @@ static void collect_some_attrs(struct index_state *istate,
11231166}
11241167
11251168void git_check_attr(struct index_state *istate,
1126- const char *path,
1169+ const struct object_id *tree_oid, const char *path,
11271170 struct attr_check *check)
11281171{
11291172 int i;
11301173
1131- collect_some_attrs(istate, path, check);
1174+ collect_some_attrs(istate, tree_oid, path, check);
11321175
11331176 for (i = 0; i < check->nr; i++) {
11341177 unsigned int n = check->items[i].attr->attr_nr;
@@ -1139,13 +1182,13 @@ void git_check_attr(struct index_state *istate,
11391182 }
11401183}
11411184
1142- void git_all_attrs(struct index_state *istate,
1185+ void git_all_attrs(struct index_state *istate, const struct object_id *tree_oid,
11431186 const char *path, struct attr_check *check)
11441187{
11451188 int i;
11461189
11471190 attr_check_reset(check);
1148- collect_some_attrs(istate, path, check);
1191+ collect_some_attrs(istate, tree_oid, path, check);
11491192
11501193 for (i = 0; i < check->all_attrs_nr; i++) {
11511194 const char *name = check->all_attrs[i].attr->name;
0 commit comments