git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GSoC] [PATCH 0/6] builtin rebase rest
@ 2018-08-08 15:36 Pratik Karki
  2018-08-08 15:36 ` [PATCH 1/6] builtin rebase: optionally auto-detect the upstream Pratik Karki
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

This patch pretty much converts all what is remaining from the shell-script
version of `git rebase` to the builtin version. After the conversion of
actions and different options which are important for builtin rebase and have
been organized to make a patch series of their own. There were still some
leftover shell scripts on the original rebase and hence, this patch series
addresses those by converting them and this completes the builtin rebase.

It adds the functionality to the previous patch series,
(https://public-inbox.org/git/20180808152140.14585-1-predatoramigo@gmail.com/).

This is the fifth patch series that brings us more closer to a builtin
"git rebase".

If you like to view the development branch, you can view
(https://github.com/git/git/pull/505), where I have kept my commits up to date
and leveraged Travis(there is sporadic failures in t5520 for macos gcc and
isn't due to my patches) for extra testing other than my system.

The next in line patch series which I'll be sending out today are:

default to builtin rebase: This will turn on the feature-complete builtin
rebase to on.

These patch series are built on top of each other, i.e. they depend on this
order.

Pratik Karki (6):
  builtin rebase: optionally auto-detect the upstream
  builtin rebase: optionally pass custom reflogs to reset_head()
  builtin rebase: fast-forward to onto if it is a proper descendant
  builtin rebase: show progress when connected to a terminal
  builtin rebase: use no-op editor when interactive is "implied"
  builtin rebase: error out on incompatible option/mode combinations

 builtin/rebase.c | 150 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 135 insertions(+), 15 deletions(-)

-- 
2.18.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/6] builtin rebase: optionally auto-detect the upstream
  2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
@ 2018-08-08 15:36 ` Pratik Karki
  2018-08-08 15:36 ` [PATCH 2/6] builtin rebase: optionally pass custom reflogs to reset_head() Pratik Karki
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

The `git rebase` command, when called without the `<upstream>`
command-line argument, automatically looks for the upstream
branch configured for the current branch.

With this commit, the builtin rebase learned that trick, too.

Signed-off-by: Pratik Karki <predatoramigo@gmail.com>
---
 builtin/rebase.c | 44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 94abaaa890..c5b2534717 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -622,6 +622,36 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
 	return 0;
 }
 
+static void NORETURN error_on_missing_default_upstream(void)
+{
+	struct branch *current_branch = branch_get(NULL);
+
+	printf(_("%s\n"
+		 "Please specify which branch you want to rebase against.\n"
+		 "See git-rebase(1) for details.\n"
+		 "\n"
+		 "    git rebase '<branch>'\n"
+		 "\n"),
+		current_branch ? _("There is no tracking information for "
+			"the current branch.") :
+			_("You are not currently on a branch."));
+
+	if (current_branch) {
+		const char *remote = current_branch->remote_name;
+
+		if (!remote)
+			remote = _("<remote>");
+
+		printf(_("If you wish to set tracking information for this "
+			 "branch you can do so with:\n"
+			 "\n"
+			 "    git branch --set-upstream-to=%s/<branch> %s\n"
+			 "\n"),
+		       remote, current_branch->name);
+	}
+	exit(1);
+}
+
 int cmd_rebase(int argc, const char **argv, const char *prefix)
 {
 	struct rebase_options options = {
@@ -1056,9 +1086,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	if (!options.root) {
-		if (argc < 1)
-			die("TODO: handle @{upstream}");
-		else {
+		if (argc < 1) {
+			struct branch *branch;
+
+			branch = branch_get(NULL);
+			options.upstream_name = branch_get_upstream(branch,
+								    NULL);
+			if (!options.upstream_name)
+				error_on_missing_default_upstream();
+			if (fork_point < 0)
+				fork_point = 1;
+		} else {
 			options.upstream_name = argv[0];
 			argc--;
 			argv++;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] builtin rebase: optionally pass custom reflogs to reset_head()
  2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
  2018-08-08 15:36 ` [PATCH 1/6] builtin rebase: optionally auto-detect the upstream Pratik Karki
@ 2018-08-08 15:36 ` Pratik Karki
  2018-08-08 15:36 ` [PATCH 3/6] builtin rebase: fast-forward to onto if it is a proper descendant Pratik Karki
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

In the next patch, we will make use of that in the code that
fast-forwards to `onto` whenever possible.

