All of lore.kernel.org
 help / color / mirror / Atom feed
From: Neil Horman <nhorman@tuxdriver.com>
To: git@vger.kernel.org
Cc: Neil Horman <nhorman@tuxdriver.com>, Jeff King <peff@peff.net>,
	Phil Hord <phil.hord@gmail.com>,
	Junio C Hamano <gitster@pobox.com>
Subject: [PATCH 3/5] git-cherry-pick: Add ignore-if-made-empty option [v2]
Date: Thu,  5 Apr 2012 15:39:03 -0400	[thread overview]
Message-ID: <1333654745-7898-4-git-send-email-nhorman@tuxdriver.com> (raw)
In-Reply-To: <1333654745-7898-1-git-send-email-nhorman@tuxdriver.com>

Since we'll be using git-cherry-pick to enhance git-rebase's ability to preserve
empty commits, we open ourselves to the possibility of preserving commits that
are made empty by a previous merge as well, which is almost certainly not what
we want (most of the time).  To handle this, we can add the ignore-if-made-empty
option.  If enabled, it will look at cherry-picked commits, and if the origional
sha1 has the same tree as its parent, then the cherry-pick is comitted as an
empty commit, otherwise the commit is skipped (because it previously made
changes to the tree, but no longer does).

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jeff King <peff@peff.net>
CC: Phil Hord <phil.hord@gmail.com>
CC: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-cherry-pick.txt |   10 +++-
 builtin/revert.c                  |    2 +
 sequencer.c                       |  113 ++++++++++++++++++++++++++++++++-----
 sequencer.h                       |    1 +
 4 files changed, 111 insertions(+), 15 deletions(-)

diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index c283d8c..bb7eb4a 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -103,7 +103,7 @@ effect to your index in a row.
 	cherry-pick'ed commit, then a fast forward to this commit will
 	be performed.
 
---allow-empty:
+--allow-empty:::
 	By default, cherry-picking an empty commit will fail,
 	indicating that an explicit invocation of `git commit
 	--allow-empty` is required. This option overrides that
@@ -112,6 +112,14 @@ effect to your index in a row.
 	commits that meet the "fast-forward" requirement will be kept
 	even without this option.
 
+--ignore-if-made-empty::
+	If the --allow-empty option is used, all empty commits are kept,
+	including those which were made empty due to a previous change.
+	While this may be desireable, likely it is not.  This option
+	restricts the scope of --allow-empty to only those commits which
+	were created as empty commits (i.e. if for commit C,  C^{tree} and 
+	C^^{tree} are identical).
+
 --strategy=<strategy>::
 	Use the given merge strategy.  Should only be used once.
 	See the MERGE STRATEGIES section in linkgit:git-merge[1]
diff --git a/builtin/revert.c b/builtin/revert.c
index 06b00e6..0fa76ca 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -115,6 +115,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 		OPT_END(),
 		OPT_END(),
 		OPT_END(),
+		OPT_END(),
 	};
 
 	if (opts->action == REPLAY_PICK) {
@@ -122,6 +123,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 			OPT_BOOLEAN('x', NULL, &opts->record_origin, "append commit name"),
 			OPT_BOOLEAN(0, "ff", &opts->allow_ff, "allow fast-forward"),
 			OPT_BOOLEAN(0, "allow-empty", &opts->allow_empty, "preserve empty commits"),
+			OPT_BOOLEAN(0, "ignore-if-made-empty", &opts->ignore_if_made_empty, "ignore commits already in tree"),
 			OPT_END(),
 		};
 		if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
diff --git a/sequencer.c b/sequencer.c
index 71929ba..a512598 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -13,6 +13,7 @@
 #include "rerere.h"
 #include "merge-recursive.h"
 #include "refs.h"
+#include "argv-array.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -258,26 +259,107 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
  * If we are revert, or if our cherry-pick results in a hand merge,
  * we had better say that the current user is responsible for that.
  */
