@@ -24,6 +24,9 @@ static const char * const git_stash_helper_usage[] = {
24
24
N_ ("git stash--helper ( pop | apply ) [--index] [-q|--quiet] [<stash>]" ),
25
25
N_ ("git stash--helper branch <branchname> [<stash>]" ),
26
26
N_ ("git stash--helper clear" ),
27
+ N_ ("git stash--helper [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
28
+ " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
29
+ " [--] [<pathspec>...]]" ),
27
30
NULL
28
31
};
29
32
@@ -72,6 +75,13 @@ static const char * const git_stash_helper_create_usage[] = {
72
75
NULL
73
76
};
74
77
78
+ static const char * const git_stash_helper_push_usage [] = {
79
+ N_ ("git stash--helper [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
80
+ " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
81
+ " [--] [<pathspec>...]]" ),
82
+ NULL
83
+ };
84
+
75
85
static const char * ref_stash = "refs/stash" ;
76
86
static struct strbuf stash_index_path = STRBUF_INIT ;
77
87
@@ -1090,7 +1100,7 @@ static int stash_working_tree(struct stash_info *info, struct pathspec ps)
1090
1100
1091
1101
static int do_create_stash (struct pathspec ps , struct strbuf * stash_msg_buf ,
1092
1102
int include_untracked , int patch_mode ,
1093
- struct stash_info * info )
1103
+ struct stash_info * info , struct strbuf * patch )
1094
1104
{
1095
1105
int ret = 0 ;
1096
1106
int flags = 0 ;
@@ -1103,7 +1113,6 @@ static int do_create_stash(struct pathspec ps, struct strbuf *stash_msg_buf,
1103
1113
struct strbuf msg = STRBUF_INIT ;
1104
1114
struct strbuf commit_tree_label = STRBUF_INIT ;
1105
1115
struct strbuf untracked_files = STRBUF_INIT ;
1106
- struct strbuf patch = STRBUF_INIT ;
1107
1116
1108
1117
prepare_fallback_ident ("git stash" , "git@stash" );
1109
1118
@@ -1152,7 +1161,7 @@ static int do_create_stash(struct pathspec ps, struct strbuf *stash_msg_buf,
1152
1161
untracked_commit_option = 1 ;
1153
1162
}
1154
1163
if (patch_mode ) {
1155
- ret = stash_patch (info , ps , & patch );
1164
+ ret = stash_patch (info , ps , patch );
1156
1165
if (ret < 0 ) {
1157
1166
fprintf_ln (stderr , _ ("Cannot save the current "
1158
1167
"worktree state" ));
@@ -1223,7 +1232,8 @@ static int create_stash(int argc, const char **argv, const char *prefix)
1223
1232
1224
1233
memset (& ps , 0 , sizeof (ps ));
1225
1234
strbuf_addstr (& stash_msg_buf , stash_msg );
1226
- ret = do_create_stash (ps , & stash_msg_buf , include_untracked , 0 , & info );
1235
+ ret = do_create_stash (ps , & stash_msg_buf , include_untracked , 0 , & info ,
1236
+ NULL );
1227
1237
if (!ret )
1228
1238
printf_ln ("%s" , oid_to_hex (& info .w_commit ));
1229
1239
@@ -1236,6 +1246,232 @@ static int create_stash(int argc, const char **argv, const char *prefix)
1236
1246
return ret < 0 ;
1237
1247
}
1238
1248
1249
+ static int do_push_stash (struct pathspec ps , const char * stash_msg , int quiet ,
1250
+ int keep_index , int patch_mode , int include_untracked )
1251
+ {
1252
+ int ret = 0 ;
1253
+ struct stash_info info ;
1254
+ struct strbuf patch = STRBUF_INIT ;
1255
+ struct strbuf stash_msg_buf = STRBUF_INIT ;
1256
+
1257
+ if (patch_mode && keep_index == -1 )
1258
+ keep_index = 1 ;
1259
+
1260
+ if (patch_mode && include_untracked ) {
1261
+ fprintf_ln (stderr , _ ("Can't use --patch and --include-untracked"
1262
+ " or --all at the same time" ));
1263
+ ret = -1 ;
1264
+ goto done ;
1265
+ }
1266
+
1267
+ read_cache_preload (NULL );
1268
+ if (!include_untracked && ps .nr ) {
1269
+ int i ;
1270
+ char * ps_matched = xcalloc (ps .nr , 1 );
1271
+
1272
+ for (i = 0 ; i < active_nr ; i ++ )
1273
+ ce_path_match (& the_index , active_cache [i ], & ps ,
1274
+ ps_matched );
1275
+
1276
+ if (report_path_error (ps_matched , & ps , NULL )) {
1277
+ fprintf_ln (stderr , _ ("Did you forget to 'git add'?" ));
1278
+ ret = -1 ;
1279
+ free (ps_matched );
1280
+ goto done ;
1281
+ }
1282
+ free (ps_matched );
1283
+ }
1284
+
1285
+ if (refresh_cache (REFRESH_QUIET )) {
1286
+ ret = -1 ;
1287
+ goto done ;
1288
+ }
1289
+
1290
+ if (!check_changes (ps , include_untracked )) {
1291
+ if (!quiet )
1292
+ printf_ln (_ ("No local changes to save" ));
1293
+ goto done ;
1294
+ }
1295
+
1296
+ if (!reflog_exists (ref_stash ) && do_clear_stash ()) {
1297
+ ret = -1 ;
1298
+ fprintf_ln (stderr , _ ("Cannot initialize stash" ));
1299
+ goto done ;
1300
+ }
1301
+
1302
+ if (stash_msg )
1303
+ strbuf_addstr (& stash_msg_buf , stash_msg );
1304
+ if (do_create_stash (ps , & stash_msg_buf , include_untracked , patch_mode ,
1305
+ & info , & patch )) {
1306
+ ret = -1 ;
1307
+ goto done ;
1308
+ }
1309
+
1310
+ if (do_store_stash (& info .w_commit , stash_msg_buf .buf , 1 )) {
1311
+ ret = -1 ;
1312
+ fprintf_ln (stderr , _ ("Cannot save the current status" ));
1313
+ goto done ;
1314
+ }
1315
+
1316
+ printf_ln (_ ("Saved working directory and index state %s" ),
1317
+ stash_msg_buf .buf );
1318
+
1319
+ if (!patch_mode ) {
1320
+ if (include_untracked && !ps .nr ) {
1321
+ struct child_process cp = CHILD_PROCESS_INIT ;
1322
+
1323
+ cp .git_cmd = 1 ;
1324
+ argv_array_pushl (& cp .args , "clean" , "--force" ,
1325
+ "--quiet" , "-d" , NULL );
1326
+ if (include_untracked == INCLUDE_ALL_FILES )
1327
+ argv_array_push (& cp .args , "-x" );
1328
+ if (run_command (& cp )) {
1329
+ ret = -1 ;
1330
+ goto done ;
1331
+ }
1332
+ }
1333
+ discard_cache ();
1334
+ if (ps .nr ) {
1335
+ struct child_process cp_add = CHILD_PROCESS_INIT ;
1336
+ struct child_process cp_diff = CHILD_PROCESS_INIT ;
1337
+ struct child_process cp_apply = CHILD_PROCESS_INIT ;
1338
+ struct strbuf out = STRBUF_INIT ;
1339
+
1340
+ cp_add .git_cmd = 1 ;
1341
+ argv_array_push (& cp_add .args , "add" );
1342
+ if (!include_untracked )
1343
+ argv_array_push (& cp_add .args , "-u" );
1344
+ if (include_untracked == INCLUDE_ALL_FILES )
1345
+ argv_array_push (& cp_add .args , "--force" );
1346
+ argv_array_push (& cp_add .args , "--" );
1347
+ add_pathspecs (& cp_add .args , ps );
1348
+ if (run_command (& cp_add )) {
1349
+ ret = -1 ;
1350
+ goto done ;
1351
+ }
1352
+
1353
+ cp_diff .git_cmd = 1 ;
1354
+ argv_array_pushl (& cp_diff .args , "diff-index" , "-p" ,
1355
+ "--cached" , "--binary" , "HEAD" , "--" ,
1356
+ NULL );
1357
+ add_pathspecs (& cp_diff .args , ps );
1358
+ if (pipe_command (& cp_diff , NULL , 0 , & out , 0 , NULL , 0 )) {
1359
+ ret = -1 ;
1360
+ goto done ;
1361
+ }
1362
+
1363
+ cp_apply .git_cmd = 1 ;
1364
+ argv_array_pushl (& cp_apply .args , "apply" , "--index" ,
1365
+ "-R" , NULL );
1366
+ if (pipe_command (& cp_apply , out .buf , out .len , NULL , 0 ,
1367
+ NULL , 0 )) {
1368
+ ret = -1 ;
1369
+ goto done ;
1370
+ }
1371
+ } else {
1372
+ struct child_process cp = CHILD_PROCESS_INIT ;
1373
+ cp .git_cmd = 1 ;
1374
+ argv_array_pushl (& cp .args , "reset" , "--hard" , "-q" ,
1375
+ NULL );
1376
+ if (run_command (& cp )) {
1377
+ ret = -1 ;
1378
+ goto done ;
1379
+ }
1380
+ }
1381
+
1382
+ if (keep_index == 1 && !is_null_oid (& info .i_tree )) {
1383
+ struct child_process cp_ls = CHILD_PROCESS_INIT ;
1384
+ struct child_process cp_checkout = CHILD_PROCESS_INIT ;
1385
+ struct strbuf out = STRBUF_INIT ;
1386
+
1387
+ if (reset_tree (& info .i_tree , 0 , 1 )) {
1388
+ ret = -1 ;
1389
+ goto done ;
1390
+ }
1391
+
1392
+ cp_ls .git_cmd = 1 ;
1393
+ argv_array_pushl (& cp_ls .args , "ls-files" , "-z" ,
1394
+ "--modified" , "--" , NULL );
1395
+
1396
+ add_pathspecs (& cp_ls .args , ps );
1397
+ if (pipe_command (& cp_ls , NULL , 0 , & out , 0 , NULL , 0 )) {
1398
+ ret = -1 ;
1399
+ goto done ;
1400
+ }
1401
+
1402
+ cp_checkout .git_cmd = 1 ;
1403
+ argv_array_pushl (& cp_checkout .args , "checkout-index" ,
1404
+ "-z" , "--force" , "--stdin" , NULL );
1405
+ if (pipe_command (& cp_checkout , out .buf , out .len , NULL ,
1406
+ 0 , NULL , 0 )) {
1407
+ ret = -1 ;
1408
+ goto done ;
1409
+ }
1410
+ }
1411
+ goto done ;
1412
+ } else {
1413
+ struct child_process cp = CHILD_PROCESS_INIT ;
1414
+
1415
+ cp .git_cmd = 1 ;
1416
+ argv_array_pushl (& cp .args , "apply" , "-R" , NULL );
1417
+
1418
+ if (pipe_command (& cp , patch .buf , patch .len , NULL , 0 , NULL , 0 )) {
1419
+ fprintf_ln (stderr , _ ("Cannot remove worktree changes" ));
1420
+ ret = -1 ;
1421
+ goto done ;
1422
+ }
1423
+
1424
+ if (keep_index < 1 ) {
1425
+ struct child_process cp = CHILD_PROCESS_INIT ;
1426
+
1427
+ cp .git_cmd = 1 ;
1428
+ argv_array_pushl (& cp .args , "reset" , "-q" , "--" , NULL );
1429
+ add_pathspecs (& cp .args , ps );
1430
+ if (run_command (& cp )) {
1431
+ ret = -1 ;
1432
+ goto done ;
1433
+ }
1434
+ }
1435
+ goto done ;
1436
+ }
1437
+
1438
+ done :
1439
+ strbuf_release (& stash_msg_buf );
1440
+ return ret ;
1441
+ }
1442
+
1443
+ static int push_stash (int argc , const char * * argv , const char * prefix )
1444
+ {
1445
+ int keep_index = -1 ;
1446
+ int patch_mode = 0 ;
1447
+ int include_untracked = 0 ;
1448
+ int quiet = 0 ;
1449
+ const char * stash_msg = NULL ;
1450
+ struct pathspec ps ;
1451
+ struct option options [] = {
1452
+ OPT_BOOL ('k' , "keep-index" , & keep_index ,
1453
+ N_ ("keep index" )),
1454
+ OPT_BOOL ('p' , "patch" , & patch_mode ,
1455
+ N_ ("stash in patch mode" )),
1456
+ OPT__QUIET (& quiet , N_ ("quiet mode" )),
1457
+ OPT_BOOL ('u' , "include-untracked" , & include_untracked ,
1458
+ N_ ("include untracked files in stash" )),
1459
+ OPT_SET_INT ('a' , "all" , & include_untracked ,
1460
+ N_ ("include ignore files" ), 2 ),
1461
+ OPT_STRING ('m' , "message" , & stash_msg , N_ ("message" ),
1462
+ N_ ("stash message" )),
1463
+ OPT_END ()
1464
+ };
1465
+
1466
+ argc = parse_options (argc , argv , prefix , options ,
1467
+ git_stash_helper_push_usage ,
1468
+ 0 );
1469
+
1470
+ parse_pathspec (& ps , 0 , PATHSPEC_PREFER_FULL , prefix , argv );
1471
+ return do_push_stash (ps , stash_msg , quiet , keep_index , patch_mode ,
1472
+ include_untracked );
1473
+ }
1474
+
1239
1475
int cmd_stash__helper (int argc , const char * * argv , const char * prefix )
1240
1476
{
1241
1477
pid_t pid = getpid ();
@@ -1274,6 +1510,8 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
1274
1510
return !!store_stash (argc , argv , prefix );
1275
1511
else if (!strcmp (argv [0 ], "create" ))
1276
1512
return !!create_stash (argc , argv , prefix );
1513
+ else if (!strcmp (argv [0 ], "push" ))
1514
+ return !!push_stash (argc , argv , prefix );
1277
1515
1278
1516
usage_msg_opt (xstrfmt (_ ("unknown subcommand: %s" ), argv [0 ]),
1279
1517
git_stash_helper_usage , options );
0 commit comments