Signed-off-by: Pratik Karki <predatoramigo@gmail.com>
---
 builtin/rebase.c | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index c5b2534717..c51b9d288a 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -431,7 +431,8 @@ static int run_specific_rebase(struct rebase_options *opts)
 #define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
 
 static int reset_head(struct object_id *oid, const char *action,
-		      const char *switch_to_branch, int detach_head)
+		      const char *switch_to_branch, int detach_head,
+		      const char *reflog_orig_head, const char *reflog_head)
 {
 	struct object_id head_oid;
 	struct tree_desc desc;
@@ -506,20 +507,26 @@ static int reset_head(struct object_id *oid, const char *action,
 		old_orig = &oid_old_orig;
 	if (!get_oid("HEAD", &oid_orig)) {
 		orig = &oid_orig;
-		strbuf_addstr(&msg, "updating ORIG_HEAD");
-		update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
+		if (!reflog_orig_head) {
+			strbuf_addstr(&msg, "updating ORIG_HEAD");
+			reflog_orig_head = msg.buf;
+		}
+		update_ref(reflog_orig_head, "ORIG_HEAD", orig, old_orig, 0,
 			   UPDATE_REFS_MSG_ON_ERR);
 	} else if (old_orig)
 		delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
-	strbuf_setlen(&msg, prefix_len);
-	strbuf_addstr(&msg, "updating HEAD");
+	if (!reflog_head) {
+		strbuf_setlen(&msg, prefix_len);
+		strbuf_addstr(&msg, "updating HEAD");
+		reflog_head = msg.buf;
+	}
 	if (!switch_to_branch)
-		ret = update_ref(msg.buf, "HEAD", oid, orig, REF_NO_DEREF,
+		ret = update_ref(reflog_head, "HEAD", oid, orig, REF_NO_DEREF,
 				 UPDATE_REFS_MSG_ON_ERR);
 	else {
 		ret = create_symref("HEAD", switch_to_branch, msg.buf);
 		if (!ret)
-			ret = update_ref(msg.buf, "HEAD", oid, NULL, 0,
+			ret = update_ref(reflog_head, "HEAD", oid, NULL, 0,
 					 UPDATE_REFS_MSG_ON_ERR);
 	}
 
@@ -899,7 +906,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		rerere_clear(&merge_rr);
 		string_list_clear(&merge_rr, 1);
 
-		if (reset_head(NULL, "reset", NULL, 0) < 0)
+		if (reset_head(NULL, "reset", NULL, 0, NULL, NULL) < 0)
 			die(_("could not discard worktree changes"));
 		if (read_basic_state(&options))
 			exit(1);
@@ -915,7 +922,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (read_basic_state(&options))
 			exit(1);
 		if (reset_head(&options.orig_head, "reset",
-			       options.head_name, 0) < 0)
+			       options.head_name, 0, NULL, NULL) < 0)
 			die(_("could not move back to %s"),
 			    oid_to_hex(&options.orig_head));
 		ret = finish_rebase(&options);
@@ -1235,7 +1242,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			write_file(autostash, "%s", buf.buf);
 			printf(_("Created autostash: %s\n"), buf.buf);
 			if (reset_head(&head->object.oid, "reset --hard",
-				       NULL, 0) < 0)
+				       NULL, 0, NULL, NULL) < 0)
 				die(_("could not reset --hard"));
 			printf(_("HEAD is now at %s"),
 			       find_unique_abbrev(&head->object.oid,
@@ -1289,7 +1296,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				strbuf_addf(&buf, "rebase: checkout %s",
 					    options.switch_to);
 				if (reset_head(&oid, "checkout",
-					       options.head_name, 0) < 0) {
+					       options.head_name, 0,
+					       NULL, NULL) < 0) {
 					ret = !!error(_("could not switch to "
 							"%s"),
 						      options.switch_to);
@@ -1354,7 +1362,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			 "it...\n"));
 
 	strbuf_addf(&msg, "rebase: checkout %s", options.onto_name);
-	if (reset_head(&options.onto->object.oid, "checkout", NULL, 1))
+	if (reset_head(&options.onto->object.oid, "checkout", NULL, 1,
+	    NULL, msg.buf))
 		die(_("Could not detach HEAD"));
 	strbuf_release(&msg);
 
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] builtin rebase: fast-forward to onto if it is a proper descendant
  2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
  2018-08-08 15:36 ` [PATCH 1/6] builtin rebase: optionally auto-detect the upstream Pratik Karki
  2018-08-08 15:36 ` [PATCH 2/6] builtin rebase: optionally pass custom reflogs to reset_head() Pratik Karki
@ 2018-08-08 15:36 ` Pratik Karki
  2018-08-08 15:36 ` [PATCH 4/6] builtin rebase: show progress when connected to a terminal Pratik Karki
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

