Commit d3bc95fd by Russell Belfer

Update behavior for untracked sub-repos

When a directory containing a .git directory (or even just a plain
gitlink) was found, libgit2 was going out of its way to treat it
specially.  This seemed like it was necessary because the diff
code was not originally emulating Git's behavior for untracked
directories correctly (i.e. scanning for ignored vs untracked items
inside).  Now that libgit2 diff mimics Git's untracked directory
behavior, the special handling for contained Git repos is actually
incorrect and this commit rips it out.
parent f210cb5b
......@@ -1313,8 +1313,8 @@ static int workdir_iterator__update_entry(fs_iterator *fi)
if (error < 0)
giterr_clear();
/* mark submodule (or any dir with .git) as GITLINK and remove slash */
if (!error || error == GIT_EEXISTS) {
/* mark submodule as GITLINK and remove slash */
if (!error) {
fi->entry.mode = S_IFGITLINK;
fi->entry.path[strlen(fi->entry.path) - 1] = '\0';
}
......
......@@ -1051,15 +1051,8 @@ int git_path_dirload_with_stat(
}
if (S_ISDIR(ps->st.st_mode)) {
if ((error = git_buf_joinpath(&full, full.ptr, ".git")) < 0)
break;
if (p_access(full.ptr, F_OK) == 0) {
ps->st.st_mode = GIT_FILEMODE_COMMIT;
} else {
ps->path[ps->path_len++] = '/';
ps->path[ps->path_len] = '\0';
}
ps->path[ps->path_len++] = '/';
ps->path[ps->path_len] = '\0';
}
}
......
......@@ -737,13 +737,13 @@ void test_diff_iterator__workdir_builtin_ignores(void)
{ "root_test2", false },
{ "root_test3", false },
{ "root_test4.txt", false },
{ "sub", false },
{ "sub/", false },
{ "sub/.gitattributes", false },
{ "sub/abc", false },
{ "sub/dir/", true },
{ "sub/file", false },
{ "sub/ign/", true },
{ "sub/sub", false },
{ "sub/sub/", false },
{ "sub/sub/.gitattributes", false },
{ "sub/sub/dir", false }, /* file is not actually a dir */
{ "sub/sub/file", false },
......
#include "clar_libgit2.h"
#include "repository.h"
#include "posix.h"
#include "diff_helpers.h"
#include "../submodule/submodule_helpers.h"
static git_repository *g_repo = NULL;
......@@ -11,6 +12,7 @@ void test_diff_submodules__initialize(void)
void test_diff_submodules__cleanup(void)
{
cl_git_sandbox_cleanup();
}
#define get_buf_ptr(buf) ((buf)->asize ? (buf)->ptr : NULL)
......@@ -34,6 +36,10 @@ static void check_diff_patches_at_line(
if (expected[d] && !strcmp(expected[d], "<SKIP>"))
continue;
if (expected[d] && !strcmp(expected[d], "<UNTRACKED>")) {
cl_assert_at_line(delta->status == GIT_DELTA_UNTRACKED, file, line);
continue;
}
if (expected[d] && !strcmp(expected[d], "<END>")) {
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_at_line(!strcmp(expected[d], "<END>"), file, line);
......@@ -115,7 +121,9 @@ void test_diff_submodules__dirty_submodule_2(void)
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff = NULL, *diff2 = NULL;
char *smpath = "testrepo";
static const char *expected_none[] = { "<END>" };
static const char *expected_none[] = {
"<END>"
};
static const char *expected_dirty[] = {
"diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */
"<END>"
......@@ -170,6 +178,8 @@ void test_diff_submodules__submod2_index_to_wd(void)
git_diff *diff = NULL;
static const char *expected[] = {
"<SKIP>", /* .gitmodules */
"<UNTRACKED>", /* not-submodule */
"<UNTRACKED>", /* not */
"diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */
"diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */
"diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */
......@@ -349,6 +359,8 @@ void test_diff_submodules__diff_ignore_options(void)
git_config *cfg;
static const char *expected_normal[] = {
"<SKIP>", /* .gitmodules */
"<UNTRACKED>", /* not-submodule */
"<UNTRACKED>", /* not */
"diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */
"diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */
"diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */
......@@ -358,10 +370,14 @@ void test_diff_submodules__diff_ignore_options(void)
};
static const char *expected_ignore_all[] = {
"<SKIP>", /* .gitmodules */
"<UNTRACKED>", /* not-submodule */
"<UNTRACKED>", /* not */
"<END>"
};
static const char *expected_ignore_dirty[] = {
"<SKIP>", /* .gitmodules */
"<UNTRACKED>", /* not-submodule */
"<UNTRACKED>", /* not */
"diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */
"diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */
"<END>"
......@@ -423,3 +439,49 @@ void test_diff_submodules__diff_ignore_options(void)
git_config_free(cfg);
}
void test_diff_submodules__skips_empty_includes_used(void)
{
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff = NULL;
diff_expects exp;
git_repository *r2;
/* A side effect of of Git's handling of untracked directories and
* auto-ignoring of ".git" entries is that a newly initialized Git
* repo inside another repo will be skipped by diff, but one that
* actually has a commit it in will show as an untracked directory.
* Let's make sure that works.
*/
g_repo = cl_git_sandbox_init("empty_standard_repo");
opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
git_diff_free(diff);
cl_git_pass(git_repository_init(&r2, "empty_standard_repo/subrepo", 0));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
git_diff_free(diff);
cl_git_mkfile("empty_standard_repo/subrepo/README.txt", "hello\n");
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
git_diff_free(diff);
}
......@@ -881,7 +881,7 @@ void test_diff_workdir__submodules(void)
* only significant difference is that those Added items will show up
* as Untracked items in the pure libgit2 diff.
*
* Then add in the two extra ignored items "not" and "not-submodule"
* Then add in the two extra untracked items "not" and "not-submodule"
* to get the 12 files reported here.
*/
......@@ -890,8 +890,8 @@ void test_diff_workdir__submodules(void)
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_IGNORED]);
cl_assert_equal_i(8, exp.file_status[GIT_DELTA_UNTRACKED]);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
cl_assert_equal_i(10, exp.file_status[GIT_DELTA_UNTRACKED]);
/* the following numbers match "git diff 873585" exactly */
......
......@@ -324,7 +324,7 @@ static int confirm_submodule_status(
{
submodule_expectations *exp = payload;
while (git__suffixcmp(exp->paths[exp->counter], "/") == 0)
while (exp->statuses[exp->counter] < 0)
exp->counter++;
cl_assert_equal_i(exp->statuses[exp->counter], (int)status_flags);
......@@ -345,8 +345,10 @@ void test_submodule_status__iterator(void)
"just_a_dir/",
"just_a_dir/contents",
"just_a_file",
"not",
"not-submodule",
"not-submodule/",
"not-submodule/README.txt",
"not/",
"not/README.txt",
"README.txt",
"sm_added_and_uncommited",
"sm_changed_file",
......@@ -359,11 +361,13 @@ void test_submodule_status__iterator(void)
};
static int expected_flags[] = {
GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, /* ".gitmodules" */
0, /* "just_a_dir/" will be skipped */
-1, /* "just_a_dir/" will be skipped */
GIT_STATUS_CURRENT, /* "just_a_dir/contents" */
GIT_STATUS_CURRENT, /* "just_a_file" */
GIT_STATUS_IGNORED, /* "not" (contains .git) */
GIT_STATUS_IGNORED, /* "not-submodule" (contains .git) */
GIT_STATUS_WT_NEW, /* "not-submodule/" untracked item */
-1, /* "not-submodule/README.txt" */
GIT_STATUS_WT_NEW, /* "not/" untracked item */
-1, /* "not/README.txt" */
GIT_STATUS_CURRENT, /* "README.txt */
GIT_STATUS_INDEX_NEW, /* "sm_added_and_uncommited" */
GIT_STATUS_WT_MODIFIED, /* "sm_changed_file" */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment