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

[PATCH v4 4/8] status: per-file data collection for --porcelain=v2

From
JHJeff Hostetler <git@jeffhostetler.com>
Date
Aug 2, 2016, 14:12 UTC
Message-ID
<1470147137-17498-5-git-send-email-git@jeffhostetler.com>
In-Reply-To
<1470147137-17498-1-git-send-email-git@jeffhostetler.com>
From: Jeff Hostetler <jeffhost@microsoft.com>

The output of `git status --porcelain` leaves out many details about the current status that clients might like to have. This can force them to be less efficient as they may need to launch secondary commands (and try to match the logic within git) to accumulate this extra information. For example, a GUI IDE might want the file mode to display the correct icon for a changed item (without having to stat it afterwards).

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <git@jeffhostetler.com>
---
 builtin/commit.c |  3 +++
 wt-status.c      | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 wt-status.h      |  4 ++++
 3 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/builtin/commit.c b/builtin/commit.c
index c3ae2c3..93ce28c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -153,6 +153,8 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
 		*value = STATUS_FORMAT_PORCELAIN;
 	else if (!strcmp(arg, "v1") || !strcmp(arg,"1"))
 		*value = STATUS_FORMAT_PORCELAIN;
+	else if (!strcmp(arg, "v2") || !strcmp(arg, "2"))
+		*value = STATUS_FORMAT_PORCELAIN_V2;
 	else
 		die("unsupported porcelain version '%s'", arg);
 
@@ -1104,6 +1106,7 @@ static struct status_deferred_config {
 static void finalize_deferred_config(struct wt_status *s)
 {
 	int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
+				   status_format != STATUS_FORMAT_PORCELAIN_V2 &&
 				   !s->null_termination);
 
 	if (s->null_termination) {
diff --git a/wt-status.c b/wt-status.c
index a9031e4..15d3349 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -434,6 +434,31 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
 		if (S_ISGITLINK(p->two->mode))
 			d->new_submodule_commits = !!oidcmp(&p->one->oid,
 							    &p->two->oid);
+
+		switch (p->status) {
+		case DIFF_STATUS_ADDED:
+			die("BUG: worktree status add???");
+			break;
+
+		case DIFF_STATUS_DELETED:
+			d->mode_index = p->one->mode;
+			oidcpy(&d->oid_index, &p->one->oid);
+			/* mode_worktree is zero for a delete. */
+			break;
+
+		case DIFF_STATUS_MODIFIED:
+		case DIFF_STATUS_TYPE_CHANGED:
+		case DIFF_STATUS_UNMERGED:
+			d->mode_index = p->one->mode;
+			d->mode_worktree = p->two->mode;
+			oidcpy(&d->oid_index, &p->one->oid);
+			break;
+
+		case DIFF_STATUS_UNKNOWN:
+			die("BUG: worktree status unknown???");
+			break;
+		}
+
 	}
 }
 
@@ -479,12 +504,36 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
 		if (!d->index_status)
 			d->index_status = p->status;
 		switch (p->status) {
+		case DIFF_STATUS_ADDED:
+			/* Leave {mode,oid}_head zero for an add. */
+			d->mode_index = p->two->mode;
+			oidcpy(&d->oid_index, &p->two->oid);
+			break;
+		case DIFF_STATUS_DELETED:
+			d->mode_head = p->one->mode;
+			oidcpy(&d->oid_head, &p->one->oid);
+			/* Leave {mode,oid}_index zero for a delete. */
+			break;
+			
 		case DIFF_STATUS_COPIED:
 		case DIFF_STATUS_RENAMED:
 			d->head_path = xstrdup(p->one->path);
+			d->score = p->score * 100 / MAX_SCORE;
+			/* fallthru */
+		case DIFF_STATUS_MODIFIED:
+		case DIFF_STATUS_TYPE_CHANGED:
+			d->mode_head = p->one->mode;
+			d->mode_index = p->two->mode;
+			oidcpy(&d->oid_head, &p->one->oid);
+			oidcpy(&d->oid_index, &p->two->oid);
 			break;
 		case DIFF_STATUS_UNMERGED:
 			d->stagemask = unmerged_mask(p->two->path);
+			/*
+			 * Don't bother setting {mode,oid}_{head,index} since the print
+			 * code will output the stage values directly and not use the
+			 * values in these fields.
+			 */
 			break;
 		}
 	}
