summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2014-03-31 12:27:05 -0700
committerRussell Belfer <rb@github.com>2014-03-31 12:41:29 -0700
commitc856f8c503a59ab6c8cc974d467aa2fcf509fd9b (patch)
tree5e2a119efe468a859880774f6f4391208debc8c1
parent945c92a5cf1f73d56d0d2f06776f3181ed5b5548 (diff)
downloadlibgit2-c856f8c503a59ab6c8cc974d467aa2fcf509fd9b.tar.gz
Fix submodule sorting in workdir iterator
With the changes to how git_path_dirload_with_stat handles things that look like submodules, submodules could end up sorted in the wrong order with the workdir iterator. This moves the submodule check earlier in the iterator processing of a new directory so that the submodule name updates will happen immediately and the sort order will be correct.
-rw-r--r--src/iterator.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/src/iterator.c b/src/iterator.c
index e9ec65250..1276903a7 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -1275,14 +1275,38 @@ GIT_INLINE(bool) workdir_path_is_dotgit(const git_buf *path)
static int workdir_iterator__enter_dir(fs_iterator *fi)
{
+ fs_iterator_frame *ff = fi->stack;
+ size_t pos;
+ git_path_with_stat *entry;
+ bool found_submodules = false;
+
/* only push new ignores if this is not top level directory */
- if (fi->stack->next != NULL) {
+ if (ff->next != NULL) {
workdir_iterator *wi = (workdir_iterator *)fi;
ssize_t slash_pos = git_buf_rfind_next(&fi->path, '/');
(void)git_ignore__push_dir(&wi->ignores, &fi->path.ptr[slash_pos + 1]);
}
+ /* convert submodules to GITLINK and remove trailing slashes */
+ git_vector_foreach(&ff->entries, pos, entry) {
+ if (S_ISDIR(entry->st.st_mode) &&
+ git_submodule__is_submodule(fi->base.repo, entry->path))
+ {
+ entry->st.st_mode = GIT_FILEMODE_COMMIT;
+ entry->path_len--;
+ entry->path[entry->path_len] = '\0';
+ found_submodules = true;
+ }
+ }
+
+ /* if we renamed submodules, re-sort and re-seek to start */
+ if (found_submodules) {
+ git_vector_set_sorted(&ff->entries, 0);
+ git_vector_sort(&ff->entries);
+ fs_iterator__seek_frame_start(fi, ff);
+ }
+
return 0;
}
@@ -1295,7 +1319,6 @@ static int workdir_iterator__leave_dir(fs_iterator *fi)
static int workdir_iterator__update_entry(fs_iterator *fi)
{
- int error = 0;
workdir_iterator *wi = (workdir_iterator *)fi;
/* skip over .git entries */
@@ -1305,20 +1328,6 @@ static int workdir_iterator__update_entry(fs_iterator *fi)
/* reset is_ignored since we haven't checked yet */
wi->is_ignored = -1;
- /* check if apparent tree entries are actually submodules */
- if (fi->entry.mode != GIT_FILEMODE_TREE)
- return 0;
-
- error = git_submodule_lookup(NULL, fi->base.repo, fi->entry.path);
- if (error < 0)
- giterr_clear();
-
- /* mark submodule as GITLINK and remove slash */
- if (!error) {
- fi->entry.mode = S_IFGITLINK;
- fi->entry.path[strlen(fi->entry.path) - 1] = '\0';
- }
-
return 0;
}