diff options
author | Russell Belfer <rb@github.com> | 2014-03-31 12:27:05 -0700 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2014-03-31 12:41:29 -0700 |
commit | c856f8c503a59ab6c8cc974d467aa2fcf509fd9b (patch) | |
tree | 5e2a119efe468a859880774f6f4391208debc8c1 | |
parent | 945c92a5cf1f73d56d0d2f06776f3181ed5b5548 (diff) | |
download | libgit2-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.c | 41 |
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; } |