change against v2: * add SP at appropriate places * add in-code comment around magic "adjustment" Shuqi Liang (3): attr.c: read attributes in a sparse directory t1092: add tests for `git check-attr` check-attr: integrate with sparse-index attr.c | 47 ++++++++++++-------- builtin/check-attr.c | 3 ++ t/perf/p2000-sparse-operations.sh | 1 + t/t1092-sparse-checkout-compatibility.sh | 55 ++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 19 deletions(-) Range-diff against v2: 1: 0ff2ab9430 ! 1: 199cc90a5b Enable gitattributes read from sparse directories @@ Metadata Author: Shuqi Liang <cheskaqiqi@xxxxxxxxx> ## Commit message ## - Enable gitattributes read from sparse directories + attr.c: read attributes in a sparse directory 'git check-attr' cannot currently find attributes of a file within a sparse directory. This is due to .gitattributes files are irrelevant in @@ attr.c: static struct attr_stack *read_attr_from_blob(struct index_state *istate 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 @@ attr.c: static struct attr_stack *read_attr_from_blob(struct index_state *istate - * 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 the pos value is negative, it means the path is not in the index. ++ * However, the absolute value of pos minus 1 gives us the position where the path ++ * would be inserted in lexicographic order. By subtracting another 1 from this ++ * value (pos = -pos - 2), we find the position of the last index entry ++ * which is lexicographically smaller than the provided path. This would be ++ * the sparse directory containing the path. + */ - if (!path_in_cone_mode_sparse_checkout(path, istate)) - return NULL; + pos = index_name_pos_sparse(istate, path, strlen(path)); -+ pos = -pos-2; -+ if (!path_in_cone_mode_sparse_checkout(path, istate) && pos>=0) { -+ if (!S_ISSPARSEDIR(istate->cache[pos]->ce_mode)) -+ return NULL; ++ pos = - pos - 2; - buf = read_blob_data_from_index(istate, path, &size); - if (!buf) @@ attr.c: static struct attr_stack *read_attr_from_blob(struct index_state *istate - if (size >= ATTR_MAX_FILE_SIZE) { - warning(_("ignoring overly large gitattributes blob '%s'"), path); - return NULL; +- } ++ if (!path_in_cone_mode_sparse_checkout(path, istate) && 0 <= pos) { ++ if (!S_ISSPARSEDIR(istate->cache[pos]->ce_mode)) ++ return NULL; + +- return read_attr_from_buf(buf, path, flags); + if (strncmp(istate->cache[pos]->name, path, ce_namelen(istate->cache[pos])) == 0) { + const char *relative_path = path + ce_namelen(istate->cache[pos]); + stack = read_attr_from_blob(istate, &istate->cache[pos]->oid, relative_path, flags); @@ attr.c: static struct attr_stack *read_attr_from_blob(struct index_state *istate + return NULL; + } + stack = read_attr_from_buf(buf, path, flags); - } -- -- return read_attr_from_buf(buf, path, flags); ++ } + return stack; } 2: 835e1176b0 = 2: eefce85083 t1092: add tests for `git check-attr` 3: 672d692e51 = 3: 65c2624504 check-attr: integrate with sparse-index -- 2.39.0