Skip to content

Commit 41f9d92

Browse files
jeffhostetlerdscho
authored andcommitted
status: collect per-file data for --porcelain=v2
Collect extra per-file data for porcelain V2 format. 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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6872353 commit 41f9d92

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

builtin/commit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
153153
*value = STATUS_FORMAT_PORCELAIN;
154154
else if (!strcmp(arg, "v1") || !strcmp(arg, "1"))
155155
*value = STATUS_FORMAT_PORCELAIN;
156+
else if (!strcmp(arg, "v2") || !strcmp(arg, "2"))
157+
*value = STATUS_FORMAT_PORCELAIN_V2;
156158
else
157159
die("unsupported porcelain version '%s'", arg);
158160

@@ -1104,6 +1106,7 @@ static struct status_deferred_config {
11041106
static void finalize_deferred_config(struct wt_status *s)
11051107
{
11061108
int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
1109+
status_format != STATUS_FORMAT_PORCELAIN_V2 &&
11071110
!s->null_termination);
11081111

11091112
if (s->null_termination) {

wt-status.c

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,31 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
433433
d->dirty_submodule = p->two->dirty_submodule;
434434
if (S_ISGITLINK(p->two->mode))
435435
d->new_submodule_commits = !!hashcmp(p->one->sha1, p->two->sha1);
436+
437+
switch (p->status) {
438+
case DIFF_STATUS_ADDED:
439+
die("BUG: worktree status add???");
440+
break;
441+
442+
case DIFF_STATUS_DELETED:
443+
d->mode_index = p->one->mode;
444+
hashcpy(d->oid_index.hash, p->one->sha1);
445+
/* mode_worktree is zero for a delete. */
446+
break;
447+
448+
case DIFF_STATUS_MODIFIED:
449+
case DIFF_STATUS_TYPE_CHANGED:
450+
case DIFF_STATUS_UNMERGED:
451+
d->mode_index = p->one->mode;
452+
d->mode_worktree = p->two->mode;
453+
hashcpy(d->oid_index.hash, p->one->sha1);
454+
break;
455+
456+
case DIFF_STATUS_UNKNOWN:
457+
die("BUG: worktree status unknown???");
458+
break;
459+
}
460+
436461
}
437462
}
438463

@@ -478,12 +503,36 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
478503
if (!d->index_status)
479504
d->index_status = p->status;
480505
switch (p->status) {
506+
case DIFF_STATUS_ADDED:
507+
/* Leave {mode,oid}_head zero for an add. */
508+
d->mode_index = p->two->mode;
509+
hashcpy(d->oid_index.hash, p->two->sha1);
510+
break;
511+
case DIFF_STATUS_DELETED:
512+
d->mode_head = p->one->mode;
513+
hashcpy(d->oid_head.hash, p->one->sha1);
514+
/* Leave {mode,oid}_index zero for a delete. */
515+
break;
516+
481517
case DIFF_STATUS_COPIED:
482518
case DIFF_STATUS_RENAMED:
483519
d->head_path = xstrdup(p->one->path);
520+
d->score = p->score * 100 / MAX_SCORE;
521+
/* fallthru */
522+
case DIFF_STATUS_MODIFIED:
523+
case DIFF_STATUS_TYPE_CHANGED:
524+
d->mode_head = p->one->mode;
525+
d->mode_index = p->two->mode;
526+
hashcpy(d->oid_head.hash, p->one->sha1);
527+
hashcpy(d->oid_index.hash, p->two->sha1);
484528
break;
485529
case DIFF_STATUS_UNMERGED:
486530
d->stagemask = unmerged_mask(p->two->path);
531+
/*
532+
* Don't bother setting {mode,oid}_{head,index} since the print
533+
* code will output the stage values directly and not use the
534+
* values in these fields.
535+
*/
487536
break;
488537
}
489538
}
@@ -564,9 +613,17 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
564613
if (ce_stage(ce)) {
565614
d->index_status = DIFF_STATUS_UNMERGED;
566615
d->stagemask |= (1 << (ce_stage(ce) - 1));
567-
}
568-
else
616+
/*
617+
* Don't bother setting {mode,oid}_{head,index} since the print
618+
* code will output the stage values directly and not use the
619+
* values in these fields.
620+
*/
621+
} else {
569622
d->index_status = DIFF_STATUS_ADDED;
623+
/* Leave {mode,oid}_head zero for adds. */
624+
d->mode_index = ce->ce_mode;
625+
hashcpy(d->oid_index.hash, ce->sha1);
626+
}
570627
}
571628
}
572629

@@ -1763,6 +1820,9 @@ void wt_status_print(struct wt_status *s)
17631820
case STATUS_FORMAT_PORCELAIN:
17641821
wt_porcelain_print(s);
17651822
break;
1823+
case STATUS_FORMAT_PORCELAIN_V2:
1824+
/* TODO */
1825+
break;
17661826
case STATUS_FORMAT_UNSPECIFIED:
17671827
die("BUG: finalize_deferred_config() should have been called");
17681828
break;

wt-status.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ struct wt_status_change_data {
3838
int worktree_status;
3939
int index_status;
4040
int stagemask;
41+
int score;
42+
int mode_head, mode_index, mode_worktree;
43+
struct object_id oid_head, oid_index;
4144
char *head_path;
4245
unsigned dirty_submodule : 2;
4346
unsigned new_submodule_commits : 1;
@@ -48,6 +51,7 @@ enum wt_status_format {
4851
STATUS_FORMAT_LONG,
4952
STATUS_FORMAT_SHORT,
5053
STATUS_FORMAT_PORCELAIN,
54+
STATUS_FORMAT_PORCELAIN_V2,
5155

5256
STATUS_FORMAT_UNSPECIFIED
5357
};

0 commit comments

Comments
 (0)