When trying to rebase onto a direct descendant of HEAD, we can
take a shortcut and fast-forward instead. This commit makes it so.

Signed-off-by: Pratik Karki <predatoramigo@gmail.com>
---
 builtin/rebase.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index c51b9d288a..1bb64e7cd7 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1367,6 +1367,24 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		die(_("Could not detach HEAD"));
 	strbuf_release(&msg);
 
+	/*
+	 * If the onto is a proper descendant of the tip of the branch, then
+	 * we just fast-forwarded.
+	 */
+	strbuf_reset(&msg);
+	if (!oidcmp(&merge_base, &options.orig_head)) {
+		printf(_("Fast-forwarded %s to %s. \n"),
+			branch_name, options.onto_name);
+		strbuf_addf(&msg, "rebase finished: %s onto %s",
+			options.head_name ? options.head_name : "detached HEAD",
+			oid_to_hex(&options.onto->object.oid));
+		reset_head(NULL, "Fast-forwarded", options.head_name, 0,
+			   "HEAD", msg.buf);
+		strbuf_release(&msg);
+		ret = !!finish_rebase(&options);
+		goto cleanup;
+	}
+
 	strbuf_addf(&revisions, "%s..%s",
 		    options.root ? oid_to_hex(&options.onto->object.oid) :
 		    (options.restrict_revision ?
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] builtin rebase: show progress when connected to a terminal
  2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
                   ` (2 preceding siblings ...)
  2018-08-08 15:36 ` [PATCH 3/6] builtin rebase: fast-forward to onto if it is a proper descendant Pratik Karki
@ 2018-08-08 15:36 ` Pratik Karki
  2018-08-08 15:36 ` [PATCH 5/6] builtin rebase: use no-op editor when interactive is "implied" Pratik Karki
  2018-08-08 15:36 ` [PATCH 6/6] builtin rebase: error out on incompatible option/mode combinations Pratik Karki
  5 siblings, 0 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

In this commit, we pass `--progress` to the `format-patch` command if
stderr is connected to an interactive terminal, unless we're in quiet
mode.

This `--progress` option will be used in `format-patch` to show progress
reports on stderr as patches are generated.

Signed-off-by: Pratik Karki <predatoramigo@gmail.com>
---
 builtin/rebase.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 1bb64e7cd7..04974dff6e 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -98,6 +98,7 @@ struct rebase_options {
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
 	char *strategy, *strategy_opts;
+	struct strbuf git_format_patch_opt;
 };
 
 static int is_interactive(struct rebase_options *opts)
@@ -379,6 +380,8 @@ static int run_specific_rebase(struct rebase_options *opts)
 	add_var(&script_snippet, "rebase_root", opts->root ? "t" : "");
 	add_var(&script_snippet, "squash_onto",
 		opts->squash_onto ? oid_to_hex(opts->squash_onto) : "");
+	add_var(&script_snippet, "git_format_patch_opt",
+		opts->git_format_patch_opt.buf);
 
 	switch (opts->type) {
 	case REBASE_AM:
@@ -667,6 +670,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		.git_am_opt = STRBUF_INIT,
 		.allow_rerere_autoupdate  = -1,
 		.allow_empty_message = 1,
+		.git_format_patch_opt = STRBUF_INIT,
 	};
 	const char *branch_name;
 	int ret, flags, total_argc, in_progress = 0;
@@ -1068,6 +1072,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	if (options.root && !options.onto_name)
 		imply_interactive(&options, "--root without --onto");
 
+	if (isatty(2) && options.flags & REBASE_NO_QUIET)
+		strbuf_addstr(&options.git_format_patch_opt, " --progress");
+
 	switch (options.type) {
 	case REBASE_MERGE:
 	case REBASE_INTERACTIVE:
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] builtin rebase: use no-op editor when interactive is "implied"
  2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
                   ` (3 preceding siblings ...)
  2018-08-08 15:36 ` [PATCH 4/6] builtin rebase: show progress when connected to a terminal Pratik Karki
@ 2018-08-08 15:36 ` Pratik Karki
  2018-08-08 15:36 ` [PATCH 6/6] builtin rebase: error out on incompatible option/mode combinations Pratik Karki
  5 siblings, 0 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

Some options are only handled by the git-rebase--interactive backend,
even if run non-interactively. For this awkward situation (run
non-interactively, but use the interactive backend), the shell scripted
version of `git rebase` introduced the concept of an "implied
interactive rebase". All it does is to replace the editor by a dummy one
(`:` is the Unix command that takes arbitrary command-line parameters,
ignores them and simply exits with success).

Signed-off-by: Pratik Karki <predatoramigo@gmail.com>
---
 builtin/rebase.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 04974dff6e..fb8ab5a177 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -383,6 +383,13 @@ static int run_specific_rebase(struct rebase_options *opts)
 	add_var(&script_snippet, "git_format_patch_opt",
 		opts->git_format_patch_opt.buf);
 
+	if (is_interactive(opts) &&
+	    !(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
+		strbuf_addstr(&script_snippet,
+			      "GIT_EDITOR=:; export GIT_EDITOR; ");
+		opts->autosquash = 0;
+	}
+
 	switch (opts->type) {
 	case REBASE_AM:
 		backend = "git-rebase--am";
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] builtin rebase: error out on incompatible option/mode combinations
  2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
                   ` (4 preceding siblings ...)
  2018-08-08 15:36 ` [PATCH 5/6] builtin rebase: use no-op editor when interactive is "implied" Pratik Karki
@ 2018-08-08 15:36 ` Pratik Karki
  5 siblings, 0 replies; 7+ messages in thread
From: Pratik Karki @ 2018-08-08 15:36 UTC (permalink / raw)
  To: git
  Cc: christian.couder, Johannes.Schindelin, sbeller, alban.gruin,
	gitster, Pratik Karki

While working on the GSoC project to convert the rebase command to a
builtin, the rebase command learned to error out on certain command-line
option combinations that cannot work, such as --whitespace=fix with
--interactive.

This commit converts that code.

Signed-off-by: Pratik Karki <predatoramigo@gmail.com>
---
 builtin/rebase.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index fb8ab5a177..4e69458161 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1098,6 +1098,28 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		break;
 	}
 
