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

Re: Fwd: git status options feature suggestion

From
Junio C Hamano <gitster@pobox.com>
Date
Oct 12, 2008, 08:10 UTC
Message-ID
<7v1vymgrom.fsf@gitster.siamese.dyndns.org>
In-Reply-To
<20081012064512.GA32597@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I remember a long time ago you started on a parallel diff walker that
> could diff the working tree, the index, and a tree at once. Do you
> remember the issues with it?
Sorry, I don't.
Show 7 quoted lines
> I think that would be the right tool here to show each file only once,
> but with multiple status flags. Something like:
>
>   A M foo
>
> to show that "foo" has been added since the last commit, but there are
> modifications in the working tree that have not yet been staged.

One thing to keep in mind is what to do when you would want to detect renames. The parallel walk would be Ok but between HEAD and index there could be renames involved, and at that point it would get quite tricky. Once the index is in-core, I think it hurts us much to walk HEAD vs index and index vs working tree in separate passes.

I think it is perfectly fine to run the diff-index first, and keep the result from it in a string_list, and then run "diff-files" and annotate the string_list with the output from it.

Something like...
	struct git_st_data {
        	const char *head_path;
                char head_to_index_status;
                char index_to_worktree_status;
	};
	static int cmp_head_path(const void *a_, const void *b_)
        {
		struct git_st_data *a = (struct git_st_data *)a_;
		struct git_st_data *b = (struct git_st_data *)b_;
		return strcmp(a->head_path, b->head_path);
        }
	static void git_st_inspect_index_cb(struct diff_queue_struct *q,
        			struct diff_options *opts, void *data)
	{
		struct string_list *git_st_list = data;
		int i;
		for (i = 0; i < q->nr; i++) {
                	struct git_st_data *d;
                        struct string_list_item *e;
			struct diff_filepair *fp = &q->queue[i];
			d = xcalloc(1, sizeof(*d));
                        d->head_path = xstrdup(fp->one->path);
                        e = string_list_insert(fp->two->path, git_st_list);
			e->util = d;
                        d->head_to_index_status = fp->status;
                }
	}
	static void git_st_inspect_file_cb(struct diff_queue_struct *q,
        			struct diff_options *opts, void *data)
	{
		struct string_list *git_st_list = data;
		int i;
		for (i = 0; i < q->nr; i++) {
                	struct git_st_data *d;
                        struct string_list_item *e;
			struct diff_filepair *fp = &q->queue[i];
			e = string_list_lookup(fp->one->path, git_st_list);
			if (!e)
                        	die("Oops -- shouldn't happen");
			d = e->util;
                        d->index_to_worktree_status = fp->status;
                }
	}
	void git_st_inspect(struct string_list *git_st_list)
        {
        	struct rev_info rev;
		git_st_list->items = NULL;
                git_st_list->nr = git_st_list->alloc = 0;
                git_st_list->strdup_strings = 1;
		/*
                 * run "diff-index -B -M HEAD" and keep the result in a
                 * string list, keyed by the path in the index.
                 */
                init_revisions(&rev, NULL);
                setup_revisions(0, NULL, &rev, "HEAD");
                rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
                rev.diffopt.format_callback = git_st_inspect_index_cb;
                rev.diffopt.format_callback_data = git_st_list;
                rev.diffopt.detect_rename = 1;
                rev.diffopt.rename_limit = 200;
                rev.diffopt.break_opt = 0;
                run_diff_index(&rev, 1);
		/*
                 * run "diff-files" and update the previous with the result.
		 */
		init_revisions(&rev, NULL);
                setup_revisions(0, NULL, &rev, NULL);
                rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
                rev.diffopt.format_callback = git_st_inspect_file_cb;                
                rev.diffopt.format_callback_data = git_st_list;
                run_diff_files(&rev, 0);
		/*
                 * sort the string-list entries in HEAD path order
                 */
		qsort(git_st_list->items, git_st_list->nr,
                      sizeof(struct string_list_item),
                      cmp_head_path);
	}

Then git_st_inspect() can also be called by wt_status_print(), making it unnecessary to do the equivalent of the above in wt_status_print_updated() and wt_status_print_changed().

Previous: Jeff KingNext: Jeff King
Message 12 of 29 in “git status options feature suggestion”
  1. Caleb CushingOct 9, 2008
  2. Jeff KingOct 9, 2008
  3. Fwd: git status options feature suggestionCaleb Cushing, Oct 9, 2008
  4. Johannes SchindelinOct 9, 2008
  5. Michael J GruberOct 9, 2008
  6. Caleb CushingOct 10, 2008
  7. Elijah NewrenOct 10, 2008
  8. Johannes SchindelinOct 10, 2008
  9. Jeff KingOct 12, 2008
  10. Junio C HamanoOct 12, 2008
  11. Jeff KingOct 12, 2008
  12. Junio C HamanoOct 12, 2008
  13. Jeff KingOct 13, 2008
  14. Shawn O. PearceOct 13, 2008
  15. Junio C HamanoOct 26, 2008
  16. Jeff KingOct 26, 2008
  17. Shawn O. PearceOct 12, 2008
  18. Jeff KingOct 13, 2008
  19. Jakub NarebskiOct 12, 2008
  20. Wincent ColaiutaOct 12, 2008
  21. Teemu LikonenOct 12, 2008
  22. Andreas EricssonOct 12, 2008
  23. Jeff KingOct 12, 2008
  24. Junio C HamanoOct 12, 2008
  25. Jeff KingOct 13, 2008
  26. ls-files [Was: Re: Fwd: git status options feature suggestion]James Cloos, Oct 9, 2008
  27. Shawn O. PearceOct 9, 2008
  28. Jeremy RamerOct 9, 2008
  29. James CloosOct 9, 2008

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.