@@ -1814,6 +1814,289 @@ static void wt_porcelain_print(struct wt_status *s)
1814
1814
wt_shortstatus_print (s );
1815
1815
}
1816
1816
1817
+ /*
1818
+ * Convert various submodule status values into a
1819
+ * fixed-length string of characters in the buffer provided.
1820
+ */
1821
+ static void wt_porcelain_v2_submodule_state (
1822
+ struct wt_status_change_data * d ,
1823
+ char sub [5 ])
1824
+ {
1825
+ if (S_ISGITLINK (d -> mode_head ) ||
1826
+ S_ISGITLINK (d -> mode_index ) ||
1827
+ S_ISGITLINK (d -> mode_worktree )) {
1828
+ sub [0 ] = 'S' ;
1829
+ sub [1 ] = d -> new_submodule_commits ? 'C' : '.' ;
1830
+ sub [2 ] = (d -> dirty_submodule & DIRTY_SUBMODULE_MODIFIED ) ? 'M' : '.' ;
1831
+ sub [3 ] = (d -> dirty_submodule & DIRTY_SUBMODULE_UNTRACKED ) ? 'U' : '.' ;
1832
+ } else {
1833
+ sub [0 ] = 'N' ;
1834
+ sub [1 ] = '.' ;
1835
+ sub [2 ] = '.' ;
1836
+ sub [3 ] = '.' ;
1837
+ }
1838
+ sub [4 ] = 0 ;
1839
+ }
1840
+
1841
+ /*
1842
+ * Fix-up changed entries before we print them.
1843
+ */
1844
+ static void wt_porcelain_v2_fix_up_changed (
1845
+ struct string_list_item * it ,
1846
+ struct wt_status * s )
1847
+ {
1848
+ struct wt_status_change_data * d = it -> util ;
1849
+
1850
+ if (!d -> index_status ) {
1851
+ /*
1852
+ * This entry is unchanged in the index (relative to the head).
1853
+ * Therefore, the collect_updated_cb was never called for this
1854
+ * entry (during the head-vs-index scan) and so the head column
1855
+ * fields were never set.
1856
+ *
1857
+ * We must have data for the index column (from the
1858
+ * index-vs-worktree scan (otherwise, this entry should not be
1859
+ * in the list of changes)).
1860
+ *
1861
+ * Copy index column fields to the head column, so that our
1862
+ * output looks complete.
1863
+ */
1864
+ assert (d -> mode_head == 0 );
1865
+ d -> mode_head = d -> mode_index ;
1866
+ oidcpy (& d -> oid_head , & d -> oid_index );
1867
+ }
1868
+
1869
+ if (!d -> worktree_status ) {
1870
+ /*
1871
+ * This entry is unchanged in the worktree (relative to the index).
1872
+ * Therefore, the collect_changed_cb was never called for this entry
1873
+ * (during the index-vs-worktree scan) and so the worktree column
1874
+ * fields were never set.
1875
+ *
1876
+ * We must have data for the index column (from the head-vs-index
1877
+ * scan).
1878
+ *
1879
+ * Copy the index column fields to the worktree column so that
1880
+ * our output looks complete.
1881
+ *
1882
+ * Note that we only have a mode field in the worktree column
1883
+ * because the scan code tries really hard to not have to compute it.
1884
+ */
1885
+ assert (d -> mode_worktree == 0 );
1886
+ d -> mode_worktree = d -> mode_index ;
1887
+ }
1888
+ }
1889
+
1890
+ /*
1891
+ * Print porcelain v2 info for tracked entries with changes.
1892
+ */
1893
+ static void wt_porcelain_v2_print_changed_entry (
1894
+ struct string_list_item * it ,
1895
+ struct wt_status * s )
1896
+ {
1897
+ struct wt_status_change_data * d = it -> util ;
1898
+ struct strbuf buf_index = STRBUF_INIT ;
1899
+ struct strbuf buf_head = STRBUF_INIT ;
1900
+ const char * path_index = NULL ;
1901
+ const char * path_head = NULL ;
1902
+ char key [3 ];
1903
+ char submodule_token [5 ];
1904
+ char sep_char , eol_char ;
1905
+
1906
+ wt_porcelain_v2_fix_up_changed (it , s );
1907
+ wt_porcelain_v2_submodule_state (d , submodule_token );
1908
+
1909
+ key [0 ] = d -> index_status ? d -> index_status : '.' ;
1910
+ key [1 ] = d -> worktree_status ? d -> worktree_status : '.' ;
1911
+ key [2 ] = 0 ;
1912
+
1913
+ if (s -> null_termination ) {
1914
+ /*
1915
+ * In -z mode, we DO NOT C-quote pathnames. Current path is ALWAYS first.
1916
+ * A single NUL character separates them.
1917
+ */
1918
+ sep_char = '\0' ;
1919
+ eol_char = '\0' ;
1920
+ path_index = it -> string ;
1921
+ path_head = d -> head_path ;
1922
+ } else {
1923
+ /*
1924
+ * Path(s) are C-quoted if necessary. Current path is ALWAYS first.
1925
+ * The source path is only present when necessary.
1926
+ * A single TAB separates them (because paths can contain spaces
1927
+ * which are not escaped and C-quoting does escape TAB characters).
1928
+ */
1929
+ sep_char = '\t' ;
1930
+ eol_char = '\n' ;
1931
+ path_index = quote_path (it -> string , s -> prefix , & buf_index );
1932
+ if (d -> head_path )
1933
+ path_head = quote_path (d -> head_path , s -> prefix , & buf_head );
1934
+ }
1935
+
1936
+ if (path_head )
1937
+ fprintf (s -> fp , "2 %s %s %06o %06o %06o %s %s %c%d %s%c%s%c" ,
1938
+ key , submodule_token ,
1939
+ d -> mode_head , d -> mode_index , d -> mode_worktree ,
1940
+ oid_to_hex (& d -> oid_head ), oid_to_hex (& d -> oid_index ),
1941
+ key [0 ], d -> score ,
1942
+ path_index , sep_char , path_head , eol_char );
1943
+ else
1944
+ fprintf (s -> fp , "1 %s %s %06o %06o %06o %s %s %s%c" ,
1945
+ key , submodule_token ,
1946
+ d -> mode_head , d -> mode_index , d -> mode_worktree ,
1947
+ oid_to_hex (& d -> oid_head ), oid_to_hex (& d -> oid_index ),
1948
+ path_index , eol_char );
1949
+
1950
+ strbuf_release (& buf_index );
1951
+ strbuf_release (& buf_head );
1952
+ }
1953
+
1954
+ /*
1955
+ * Print porcelain v2 status info for unmerged entries.
1956
+ */
1957
+ static void wt_porcelain_v2_print_unmerged_entry (
1958
+ struct string_list_item * it ,
1959
+ struct wt_status * s )
1960
+ {
1961
+ struct wt_status_change_data * d = it -> util ;
1962
+ const struct cache_entry * ce ;
1963
+ struct strbuf buf_index = STRBUF_INIT ;
1964
+ const char * path_index = NULL ;
1965
+ int pos , stage , sum ;
1966
+ struct {
1967
+ int mode ;
1968
+ struct object_id oid ;
1969
+ } stages [3 ];
1970
+ char * key ;
1971
+ char submodule_token [5 ];
1972
+ char unmerged_prefix = 'u' ;
1973
+ char eol_char = s -> null_termination ? '\0' : '\n' ;
1974
+
1975
+ wt_porcelain_v2_submodule_state (d , submodule_token );
1976
+
1977
+ switch (d -> stagemask ) {
1978
+ case 1 : key = "DD" ; break ; /* both deleted */
1979
+ case 2 : key = "AU" ; break ; /* added by us */
1980
+ case 3 : key = "UD" ; break ; /* deleted by them */
1981
+ case 4 : key = "UA" ; break ; /* added by them */
1982
+ case 5 : key = "DU" ; break ; /* deleted by us */
1983
+ case 6 : key = "AA" ; break ; /* both added */
1984
+ case 7 : key = "UU" ; break ; /* both modified */
1985
+ default :
1986
+ die ("BUG: unhandled unmerged status %x" , d -> stagemask );
1987
+ }
1988
+
1989
+ /*
1990
+ * Disregard d.aux.porcelain_v2 data that we accumulated
1991
+ * for the head and index columns during the scans and
1992
+ * replace with the actual stage data.
1993
+ *
1994
+ * Note that this is a last-one-wins for each the individual
1995
+ * stage [123] columns in the event of multiple cache entries
1996
+ * for same stage.
1997
+ */
1998
+ memset (stages , 0 , sizeof (stages ));
1999
+ sum = 0 ;
2000
+ pos = cache_name_pos (it -> string , strlen (it -> string ));
2001
+ assert (pos < 0 );
2002
+ pos = - pos - 1 ;
2003
+ while (pos < active_nr ) {
2004
+ ce = active_cache [pos ++ ];
2005
+ stage = ce_stage (ce );
2006
+ if (strcmp (ce -> name , it -> string ) || !stage )
2007
+ break ;
2008
+ stages [stage - 1 ].mode = ce -> ce_mode ;
2009
+ hashcpy (stages [stage - 1 ].oid .hash , ce -> sha1 );
2010
+ sum |= (1 << (stage - 1 ));
2011
+ }
2012
+ if (sum != d -> stagemask )
2013
+ die ("BUG: observed stagemask 0x%x != expected stagemask 0x%x" , sum , d -> stagemask );
2014
+
2015
+ if (s -> null_termination )
2016
+ path_index = it -> string ;
2017
+ else
2018
+ path_index = quote_path (it -> string , s -> prefix , & buf_index );
2019
+
2020
+ fprintf (s -> fp , "%c %s %s %06o %06o %06o %06o %s %s %s %s%c" ,
2021
+ unmerged_prefix , key , submodule_token ,
2022
+ stages [0 ].mode , /* stage 1 */
2023
+ stages [1 ].mode , /* stage 2 */
2024
+ stages [2 ].mode , /* stage 3 */
2025
+ d -> mode_worktree ,
2026
+ oid_to_hex (& stages [0 ].oid ), /* stage 1 */
2027
+ oid_to_hex (& stages [1 ].oid ), /* stage 2 */
2028
+ oid_to_hex (& stages [2 ].oid ), /* stage 3 */
2029
+ path_index ,
2030
+ eol_char );
2031
+
2032
+ strbuf_release (& buf_index );
2033
+ }
2034
+
2035
+ /*
2036
+ * Print porcelain V2 status info for untracked and ignored entries.
2037
+ */
2038
+ static void wt_porcelain_v2_print_other (
2039
+ struct string_list_item * it ,
2040
+ struct wt_status * s ,
2041
+ char prefix )
2042
+ {
2043
+ struct strbuf buf = STRBUF_INIT ;
2044
+ const char * path ;
2045
+ char eol_char ;
2046
+
2047
+ if (s -> null_termination ) {
2048
+ path = it -> string ;
2049
+ eol_char = '\0' ;
2050
+ } else {
2051
+ path = quote_path (it -> string , s -> prefix , & buf );
2052
+ eol_char = '\n' ;
2053
+ }
2054
+
2055
+ fprintf (s -> fp , "%c %s%c" , prefix , path , eol_char );
2056
+
2057
+ strbuf_release (& buf );
2058
+ }
2059
+
2060
+ /*
2061
+ * Print porcelain V2 status.
2062
+ *
2063
+ * [<v2_changed_items>]*
2064
+ * [<v2_unmerged_items>]*
2065
+ * [<v2_untracked_items>]*
2066
+ * [<v2_ignored_items>]*
2067
+ *
2068
+ */
2069
+ static void wt_porcelain_v2_print (struct wt_status * s )
2070
+ {
2071
+ struct wt_status_change_data * d ;
2072
+ struct string_list_item * it ;
2073
+ int i ;
2074
+
2075
+ for (i = 0 ; i < s -> change .nr ; i ++ ) {
2076
+ it = & (s -> change .items [i ]);
2077
+ d = it -> util ;
2078
+ if (!d -> stagemask )
2079
+ wt_porcelain_v2_print_changed_entry (it , s );
2080
+ }
2081
+
2082
+ for (i = 0 ; i < s -> change .nr ; i ++ ) {
2083
+ it = & (s -> change .items [i ]);
2084
+ d = it -> util ;
2085
+ if (d -> stagemask )
2086
+ wt_porcelain_v2_print_unmerged_entry (it , s );
2087
+ }
2088
+
2089
+ for (i = 0 ; i < s -> untracked .nr ; i ++ ) {
2090
+ it = & (s -> untracked .items [i ]);
2091
+ wt_porcelain_v2_print_other (it , s , '?' );
2092
+ }
2093
+
2094
+ for (i = 0 ; i < s -> ignored .nr ; i ++ ) {
2095
+ it = & (s -> ignored .items [i ]);
2096
+ wt_porcelain_v2_print_other (it , s , '!' );
2097
+ }
2098
+ }
2099
+
1817
2100
void wt_status_print (struct wt_status * s )
1818
2101
{
1819
2102
switch (s -> status_format ) {
@@ -1824,7 +2107,7 @@ void wt_status_print(struct wt_status *s)
1824
2107
wt_porcelain_print (s );
1825
2108
break ;
1826
2109
case STATUS_FORMAT_PORCELAIN_V2 :
1827
- /* TODO */
2110
+ wt_porcelain_v2_print ( s );
1828
2111
break ;
1829
2112
case STATUS_FORMAT_UNSPECIFIED :
1830
2113
die ("BUG: finalize_deferred_config() should have been called" );
0 commit comments