Before this patch,`git check-attr` can't find the attributes of a file within a sparse directory. In order to read attributes from '.gitattributes' files that may be in a sparse directory: When path is in cone mode of sparse checkout: 1.If path is a sparse directory, read the tree OIDs from the sparse directory. 2.If path is a regular files, read the attributes directly from the blob data stored in the cache. Helped-by: Victoria Dye <vdye@xxxxxxxxxx> Signed-off-by: Shuqi Liang <cheskaqiqi@xxxxxxxxx> --- attr.c | 64 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/attr.c b/attr.c index 7d39ac4a29..b0d26da102 100644 --- a/attr.c +++ b/attr.c @@ -808,35 +808,57 @@ static struct attr_stack *read_attr_from_blob(struct index_state *istate, static struct attr_stack *read_attr_from_index(struct index_state *istate, const char *path, unsigned flags) { + struct attr_stack *stack = NULL; + int i; + struct strbuf path1 = STRBUF_INIT; + struct strbuf path2 = STRBUF_INIT; + char *first_slash = NULL; char *buf; unsigned long size; if (!istate) return NULL; - /* - * The .gitattributes file only applies to files within its - * parent directory. In the case of cone-mode sparse-checkout, - * the .gitattributes file is sparse if and only if all paths - * within that directory are also sparse. Thus, don't load the - * .gitattributes file since it will not matter. - * - * In the case of a sparse index, it is critical that we don't go - * looking for a .gitattributes file, as doing so would cause the - * index to expand. - */ - if (!path_in_cone_mode_sparse_checkout(path, istate)) - return NULL; - - buf = read_blob_data_from_index(istate, path, &size); - if (!buf) - return NULL; - if (size >= ATTR_MAX_FILE_SIZE) { - warning(_("ignoring overly large gitattributes blob '%s'"), path); - return NULL; + first_slash = strchr(path, '/'); + if (first_slash) { + strbuf_add(&path1, path, first_slash - path + 1); + strbuf_addstr(&path2, first_slash + 1); } - return read_attr_from_buf(buf, path, flags); + if(!path_in_cone_mode_sparse_checkout(path, istate)){ + for (i = 0; i < istate->cache_nr; i++) { + struct cache_entry *ce = istate->cache[i]; + if ( !strcmp(istate->cache[i]->name, path1.buf)&&S_ISSPARSEDIR(ce->ce_mode)) { + stack = read_attr_from_blob(istate, &ce->oid, path2.buf, flags); + }else if(S_ISREG(ce->ce_mode) && !strcmp(istate->cache[i]->name, path)){ + unsigned long sz; + enum object_type type; + void *data; + + data = repo_read_object_file(the_repository, &istate->cache[i]->oid, + &type, &sz); + if (!data || type != OBJ_BLOB) { + free(data); + strbuf_release(&path1); + strbuf_release(&path2); + return NULL; + } + stack = read_attr_from_buf(data, path, flags); + } + } + }else{ + buf = read_blob_data_from_index(istate, path, &size); + if (!buf) + return NULL; + if (size >= ATTR_MAX_FILE_SIZE) { + warning(_("ignoring overly large gitattributes blob '%s'"), path); + return NULL; + } + stack = read_attr_from_buf(buf, path, flags); + } + strbuf_release(&path1); + strbuf_release(&path2); + return stack; } static struct attr_stack *read_attr(struct index_state *istate, -- 2.39.0