@@ -143,6 +143,67 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
143
143
return 0 ;
144
144
}
145
145
146
+ static int do_serialize = 0 ;
147
+ static int do_implicit_deserialize = 0 ;
148
+ static int do_explicit_deserialize = 0 ;
149
+ static char * deserialize_path = NULL ;
150
+
151
+ /*
152
+ * --serialize | --serialize=1 | --serialize=v1
153
+ *
154
+ * Request that we serialize our output rather than printing in
155
+ * any of the established formats. Optionally specify serialization
156
+ * version.
157
+ */
158
+ static int opt_parse_serialize (const struct option * opt , const char * arg , int unset )
159
+ {
160
+ enum wt_status_format * value = (enum wt_status_format * )opt -> value ;
161
+ if (unset || !arg )
162
+ * value = STATUS_FORMAT_SERIALIZE_V1 ;
163
+ else if (!strcmp (arg , "v1" ) || !strcmp (arg , "1" ))
164
+ * value = STATUS_FORMAT_SERIALIZE_V1 ;
165
+ else
166
+ die ("unsupported serialize version '%s'" , arg );
167
+
168
+ if (do_explicit_deserialize )
169
+ die ("cannot mix --serialize and --deserialize" );
170
+ do_implicit_deserialize = 0 ;
171
+
172
+ do_serialize = 1 ;
173
+ return 0 ;
174
+ }
175
+
176
+ /*
177
+ * --deserialize | --deserialize=<path> |
178
+ * --no-deserialize
179
+ *
180
+ * Request that we deserialize status data from some existing resource
181
+ * rather than performing a status scan.
182
+ *
183
+ * The input source can come from stdin or a path given here -- or be
184
+ * inherited from the config settings.
185
+ */
186
+ static int opt_parse_deserialize (const struct option * opt , const char * arg , int unset )
187
+ {
188
+ if (unset ) {
189
+ do_implicit_deserialize = 0 ;
190
+ do_explicit_deserialize = 0 ;
191
+ } else {
192
+ if (do_serialize )
193
+ die ("cannot mix --serialize and --deserialize" );
194
+ /* override config or stdin */
195
+ deserialize_path = xstrdup_or_null (arg );
196
+ if (deserialize_path && * deserialize_path
197
+ && (access (deserialize_path , R_OK ) != 0 ))
198
+ die ("cannot find serialization file '%s'" ,
199
+ deserialize_path );
200
+
201
+ do_explicit_deserialize = 1 ;
202
+ }
203
+
204
+ return 0 ;
205
+ }
206
+
146
207
static int opt_parse_m (const struct option * opt , const char * arg , int unset )
147
208
{
148
209
struct strbuf * buf = opt -> value ;
@@ -1038,6 +1099,8 @@ static void handle_untracked_files_arg(struct wt_status *s)
1038
1099
s -> show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES ;
1039
1100
else if (!strcmp (untracked_files_arg , "all" ))
1040
1101
s -> show_untracked_files = SHOW_ALL_UNTRACKED_FILES ;
1102
+ else if (!strcmp (untracked_files_arg ,"complete" ))
1103
+ s -> show_untracked_files = SHOW_COMPLETE_UNTRACKED_FILES ;
1041
1104
else
1042
1105
die (_ ("Invalid untracked files mode '%s'" ), untracked_files_arg );
1043
1106
}
@@ -1266,6 +1329,19 @@ static int git_status_config(const char *k, const char *v, void *cb)
1266
1329
s -> relative_paths = git_config_bool (k , v );
1267
1330
return 0 ;
1268
1331
}
1332
+ if (!strcmp (k , "status.deserializepath" )) {
1333
+ /*
1334
+ * Automatically assume deserialization if this is
1335
+ * set in the config and the file exists. Do not
1336
+ * complain if the file does not exist, because we
1337
+ * silently fall back to normal mode.
1338
+ */
1339
+ if (v && * v && access (v , R_OK ) == 0 ) {
1340
+ do_implicit_deserialize = 1 ;
1341
+ deserialize_path = xstrdup (v );
1342
+ }
1343
+ return 0 ;
1344
+ }
1269
1345
if (!strcmp (k , "status.showuntrackedfiles" )) {
1270
1346
if (!v )
1271
1347
return config_error_nonbool (k );
@@ -1308,7 +1384,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1308
1384
static int show_ignored_directory = 0 ;
1309
1385
static struct wt_status s ;
1310
1386
unsigned int progress_flag = 0 ;
1311
- int fd ;
1387
+ int try_deserialize ;
1388
+ int fd = -1 ;
1312
1389
struct object_id oid ;
1313
1390
static struct option builtin_status_options [] = {
1314
1391
OPT__VERBOSE (& verbose , N_ ("be verbose" )),
@@ -1323,6 +1400,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1323
1400
{ OPTION_CALLBACK , 0 , "porcelain" , & status_format ,
1324
1401
N_ ("version" ), N_ ("machine-readable output" ),
1325
1402
PARSE_OPT_OPTARG , opt_parse_porcelain },
1403
+ { OPTION_CALLBACK , 0 , "serialize" , & status_format ,
1404
+ N_ ("version" ), N_ ("serialize raw status data to stdout" ),
1405
+ PARSE_OPT_OPTARG | PARSE_OPT_NONEG , opt_parse_serialize },
1406
+ { OPTION_CALLBACK , 0 , "deserialize" , NULL ,
1407
+ N_ ("path" ), N_ ("deserialize raw status data from file" ),
1408
+ PARSE_OPT_OPTARG , opt_parse_deserialize },
1326
1409
OPT_SET_INT (0 , "long" , & status_format ,
1327
1410
N_ ("show status in long format (default)" ),
1328
1411
STATUS_FORMAT_LONG ),
@@ -1383,10 +1466,26 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1383
1466
s .show_untracked_files == SHOW_NO_UNTRACKED_FILES )
1384
1467
die (_ ("Unsupported combination of ignored and untracked-files arguments" ));
1385
1468
1469
+ if (s .show_untracked_files == SHOW_COMPLETE_UNTRACKED_FILES &&
1470
+ s .show_ignored_mode == SHOW_NO_IGNORED )
1471
+ die (_ ("Complete Untracked only supported with ignored files" ));
1472
+
1386
1473
parse_pathspec (& s .pathspec , 0 ,
1387
1474
PATHSPEC_PREFER_FULL ,
1388
1475
prefix , argv );
1389
1476
1477
+ /*
1478
+ * If we want to try to deserialize status data from a cache file,
1479
+ * we need to re-order the initialization code. The problem is that
1480
+ * this makes for a very nasty diff and causes merge conflicts as we
1481
+ * carry it forward. And it easy to mess up the merge, so we
1482
+ * duplicate some code here to hopefully reduce conflicts.
1483
+ */
1484
+ try_deserialize = (!do_serialize &&
1485
+ (do_implicit_deserialize || do_explicit_deserialize ));
1486
+ if (try_deserialize )
1487
+ goto skip_init ;
1488
+
1390
1489
enable_fscache (0 );
1391
1490
if (status_format != STATUS_FORMAT_PORCELAIN &&
1392
1491
status_format != STATUS_FORMAT_PORCELAIN_V2 )
@@ -1401,6 +1500,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1401
1500
else
1402
1501
fd = -1 ;
1403
1502
1503
+ skip_init :
1404
1504
s .is_initial = get_oid (s .reference , & oid ) ? 1 : 0 ;
1405
1505
if (!s .is_initial )
1406
1506
hashcpy (s .sha1_commit , oid .hash );
@@ -1417,6 +1517,24 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1417
1517
s .rename_score = parse_rename_score (& rename_score_arg );
1418
1518
}
1419
1519
1520
+ if (try_deserialize ) {
1521
+ if (s .relative_paths )
1522
+ s .prefix = prefix ;
1523
+
1524
+ if (wt_status_deserialize (& s , deserialize_path ) == DESERIALIZE_OK )
1525
+ return 0 ;
1526
+
1527
+ /* deserialize failed, so force the initialization we skipped above. */
1528
+ enable_fscache (1 );
1529
+ read_cache_preload (& s .pathspec );
1530
+ refresh_index (& the_index , REFRESH_QUIET |REFRESH_UNMERGED , & s .pathspec , NULL , NULL );
1531
+
1532
+ if (use_optional_locks ())
1533
+ fd = hold_locked_index (& index_lock , 0 );
1534
+ else
1535
+ fd = -1 ;
1536
+ }
1537
+
1420
1538
wt_status_collect (& s );
1421
1539
1422
1540
if (0 <= fd )
0 commit comments