diff options
author | Vicent Marti <vicent@github.com> | 2014-04-25 02:04:12 -0700 |
---|---|---|
committer | Vicent Marti <vicent@github.com> | 2014-04-25 02:04:12 -0700 |
commit | 2ad51b81d2d735c50549f16c308d61c0a5ed990c (patch) | |
tree | 206483ccc5c59eafe9f7036faaf8ecf26ea40de7 /src/iterator.c | |
parent | af9eeac93929bdf10c30e60f34717959d83b6bd3 (diff) | |
parent | a409acefbbadeb607e4d6dde681bff5aed6ae9fc (diff) | |
download | libgit2-2ad51b81d2d735c50549f16c308d61c0a5ed990c.tar.gz |
Merge pull request #2241 from libgit2/rb/stash-skip-submodules
Improve stash and checkout for ignored + untracked items
Diffstat (limited to 'src/iterator.c')
-rw-r--r-- | src/iterator.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/iterator.c b/src/iterator.c index 63c14f962..ef27fa71f 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1528,3 +1528,77 @@ int git_iterator_current_workdir_path(git_buf **path, git_iterator *iter) return 0; } + +int git_iterator_advance_over_with_status( + const git_index_entry **entryptr, + git_iterator_status_t *status, + git_iterator *iter) +{ + int error = 0; + workdir_iterator *wi = (workdir_iterator *)iter; + char *base = NULL; + const git_index_entry *entry; + + *status = GIT_ITERATOR_STATUS_NORMAL; + + if (iter->type != GIT_ITERATOR_TYPE_WORKDIR) + return git_iterator_advance(entryptr, iter); + if ((error = git_iterator_current(&entry, iter)) < 0) + return error; + + if (!S_ISDIR(entry->mode)) { + if (git_ignore__lookup( + &wi->ignores, wi->fi.entry.path, &wi->is_ignored) < 0) + wi->is_ignored = true; + if (wi->is_ignored) + *status = GIT_ITERATOR_STATUS_IGNORED; + return git_iterator_advance(entryptr, iter); + } + + *status = GIT_ITERATOR_STATUS_EMPTY; + + base = git__strdup(entry->path); + GITERR_CHECK_ALLOC(base); + + /* scan inside directory looking for a non-ignored item */ + while (entry && !iter->prefixcomp(entry->path, base)) { + if (git_ignore__lookup( + &wi->ignores, wi->fi.entry.path, &wi->is_ignored) < 0) + wi->is_ignored = true; + + /* if we found an explicitly ignored item, then update from + * EMPTY to IGNORED + */ + if (wi->is_ignored) + *status = GIT_ITERATOR_STATUS_IGNORED; + else if (S_ISDIR(entry->mode)) { + error = git_iterator_advance_into(&entry, iter); + + if (!error) + continue; + else if (error == GIT_ENOTFOUND) { + error = 0; + wi->is_ignored = true; /* mark empty directories as ignored */ + } else + break; /* real error, stop here */ + } else { + /* we found a non-ignored item, treat parent as untracked */ + *status = GIT_ITERATOR_STATUS_NORMAL; + break; + } + + if ((error = git_iterator_advance(&entry, iter)) < 0) + break; + } + + /* wrap up scan back to base directory */ + while (entry && !iter->prefixcomp(entry->path, base)) + if ((error = git_iterator_advance(&entry, iter)) < 0) + break; + + *entryptr = entry; + git__free(base); + + return error; +} + |