summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <vicent@github.com>2014-04-09 12:09:30 +0200
committerVicent Marti <vicent@github.com>2014-04-09 12:09:30 +0200
commit361e919280b848991108794ce6bb329d93eef676 (patch)
tree0bdca8f0e030b3d4ffe1c40ea87184107302504f
parent3ed8d00cc87f671ab060b985e7597efbb5de8c91 (diff)
parenteb7e17cc900f1f59f653cd7b277750fb1d5b721a (diff)
downloadlibgit2-361e919280b848991108794ce6bb329d93eef676.tar.gz
Merge pull request #2257 from libgit2/rb/fix-submodules-with-tracked-content
Update treatment of submodule-like directories with tracked content in the parent
-rw-r--r--src/diff.c12
-rw-r--r--tests/status/submodules.c93
2 files changed, 101 insertions, 4 deletions
diff --git a/src/diff.c b/src/diff.c
index 484273f4a..e62f45c22 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -876,7 +876,7 @@ static int handle_unmatched_new_item(
DIFF_FLAG_IS_SET(diff, GIT_DIFF_RECURSE_IGNORED_DIRS));
/* do not advance into directories that contain a .git file */
- if (recurse_into_dir) {
+ if (recurse_into_dir && !contains_oitem) {
git_buf *full = NULL;
if (git_iterator_current_workdir_path(&full, info->new_iter) < 0)
return -1;
@@ -969,6 +969,16 @@ static int handle_unmatched_new_item(
if (git_submodule_lookup(NULL, info->repo, nitem->path) != 0) {
giterr_clear();
delta_type = GIT_DELTA_IGNORED;
+
+ /* if this contains a tracked item, treat as normal TREE */
+ if (contains_oitem) {
+ error = git_iterator_advance_into(&info->nitem, info->new_iter);
+ if (error != GIT_ENOTFOUND)
+ return error;
+
+ giterr_clear();
+ return git_iterator_advance(&info->nitem, info->new_iter);
+ }
}
}
diff --git a/tests/status/submodules.c b/tests/status/submodules.c
index 6d0d63a5f..63cf73f36 100644
--- a/tests/status/submodules.c
+++ b/tests/status/submodules.c
@@ -1,7 +1,5 @@
#include "clar_libgit2.h"
-#include "buffer.h"
-#include "path.h"
-#include "posix.h"
+#include "fileops.h"
#include "status_helpers.h"
#include "../submodule/submodule_helpers.h"
@@ -389,3 +387,92 @@ void test_status_submodules__contained_untracked_repo(void)
g_repo, &opts, cb_status__match, &counts));
cl_assert_equal_i(5, counts.entry_count);
}
+
+void test_status_submodules__broken_stuff_that_git_allows(void)
+{
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+ status_entry_counts counts;
+ git_repository *contained;
+ static const char *expected_files_with_broken[] = {
+ ".gitmodules",
+ "added",
+ "broken/tracked",
+ "deleted",
+ "ignored",
+ "modified",
+ "untracked"
+ };
+ static unsigned int expected_status_with_broken[] = {
+ GIT_STATUS_WT_MODIFIED,
+ GIT_STATUS_INDEX_NEW,
+ GIT_STATUS_INDEX_NEW,
+ GIT_STATUS_INDEX_DELETED,
+ GIT_STATUS_IGNORED,
+ GIT_STATUS_WT_MODIFIED,
+ GIT_STATUS_WT_NEW,
+ };
+
+ g_repo = setup_fixture_submodules();
+
+ opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
+ GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS |
+ GIT_STATUS_OPT_INCLUDE_IGNORED;
+
+ /* make a directory and stick a tracked item into the index */
+ {
+ git_index *idx;
+ cl_must_pass(p_mkdir("submodules/broken", 0777));
+ cl_git_mkfile("submodules/broken/tracked", "tracked content");
+ cl_git_pass(git_repository_index(&idx, g_repo));
+ cl_git_pass(git_index_add_bypath(idx, "broken/tracked"));
+ cl_git_pass(git_index_write(idx));
+ git_index_free(idx);
+ }
+
+ status_counts_init(
+ counts, expected_files_with_broken, expected_status_with_broken);
+ cl_git_pass(git_status_foreach_ext(
+ g_repo, &opts, cb_status__match, &counts));
+ cl_assert_equal_i(7, counts.entry_count);
+
+ /* directory with tracked items that looks a little bit like a repo */
+
+ cl_must_pass(p_mkdir("submodules/broken/.git", 0777));
+ cl_must_pass(p_mkdir("submodules/broken/.git/info", 0777));
+ cl_git_mkfile("submodules/broken/.git/info/exclude", "# bogus");
+
+ status_counts_init(
+ counts, expected_files_with_broken, expected_status_with_broken);
+ cl_git_pass(git_status_foreach_ext(
+ g_repo, &opts, cb_status__match, &counts));
+ cl_assert_equal_i(7, counts.entry_count);
+
+ /* directory with tracked items that is a repo */
+
+ cl_git_pass(git_futils_rmdir_r(
+ "submodules/broken/.git", NULL, GIT_RMDIR_REMOVE_FILES));
+ cl_git_pass(git_repository_init(&contained, "submodules/broken", false));
+ git_repository_free(contained);
+
+ status_counts_init(
+ counts, expected_files_with_broken, expected_status_with_broken);
+ cl_git_pass(git_status_foreach_ext(
+ g_repo, &opts, cb_status__match, &counts));
+ cl_assert_equal_i(7, counts.entry_count);
+
+ /* directory with tracked items that claims to be a submodule but is not */
+
+ cl_git_pass(git_futils_rmdir_r(
+ "submodules/broken/.git", NULL, GIT_RMDIR_REMOVE_FILES));
+ cl_git_append2file("submodules/.gitmodules",
+ "\n[submodule \"broken\"]\n"
+ "\tpath = broken\n"
+ "\turl = https://github.com/not/used\n\n");
+
+ status_counts_init(
+ counts, expected_files_with_broken, expected_status_with_broken);
+ cl_git_pass(git_status_foreach_ext(
+ g_repo, &opts, cb_status__match, &counts));
+ cl_assert_equal_i(7, counts.entry_count);
+}
+