mirror of
https://github.com/git/git.git
synced 2024-05-05 18:46:10 +02:00
Merge branch 'sl/sparse-check-attr'
Teach "git check-attr" work better with sparse-index. * sl/sparse-check-attr: check-attr: integrate with sparse-index attr.c: read attributes in a sparse directory t1092: add tests for 'git check-attr'
This commit is contained in:
commit
354356feff
57
attr.c
57
attr.c
|
@ -807,35 +807,56 @@ 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;
|
||||
char *buf;
|
||||
unsigned long size;
|
||||
int sparse_dir_pos = -1;
|
||||
|
||||
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.
|
||||
* When handling sparse-checkouts, .gitattributes files
|
||||
* may reside within a sparse directory. We distinguish
|
||||
* whether a path exists directly in the index or not by
|
||||
* evaluating if 'pos' is negative.
|
||||
* If 'pos' is negative, the path is not directly present
|
||||
* in the index and is likely within a sparse directory.
|
||||
* For paths not in the index, The absolute value of 'pos'
|
||||
* minus 1 gives us the position where the path would be
|
||||
* inserted in lexicographic order within the index.
|
||||
* We then subtract another 1 from this value
|
||||
* (sparse_dir_pos = -pos - 2) to find the position of the
|
||||
* last index entry which is lexicographically smaller than
|
||||
* the path. This would be the sparse directory containing
|
||||
* the path. By identifying the sparse directory containing
|
||||
* the path, we can correctly read the attributes specified
|
||||
* in the .gitattributes file from the tree object of the
|
||||
* sparse directory.
|
||||
*/
|
||||
if (!path_in_cone_mode_sparse_checkout(path, istate))
|
||||
return NULL;
|
||||
if (!path_in_cone_mode_sparse_checkout(path, istate)) {
|
||||
int pos = index_name_pos_sparse(istate, path, strlen(path));
|
||||
|
||||
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;
|
||||
if (pos < 0)
|
||||
sparse_dir_pos = -pos - 2;
|
||||
}
|
||||
|
||||
return read_attr_from_buf(buf, path, flags);
|
||||
if (sparse_dir_pos >= 0 &&
|
||||
S_ISSPARSEDIR(istate->cache[sparse_dir_pos]->ce_mode) &&
|
||||
!strncmp(istate->cache[sparse_dir_pos]->name, path, ce_namelen(istate->cache[sparse_dir_pos]))) {
|
||||
const char *relative_path = path + ce_namelen(istate->cache[sparse_dir_pos]);
|
||||
stack = read_attr_from_blob(istate, &istate->cache[sparse_dir_pos]->oid, relative_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);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(struct index_state *istate,
|
||||
|
|
|
@ -122,6 +122,9 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
|||
argc = parse_options(argc, argv, prefix, check_attr_options,
|
||||
check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
|
||||
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
|
||||
if (repo_read_index(the_repository) < 0) {
|
||||
die("invalid cache");
|
||||
}
|
||||
|
|
|
@ -134,5 +134,6 @@ test_perf_on_all git diff-files -- $SPARSE_CONE/a
|
|||
test_perf_on_all git diff-tree HEAD
|
||||
test_perf_on_all git diff-tree HEAD -- $SPARSE_CONE/a
|
||||
test_perf_on_all "git worktree add ../temp && git worktree remove ../temp"
|
||||
test_perf_on_all git check-attr -a -- $SPARSE_CONE/a
|
||||
|
||||
test_done
|
||||
|
|
|
@ -2259,4 +2259,76 @@ test_expect_success 'worktree is not expanded' '
|
|||
ensure_not_expanded worktree remove .worktrees/hotfix
|
||||
'
|
||||
|
||||
test_expect_success 'check-attr with pathspec inside sparse definition' '
|
||||
init_repos &&
|
||||
|
||||
echo "a -crlf myAttr" >>.gitattributes &&
|
||||
run_on_all cp ../.gitattributes ./deep &&
|
||||
|
||||
test_all_match git check-attr -a -- deep/a &&
|
||||
|
||||
test_all_match git add deep/.gitattributes &&
|
||||
test_all_match git check-attr -a --cached -- deep/a
|
||||
'
|
||||
|
||||
test_expect_success 'check-attr with pathspec outside sparse definition' '
|
||||
init_repos &&
|
||||
|
||||
echo "a -crlf myAttr" >>.gitattributes &&
|
||||
run_on_sparse mkdir folder1 &&
|
||||
run_on_all cp ../.gitattributes ./folder1 &&
|
||||
run_on_all cp a folder1/a &&
|
||||
|
||||
test_all_match git check-attr -a -- folder1/a &&
|
||||
|
||||
git -C full-checkout add folder1/.gitattributes &&
|
||||
test_sparse_match git add --sparse folder1/.gitattributes &&
|
||||
test_all_match git commit -m "add .gitattributes" &&
|
||||
test_sparse_match git sparse-checkout reapply &&
|
||||
test_all_match git check-attr -a --cached -- folder1/a
|
||||
'
|
||||
|
||||
# NEEDSWORK: The 'diff --check' test is left as 'test_expect_failure' due
|
||||
# to an underlying issue in oneway_diff() within diff-lib.c.
|
||||
# 'do_oneway_diff()' is not called as expected for paths that could match
|
||||
# inside of a sparse directory. Specifically, the 'ce_path_match()' function
|
||||
# fails to recognize files inside a sparse directory (e.g., when 'folder1/'
|
||||
# is a sparse directory, 'folder1/a' cannot be recognized). The goal is to
|
||||
# proceed with 'do_oneway_diff()' if the pathspec could match inside of a
|
||||
# sparse directory.
|
||||
test_expect_failure 'diff --check with pathspec outside sparse definition' '
|
||||
init_repos &&
|
||||
|
||||
write_script edit-contents <<-\EOF &&
|
||||
echo "a " >"$1"
|
||||
EOF
|
||||
|
||||
test_all_match git config core.whitespace -trailing-space,-space-before-tab &&
|
||||
|
||||
echo "a whitespace=trailing-space,space-before-tab" >>.gitattributes &&
|
||||
run_on_all mkdir -p folder1 &&
|
||||
run_on_all cp ../.gitattributes ./folder1 &&
|
||||
test_all_match git add --sparse folder1/.gitattributes &&
|
||||
run_on_all ../edit-contents folder1/a &&
|
||||
test_all_match git add --sparse folder1/a &&
|
||||
|
||||
test_sparse_match git sparse-checkout reapply &&
|
||||
test_all_match test_must_fail git diff --check --cached -- folder1/a
|
||||
'
|
||||
|
||||
test_expect_success 'sparse-index is not expanded: check-attr' '
|
||||
init_repos &&
|
||||
|
||||
echo "a -crlf myAttr" >>.gitattributes &&
|
||||
mkdir ./sparse-index/folder1 &&
|
||||
cp ./sparse-index/a ./sparse-index/folder1/a &&
|
||||
cp .gitattributes ./sparse-index/deep &&
|
||||
cp .gitattributes ./sparse-index/folder1 &&
|
||||
|
||||
git -C sparse-index add deep/.gitattributes &&
|
||||
git -C sparse-index add --sparse folder1/.gitattributes &&
|
||||
ensure_not_expanded check-attr -a --cached -- deep/a &&
|
||||
ensure_not_expanded check-attr -a --cached -- folder1/a
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Loading…
Reference in New Issue