@@ -565,9 +614,18 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
 		if (ce_stage(ce)) {
 			d->index_status = DIFF_STATUS_UNMERGED;
 			d->stagemask |= (1 << (ce_stage(ce) - 1));
+			/*
+			 * Don't bother setting {mode,oid}_{head,index} since the print
+			 * code will output the stage values directly and not use the
+			 * values in these fields.
+			 */
 		}
-		else
+		else {
 			d->index_status = DIFF_STATUS_ADDED;
+			/* Leave {mode,oid}_head zero for adds. */
+			d->mode_index = ce->ce_mode;
+			hashcpy(d->oid_index.hash, ce->sha1);
+		}
 	}
 }
 
@@ -1764,6 +1822,9 @@ void wt_status_print(struct wt_status *s)
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(s);
 		break;
+	case STATUS_FORMAT_PORCELAIN_V2:
+		/* TODO */
+		break;
 	case STATUS_FORMAT_UNSPECIFIED:
 		die("BUG: finalize_deferred_config() should have been called");
 		break;
diff --git a/wt-status.h b/wt-status.h
index a859a12..89a6d43 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -38,6 +38,9 @@ struct wt_status_change_data {
 	int worktree_status;
 	int index_status;
 	int stagemask;
+	int score;
+	int mode_head, mode_index, mode_worktree;
+	struct object_id oid_head, oid_index;
 	char *head_path;
 	unsigned dirty_submodule       : 2;
 	unsigned new_submodule_commits : 1;
@@ -48,6 +51,7 @@ struct wt_status_change_data {
 	STATUS_FORMAT_LONG,
 	STATUS_FORMAT_SHORT,
 	STATUS_FORMAT_PORCELAIN,
+	STATUS_FORMAT_PORCELAIN_V2,
 
 	STATUS_FORMAT_UNSPECIFIED
  };
-- 
2.8.0.rc4.17.gac42084.dirty
Previous: Jeff HostetlerNext: Johannes Schindelin
Message 27 of 31 in “status: V2 porcelain status”
  1. 0/8 status: V2 porcelain statusJeff Hostetler, Aug 2, 2016
  2. 2/8 status: cleanup API to wt_status_printJeff Hostetler, Aug 2, 2016
  3. Junio C HamanoAug 3, 2016
  4. Jeff HostetlerAug 4, 2016
  5. 3/8 status: support --porcelain[=<version>]Jeff Hostetler, Aug 2, 2016
  6. Junio C HamanoAug 3, 2016
  7. 8/8 status: tests for --porcelain=v2Jeff Hostetler, Aug 2, 2016
  8. Junio C HamanoAug 5, 2016
  9. Jeff HostetlerAug 5, 2016
  10. 6/8 status: print branch info with --porcelain=v2 --branchJeff Hostetler, Aug 2, 2016
  11. Junio C HamanoAug 5, 2016
  12. Jeff HostetlerAug 5, 2016
  13. 5/8 status: print per-file porcelain v2 status dataJeff Hostetler, Aug 2, 2016
  14. Jeff KingAug 5, 2016
  15. Junio C HamanoAug 5, 2016
  16. Jeff KingAug 5, 2016
  17. Junio C HamanoAug 5, 2016
  18. Stefan BellerAug 5, 2016
  19. Stefan BellerAug 5, 2016
  20. Jeff HostetlerAug 5, 2016
  21. 7/8 git-status.txt: describe --porcelain=v2 formatJeff Hostetler, Aug 2, 2016
  22. Junio C HamanoAug 5, 2016
  23. Jeff HostetlerAug 5, 2016
  24. 1/8 status: rename long-format print routinesJeff Hostetler, Aug 2, 2016
  25. Junio C HamanoAug 3, 2016
  26. Jeff HostetlerAug 4, 2016
  27. 4/8 status: per-file data collection for --porcelain=v2Jeff Hostetler, Aug 2, 2016
  28. Johannes SchindelinAug 3, 2016
  29. Junio C HamanoAug 3, 2016
  30. Johannes SchindelinAug 3, 2016
  31. Junio C HamanoAug 3, 2016

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.