+	if (options.git_am_opt.len) {
+		const char *p;
+
+		/* all am options except -q are compatible only with --am */
+		strbuf_reset(&buf);
+		strbuf_addbuf(&buf, &options.git_am_opt);
+		strbuf_addch(&buf, ' ');
+		while ((p = strstr(buf.buf, " -q ")))
+			strbuf_splice(&buf, p - buf.buf, 4, " ", 1);
+		strbuf_trim(&buf);
+
+		if (is_interactive(&options) && buf.len)
+			die(_("error: cannot combine interactive options "
+			      "(--interactive, --exec, --rebase-merges, "
+			      "--preserve-merges, --keep-empty, --root + "
+			      "--onto) with am options (%s)"), buf.buf);
+		if (options.type == REBASE_MERGE && buf.len)
+			die(_("error: cannot combine merge options (--merge, "
+			      "--strategy, --strategy-option) with am options "
+			      "(%s)"), buf.buf);
+	}
+
 	if (options.signoff) {
 		if (options.type == REBASE_PRESERVE_MERGES)
 			die("cannot combine '--signoff' with "
@@ -1106,6 +1128,25 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		options.flags |= REBASE_FORCE;
 	}
 
+	if (options.type == REBASE_PRESERVE_MERGES)
+		/*
+		 * Note: incompatibility with --signoff handled in signoff block above
+		 * Note: incompatibility with --interactive is just a strong warning;
+		 *       git-rebase.txt caveats with "unless you know what you are doing"
+		 */
+		if (options.rebase_merges)
+			die(_("error: cannot combine '--preserve_merges' with "
+			      "'--rebase-merges'"));
+
+	if (options.rebase_merges) {
+		if (strategy_options.nr)
+			die(_("error: cannot combine '--rebase_merges' with "
+			      "'--strategy-option'"));
+		if (options.strategy)
+			die(_("error: cannot combine '--rebase_merges' with "
+			      "'--strategy'"));
+	}
+
 	if (!options.root) {
 		if (argc < 1) {
 			struct branch *branch;
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-08-08 15:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-08 15:36 [GSoC] [PATCH 0/6] builtin rebase rest Pratik Karki
2018-08-08 15:36 ` [PATCH 1/6] builtin rebase: optionally auto-detect the upstream Pratik Karki
2018-08-08 15:36 ` [PATCH 2/6] builtin rebase: optionally pass custom reflogs to reset_head() Pratik Karki
2018-08-08 15:36 ` [PATCH 3/6] builtin rebase: fast-forward to onto if it is a proper descendant Pratik Karki
2018-08-08 15:36 ` [PATCH 4/6] builtin rebase: show progress when connected to a terminal Pratik Karki
2018-08-08 15:36 ` [PATCH 5/6] builtin rebase: use no-op editor when interactive is "implied" Pratik Karki
2018-08-08 15:36 ` [PATCH 6/6] builtin rebase: error out on incompatible option/mode combinations Pratik Karki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).