From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Junio C Hamano <gitster@pobox.com>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH v2 2/9] built-in add -i: allow filtering the modified files list
Date: Fri, 29 Nov 2019 21:11:42 +0000 [thread overview]
Message-ID: <fab098d86eb47d8ef108e62080db87c1381b2e56.1575061909.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.171.v2.git.1575061909.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
In the `update` command of `git add -i`, we are primarily interested in the
list of modified files that have worktree (i.e. unstaged) changes.
At the same time, we need to determine _also_ the staged changes, to be
able to produce the full added/deleted information.
The Perl script version of `git add -i` has a parameter of the
`list_modified()` function for that matter. In C, we can be a lot more
precise, using an `enum`.
The C implementation of the filter also has an easier time to avoid
unnecessary work, simply by using an adaptive order of the `diff-index`
and `diff-files` phases, and then skipping files in the second phase
when they have not been seen in the first phase.
Seeing as we change the meaning of the `phase` field, we rename it to
`mode` to reflect that the order depends on the exact invocation of the
`git add -i` command.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
add-interactive.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/add-interactive.c b/add-interactive.c
index de2fccb0ef..c62d63e35b 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -344,10 +344,11 @@ static int pathname_entry_cmp(const void *unused_cmp_data,
}
struct collection_status {
- enum { FROM_WORKTREE = 0, FROM_INDEX = 1 } phase;
+ enum { FROM_WORKTREE = 0, FROM_INDEX = 1 } mode;
const char *reference;
+ unsigned skip_unseen:1;
struct string_list *files;
struct hashmap file_map;
};
@@ -375,6 +376,9 @@ static void collect_changes_cb(struct diff_queue_struct *q,
entry = hashmap_get_entry_from_hash(&s->file_map, hash, name,
struct pathname_entry, ent);
if (!entry) {
+ if (s->skip_unseen)
+ continue;
+
add_file_item(s->files, name);
entry = xcalloc(sizeof(*entry), 1);
@@ -385,7 +389,7 @@ static void collect_changes_cb(struct diff_queue_struct *q,
}
file_item = entry->item;
- adddel = s->phase == FROM_INDEX ?
+ adddel = s->mode == FROM_INDEX ?
&file_item->index : &file_item->worktree;
adddel->seen = 1;
adddel->add = stat.files[i]->added;
@@ -396,13 +400,22 @@ static void collect_changes_cb(struct diff_queue_struct *q,
free_diffstat_info(&stat);
}
-static int get_modified_files(struct repository *r, struct string_list *files,
+enum modified_files_filter {
+ NO_FILTER = 0,
+ WORKTREE_ONLY = 1,
+ INDEX_ONLY = 2,
+};
+
+static int get_modified_files(struct repository *r,
+ enum modified_files_filter filter,
+ struct string_list *files,
const struct pathspec *ps)
{
struct object_id head_oid;
int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
&head_oid, NULL);
- struct collection_status s = { FROM_WORKTREE };
+ struct collection_status s = { 0 };
+ int i;
if (discard_index(r->index) < 0 ||
repo_read_index_preload(r, ps, 0) < 0)
@@ -412,10 +425,16 @@ static int get_modified_files(struct repository *r, struct string_list *files,
s.files = files;
hashmap_init(&s.file_map, pathname_entry_cmp, NULL, 0);
- for (s.phase = FROM_WORKTREE; s.phase <= FROM_INDEX; s.phase++) {
+ for (i = 0; i < 2; i++) {
struct rev_info rev;
struct setup_revision_opt opt = { 0 };
+ if (filter == INDEX_ONLY)
+ s.mode = (i == 0) ? FROM_INDEX : FROM_WORKTREE;
+ else
+ s.mode = (i == 0) ? FROM_WORKTREE : FROM_INDEX;
+ s.skip_unseen = filter && i;
+
opt.def = is_initial ?
empty_tree_oid_hex() : oid_to_hex(&head_oid);
@@ -429,7 +448,7 @@ static int get_modified_files(struct repository *r, struct string_list *files,
if (ps)
copy_pathspec(&rev.prune_data, ps);
- if (s.phase == FROM_INDEX)
+ if (s.mode == FROM_INDEX)
run_diff_index(&rev, 1);
else {
rev.diffopt.flags.ignore_dirty_submodules = 1;
@@ -502,7 +521,7 @@ static void print_file_item(int i, struct string_list_item *item,
static int run_status(struct add_i_state *s, const struct pathspec *ps,
struct string_list *files, struct list_options *opts)
{
- if (get_modified_files(s->r, files, ps) < 0)
+ if (get_modified_files(s->r, NO_FILTER, files, ps) < 0)
return -1;
list(s, files, opts);
--
gitgitgadget
next prev parent reply other threads:[~2019-11-29 21:11 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-15 12:36 [PATCH 0/8] build-in add -i: implement all commands in the main loop Johannes Schindelin via GitGitGadget
2019-11-15 12:36 ` [PATCH 1/8] built-in add -i: allow filtering the modified files list Johannes Schindelin via GitGitGadget
2019-11-21 8:06 ` Junio C Hamano
2019-11-25 15:20 ` Johannes Schindelin
2019-11-15 12:36 ` [PATCH 2/8] built-in add -i: prepare for multi-selection commands Johannes Schindelin via GitGitGadget
2019-11-21 8:12 ` Junio C Hamano
2019-11-25 15:21 ` Johannes Schindelin
2019-11-15 12:36 ` [PATCH 3/8] built-in add -i: implement the `update` command Johannes Schindelin via GitGitGadget
2019-11-15 12:36 ` [PATCH 4/8] built-in add -i: re-implement `revert` in C Johannes Schindelin via GitGitGadget
2019-11-15 12:36 ` [PATCH 5/8] built-in add -i: re-implement `add-untracked` " Johannes Schindelin via GitGitGadget
2019-11-15 12:36 ` [PATCH 6/8] built-in add -i: implement the `patch` command Johannes Schindelin via GitGitGadget
2019-11-15 12:36 ` [PATCH 7/8] built-in add -i: re-implement the `diff` command Johannes Schindelin via GitGitGadget
2019-11-15 12:36 ` [PATCH 8/8] built-in add -i: offer the `quit` command Johannes Schindelin via GitGitGadget
2019-11-18 2:17 ` [PATCH 0/8] build-in add -i: implement all commands in the main loop Junio C Hamano
2019-11-18 2:22 ` Junio C Hamano
2019-11-18 19:22 ` Johannes Schindelin
2019-11-18 2:27 ` Junio C Hamano
2019-11-18 18:53 ` Johannes Schindelin
2019-11-19 1:29 ` Junio C Hamano
2019-11-29 21:11 ` [PATCH v2 0/9] built-in " Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 1/9] add-interactive: make sure to release `rev.prune_data` Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` Johannes Schindelin via GitGitGadget [this message]
2019-11-29 21:11 ` [PATCH v2 3/9] built-in add -i: prepare for multi-selection commands Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 4/9] built-in add -i: implement the `update` command Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 5/9] built-in add -i: re-implement `revert` in C Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 6/9] built-in add -i: re-implement `add-untracked` " Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 7/9] built-in add -i: implement the `patch` command Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 8/9] built-in add -i: re-implement the `diff` command Johannes Schindelin via GitGitGadget
2019-11-29 21:11 ` [PATCH v2 9/9] built-in add -i: offer the `quit` command Johannes Schindelin via GitGitGadget
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fab098d86eb47d8ef108e62080db87c1381b2e56.1575061909.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=johannes.schindelin@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).