summaryrefslogtreecommitdiff
path: root/src/status.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-03-25 22:19:39 -0700
committerRussell Belfer <rb@github.com>2013-03-25 22:19:39 -0700
commit37ee70fab4e6dcf35afc08c0edbe9f101d4abf2d (patch)
treee9bee47b3059bbc5189e0833b927a3bf50776bdf /src/status.c
parent0c289dd7c6831f4f402f9581b46d0c920053abf9 (diff)
downloadlibgit2-37ee70fab4e6dcf35afc08c0edbe9f101d4abf2d.tar.gz
Implement GIT_STATUS_OPT_EXCLUDE_SUBMODULES
This option has been sitting unimplemented for a while, so I finally went through and implemented it along with some tests. As part of this, I improved the implementation of GIT_DIFF_IGNORE_SUBMODULES so it be more diligent about avoiding extra work and about leaving off delta records for submodules to the greatest extent possible (though it may include them still if you are request TYPECHANGE records).
Diffstat (limited to 'src/status.c')
-rw-r--r--src/status.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/src/status.c b/src/status.c
index 7f84235f4..ac6b4379b 100644
--- a/src/status.c
+++ b/src/status.c
@@ -80,22 +80,37 @@ static unsigned int workdir_delta2status(git_delta_t workdir_status)
typedef struct {
git_status_cb cb;
void *payload;
+ const git_status_options *opts;
} status_user_callback;
static int status_invoke_cb(
- git_diff_delta *i2h, git_diff_delta *w2i, void *payload)
+ git_diff_delta *h2i, git_diff_delta *i2w, void *payload)
{
status_user_callback *usercb = payload;
const char *path = NULL;
unsigned int status = 0;
- if (w2i) {
- path = w2i->old_file.path;
- status |= workdir_delta2status(w2i->status);
+ if (i2w) {
+ path = i2w->old_file.path;
+ status |= workdir_delta2status(i2w->status);
}
- if (i2h) {
- path = i2h->old_file.path;
- status |= index_delta2status(i2h->status);
+ if (h2i) {
+ path = h2i->old_file.path;
+ status |= index_delta2status(h2i->status);
+ }
+
+ /* if excluding submodules and this is a submodule everywhere */
+ if (usercb->opts &&
+ (usercb->opts->flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0)
+ {
+ bool in_tree = (h2i && h2i->status != GIT_DELTA_ADDED);
+ bool in_index = (h2i && h2i->status != GIT_DELTA_DELETED);
+ bool in_wd = (i2w && i2w->status != GIT_DELTA_DELETED);
+
+ if ((!in_tree || h2i->old_file.mode == GIT_FILEMODE_COMMIT) &&
+ (!in_index || h2i->new_file.mode == GIT_FILEMODE_COMMIT) &&
+ (!in_wd || i2w->new_file.mode == GIT_FILEMODE_COMMIT))
+ return 0;
}
return usercb->cb(path, status, usercb->payload);
@@ -109,7 +124,7 @@ int git_status_foreach_ext(
{
int err = 0;
git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT;
- git_diff_list *idx2head = NULL, *wd2idx = NULL;
+ git_diff_list *head2idx = NULL, *idx2wd = NULL;
git_tree *head = NULL;
git_status_show_t show =
opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
@@ -144,33 +159,40 @@ int git_status_foreach_ext(
diffopt.flags = diffopt.flags | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
if ((opts->flags & GIT_STATUS_OPT_RECURSE_IGNORED_DIRS) != 0)
diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_IGNORED_DIRS;
+ if ((opts->flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0)
+ diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES;
- if (show != GIT_STATUS_SHOW_WORKDIR_ONLY &&
- (err = git_diff_tree_to_index(&idx2head, repo, head, NULL, &diffopt)) < 0)
- goto cleanup;
+ if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) {
+ err = git_diff_tree_to_index(&head2idx, repo, head, NULL, &diffopt);
+ if (err < 0)
+ goto cleanup;
+ }
- if (show != GIT_STATUS_SHOW_INDEX_ONLY &&
- (err = git_diff_index_to_workdir(&wd2idx, repo, NULL, &diffopt)) < 0)
- goto cleanup;
+ if (show != GIT_STATUS_SHOW_INDEX_ONLY) {
+ err = git_diff_index_to_workdir(&idx2wd, repo, NULL, &diffopt);
+ if (err < 0)
+ goto cleanup;
+ }
usercb.cb = cb;
usercb.payload = payload;
+ usercb.opts = opts;
if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) {
if ((err = git_diff__paired_foreach(
- idx2head, NULL, status_invoke_cb, &usercb)) < 0)
+ head2idx, NULL, status_invoke_cb, &usercb)) < 0)
goto cleanup;
- git_diff_list_free(idx2head);
- idx2head = NULL;
+ git_diff_list_free(head2idx);
+ head2idx = NULL;
}
- err = git_diff__paired_foreach(idx2head, wd2idx, status_invoke_cb, &usercb);
+ err = git_diff__paired_foreach(head2idx, idx2wd, status_invoke_cb, &usercb);
cleanup:
git_tree_free(head);
- git_diff_list_free(idx2head);
- git_diff_list_free(wd2idx);
+ git_diff_list_free(head2idx);
+ git_diff_list_free(idx2wd);
if (err == GIT_EUSER)
giterr_clear();