@@ -175,6 +175,70 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
175
175
return 0 ;
176
176
}
177
177
178
+ static int do_serialize = 0 ;
179
+ static int do_implicit_deserialize = 0 ;
180
+ static int do_explicit_deserialize = 0 ;
181
+ static char * deserialize_path = NULL ;
182
+
183
+ /*
184
+ * --serialize | --serialize=1 | --serialize=v1
185
+ *
186
+ * Request that we serialize our output rather than printing in
187
+ * any of the established formats. Optionally specify serialization
188
+ * version.
189
+ */
190
+ static int opt_parse_serialize (const struct option * opt , const char * arg , int unset )
191
+ {
192
+ enum wt_status_format * value = (enum wt_status_format * )opt -> value ;
193
+ if (unset || !arg )
194
+ * value = STATUS_FORMAT_SERIALIZE_V1 ;
195
+ else if (!strcmp (arg , "v1" ) || !strcmp (arg , "1" ))
196
+ * value = STATUS_FORMAT_SERIALIZE_V1 ;
197
+ else
198
+ die ("unsupported serialize version '%s'" , arg );
199
+
200
+ if (do_explicit_deserialize )
201
+ die ("cannot mix --serialize and --deserialize" );
202
+ do_implicit_deserialize = 0 ;
203
+
204
+ do_serialize = 1 ;
205
+ return 0 ;
206
+ }
207
+
208
+ /*
209
+ * --deserialize | --deserialize=<path> |
210
+ * --no-deserialize
211
+ *
212
+ * Request that we deserialize status data from some existing resource
213
+ * rather than performing a status scan.
214
+ *
215
+ * The input source can come from stdin or a path given here -- or be
216
+ * inherited from the config settings.
217
+ */
218
+ static int opt_parse_deserialize (const struct option * opt , const char * arg , int unset )
219
+ {
220
+ if (unset ) {
221
+ do_implicit_deserialize = 0 ;
222
+ do_explicit_deserialize = 0 ;
223
+ } else {
224
+ if (do_serialize )
225
+ die ("cannot mix --serialize and --deserialize" );
226
+ if (arg ) {
227
+ /* override config or stdin */
228
+ free (deserialize_path );
229
+ deserialize_path = xstrdup (arg );
230
+ }
231
+ if (deserialize_path && * deserialize_path
232
+ && (access (deserialize_path , R_OK ) != 0 ))
233
+ die ("cannot find serialization file '%s'" ,
234
+ deserialize_path );
235
+
236
+ do_explicit_deserialize = 1 ;
237
+ }
238
+
239
+ return 0 ;
240
+ }
241
+
178
242
static int opt_parse_m (const struct option * opt , const char * arg , int unset )
179
243
{
180
244
struct strbuf * buf = opt -> value ;
@@ -1176,6 +1240,8 @@ static void handle_untracked_files_arg(struct wt_status *s)
1176
1240
s -> show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES ;
1177
1241
else if (!strcmp (untracked_files_arg , "all" ))
1178
1242
s -> show_untracked_files = SHOW_ALL_UNTRACKED_FILES ;
1243
+ else if (!strcmp (untracked_files_arg ,"complete" ))
1244
+ s -> show_untracked_files = SHOW_COMPLETE_UNTRACKED_FILES ;
1179
1245
/*
1180
1246
* Please update $__git_untracked_file_modes in
1181
1247
* git-completion.bash when you add new options
@@ -1463,6 +1529,19 @@ static int git_status_config(const char *k, const char *v,
1463
1529
s -> relative_paths = git_config_bool (k , v );
1464
1530
return 0 ;
1465
1531
}
1532
+ if (!strcmp (k , "status.deserializepath" )) {
1533
+ /*
1534
+ * Automatically assume deserialization if this is
1535
+ * set in the config and the file exists. Do not
1536
+ * complain if the file does not exist, because we
1537
+ * silently fall back to normal mode.
1538
+ */
1539
+ if (v && * v && access (v , R_OK ) == 0 ) {
1540
+ do_implicit_deserialize = 1 ;
1541
+ deserialize_path = xstrdup (v );
1542
+ }
1543
+ return 0 ;
1544
+ }
1466
1545
if (!strcmp (k , "status.showuntrackedfiles" )) {
1467
1546
if (!v )
1468
1547
return config_error_nonbool (k );
@@ -1503,7 +1582,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1503
1582
static const char * rename_score_arg = (const char * )-1 ;
1504
1583
static struct wt_status s ;
1505
1584
unsigned int progress_flag = 0 ;
1506
- int fd ;
1585
+ int try_deserialize ;
1586
+ int fd = -1 ;
1507
1587
struct object_id oid ;
1508
1588
static struct option builtin_status_options [] = {
1509
1589
OPT__VERBOSE (& verbose , N_ ("be verbose" )),
@@ -1518,6 +1598,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1518
1598
OPT_CALLBACK_F (0 , "porcelain" , & status_format ,
1519
1599
N_ ("version" ), N_ ("machine-readable output" ),
1520
1600
PARSE_OPT_OPTARG , opt_parse_porcelain ),
1601
+ { OPTION_CALLBACK , 0 , "serialize" , & status_format ,
1602
+ N_ ("version" ), N_ ("serialize raw status data to stdout" ),
1603
+ PARSE_OPT_OPTARG | PARSE_OPT_NONEG , opt_parse_serialize },
1604
+ { OPTION_CALLBACK , 0 , "deserialize" , NULL ,
1605
+ N_ ("path" ), N_ ("deserialize raw status data from file" ),
1606
+ PARSE_OPT_OPTARG , opt_parse_deserialize },
1521
1607
OPT_SET_INT (0 , "long" , & status_format ,
1522
1608
N_ ("show status in long format (default)" ),
1523
1609
STATUS_FORMAT_LONG ),
@@ -1562,10 +1648,26 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1562
1648
s .show_untracked_files == SHOW_NO_UNTRACKED_FILES )
1563
1649
die (_ ("Unsupported combination of ignored and untracked-files arguments" ));
1564
1650
1651
+ if (s .show_untracked_files == SHOW_COMPLETE_UNTRACKED_FILES &&
1652
+ s .show_ignored_mode == SHOW_NO_IGNORED )
1653
+ die (_ ("Complete Untracked only supported with ignored files" ));
1654
+
1565
1655
parse_pathspec (& s .pathspec , 0 ,
1566
1656
PATHSPEC_PREFER_FULL ,
1567
1657
prefix , argv );
1568
1658
1659
+ /*
1660
+ * If we want to try to deserialize status data from a cache file,
1661
+ * we need to re-order the initialization code. The problem is that
1662
+ * this makes for a very nasty diff and causes merge conflicts as we
1663
+ * carry it forward. And it easy to mess up the merge, so we
1664
+ * duplicate some code here to hopefully reduce conflicts.
1665
+ */
1666
+ try_deserialize = (!do_serialize &&
1667
+ (do_implicit_deserialize || do_explicit_deserialize ));
1668
+ if (try_deserialize )
1669
+ goto skip_init ;
1670
+
1569
1671
enable_fscache (0 );
1570
1672
if (status_format != STATUS_FORMAT_PORCELAIN &&
1571
1673
status_format != STATUS_FORMAT_PORCELAIN_V2 )
@@ -1580,6 +1682,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1580
1682
else
1581
1683
fd = -1 ;
1582
1684
1685
+ skip_init :
1583
1686
s .is_initial = repo_get_oid (the_repository , s .reference , & oid ) ? 1 : 0 ;
1584
1687
if (!s .is_initial )
1585
1688
oidcpy (& s .oid_commit , & oid );
@@ -1596,6 +1699,24 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1596
1699
s .rename_score = parse_rename_score (& rename_score_arg );
1597
1700
}
1598
1701
1702
+ if (try_deserialize ) {
1703
+ if (s .relative_paths )
1704
+ s .prefix = prefix ;
1705
+
1706
+ if (wt_status_deserialize (& s , deserialize_path ) == DESERIALIZE_OK )
1707
+ return 0 ;
1708
+
1709
+ /* deserialize failed, so force the initialization we skipped above. */
1710
+ enable_fscache (1 );
1711
+ repo_read_index_preload (the_repository , & s .pathspec , 0 );
1712
+ refresh_index (& the_index , REFRESH_QUIET |REFRESH_UNMERGED , & s .pathspec , NULL , NULL );
1713
+
1714
+ if (use_optional_locks ())
1715
+ fd = repo_hold_locked_index (the_repository , & index_lock , 0 );
1716
+ else
1717
+ fd = -1 ;
1718
+ }
1719
+
1599
1720
wt_status_collect (& s );
1600
1721
1601
1722
if (0 <= fd )
0 commit comments