-static int run_git_commit(const char *defmsg, struct replay_opts *opts)
-{
-	/* 7 is max possible length of our args array including NULL */
-	const char *args[7];
-	int i = 0;
+static int run_git_commit(const char *defmsg, struct replay_opts *opts, int empty)
+{
+	struct argv_array array;
+	int rc;
+
+	argv_array_init(&array);
+	argv_array_push(&array, "commit");
+	argv_array_push(&array, "-n");
+
+	if ((!empty) && (opts->ignore_if_made_empty)) {
+		/* Note: This implies --dry-run */
+		argv_array_push(&array, "--porcelain");
+		if (run_command_v_opt(array.argv, RUN_GIT_CMD) == 1) {
+			/* The dry run exit code of 1 tells us this is
+ 			 * an empty commit, just skip it.
+ 			 */
+			argv_array_clear(&array);
+			return 0;
+		}
+		argv_array_pop(&array, 1);
+	}
+
 
-	args[i++] = "commit";
-	args[i++] = "-n";
 	if (opts->signoff)
-		args[i++] = "-s";
+		argv_array_push(&array, "-s");
 	if (!opts->edit) {
-		args[i++] = "-F";
-		args[i++] = defmsg;
+		argv_array_push(&array, "-F");
+		argv_array_push(&array, defmsg);
 	}
+	
 	if (opts->allow_empty)
-		args[i++] = "--allow-empty";
+		argv_array_push(&array, "--allow-empty");
+
+
+	rc = run_command_v_opt(array.argv, RUN_GIT_CMD);
+	argv_array_clear(&array);
+	return rc;
+}
+
+static int is_origional_commit_empty(struct commit *commit)
+{
+	struct argv_array argv_array;
+	struct child_process cp;
+	char ptree[41], pptree[41];
+	int pipefd[2];
+	FILE *output;
+	int ret = 0;
+
+	if (pipe2(pipefd, 0) < 0)
+		return 0;
+
+	output = xfdopen(pipefd[0], "r");
+
+	argv_array_init(&argv_array);
+	memset(&cp, 0, sizeof(struct child_process));
 
-	args[i] = NULL;
+	argv_array_push(&argv_array, "rev-parse");
+	argv_array_pushf(&argv_array, "%s^{tree}", sha1_to_hex(commit->object.sha1));
 
-	return run_command_v_opt(args, RUN_GIT_CMD);
+	cp.git_cmd = 1;
+	cp.no_stdin = 1;
+	cp.no_stderr = 1;
+	cp.out = pipefd[1];
+	cp.argv = argv_array.argv;
+
+	if (start_command(&cp) < 0)
+		goto out;
+
+	if (fscanf(output, "%s\n", ptree) < 1)
+		goto out;
+
+	finish_command(&cp);
+
+	fclose(output);
+	close(pipefd[0]);
+	argv_array_clear(&argv_array);
+
+	if (pipe2(pipefd, 0) < 0)
+		return 0;
+
+	output = xfdopen(pipefd[0], "r");
+
+	argv_array_push(&argv_array, "rev-parse");
+	argv_array_pushf(&argv_array, "%s^^{tree}", sha1_to_hex(commit->object.sha1));
+	cp.argv = argv_array.argv;
+
+	if (start_command(&cp) < 0)
+		goto out;
+
+	if (fscanf(output, "%s\n", pptree) < 1)
+		goto out;
+
+	finish_command(&cp);
+	close(pipefd[0]);
+
+	if (!strncmp(ptree, pptree, 40))
+		ret = 1;
+out:
+	fclose(output);
+	argv_array_clear(&argv_array);	
+	return ret;
 }
 
 static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
@@ -289,6 +371,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 	char *defmsg = NULL;
 	struct strbuf msgbuf = STRBUF_INIT;
 	int res;
+	int empty_commit;
 
 	if (opts->no_commit) {
 		/*
@@ -414,6 +497,8 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 		free_commit_list(remotes);
 	}
 
+	empty_commit = is_origional_commit_empty(commit);
+
 	/*
 	 * If the merge was clean or if it failed due to conflict, we write
 	 * CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
@@ -435,7 +520,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 		rerere(opts->allow_rerere_auto);
 	} else {
 		if (!opts->no_commit)
-			res = run_git_commit(defmsg, opts);
+			res = run_git_commit(defmsg, opts, empty_commit);
 	}
 
 	free_message(&msg);
diff --git a/sequencer.h b/sequencer.h
index e2cd725..3e1106f 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -30,6 +30,7 @@ struct replay_opts {
 	int allow_ff;
 	int allow_rerere_auto;
 	int allow_empty;
+	int ignore_if_made_empty;
 
 	int mainline;
 
-- 
1.7.7.6

  parent reply	other threads:[~2012-04-05 19:41 UTC|newest]

Thread overview: 121+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-30 19:48 [PATCH 0/4] Enhance git-rebases flexibiilty in handling empty commits Neil Horman
2012-03-30 19:48 ` [PATCH 1/4] git-cherry-pick: add keep-empty option Neil Horman
2012-03-30 20:34   ` Junio C Hamano
2012-03-30 21:15   ` Jeff King
2012-03-31 12:57   ` Neil Horman
2012-03-30 19:48 ` [PATCH 2/4] git-rebase: add keep_empty flag Neil Horman
2012-03-30 20:43   ` Junio C Hamano
2012-03-31 12:59     ` Neil Horman
2012-03-30 19:48 ` [PATCH 3/4] git-commit-am: Allow automatic rebasing to preserve empty commits Neil Horman
2012-03-30 20:46   ` Junio C Hamano
2012-03-31 13:01     ` Neil Horman
2012-03-30 20:47   ` Junio C Hamano
2012-03-31 13:03     ` Neil Horman
2012-03-30 19:48 ` [PATCH 4/4] git-commit-interactive: Allow " Neil Horman
2012-03-30 20:59   ` Junio C Hamano
2012-03-31 13:11     ` Neil Horman
2012-03-30 20:32 ` [PATCH 0/4] Enhance git-rebases flexibiilty in handling " Junio C Hamano
2012-04-05 19:39 ` [PATCH 0/5] Enhance git-rebases flexibiilty handling empty commits [v2] Neil Horman
2012-04-05 19:39   ` [PATCH 1/5] argv-array: Add argv_array_pop function [v2] Neil Horman
2012-04-05 20:12     ` Junio C Hamano
2012-04-05 23:24       ` Neil Horman
2012-04-06  0:12         ` Neil Horman
2012-04-06  0:19         ` Jeff King
2012-04-06  1:12           ` Neil Horman
2012-04-06  1:20         ` Junio C Hamano
2012-04-06  2:20           ` Jeff King
2012-04-06  4:19             ` Cc tags in the commit message (Re: [PATCH 1/5] argv-array: Add argv_array_pop function [v2]) Jonathan Nieder
2012-04-06  6:55             ` [PATCH 1/5] argv-array: Add argv_array_pop function [v2] Junio C Hamano
2012-04-06  7:33               ` Jeff King
2012-04-06 16:49                 ` Junio C Hamano
2012-04-06 18:02             ` Neil Horman
2012-04-05 19:39   ` [PATCH 2/5] git-cherry-pick: add allow-empty option [v2] Neil Horman
2012-04-05 19:39   ` Neil Horman [this message]
2012-04-05 21:01     ` [PATCH 3/5] git-cherry-pick: Add ignore-if-made-empty " Junio C Hamano
2012-04-05 23:45       ` Neil Horman
2012-04-06  1:20         ` Junio C Hamano
2012-04-06 18:06       ` Neil Horman
2012-04-06 18:30     ` Johannes Sixt
2012-04-05 19:39   ` [PATCH 4/5] git-cherry-pick: Add test to validate new options [v2] Neil Horman
2012-04-05 19:39   ` [PATCH 5/5] git-rebase: add keep_empty flag [v2] Neil Horman
2012-04-10 15:47 ` [PATCH v3 0/4] Enhance git-rebases flexibiilty in handling empty commits Neil Horman
2012-04-10 15:47   ` [PATCH v3 1/4] git-cherry-pick: add allow-empty option Neil Horman
2012-04-10 16:45     ` Junio C Hamano
2012-04-10 18:13       ` Neil Horman
2012-04-10 19:32         ` Junio C Hamano
2012-04-10 20:00           ` Neil Horman
2012-04-10 20:32             ` Junio C Hamano
2012-04-10 20:39               ` Neil Horman
2012-04-10 21:09                 ` Junio C Hamano
2012-04-11  0:44                   ` Neil Horman
2012-04-11 16:52                     ` Junio C Hamano
2012-04-11 18:29                       ` Neil Horman
2012-04-11 18:50                         ` Junio C Hamano
2012-04-11 18:56                           ` Neil Horman
2012-04-10 15:47   ` [PATCH v3 2/4] git-cherry-pick: Add keep-redundant-commits option Neil Horman
2012-04-10 17:04     ` Junio C Hamano
2012-04-10 18:25       ` Neil Horman
2012-04-10 15:47   ` [PATCH v3 3/4] git-cherry-pick: Add test to validate new options Neil Horman
2012-04-10 15:47   ` [PATCH v3 4/4] git-rebase: add keep_empty flag Neil Horman
2012-04-13 18:45 ` [PATCH v5 0/4]Enhance git-rebases flexibiilty in handling empty commits Neil Horman
2012-04-13 18:45   ` [PATCH v5 1/4] git-cherry-pick: add allow-empty option Neil Horman
2012-04-13 18:45   ` [PATCH v5 2/4] git-cherry-pick: Add keep-redundant-commits option Neil Horman
2012-04-15 10:42     ` Clemens Buchacher
2012-04-16 15:38       ` Neil Horman
2012-04-16 22:10         ` Clemens Buchacher
2012-04-17 10:43           ` Neil Horman
2012-04-17 15:42           ` Junio C Hamano
2012-04-17 21:37             ` Clemens Buchacher
2012-04-18 10:41               ` Neil Horman
2012-04-13 18:45   ` [PATCH v5 3/4] git-cherry-pick: Add test to validate new options Neil Horman
2012-04-15  9:39     ` Clemens Buchacher
2012-04-16 11:04       ` Neil Horman
2012-04-16 16:14       ` Neil Horman
2012-04-16 16:35         ` Junio C Hamano
2012-04-16 16:50           ` Neil Horman
2012-04-16 21:42             ` Clemens Buchacher
2012-04-17 10:56               ` Neil Horman
2012-04-17 21:38                 ` Clemens Buchacher
2012-04-18 10:48                   ` Neil Horman
2012-04-18 18:34                     ` Clemens Buchacher
2012-04-13 18:45   ` [PATCH v5 4/4] git-rebase: add keep_empty flag Neil Horman
2012-04-15  9:33     ` Clemens Buchacher
2012-04-16 16:46       ` Neil Horman
2012-04-17 18:20 ` [PATCH v6 0/4] Enhance git-rebases flexibiilty in handling empty commits Neil Horman
2012-04-17 18:20   ` [PATCH v6 1/4] git-cherry-pick: add allow-empty option Neil Horman
2012-04-17 18:20   ` [PATCH v6 2/4] git-cherry-pick: Add keep-redundant-commits option Neil Horman
2012-04-17 21:45     ` Clemens Buchacher
2012-04-18 10:49       ` Neil Horman
2012-04-17 18:20   ` [PATCH v6 3/4] git-cherry-pick: Add test to validate new options Neil Horman
2012-04-17 18:20   ` [PATCH v6 4/4] git-rebase: add keep_empty flag Neil Horman
2012-04-17 21:47     ` Clemens Buchacher
2012-04-18 10:50       ` Neil Horman
2012-04-18 22:58     ` Junio C Hamano
2012-04-19 13:08       ` Neil Horman
2012-04-19 17:53         ` Junio C Hamano
2012-04-18 19:17 ` [PATCH v7 0/4] Enhance git-rebases flexibiilty in handling empty commits Neil Horman
2012-04-18 19:17   ` [PATCH v7 1/4] git-cherry-pick: add allow-empty option Neil Horman
2012-04-18 19:17   ` [PATCH v7 2/4] git-cherry-pick: Add keep-redundant-commits option Neil Horman
2012-04-18 22:59     ` Junio C Hamano
2012-04-18 19:17   ` [PATCH v7 3/4] git-cherry-pick: Add test to validate new options Neil Horman
2012-04-18 19:18   ` [PATCH v7 4/4] git-rebase: add keep_empty flag Neil Horman
2012-04-19 10:02     ` Zbigniew Jędrzejewski-Szmek
2012-04-19 11:49       ` Thomas Rast
2012-04-19 12:19         ` Zbigniew Jędrzejewski-Szmek
2012-04-19 13:12           ` Neil Horman
2012-04-19 18:59         ` Junio C Hamano
2012-04-19 19:05           ` Junio C Hamano
2012-04-20 10:35             ` Neil Horman
2012-04-20 14:36 ` [PATCH v8 0/4] Enhance git-rebases flexibiilty in handling empty commits Neil Horman
2012-04-20 14:36   ` [PATCH v8 1/4] git-cherry-pick: add allow-empty option Neil Horman
2012-04-20 14:36   ` [PATCH v8 2/4] git-cherry-pick: Add keep-redundant-commits option Neil Horman
2012-04-20 19:21     ` Junio C Hamano
2012-04-20 19:56       ` Neil Horman
2012-04-20 14:36   ` [PATCH v8 3/4] git-cherry-pick: Add test to validate new options Neil Horman
2012-04-20 14:36   ` [PATCH v8 4/4] git-rebase: add keep_empty flag Neil Horman
2012-04-25  1:50     ` Junio C Hamano
2012-04-25 10:38       ` Neil Horman
2012-07-18  6:20     ` Martin von Zweigbergk
2012-07-18  7:10       ` Johannes Sixt
2012-07-18  7:16         ` Martin von Zweigbergk
2012-07-18 12:17         ` Neil Horman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1333654745-7898-4-git-send-email-nhorman@tuxdriver.com \
    --to=nhorman@tuxdriver.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    --cc=phil.hord@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.