git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 1/8] built-in add -i: allow filtering the modified files list

From
Junio C Hamano <gitster@pobox.com>
Date
Nov 21, 2019, 08:06 UTC
Message-ID
<xmqqeey18xha.fsf@gitster-ct.c.googlers.com>
In-Reply-To
<1844c4d55e21c40cbdbfdd73c82b4a1a074ff184.1573821382.git.gitgitgadget@gmail.com>

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

Show 15 quoted lines
> +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 };
Will have a comment on this later.
Show 18 quoted lines
> +	int i;
>  
>  	if (discard_index(r->index) < 0 ||
>  	    repo_read_index_preload(r, ps, 0) < 0)
> @@ -411,10 +424,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.phase = i ? FROM_WORKTREE : FROM_INDEX;
> +		else
> +			s.phase = i ? FROM_INDEX : FROM_WORKTREE;
> +		s.skip_unseen = filter && i;
;-)

Looks somewhat crazy but it works---when the caller wants to do 'index-only' for example we are not interested in paths that did not appear in the INDEX side of the diff, so we run FROM_INDEX diff first and then the let next one (i.e. FROM_WORKTREE diff) be skipped for paths that are not in the result of the first one. To me personally, I would find the tertially expession written like this

	s.phase = (i == 0) ? FROM_INDEX : FROM_WORKTREE;

much easier to follow, as it matches the order which ones are done first.

Also I notice two things.
 - It used to make 100% sense to call this field .phase because we
   always processed the first phase and then on to the second phase,
   where the first one was called WORKTREE and the second one was
   called INDEX.  In the new world order after this step, the name
   .phase no longer makes any sense.  Sometimes we run diff-files in
   phase 0 and diff-index in phase 1, but some other times we run
   diff-index in phase 0 and diff-files in phase 0.  The variable
   that has the closest meaning to the 'phase' is the newly
   introduced 'i'.
 - The initialization of the local "struct collection_status s" at
   the beginning of the function still uses .phase = FROM_WORKTREE
   which might be somewhat misleading.  We cannot remove the whole
   initialization, as the original used to nul initialize the other
   fields in this structure and I suspect the code still relies on
   it, but the initialization of .phase in particular no longer has
   any effect; it always is assigned inside the loop before the
   field gets used.
>  		opt.def = is_initial ?
>  			empty_tree_oid_hex() : oid_to_hex(&head_oid);

By the way, this is not a new issue introduced by this patch, but I notice copy_pathspec() is used twice on the same rev.prune_data in this functino. Who is responsible for releasing the resource held in this struct?

Previous: Johannes Schindelin via GitGitGadgetNext: Johannes Schindelin
Message 3 of 29 in “build-in add -i: implement all commands in the main loop”
  1. 0/8 build-in add -i: implement all commands in the main loopJohannes Schindelin via GitGitGadget, Nov 15, 2019
  2. 1/8 built-in add -i: allow filtering the modified files listJohannes Schindelin via GitGitGadget, Nov 15, 2019
  3. Junio C HamanoNov 21, 2019
  4. Johannes SchindelinNov 25, 2019
  5. 3/8 built-in add -i: implement the `update` commandJohannes Schindelin via GitGitGadget, Nov 15, 2019
  6. 5/8 built-in add -i: re-implement `add-untracked` in CJohannes Schindelin via GitGitGadget, Nov 15, 2019
  7. 4/8 built-in add -i: re-implement `revert` in CJohannes Schindelin via GitGitGadget, Nov 15, 2019
  8. 6/8 built-in add -i: implement the `patch` commandJohannes Schindelin via GitGitGadget, Nov 15, 2019
  9. 8/8 built-in add -i: offer the `quit` commandJohannes Schindelin via GitGitGadget, Nov 15, 2019
  10. 7/8 built-in add -i: re-implement the `diff` commandJohannes Schindelin via GitGitGadget, Nov 15, 2019
  11. 2/8 built-in add -i: prepare for multi-selection commandsJohannes Schindelin via GitGitGadget, Nov 15, 2019
  12. Junio C HamanoNov 21, 2019
  13. Johannes SchindelinNov 25, 2019
  14. Junio C HamanoNov 18, 2019
  15. Junio C HamanoNov 18, 2019
  16. Johannes SchindelinNov 18, 2019
  17. Junio C HamanoNov 18, 2019
  18. Johannes SchindelinNov 18, 2019
  19. Junio C HamanoNov 19, 2019
  20. 0/9 built-in add -i: implement all commands in the main loopJohannes Schindelin via GitGitGadget, Nov 29, 2019
  21. 1/9 add-interactive: make sure to release `rev.prune_data`Johannes Schindelin via GitGitGadget, Nov 29, 2019
  22. 2/9 built-in add -i: allow filtering the modified files listJohannes Schindelin via GitGitGadget, Nov 29, 2019
  23. 3/9 built-in add -i: prepare for multi-selection commandsJohannes Schindelin via GitGitGadget, Nov 29, 2019
  24. 4/9 built-in add -i: implement the `update` commandJohannes Schindelin via GitGitGadget, Nov 29, 2019
  25. 5/9 built-in add -i: re-implement `revert` in CJohannes Schindelin via GitGitGadget, Nov 29, 2019
  26. 7/9 built-in add -i: implement the `patch` commandJohannes Schindelin via GitGitGadget, Nov 29, 2019
  27. 8/9 built-in add -i: re-implement the `diff` commandJohannes Schindelin via GitGitGadget, Nov 29, 2019
  28. 9/9 built-in add -i: offer the `quit` commandJohannes Schindelin via GitGitGadget, Nov 29, 2019
  29. 6/9 built-in add -i: re-implement `add-untracked` in CJohannes Schindelin via GitGitGadget, Nov 29, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.