diff options
Diffstat (limited to 'builtin/stash.c')
| -rw-r--r-- | builtin/stash.c | 80 | 
1 files changed, 71 insertions, 9 deletions
diff --git a/builtin/stash.c b/builtin/stash.c index a0ccc8654d..18c812bbe0 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -27,11 +27,11 @@ static const char * const git_stash_usage[] = {  	N_("git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]"),  	N_("git stash branch <branchname> [<stash>]"),  	"git stash clear", -	N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" +	N_("git stash [push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--quiet]\n"  	   "          [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"  	   "          [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"  	   "          [--] [<pathspec>...]]"), -	N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" +	N_("git stash save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--quiet]\n"  	   "          [-u|--include-untracked] [-a|--all] [<message>]"),  	NULL  }; @@ -1132,6 +1132,38 @@ done:  	return ret;  } +static int stash_staged(struct stash_info *info, struct strbuf *out_patch, +			int quiet) +{ +	int ret = 0; +	struct child_process cp_diff_tree = CHILD_PROCESS_INIT; +	struct index_state istate = { NULL }; + +	if (write_index_as_tree(&info->w_tree, &istate, the_repository->index_file, +				0, NULL)) { +		ret = -1; +		goto done; +	} + +	cp_diff_tree.git_cmd = 1; +	strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD", +		     oid_to_hex(&info->w_tree), "--", NULL); +	if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) { +		ret = -1; +		goto done; +	} + +	if (!out_patch->len) { +		if (!quiet) +			fprintf_ln(stderr, _("No staged changes")); +		ret = 1; +	} + +done: +	discard_index(&istate); +	return ret; +} +  static int stash_patch(struct stash_info *info, const struct pathspec *ps,  		       struct strbuf *out_patch, int quiet)  { @@ -1258,7 +1290,7 @@ done:  }  static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_buf, -			   int include_untracked, int patch_mode, +			   int include_untracked, int patch_mode, int only_staged,  			   struct stash_info *info, struct strbuf *patch,  			   int quiet)  { @@ -1337,6 +1369,16 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b  		} else if (ret > 0) {  			goto done;  		} +	} else if (only_staged) { +		ret = stash_staged(info, patch, quiet); +		if (ret < 0) { +			if (!quiet) +				fprintf_ln(stderr, _("Cannot save the current " +						     "staged state")); +			goto done; +		} else if (ret > 0) { +			goto done; +		}  	} else {  		if (stash_working_tree(info, ps)) {  			if (!quiet) @@ -1395,7 +1437,7 @@ static int create_stash(int argc, const char **argv, const char *prefix)  	if (!check_changes_tracked_files(&ps))  		return 0; -	ret = do_create_stash(&ps, &stash_msg_buf, 0, 0, &info, +	ret = do_create_stash(&ps, &stash_msg_buf, 0, 0, 0, &info,  			      NULL, 0);  	if (!ret)  		printf_ln("%s", oid_to_hex(&info.w_commit)); @@ -1405,7 +1447,7 @@ static int create_stash(int argc, const char **argv, const char *prefix)  }  static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int quiet, -			 int keep_index, int patch_mode, int include_untracked) +			 int keep_index, int patch_mode, int include_untracked, int only_staged)  {  	int ret = 0;  	struct stash_info info; @@ -1423,6 +1465,17 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q  		goto done;  	} +	/* --patch overrides --staged */ +	if (patch_mode) +		only_staged = 0; + +	if (only_staged && include_untracked) { +		fprintf_ln(stderr, _("Can't use --staged and --include-untracked" +				     " or --all at the same time")); +		ret = -1; +		goto done; +	} +  	read_cache_preload(NULL);  	if (!include_untracked && ps->nr) {  		int i; @@ -1463,7 +1516,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q  	if (stash_msg)  		strbuf_addstr(&stash_msg_buf, stash_msg); -	if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode, +	if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode, only_staged,  			    &info, &patch, quiet)) {  		ret = -1;  		goto done; @@ -1480,7 +1533,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q  		printf_ln(_("Saved working directory and index state %s"),  			  stash_msg_buf.buf); -	if (!patch_mode) { +	if (!(patch_mode || only_staged)) {  		if (include_untracked && !ps->nr) {  			struct child_process cp = CHILD_PROCESS_INIT; @@ -1598,6 +1651,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,  {  	int force_assume = 0;  	int keep_index = -1; +	int only_staged = 0;  	int patch_mode = 0;  	int include_untracked = 0;  	int quiet = 0; @@ -1608,6 +1662,8 @@ static int push_stash(int argc, const char **argv, const char *prefix,  	struct option options[] = {  		OPT_BOOL('k', "keep-index", &keep_index,  			 N_("keep index")), +		OPT_BOOL('S', "staged", &only_staged, +			 N_("stash staged changes only")),  		OPT_BOOL('p', "patch", &patch_mode,  			 N_("stash in patch mode")),  		OPT__QUIET(&quiet, N_("quiet mode")), @@ -1646,6 +1702,9 @@ static int push_stash(int argc, const char **argv, const char *prefix,  		if (patch_mode)  			die(_("--pathspec-from-file is incompatible with --patch")); +		if (only_staged) +			die(_("--pathspec-from-file is incompatible with --staged")); +  		if (ps.nr)  			die(_("--pathspec-from-file is incompatible with pathspec arguments")); @@ -1657,12 +1716,13 @@ static int push_stash(int argc, const char **argv, const char *prefix,  	}  	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode, -			     include_untracked); +			     include_untracked, only_staged);  }  static int save_stash(int argc, const char **argv, const char *prefix)  {  	int keep_index = -1; +	int only_staged = 0;  	int patch_mode = 0;  	int include_untracked = 0;  	int quiet = 0; @@ -1673,6 +1733,8 @@ static int save_stash(int argc, const char **argv, const char *prefix)  	struct option options[] = {  		OPT_BOOL('k', "keep-index", &keep_index,  			 N_("keep index")), +		OPT_BOOL('S', "staged", &only_staged, +			 N_("stash staged changes only")),  		OPT_BOOL('p', "patch", &patch_mode,  			 N_("stash in patch mode")),  		OPT__QUIET(&quiet, N_("quiet mode")), @@ -1694,7 +1756,7 @@ static int save_stash(int argc, const char **argv, const char *prefix)  	memset(&ps, 0, sizeof(ps));  	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, -			    patch_mode, include_untracked); +			    patch_mode, include_untracked, only_staged);  	strbuf_release(&stash_msg_buf);  	return ret;  | 
