From: Jeff Hostetler <hidden> Date: 2016-07-19 22:13:33
This patch series adds porcelain V2 format to status.
This provides detailed information about file changes
and about the current branch.
The new output is accessed via:
git status --porcelain=2 [--branch]
An earlier draft of this work was submitted under the
"Add very verbose porcelain output to status" title.
This new version addresses the concerns about using
(abusing) "-vv" and simplifies the some of the formatting.
This version does not include the state header from my
first draft. I agree that if guarded by a "--state"
argument, that output could be added to both formats.
Jeff Hostetler (6):
Allow --porcelain[=<n>] in status and commit commands
Status and checkout unit tests for --porcelain[=<n>]
Per-file output for Porcelain Status V2
Expanded branch header for Porcelain Status V2
Add porcelain V2 documentation to status manpage
Unit tests for V2 porcelain status
Documentation/git-commit.txt | 2 +-
Documentation/git-status.txt | 69 +++++-
builtin/commit.c | 54 +++--
t/t7060-wtstatus.sh | 21 ++
t/t7064-wtstatus-pv2.sh | 461 ++++++++++++++++++++++++++++++++++++++++
t/t7501-commit.sh | 23 ++
wt-status.c | 487 ++++++++++++++++++++++++++++++++++++++++++-
wt-status.h | 25 +++
8 files changed, 1122 insertions(+), 20 deletions(-)
create mode 100755 t/t7064-wtstatus-pv2.sh
--
2.8.0.rc4.17.gac42084.dirty
From: Jeff Hostetler <hidden> Date: 2016-07-19 22:13:51
Update the --porcelain argument to take an optional
version number. This will allow us to define new
porcelain formats in the future.
This default to 1 and represents the existing porcelain
format.
Signed-off-by: Jeff Hostetler <redacted>
---
Documentation/git-commit.txt | 2 +-
Documentation/git-status.txt | 7 +++++--
builtin/commit.c | 40 +++++++++++++++++++++++++++-------------
wt-status.h | 10 ++++++++++
4 files changed, 43 insertions(+), 16 deletions(-)
@@ -104,7 +104,7 @@ OPTIONS --branch:: Show the branch and tracking info even in short-format.---porcelain::+--porcelain[=<version>]:: When doing a dry-run, give the output in a porcelain-ready format. See linkgit:git-status[1] for details. Implies `--dry-run`.
@@ -32,11 +32,14 @@ OPTIONS --branch:: Show the branch and tracking info even in short-format.---porcelain::+--porcelain[=<version>]:: Give the output in an easy-to-parse format for scripts. This is similar to the short output, but will remain stable across Git versions and regardless of user configuration. See below for details.+++The version parameter is used to specify the format version.+This is optional and defaults to the original version '1' format. --long:: Give the output in the long-format. This is the default.
@@ -96,7 +99,7 @@ configuration variable documented in linkgit:git-config[1]. -z:: Terminate entries with NUL, instead of LF. This implies- the `--porcelain` output format if no other format is given.+ the `--porcelain=1` output format if no other format is given. --column[=<options>]:: --no-column::
@@ -1336,9 +1347,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_("show status concisely"),STATUS_FORMAT_SHORT),OPT_BOOL('b',"branch",&s.show_branch,N_("show branch information")),-OPT_SET_INT(0,"porcelain",&status_format,-N_("machine-readable output"),-STATUS_FORMAT_PORCELAIN),+{OPTION_CALLBACK,0,"porcelain",&status_format,+N_("version"),N_("machine-readable output"),+PARSE_OPT_OPTARG,opt_parse_porcelain},OPT_SET_INT(0,"long",&status_format,N_("show status in long format (default)"),STATUS_FORMAT_LONG),
@@ -1622,8 +1635,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)OPT_SET_INT(0,"short",&status_format,N_("show status concisely"),STATUS_FORMAT_SHORT),OPT_BOOL(0,"branch",&s.show_branch,N_("show branch information")),-OPT_SET_INT(0,"porcelain",&status_format,-N_("machine-readable output"),STATUS_FORMAT_PORCELAIN),+{OPTION_CALLBACK,0,"porcelain",&status_format,+N_("version"),N_("machine-readable output"),+PARSE_OPT_OPTARG,opt_parse_porcelain},OPT_SET_INT(0,"long",&status_format,N_("show status in long format (default)"),STATUS_FORMAT_LONG),
@@ -66,6 +75,7 @@ struct wt_status {intshow_branch;inthints;+enumwt_status_formatstatus_format;/* These are computed during processing of the individual sections */intcommitable;intworkdir_dirty;
@@ -228,4 +228,25 @@ test_expect_success 'status --branch with detached HEAD' 'test_i18ncmpexpectedactual'+## Duplicate the above test and verify --porcelain=1 has no effect.+test_expect_success'status --branch with detached HEAD''+gitreset--hard&&+gitcheckoutmaster^0&&+gitstatus--branch--porcelain=1>actual&&+cat>expected<<-EOF&&+## HEAD (no branch)+??.gitconfig+??actual+??expect+??expected+??mdconflict/+EOF+test_i18ncmpexpectedactual+'++## Verify parser error on --porcelain argument.+test_expect_failure'status --porcelain=bogus''+gitstatus--porcelain=bogus+'+ test_done
@@ -73,6 +73,10 @@ test_expect_success '--porcelain fails with nothing to commit' 'test_must_failgitcommit-minitial--porcelain'+test_expect_success'--porcelain=1 fails with nothing to commit''+test_must_failgitcommit-minitial--porcelain=1+'+ test_expect_success'--long fails with nothing to commit''test_must_failgitcommit-minitial--long'
@@ -97,6 +101,16 @@ test_expect_failure '--porcelain with stuff to commit returns ok' 'gitcommit-mnext-a--porcelain'+test_expect_failure'--porcelain=1 with stuff to commit returns ok''+echobongobongobongo>>file&&+gitcommit-mnext-a--porcelain=1+'++test_expect_failure'--porcelain=bogus with stuff to commit returns ok''+echobongobongobongo>>file&&+gitcommit-mnext-a--porcelain=bogus+'+ test_expect_success'--long with stuff to commit returns ok''echobongobongobongo>>file&&gitcommit-mnext-a--long
From: Jeff Hostetler <hidden> Date: 2016-07-19 22:13:56
This commit sets up version 2 porcelain status and
defines the format of detail lines. This includes
the usual XY and pathname fields. It adds the various
file modes and SHAs and the rename score. For regular
entries these values reflect the head, index and
worktree. For unmerged entries these values reflect
the stage 1, 2, and 3 values.
Signed-off-by: Jeff Hostetler <redacted>
---
builtin/commit.c | 9 ++
wt-status.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
wt-status.h | 13 ++
3 files changed, 419 insertions(+), 1 deletion(-)
@@ -153,6 +153,8 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int unintn=strtol(arg,NULL,10);if(n==1)*value=STATUS_FORMAT_PORCELAIN;+elseif(n==2)+*value=STATUS_FORMAT_PORCELAIN_V2;elsedie("unsupported porcelain version");}else{
@@ -521,6 +523,9 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, intcaseSTATUS_FORMAT_PORCELAIN:wt_porcelain_print(s);break;+caseSTATUS_FORMAT_PORCELAIN_V2:+wt_porcelain_v2_print(s);+break;caseSTATUS_FORMAT_UNSPECIFIED:die("BUG: finalize_deferred_config() should have been called");break;
@@ -1409,6 +1415,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)caseSTATUS_FORMAT_PORCELAIN:wt_porcelain_print(&s);break;+caseSTATUS_FORMAT_PORCELAIN_V2:+wt_porcelain_v2_print(&s);+break;caseSTATUS_FORMAT_UNSPECIFIED:die("BUG: finalize_deferred_config() should have been called");break;
@@ -406,6 +406,89 @@ static void wt_status_print_change_data(struct wt_status *s,strbuf_release(&twobuf);}++/* Copy info for both sides of a head-vs-index change+*intothePorcelainV2data.+*/+staticvoidporcelain_v2_updated_entry(+structwt_status_change_data*d,+structdiff_filepair*p)+{+switch(p->status){+caseDIFF_STATUS_ADDED:+d->porcelain_v2.mode_index=p->two->mode;+hashcpy(d->porcelain_v2.sha1_index,p->two->sha1);+break;++caseDIFF_STATUS_DELETED:+d->porcelain_v2.mode_head=p->one->mode;+hashcpy(d->porcelain_v2.sha1_head,p->one->sha1);+break;++caseDIFF_STATUS_RENAMED:+d->porcelain_v2.rename_score=p->score*100/MAX_SCORE;+caseDIFF_STATUS_COPIED:+caseDIFF_STATUS_MODIFIED:+caseDIFF_STATUS_TYPE_CHANGED:+caseDIFF_STATUS_UNMERGED:+d->porcelain_v2.mode_head=p->one->mode;+d->porcelain_v2.mode_index=p->two->mode;+hashcpy(d->porcelain_v2.sha1_head,p->one->sha1);+hashcpy(d->porcelain_v2.sha1_index,p->two->sha1);+break;++caseDIFF_STATUS_UNKNOWN:+/* This should never happen. */+break;+}+}++/* Copy info for both sides of an index-vs-worktree change+*intotheveryverboseporcelaindata.+*/+staticvoidporcelain_v2_changed_entry(+structwt_status_change_data*d,+conststructdiff_filepair*p)+{+switch(p->status){+caseDIFF_STATUS_ADDED:+d->porcelain_v2.mode_worktree=p->two->mode;+/* don't bother with worktree sha, since it is almost always zero. */+break;++caseDIFF_STATUS_DELETED:+d->porcelain_v2.mode_index=p->one->mode;+hashcpy(d->porcelain_v2.sha1_index,p->one->sha1);+break;++caseDIFF_STATUS_COPIED:+caseDIFF_STATUS_MODIFIED:+caseDIFF_STATUS_RENAMED:+caseDIFF_STATUS_TYPE_CHANGED:+d->porcelain_v2.mode_index=p->one->mode;+d->porcelain_v2.mode_worktree=p->two->mode;+hashcpy(d->porcelain_v2.sha1_index,p->one->sha1);+/* don't bother with worktree sha, since it is almost always zero. */+break;++caseDIFF_STATUS_UNKNOWN:+/* This should never happen. */+break;++caseDIFF_STATUS_UNMERGED:+/* This should never happen. */+break;+}+}++staticvoidporcelain_v2_added_initial_entry(+structwt_status_change_data*d,+conststructcache_entry*ce)+{+d->porcelain_v2.mode_index=ce->ce_mode;+hashcpy(d->porcelain_v2.sha1_index,ce->sha1);+}+staticvoidwt_status_collect_changed_cb(structdiff_queue_struct*q,structdiff_options*options,void*data)
@@ -1753,3 +1846,306 @@ void wt_porcelain_print(struct wt_status *s)s->no_gettext=1;wt_shortstatus_print(s);}++/* Convert various submodule status values into a+*stringofcharactersinthebufferprovided.+*/+staticvoidwt_porcelain_v2_submodule_state(+structwt_status_change_data*d,+charsub[5])+{+intk=0;++if(S_ISGITLINK(d->porcelain_v2.mode_head)||+S_ISGITLINK(d->porcelain_v2.mode_index)||+S_ISGITLINK(d->porcelain_v2.mode_worktree)){+/* We have a submodule */+sub[k++]='S';++/* Sub-flags for each type of dirt */+if(d->new_submodule_commits)+sub[k++]='C';+if(d->dirty_submodule&DIRTY_SUBMODULE_MODIFIED)+sub[k++]='M';+if(d->dirty_submodule&DIRTY_SUBMODULE_UNTRACKED)+sub[k++]='U';+}else{+/* Not a submodule */+sub[k++]='N';+}++sub[k]=0;+}++/* Various fix-up steps before we start printing an item.+*/+staticvoidwt_porcelain_v2_fix_up_status(+structstring_list_item*it,+structwt_status*s)+{+structwt_status_change_data*d=it->util;++if(!d->index_status){+if(d->worktree_status==DIFF_STATUS_MODIFIED||+d->worktree_status==DIFF_STATUS_DELETED){+/* X=' ' Y=[MD]+*Theitemdidnotchangeinhead-vs-indexscansothehead+*columnwasneverset.(Theindexcolumnwassetduringthe+*index-vs-worktreescan.)+*Forcesettheheadcolumntomaketheoutputcomplete.+*/+d->porcelain_v2.mode_head=d->porcelain_v2.mode_index;+hashcpy(d->porcelain_v2.sha1_head,d->porcelain_v2.sha1_index);+}+}++if(!d->worktree_status){+if(d->index_status==DIFF_STATUS_MODIFIED||+d->index_status==DIFF_STATUS_ADDED||+d->index_status==DIFF_STATUS_RENAMED||+d->index_status==DIFF_STATUS_COPIED){+/* X=[MARC] Y=' '+*Theitemdidnotchangedintheindex-vs-worktreescanso+*theworktreecolumnwasneverset.+*Forcesettheworktreemodetomaketheoutputcomplete.+*/+d->porcelain_v2.mode_worktree=d->porcelain_v2.mode_index;+}+}+}++/*+*Defineasingleformatfortrackedentries.Thisincludes:+*normalchanges,renamechanges,andunmergedchanges.+*+*Themeaningsofmodes_[abcd]andsha_[abc]dependsonthe+*changetype,butarealwayspresent.+*+*Path(s)areC-Quotedifnecessary.CurrentpathisALWAYS+*first.Therenamesourcepathisonlypresentwhennecessary.+*AsingleTABseparatesthem(becausepathscancontainspaces+*andC-QuotingconvertsactualtabsinpathnamestoaCescape+*sequence).+*/+staticvoidwt_porcelain_v2_print_tracked_entry(+FILE*fp,+charx_staged,+chary_unstaged,+constchar*submodule,+intmode_a,+intmode_b,+intmode_c,+intmode_d,+constunsignedcharsha_a[GIT_SHA1_RAWSZ],+constunsignedcharsha_b[GIT_SHA1_RAWSZ],+constunsignedcharsha_c[GIT_SHA1_RAWSZ],+intrename_score,+constchar*path_current,+constchar*path_rename_src,+intnull_termination)+{+charsep_char=null_termination?'\0':'\t';+chareol_char=null_termination?'\0':'\n';++if(path_rename_src)+fprintf(fp,"%c%c %s %06o %06o %06o %06o %s %s %s R%d %s%c%s%c",+x_staged,y_unstaged,submodule,+mode_a,mode_b,mode_c,mode_d,+sha1_to_hex(sha_a),sha1_to_hex(sha_b),sha1_to_hex(sha_c),+rename_score,+path_current,sep_char,path_rename_src,+eol_char);+else+fprintf(fp,"%c%c %s %06o %06o %06o %06o %s %s %s R%d %s%c",+x_staged,y_unstaged,submodule,+mode_a,mode_b,mode_c,mode_d,+sha1_to_hex(sha_a),sha1_to_hex(sha_b),sha1_to_hex(sha_c),+rename_score,+path_current,+eol_char);+}++/*+*PrintporcelainV2infofornormaltrackedentries.+*/+staticvoidwt_porcelain_v2_print_normal_entry(+structstring_list_item*it,+structwt_status*s)+{+staticconstunsignedcharsha_zero[GIT_SHA1_RAWSZ]={0};+structwt_status_change_data*d=it->util;+structstrbufbuf_current=STRBUF_INIT;+structstrbufbuf_rename_src=STRBUF_INIT;+constchar*path_current=NULL;+constchar*path_rename_src=NULL;+charx_staged,y_unstaged;+charsubmodule[5];++wt_porcelain_v2_fix_up_status(it,s);+x_staged=d->index_status?d->index_status:'.';+y_unstaged=d->worktree_status?d->worktree_status:'.';+wt_porcelain_v2_submodule_state(d,submodule);++if(s->null_termination){+path_current=it->string;+path_rename_src=d->head_path;+}else{+path_current=quote_path(it->string,s->prefix,&buf_current);+if(d->head_path)+path_rename_src=quote_path(d->head_path,s->prefix,&buf_rename_src);+}++wt_porcelain_v2_print_tracked_entry(+s->fp,+x_staged,y_unstaged,submodule,+d->porcelain_v2.mode_head,+d->porcelain_v2.mode_index,+d->porcelain_v2.mode_worktree,+0,+d->porcelain_v2.sha1_head,+d->porcelain_v2.sha1_index,+sha_zero,+d->porcelain_v2.rename_score,+path_current,+path_rename_src,+s->null_termination);++strbuf_release(&buf_current);+strbuf_release(&buf_rename_src);+}++/*+*Printveryverboseporcelainstatusinfoforunmergedentries.+*/+staticvoidwt_porcelain_v2_print_unmerged_entry(+structstring_list_item*it,+structwt_status*s)+{+structwt_status_change_data*d=it->util;+conststructcache_entry*ce;+structstrbufbuf_current=STRBUF_INIT;+constchar*path_current=NULL;+intpos,stage;+struct{+intmode;+unsignedcharsha1[GIT_SHA1_RAWSZ];+}stages[3];+charx_us='U',y_them='U';+charsubmodule[5];++switch(d->stagemask){+case1:x_us='D';y_them='D';break;/* both deleted */+case2:x_us='A';y_them='U';break;/* added by us */+case3:x_us='U';y_them='D';break;/* deleted by them */+case4:x_us='U';y_them='A';break;/* added by them */+case5:x_us='D';y_them='U';break;/* deleted by us */+case6:x_us='A';y_them='A';break;/* both added */+case7:x_us='U';y_them='U';break;/* both modified */+}++wt_porcelain_v2_submodule_state(d,submodule);++/*+*DisregardtheV2{mode,sha}valuesforheadandindex+*thatwecomputedfromthediffsandlookuptheactual+*stagedata.+*/+memset(stages,0,sizeof(stages));+pos=cache_name_pos(it->string,strlen(it->string));+assert(pos<0);+pos=-pos-1;+while(pos<active_nr){+ce=active_cache[pos++];+stage=ce_stage(ce);+if(strcmp(ce->name,it->string)||!stage)+break;+stages[stage-1].mode=ce->ce_mode;+hashcpy(stages[stage-1].sha1,ce->sha1);+}++if(s->null_termination)+path_current=it->string;+else+path_current=quote_path(it->string,s->prefix,&buf_current);++wt_porcelain_v2_print_tracked_entry(+s->fp,x_us,y_them,submodule,+stages[0].mode,/* stage 1 */+stages[1].mode,/* stage 2 */+stages[2].mode,/* stage 3 */+d->porcelain_v2.mode_worktree,+stages[0].sha1,/* stage 1 */+stages[1].sha1,/* stage 2 */+stages[2].sha1,/* stage 3 */+0,+path_current,+NULL,+s->null_termination);++strbuf_release(&buf_current);+}++/*+*PrintporcelainV2statusinfoforuntrackedandignoredentries.+*/+staticvoidwt_porcelain_v2_print_other(+structstring_list_item*it,+structwt_status*s,+constchar*sign)+{+structstrbufbuf=STRBUF_INIT;+constchar*path;+chareol;++if(s->null_termination){+path=it->string;+eol='\0';+}else{+path=quote_path(it->string,s->prefix,&buf);+eol='\n';+}++fprintf(s->fp,"%s %s%c",sign,path,eol);++strbuf_release(&buf);+}++/* Print porcelain V2 status.+*+*[<v2_branch>]+*[<v2_tracked_items>]*+*[<v2_untracked_items>]*+*[<v2_ignored_items>]*+*+*/+voidwt_porcelain_v2_print(structwt_status*s)+{+inti;++for(i=0;i<s->change.nr;i++){+structwt_status_change_data*d;+structstring_list_item*it;++it=&(s->change.items[i]);+d=it->util;++if(d->stagemask)+wt_porcelain_v2_print_unmerged_entry(it,s);+else+wt_porcelain_v2_print_normal_entry(it,s);+}++for(i=0;i<s->untracked.nr;i++){+structstring_list_item*it;++it=&(s->untracked.items[i]);+wt_porcelain_v2_print_other(it,s,"??");+}++for(i=0;i<s->ignored.nr;i++){+structstring_list_item*it;++it=&(s->ignored.items[i]);+wt_porcelain_v2_print_other(it,s,"!!");+}+}
From: Jeff Hostetler <hidden> Date: 2016-07-19 22:13:57
This commit expand porcelain status V2 to print
detailed information about the current branch.
This includes the SHA of the current commit, the
current branch name, the upstream branch name,
and the ahead/behind counts.
This additional information is included when
the --branch argument is given.
Signed-off-by: Jeff Hostetler <redacted>
---
builtin/commit.c | 5 ++++
wt-status.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 2 ++
3 files changed, 96 insertions(+)
@@ -88,6 +88,8 @@ struct wt_status {inthints;enumwt_status_formatstatus_format;+unsignedcharsha_commit[GIT_SHA1_RAWSZ];/* Commit SHA (when not Initial) */+/* These are computed during processing of the individual sections */intcommitable;intworkdir_dirty;
@@ -77,6 +77,10 @@ test_expect_success '--porcelain=1 fails with nothing to commit' 'test_must_failgitcommit-minitial--porcelain=1'+test_expect_success'--porcelain=2 fails with nothing to commit''+test_must_failgitcommit-minitial--porcelain=2+'+ test_expect_success'--long fails with nothing to commit''test_must_failgitcommit-minitial--long'
@@ -106,6 +110,11 @@ test_expect_failure '--porcelain=1 with stuff to commit returns ok' 'gitcommit-mnext-a--porcelain=1'+test_expect_failure'--porcelain=2 with stuff to commit returns ok''+echobongobongobongo>>file&&+gitcommit-mnext-a--porcelain=2+'+ test_expect_failure'--porcelain=bogus with stuff to commit returns ok''echobongobongobongo>>file&&gitcommit-mnext-a--porcelain=bogus
From: Jeff Hostetler <hidden> Date: 2016-07-19 22:14:00
This commit updates the status manpage to include
information about porcelain format V2.
Signed-off-by: Jeff Hostetler <redacted>
---
Documentation/git-status.txt | 62 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 59 insertions(+), 3 deletions(-)
@@ -185,10 +185,10 @@ If -b is used the short-format status is preceded by a line ## branchname tracking info-Porcelain Format-~~~~~~~~~~~~~~~~+Porcelain Format Version 1+~~~~~~~~~~~~~~~~~~~~~~~~~~-The porcelain format is similar to the short format, but is guaranteed+Version 1 porcelain format is similar to the short format, but is guaranteed not to change in a backwards-incompatible way between Git versions or based on user configuration. This makes it ideal for parsing by scripts. The description of the short format above also describes the porcelain
@@ -210,6 +210,62 @@ field from the first filename). Third, filenames containing special characters are not specially formatted; no quoting or backslash-escaping is performed.+Porcelain Format Version 2+~~~~~~~~~~~~~~~~~~~~~~~~~~+++If `--branch` is given, a header line showing branch tracking information+is printed. This line begins with "### branch: ". Fields are separated+by a single space.++ Field Meaning+ --------------------------------------------------------+ <sha> | (initial) Current commit+ <branch> | (detached) Current branch+ <upstream> Upstream branch, if set+ +<ahead> Ahead count, if upstream present+ -<behind> Behind count, if upstream present+ --------------------------------------------------------++A series of lines are then displayed for the tracked entries.++ <xy> <sub> <mA> <mB> <mC> <mD> <shaA> <shaB> <shaC> R<nr> <path>[\t<pathSrc>]++ Field Meaning+ --------------------------------------------------------+ <xy> The staged and unstaged values described earlier, with+ unchanged indicated by a "." rather than a space.+ <sub> The submodule state. "N" when the entry is not a submodule.+ "S[C][M][U]" when the entry is a submodule.+ "C" indicates the submodule commit has changed.+ "M" indicates the submodule has tracked changes.+ "U" indicates the submodule has untracked changes.+ <m*> The file modes for the entry.+ For unmerged entries, these are the stage 1, 2, and 3,+ and the worktree modes.+ For regular entries, these are the head, index, and+ worktree modes; the fourth is zero.+ <sha*> The SHA1 values for the entry.+ For unmerged entries, these are the stage 1,2, and 3 values.+ For regular entries, these are the head and index values;+ the third entry is zero.+ R<nr> The rename percentage score.+ <path> The current pathname. It is C-Quoted if necessary.+ <pathSrc> The original path. This is only present for staged renames.+ It is C-Quoted if necessary.+ --------------------------------------------------------++A series of lines are then displayed for untracked and ignored entries.++ <xx> <path>++Where <xx> is "??" for untracked entries and "!!" for ignored entries.++When the `-z` option is given, a NUL (zero) byte follows each pathname;+serving as both a separator and line termination. No pathname quoting+or backslash escaping is performed. All fields are output in the same+order.+ CONFIGURATION -------------
From: Johannes Schindelin <hidden> Date: 2016-07-20 15:09:24
Hi Jeff,
On Tue, 19 Jul 2016, Jeff Hostetler wrote:
Update the --porcelain argument to take an optional
version number. This will allow us to define new
porcelain formats in the future.
This default to 1 and represents the existing porcelain
format.
Signed-off-by: Jeff Hostetler <redacted>
How about using a COUNTUP here instead? We could then set the status
format afterwards, like this:
if (porcelain == 0)
status_format = STATUS_FORMAT_UNSPECIFIED;
else {
status_format = STATUS_FORMAT_PORCELAIN;
if (porcelain > 1)
warning("No porcelain v%d; falling back to v1",
porcelain);
}
The rest of the patch looks good to me!
Ciao,
Johannes
From: Johannes Schindelin <hidden> Date: 2016-07-20 15:19:52
Hi Jeff,
On Tue, 19 Jul 2016, Jeff Hostetler wrote:
Simple unit tests to validate the argument parsing.
Signed-off-by: Jeff Hostetler <redacted>
They are simple alright, but do we really need so many of them? I would
like to keep the ones in t7060, but I do not think that we necessarily
have to add the t7501 ones.
I know I am a bit at odds here with Junio, who frequently prefers more
tests. It's just that I have to run the complete test suite so often and
it does take 30-45 minutes to run here (due to the fact that the test
suite exercises quite a lot of the POSIX emulation layer via shell
scripting).
So do not take my suggestions as the sole basis for deciding how to go
from here.
Ciao,
Johannes
From: Jakub Narębski <hidden> Date: 2016-07-20 15:29:13
W dniu 2016-07-20 o 00:10, Jeff Hostetler pisze:
+Porcelain Format Version 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+If `--branch` is given, a header line showing branch tracking information
+is printed. This line begins with "### branch: ". Fields are separated
+by a single space.
+
+ Field Meaning
+ --------------------------------------------------------
+ <sha> | (initial) Current commit
+ <branch> | (detached) Current branch
I was wondering if all possible combinations are allowed. It turns out
that for technical implementation reasons it is not possible to have
"(initial) (detached)".
Just something I was wondering about, no need for any change...
--
Jakub Narębski
From: Jeff Hostetler <hidden> Date: 2016-07-20 15:40:43
On 07/20/2016 11:08 AM, Johannes Schindelin wrote:
On Tue, 19 Jul 2016, Jeff Hostetler wrote:
quoted
diff --git a/builtin/commit.c b/builtin/commit.c
+ } else if (arg) {
+ int n = strtol(arg, NULL, 10);
+ if (n == 1)
+ *value = STATUS_FORMAT_PORCELAIN;
+ else
+ die("unsupported porcelain version");
+ } else {
+ *value = STATUS_FORMAT_PORCELAIN;
This could be folded into the previous conditional:
}
else {
int n = arg ? strtol(arg, NULL, 10) : 1;
...
I did it this way because I didn't want to make any assumptions
here on the numeric value of the enum values. Or rather, I didn't
want to add specific assignments to the enum type.
This also helps make it easier to see my later commit:
else if (n == 2) *value = STATUS_FORMAT_PORCELAIN_V2;
Also, I didn't want to alter the order of assignments to the global
status_format variable. That is, if I capture the value of <n> in
a porcelain_version variable and assign that to status_format
afterwards, there is opportunity for mistakes if they type:
git status --short --porcelain=1 --long
where the status_format variable is assigned 3 times.
How about using a COUNTUP here instead? We could then set the status
format afterwards, like this:
if (porcelain == 0)
status_format = STATUS_FORMAT_UNSPECIFIED;
else {
status_format = STATUS_FORMAT_PORCELAIN;
if (porcelain > 1)
warning("No porcelain v%d; falling back to v1",
porcelain);
}
Maybe I misread the COUNTUP docs, but it looked like it would
allow "--porcelain --porcelain", but not "--porcelain=2".
Jeff
From: Jeff Hostetler <hidden> Date: 2016-07-20 15:44:33
On 07/20/2016 11:29 AM, Jakub Narębski wrote:
W dniu 2016-07-20 o 00:10, Jeff Hostetler pisze:
quoted
+Porcelain Format Version 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+If `--branch` is given, a header line showing branch tracking information
+is printed. This line begins with "### branch: ". Fields are separated
+by a single space.
+
+ Field Meaning
+ --------------------------------------------------------
+ <sha> | (initial) Current commit
+ <branch> | (detached) Current branch
I was wondering if all possible combinations are allowed. It turns out
that for technical implementation reasons it is not possible to have
"(initial) (detached)".
Just something I was wondering about, no need for any change...
Right. I don't think that combination is possible. Not sure how
to document that succinctly.
Jeff
Why not use heredoc syntax (cat <<\EOF), or prepare a file
with expected output in the testsuite?
The tests involving renames needed to embed a tab character
in the output and hiding a tab character in a heredoc seemed
error prone. So to be consistent I made them all printf-style.
Also, some of the tests include SHAs for the commit and for
file content, so having pre-computed expected output is awkward.
Granted we could hard code the file SHAs, but not the commits.
Jeff
From: Jeff Hostetler <hidden> Date: 2016-07-20 15:53:30
On 07/20/2016 11:19 AM, Johannes Schindelin wrote:
Hi Jeff,
On Tue, 19 Jul 2016, Jeff Hostetler wrote:
quoted
Simple unit tests to validate the argument parsing.
Signed-off-by: Jeff Hostetler <redacted>
They are simple alright, but do we really need so many of them? I would
like to keep the ones in t7060, but I do not think that we necessarily
have to add the t7501 ones.
I know I am a bit at odds here with Junio, who frequently prefers more
tests. It's just that I have to run the complete test suite so often and
it does take 30-45 minutes to run here (due to the fact that the test
suite exercises quite a lot of the POSIX emulation layer via shell
scripting).
So do not take my suggestions as the sole basis for deciding how to go
from here.
I'm open to suggestion here. I mainly wanted to be able to
prove that adding "=1" didn't affect the output and that an invalid
parameter throws. We could eliminate several of the "more trivial"
ones if that would help.
Jeff
From: Jakub Narębski <hidden> Date: 2016-07-20 15:56:07
On 20 July 2016 at 17:42, Jeff Hostetler [off-list ref] wrote:
On 07/20/2016 11:29 AM, Jakub Narębski wrote:
quoted
W dniu 2016-07-20 o 00:10, Jeff Hostetler pisze:
quoted
+Porcelain Format Version 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+If `--branch` is given, a header line showing branch tracking
information
+is printed. This line begins with "### branch: ". Fields are separated
+by a single space.
+
+ Field Meaning
+ --------------------------------------------------------
+ <sha> | (initial) Current commit
+ <branch> | (detached) Current branch
I was wondering if all possible combinations are allowed. It turns out
that for technical implementation reasons it is not possible to have
"(initial) (detached)".
Just something I was wondering about, no need for any change...
Right. I don't think that combination is possible. Not sure how
to document that succinctly.
I don't think it is something we need to document, at least not here.
--
Jakub Narębski
From: Jeff King <hidden> Date: 2016-07-20 15:58:50
On Tue, Jul 19, 2016 at 06:10:53PM -0400, Jeff Hostetler wrote:
+static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
+{
+ enum wt_status_format *value = (enum wt_status_format *)opt->value;
+ if (unset) {
+ *value = STATUS_FORMAT_UNSPECIFIED;
Nice attention to detail here and below in handling "unset" and "!arg"
cases. I think should be STATUS_FORMAT_NONE, though, which is what the
old code used to do (since "0" is the usual special value for --no-*
options). It only matters if you do:
git status --no-porcelain
Right now that will switch to the long format, regardless of your
config. With your path it defaults to any configured value. It's
probably a case that nobody hits ever, but in the absence of a good
reason to do otherwise, I'd stick with the current behavior.
+ } else if (arg) {
+ int n = strtol(arg, NULL, 10);
+ if (n == 1)
+ *value = STATUS_FORMAT_PORCELAIN;
+ else
+ die("unsupported porcelain version");
This silently allows:
git status --porcelain="1 for the money"
and later:
git status --porcelain="2 for the show"
Probably not a big deal in practice, but since the list of formats is
constrained, we don't really care about parsing arbitrary numbers.
So:
if (!strcmp(arg, "1"))
*value = STATUS_FORMAT_PORCELAIN;
is actually simpler, and more robust.
I also wondered if:
git status --porcelain=v1
is more self-documenting about the meaning of "1". It's purely
aesthetics, but it somehow looks better to me. Matching that is also
much easier with pure strcmps.
I wonder what happens if you pass a "wt_status" with a format of "SHORT"
to the long-formatting code.
I think it is ignored completely, as you are just now introducing the
s.status_format field. But I wonder if there is room for further cleanup
in pushing the big switch statements from run_status() and cmd_status()
into wt-status.c.
-Peff
Why not use heredoc syntax (cat <<\EOF), or prepare a file
with expected output in the testsuite?
The tests involving renames needed to embed a tab character
in the output and hiding a tab character in a heredoc seemed
error prone. So to be consistent I made them all printf-style.
Ah, so that's the case for series of printf. I think in some other
cases the Git testsuite simply uses HT variable for the TAB
character. I guess that "\t" for TAB is available in POSIX and
all shells that Git is run on?
See t3300-funny-names.sh, t3902-quoted.sh, t4213-log-tabexpand.sh
Also, some of the tests include SHAs for the commit and for
file content, so having pre-computed expected output is awkward.
Granted we could hard code the file SHAs, but not the commits.
Right... but heredoc can include variable expansion (or rather
it includes variable expansion by default, and you can prevent
it by quoting end-of-heredoc marker).
--
Jakub Narębski
From: Jeff King <hidden> Date: 2016-07-20 16:04:15
On Wed, Jul 20, 2016 at 10:00:07AM -0600, Jeff King wrote:
On Tue, Jul 19, 2016 at 06:10:54PM -0400, Jeff Hostetler wrote:
quoted
+test_expect_failure '--porcelain=bogus with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --porcelain=bogus
+'
Hrm. That seems unexpected to me. Shouldn't it complain about
--porcelain=bogus?
Pondering more, did you mean:
test_expect_success '--porcelain=bogus complains about format' '
echo bongo bongo bongo >>file &&
test_must_fail git commit -m next -a --porcelain=bogus
'
?
expect_failure is for tests which we _want_ to succeed, but do not yet
(so they get annotated in test results appropriately). expect_success is
for an outcome we expect to happen, but which may involve specific steps
returning failure.
The names are kind of confusing in that regard.
I wonder if just "test_expect" would be a better name for
test_expect_success, and an argument or environment variable to trigger
"we know this is currently broken" rather than having a separate
test_expect_failure function. That's clearly outside the scope of your
series, of course.
-Peff
From: Jeff King <hidden> Date: 2016-07-20 16:07:06
On Tue, Jul 19, 2016 at 06:10:56PM -0400, Jeff Hostetler wrote:
+ } else {
+ /*
+ * TODO All of various print routines allow for s->branch to be null.
+ * TODO When can this happen and what should we report here?
+ */
+ fprintf(s->fp, " %s", "(unknown)");
+ }
IIRC, it happens when HEAD points to a broken ref. So something like:
git init
echo broken >.git/refs/heads/master
would cause resolving HEAD to return NULL.
-Peff
From: Jeff King <hidden> Date: 2016-07-20 16:15:55
On Tue, Jul 19, 2016 at 06:10:52PM -0400, Jeff Hostetler wrote:
This patch series adds porcelain V2 format to status.
This provides detailed information about file changes
and about the current branch.
The new output is accessed via:
git status --porcelain=2 [--branch]
An earlier draft of this work was submitted under the
"Add very verbose porcelain output to status" title.
This new version addresses the concerns about using
(abusing) "-vv" and simplifies the some of the formatting.
I reviewed the first two, which look good except for a few minor
comments. I don't have time at the moment to dig carefully into the v2
format itself from the later patches (but from a cursory view they look
OK). I'm flying all day today, so probably won't get to a more thorough
review for a day or two (but if there are other reviewers, please don't
feel you have to wait for my input).
One final bit of food for thought.
Just yesterday somebody asked me about renewing the old idea of using a
more standardized format for machine-readable output, like --json.
That's obviously something that would exist alongside the existing
formats for compatibility, and it doesn't fundamentally change anything
about adding a new format as your patches do (it just becomes yet
another format).
However I wanted to mention it in case you are intrigued by the idea,
and would be interested in skipping porcelain-v2 entirely in favor of
moving to something like json.
A totally reasonable response is "haha no. Please stop moving the
goalposts". I just wanted to throw it out there as an option (and in
case you are interested, to let you think about it before any more work
goes into this direction).
-Peff
From: Jeff Hostetler <hidden> Date: 2016-07-20 17:29:05
On 07/20/2016 11:58 AM, Jeff King wrote:
On Tue, Jul 19, 2016 at 06:10:53PM -0400, Jeff Hostetler wrote:
quoted
+static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
+{
+ enum wt_status_format *value = (enum wt_status_format *)opt->value;
+ if (unset) {
+ *value = STATUS_FORMAT_UNSPECIFIED;
Nice attention to detail here and below in handling "unset" and "!arg"
cases. I think should be STATUS_FORMAT_NONE, though, which is what the
old code used to do (since "0" is the usual special value for --no-*
options). It only matters if you do:
git status --no-porcelain
Right now that will switch to the long format, regardless of your
config. With your path it defaults to any configured value. It's
probably a case that nobody hits ever, but in the absence of a good
reason to do otherwise, I'd stick with the current behavior.
Good catch. I'll make it _NONE.
quoted
+ } else if (arg) {
+ int n = strtol(arg, NULL, 10);
+ if (n == 1)
+ *value = STATUS_FORMAT_PORCELAIN;
+ else
+ die("unsupported porcelain version");
This silently allows:
git status --porcelain="1 for the money"
and later:
git status --porcelain="2 for the show"
Probably not a big deal in practice, but since the list of formats is
constrained, we don't really care about parsing arbitrary numbers.
So:
if (!strcmp(arg, "1"))
*value = STATUS_FORMAT_PORCELAIN;
is actually simpler, and more robust.
I also wondered if:
git status --porcelain=v1
is more self-documenting about the meaning of "1". It's purely
aesthetics, but it somehow looks better to me. Matching that is also
much easier with pure strcmps.
I wondered about making it =v1 rather than just =1. It seemed
more aesthetically pleasing, even if it was an extra character
to type. In a later email in this thread you mention a JSON
option. If I switched this here to be "=v1" and "=v2", it would
be easy later to have a "=j2" or "=v2j" to do that.
I wonder what happens if you pass a "wt_status" with a format of "SHORT"
to the long-formatting code.
I think it is ignored completely, as you are just now introducing the
s.status_format field. But I wonder if there is room for further cleanup
in pushing the big switch statements from run_status() and cmd_status()
into wt-status.c.
From: Jeff Hostetler <hidden> Date: 2016-07-20 18:22:56
On 07/20/2016 12:06 PM, Jeff King wrote:
On Tue, Jul 19, 2016 at 06:10:56PM -0400, Jeff Hostetler wrote:
quoted
+ } else {
+ /*
+ * TODO All of various print routines allow for s->branch to be null.
+ * TODO When can this happen and what should we report here?
+ */
+ fprintf(s->fp, " %s", "(unknown)");
+ }
IIRC, it happens when HEAD points to a broken ref. So something like:
git init
echo broken >.git/refs/heads/master
would cause resolving HEAD to return NULL.
That worked and I see "(unknown)".
This is a bit of a nit, but is there a value we'd like
to see there, such as "(unknown)" or "(broken)" or "(missing)"
in that case? (And make it clear that this is a different
case from "(detached)".)
I'm thinking it would be nicer to always have a field
there for parsing.
Jeff
From: Jeff Hostetler <hidden> Date: 2016-07-20 19:30:07
On 07/20/2016 12:15 PM, Jeff King wrote:
One final bit of food for thought.
Just yesterday somebody asked me about renewing the old idea of using a
more standardized format for machine-readable output, like --json.
That's obviously something that would exist alongside the existing
formats for compatibility, and it doesn't fundamentally change anything
about adding a new format as your patches do (it just becomes yet
another format).
However I wanted to mention it in case you are intrigued by the idea,
and would be interested in skipping porcelain-v2 entirely in favor of
moving to something like json.
A totally reasonable response is "haha no. Please stop moving the
goalposts". I just wanted to throw it out there as an option (and in
case you are interested, to let you think about it before any more work
goes into this direction).
haha no.... :-)
Short term, I'd rather nail down what I have now (both content-wise
and format-wise) and see how we like it. And have a follow-up task
to look at the --state header we spoke of earlier. And save the JSON
version as an independent task for later.
I understand the motivation for a JSON option (and have thought
about it before) but I think it ought to be kept separate.
At a higher-level, it seems like a JSON option would be an
opportunity to start a project-wide conversation about formats,
consistency, plumbing, and etc. A top-down conversation if you
will about which commands will/won't get enhanced, legacy cruft
that would not need to be converted, JSON style and naming and
consistency issues, current best practices in the node/whatever
community, and etc. I could be wrong, but this feels like a
top-down feature conversation in a wider audience.
Jeff
From: Jeff King <hidden> Date: 2016-07-20 20:54:35
On Wed, Jul 20, 2016 at 02:20:24PM -0400, Jeff Hostetler wrote:
quoted
IIRC, it happens when HEAD points to a broken ref. So something like:
git init
echo broken >.git/refs/heads/master
would cause resolving HEAD to return NULL.
That worked and I see "(unknown)".
This is a bit of a nit, but is there a value we'd like
to see there, such as "(unknown)" or "(broken)" or "(missing)"
in that case? (And make it clear that this is a different
case from "(detached)".)
I'm thinking it would be nicer to always have a field
there for parsing.
My gut feeling is to err on the side of being vague, like "unknown".
This is something that _shouldn't_ ever happen, and if it does, it could
be a broken on-disk ref, a transient syscall error, or some other
weirdness. I don't think we need to get too specific in this context
(we'll likely have said something else useful on stderr already, I
think).
-Peff
From: Jeff King <hidden> Date: 2016-07-20 20:58:01
On Wed, Jul 20, 2016 at 03:27:45PM -0400, Jeff Hostetler wrote:
quoted
A totally reasonable response is "haha no. Please stop moving the
goalposts". I just wanted to throw it out there as an option (and in
case you are interested, to let you think about it before any more work
goes into this direction).
haha no.... :-)
Short term, I'd rather nail down what I have now (both content-wise
and format-wise) and see how we like it. And have a follow-up task
to look at the --state header we spoke of earlier. And save the JSON
version as an independent task for later.
I understand the motivation for a JSON option (and have thought
about it before) but I think it ought to be kept separate.
At a higher-level, it seems like a JSON option would be an
opportunity to start a project-wide conversation about formats,
consistency, plumbing, and etc. A top-down conversation if you
will about which commands will/won't get enhanced, legacy cruft
that would not need to be converted, JSON style and naming and
consistency issues, current best practices in the node/whatever
community, and etc. I could be wrong, but this feels like a
top-down feature conversation in a wider audience.
I agree with everything you've said here.
If we add JSON, we'd want to do it everywhere: lists of commits, lists
of refs, status output, etc. I mentioned that somebody had asked me
about it recently; they are working on a git client and finding that
libgit2 is not serving their needs well, so they'd like to shell out to
git more, and wanted to have a standard way to get the data back in.
-Peff
How about using a COUNTUP here instead? We could then set the status
format afterwards, like this:
if (porcelain == 0)
status_format = STATUS_FORMAT_UNSPECIFIED;
else {
status_format = STATUS_FORMAT_PORCELAIN;
if (porcelain > 1)
warning("No porcelain v%d; falling back to v1",
porcelain);
}
Maybe I misread the COUNTUP docs, but it looked like it would
allow "--porcelain --porcelain", but not "--porcelain=2".
Whoops, you're right. It is *I* who misread the code (I did not bother
looking for the docs ;-))
Still, I would prefer to avoid that callback. IOW something like
{ OPTION_INTEGER, 0, "porcelain", &status_format,
N_("version"), N_("machine-readable output"),
PARSE_OPT_OPTARG, NULL, 1 },
followed by the if () outlined above.
Ciao,
Johannes
From: Johannes Schindelin <hidden> Date: 2016-07-21 15:47:55
Hi Peff & Jeff ;-)
On Wed, 20 Jul 2016, Jeff King wrote:
On Wed, Jul 20, 2016 at 02:20:24PM -0400, Jeff Hostetler wrote:
quoted
quoted
IIRC, it happens when HEAD points to a broken ref. So something like:
git init
echo broken >.git/refs/heads/master
would cause resolving HEAD to return NULL.
That worked and I see "(unknown)".
This is a bit of a nit, but is there a value we'd like
to see there, such as "(unknown)" or "(broken)" or "(missing)"
in that case? (And make it clear that this is a different
case from "(detached)".)
I'm thinking it would be nicer to always have a field
there for parsing.
My gut feeling is to err on the side of being vague, like "unknown".
This is something that _shouldn't_ ever happen, and if it does, it could
be a broken on-disk ref, a transient syscall error, or some other
weirdness. I don't think we need to get too specific in this context
(we'll likely have said something else useful on stderr already, I
think).
FWIW I think "unknown" is a nice conservative way to shrug Git's
shoulders.
When we call `git status --porcelain=v2` and read "unknown", we could
always try to find out more using additional low-level tools and/or disk
access: this is such a rare case that it does not *really* matter all that
much.
Ciao,
Dscho
Why not use heredoc syntax (cat <<\EOF), or prepare a file
with expected output in the testsuite?
The tests involving renames needed to embed a tab character
in the output and hiding a tab character in a heredoc seemed
error prone. So to be consistent I made them all printf-style.
Ah, so that's the case for series of printf. I think in some other
cases the Git testsuite simply uses HT variable for the TAB
character.
Yeah, it would be more pleasant to read
echo >expected <<-EOF
## branch: (initial) master
?? actual
?? dir1/
?? expected
?? file_x
?? file_y
?? file_z
EOF
And it is also easy to use $HT in there (unless you want to use <<-\EOF).
Actually, even if you want to use \EOF, you can easily use `sed` to
expand, say, "Q" to tabs, such as was done here:
https://github.com/git/git/blob/v2.9.2/t/t4213-log-tabexpand.sh#L88-L92
Ciao,
Dscho
From: Johannes Schindelin <hidden> Date: 2016-07-21 16:03:24
Hi Peff & Jeff ;-)
On Wed, 20 Jul 2016, Jeff King wrote:
On Wed, Jul 20, 2016 at 03:27:45PM -0400, Jeff Hostetler wrote:
quoted
quoted
A totally reasonable response is "haha no. Please stop moving the
goalposts". I just wanted to throw it out there as an option (and in
case you are interested, to let you think about it before any more work
goes into this direction).
haha no.... :-)
Short term, I'd rather nail down what I have now (both content-wise
and format-wise) and see how we like it. And have a follow-up task
to look at the --state header we spoke of earlier. And save the JSON
version as an independent task for later.
I understand the motivation for a JSON option (and have thought
about it before) but I think it ought to be kept separate.
At a higher-level, it seems like a JSON option would be an
opportunity to start a project-wide conversation about formats,
consistency, plumbing, and etc. A top-down conversation if you
will about which commands will/won't get enhanced, legacy cruft
that would not need to be converted, JSON style and naming and
consistency issues, current best practices in the node/whatever
community, and etc. I could be wrong, but this feels like a
top-down feature conversation in a wider audience.
I agree with everything you've said here.
If we add JSON, we'd want to do it everywhere: lists of commits, lists
of refs, status output, etc. I mentioned that somebody had asked me
about it recently; they are working on a git client and finding that
libgit2 is not serving their needs well, so they'd like to shell out to
git more, and wanted to have a standard way to get the data back in.
Yeah, if we add JSON, we would want to add it everywhere. But we would
want to add that incrementally; otherwise it would be too humongous a
task.
And I think a good way forward was already suggested elsewhere in this
thread by Jeff: --porcelain=1j, or --porcelain=json (and maybe later
json-v2, json-v3, etc).
Ciao,
Dscho
From: Jeff Hostetler <hidden> Date: 2016-07-21 19:05:22
On 07/21/2016 11:46 AM, Johannes Schindelin wrote:
On Wed, 20 Jul 2016, Jeff King wrote:
quoted
On Wed, Jul 20, 2016 at 02:20:24PM -0400, Jeff Hostetler wrote:
quoted
quoted
IIRC, it happens when HEAD points to a broken ref. So something like:
git init
echo broken >.git/refs/heads/master
would cause resolving HEAD to return NULL.
That worked and I see "(unknown)".
This is a bit of a nit, but is there a value we'd like
to see there, such as "(unknown)" or "(broken)" or "(missing)"
in that case? (And make it clear that this is a different
case from "(detached)".)
I'm thinking it would be nicer to always have a field
there for parsing.
My gut feeling is to err on the side of being vague, like "unknown".
This is something that _shouldn't_ ever happen, and if it does, it could
be a broken on-disk ref, a transient syscall error, or some other
weirdness. I don't think we need to get too specific in this context
(we'll likely have said something else useful on stderr already, I
think).
FWIW I think "unknown" is a nice conservative way to shrug Git's
shoulders.
When we call `git status --porcelain=v2` and read "unknown", we could
always try to find out more using additional low-level tools and/or disk
access: this is such a rare case that it does not *really* matter all that
much.
yes, this case causes even rev-parse fits. I'l make it return a
known quantity so that users don't have to deal with stuff like:
$ more .git/HEAD
ref: refs/heads/foo
$ more .git/refs/heads/foo
brokwn
$ git rev-parse HEAD
HEAD
fatal: ambiguous argument 'HEAD': unknown revision or path not in the
working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
$ git rev-parse HEAD --
fatal: bad revision 'HEAD'
$
Jeff