Git Mailing List Archive on lore.kernel.org
 help / color / Atom feed
* [GSoC][PATCHl 0/6] rebase -i: support more options
@ 2019-08-06 17:36 Rohit Ashiwal
  2019-08-06 17:36 ` [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
                   ` (9 more replies)
  0 siblings, 10 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

The previous versions of this patch series were sent here[1]. This patch
accounts for all the suggestions mentioned there and also introduces a flag
--ignore-date (also aliased --author-date-is-committer-date).

Caveat:

        The flag --ignore-date (of rebase -am) silently overrides the
        --committer-date-is-author-date flag. This behaviour is not actually
        documented. I've made rebase -i to replicate this behaviour anyway.

Thanks
Rohit

[1]: https://public-inbox.org/git/20190712185015.20585-1-rohit.ashiwal265@gmail.com/

Rohit Ashiwal (6):
  rebase -i: add --ignore-whitespace flag
  sequencer: add NULL checks under read_author_script
  rebase -i: support --committer-date-is-author-date
  sequencer: rename amend_author to author_to_rename
  rebase -i: support --ignore-date
  rebase: add --author-date-is-committer-date

 Documentation/git-rebase.txt            |  23 +++--
 builtin/rebase.c                        |  59 +++++++++---
 sequencer.c                             | 114 ++++++++++++++++++++++--
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 100 +++++++++++++++++++++
 6 files changed, 271 insertions(+), 29 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

-- 
2.21.0


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

* [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
@ 2019-08-06 17:36 ` Rohit Ashiwal
  2019-08-07  5:38   ` Junio C Hamano
  2019-08-06 17:36 ` [GSoC][PATCHl 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

There are two backends available for rebasing, viz, the am and the
interactive. Naturally, there shall be some features that are
implemented in one but not in the other. One such flag is
--ignore-whitespace which indicates merge mechanism to treat lines
with only whitespace changes as unchanged. Wire the interactive
rebase to also understand the --ignore-whitespace flag by
translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 10 +++-
 builtin/rebase.c                        | 26 ++++++++--
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
 4 files changed, 95 insertions(+), 7 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 5e4e927647..85404fea52 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -371,8 +371,13 @@ If either <upstream> or --root is given on the command line, then the
 default is `--no-fork-point`, otherwise the default is `--fork-point`.
 
 --ignore-whitespace::
+	This flag is either passed to the 'git apply' program
+	(see linkgit:git-apply[1]), or to 'git merge' program
+	(see linkgit:git-merge[1]) as `-Xignore-space-change`,
+	depending on which backend is selected by other options.
+
 --whitespace=<option>::
-	These flag are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -520,7 +525,6 @@ The following options:
  * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
- * --ignore-whitespace
  * -C
 
 are incompatible with the following options:
@@ -543,6 +547,8 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --interactive
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
+ * --preserve-merges and --ignore-whitespace
+ * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index db6ca9bd7d..3c195ddc73 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -79,6 +79,7 @@ struct rebase_options {
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -97,7 +98,7 @@ struct rebase_options {
 		.git_format_patch_opt = STRBUF_INIT	\
 	}
 
-static struct replay_opts get_replay_opts(const struct rebase_options *opts)
+static struct replay_opts get_replay_opts(struct rebase_options *opts)
 {
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
@@ -114,6 +115,17 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
+	if (opts->ignore_whitespace) {
+		struct strbuf buf = STRBUF_INIT;
+
+		if (opts->strategy_opts)
+			strbuf_addstr(&buf, opts->strategy_opts);
+
+		strbuf_addstr(&buf, " --ignore-space-change");
+		free(opts->strategy_opts);
+		opts->strategy_opts = strbuf_detach(&buf, NULL);
+	}
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
 
@@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, NULL, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -954,6 +968,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1401,9 +1417,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1411,6 +1424,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1821,6 +1836,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	if (options.rebase_merges) {
+		if (options.ignore_whitespace)
+			die(_("cannot combine '--rebase-merges' with "
+			      "'--ignore-whitespace'"));
 		if (strategy_options.nr)
 			die(_("cannot combine '--rebase-merges' with "
 			      "'--strategy-option'"));
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index a5868ea152..4342f79eea 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
new file mode 100755
index 0000000000..e617d3150e
--- /dev/null
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	cat >file <<-EOF &&
+	line 1
+	        line 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with am backend' '
+	cat >expect <<-EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase main side &&
+	git rebase --abort &&
+	git rebase --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with interactive backend' '
+	cat >expect <<-EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_done
-- 
2.21.0


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

* [GSoC][PATCHl 2/6] sequencer: add NULL checks under read_author_script
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-06 17:36 ` [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-08-06 17:36 ` Rohit Ashiwal
  2019-08-06 17:36 ` [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

read_author_script reads name, email and author date from the author
script. However, it does not check if the arguments are NULL. Adding
NULL checks will allow us to selectively get the required value, for
example:

    char *date;
    if (read_author_script(_path_, NULL, NULL, &date, _int_))
	    die(_("failed to read author date"));
    /* needs to be free()'d */
    return date;

Add NULL checks for better control over the information retrieved.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index f88a97fb10..a2d7b0925e 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -821,9 +821,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-	*name = kv.items[name_i].util;
-	*email = kv.items[email_i].util;
-	*date = kv.items[date_i].util;
+
+	if (name)
+		*name = kv.items[name_i].util;
+	else
+		free(kv.items[name_i].util);
+	if (email)
+		*email = kv.items[email_i].util;
+	else
+		free(kv.items[email_i].util);
+	if (date)
+		*date = kv.items[date_i].util;
+	else
+		free(kv.items[date_i].util);
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
-- 
2.21.0


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

* [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-06 17:36 ` [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
  2019-08-06 17:36 ` [GSoC][PATCHl 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
@ 2019-08-06 17:36 ` Rohit Ashiwal
  2019-08-08 11:29   ` Phillip Wood
  2019-08-06 17:36 ` [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

rebase am already has this flag to "lie" about the committer date
by changing it to the author date. Let's add the same for
interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  8 +++-
 builtin/rebase.c                        | 20 +++++++---
 sequencer.c                             | 52 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 19 +++++++++
 6 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 85404fea52..83c5bbe06c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of recording the time the rebased commits are
+	created as the committer date, reuse the author date
+	as the committer date. This implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
+	This flag is passed to 'git am' to change the author date
 	of the rebased commits (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -548,6 +551,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 3c195ddc73..41fe9ebff8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -82,6 +82,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -113,6 +114,8 @@ static struct replay_opts get_replay_opts(struct rebase_options *opts)
 	replay.allow_empty_message = opts->allow_empty_message;
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -532,6 +535,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 		warning(_("--[no-]rebase-cousins has no effect without "
 			  "--rebase-merges"));
 
+	if (opts.committer_date_is_author_date)
+		opts.flags |= REBASE_FORCE;
+
 	return !!run_rebase_interactive(&opts, command);
 }
 
@@ -970,6 +976,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1417,9 +1425,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1686,10 +1694,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
+
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
diff --git a/sequencer.c b/sequencer.c
index a2d7b0925e..65adf79222 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -876,6 +877,17 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+/* Returns a "date" string that needs to be free()'d by the caller */
+static char *read_author_date_or_null(void)
+{
+	char *date;
+
+	if (read_author_script(rebase_path_author_script(),
+			       NULL, NULL, &date, 0))
+		return NULL;
+	return date;
+}
+
 /* Read author-script and return an ident line (author <email> timestamp) */
 static const char *read_author_ident(struct strbuf *buf)
 {
@@ -904,6 +916,18 @@ static const char *read_author_ident(struct strbuf *buf)
 	return buf->buf;
 }
 
+static int setenv_committer_date_to_author_date(void)
+{
+	int res = 1;
+	char *date = read_author_date_or_null();
+
+	if (date)
+		res = setenv("GIT_COMMITTER_DATE", date, 1);
+
+	free(date);
+	return res;
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -961,6 +985,9 @@ static int run_git_commit(struct repository *r,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 
+	if (opts->committer_date_is_author_date &&
+	    setenv_committer_date_to_author_date())
+		return 1;
 	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
 		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
 		const char *author = NULL;
@@ -1397,7 +1424,9 @@ static int try_to_commit(struct repository *r,
 
 	if (parse_head(r, &current_head))
 		return -1;
-
+	if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
+	    setenv_committer_date_to_author_date())
+		return -1;
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1418,6 +1447,17 @@ static int try_to_commit(struct repository *r,
 			res = error(_("unable to parse commit author"));
 			goto out;
 		}
+		if (opts->committer_date_is_author_date) {
+			char *date;
+			int len = strlen(author);
+			char *idx = memchr(author, '>', len);
+
+			++idx;
+			date = malloc(author + len - idx);
+			memcpy(date, idx, author + len - idx);
+			setenv("GIT_COMMITTER_DATE", date, 1);
+			free(date);
+		}
 		parents = copy_commit_list(current_head->parents);
 		extra = read_commit_extra_headers(current_head, exclude_gpgsig);
 	} else if (current_head) {
@@ -2538,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2620,6 +2665,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
 	if (opts->signoff)
 		write_file(rebase_path_signoff(), "--signoff\n");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3708,7 +3755,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0c494b83d4..e6cba468db 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -43,6 +43,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 4342f79eea..7402f7e3da 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index e617d3150e..ceab48a831 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . ./test-lib.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with am backend' '
+	git rebase -f HEAD^ &&
+	git rebase --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%at" >authortime &&
+	git show HEAD --pretty="format:%ct" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with interactive backend' '
+	git rebase -f HEAD^ &&
+	git rebase -i --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%at" >authortime &&
+	git show HEAD --pretty="format:%ct" >committertime &&
+	test_cmp authortime committertime
+'
+
 test_done
-- 
2.21.0


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

* [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (2 preceding siblings ...)
  2019-08-06 17:36 ` [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-08-06 17:36 ` Rohit Ashiwal
  2019-08-08 11:30   ` Phillip Wood
  2019-08-06 17:36 ` [GSoC][PATCHl 5/6] rebase -i: support --ignore-date Rohit Ashiwal
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author(). But the name does not actually convey
this purpose. Rename it to something meaningful.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 65adf79222..d24a6fd585 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1417,7 +1417,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1441,7 +1441,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1526,7 +1526,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.21.0


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

* [GSoC][PATCHl 5/6] rebase -i: support --ignore-date
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (3 preceding siblings ...)
  2019-08-06 17:36 ` [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-08-06 17:36 ` Rohit Ashiwal
  2019-08-07 19:41   ` Johannes Schindelin
  2019-08-08 11:42   ` Phillip Wood
  2019-08-06 17:36 ` [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

rebase am already has this flag to "lie" about the author date
by changing it to the committer (current) date. Let's add the same
for interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  6 ++--
 builtin/rebase.c                        | 17 +++++----
 sequencer.c                             | 48 ++++++++++++++++++++++---
 sequencer.h                             |  1 +
 t/t3433-rebase-options-compatibility.sh | 16 +++++++++
 5 files changed, 74 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 83c5bbe06c..a5cdf8518b 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of the rebased commits (see linkgit:git-am[1]).
+	Lie about the author date by re-setting it to the value
+	same as committer (current) date. This implies --force-rebase.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --ignore-date
  * --whitespace
  * -C
 
@@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 41fe9ebff8..7f464fc9ba 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -83,6 +83,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -116,6 +117,7 @@ static struct replay_opts get_replay_opts(struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -535,7 +537,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 		warning(_("--[no-]rebase-cousins has no effect without "
 			  "--rebase-merges"));
 
-	if (opts.committer_date_is_author_date)
+	if (opts.committer_date_is_author_date ||
+	    opts.ignore_date)
 		opts.flags |= REBASE_FORCE;
 
 	return !!run_rebase_interactive(&opts, command);
@@ -978,6 +981,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1428,8 +1433,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1694,13 +1699,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date ||
+	    options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index d24a6fd585..c882dc5d5f 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -928,6 +929,17 @@ static int setenv_committer_date_to_author_date(void)
 	return res;
 }
 
+static void ignore_author_date(const char **author)
+{
+	struct strbuf new_author = STRBUF_INIT;
+	char *idx = memchr(*author, '>', strlen(*author));
+
+	strbuf_add(&new_author, *author, idx - *author);
+	strbuf_addstr(&new_author, "> ");
+	datestamp(&new_author);
+	*author = strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -985,7 +997,7 @@ static int run_git_commit(struct repository *r,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 
-	if (opts->committer_date_is_author_date &&
+	if (opts->committer_date_is_author_date && !opts->ignore_date &&
 	    setenv_committer_date_to_author_date())
 		return 1;
 	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
@@ -1013,10 +1025,18 @@ static int run_git_commit(struct repository *r,
 
 		if (res <= 0)
 			res = error_errno(_("could not read '%s'"), defmsg);
-		else
+		else {
+			if (opts->ignore_date) {
+				if (!author)
+					BUG("ignore-date can only be used with "
+					    "rebase -i, which must set the "
+					    "author before committing the tree");
+				ignore_author_date(&author);
+			}
 			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
 					  NULL, &root_commit, author,
 					  opts->gpg_sign);
+		}
 
 		strbuf_release(&msg);
 		strbuf_release(&script);
@@ -1046,6 +1066,8 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+	if (opts->ignore_date)
+		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -1425,7 +1447,7 @@ static int try_to_commit(struct repository *r,
 	if (parse_head(r, &current_head))
 		return -1;
 	if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
-	    setenv_committer_date_to_author_date())
+	    !opts->ignore_date && setenv_committer_date_to_author_date())
 		return -1;
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
@@ -1447,7 +1469,7 @@ static int try_to_commit(struct repository *r,
 			res = error(_("unable to parse commit author"));
 			goto out;
 		}
-		if (opts->committer_date_is_author_date) {
+		if (opts->committer_date_is_author_date && !opts->ignore_date) {
 			char *date;
 			int len = strlen(author);
 			char *idx = memchr(author, '>', len);
@@ -1507,6 +1529,11 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		ignore_author_date(&author);
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2583,6 +2610,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2667,6 +2699,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_signoff(), "--signoff\n");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3484,6 +3518,9 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
+		if (opts->ignore_date)
+			argv_array_pushf(&cmd.args,
+					 "GIT_AUTHOR_DATE=%ld", time(NULL));
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3756,7 +3793,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index e6cba468db..73d0515a3e 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -44,6 +44,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index ceab48a831..95d99c4b7b 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back
 	test_cmp authortime committertime
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with am backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with interactive backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -i HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
 test_done
-- 
2.21.0


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

* [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (4 preceding siblings ...)
  2019-08-06 17:36 ` [GSoC][PATCHl 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-08-06 17:36 ` Rohit Ashiwal
  2019-08-08 11:42   ` Phillip Wood
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-06 17:36 UTC (permalink / raw)
  To: Junio, GIT Mailing List
  Cc: Thomas, Elijah, Phillip, Dscho, Martin, Rohit Ashiwal

The previous commit introduced --ignore-date flag to interactive
rebase, but the name is actually very vague in context of rebase -i
since there are two dates we can work with. Add an alias to convey
the precise purpose.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt | 1 +
 builtin/rebase.c             | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index a5cdf8518b..bb60426911 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
+--author-date-is-committer-date::
 	Lie about the author date by re-setting it to the value
 	same as committer (current) date. This implies --force-rebase.
 +
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 7f464fc9ba..a9a42f9ee4 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1433,6 +1433,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
+		OPT_BOOL(0, "author-date-is-committer-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_BOOL(0, "ignore-date", &options.ignore_date,
 			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-- 
2.21.0


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

* Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-06 17:36 ` [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-08-07  5:38   ` Junio C Hamano
  2019-08-07 20:25     ` Rohit Ashiwal
  0 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-07  5:38 UTC (permalink / raw)
  To: Rohit Ashiwal; +Cc: GIT Mailing List, Thomas, Elijah, Phillip, Dscho, Martin

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index db6ca9bd7d..3c195ddc73 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> ...
> @@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>  	argc = parse_options(argc, argv, NULL, options,
>  			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);

Curious.  Did you rebase onto an older codebase?  I think the round
currently queued in my tree already has c0e78f7e46 which merged the
jk/unused-params-final-batch topic that updated this call to
parse_options() to pass prefix.  Perhaps you want to fetch from me
what has been on 'pu' (it should be "log master..10827432") and
compare what you had?  Unless there is no compelling reason not to,
it would be a good idea to base the reroll on the same commit as
the commit on which the previous version has been queued, which in
this case is 9c9b961d ("The sixth batch", 2019-07-19).

> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> new file mode 100755
> index 0000000000..e617d3150e
> --- /dev/null
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -0,0 +1,65 @@
> ...
> +
> +	git checkout --orphan master &&
> +	cat >file <<-EOF &&
> +	line 1
> +	        line 2
> +	line 3
> +	EOF

The second line triggers "indent with spaces" whitespace error; you
can protect these spaces in the leading indent like so:

	sed -e "s/^|//" <<-\EOF &&
	|line 1
	|        line 2
	|line 3
	EOF

Also make it a habit to always quote the EOF token that begins the
here document (i.e. <<-\EOF) when the here document does not need
variable interpolation.  I suspect (but I did not read all of the
tests) that there may be many other instances of here document in
this patch that can use the same improvement.

Thanks.

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

* Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date
  2019-08-06 17:36 ` [GSoC][PATCHl 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-08-07 19:41   ` Johannes Schindelin
  2019-08-07 20:22     ` Junio C Hamano
  2019-08-08 11:42   ` Phillip Wood
  1 sibling, 1 reply; 92+ messages in thread
From: Johannes Schindelin @ 2019-08-07 19:41 UTC (permalink / raw)
  To: Rohit Ashiwal; +Cc: Junio, GIT Mailing List, Thomas, Elijah, Phillip, Martin

Hi Rohit,

On Tue, 6 Aug 2019, Rohit Ashiwal wrote:

> @@ -1046,6 +1066,8 @@ static int run_git_commit(struct repository *r,
>  		argv_array_push(&cmd.args, "--amend");
>  	if (opts->gpg_sign)
>  		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> +	if (opts->ignore_date)
> +		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
>  	if (defmsg)
>  		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>  	else if (!(flags & EDIT_MSG))

I need this patch to make the code _at least_ compile on Windows again
(I don't know whether it breaks the test suite yet):

-- snipsnap --
Subject: [PATCH] fixup! rebase -i: support --ignore-date

It is a mistake to believe that the return value of `time()` is always
an `unsigned long`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 sequencer.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 539c0ef601b..a4c932d3407 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1070,7 +1070,8 @@ static int run_git_commit(struct repository *r,
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
 	if (opts->ignore_date)
-		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
+		argv_array_pushf(&cmd.args, "--date=%"PRIuMAX,
+				 (uintmax_t)time(NULL));
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -3642,7 +3643,8 @@ static int do_merge(struct repository *r,
 			argv_array_push(&cmd.args, opts->gpg_sign);
 		if (opts->ignore_date)
 			argv_array_pushf(&cmd.args,
-					 "GIT_AUTHOR_DATE=%ld", time(NULL));
+					 "GIT_AUTHOR_DATE=%"PRIuMAX,
+					 (uintmax_t)time(NULL));

 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
--
2.22.0.windows.1.6.g271c090e89


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

* Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date
  2019-08-07 19:41   ` Johannes Schindelin
@ 2019-08-07 20:22     ` Junio C Hamano
  2019-08-07 20:33       ` Rohit Ashiwal
  0 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-07 20:22 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Rohit Ashiwal, GIT Mailing List, Thomas, Elijah, Phillip, Martin

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> On Tue, 6 Aug 2019, Rohit Ashiwal wrote:
>
>> @@ -1046,6 +1066,8 @@ static int run_git_commit(struct repository *r,
>>  		argv_array_push(&cmd.args, "--amend");
>>  	if (opts->gpg_sign)
>>  		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>> +	if (opts->ignore_date)
>> +		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
>>  	if (defmsg)
>>  		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>>  	else if (!(flags & EDIT_MSG))
>
> I need this patch to make the code _at least_ compile on Windows again
> (I don't know whether it breaks the test suite yet):
>
> -- snipsnap --
> Subject: [PATCH] fixup! rebase -i: support --ignore-date
>
> It is a mistake to believe that the return value of `time()` is always
> an `unsigned long`.

Good catch.  We can at least expect it to be some integral type ;-)

With or without this fix-up, I think the patch is still not quite
right.  Output from time() formatted as an integer is a string of
digits, and the side that reads that string and interprets it as a
timestamp does so by calling parse_date(); it is up to that function
to decide what datestring format it is in, and it does not
necessarily take it as seconds since epoch.  It is safer to force
the "seconds since epoch" interpretation by writing the timestamp
string like so:

	argv_array_pushf(&args, "--date=@%ld", time(NULL));

See 14ac2864 ("commit: accept more date formats for "--date"",
2014-05-01), which gives a good hint on how to do this right, and
2c733fb2 ("parse_date(): '@' prefix forces git-timestamp",
2012-02-02) for a backstory.

> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  sequencer.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/sequencer.c b/sequencer.c
> index 539c0ef601b..a4c932d3407 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -1070,7 +1070,8 @@ static int run_git_commit(struct repository *r,
>  	if (opts->gpg_sign)
>  		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>  	if (opts->ignore_date)
> -		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
> +		argv_array_pushf(&cmd.args, "--date=%"PRIuMAX,
> +				 (uintmax_t)time(NULL));
>  	if (defmsg)
>  		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>  	else if (!(flags & EDIT_MSG))
> @@ -3642,7 +3643,8 @@ static int do_merge(struct repository *r,
>  			argv_array_push(&cmd.args, opts->gpg_sign);
>  		if (opts->ignore_date)
>  			argv_array_pushf(&cmd.args,
> -					 "GIT_AUTHOR_DATE=%ld", time(NULL));
> +					 "GIT_AUTHOR_DATE=%"PRIuMAX,
> +					 (uintmax_t)time(NULL));
>
>  		/* Add the tips to be merged */
>  		for (j = to_merge; j; j = j->next)
> --
> 2.22.0.windows.1.6.g271c090e89

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

* Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-07  5:38   ` Junio C Hamano
@ 2019-08-07 20:25     ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-07 20:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: GIT Mailing List, Thomas, Elijah, Phillip, Dscho, Martin

Hi Junio

On Wed, Aug 7, 2019 at 11:08 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:
>
> > diff --git a/builtin/rebase.c b/builtin/rebase.c
> > index db6ca9bd7d..3c195ddc73 100644
> > --- a/builtin/rebase.c
> > +++ b/builtin/rebase.c
> > ...
> > @@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
> >       argc = parse_options(argc, argv, NULL, options,
> >                       builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>
> Curious.  Did you rebase onto an older codebase?  I think the round
> currently queued in my tree already has c0e78f7e46 which merged the
> jk/unused-params-final-batch topic that updated this call to
> parse_options() to pass prefix.  Perhaps you want to fetch from me
> what has been on 'pu' (it should be "log master..10827432") and
> compare what you had?  Unless there is no compelling reason not to,
> it would be a good idea to base the reroll on the same commit as
> the commit on which the previous version has been queued, which in
> this case is 9c9b961d ("The sixth batch", 2019-07-19).

Oh~ I didn't notice it. I'll rebase and re send the patch. Thanks for
pointing out.

> > diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> > new file mode 100755
> > index 0000000000..e617d3150e
> > --- /dev/null
> > +++ b/t/t3433-rebase-options-compatibility.sh
> > @@ -0,0 +1,65 @@
> > ...
> > +
> > +     git checkout --orphan master &&
> > +     cat >file <<-EOF &&
> > +     line 1
> > +             line 2
> > +     line 3
> > +     EOF
>
> The second line triggers "indent with spaces" whitespace error; you
> can protect these spaces in the leading indent like so:
>
>         sed -e "s/^|//" <<-\EOF &&
>         |line 1
>         |        line 2
>         |line 3
>         EOF
>
> Also make it a habit to always quote the EOF token that begins the
> here document (i.e. <<-\EOF) when the here document does not need
> variable interpolation.  I suspect (but I did not read all of the
> tests) that there may be many other instances of here document in
> this patch that can use the same improvement.

Will keep this in mind.

Thanks
Rohit

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

* Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date
  2019-08-07 20:22     ` Junio C Hamano
@ 2019-08-07 20:33       ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-07 20:33 UTC (permalink / raw)
  To: Junio C Hamano, Johannes Schindelin
  Cc: GIT Mailing List, Thomas, Elijah, Phillip, Martin

Hi Junio and Dscho

On Thu, Aug 8, 2019 at 1:52 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > On Tue, 6 Aug 2019, Rohit Ashiwal wrote:
> >
> >> @@ -1046,6 +1066,8 @@ static int run_git_commit(struct repository *r,
> >>              argv_array_push(&cmd.args, "--amend");
> >>      if (opts->gpg_sign)
> >>              argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> >> +    if (opts->ignore_date)
> >> +            argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
> >>      if (defmsg)
> >>              argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
> >>      else if (!(flags & EDIT_MSG))
> >
> > I need this patch to make the code _at least_ compile on Windows again
> > (I don't know whether it breaks the test suite yet):
> >
> > -- snipsnap --
> > Subject: [PATCH] fixup! rebase -i: support --ignore-date
> >
> > It is a mistake to believe that the return value of `time()` is always
> > an `unsigned long`.
>
> Good catch.  We can at least expect it to be some integral type ;-)
>
> With or without this fix-up, I think the patch is still not quite
> right.  Output from time() formatted as an integer is a string of
> digits, and the side that reads that string and interprets it as a
> timestamp does so by calling parse_date(); it is up to that function
> to decide what datestring format it is in, and it does not
> necessarily take it as seconds since epoch.  It is safer to force
> the "seconds since epoch" interpretation by writing the timestamp
> string like so:
>
>         argv_array_pushf(&args, "--date=@%ld", time(NULL));
>
> See 14ac2864 ("commit: accept more date formats for "--date"",
> 2014-05-01), which gives a good hint on how to do this right, and
> 2c733fb2 ("parse_date(): '@' prefix forces git-timestamp",
> 2012-02-02) for a backstory.
>
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
> >  sequencer.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/sequencer.c b/sequencer.c
> > index 539c0ef601b..a4c932d3407 100644
> > --- a/sequencer.c
> > +++ b/sequencer.c
> > @@ -1070,7 +1070,8 @@ static int run_git_commit(struct repository *r,
> >       if (opts->gpg_sign)
> >               argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> >       if (opts->ignore_date)
> > -             argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
> > +             argv_array_pushf(&cmd.args, "--date=%"PRIuMAX,
> > +                              (uintmax_t)time(NULL));
> >       if (defmsg)
> >               argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
> >       else if (!(flags & EDIT_MSG))
> > @@ -3642,7 +3643,8 @@ static int do_merge(struct repository *r,
> >                       argv_array_push(&cmd.args, opts->gpg_sign);
> >               if (opts->ignore_date)
> >                       argv_array_pushf(&cmd.args,
> > -                                      "GIT_AUTHOR_DATE=%ld", time(NULL));
> > +                                      "GIT_AUTHOR_DATE=%"PRIuMAX,
> > +                                      (uintmax_t)time(NULL));
> >
> >               /* Add the tips to be merged */
> >               for (j = to_merge; j; j = j->next)
> > --
> > 2.22.0.windows.1.6.g271c090e89

Thanks for suggestions, I'll incorporate these changes along
with changes suggested by Junio and re-send the patch.

- Rohit

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

* Re: [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-06 17:36 ` [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-08-08 11:29   ` Phillip Wood
  2019-08-08 16:00     ` Junio C Hamano
  0 siblings, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-08-08 11:29 UTC (permalink / raw)
  To: Rohit Ashiwal, Junio, GIT Mailing List; +Cc: Thomas, Elijah, Dscho, Martin

Hi Rohit

On 06/08/2019 18:36, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the committer date
> by changing it to the author date. Let's add the same for
> interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            |  8 +++-
>   builtin/rebase.c                        | 20 +++++++---
>   sequencer.c                             | 52 ++++++++++++++++++++++++-
>   sequencer.h                             |  1 +
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++
>   6 files changed, 91 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 85404fea52..83c5bbe06c 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
>   See also INCOMPATIBLE OPTIONS below.
>   
>   --committer-date-is-author-date::
> +	Instead of recording the time the rebased commits are
> +	created as the committer date, reuse the author date
> +	as the committer date. This implies --force-rebase.
> +
>   --ignore-date::
> -	These flags are passed to 'git am' to easily change the dates
> +	This flag is passed to 'git am' to change the author date
>   	of the rebased commits (see linkgit:git-am[1]).
>   +
>   See also INCOMPATIBLE OPTIONS below.
> @@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
>    * -C
> @@ -548,6 +551,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 3c195ddc73..41fe9ebff8 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -82,6 +82,7 @@ struct rebase_options {
>   	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
> +	int committer_date_is_author_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -113,6 +114,8 @@ static struct replay_opts get_replay_opts(struct rebase_options *opts)
>   	replay.allow_empty_message = opts->allow_empty_message;
>   	replay.verbose = opts->flags & REBASE_VERBOSE;
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +	replay.committer_date_is_author_date =
> +					opts->committer_date_is_author_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -532,6 +535,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   		warning(_("--[no-]rebase-cousins has no effect without "
>   			  "--rebase-merges"));
>   
> +	if (opts.committer_date_is_author_date)
> +		opts.flags |= REBASE_FORCE;
> +
>   	return !!run_rebase_interactive(&opts, command);
>   }
>   
> @@ -970,6 +976,8 @@ static int run_am(struct rebase_options *opts)
>   
>   	if (opts->ignore_whitespace)
>   		argv_array_push(&am.args, "--ignore-whitespace");
> +	if (opts->committer_date_is_author_date)
> +		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1417,9 +1425,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -				  &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "committer-date-is-author-date",
> +			 &options.committer_date_is_author_date,
> +			 N_("make committer date match author date")),
>   		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1686,10 +1694,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> +	if (options.committer_date_is_author_date)
> +		options.flags |= REBASE_FORCE;
> +
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--committer-date-is-author-date") ||
> -		    !strcmp(option, "--ignore-date") ||
> +		if (!strcmp(option, "--ignore-date") ||
>   		    !strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
> diff --git a/sequencer.c b/sequencer.c
> index a2d7b0925e..65adf79222 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    * command-line.
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -876,6 +877,17 @@ static char *get_author(const char *message)
>   	return NULL;
>   }
>   
> +/* Returns a "date" string that needs to be free()'d by the caller */
> +static char *read_author_date_or_null(void)
> +{
> +	char *date;
> +
> +	if (read_author_script(rebase_path_author_script(),
> +			       NULL, NULL, &date, 0))
> +		return NULL;
> +	return date;
> +}
> +
>   /* Read author-script and return an ident line (author <email> timestamp) */
>   static const char *read_author_ident(struct strbuf *buf)
>   {
> @@ -904,6 +916,18 @@ static const char *read_author_ident(struct strbuf *buf)
>   	return buf->buf;
>   }
>   
> +static int setenv_committer_date_to_author_date(void)
> +{
> +	int res = 1;

In the git codebase it is conventional to return -1 for an error

> +	char *date = read_author_date_or_null();
> +
> +	if (date)
> +		res = setenv("GIT_COMMITTER_DATE", date, 1);
> +
> +	free(date);
> +	return res;
> +}
> +
>   static const char staged_changes_advice[] =
>   N_("you have staged changes in your working tree\n"
>   "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -961,6 +985,9 @@ static int run_git_commit(struct repository *r,
>   {
>   	struct child_process cmd = CHILD_PROCESS_INIT;
>   
> +	if (opts->committer_date_is_author_date &&
> +	    setenv_committer_date_to_author_date())
> +		return 1;

-1 for errors please, as seen in the surrounding code.

>   	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
>   		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
>   		const char *author = NULL;
> @@ -1397,7 +1424,9 @@ static int try_to_commit(struct repository *r,
>   
>   	if (parse_head(r, &current_head))
>   		return -1;
> -
> +	if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
> +	    setenv_committer_date_to_author_date())
> +		return -1;

I think it would be better to handle committer_date_is_author_date in a 
single place in this function, not have two implementations one of which 
is untested as shown in Stolee's latest test email. This function 
receives the author as a string so it should work with the author string 
once we have checked for amend.

>   	if (flags & AMEND_MSG) {
>   		const char *exclude_gpgsig[] = { "gpgsig", NULL };
>   		const char *out_enc = get_commit_output_encoding();
> @@ -1418,6 +1447,17 @@ static int try_to_commit(struct repository *r,
>   			res = error(_("unable to parse commit author"));
>   			goto out;
>   		}
> +		if (opts->committer_date_is_author_date) {
> +			char *date;
> +			int len = strlen(author);
> +			char *idx = memchr(author, '>', len);

what happens if there is a corrupted author without an email?  - We end 
up with undefined behavior.

> +
> +			++idx;
> +			date = malloc(author + len - idx);
> +			memcpy(date, idx, author + len - idx);
> +			setenv("GIT_COMMITTER_DATE", date, 1);
> +			free(date);

git has a high level api for manipulation author/committer information 
in ident.c, it would be best to use that. In any case code like this 
should be using strbuf's rather than malloc

> +		}
>   		parents = copy_commit_list(current_head->parents);
>   		extra = read_commit_extra_headers(current_head, exclude_gpgsig);
>   	} else if (current_head) {

Do the committer_date_is_author_date check after the end of this if.

Best Wishes

Phillip

> @@ -2538,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->signoff = 1;
>   		}
>   
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2620,6 +2665,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
>   	if (opts->signoff)
>   		write_file(rebase_path_signoff(), "--signoff\n");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3708,7 +3755,8 @@ static int pick_commits(struct repository *r,
>   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index 0c494b83d4..e6cba468db 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -43,6 +43,7 @@ struct replay_opts {
>   	int verbose;
>   	int quiet;
>   	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 4342f79eea..7402f7e3da 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index e617d3150e..ceab48a831 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>   
>   . ./test-lib.sh
>   
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>   # This is a special case in which both am and interactive backends
>   # provide the same output. It was done intentionally because
>   # both the backends fall short of optimal behaviour.
> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>   	test_cmp expect file
>   '
>   
> +test_expect_success '--committer-date-is-author-date works with am backend' '
> +	git rebase -f HEAD^ &&
> +	git rebase --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%at" >authortime &&
> +	git show HEAD --pretty="format:%ct" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
> +	git rebase -f HEAD^ &&
> +	git rebase -i --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%at" >authortime &&
> +	git show HEAD --pretty="format:%ct" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
>   test_done
> 

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

* Re: [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename
  2019-08-06 17:36 ` [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-08-08 11:30   ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-08 11:30 UTC (permalink / raw)
  To: Rohit Ashiwal, Junio, GIT Mailing List; +Cc: Thomas, Elijah, Dscho, Martin

Hi Rohit

On 06/08/2019 18:36, Rohit Ashiwal wrote:
> The purpose of amend_author was to free() the malloc()'d string
> obtained from get_author(). But the name does not actually convey
> this purpose. Rename it to something meaningful.

The name was intended to covey that it was only used when amending a 
commit, I'm fine with the rename though.

Best Wishes

Phillip

> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   sequencer.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/sequencer.c b/sequencer.c
> index 65adf79222..d24a6fd585 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -1417,7 +1417,7 @@ static int try_to_commit(struct repository *r,
>   	struct commit_extra_header *extra = NULL;
>   	struct strbuf err = STRBUF_INIT;
>   	struct strbuf commit_msg = STRBUF_INIT;
> -	char *amend_author = NULL;
> +	char *author_to_free = NULL;
>   	const char *hook_commit = NULL;
>   	enum commit_msg_cleanup_mode cleanup;
>   	int res = 0;
> @@ -1441,7 +1441,7 @@ static int try_to_commit(struct repository *r,
>   			strbuf_addstr(msg, orig_message);
>   			hook_commit = "HEAD";
>   		}
> -		author = amend_author = get_author(message);
> +		author = author_to_free = get_author(message);
>   		unuse_commit_buffer(current_head, message);
>   		if (!author) {
>   			res = error(_("unable to parse commit author"));
> @@ -1526,7 +1526,7 @@ static int try_to_commit(struct repository *r,
>   	free_commit_extra_headers(extra);
>   	strbuf_release(&err);
>   	strbuf_release(&commit_msg);
> -	free(amend_author);
> +	free(author_to_free);
>   
>   	return res;
>   }
> 

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

* Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date
  2019-08-06 17:36 ` [GSoC][PATCHl 5/6] rebase -i: support --ignore-date Rohit Ashiwal
  2019-08-07 19:41   ` Johannes Schindelin
@ 2019-08-08 11:42   ` Phillip Wood
  2019-08-08 16:53     ` Phillip Wood
  1 sibling, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-08-08 11:42 UTC (permalink / raw)
  To: Rohit Ashiwal, Junio, GIT Mailing List; +Cc: Thomas, Elijah, Dscho, Martin



On 06/08/2019 18:36, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the author date
> by changing it to the committer (current) date. Let's add the same
> for interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            |  6 ++--
>   builtin/rebase.c                        | 17 +++++----
>   sequencer.c                             | 48 ++++++++++++++++++++++---
>   sequencer.h                             |  1 +
>   t/t3433-rebase-options-compatibility.sh | 16 +++++++++
>   5 files changed, 74 insertions(+), 14 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 83c5bbe06c..a5cdf8518b 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.
>   	as the committer date. This implies --force-rebase.
>   
>   --ignore-date::
> -	This flag is passed to 'git am' to change the author date
> -	of the rebased commits (see linkgit:git-am[1]).
> +	Lie about the author date by re-setting it to the value
> +	same as committer (current) date. This implies --force-rebase.

I'm not keen on talking about lying with the implication of deceit. Just 
say that this resets the author date, there are perfectly legitimate 
reasons to do this.

>   +
>   See also INCOMPATIBLE OPTIONS below.
>   
> @@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --ignore-date
>    * --whitespace
>    * -C
>   
> @@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
>    * --preserve-merges and --committer-date-is-author-date
> + * --preserve-merges and --ignore-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 41fe9ebff8..7f464fc9ba 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -83,6 +83,7 @@ struct rebase_options {
>   	char *gpg_sign_opt;
>   	int autostash;
>   	int committer_date_is_author_date;
> +	int ignore_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -116,6 +117,7 @@ static struct replay_opts get_replay_opts(struct rebase_options *opts)
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.committer_date_is_author_date =
>   					opts->committer_date_is_author_date;
> +	replay.ignore_date = opts->ignore_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -535,7 +537,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   		warning(_("--[no-]rebase-cousins has no effect without "
>   			  "--rebase-merges"));
>   
> -	if (opts.committer_date_is_author_date)
> +	if (opts.committer_date_is_author_date ||
> +	    opts.ignore_date)
>   		opts.flags |= REBASE_FORCE;
>   
>   	return !!run_rebase_interactive(&opts, command);
> @@ -978,6 +981,8 @@ static int run_am(struct rebase_options *opts)
>   		argv_array_push(&am.args, "--ignore-whitespace");
>   	if (opts->committer_date_is_author_date)
>   		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
> +	if (opts->ignore_date)
> +		argv_array_push(&opts->git_am_opts, "--ignore-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1428,8 +1433,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		OPT_BOOL(0, "committer-date-is-author-date",
>   			 &options.committer_date_is_author_date,
>   			 N_("make committer date match author date")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "ignore-date", &options.ignore_date,
> +			 "ignore author date and use current date"),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>   				  N_("passed to 'git apply'"), 0),
>   		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> @@ -1694,13 +1699,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> -	if (options.committer_date_is_author_date)
> +	if (options.committer_date_is_author_date ||
> +	    options.ignore_date)
>   		options.flags |= REBASE_FORCE;
>   
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--ignore-date") ||
> -		    !strcmp(option, "--whitespace=fix") ||
> +		if (!strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
>   		else if (skip_prefix(option, "-C", &p)) {
> diff --git a/sequencer.c b/sequencer.c
> index d24a6fd585..c882dc5d5f 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -928,6 +929,17 @@ static int setenv_committer_date_to_author_date(void)
>   	return res;
>   }
>   
> +static void ignore_author_date(const char **author)
> +{
> +	struct strbuf new_author = STRBUF_INIT;
> +	char *idx = memchr(*author, '>', strlen(*author));

strchr? I'd be happy to see this using the functions in ident.c which 
check the author is formatted correctly, as it stands this code will 
happily continue if idx == NULL.

> +
> +	strbuf_add(&new_author, *author, idx - *author);
> +	strbuf_addstr(&new_author, "> ");
> +	datestamp(&new_author);
> +	*author = strbuf_detach(&new_author, NULL);
> +}
> +
>   static const char staged_changes_advice[] =
>   N_("you have staged changes in your working tree\n"
>   "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -985,7 +997,7 @@ static int run_git_commit(struct repository *r,
>   {
>   	struct child_process cmd = CHILD_PROCESS_INIT;
>   
> -	if (opts->committer_date_is_author_date &&
> +	if (opts->committer_date_is_author_date && !opts->ignore_date &&
>   	    setenv_committer_date_to_author_date())
>   		return 1;

We read the author script again just below, can set the committer date 
there by parsing the author string, that would mean you could use the 
same function that works on an author string in try_to_commit() (this 
comment should be on patch 3 I think)

>   	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
> @@ -1013,10 +1025,18 @@ static int run_git_commit(struct repository *r,
>   
>   		if (res <= 0)
>   			res = error_errno(_("could not read '%s'"), defmsg);
> -		else
> +		else {
> +			if (opts->ignore_date) {
> +				if (!author)
> +					BUG("ignore-date can only be used with "
> +					    "rebase -i, which must set the "

I know it's only a bug message but it's not just 'rebase -i' but 'rebase 
-k', 'rebase -m' ... that use this code path, it would be better just to 
say 'rebase'

> +					    "author before committing the tree");
> +				ignore_author_date(&author);
> +			}
>   			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>   					  NULL, &root_commit, author,
>   					  opts->gpg_sign);
> +		}
>   
>   		strbuf_release(&msg);
>   		strbuf_release(&script);
> @@ -1046,6 +1066,8 @@ static int run_git_commit(struct repository *r,
>   		argv_array_push(&cmd.args, "--amend");
>   	if (opts->gpg_sign)
>   		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> +	if (opts->ignore_date)
> +		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));

I think this is racy as it only sets the author date, the committer date 
may end up being different.

>   	if (defmsg)
>   		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>   	else if (!(flags & EDIT_MSG))
> @@ -1425,7 +1447,7 @@ static int try_to_commit(struct repository *r,
>   	if (parse_head(r, &current_head))
>   		return -1;
>   	if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
> -	    setenv_committer_date_to_author_date())
> +	    !opts->ignore_date && setenv_committer_date_to_author_date())
>   		return -1;
>   	if (flags & AMEND_MSG) {
>   		const char *exclude_gpgsig[] = { "gpgsig", NULL };
> @@ -1447,7 +1469,7 @@ static int try_to_commit(struct repository *r,
>   			res = error(_("unable to parse commit author"));
>   			goto out;
>   		}
> -		if (opts->committer_date_is_author_date) {
> +		if (opts->committer_date_is_author_date && !opts->ignore_date) {

If we only handled committer_date_is_author_date in a single place it 
wouldn't need to be changed twice in this patch

>   			char *date;
>   			int len = strlen(author);
>   			char *idx = memchr(author, '>', len);
> @@ -1507,6 +1529,11 @@ static int try_to_commit(struct repository *r,
>   
>   	reset_ident_date();
>   
> +	if (opts->ignore_date) {
> +		ignore_author_date(&author);
> +		free(author_to_free);
> +		author_to_free = (char *)author;
> +	}
>   	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>   				 oid, author, opts->gpg_sign, extra)) {
>   		res = error(_("failed to write commit object"));
> @@ -2583,6 +2610,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->committer_date_is_author_date = 1;
>   		}
>   
> +		if (file_exists(rebase_path_ignore_date())) {
> +			opts->allow_ff = 0;
> +			opts->ignore_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2667,6 +2699,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_signoff(), "--signoff\n");
>   	if (opts->committer_date_is_author_date)
>   		write_file(rebase_path_cdate_is_adate(), "%s", "");
> +	if (opts->ignore_date)
> +		write_file(rebase_path_ignore_date(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3484,6 +3518,9 @@ static int do_merge(struct repository *r,
>   		argv_array_push(&cmd.args, git_path_merge_msg(r));
>   		if (opts->gpg_sign)
>   			argv_array_push(&cmd.args, opts->gpg_sign);
> +		if (opts->ignore_date)
> +			argv_array_pushf(&cmd.args,
> +					 "GIT_AUTHOR_DATE=%ld", time(NULL));
>   
>   		/* Add the tips to be merged */
>   		for (j = to_merge; j; j = j->next)
> @@ -3756,7 +3793,8 @@ static int pick_commits(struct repository *r,
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
>   				opts->record_origin || opts->edit ||
> -				opts->committer_date_is_author_date));
> +				opts->committer_date_is_author_date ||
> +				opts->ignore_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index e6cba468db..73d0515a3e 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -44,6 +44,7 @@ struct replay_opts {
>   	int quiet;
>   	int reschedule_failed_exec;
>   	int committer_date_is_author_date;
> +	int ignore_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index ceab48a831..95d99c4b7b 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back
>   	test_cmp authortime committertime
>   '
>   
> +# Checking for +0000 in author time is enough since default
> +# timezone is UTC, but the timezone used while committing
> +# sets to +0530.

That sounds potentially fragile but I guess the timezone is unlikely to 
change in the future

Best Wishes

Phillip

> +test_expect_success '--ignore-date works with am backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with interactive backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date -i HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
>   test_done
> 

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

* Re: [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date
  2019-08-06 17:36 ` [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
@ 2019-08-08 11:42   ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-08 11:42 UTC (permalink / raw)
  To: Rohit Ashiwal, Junio, GIT Mailing List; +Cc: Thomas, Elijah, Dscho, Martin

Hi Rohit

On 06/08/2019 18:36, Rohit Ashiwal wrote:
> The previous commit introduced --ignore-date flag to interactive
> rebase, but the name is actually very vague in context of rebase -i
> since there are two dates we can work with. Add an alias to convey
> the precise purpose.

That's an excellent idea

Best Wishes

Phillip

> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt | 1 +
>   builtin/rebase.c             | 2 ++
>   2 files changed, 3 insertions(+)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index a5cdf8518b..bb60426911 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.
>   	as the committer date. This implies --force-rebase.
>   
>   --ignore-date::
> +--author-date-is-committer-date::
>   	Lie about the author date by re-setting it to the value
>   	same as committer (current) date. This implies --force-rebase.
>   +
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 7f464fc9ba..a9a42f9ee4 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -1433,6 +1433,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		OPT_BOOL(0, "committer-date-is-author-date",
>   			 &options.committer_date_is_author_date,
>   			 N_("make committer date match author date")),
> +		OPT_BOOL(0, "author-date-is-committer-date", &options.ignore_date,
> +			 "ignore author date and use current date"),
>   		OPT_BOOL(0, "ignore-date", &options.ignore_date,
>   			 "ignore author date and use current date"),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> 

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

* Re: [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-08 11:29   ` Phillip Wood
@ 2019-08-08 16:00     ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-08-08 16:00 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, GIT Mailing List, Thomas, Elijah, Dscho, Martin

Phillip Wood <phillip.wood123@gmail.com> writes:

> ...
> I think it would be better to handle committer_date_is_author_date in
> a single place in this function, not have two implementations one of
> ...
> git has a high level api for manipulation author/committer information
> in ident.c, it would be best to use that. In any case code like this
> should be using strbuf's rather than malloc
> ...
> Do the committer_date_is_author_date check after the end of this if.
>
> Best Wishes
>
> Phillip

I've read all your review comments for this round, and they all
cover good points.  Thanks for a good reviewer and a mentor.  After
reading the patches myself, I have little to add ;-)

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

* Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date
  2019-08-08 11:42   ` Phillip Wood
@ 2019-08-08 16:53     ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-08 16:53 UTC (permalink / raw)
  To: Rohit Ashiwal, Junio, GIT Mailing List; +Cc: Thomas, Elijah, Dscho, Martin

On 08/08/2019 12:42, Phillip Wood wrote:
> On 06/08/2019 18:36, Rohit Ashiwal wrote:
>> rebase am already has this flag to "lie" about the author date
>> by changing it to the committer (current) date. Let's add the same
>> for interactive machinery.
>>
>> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>> ---
 >> [...[
>>   static const char staged_changes_advice[] =
>>   N_("you have staged changes in your working tree\n"
>>   "If these changes are meant to be squashed into the previous commit, 
>> run:\n"
>> @@ -985,7 +997,7 @@ static int run_git_commit(struct repository *r,
>>   {
>>       struct child_process cmd = CHILD_PROCESS_INIT;
>> -    if (opts->committer_date_is_author_date &&
>> +    if (opts->committer_date_is_author_date && !opts->ignore_date &&
>>           setenv_committer_date_to_author_date())
>>           return 1;
> 
> We read the author script again just below, can set the committer date 
> there by parsing the author string, that would mean you could use the 
> same function that works on an author string in try_to_commit() (this 
> comment should be on patch 3 I think)

It's a bit more complicated as you've done this to avoid the duplication 
in the previous version. I think it should be possible to do it by 
reading the author identity upfront (protected by 'if 
is_rebase_i(opts)') and processing it appropriately in the two code 
paths. (You might need to refactor some of the functions like 
read_env_script() to do this.) An alternative would be to refactor 
try_to_commit() so that it can create the root commit and delete the 
code here that does that.

Best Wishes

Phillip

> 
>>       if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
>> @@ -1013,10 +1025,18 @@ static int run_git_commit(struct repository *r,
>>           if (res <= 0)
>>               res = error_errno(_("could not read '%s'"), defmsg);
>> -        else
>> +        else {
>> +            if (opts->ignore_date) {
>> +                if (!author)
>> +                    BUG("ignore-date can only be used with "
>> +                        "rebase -i, which must set the "
> 
> I know it's only a bug message but it's not just 'rebase -i' but 'rebase 
> -k', 'rebase -m' ... that use this code path, it would be better just to 
> say 'rebase'
> 
>> +                        "author before committing the tree");
>> +                ignore_author_date(&author);
>> +            }
>>               res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>>                         NULL, &root_commit, author,
>>                         opts->gpg_sign);
>> +        }
>>           strbuf_release(&msg);
>>           strbuf_release(&script);
>> @@ -1046,6 +1066,8 @@ static int run_git_commit(struct repository *r,
>>           argv_array_push(&cmd.args, "--amend");
>>       if (opts->gpg_sign)
>>           argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>> +    if (opts->ignore_date)
>> +        argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
> 
> I think this is racy as it only sets the author date, the committer date 
> may end up being different.
> 
>>       if (defmsg)
>>           argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>>       else if (!(flags & EDIT_MSG))
>> @@ -1425,7 +1447,7 @@ static int try_to_commit(struct repository *r,
>>       if (parse_head(r, &current_head))
>>           return -1;
>>       if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
>> -        setenv_committer_date_to_author_date())
>> +        !opts->ignore_date && setenv_committer_date_to_author_date())
>>           return -1;
>>       if (flags & AMEND_MSG) {
>>           const char *exclude_gpgsig[] = { "gpgsig", NULL };
>> @@ -1447,7 +1469,7 @@ static int try_to_commit(struct repository *r,
>>               res = error(_("unable to parse commit author"));
>>               goto out;
>>           }
>> -        if (opts->committer_date_is_author_date) {
>> +        if (opts->committer_date_is_author_date && !opts->ignore_date) {
> 
> If we only handled committer_date_is_author_date in a single place it 
> wouldn't need to be changed twice in this patch
> 
>>               char *date;
>>               int len = strlen(author);
>>               char *idx = memchr(author, '>', len);
>> @@ -1507,6 +1529,11 @@ static int try_to_commit(struct repository *r,
>>       reset_ident_date();
>> +    if (opts->ignore_date) {
>> +        ignore_author_date(&author);
>> +        free(author_to_free);
>> +        author_to_free = (char *)author;
>> +    }
>>       if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>>                    oid, author, opts->gpg_sign, extra)) {
>>           res = error(_("failed to write commit object"));
>> @@ -2583,6 +2610,11 @@ static int read_populate_opts(struct 
>> replay_opts *opts)
>>               opts->committer_date_is_author_date = 1;
>>           }
>> +        if (file_exists(rebase_path_ignore_date())) {
>> +            opts->allow_ff = 0;
>> +            opts->ignore_date = 1;
>> +        }
>> +
>>           if (file_exists(rebase_path_reschedule_failed_exec()))
>>               opts->reschedule_failed_exec = 1;
>> @@ -2667,6 +2699,8 @@ int write_basic_state(struct replay_opts *opts, 
>> const char *head_name,
>>           write_file(rebase_path_signoff(), "--signoff\n");
>>       if (opts->committer_date_is_author_date)
>>           write_file(rebase_path_cdate_is_adate(), "%s", "");
>> +    if (opts->ignore_date)
>> +        write_file(rebase_path_ignore_date(), "%s", "");
>>       if (opts->reschedule_failed_exec)
>>           write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>> @@ -3484,6 +3518,9 @@ static int do_merge(struct repository *r,
>>           argv_array_push(&cmd.args, git_path_merge_msg(r));
>>           if (opts->gpg_sign)
>>               argv_array_push(&cmd.args, opts->gpg_sign);
>> +        if (opts->ignore_date)
>> +            argv_array_pushf(&cmd.args,
>> +                     "GIT_AUTHOR_DATE=%ld", time(NULL));
>>           /* Add the tips to be merged */
>>           for (j = to_merge; j; j = j->next)
>> @@ -3756,7 +3793,8 @@ static int pick_commits(struct repository *r,
>>       if (opts->allow_ff)
>>           assert(!(opts->signoff || opts->no_commit ||
>>                   opts->record_origin || opts->edit ||
>> -                opts->committer_date_is_author_date));
>> +                opts->committer_date_is_author_date ||
>> +                opts->ignore_date));
>>       if (read_and_refresh_cache(r, opts))
>>           return -1;
>> diff --git a/sequencer.h b/sequencer.h
>> index e6cba468db..73d0515a3e 100644
>> --- a/sequencer.h
>> +++ b/sequencer.h
>> @@ -44,6 +44,7 @@ struct replay_opts {
>>       int quiet;
>>       int reschedule_failed_exec;
>>       int committer_date_is_author_date;
>> +    int ignore_date;
>>       int mainline;
>> diff --git a/t/t3433-rebase-options-compatibility.sh 
>> b/t/t3433-rebase-options-compatibility.sh
>> index ceab48a831..95d99c4b7b 100755
>> --- a/t/t3433-rebase-options-compatibility.sh
>> +++ b/t/t3433-rebase-options-compatibility.sh
>> @@ -81,4 +81,20 @@ test_expect_success 
>> '--committer-date-is-author-date works with interactive back
>>       test_cmp authortime committertime
>>   '
>> +# Checking for +0000 in author time is enough since default
>> +# timezone is UTC, but the timezone used while committing
>> +# sets to +0530.
> 
> That sounds potentially fragile but I guess the timezone is unlikely to 
> change in the future
> 
> Best Wishes
> 
> Phillip
> 
>> +test_expect_success '--ignore-date works with am backend' '
>> +    git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> +    git rebase --ignore-date HEAD^ &&
>> +    git show HEAD --pretty="format:%ai" >authortime &&
>> +    grep "+0000" authortime
>> +'
>> +
>> +test_expect_success '--ignore-date works with interactive backend' '
>> +    git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> +    git rebase --ignore-date -i HEAD^ &&
>> +    git show HEAD --pretty="format:%ai" >authortime &&
>> +    grep "+0000" authortime
>> +'
>>   test_done
>>

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

* Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-08 16:44 [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2019-08-12 17:43 ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 17:43 UTC (permalink / raw)
  To: phillip.wood123
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	rohit.ashiwal265, t.gummerer

Hi Phillip

On Thu, 8 Aug 2019 17:44:38 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:
> 
> [...]
> >   --ignore-whitespace::
> > +	This flag is either passed to the 'git apply' program
> > +	(see linkgit:git-apply[1]), or to 'git merge' program
> > +	(see linkgit:git-merge[1]) as `-Xignore-space-change`,
> > +	depending on which backend is selected by other options.
> 
> I think it would be better to document the effect of this option rather
> than the implementation detail. It is confusing at the moment as it
> talks about 'git merge' but we don't allow this option with merges.

Oh, it is just to indicate the user where to look for the definitions
as currently the behaviour of both the backends is not exactly the
same neither do they work optimally. Hope in future when they are in
harmony, then we can happily change it to match the then behaviour.

> [...]

Thanks
Rohit


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

* [GSoC][PATCH v2 0/6] rebase -i: support more options
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (5 preceding siblings ...)
  2019-08-06 17:36 ` [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
@ 2019-08-12 19:42 ` Rohit Ashiwal
  2019-08-12 19:42   ` [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
                     ` (5 more replies)
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (2 subsequent siblings)
  9 siblings, 6 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:42 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

I've tried to work on all the suggestion in this revision.

Based on: 2e27de94d485a6da0c8e264c165e55100f1a13a8 (tag: v2.23.0-rc2)

Rohit Ashiwal (6):
  rebase -i: add --ignore-whitespace flag
  sequencer: add NULL checks under read_author_script
  rebase -i: support --committer-date-is-author-date
  sequencer: rename amend_author to author_to_rename
  rebase -i: support --ignore-date
  rebase: add --author-date-is-committer-date

 Documentation/git-rebase.txt            |  23 +++--
 builtin/rebase.c                        |  66 +++++++++---
 sequencer.c                             | 132 ++++++++++++++++++++++--
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 100 ++++++++++++++++++
 6 files changed, 295 insertions(+), 30 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

Range-diff:
1:  e213112385 ! 1:  4cd0aa3084 rebase -i: add --ignore-whitespace flag
    @@ -60,32 +60,35 @@
      	int autostash;
      	char *cmd;
     @@
    - 		.git_format_patch_opt = STRBUF_INIT	\
    - 	}
      
    --static struct replay_opts get_replay_opts(const struct rebase_options *opts)
    -+static struct replay_opts get_replay_opts(struct rebase_options *opts)
    + static struct replay_opts get_replay_opts(const struct rebase_options *opts)
      {
    ++	char *strategy_opts = opts->strategy_opts;
      	struct replay_opts replay = REPLAY_OPTS_INIT;
      
    + 	replay.action = REPLAY_INTERACTIVE_REBASE;
     @@
      	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
    +-	if (opts->strategy_opts)
    +-		parse_strategy_opts(&replay, opts->strategy_opts);
     +
     +	if (opts->ignore_whitespace) {
     +		struct strbuf buf = STRBUF_INIT;
     +
    -+		if (opts->strategy_opts)
    -+			strbuf_addstr(&buf, opts->strategy_opts);
    ++		if (strategy_opts)
    ++			strbuf_addstr(&buf, strategy_opts);
     +
     +		strbuf_addstr(&buf, " --ignore-space-change");
    -+		free(opts->strategy_opts);
    -+		opts->strategy_opts = strbuf_detach(&buf, NULL);
    ++		free(strategy_opts);
    ++		strategy_opts = strbuf_detach(&buf, NULL);
     +	}
    - 	if (opts->strategy_opts)
    - 		parse_strategy_opts(&replay, opts->strategy_opts);
    ++	if (strategy_opts)
    ++		parse_strategy_opts(&replay, strategy_opts);
      
    + 	return replay;
    + }
     @@
      	argc = parse_options(argc, argv, prefix, options,
      			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
    @@ -165,14 +168,14 @@
     +# both the backends fall short of optimal behaviour.
     +test_expect_success 'setup' '
     +	git checkout -b topic &&
    -+	q_to_tab >file <<-EOF &&
    ++	q_to_tab >file <<-\EOF &&
     +	line 1
     +	Qline 2
     +	line 3
     +	EOF
     +	git add file &&
     +	git commit -m "add file" &&
    -+	cat >file <<-EOF &&
    ++	cat >file <<-\EOF &&
     +	line 1
     +	new line 2
     +	line 3
    @@ -181,10 +184,10 @@
     +	git tag side &&
     +
     +	git checkout --orphan master &&
    -+	cat >file <<-EOF &&
    -+	line 1
    -+	        line 2
    -+	line 3
    ++	sed -e "s/^|//" >file <<-\EOF &&
    ++	|line 1
    ++	|        line 2
    ++	|line 3
     +	EOF
     +	git add file &&
     +	git commit -m "add file" &&
    @@ -192,7 +195,7 @@
     +'
     +
     +test_expect_success '--ignore-whitespace works with am backend' '
    -+	cat >expect <<-EOF &&
    ++	cat >expect <<-\EOF &&
     +	line 1
     +	new line 2
     +	line 3
    @@ -204,7 +207,7 @@
     +'
     +
     +test_expect_success '--ignore-whitespace works with interactive backend' '
    -+	cat >expect <<-EOF &&
    ++	cat >expect <<-\EOF &&
     +	line 1
     +	new line 2
     +	line 3
2:  df13514788 = 2:  e2c0304587 sequencer: add NULL checks under read_author_script
3:  5735ec9ca2 ! 3:  6aed57ae2e rebase -i: support --committer-date-is-author-date
    @@ -140,31 +140,28 @@
      static const char *read_author_ident(struct strbuf *buf)
      {
     @@
    - 	return buf->buf;
    - }
    + {
    + 	struct child_process cmd = CHILD_PROCESS_INIT;
      
    -+static int setenv_committer_date_to_author_date(void)
    -+{
    -+	int res = 1;
    -+	char *date = read_author_date_or_null();
    ++	if (opts->committer_date_is_author_date) {
    ++		size_t len;
    ++		int res = -1;
    ++		struct strbuf datebuf = STRBUF_INIT;
    ++		char *date = read_author_date_or_null();
     +
    -+	if (date)
    -+		res = setenv("GIT_COMMITTER_DATE", date, 1);
    ++		strbuf_addf(&datebuf, "@%s", date);
    ++		free(date);
     +
    -+	free(date);
    -+	return res;
    -+}
    ++		date = strbuf_detach(&datebuf, &len);
     +
    - static const char staged_changes_advice[] =
    - N_("you have staged changes in your working tree\n"
    - "If these changes are meant to be squashed into the previous commit, run:\n"
    -@@
    - {
    - 	struct child_process cmd = CHILD_PROCESS_INIT;
    - 
    -+	if (opts->committer_date_is_author_date &&
    -+	    setenv_committer_date_to_author_date())
    -+		return 1;
    ++		if (len > 1)
    ++			res = setenv("GIT_COMMITTER_DATE", date, 1);
    ++
    ++		free(date);
    ++
    ++		if (res)
    ++			return -1;
    ++	}
      	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
      		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
      		const char *author = NULL;
    @@ -173,30 +170,31 @@
      	if (parse_head(r, &current_head))
      		return -1;
     -
    -+	if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
    -+	    setenv_committer_date_to_author_date())
    -+		return -1;
      	if (flags & AMEND_MSG) {
      		const char *exclude_gpgsig[] = { "gpgsig", NULL };
      		const char *out_enc = get_commit_output_encoding();
     @@
    - 			res = error(_("unable to parse commit author"));
    - 			goto out;
    - 		}
    -+		if (opts->committer_date_is_author_date) {
    -+			char *date;
    -+			int len = strlen(author);
    -+			char *idx = memchr(author, '>', len);
    + 		commit_list_insert(current_head, &parents);
    + 	}
    + 
    ++	if (opts->committer_date_is_author_date) {
    ++		int len = strlen(author);
    ++		struct ident_split ident;
    ++		struct strbuf date = STRBUF_INIT;
     +
    -+			++idx;
    -+			date = malloc(author + len - idx);
    -+			memcpy(date, idx, author + len - idx);
    -+			setenv("GIT_COMMITTER_DATE", date, 1);
    -+			free(date);
    -+		}
    - 		parents = copy_commit_list(current_head->parents);
    - 		extra = read_commit_extra_headers(current_head, exclude_gpgsig);
    - 	} else if (current_head) {
    ++		split_ident_line(&ident, author, len);
    ++
    ++		if (!ident.date_begin)
    ++			return error(_("corrupted author without date information"));
    ++
    ++		strbuf_addf(&date, "@%s",ident.date_begin);
    ++		setenv("GIT_COMMITTER_DATE", date.buf, 1);
    ++		strbuf_release(&date);
    ++	}
    ++
    + 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
    + 		res = error(_("git write-tree failed to write a tree"));
    + 		goto out;
     @@
      			opts->signoff = 1;
      		}
    @@ -271,18 +269,18 @@
      '
      
     +test_expect_success '--committer-date-is-author-date works with am backend' '
    -+	git rebase -f HEAD^ &&
    ++	git commit --amend &&
     +	git rebase --committer-date-is-author-date HEAD^ &&
    -+	git show HEAD --pretty="format:%at" >authortime &&
    -+	git show HEAD --pretty="format:%ct" >committertime &&
    ++	git show HEAD --pretty="format:%ai" >authortime &&
    ++	git show HEAD --pretty="format:%ci" >committertime &&
     +	test_cmp authortime committertime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works with interactive backend' '
    -+	git rebase -f HEAD^ &&
    ++	git commit --amend &&
     +	git rebase -i --committer-date-is-author-date HEAD^ &&
    -+	git show HEAD --pretty="format:%at" >authortime &&
    -+	git show HEAD --pretty="format:%ct" >committertime &&
    ++	git show HEAD --pretty="format:%ai" >authortime &&
    ++	git show HEAD --pretty="format:%ci" >committertime &&
     +	test_cmp authortime committertime
     +'
     +
4:  cdcd66347b ! 4:  36a0c017c2 sequencer: rename amend_author to author_to_rename
    @@ -3,8 +3,9 @@
         sequencer: rename amend_author to author_to_rename
     
         The purpose of amend_author was to free() the malloc()'d string
    -    obtained from get_author(). But the name does not actually convey
    -    this purpose. Rename it to something meaningful.
    +    obtained from get_author() while amending a commit. But we can
    +    also use the variable to free() the author at our convenience.
    +    Rename it to convey this meaning.
     
         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
     
5:  2f45a4e0b9 ! 5:  3a4ffeb995 rebase -i: support --ignore-date
    @@ -17,7 +17,7 @@
      --ignore-date::
     -	This flag is passed to 'git am' to change the author date
     -	of the rebased commits (see linkgit:git-am[1]).
    -+	Lie about the author date by re-setting it to the value
    ++	Instead of using the given author date, re-set it to the value
     +	same as committer (current) date. This implies --force-rebase.
      +
      See also INCOMPATIBLE OPTIONS below.
    @@ -63,6 +63,8 @@
      			  "--rebase-merges"));
      
     -	if (opts.committer_date_is_author_date)
    ++	if (opts.ignore_date)
    ++		opts.committer_date_is_author_date = 0;
     +	if (opts.committer_date_is_author_date ||
     +	    opts.ignore_date)
      		opts.flags |= REBASE_FORCE;
    @@ -93,6 +95,8 @@
      	}
      
     -	if (options.committer_date_is_author_date)
    ++	if (options.ignore_date)
    ++		options.committer_date_is_author_date = 0;
     +	if (options.committer_date_is_author_date ||
     +	    options.ignore_date)
      		options.flags |= REBASE_FORCE;
    @@ -118,33 +122,38 @@
      static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
      static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
     @@
    - 	return res;
    + 	return buf->buf;
      }
      
     +static void ignore_author_date(const char **author)
     +{
    ++	int len = strlen(*author);
    ++	struct ident_split ident;
     +	struct strbuf new_author = STRBUF_INIT;
    -+	char *idx = memchr(*author, '>', strlen(*author));
     +
    -+	strbuf_add(&new_author, *author, idx - *author);
    -+	strbuf_addstr(&new_author, "> ");
    ++	split_ident_line(&ident, *author, len);
    ++	len = ident.mail_end - ident.name_begin + 1;
    ++
    ++	strbuf_addf(&new_author, "%.*s", len, *author);
     +	datestamp(&new_author);
     +	*author = strbuf_detach(&new_author, NULL);
     +}
    ++
    ++static void push_dates(struct child_process *child)
    ++{
    ++	time_t now = time(NULL);
    ++	struct strbuf date = STRBUF_INIT;
    ++
    ++	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
    ++	argv_array_pushf(&child->args, "--date=%s", date.buf);
    ++	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
    ++	strbuf_release(&date);
    ++}
     +
      static const char staged_changes_advice[] =
      N_("you have staged changes in your working tree\n"
      "If these changes are meant to be squashed into the previous commit, run:\n"
     @@
    - {
    - 	struct child_process cmd = CHILD_PROCESS_INIT;
    - 
    --	if (opts->committer_date_is_author_date &&
    -+	if (opts->committer_date_is_author_date && !opts->ignore_date &&
    - 	    setenv_committer_date_to_author_date())
    - 		return 1;
    - 	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
    -@@
      
      		if (res <= 0)
      			res = error_errno(_("could not read '%s'"), defmsg);
    @@ -153,8 +162,8 @@
     +			if (opts->ignore_date) {
     +				if (!author)
     +					BUG("ignore-date can only be used with "
    -+					    "rebase -i, which must set the "
    -+					    "author before committing the tree");
    ++					    "rebase, which must set the author "
    ++					    "before committing the tree");
     +				ignore_author_date(&author);
     +			}
      			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
    @@ -169,29 +178,11 @@
      	if (opts->gpg_sign)
      		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
     +	if (opts->ignore_date)
    -+		argv_array_pushf(&cmd.args, "--date=%ld", time(NULL));
    ++		push_dates(&cmd);
      	if (defmsg)
      		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
      	else if (!(flags & EDIT_MSG))
     @@
    - 	if (parse_head(r, &current_head))
    - 		return -1;
    - 	if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&
    --	    setenv_committer_date_to_author_date())
    -+	    !opts->ignore_date && setenv_committer_date_to_author_date())
    - 		return -1;
    - 	if (flags & AMEND_MSG) {
    - 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
    -@@
    - 			res = error(_("unable to parse commit author"));
    - 			goto out;
    - 		}
    --		if (opts->committer_date_is_author_date) {
    -+		if (opts->committer_date_is_author_date && !opts->ignore_date) {
    - 			char *date;
    - 			int len = strlen(author);
    - 			char *idx = memchr(author, '>', len);
    -@@
      
      	reset_ident_date();
      
    @@ -229,8 +220,7 @@
      		if (opts->gpg_sign)
      			argv_array_push(&cmd.args, opts->gpg_sign);
     +		if (opts->ignore_date)
    -+			argv_array_pushf(&cmd.args,
    -+					 "GIT_AUTHOR_DATE=%ld", time(NULL));
    ++			push_dates(&cmd);
      
      		/* Add the tips to be merged */
      		for (j = to_merge; j; j = j->next)
6:  8fa3da175c ! 6:  cb81e6c4e5 rebase: add --author-date-is-committer-date
    @@ -17,7 +17,7 @@
      
      --ignore-date::
     +--author-date-is-committer-date::
    - 	Lie about the author date by re-setting it to the value
    + 	Instead of using the given author date, re-set it to the value
      	same as committer (current) date. This implies --force-rebase.
      +
     
-- 
2.21.0


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

* [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
@ 2019-08-12 19:42   ` Rohit Ashiwal
  2019-08-13 12:07     ` Phillip Wood
  2019-08-12 19:42   ` [GSoC][PATCH v2 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:42 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

There are two backends available for rebasing, viz, the am and the
interactive. Naturally, there shall be some features that are
implemented in one but not in the other. One such flag is
--ignore-whitespace which indicates merge mechanism to treat lines
with only whitespace changes as unchanged. Wire the interactive
rebase to also understand the --ignore-whitespace flag by
translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 10 +++-
 builtin/rebase.c                        | 29 +++++++++--
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
 4 files changed, 97 insertions(+), 8 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 6156609cf7..28e5e08a83 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -371,8 +371,13 @@ If either <upstream> or --root is given on the command line, then the
 default is `--no-fork-point`, otherwise the default is `--fork-point`.
 
 --ignore-whitespace::
+	This flag is either passed to the 'git apply' program
+	(see linkgit:git-apply[1]), or to 'git merge' program
+	(see linkgit:git-merge[1]) as `-Xignore-space-change`,
+	depending on which backend is selected by other options.
+
 --whitespace=<option>::
-	These flag are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -520,7 +525,6 @@ The following options:
  * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
- * --ignore-whitespace
  * -C
 
 are incompatible with the following options:
@@ -543,6 +547,8 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --interactive
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
+ * --preserve-merges and --ignore-whitespace
+ * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 670096c065..ab1bbb78ee 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -79,6 +79,7 @@ struct rebase_options {
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -99,6 +100,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	char *strategy_opts = opts->strategy_opts;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -114,8 +116,19 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
-	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+
+	if (opts->ignore_whitespace) {
+		struct strbuf buf = STRBUF_INIT;
+
+		if (strategy_opts)
+			strbuf_addstr(&buf, strategy_opts);
+
+		strbuf_addstr(&buf, " --ignore-space-change");
+		free(strategy_opts);
+		strategy_opts = strbuf_detach(&buf, NULL);
+	}
+	if (strategy_opts)
+		parse_strategy_opts(&replay, strategy_opts);
 
 	return replay;
 }
@@ -511,6 +524,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -964,6 +979,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1407,9 +1424,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1417,6 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1834,6 +1850,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	if (options.rebase_merges) {
+		if (options.ignore_whitespace)
+			die(_("cannot combine '--rebase-merges' with "
+			      "'--ignore-whitespace'"));
 		if (strategy_options.nr)
 			die(_("cannot combine '--rebase-merges' with "
 			      "'--strategy-option'"));
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index a5868ea152..4342f79eea 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
new file mode 100755
index 0000000000..2e16e00a9d
--- /dev/null
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with am backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase main side &&
+	git rebase --abort &&
+	git rebase --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with interactive backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_done
-- 
2.21.0


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

* [GSoC][PATCH v2 2/6] sequencer: add NULL checks under read_author_script
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-12 19:42   ` [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-08-12 19:42   ` Rohit Ashiwal
  2019-08-12 19:42   ` [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:42 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

read_author_script reads name, email and author date from the author
script. However, it does not check if the arguments are NULL. Adding
NULL checks will allow us to selectively get the required value, for
example:

    char *date;
    if (read_author_script(_path_, NULL, NULL, &date, _int_))
	    die(_("failed to read author date"));
    /* needs to be free()'d */
    return date;

Add NULL checks for better control over the information retrieved.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 34ebf8ed94..30d77c2682 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -824,9 +824,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-	*name = kv.items[name_i].util;
-	*email = kv.items[email_i].util;
-	*date = kv.items[date_i].util;
+
+	if (name)
+		*name = kv.items[name_i].util;
+	else
+		free(kv.items[name_i].util);
+	if (email)
+		*email = kv.items[email_i].util;
+	else
+		free(kv.items[email_i].util);
+	if (date)
+		*date = kv.items[date_i].util;
+	else
+		free(kv.items[date_i].util);
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
-- 
2.21.0


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

* [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-12 19:42   ` [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
  2019-08-12 19:42   ` [GSoC][PATCH v2 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
@ 2019-08-12 19:42   ` Rohit Ashiwal
  2019-08-13 10:38     ` Phillip Wood
  2019-08-13 13:35     ` Phillip Wood
  2019-08-12 19:42   ` [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
                     ` (2 subsequent siblings)
  5 siblings, 2 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:42 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the committer date
by changing it to the author date. Let's add the same for
interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  8 +++-
 builtin/rebase.c                        | 20 ++++++---
 sequencer.c                             | 57 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 19 +++++++++
 6 files changed, 96 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 28e5e08a83..697ce8e6ff 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of recording the time the rebased commits are
+	created as the committer date, reuse the author date
+	as the committer date. This implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
+	This flag is passed to 'git am' to change the author date
 	of the rebased commits (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -548,6 +551,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index ab1bbb78ee..b1039f8db0 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -82,6 +82,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.allow_empty_message = opts->allow_empty_message;
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -533,6 +536,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 		warning(_("--[no-]rebase-cousins has no effect without "
 			  "--rebase-merges"));
 
+	if (opts.committer_date_is_author_date)
+		opts.flags |= REBASE_FORCE;
+
 	return !!run_rebase_interactive(&opts, command);
 }
 
@@ -981,6 +987,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1424,9 +1432,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1697,10 +1705,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
+
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
diff --git a/sequencer.c b/sequencer.c
index 30d77c2682..fbc0ed0cad 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -879,6 +880,17 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+/* Returns a "date" string that needs to be free()'d by the caller */
+static char *read_author_date_or_null(void)
+{
+	char *date;
+
+	if (read_author_script(rebase_path_author_script(),
+			       NULL, NULL, &date, 0))
+		return NULL;
+	return date;
+}
+
 /* Read author-script and return an ident line (author <email> timestamp) */
 static const char *read_author_ident(struct strbuf *buf)
 {
@@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 
+	if (opts->committer_date_is_author_date) {
+		size_t len;
+		int res = -1;
+		struct strbuf datebuf = STRBUF_INIT;
+		char *date = read_author_date_or_null();
+
+		strbuf_addf(&datebuf, "@%s", date);
+		free(date);
+
+		date = strbuf_detach(&datebuf, &len);
+
+		if (len > 1)
+			res = setenv("GIT_COMMITTER_DATE", date, 1);
+
+		free(date);
+
+		if (res)
+			return -1;
+	}
 	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
 		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
 		const char *author = NULL;
@@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,
 
 	if (parse_head(r, &current_head))
 		return -1;
-
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		split_ident_line(&ident, author, len);
+
+		if (!ident.date_begin)
+			return error(_("corrupted author without date information"));
+
+		strbuf_addf(&date, "@%s",ident.date_begin);
+		setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2542,6 +2587,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
 	if (opts->signoff)
 		write_file(rebase_path_signoff(), "--signoff\n");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3821,7 +3873,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 6704acbb9c..e3881e9275 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -43,6 +43,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 4342f79eea..7402f7e3da 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 2e16e00a9d..b2419a2b75 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . ./test-lib.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with am backend' '
+	git commit --amend &&
+	git rebase --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with interactive backend' '
+	git commit --amend &&
+	git rebase -i --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
 test_done
-- 
2.21.0


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

* [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (2 preceding siblings ...)
  2019-08-12 19:42   ` [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-08-12 19:42   ` Rohit Ashiwal
  2019-08-13 13:29     ` Phillip Wood
  2019-08-12 19:42   ` [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date Rohit Ashiwal
  2019-08-12 19:43   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
  5 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:42 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() while amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index fbc0ed0cad..e186136ccc 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1424,7 +1424,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1445,7 +1445,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1534,7 +1534,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.21.0


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

* [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (3 preceding siblings ...)
  2019-08-12 19:42   ` [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-08-12 19:42   ` Rohit Ashiwal
  2019-08-13 13:28     ` Phillip Wood
  2019-08-13 21:45     ` Junio C Hamano
  2019-08-12 19:43   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
  5 siblings, 2 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:42 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the author date
by changing it to the committer (current) date. Let's add the same
for interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  6 +--
 builtin/rebase.c                        | 21 +++++++---
 sequencer.c                             | 55 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3433-rebase-options-compatibility.sh | 16 +++++++
 5 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 697ce8e6ff..24ad2dda0b 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of the rebased commits (see linkgit:git-am[1]).
+	Instead of using the given author date, re-set it to the value
+	same as committer (current) date. This implies --force-rebase.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --ignore-date
  * --whitespace
  * -C
 
@@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index b1039f8db0..ed58ca8e5a 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -83,6 +83,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -536,7 +538,10 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 		warning(_("--[no-]rebase-cousins has no effect without "
 			  "--rebase-merges"));
 
-	if (opts.committer_date_is_author_date)
+	if (opts.ignore_date)
+		opts.committer_date_is_author_date = 0;
+	if (opts.committer_date_is_author_date ||
+	    opts.ignore_date)
 		opts.flags |= REBASE_FORCE;
 
 	return !!run_rebase_interactive(&opts, command);
@@ -989,6 +994,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1435,8 +1442,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1705,13 +1712,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
-	if (options.committer_date_is_author_date)
+	if (options.ignore_date)
+		options.committer_date_is_author_date = 0;
+	if (options.committer_date_is_author_date ||
+	    options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index e186136ccc..aecd9b4ad8 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -919,6 +920,31 @@ static const char *read_author_ident(struct strbuf *buf)
 	return buf->buf;
 }
 
+static void ignore_author_date(const char **author)
+{
+	int len = strlen(*author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	split_ident_line(&ident, *author, len);
+	len = ident.mail_end - ident.name_begin + 1;
+
+	strbuf_addf(&new_author, "%.*s", len, *author);
+	datestamp(&new_author);
+	*author = strbuf_detach(&new_author, NULL);
+}
+
+static void push_dates(struct child_process *child)
+{
+	time_t now = time(NULL);
+	struct strbuf date = STRBUF_INIT;
+
+	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
+	argv_array_pushf(&child->args, "--date=%s", date.buf);
+	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
+	strbuf_release(&date);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -1020,10 +1046,18 @@ static int run_git_commit(struct repository *r,
 
 		if (res <= 0)
 			res = error_errno(_("could not read '%s'"), defmsg);
-		else
+		else {
+			if (opts->ignore_date) {
+				if (!author)
+					BUG("ignore-date can only be used with "
+					    "rebase, which must set the author "
+					    "before committing the tree");
+				ignore_author_date(&author);
+			}
 			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
 					  NULL, &root_commit, author,
 					  opts->gpg_sign);
+		}
 
 		strbuf_release(&msg);
 		strbuf_release(&script);
@@ -1053,6 +1087,8 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+	if (opts->ignore_date)
+		push_dates(&cmd);
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		ignore_author_date(&author);
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2592,6 +2633,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2676,6 +2722,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_signoff(), "--signoff\n");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3601,6 +3649,8 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
+		if (opts->ignore_date)
+			push_dates(&cmd);
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3874,7 +3924,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index e3881e9275..bf5a79afdb 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -44,6 +44,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index b2419a2b75..c060fcd10b 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back
 	test_cmp authortime committertime
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with am backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with interactive backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -i HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
 test_done
-- 
2.21.0


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

* [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (4 preceding siblings ...)
  2019-08-12 19:42   ` [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-08-12 19:43   ` Rohit Ashiwal
  2019-08-13 17:28     ` Junio C Hamano
  5 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-12 19:43 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The previous commit introduced --ignore-date flag to interactive
rebase, but the name is actually very vague in context of rebase -i
since there are two dates we can work with. Add an alias to convey
the precise purpose.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt | 1 +
 builtin/rebase.c             | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 24ad2dda0b..6a52d721e2 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
+--author-date-is-committer-date::
 	Instead of using the given author date, re-set it to the value
 	same as committer (current) date. This implies --force-rebase.
 +
diff --git a/builtin/rebase.c b/builtin/rebase.c
index ed58ca8e5a..19b1fc0f3a 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1442,6 +1442,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
+		OPT_BOOL(0, "author-date-is-committer-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_BOOL(0, "ignore-date", &options.ignore_date,
 			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-- 
2.21.0


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

* Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-12 19:42   ` [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-08-13 10:38     ` Phillip Wood
  2019-08-13 12:09       ` Phillip Wood
  2019-08-13 17:06       ` Junio C Hamano
  2019-08-13 13:35     ` Phillip Wood
  1 sibling, 2 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-13 10:38 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

This is looking good, I think it is almost there now

On 12/08/2019 20:42, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the committer date
> by changing it to the author date. Let's add the same for
> interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            |  8 +++-
>   builtin/rebase.c                        | 20 ++++++---
>   sequencer.c                             | 57 ++++++++++++++++++++++++-
>   sequencer.h                             |  1 +
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++
>   6 files changed, 96 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 28e5e08a83..697ce8e6ff 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
>   See also INCOMPATIBLE OPTIONS below.
>   
>   --committer-date-is-author-date::
> +	Instead of recording the time the rebased commits are
> +	created as the committer date, reuse the author date
> +	as the committer date. This implies --force-rebase.
> +
>   --ignore-date::
> -	These flags are passed to 'git am' to easily change the dates
> +	This flag is passed to 'git am' to change the author date
>   	of the rebased commits (see linkgit:git-am[1]).
>   +
>   See also INCOMPATIBLE OPTIONS below.
> @@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
>    * -C
> @@ -548,6 +551,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index ab1bbb78ee..b1039f8db0 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -82,6 +82,7 @@ struct rebase_options {
>   	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
> +	int committer_date_is_author_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.allow_empty_message = opts->allow_empty_message;
>   	replay.verbose = opts->flags & REBASE_VERBOSE;
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +	replay.committer_date_is_author_date =
> +					opts->committer_date_is_author_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -533,6 +536,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   		warning(_("--[no-]rebase-cousins has no effect without "
>   			  "--rebase-merges"));
>   
> +	if (opts.committer_date_is_author_date)
> +		opts.flags |= REBASE_FORCE;
> +
>   	return !!run_rebase_interactive(&opts, command);
>   }
>   
> @@ -981,6 +987,8 @@ static int run_am(struct rebase_options *opts)
>   
>   	if (opts->ignore_whitespace)
>   		argv_array_push(&am.args, "--ignore-whitespace");
> +	if (opts->committer_date_is_author_date)
> +		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1424,9 +1432,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -				  &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "committer-date-is-author-date",
> +			 &options.committer_date_is_author_date,
> +			 N_("make committer date match author date")),
>   		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1697,10 +1705,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> +	if (options.committer_date_is_author_date)
> +		options.flags |= REBASE_FORCE;
> +
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--committer-date-is-author-date") ||
> -		    !strcmp(option, "--ignore-date") ||
> +		if (!strcmp(option, "--ignore-date") ||
>   		    !strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
> diff --git a/sequencer.c b/sequencer.c
> index 30d77c2682..fbc0ed0cad 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    * command-line.
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -879,6 +880,17 @@ static char *get_author(const char *message)
>   	return NULL;
>   }
>   
> +/* Returns a "date" string that needs to be free()'d by the caller */
> +static char *read_author_date_or_null(void)
> +{
> +	char *date;
> +
> +	if (read_author_script(rebase_path_author_script(),
> +			       NULL, NULL, &date, 0))
> +		return NULL;
> +	return date;
> +}
> +
>   /* Read author-script and return an ident line (author <email> timestamp) */
>   static const char *read_author_ident(struct strbuf *buf)
>   {
> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,
>   {
>   	struct child_process cmd = CHILD_PROCESS_INIT;
>   
> +	if (opts->committer_date_is_author_date) {
> +		size_t len;
> +		int res = -1;
> +		struct strbuf datebuf = STRBUF_INIT;
> +		char *date = read_author_date_or_null();

You must always check the return value of functions that might return 
NULL. In this case we should return an error as you do in try_to 
_commit() later

> +
> +		strbuf_addf(&datebuf, "@%s", date);

GNU printf() will add something like '(null)' to the buffer if you pass 
a NULL pointer so I don't think we can be sure that this will not 
increase the length of the buffer if date is NULL. An explicit check 
above would be much clearer as well rather than checking len later. What 
happens if you don't add the '@' at the beginning? (I'm don't know much 
about git's date handling)

> +		free(date);
> +
> +		date = strbuf_detach(&datebuf, &len);
> +
> +		if (len > 1)
> +			res = setenv("GIT_COMMITTER_DATE", date, 1);
> +
> +		free(date);
> +
> +		if (res)
> +			return -1;
> +	}
>   	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
>   		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
>   		const char *author = NULL;
> @@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,
>   
>   	if (parse_head(r, &current_head))
>   		return -1;
> -
>   	if (flags & AMEND_MSG) {
>   		const char *exclude_gpgsig[] = { "gpgsig", NULL };
>   		const char *out_enc = get_commit_output_encoding();
> @@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,
>   		commit_list_insert(current_head, &parents);
>   	}
>   
> +	if (opts->committer_date_is_author_date) {
> +		int len = strlen(author);
> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		split_ident_line(&ident, author, len);
> +
> +		if (!ident.date_begin)
> +			return error(_("corrupted author without date information"));

We return an error if we cannot get the date - this is exactly what we 
should be doing above. It is also great to see a single version of this 
being used whether or not we are amending.

> +
> +		strbuf_addf(&date, "@%s",ident.date_begin);

I think we should use %s.* and ident.date_end to be sure we getting what 
we want. Your version is OK if the author is formatted correctly but I'm 
uneasy about relying on that when we can get the verified end from ident.

Best Wishes

Phillip

> +		setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		strbuf_release(&date);
> +	}
> +
>   	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>   		res = error(_("git write-tree failed to write a tree"));
>   		goto out;
> @@ -2542,6 +2587,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->signoff = 1;
>   		}
>   
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
>   	if (opts->signoff)
>   		write_file(rebase_path_signoff(), "--signoff\n");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3821,7 +3873,8 @@ static int pick_commits(struct repository *r,
>   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index 6704acbb9c..e3881e9275 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -43,6 +43,7 @@ struct replay_opts {
>   	int verbose;
>   	int quiet;
>   	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 4342f79eea..7402f7e3da 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 2e16e00a9d..b2419a2b75 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>   
>   . ./test-lib.sh
>   
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>   # This is a special case in which both am and interactive backends
>   # provide the same output. It was done intentionally because
>   # both the backends fall short of optimal behaviour.
> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>   	test_cmp expect file
>   '
>   
> +test_expect_success '--committer-date-is-author-date works with am backend' '
> +	git commit --amend &&
> +	git rebase --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
> +	git commit --amend &&
> +	git rebase -i --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
>   test_done
> 

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

* Re: [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-12 19:42   ` [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-08-13 12:07     ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-13 12:07 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

Thanks for the re-roll

On 12/08/2019 20:42, Rohit Ashiwal wrote:
> There are two backends available for rebasing, viz, the am and the
> interactive. Naturally, there shall be some features that are
> implemented in one but not in the other. One such flag is
> --ignore-whitespace which indicates merge mechanism to treat lines
> with only whitespace changes as unchanged. Wire the interactive
> rebase to also understand the --ignore-whitespace flag by
> translating it to -Xignore-space-change.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            | 10 +++-
>   builtin/rebase.c                        | 29 +++++++++--
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
>   4 files changed, 97 insertions(+), 8 deletions(-)
>   create mode 100755 t/t3433-rebase-options-compatibility.sh
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 6156609cf7..28e5e08a83 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -371,8 +371,13 @@ If either <upstream> or --root is given on the command line, then the
>   default is `--no-fork-point`, otherwise the default is `--fork-point`.
>   
>   --ignore-whitespace::
> +	This flag is either passed to the 'git apply' program
> +	(see linkgit:git-apply[1]), or to 'git merge' program
> +	(see linkgit:git-merge[1]) as `-Xignore-space-change`,
> +	depending on which backend is selected by other options.

I still think this should document what it does rather than how it is 
implemented - see my previous comments.
> +
>   --whitespace=<option>::
> -	These flag are passed to the 'git apply' program
> +	This flag is passed to the 'git apply' program
>   	(see linkgit:git-apply[1]) that applies the patch.
>   +
>   See also INCOMPATIBLE OPTIONS below.
> @@ -520,7 +525,6 @@ The following options:
>    * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
> - * --ignore-whitespace
>    * -C
>   
>   are incompatible with the following options:
> @@ -543,6 +547,8 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --interactive
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
> + * --preserve-merges and --ignore-whitespace
> + * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
>   
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 670096c065..ab1bbb78ee 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -79,6 +79,7 @@ struct rebase_options {
>   	int allow_rerere_autoupdate;
>   	int keep_empty;
>   	int autosquash;
> +	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
>   	char *cmd;
> @@ -99,6 +100,7 @@ struct rebase_options {
>   
>   static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   {
> +	char *strategy_opts = opts->strategy_opts;

strategy_opts is a shallow copy of opts->strategy_opts - this will cause 
problems later

>   	struct replay_opts replay = REPLAY_OPTS_INIT;
>   
>   	replay.action = REPLAY_INTERACTIVE_REBASE;
> @@ -114,8 +116,19 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
> -	if (opts->strategy_opts)
> -		parse_strategy_opts(&replay, opts->strategy_opts);
> +
> +	if (opts->ignore_whitespace) {
> +		struct strbuf buf = STRBUF_INIT;
> +
> +		if (strategy_opts)
> +			strbuf_addstr(&buf, strategy_opts);

I'd rewrite this as
	if (opts->strategy_opts)
		strbuf_addstr(&buf, opts->strategy_opts);

without the outer if testing opts->ignore_whitespace
> +
then add
	if (opts->ignore_whitespace)
here
> +		strbuf_addstr(&buf, " --ignore-space-change");
> +		free(strategy_opts);

and then you don't need this free() or strategy_opts. At the moment this 
has freed opts->stragety_opts which is what we were trying to avoid, in 
fact it's slightly worse than the last version because we don't change 
opts->strategy_opts to reflect the fact it has been freed. Also the 
caller cannot know if it has been freed as it depends what other options 
are set.

> +		strategy_opts = strbuf_detach(&buf, NULL);
> +	}
> +	if (strategy_opts)
> +		parse_strategy_opts(&replay, strategy_opts);

replace this withe
	if (buf.len)
		parse_strategy_opts(&replay, buf.buf);
	strbuf_release(&buf);

This way we never change opts->strategy_opts and we always release the 
temporary copy.

Best Wishes

Phillip

>   
>   	return replay;
>   }
> @@ -511,6 +524,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   	argc = parse_options(argc, argv, prefix, options,
>   			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>   
> +	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> +
>   	if (!is_null_oid(&squash_onto))
>   		opts.squash_onto = &squash_onto;
>   
> @@ -964,6 +979,8 @@ static int run_am(struct rebase_options *opts)
>   	am.git_cmd = 1;
>   	argv_array_push(&am.args, "am");
>   
> +	if (opts->ignore_whitespace)
> +		argv_array_push(&am.args, "--ignore-whitespace");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1407,9 +1424,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -				  NULL, N_("passed to 'git am'"),
> -				  PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>   				  &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> @@ -1417,6 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>   				  N_("passed to 'git apply'"), 0),
> +		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> +			 N_("ignore changes in whitespace")),
>   		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>   				  N_("action"), N_("passed to 'git apply'"), 0),
>   		OPT_BIT('f', "force-rebase", &options.flags,
> @@ -1834,6 +1850,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   	}
>   
>   	if (options.rebase_merges) {
> +		if (options.ignore_whitespace)
> +			die(_("cannot combine '--rebase-merges' with "
> +			      "'--ignore-whitespace'"));
>   		if (strategy_options.nr)
>   			die(_("cannot combine '--rebase-merges' with "
>   			      "'--strategy-option'"));
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index a5868ea152..4342f79eea 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>   test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> new file mode 100755
> index 0000000000..2e16e00a9d
> --- /dev/null
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -0,0 +1,65 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +	git checkout -b topic &&
> +	q_to_tab >file <<-\EOF &&
> +	line 1
> +	Qline 2
> +	line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	cat >file <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	git commit -am "update file" &&
> +	git tag side &&
> +
> +	git checkout --orphan master &&
> +	sed -e "s/^|//" >file <<-\EOF &&
> +	|line 1
> +	|        line 2
> +	|line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	git tag main
> +'
> +
> +test_expect_success '--ignore-whitespace works with am backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	test_must_fail git rebase main side &&
> +	git rebase --abort &&
> +	git rebase --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace works with interactive backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	test_must_fail git rebase --merge main side &&
> +	git rebase --abort &&
> +	git rebase --merge --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_done
> 

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

* Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-13 10:38     ` Phillip Wood
@ 2019-08-13 12:09       ` Phillip Wood
  2019-08-13 17:06       ` Junio C Hamano
  1 sibling, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-13 12:09 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

On 13/08/2019 11:38, Phillip Wood wrote:
> Hi Rohit
> 
> [...]
>> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,
>>   {
>>       struct child_process cmd = CHILD_PROCESS_INIT;
>> +    if (opts->committer_date_is_author_date) {
>> +        size_t len;
>> +        int res = -1;
>> +        struct strbuf datebuf = STRBUF_INIT;
>> +        char *date = read_author_date_or_null();
> 
> You must always check the return value of functions that might return 
> NULL. In this case we should return an error as you do in try_to 
> _commit() later
> 
>> +
>> +        strbuf_addf(&datebuf, "@%s", date);
> 
> GNU printf() will add something like '(null)' to the buffer if you pass 
> a NULL pointer so I don't think we can be sure that this will not 
> increase the length of the buffer if date is NULL.

I should have added that passing NULL to snprintf() and friends is going 
to be undefined behavior anyway so you shouldn't do it for that reason 
alone.

Best Wishes

Phillip

  An explicit check
> above would be much clearer as well rather than checking len later. What 
> happens if you don't add the '@' at the beginning? (I'm don't know much 
> about git's date handling)
> 
>> +        free(date);
>> +
>> +        date = strbuf_detach(&datebuf, &len);
>> +
>> +        if (len > 1)
>> +            res = setenv("GIT_COMMITTER_DATE", date, 1);
>> +
>> +        free(date);
>> +
>> +        if (res)
>> +            return -1;
>> +    }
>>       if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
>>           struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
>>           const char *author = NULL;
>> @@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,
>>       if (parse_head(r, &current_head))
>>           return -1;
>> -
>>       if (flags & AMEND_MSG) {
>>           const char *exclude_gpgsig[] = { "gpgsig", NULL };
>>           const char *out_enc = get_commit_output_encoding();
>> @@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,
>>           commit_list_insert(current_head, &parents);
>>       }
>> +    if (opts->committer_date_is_author_date) {
>> +        int len = strlen(author);
>> +        struct ident_split ident;
>> +        struct strbuf date = STRBUF_INIT;
>> +
>> +        split_ident_line(&ident, author, len);
>> +
>> +        if (!ident.date_begin)
>> +            return error(_("corrupted author without date 
>> information"));
> 
> We return an error if we cannot get the date - this is exactly what we 
> should be doing above. It is also great to see a single version of this 
> being used whether or not we are amending.
> 
>> +
>> +        strbuf_addf(&date, "@%s",ident.date_begin);
> 
> I think we should use %s.* and ident.date_end to be sure we getting what 
> we want. Your version is OK if the author is formatted correctly but I'm 
> uneasy about relying on that when we can get the verified end from ident.
> 
> Best Wishes
> 
> Phillip
> 
>> +        setenv("GIT_COMMITTER_DATE", date.buf, 1);
>> +        strbuf_release(&date);
>> +    }
>> +
>>       if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>>           res = error(_("git write-tree failed to write a tree"));
>>           goto out;
>> @@ -2542,6 +2587,11 @@ static int read_populate_opts(struct 
>> replay_opts *opts)
>>               opts->signoff = 1;
>>           }
>> +        if (file_exists(rebase_path_cdate_is_adate())) {
>> +            opts->allow_ff = 0;
>> +            opts->committer_date_is_author_date = 1;
>> +        }
>> +
>>           if (file_exists(rebase_path_reschedule_failed_exec()))
>>               opts->reschedule_failed_exec = 1;
>> @@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, 
>> const char *head_name,
>>           write_file(rebase_path_gpg_sign_opt(), "-S%s\n", 
>> opts->gpg_sign);
>>       if (opts->signoff)
>>           write_file(rebase_path_signoff(), "--signoff\n");
>> +    if (opts->committer_date_is_author_date)
>> +        write_file(rebase_path_cdate_is_adate(), "%s", "");
>>       if (opts->reschedule_failed_exec)
>>           write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>> @@ -3821,7 +3873,8 @@ static int pick_commits(struct repository *r,
>>       setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>>       if (opts->allow_ff)
>>           assert(!(opts->signoff || opts->no_commit ||
>> -                opts->record_origin || opts->edit));
>> +                opts->record_origin || opts->edit ||
>> +                opts->committer_date_is_author_date));
>>       if (read_and_refresh_cache(r, opts))
>>           return -1;
>> diff --git a/sequencer.h b/sequencer.h
>> index 6704acbb9c..e3881e9275 100644
>> --- a/sequencer.h
>> +++ b/sequencer.h
>> @@ -43,6 +43,7 @@ struct replay_opts {
>>       int verbose;
>>       int quiet;
>>       int reschedule_failed_exec;
>> +    int committer_date_is_author_date;
>>       int mainline;
>> diff --git a/t/t3422-rebase-incompatible-options.sh 
>> b/t/t3422-rebase-incompatible-options.sh
>> index 4342f79eea..7402f7e3da 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>   }
>>   test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --committer-date-is-author-date
>>   test_rebase_am_only -C4
>>   test_expect_success REBASE_P '--preserve-merges incompatible with 
>> --signoff' '
>> diff --git a/t/t3433-rebase-options-compatibility.sh 
>> b/t/t3433-rebase-options-compatibility.sh
>> index 2e16e00a9d..b2419a2b75 100755
>> --- a/t/t3433-rebase-options-compatibility.sh
>> +++ b/t/t3433-rebase-options-compatibility.sh
>> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility 
>> between am and interactive backe
>>   . ./test-lib.sh
>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>> +export GIT_AUTHOR_DATE
>> +
>>   # This is a special case in which both am and interactive backends
>>   # provide the same output. It was done intentionally because
>>   # both the backends fall short of optimal behaviour.
>> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with 
>> interactive backend' '
>>       test_cmp expect file
>>   '
>> +test_expect_success '--committer-date-is-author-date works with am 
>> backend' '
>> +    git commit --amend &&
>> +    git rebase --committer-date-is-author-date HEAD^ &&
>> +    git show HEAD --pretty="format:%ai" >authortime &&
>> +    git show HEAD --pretty="format:%ci" >committertime &&
>> +    test_cmp authortime committertime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with 
>> interactive backend' '
>> +    git commit --amend &&
>> +    git rebase -i --committer-date-is-author-date HEAD^ &&
>> +    git show HEAD --pretty="format:%ai" >authortime &&
>> +    git show HEAD --pretty="format:%ci" >committertime &&
>> +    test_cmp authortime committertime
>> +'
>> +
>>   test_done
>>

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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-12 19:42   ` [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-08-13 13:28     ` Phillip Wood
  2019-08-13 17:21       ` Junio C Hamano
  2019-08-13 21:45     ` Junio C Hamano
  1 sibling, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-08-13 13:28 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

This is looking better - there are a couple of memory management issues 
and minor nit-picks but apart from that it looks good.

On 12/08/2019 20:42, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the author date
> by changing it to the committer (current) date. Let's add the same
> for interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            |  6 +--
>   builtin/rebase.c                        | 21 +++++++---
>   sequencer.c                             | 55 ++++++++++++++++++++++++-
>   sequencer.h                             |  1 +
>   t/t3433-rebase-options-compatibility.sh | 16 +++++++
>   5 files changed, 88 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 697ce8e6ff..24ad2dda0b 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.
>   	as the committer date. This implies --force-rebase.
>   
>   --ignore-date::
> -	This flag is passed to 'git am' to change the author date
> -	of the rebased commits (see linkgit:git-am[1]).
> +	Instead of using the given author date, re-set

reset is not hyphenated

> it to the value
> +	same
> as committer (current) date. This implies --force-rebase.

s/value same as committer/same value as the committer/

>   +
>   See also INCOMPATIBLE OPTIONS below.
>   
> @@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --ignore-date
>    * --whitespace
>    * -C
>   
> @@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
>    * --preserve-merges and --committer-date-is-author-date
> + * --preserve-merges and --ignore-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index b1039f8db0..ed58ca8e5a 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -83,6 +83,7 @@ struct rebase_options {
>   	char *gpg_sign_opt;
>   	int autostash;
>   	int committer_date_is_author_date;
> +	int ignore_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.committer_date_is_author_date =
>   					opts->committer_date_is_author_date;
> +	replay.ignore_date = opts->ignore_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -536,7 +538,10 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   		warning(_("--[no-]rebase-cousins has no effect without "
>   			  "--rebase-merges"));
>   
> -	if (opts.committer_date_is_author_date)
> +	if (opts.ignore_date)
> +		opts.committer_date_is_author_date = 0;
> +	if (opts.committer_date_is_author_date ||
> +	    opts.ignore_date)
>   		opts.flags |= REBASE_FORCE;

Is any of this used by rebase--preserve-merges.sh?

>   	return !!run_rebase_interactive(&opts, command);
> @@ -989,6 +994,8 @@ static int run_am(struct rebase_options *opts)
>   		argv_array_push(&am.args, "--ignore-whitespace");
>   	if (opts->committer_date_is_author_date)
>   		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
> +	if (opts->ignore_date)
> +		argv_array_push(&opts->git_am_opts, "--ignore-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1435,8 +1442,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		OPT_BOOL(0, "committer-date-is-author-date",
>   			 &options.committer_date_is_author_date,
>   			 N_("make committer date match author date")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "ignore-date", &options.ignore_date,
> +			 "ignore author date and use current date"),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>   				  N_("passed to 'git apply'"), 0),
>   		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> @@ -1705,13 +1712,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> -	if (options.committer_date_is_author_date)
> +	if (options.ignore_date)
> +		options.committer_date_is_author_date = 0;

We should probably print an error if the user gives 
--committer-date-is-author-date and --author-date-is-committer-date (and 
in cmd_rebase__interactive() if we keep this option there)

> +	if (options.committer_date_is_author_date ||
> +	    options.ignore_date)
>   		options.flags |= REBASE_FORCE;
>   
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--ignore-date") ||
> -		    !strcmp(option, "--whitespace=fix") ||
> +		if (!strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
>   		else if (skip_prefix(option, "-C", &p)) {
> diff --git a/sequencer.c b/sequencer.c
> index e186136ccc..aecd9b4ad8 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -919,6 +920,31 @@ static const char *read_author_ident(struct strbuf *buf)
>   	return buf->buf;
>   }
>   
> +static void ignore_author_date(const char **author)
> +{
> +	int len = strlen(*author);
> +	struct ident_split ident;
> +	struct strbuf new_author = STRBUF_INIT;
> +
> +	split_ident_line(&ident, *author, len);
> +	len = ident.mail_end - ident.name_begin + 1;
> +
> +	strbuf_addf(&new_author, "%.*s", len, *author);
> +	datestamp(&new_author);
> +	*author = strbuf_detach(&new_author, NULL);
> +}

It's good to see this using the indet api. I think this would be nicer 
if it took a char* returned the new author rather than changing the 
function argument, particularly as it does not free the string that is 
passed in so the ownership is unclear.

> +
> +static void push_dates(struct child_process *child)
> +{
> +	time_t now = time(NULL);
> +	struct strbuf date = STRBUF_INIT;
> +
> +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
> +	argv_array_pushf(&child->args, "--date=%s", date.buf);

it doesn't matter but it might have been nicer to set both dates the 
same way in the environment.

> +	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
> +	strbuf_release(&date);
> +}
> +
>   static const char staged_changes_advice[] =
>   N_("you have staged changes in your working tree\n"
>   "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -1020,10 +1046,18 @@ static int run_git_commit(struct repository *r,
>   
>   		if (res <= 0)
>   			res = error_errno(_("could not read '%s'"), defmsg);
> -		else
> +		else {
> +			if (opts->ignore_date) {
> +				if (!author)
> +					BUG("ignore-date can only be used with "
> +					    "rebase, which must set the author "
> +					    "before committing the tree");
> +				ignore_author_date(&author);

Is this leaking the old author? I'd rather see

	tmp_author = ignore_author_date(author);
	free(author);
	author = tmp_author;

> +			}
>   			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>   					  NULL, &root_commit, author,
>   					  opts->gpg_sign);
> +		}
>   
>   		strbuf_release(&msg);
>   		strbuf_release(&script);
> @@ -1053,6 +1087,8 @@ static int run_git_commit(struct repository *r,
>   		argv_array_push(&cmd.args, "--amend");
>   	if (opts->gpg_sign)
>   		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> +	if (opts->ignore_date)
> +		push_dates(&cmd);
>   	if (defmsg)
>   		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>   	else if (!(flags & EDIT_MSG))
> @@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,
>   
>   	reset_ident_date();
>   
> +	if (opts->ignore_date) {
> +		ignore_author_date(&author);
> +		free(author_to_free);

Where is author_to_free set? We should always free the old author, see 
above.

> +		author_to_free = (char *)author;

Why do we need the cast - is author const?

Best Wishes

Phillip

> +	}
>   	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>   				 oid, author, opts->gpg_sign, extra)) {
>   		res = error(_("failed to write commit object"));
> @@ -2592,6 +2633,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->committer_date_is_author_date = 1;
>   		}
>   
> +		if (file_exists(rebase_path_ignore_date())) {
> +			opts->allow_ff = 0;
> +			opts->ignore_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2676,6 +2722,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_signoff(), "--signoff\n");
>   	if (opts->committer_date_is_author_date)
>   		write_file(rebase_path_cdate_is_adate(), "%s", "");
> +	if (opts->ignore_date)
> +		write_file(rebase_path_ignore_date(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3601,6 +3649,8 @@ static int do_merge(struct repository *r,
>   		argv_array_push(&cmd.args, git_path_merge_msg(r));
>   		if (opts->gpg_sign)
>   			argv_array_push(&cmd.args, opts->gpg_sign);
> +		if (opts->ignore_date)
> +			push_dates(&cmd);
>   
>   		/* Add the tips to be merged */
>   		for (j = to_merge; j; j = j->next)
> @@ -3874,7 +3924,8 @@ static int pick_commits(struct repository *r,
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
>   				opts->record_origin || opts->edit ||
> -				opts->committer_date_is_author_date));
> +				opts->committer_date_is_author_date ||
> +				opts->ignore_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index e3881e9275..bf5a79afdb 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -44,6 +44,7 @@ struct replay_opts {
>   	int quiet;
>   	int reschedule_failed_exec;
>   	int committer_date_is_author_date;
> +	int ignore_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index b2419a2b75..c060fcd10b 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back
>   	test_cmp authortime committertime
>   '
>   
> +# Checking for +0000 in author time is enough since default
> +# timezone is UTC, but the timezone used while committing
> +# sets to +0530.
> +test_expect_success '--ignore-date works with am backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with interactive backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date -i HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
>   test_done
> 

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

* Re: [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename
  2019-08-12 19:42   ` [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-08-13 13:29     ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-13 13:29 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 12/08/2019 20:42, Rohit Ashiwal wrote:
> The purpose of amend_author was to free() the malloc()'d string
> obtained from get_author() while amending a commit. But we can
> also use the variable to free() the author at our convenience.
> Rename it to convey this meaning.

Thanks for rewording this

Best Wishes

Phillip

> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   sequencer.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/sequencer.c b/sequencer.c
> index fbc0ed0cad..e186136ccc 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -1424,7 +1424,7 @@ static int try_to_commit(struct repository *r,
>   	struct commit_extra_header *extra = NULL;
>   	struct strbuf err = STRBUF_INIT;
>   	struct strbuf commit_msg = STRBUF_INIT;
> -	char *amend_author = NULL;
> +	char *author_to_free = NULL;
>   	const char *hook_commit = NULL;
>   	enum commit_msg_cleanup_mode cleanup;
>   	int res = 0;
> @@ -1445,7 +1445,7 @@ static int try_to_commit(struct repository *r,
>   			strbuf_addstr(msg, orig_message);
>   			hook_commit = "HEAD";
>   		}
> -		author = amend_author = get_author(message);
> +		author = author_to_free = get_author(message);
>   		unuse_commit_buffer(current_head, message);
>   		if (!author) {
>   			res = error(_("unable to parse commit author"));
> @@ -1534,7 +1534,7 @@ static int try_to_commit(struct repository *r,
>   	free_commit_extra_headers(extra);
>   	strbuf_release(&err);
>   	strbuf_release(&commit_msg);
> -	free(amend_author);
> +	free(author_to_free);
>   
>   	return res;
>   }
> 

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

* Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-12 19:42   ` [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
  2019-08-13 10:38     ` Phillip Wood
@ 2019-08-13 13:35     ` Phillip Wood
  1 sibling, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-13 13:35 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

On 12/08/2019 20:42, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the committer date
> by changing it to the author date. Let's add the same for
> interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            |  8 +++-
>   builtin/rebase.c                        | 20 ++++++---
>   sequencer.c                             | 57 ++++++++++++++++++++++++-
>   sequencer.h                             |  1 +
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++
>   6 files changed, 96 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 28e5e08a83..697ce8e6ff 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
>   See also INCOMPATIBLE OPTIONS below.
>   
>   --committer-date-is-author-date::
> +	Instead of recording the time the rebased commits are
> +	created as the committer date, reuse the author date
> +	as the committer date. This implies --force-rebase.
> +
>   --ignore-date::
> -	These flags are passed to 'git am' to easily change the dates
> +	This flag is passed to 'git am' to change the author date

Very minor nit-pick. This has lost the plural for 'dates'. I'm not sure 
this is correct as there will be more than one date because the commits 
will have different dates. If it had said 'change the date of each 
rebased commit' then the singular would definitely be right but as it 
stands I'm not sure this is an improvement.

Best Wishes

Phillip

>   	of the rebased commits (see linkgit:git-am[1]).
>   +
>   See also INCOMPATIBLE OPTIONS below.
> @@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
>    * -C
> @@ -548,6 +551,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index ab1bbb78ee..b1039f8db0 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -82,6 +82,7 @@ struct rebase_options {
>   	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
> +	int committer_date_is_author_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.allow_empty_message = opts->allow_empty_message;
>   	replay.verbose = opts->flags & REBASE_VERBOSE;
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +	replay.committer_date_is_author_date =
> +					opts->committer_date_is_author_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -533,6 +536,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   		warning(_("--[no-]rebase-cousins has no effect without "
>   			  "--rebase-merges"));
>   
> +	if (opts.committer_date_is_author_date)
> +		opts.flags |= REBASE_FORCE;
> +
>   	return !!run_rebase_interactive(&opts, command);
>   }
>   
> @@ -981,6 +987,8 @@ static int run_am(struct rebase_options *opts)
>   
>   	if (opts->ignore_whitespace)
>   		argv_array_push(&am.args, "--ignore-whitespace");
> +	if (opts->committer_date_is_author_date)
> +		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1424,9 +1432,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -				  &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "committer-date-is-author-date",
> +			 &options.committer_date_is_author_date,
> +			 N_("make committer date match author date")),
>   		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1697,10 +1705,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> +	if (options.committer_date_is_author_date)
> +		options.flags |= REBASE_FORCE;
> +
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--committer-date-is-author-date") ||
> -		    !strcmp(option, "--ignore-date") ||
> +		if (!strcmp(option, "--ignore-date") ||
>   		    !strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
> diff --git a/sequencer.c b/sequencer.c
> index 30d77c2682..fbc0ed0cad 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    * command-line.
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -879,6 +880,17 @@ static char *get_author(const char *message)
>   	return NULL;
>   }
>   
> +/* Returns a "date" string that needs to be free()'d by the caller */
> +static char *read_author_date_or_null(void)
> +{
> +	char *date;
> +
> +	if (read_author_script(rebase_path_author_script(),
> +			       NULL, NULL, &date, 0))
> +		return NULL;
> +	return date;
> +}
> +
>   /* Read author-script and return an ident line (author <email> timestamp) */
>   static const char *read_author_ident(struct strbuf *buf)
>   {
> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,
>   {
>   	struct child_process cmd = CHILD_PROCESS_INIT;
>   
> +	if (opts->committer_date_is_author_date) {
> +		size_t len;
> +		int res = -1;
> +		struct strbuf datebuf = STRBUF_INIT;
> +		char *date = read_author_date_or_null();
> +
> +		strbuf_addf(&datebuf, "@%s", date);
> +		free(date);
> +
> +		date = strbuf_detach(&datebuf, &len);
> +
> +		if (len > 1)
> +			res = setenv("GIT_COMMITTER_DATE", date, 1);
> +
> +		free(date);
> +
> +		if (res)
> +			return -1;
> +	}
>   	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
>   		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
>   		const char *author = NULL;
> @@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,
>   
>   	if (parse_head(r, &current_head))
>   		return -1;
> -
>   	if (flags & AMEND_MSG) {
>   		const char *exclude_gpgsig[] = { "gpgsig", NULL };
>   		const char *out_enc = get_commit_output_encoding();
> @@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,
>   		commit_list_insert(current_head, &parents);
>   	}
>   
> +	if (opts->committer_date_is_author_date) {
> +		int len = strlen(author);
> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		split_ident_line(&ident, author, len);
> +
> +		if (!ident.date_begin)
> +			return error(_("corrupted author without date information"));
> +
> +		strbuf_addf(&date, "@%s",ident.date_begin);
> +		setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		strbuf_release(&date);
> +	}
> +
>   	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>   		res = error(_("git write-tree failed to write a tree"));
>   		goto out;
> @@ -2542,6 +2587,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->signoff = 1;
>   		}
>   
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
>   	if (opts->signoff)
>   		write_file(rebase_path_signoff(), "--signoff\n");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3821,7 +3873,8 @@ static int pick_commits(struct repository *r,
>   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index 6704acbb9c..e3881e9275 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -43,6 +43,7 @@ struct replay_opts {
>   	int verbose;
>   	int quiet;
>   	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 4342f79eea..7402f7e3da 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 2e16e00a9d..b2419a2b75 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>   
>   . ./test-lib.sh
>   
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>   # This is a special case in which both am and interactive backends
>   # provide the same output. It was done intentionally because
>   # both the backends fall short of optimal behaviour.
> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>   	test_cmp expect file
>   '
>   
> +test_expect_success '--committer-date-is-author-date works with am backend' '
> +	git commit --amend &&
> +	git rebase --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
> +	git commit --amend &&
> +	git rebase -i --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
>   test_done
> 

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

* Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-13 10:38     ` Phillip Wood
  2019-08-13 12:09       ` Phillip Wood
@ 2019-08-13 17:06       ` Junio C Hamano
  2019-08-14 18:38         ` Phillip Wood
  1 sibling, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-13 17:06 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

Phillip Wood <phillip.wood123@gmail.com> writes:

>>   +	if (opts->committer_date_is_author_date) {
>> +		size_t len;
>> +		int res = -1;
>> +		struct strbuf datebuf = STRBUF_INIT;
>> +		char *date = read_author_date_or_null();
>
> You must always check the return value of functions that might return
> NULL. In this case we should return an error as you do in try_to
> _commit() later
>
>> +
>> +		strbuf_addf(&datebuf, "@%s", date);
>
> GNU printf() will add something like '(null)' to the buffer if you
> pass a NULL pointer so I don't think we can be sure that this will not
> increase the length of the buffer if date is NULL.

And an implementation that is not as lenient may outright segfault.

>>   +	if (opts->committer_date_is_author_date) {
>> +		int len = strlen(author);
>> +		struct ident_split ident;
>> +		struct strbuf date = STRBUF_INIT;
>> +
>> +		split_ident_line(&ident, author, len);
>> +
>> +		if (!ident.date_begin)
>> +			return error(_("corrupted author without date information"));
>
> We return an error if we cannot get the date - this is exactly what we
> should be doing above. It is also great to see a single version of
> this being used whether or not we are amending.
>
>> +
>> +		strbuf_addf(&date, "@%s",ident.date_begin);
>
> I think we should use %s.* and ident.date_end to be sure we getting
> what we want. Your version is OK if the author is formatted correctly
> but I'm uneasy about relying on that when we can get the verified end
> from ident.

If the author line is not formatted correctly, split_ident_line()
would notice and return NULL in these fields, I think (in other
words, my take on the call to split_ident_line() above is not
necessarily done in order to "split", but primarily to validate that
the line is formatted correctly---and find the beginning of the
timestamp field).

But your "pay attention to date_end" raises an interesting point.

The string that follows ident.date_begin would be a large integer
(i.e. number of seconds since epoch), a SP, a positive or negative
sign (i.e. east or west of GMT), 4 digits (i.e. timezone offset), so
if you want to leave something like "@1544328981" in the buffer, you
need to stop at .date_end to omit the timezone information.

On the other hand, if you do want the timezone information as well
(which I think is the case for this codepath), you should not stop
at there and have something like "@1544328981 +0900", the code as
written would give better result.

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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-13 13:28     ` Phillip Wood
@ 2019-08-13 17:21       ` Junio C Hamano
  2019-08-14 18:47         ` Phillip Wood
  0 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-13 17:21 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

Phillip Wood <phillip.wood123@gmail.com> writes:

>> +static void push_dates(struct child_process *child)
>> +{
>> +	time_t now = time(NULL);
>> +	struct strbuf date = STRBUF_INIT;
>> +
>> +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
>> +	argv_array_pushf(&child->args, "--date=%s", date.buf);
>
> it doesn't matter but it might have been nicer to set both dates the
> same way in the environment.
> +	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);

We can see that this date string lacks timezone information, which
would likely fall back to whatever timezone the user is in.  Is that
what we want?  I am guessing it is, as we are dealing with "now"
timestamp, but wanted to double check.

>> +			if (opts->ignore_date) {
>> +				if (!author)
>> +					BUG("ignore-date can only be used with "
>> +					    "rebase, which must set the author "
>> +					    "before committing the tree");
>> +				ignore_author_date(&author);
>
> Is this leaking the old author? I'd rather see
>
> 	tmp_author = ignore_author_date(author);
> 	free(author);
> 	author = tmp_author;

Or make sure ignore_author_date() does not leak the original, when
it rewrites its parameter.

But I have a larger question at the higher design level.  Why are we
passing a single string "author" around, instead of parsed and split
fields, like <name, email, timestamp, tz> tuple?  That would allow us
to replace only the time part a lot more easily.  Would it make the
other parts of the code more cumbersome (I didn't check---and if
that is the case, then that is a valid reason why we want to stick
to the current "a single string 'author' keeps the necessary info
for the 4-tuple" design).

>> +			}
>>   			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>>   					  NULL, &root_commit, author,
>>   					  opts->gpg_sign);
>> +		}
>>     		strbuf_release(&msg);
>>   		strbuf_release(&script);
>> @@ -1053,6 +1087,8 @@ static int run_git_commit(struct repository *r,
>>   		argv_array_push(&cmd.args, "--amend");
>>   	if (opts->gpg_sign)
>>   		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>> +	if (opts->ignore_date)
>> +		push_dates(&cmd);
>>   	if (defmsg)
>>   		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>>   	else if (!(flags & EDIT_MSG))
>> @@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,
>>     	reset_ident_date();
>>   +	if (opts->ignore_date) {
>> +		ignore_author_date(&author);
>> +		free(author_to_free);
>
> Where is author_to_free set? We should always free the old author, see
> above.

Or require callers to pass a free()able memory to ignore_author_date()
and have the callee free the original?

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

* Re: [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date
  2019-08-12 19:43   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
@ 2019-08-13 17:28     ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-08-13 17:28 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

> The previous commit introduced --ignore-date flag to interactive
> rebase, but the name is actually very vague in context of rebase -i
> since there are two dates we can work with. Add an alias to convey
> the precise purpose.

This sounds more like the existing "--reset-author" but only takes
over the timestamp part without taking over the authorship.

IOW, I am wondering if "--reset-author-date" is a better name.


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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-12 19:42   ` [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date Rohit Ashiwal
  2019-08-13 13:28     ` Phillip Wood
@ 2019-08-13 21:45     ` Junio C Hamano
  2019-08-14 18:51       ` Phillip Wood
  1 sibling, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-13 21:45 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

>  --ignore-date::
> -	This flag is passed to 'git am' to change the author date
> -	of the rebased commits (see linkgit:git-am[1]).
> +	Instead of using the given author date, re-set it to the value
> +	same as committer (current) date. This implies --force-rebase.

s/to the value same as .* date\./the current time./;

The more important thing is that we record the current timestamp as
the author date; that timestamp being very close to the committer
date of the resulting commit is a mere consequence of the fact that
we use the current time for committer date and much less important.

Again, I think reset-author-date would be a better synonym to this
one.


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

* Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-13 17:06       ` Junio C Hamano
@ 2019-08-14 18:38         ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-14 18:38 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

On 13/08/2019 18:06, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
>  [...]
>>> +
>>> +		strbuf_addf(&date, "@%s",ident.date_begin);
>>
>> I think we should use %s.* and ident.date_end to be sure we getting
>> what we want. Your version is OK if the author is formatted correctly
>> but I'm uneasy about relying on that when we can get the verified end
>> from ident.
> 
> If the author line is not formatted correctly, split_ident_line()
> would notice and return NULL in these fields, I think (in other
> words, my take on the call to split_ident_line() above is not
> necessarily done in order to "split", but primarily to validate that
> the line is formatted correctly---and find the beginning of the
> timestamp field).

I just had a read through split_ident_line() and it looks to me like it 
will ignore any junk after the timezone. So long as it sees '+' or '-' 
followed by at least one digit it will use that for the time zone and 
return success regardless of what follows it so I think we want to pay 
attention to the end data it returns for the date and timezone.

> But your "pay attention to date_end" raises an interesting point.
> 
> The string that follows ident.date_begin would be a large integer
> (i.e. number of seconds since epoch), a SP, a positive or negative
> sign (i.e. east or west of GMT), 4 digits (i.e. timezone offset), so
> if you want to leave something like "@1544328981" in the buffer, you
> need to stop at .date_end to omit the timezone information.
> 
> On the other hand, if you do want the timezone information as well
> (which I think is the case for this codepath), you should not stop
> at there and have something like "@1544328981 +0900", the code as
> written would give better result.

Good point, I had forgotten that split_ident_line() returned separate 
fields for the date and timezone. I agree that we want the timezone here 
too. I  I think it would be a good idea to beef up the tests to use a 
non default timezone to check that we are actually setting it correctly.

Best Wishes

Phillip


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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-13 17:21       ` Junio C Hamano
@ 2019-08-14 18:47         ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-14 18:47 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

Hi Junio & Rohit

On 13/08/2019 18:21, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>>> +static void push_dates(struct child_process *child)
>>> +{
>>> +	time_t now = time(NULL);
>>> +	struct strbuf date = STRBUF_INIT;
>>> +
>>> +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
>>> +	argv_array_pushf(&child->args, "--date=%s", date.buf);
>>
>> it doesn't matter but it might have been nicer to set both dates the
>> same way in the environment.
>> +	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
> 
> We can see that this date string lacks timezone information, which
> would likely fall back to whatever timezone the user is in.  Is that
> what we want?  I am guessing it is, as we are dealing with "now"
> timestamp, but wanted to double check.

I think we probably want to use the local timezone as you suggest

>>> +			if (opts->ignore_date) {
>>> +				if (!author)
>>> +					BUG("ignore-date can only be used with "
>>> +					    "rebase, which must set the author "
>>> +					    "before committing the tree");
>>> +				ignore_author_date(&author);
>>
>> Is this leaking the old author? I'd rather see
>>
>> 	tmp_author = ignore_author_date(author);
>> 	free(author);
>> 	author = tmp_author;
> 
> Or make sure ignore_author_date() does not leak the original, when
> it rewrites its parameter.
> 
> But I have a larger question at the higher design level.  Why are we
> passing a single string "author" around, instead of parsed and split
> fields, like <name, email, timestamp, tz> tuple?  That would allow us
> to replace only the time part a lot more easily.  Would it make the
> other parts of the code more cumbersome (I didn't check---and if
> that is the case, then that is a valid reason why we want to stick
> to the current "a single string 'author' keeps the necessary info
> for the 4-tuple" design).

It's a bit of a mess at the moment. There are places where we want a 
single author data string when calling commit_tree_extended(), and other 
places where we want to set the name, email and date in the environment 
when running 'git commit'. For the latter case we use a file which we 
read and write as the C version just follows what the shell script did. 
I think carrying round a <name, email, timestamp, tz> tuple would be the 
sensible way to go and we can build the author string when we need it. 
Doing that would hopefully eliminate having to read and write the author 
file so much. I haven't looked at how difficult it would be to change 
the existing code to do that. We should also really carry the commit 
message around in a variable and only write it to a file if a pick fails 
or we are editing the message and running 'git commit'. If we're just 
using commit_tree_extended() there is no need to be writing the message 
to a file and then reading it back in again later.

Best Wishes

Phillip

>>> +			}
>>>    			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>>>    					  NULL, &root_commit, author,
>>>    					  opts->gpg_sign);
>>> +		}
>>>      		strbuf_release(&msg);
>>>    		strbuf_release(&script);
>>> @@ -1053,6 +1087,8 @@ static int run_git_commit(struct repository *r,
>>>    		argv_array_push(&cmd.args, "--amend");
>>>    	if (opts->gpg_sign)
>>>    		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>>> +	if (opts->ignore_date)
>>> +		push_dates(&cmd);
>>>    	if (defmsg)
>>>    		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>>>    	else if (!(flags & EDIT_MSG))
>>> @@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,
>>>      	reset_ident_date();
>>>    +	if (opts->ignore_date) {
>>> +		ignore_author_date(&author);
>>> +		free(author_to_free);
>>
>> Where is author_to_free set? We should always free the old author, see
>> above.
> 
> Or require callers to pass a free()able memory to ignore_author_date()
> and have the callee free the original?
> 

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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-13 21:45     ` Junio C Hamano
@ 2019-08-14 18:51       ` Phillip Wood
  2019-08-14 19:33         ` Junio C Hamano
  0 siblings, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-08-14 18:51 UTC (permalink / raw)
  To: Junio C Hamano, Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, t.gummerer

On 13/08/2019 22:45, Junio C Hamano wrote:
> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:
> 
>>   --ignore-date::
>> -	This flag is passed to 'git am' to change the author date
>> -	of the rebased commits (see linkgit:git-am[1]).
>> +	Instead of using the given author date, re-set it to the value
>> +	same as committer (current) date. This implies --force-rebase.
> 
> s/to the value same as .* date\./the current time./;
> 
> The more important thing is that we record the current timestamp as
> the author date; that timestamp being very close to the committer
> date of the resulting commit is a mere consequence of the fact that
> we use the current time for committer date and much less important.

That's an important distinction, particularly if GIT_COMMITTER_DATE is 
set in the environment - are we aiming to have the author and committer 
dates match or are we just resetting the author date to now? Rohit - do 
you know which --ignore-date does in the am based rebase?

Best Wishes

Phillip

> 
> Again, I think reset-author-date would be a better synonym to this
> one.
> 

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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-14 18:51       ` Phillip Wood
@ 2019-08-14 19:33         ` Junio C Hamano
  2019-08-17  9:28           ` Phillip Wood
  0 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-14 19:33 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

Phillip Wood <phillip.wood123@gmail.com> writes:

> That's an important distinction, particularly if GIT_COMMITTER_DATE is
> set in the environment - are we aiming to have the author and
> committer dates match or are we just resetting the author date to now?
> Rohit - do you know which --ignore-date does in the am based rebase?

The purpose "am --ignore-date" was to ignore "Date:" that came from
the patch message, overriding it with the current date.  It might
have become harder to read in the C version, but "git show v2.0.0:git-am.sh"
would be an easier way to read how "--ignore-date" wanted to behave.


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

* Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date
  2019-08-14 19:33         ` Junio C Hamano
@ 2019-08-17  9:28           ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-17  9:28 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

On 14/08/2019 20:33, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> That's an important distinction, particularly if GIT_COMMITTER_DATE is
>> set in the environment - are we aiming to have the author and
>> committer dates match or are we just resetting the author date to now?
>> Rohit - do you know which --ignore-date does in the am based rebase?
> 
> The purpose "am --ignore-date" was to ignore "Date:" that came from
> the patch message, overriding it with the current date.  It might
> have become harder to read in the C version, but "git show v2.0.0:git-am.sh"
> would be an easier way to read how "--ignore-date" wanted to behave.

Thanks for the pointer, looking at the code I agree that 
--reset-author-date would be a better alias. If GIT_COMMITTER_DATE is 
not set then the author and committer dates match, otherwise the author 
date is reset to the current time. The code also shows how we should be 
combining --ignore-date and --committer-date-is-author-date.

Best Wishes

Phillip

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

* [PATCH v3 0/6] rebase -i: support more options
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (6 preceding siblings ...)
  2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
@ 2019-08-20  3:45 ` Rohit Ashiwal
  2019-08-20  3:45   ` [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
                     ` (7 more replies)
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
  9 siblings, 8 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

I've tries to incorporated all the suggestions.

Some points:
  - According to v2.0.0's git-am.sh, ignore-date should override
    committer-date-is-author-date. Ergo, we are not barfing out
    when both flags are provided.
  - Should the 'const' qualifier be removed[2]? Since it is leaving
    a false impression that author should not be free()'d.

[1]: git show v2.0.0:git-am.sh
[2]: https://github.com/git/git/blob/v2.23.0/sequencer.c#L959

Rohit Ashiwal (6):
  rebase -i: add --ignore-whitespace flag
  sequencer: add NULL checks under read_author_script
  rebase -i: support --committer-date-is-author-date
  sequencer: rename amend_author to author_to_rename
  rebase -i: support --ignore-date
  rebase: add --reset-author-date

 Documentation/git-rebase.txt            |  26 +++--
 builtin/rebase.c                        |  53 +++++++---
 sequencer.c                             | 135 ++++++++++++++++++++++--
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 100 ++++++++++++++++++
 6 files changed, 289 insertions(+), 29 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

Range-diff:
1:  4cd0aa3084 ! 1:  e82ed8cad5 rebase -i: add --ignore-whitespace flag
    @@ -19,10 +19,13 @@
      default is `--no-fork-point`, otherwise the default is `--fork-point`.
      
      --ignore-whitespace::
    -+	This flag is either passed to the 'git apply' program
    -+	(see linkgit:git-apply[1]), or to 'git merge' program
    -+	(see linkgit:git-merge[1]) as `-Xignore-space-change`,
    -+	depending on which backend is selected by other options.
    ++	Behaves differently depending on which backend is selected.
    +++
    ++'am' backend: When applying a patch, ignore changes in whitespace in
    ++context lines if necessary.
    +++
    ++'interactive' backend: Treat lines with only whitespace changes as
    ++unchanged for the sake of a three-way merge.
     +
      --whitespace=<option>::
     -	These flag are passed to the 'git apply' program
    @@ -63,7 +66,7 @@
      
      static struct replay_opts get_replay_opts(const struct rebase_options *opts)
      {
    -+	char *strategy_opts = opts->strategy_opts;
    ++	struct strbuf strategy_buf = STRBUF_INIT;
      	struct replay_opts replay = REPLAY_OPTS_INIT;
      
      	replay.action = REPLAY_INTERACTIVE_REBASE;
    @@ -71,24 +74,19 @@
      	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
    --	if (opts->strategy_opts)
    --		parse_strategy_opts(&replay, opts->strategy_opts);
    -+
    -+	if (opts->ignore_whitespace) {
    -+		struct strbuf buf = STRBUF_INIT;
    -+
    -+		if (strategy_opts)
    -+			strbuf_addstr(&buf, strategy_opts);
     +
    -+		strbuf_addstr(&buf, " --ignore-space-change");
    -+		free(strategy_opts);
    -+		strategy_opts = strbuf_detach(&buf, NULL);
    -+	}
    -+	if (strategy_opts)
    -+		parse_strategy_opts(&replay, strategy_opts);
    + 	if (opts->strategy_opts)
    +-		parse_strategy_opts(&replay, opts->strategy_opts);
    ++		strbuf_addstr(&strategy_buf, opts->strategy_opts);
    ++	if (opts->ignore_whitespace)
    ++		strbuf_addstr(&strategy_buf, " --ignore-space-change");
    ++	if (strategy_buf.len)
    ++		parse_strategy_opts(&replay, strategy_buf.buf);
      
    ++	strbuf_release(&strategy_buf);
      	return replay;
      }
    + 
     @@
      	argc = parse_options(argc, argv, prefix, options,
      			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
2:  e2c0304587 = 2:  209057b361 sequencer: add NULL checks under read_author_script
3:  6aed57ae2e ! 3:  a4e6644ef8 rebase -i: support --committer-date-is-author-date
    @@ -21,10 +21,12 @@
     +
      --ignore-date::
     -	These flags are passed to 'git am' to easily change the dates
    +-	of the rebased commits (see linkgit:git-am[1]).
     +	This flag is passed to 'git am' to change the author date
    - 	of the rebased commits (see linkgit:git-am[1]).
    ++	of each rebased commit (see linkgit:git-am[1]).
      +
      See also INCOMPATIBLE OPTIONS below.
    + 
     @@
      
      The following options:
    @@ -62,16 +64,6 @@
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
      
    -@@
    - 		warning(_("--[no-]rebase-cousins has no effect without "
    - 			  "--rebase-merges"));
    - 
    -+	if (opts.committer_date_is_author_date)
    -+		opts.flags |= REBASE_FORCE;
    -+
    - 	return !!run_rebase_interactive(&opts, command);
    - }
    - 
     @@
      
      	if (opts->ignore_whitespace)
    @@ -149,14 +141,14 @@
     +		struct strbuf datebuf = STRBUF_INIT;
     +		char *date = read_author_date_or_null();
     +
    ++		if (!date)
    ++			return -1;
    ++
     +		strbuf_addf(&datebuf, "@%s", date);
     +		free(date);
     +
     +		date = strbuf_detach(&datebuf, &len);
    -+
    -+		if (len > 1)
    -+			res = setenv("GIT_COMMITTER_DATE", date, 1);
    -+
    ++		res = setenv("GIT_COMMITTER_DATE", date, 1);
     +		free(date);
     +
     +		if (res)
    @@ -187,7 +179,7 @@
     +		if (!ident.date_begin)
     +			return error(_("corrupted author without date information"));
     +
    -+		strbuf_addf(&date, "@%s",ident.date_begin);
    ++		strbuf_addf(&date, "@%s", ident.date_begin);
     +		setenv("GIT_COMMITTER_DATE", date.buf, 1);
     +		strbuf_release(&date);
     +	}
4:  36a0c017c2 = 4:  6ac1885c54 sequencer: rename amend_author to author_to_rename
5:  3a4ffeb995 ! 5:  a69749dd67 rebase -i: support --ignore-date
    @@ -16,9 +16,9 @@
      
      --ignore-date::
     -	This flag is passed to 'git am' to change the author date
    --	of the rebased commits (see linkgit:git-am[1]).
    -+	Instead of using the given author date, re-set it to the value
    -+	same as committer (current) date. This implies --force-rebase.
    +-	of each rebased commit (see linkgit:git-am[1]).
    ++	Instead of using the given author date, reset it to the value
    ++	same as the current time. This implies --force-rebase.
      +
      See also INCOMPATIBLE OPTIONS below.
      
    @@ -58,18 +58,6 @@
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
      
    -@@
    - 		warning(_("--[no-]rebase-cousins has no effect without "
    - 			  "--rebase-merges"));
    - 
    --	if (opts.committer_date_is_author_date)
    -+	if (opts.ignore_date)
    -+		opts.committer_date_is_author_date = 0;
    -+	if (opts.committer_date_is_author_date ||
    -+	    opts.ignore_date)
    - 		opts.flags |= REBASE_FORCE;
    - 
    - 	return !!run_rebase_interactive(&opts, command);
     @@
      		argv_array_push(&am.args, "--ignore-whitespace");
      	if (opts->committer_date_is_author_date)
    @@ -125,18 +113,19 @@
      	return buf->buf;
      }
      
    -+static void ignore_author_date(const char **author)
    ++/* Construct a free()able author string with current time as the author date */
    ++static char *ignore_author_date(const char *author)
     +{
    -+	int len = strlen(*author);
    ++	int len = strlen(author);
     +	struct ident_split ident;
     +	struct strbuf new_author = STRBUF_INIT;
     +
    -+	split_ident_line(&ident, *author, len);
    ++	split_ident_line(&ident, author, len);
     +	len = ident.mail_end - ident.name_begin + 1;
     +
    -+	strbuf_addf(&new_author, "%.*s", len, *author);
    ++	strbuf_addf(&new_author, "%.*s ", len, author);
     +	datestamp(&new_author);
    -+	*author = strbuf_detach(&new_author, NULL);
    ++	return strbuf_detach(&new_author, NULL);
     +}
     +
     +static void push_dates(struct child_process *child)
    @@ -160,11 +149,13 @@
     -		else
     +		else {
     +			if (opts->ignore_date) {
    ++				char *new_author = ignore_author_date(author);
     +				if (!author)
     +					BUG("ignore-date can only be used with "
     +					    "rebase, which must set the author "
     +					    "before committing the tree");
    -+				ignore_author_date(&author);
    ++				free((void *)author);
    ++				author = new_author;
     +			}
      			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
      					  NULL, &root_commit, author,
    @@ -187,7 +178,7 @@
      	reset_ident_date();
      
     +	if (opts->ignore_date) {
    -+		ignore_author_date(&author);
    ++		author = ignore_author_date(author);
     +		free(author_to_free);
     +		author_to_free = (char *)author;
     +	}
6:  cb81e6c4e5 ! 6:  210d15cca0 rebase: add --author-date-is-committer-date
    @@ -1,6 +1,6 @@
     Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
     
    -    rebase: add --author-date-is-committer-date
    +    rebase: add --reset-author-date
     
         The previous commit introduced --ignore-date flag to interactive
         rebase, but the name is actually very vague in context of rebase -i
    @@ -16,9 +16,9 @@
      	as the committer date. This implies --force-rebase.
      
      --ignore-date::
    -+--author-date-is-committer-date::
    - 	Instead of using the given author date, re-set it to the value
    - 	same as committer (current) date. This implies --force-rebase.
    ++--reset-author-date::
    + 	Instead of using the given author date, reset it to the value
    + 	same as the current time. This implies --force-rebase.
      +
     
      diff --git a/builtin/rebase.c b/builtin/rebase.c
    @@ -28,7 +28,7 @@
      		OPT_BOOL(0, "committer-date-is-author-date",
      			 &options.committer_date_is_author_date,
      			 N_("make committer date match author date")),
    -+		OPT_BOOL(0, "author-date-is-committer-date", &options.ignore_date,
    ++		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
     +			 "ignore author date and use current date"),
      		OPT_BOOL(0, "ignore-date", &options.ignore_date,
      			 "ignore author date and use current date"),
-- 
2.21.0


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

* [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
@ 2019-08-20  3:45   ` Rohit Ashiwal
  2019-08-20 18:40     ` Phillip Wood
  2019-08-20  3:45   ` [PATCH v3 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

There are two backends available for rebasing, viz, the am and the
interactive. Naturally, there shall be some features that are
implemented in one but not in the other. One such flag is
--ignore-whitespace which indicates merge mechanism to treat lines
with only whitespace changes as unchanged. Wire the interactive
rebase to also understand the --ignore-whitespace flag by
translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 13 ++++-
 builtin/rebase.c                        | 22 +++++++--
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
 4 files changed, 94 insertions(+), 7 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 6156609cf7..873eb5768c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -371,8 +371,16 @@ If either <upstream> or --root is given on the command line, then the
 default is `--no-fork-point`, otherwise the default is `--fork-point`.
 
 --ignore-whitespace::
+	Behaves differently depending on which backend is selected.
++
+'am' backend: When applying a patch, ignore changes in whitespace in
+context lines if necessary.
++
+'interactive' backend: Treat lines with only whitespace changes as
+unchanged for the sake of a three-way merge.
+
 --whitespace=<option>::
-	These flag are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -520,7 +528,6 @@ The following options:
  * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
- * --ignore-whitespace
  * -C
 
 are incompatible with the following options:
@@ -543,6 +550,8 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --interactive
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
+ * --preserve-merges and --ignore-whitespace
+ * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 670096c065..f8a618d54c 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -79,6 +79,7 @@ struct rebase_options {
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -99,6 +100,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
 
+	strbuf_release(&strategy_buf);
 	return replay;
 }
 
@@ -511,6 +519,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -964,6 +974,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1407,9 +1419,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1417,6 +1426,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	if (options.rebase_merges) {
+		if (options.ignore_whitespace)
+			die(_("cannot combine '--rebase-merges' with "
+			      "'--ignore-whitespace'"));
 		if (strategy_options.nr)
 			die(_("cannot combine '--rebase-merges' with "
 			      "'--strategy-option'"));
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index a5868ea152..4342f79eea 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
new file mode 100755
index 0000000000..2e16e00a9d
--- /dev/null
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with am backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase main side &&
+	git rebase --abort &&
+	git rebase --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with interactive backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_done
-- 
2.21.0


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

* [PATCH v3 2/6] sequencer: add NULL checks under read_author_script
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-20  3:45   ` [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-08-20  3:45   ` Rohit Ashiwal
  2019-08-23 15:20     ` Junio C Hamano
  2019-08-20  3:45   ` [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

read_author_script reads name, email and author date from the author
script. However, it does not check if the arguments are NULL. Adding
NULL checks will allow us to selectively get the required value, for
example:

    char *date;
    if (read_author_script(_path_, NULL, NULL, &date, _int_))
	    die(_("failed to read author date"));
    /* needs to be free()'d */
    return date;

Add NULL checks for better control over the information retrieved.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 34ebf8ed94..30d77c2682 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -824,9 +824,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-	*name = kv.items[name_i].util;
-	*email = kv.items[email_i].util;
-	*date = kv.items[date_i].util;
+
+	if (name)
+		*name = kv.items[name_i].util;
+	else
+		free(kv.items[name_i].util);
+	if (email)
+		*email = kv.items[email_i].util;
+	else
+		free(kv.items[email_i].util);
+	if (date)
+		*date = kv.items[date_i].util;
+	else
+		free(kv.items[date_i].util);
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
-- 
2.21.0


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

* [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-20  3:45   ` [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
  2019-08-20  3:45   ` [PATCH v3 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
@ 2019-08-20  3:45   ` Rohit Ashiwal
  2019-08-20 13:32     ` Phillip Wood
  2019-08-20  3:45   ` [PATCH v3 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the committer date
by changing it to the author date. Let's add the same for
interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 10 +++--
 builtin/rebase.c                        | 17 +++++---
 sequencer.c                             | 57 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 19 +++++++++
 6 files changed, 94 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 873eb5768c..e7c0eac18c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of recording the time the rebased commits are
+	created as the committer date, reuse the author date
+	as the committer date. This implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -551,6 +554,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index f8a618d54c..656bc7d7e9 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -82,6 +82,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.allow_empty_message = opts->allow_empty_message;
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -976,6 +979,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1419,9 +1424,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1692,10 +1697,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
+
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
diff --git a/sequencer.c b/sequencer.c
index 30d77c2682..29b67bc1ae 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -879,6 +880,17 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+/* Returns a "date" string that needs to be free()'d by the caller */
+static char *read_author_date_or_null(void)
+{
+	char *date;
+
+	if (read_author_script(rebase_path_author_script(),
+			       NULL, NULL, &date, 0))
+		return NULL;
+	return date;
+}
+
 /* Read author-script and return an ident line (author <email> timestamp) */
 static const char *read_author_ident(struct strbuf *buf)
 {
@@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 
+	if (opts->committer_date_is_author_date) {
+		size_t len;
+		int res = -1;
+		struct strbuf datebuf = STRBUF_INIT;
+		char *date = read_author_date_or_null();
+
+		if (!date)
+			return -1;
+
+		strbuf_addf(&datebuf, "@%s", date);
+		free(date);
+
+		date = strbuf_detach(&datebuf, &len);
+		res = setenv("GIT_COMMITTER_DATE", date, 1);
+		free(date);
+
+		if (res)
+			return -1;
+	}
 	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
 		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
 		const char *author = NULL;
@@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,
 
 	if (parse_head(r, &current_head))
 		return -1;
-
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		split_ident_line(&ident, author, len);
+
+		if (!ident.date_begin)
+			return error(_("corrupted author without date information"));
+
+		strbuf_addf(&date, "@%s", ident.date_begin);
+		setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2542,6 +2587,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
 	if (opts->signoff)
 		write_file(rebase_path_signoff(), "--signoff\n");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3821,7 +3873,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 6704acbb9c..e3881e9275 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -43,6 +43,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 4342f79eea..7402f7e3da 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 2e16e00a9d..b2419a2b75 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . ./test-lib.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with am backend' '
+	git commit --amend &&
+	git rebase --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with interactive backend' '
+	git commit --amend &&
+	git rebase -i --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
 test_done
-- 
2.21.0


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

* [PATCH v3 4/6] sequencer: rename amend_author to author_to_rename
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (2 preceding siblings ...)
  2019-08-20  3:45   ` [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-08-20  3:45   ` Rohit Ashiwal
  2019-08-20  3:45   ` [PATCH v3 5/6] rebase -i: support --ignore-date Rohit Ashiwal
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() while amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 29b67bc1ae..8f7b984333 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1424,7 +1424,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1445,7 +1445,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1534,7 +1534,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.21.0


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

* [PATCH v3 5/6] rebase -i: support --ignore-date
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (3 preceding siblings ...)
  2019-08-20  3:45   ` [PATCH v3 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-08-20  3:45   ` Rohit Ashiwal
  2019-08-20 13:45     ` Phillip Wood
  2019-08-20 17:42     ` Junio C Hamano
  2019-08-20  3:45   ` [PATCH v3 6/6] rebase: add --reset-author-date Rohit Ashiwal
                     ` (2 subsequent siblings)
  7 siblings, 2 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the author date
by changing it to the committer (current) date. Let's add the same
for interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  6 +--
 builtin/rebase.c                        | 16 ++++---
 sequencer.c                             | 58 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3433-rebase-options-compatibility.sh | 16 +++++++
 5 files changed, 87 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e7c0eac18c..e7ac9fae0b 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the given author date, reset it to the value
+	same as the current time. This implies --force-rebase.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --ignore-date
  * --whitespace
  * -C
 
@@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 656bc7d7e9..a63531ee90 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -83,6 +83,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -981,6 +983,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1427,8 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1697,13 +1701,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
-	if (options.committer_date_is_author_date)
+	if (options.ignore_date)
+		options.committer_date_is_author_date = 0;
+	if (options.committer_date_is_author_date ||
+	    options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index 8f7b984333..f5a9590844 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -919,6 +920,32 @@ static const char *read_author_ident(struct strbuf *buf)
 	return buf->buf;
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	split_ident_line(&ident, author, len);
+	len = ident.mail_end - ident.name_begin + 1;
+
+	strbuf_addf(&new_author, "%.*s ", len, author);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
+static void push_dates(struct child_process *child)
+{
+	time_t now = time(NULL);
+	struct strbuf date = STRBUF_INIT;
+
+	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
+	argv_array_pushf(&child->args, "--date=%s", date.buf);
+	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
+	strbuf_release(&date);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,
 
 		if (res <= 0)
 			res = error_errno(_("could not read '%s'"), defmsg);
-		else
+		else {
+			if (opts->ignore_date) {
+				char *new_author = ignore_author_date(author);
+				if (!author)
+					BUG("ignore-date can only be used with "
+					    "rebase, which must set the author "
+					    "before committing the tree");
+				free((void *)author);
+				author = new_author;
+			}
 			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
 					  NULL, &root_commit, author,
 					  opts->gpg_sign);
+		}
 
 		strbuf_release(&msg);
 		strbuf_release(&script);
@@ -1053,6 +1090,8 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+	if (opts->ignore_date)
+		push_dates(&cmd);
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -1515,6 +1554,11 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2592,6 +2636,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2676,6 +2725,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_signoff(), "--signoff\n");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3601,6 +3652,8 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
+		if (opts->ignore_date)
+			push_dates(&cmd);
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3874,7 +3927,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index e3881e9275..bf5a79afdb 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -44,6 +44,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index b2419a2b75..c060fcd10b 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back
 	test_cmp authortime committertime
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with am backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with interactive backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -i HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
 test_done
-- 
2.21.0


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

* [PATCH v3 6/6] rebase: add --reset-author-date
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (4 preceding siblings ...)
  2019-08-20  3:45   ` [PATCH v3 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-08-20  3:45   ` Rohit Ashiwal
  2019-08-20  3:54   ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
  2019-08-20 13:56   ` Phillip Wood
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:45 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The previous commit introduced --ignore-date flag to interactive
rebase, but the name is actually very vague in context of rebase -i
since there are two dates we can work with. Add an alias to convey
the precise purpose.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt | 1 +
 builtin/rebase.c             | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e7ac9fae0b..ec62ba36b8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -391,6 +391,7 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the given author date, reset it to the value
 	same as the current time. This implies --force-rebase.
 +
diff --git a/builtin/rebase.c b/builtin/rebase.c
index a63531ee90..dcf758845b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1431,6 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_BOOL(0, "ignore-date", &options.ignore_date,
 			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-- 
2.21.0


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

* Re: [PATCH v3 0/6] rebase -i: support more options
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (5 preceding siblings ...)
  2019-08-20  3:45   ` [PATCH v3 6/6] rebase: add --reset-author-date Rohit Ashiwal
@ 2019-08-20  3:54   ` Rohit Ashiwal
  2019-08-20 13:56   ` Phillip Wood
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  3:54 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes Schindelin, git, Junio C Hamano, Martin Ågren,
	Elijah Newren, Phillip, Thomas Gummerer

On Tue, Aug 20, 2019 at 9:15 AM Rohit Ashiwal
<rohit.ashiwal265@gmail.com> wrote:
>
> I've tries to incorporated all the suggestions.

I've tried to incorporate all the suggestions.

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

* Re: [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date
  2019-08-20  3:45 [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
@ 2019-08-20  4:00 ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20  4:00 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

Hi Everyone

Please ignore this patch. I forgot to clean the output dir before
sending this iteration.

Thanks
Rohit


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

* Re: [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date
  2019-08-20  3:45   ` [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-08-20 13:32     ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-20 13:32 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

One thing that struck we was that we should support this with rebase -r 
which means setting GIT_COMMITTER_DATE when we fork 'git merge'. I've 
got a couple of other comments below

On 20/08/2019 04:45, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the committer date
> by changing it to the author date. Let's add the same for
> interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            | 10 +++--
>   builtin/rebase.c                        | 17 +++++---
>   sequencer.c                             | 57 ++++++++++++++++++++++++-
>   sequencer.h                             |  1 +
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++
>   6 files changed, 94 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 873eb5768c..e7c0eac18c 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.
>   See also INCOMPATIBLE OPTIONS below.
>   
>   --committer-date-is-author-date::
> +	Instead of recording the time the rebased commits are
> +	created as the committer date, reuse the author date
> +	as the committer date. This implies --force-rebase.
> +
>   --ignore-date::
> -	These flags are passed to 'git am' to easily change the dates
> -	of the rebased commits (see linkgit:git-am[1]).
> +	This flag is passed to 'git am' to change the author date
> +	of each rebased commit (see linkgit:git-am[1]).
>   +
>   See also INCOMPATIBLE OPTIONS below.
>   
> @@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
>    * -C
> @@ -551,6 +554,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index f8a618d54c..656bc7d7e9 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -82,6 +82,7 @@ struct rebase_options {
>   	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
> +	int committer_date_is_author_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.allow_empty_message = opts->allow_empty_message;
>   	replay.verbose = opts->flags & REBASE_VERBOSE;
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +	replay.committer_date_is_author_date =
> +					opts->committer_date_is_author_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -976,6 +979,8 @@ static int run_am(struct rebase_options *opts)
>   
>   	if (opts->ignore_whitespace)
>   		argv_array_push(&am.args, "--ignore-whitespace");
> +	if (opts->committer_date_is_author_date)
> +		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1419,9 +1424,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -				  &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "committer-date-is-author-date",
> +			 &options.committer_date_is_author_date,
> +			 N_("make committer date match author date")),
>   		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1692,10 +1697,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> +	if (options.committer_date_is_author_date)
> +		options.flags |= REBASE_FORCE;
> +
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--committer-date-is-author-date") ||
> -		    !strcmp(option, "--ignore-date") ||
> +		if (!strcmp(option, "--ignore-date") ||
>   		    !strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
> diff --git a/sequencer.c b/sequencer.c
> index 30d77c2682..29b67bc1ae 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    * command-line.
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -879,6 +880,17 @@ static char *get_author(const char *message)
>   	return NULL;
>   }
>   
> +/* Returns a "date" string that needs to be free()'d by the caller */
> +static char *read_author_date_or_null(void)
> +{
> +	char *date;
> +
> +	if (read_author_script(rebase_path_author_script(),
> +			       NULL, NULL, &date, 0))
> +		return NULL;
> +	return date;
> +}
> +
>   /* Read author-script and return an ident line (author <email> timestamp) */
>   static const char *read_author_ident(struct strbuf *buf)
>   {
> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,
>   {
>   	struct child_process cmd = CHILD_PROCESS_INIT;
>   
> +	if (opts->committer_date_is_author_date) {
> +		size_t len;
> +		int res = -1;
> +		struct strbuf datebuf = STRBUF_INIT;
> +		char *date = read_author_date_or_null();
> +
> +		if (!date)
> +			return -1;

It is good to this this new error checking

> +
> +		strbuf_addf(&datebuf, "@%s", date);
> +		free(date);
> +
> +		date = strbuf_detach(&datebuf, &len);
> +		res = setenv("GIT_COMMITTER_DATE", date, 1);
> +		free(date);

This could be simplified slightly by doing
	res = setenv("GIT_COMMITTER_DATE", datebuf.buf. 1);
	strbuf_release(&datebuf);

> +
> +		if (res)
> +			return -1;
> +	}
>   	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
>   		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
>   		const char *author = NULL;
> @@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,
>   
>   	if (parse_head(r, &current_head))
>   		return -1;
> -
>   	if (flags & AMEND_MSG) {
>   		const char *exclude_gpgsig[] = { "gpgsig", NULL };
>   		const char *out_enc = get_commit_output_encoding();
> @@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,
>   		commit_list_insert(current_head, &parents);
>   	}
>   
> +	if (opts->committer_date_is_author_date) {
> +		int len = strlen(author);
> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		split_ident_line(&ident, author, len);
> +
> +		if (!ident.date_begin)
> +			return error(_("corrupted author without date information"));

I had to read the source of split_ident_line() to check this was safe, I 
think it is better to use the return value to check for errors  - a 
quick greps shows that this is what all the other callers do.

> +
> +		strbuf_addf(&date, "@%s", ident.date_begin);

I still think this will pass any junk after a corrupted timezone, it 
would be better to do

	strbuf_addf(&date, "@%.*s %.*s", ident.date_begin, ident.data_end - 
ident.date_begin, ident.tz_begin, ident.tz_end - ident.tz_begin);

> +		setenv("GIT_COMMITTER_DATE", date.buf, 1);

The code above (in run_git_commit()) checks the return value of setenv() 
and returns an error if it failed should this be doing the same?

Best Wishes

Phillip

> +		strbuf_release(&date);
> +	}
> +
>   	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>   		res = error(_("git write-tree failed to write a tree"));
>   		goto out;
> @@ -2542,6 +2587,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->signoff = 1;
>   		}
>   
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
>   	if (opts->signoff)
>   		write_file(rebase_path_signoff(), "--signoff\n");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3821,7 +3873,8 @@ static int pick_commits(struct repository *r,
>   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index 6704acbb9c..e3881e9275 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -43,6 +43,7 @@ struct replay_opts {
>   	int verbose;
>   	int quiet;
>   	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 4342f79eea..7402f7e3da 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 2e16e00a9d..b2419a2b75 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>   
>   . ./test-lib.sh
>   
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>   # This is a special case in which both am and interactive backends
>   # provide the same output. It was done intentionally because
>   # both the backends fall short of optimal behaviour.
> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>   	test_cmp expect file
>   '
>   
> +test_expect_success '--committer-date-is-author-date works with am backend' '
> +	git commit --amend &&
> +	git rebase --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
> +	git commit --amend &&
> +	git rebase -i --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
>   test_done
> 

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

* Re: [PATCH v3 5/6] rebase -i: support --ignore-date
  2019-08-20  3:45   ` [PATCH v3 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-08-20 13:45     ` Phillip Wood
  2019-08-20 17:42     ` Junio C Hamano
  1 sibling, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-20 13:45 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 20/08/2019 04:45, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the author date
> by changing it to the committer (current) date. Let's add the same
> for interactive machinery.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            |  6 +--
>   builtin/rebase.c                        | 16 ++++---
>   sequencer.c                             | 58 ++++++++++++++++++++++++-
>   sequencer.h                             |  1 +
>   t/t3433-rebase-options-compatibility.sh | 16 +++++++
>   5 files changed, 87 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index e7c0eac18c..e7ac9fae0b 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.
>   	as the committer date. This implies --force-rebase.
>   
>   --ignore-date::
> -	This flag is passed to 'git am' to change the author date
> -	of each rebased commit (see linkgit:git-am[1]).
> +	Instead of using the given author date, reset it to the value
> +	same as the current time. This implies --force-rebase.
>   +
>   See also INCOMPATIBLE OPTIONS below.
>   
> @@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS
>   
>   The following options:
>   
> - * --ignore-date
>    * --whitespace
>    * -C
>   
> @@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --rebase-merges
>    * --preserve-merges and --ignore-whitespace
>    * --preserve-merges and --committer-date-is-author-date
> + * --preserve-merges and --ignore-date
>    * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 656bc7d7e9..a63531ee90 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -83,6 +83,7 @@ struct rebase_options {
>   	char *gpg_sign_opt;
>   	int autostash;
>   	int committer_date_is_author_date;
> +	int ignore_date;
>   	char *cmd;
>   	int allow_empty_message;
>   	int rebase_merges, rebase_cousins;
> @@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.committer_date_is_author_date =
>   					opts->committer_date_is_author_date;
> +	replay.ignore_date = opts->ignore_date;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
>   
> @@ -981,6 +983,8 @@ static int run_am(struct rebase_options *opts)
>   		argv_array_push(&am.args, "--ignore-whitespace");
>   	if (opts->committer_date_is_author_date)
>   		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
> +	if (opts->ignore_date)
> +		argv_array_push(&opts->git_am_opts, "--ignore-date");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1427,8 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		OPT_BOOL(0, "committer-date-is-author-date",
>   			 &options.committer_date_is_author_date,
>   			 N_("make committer date match author date")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "ignore-date", &options.ignore_date,
> +			 "ignore author date and use current date"),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>   				  N_("passed to 'git apply'"), 0),
>   		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> @@ -1697,13 +1701,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		    state_dir_base, cmd_live_rebase, buf.buf);
>   	}
>   
> -	if (options.committer_date_is_author_date)
> +	if (options.ignore_date)
> +		options.committer_date_is_author_date = 0;
> +	if (options.committer_date_is_author_date ||
> +	    options.ignore_date)
>   		options.flags |= REBASE_FORCE;
>   
>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>   		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--ignore-date") ||
> -		    !strcmp(option, "--whitespace=fix") ||
> +		if (!strcmp(option, "--whitespace=fix") ||
>   		    !strcmp(option, "--whitespace=strip"))
>   			options.flags |= REBASE_FORCE;
>   		else if (skip_prefix(option, "-C", &p)) {
> diff --git a/sequencer.c b/sequencer.c
> index 8f7b984333..f5a9590844 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -919,6 +920,32 @@ static const char *read_author_ident(struct strbuf *buf)
>   	return buf->buf;
>   }
>   
> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +	int len = strlen(author);
> +	struct ident_split ident;
> +	struct strbuf new_author = STRBUF_INIT;
> +
> +	split_ident_line(&ident, author, len);

You need to check the return value whenever you call split_ident_line(). 
In this case doing so would avoid using NULL pointers below if the 
author is corrupted.

> +	len = ident.mail_end - ident.name_begin + 1;
> +
> +	strbuf_addf(&new_author, "%.*s ", len, author);
> +	datestamp(&new_author);
> +	return strbuf_detach(&new_author, NULL);
> +}

I think this is clearer now it returns the new author

> +
> +static void push_dates(struct child_process *child)
> +{
> +	time_t now = time(NULL);
> +	struct strbuf date = STRBUF_INIT;
> +
> +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
> +	argv_array_pushf(&child->args, "--date=%s", date.buf);
> +	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);

Looking at the code in builtin/am.c it is quite clear how it handles the 
combination of --ignore-date and --committer-date-is-author date is it 
sets GIT_COMMITTER_DATE in a single place. Here we've got two separate 
pieces of code one from patch 3 the other added here. This 
implementation differs from the one in builtin/am.c if --ignore-date is 
given when GIT_COMMITTER_DATE is set in the environment and 
--committer-date-is-author-date is not given.

> +	strbuf_release(&date);
> +}
> +
>   static const char staged_changes_advice[] =
>   N_("you have staged changes in your working tree\n"
>   "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,
>   
>   		if (res <= 0)
>   			res = error_errno(_("could not read '%s'"), defmsg);
> -		else
> +		else {
> +			if (opts->ignore_date) {
> +				char *new_author = ignore_author_date(author);
> +				if (!author)
> +					BUG("ignore-date can only be used with "
> +					    "rebase, which must set the author "
> +					    "before committing the tree");
> +				free((void *)author);
> +				author = new_author;
> +			}
>   			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>   					  NULL, &root_commit, author,
>   					  opts->gpg_sign);
> +		}
>   
>   		strbuf_release(&msg);
>   		strbuf_release(&script);
> @@ -1053,6 +1090,8 @@ static int run_git_commit(struct repository *r,
>   		argv_array_push(&cmd.args, "--amend");
>   	if (opts->gpg_sign)
>   		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> +	if (opts->ignore_date)
> +		push_dates(&cmd);
>   	if (defmsg)
>   		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>   	else if (!(flags & EDIT_MSG))
> @@ -1515,6 +1554,11 @@ static int try_to_commit(struct repository *r,
>   
>   	reset_ident_date();
>   
> +	if (opts->ignore_date) {
> +		author = ignore_author_date(author);
> +		free(author_to_free);
> +		author_to_free = (char *)author;
> +	}

The memory handling is much clearer now

>   	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>   				 oid, author, opts->gpg_sign, extra)) {
>   		res = error(_("failed to write commit object"));
> @@ -2592,6 +2636,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->committer_date_is_author_date = 1;
>   		}
>   
> +		if (file_exists(rebase_path_ignore_date())) {
> +			opts->allow_ff = 0;
> +			opts->ignore_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2676,6 +2725,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_signoff(), "--signoff\n");
>   	if (opts->committer_date_is_author_date)
>   		write_file(rebase_path_cdate_is_adate(), "%s", "");
> +	if (opts->ignore_date)
> +		write_file(rebase_path_ignore_date(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3601,6 +3652,8 @@ static int do_merge(struct repository *r,
>   		argv_array_push(&cmd.args, git_path_merge_msg(r));
>   		if (opts->gpg_sign)
>   			argv_array_push(&cmd.args, opts->gpg_sign);
> +		if (opts->ignore_date)
> +			push_dates(&cmd);
>   
>   		/* Add the tips to be merged */
>   		for (j = to_merge; j; j = j->next)
> @@ -3874,7 +3927,8 @@ static int pick_commits(struct repository *r,
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
>   				opts->record_origin || opts->edit ||
> -				opts->committer_date_is_author_date));
> +				opts->committer_date_is_author_date ||
> +				opts->ignore_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index e3881e9275..bf5a79afdb 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -44,6 +44,7 @@ struct replay_opts {
>   	int quiet;
>   	int reschedule_failed_exec;
>   	int committer_date_is_author_date;
> +	int ignore_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index b2419a2b75..c060fcd10b 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back
>   	test_cmp authortime committertime
>   '
>   
> +# Checking for +0000 in author time is enough since default
> +# timezone is UTC, but the timezone used while committing
> +# sets to +0530.

I'm still worried that this will hide some breakage in the future. Can 
we add a test for rebase -r as well to check that code please.

Best Wishes

Phillip

> +test_expect_success '--ignore-date works with am backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with interactive backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date -i HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
>   test_done
> 

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

* Re: [PATCH v3 0/6] rebase -i: support more options
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
                     ` (6 preceding siblings ...)
  2019-08-20  3:54   ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
@ 2019-08-20 13:56   ` Phillip Wood
  2019-08-20 17:53     ` Junio C Hamano
  7 siblings, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-08-20 13:56 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 20/08/2019 04:45, Rohit Ashiwal wrote:
> I've tries to incorporated all the suggestions.

It is helpful if you can list the changes to remind us all what we said. 
(as a patch author I find composing that is helpful to remind me if 
there's anything I've forgotten to address)

Also there are a couple of things that were discussed such as splitting 
up the author and passing it round as a <name, email, date, tz> tuple 
and testing a non-default timezone which aren't included - that's fine 
but it helps if you take a moment to explain why in the cover letter.

> 
> Some points:
>    - According to v2.0.0's git-am.sh, ignore-date should override
>      committer-date-is-author-date. Ergo, we are not barfing out
>      when both flags are provided.
>    - Should the 'const' qualifier be removed[2]? Since it is leaving
>      a false impression that author should not be free()'d.

The author returned by read_author_ident() is owned by the strbuf that 
you pass to read_author_ident() which is confusing.

Best Wishes

Phillip

> 
> [1]: git show v2.0.0:git-am.sh
> [2]: https://github.com/git/git/blob/v2.23.0/sequencer.c#L959
> 
> Rohit Ashiwal (6):
>    rebase -i: add --ignore-whitespace flag
>    sequencer: add NULL checks under read_author_script
>    rebase -i: support --committer-date-is-author-date
>    sequencer: rename amend_author to author_to_rename
>    rebase -i: support --ignore-date
>    rebase: add --reset-author-date
> 
>   Documentation/git-rebase.txt            |  26 +++--
>   builtin/rebase.c                        |  53 +++++++---
>   sequencer.c                             | 135 ++++++++++++++++++++++--
>   sequencer.h                             |   2 +
>   t/t3422-rebase-incompatible-options.sh  |   2 -
>   t/t3433-rebase-options-compatibility.sh | 100 ++++++++++++++++++
>   6 files changed, 289 insertions(+), 29 deletions(-)
>   create mode 100755 t/t3433-rebase-options-compatibility.sh
> 
> Range-diff:
> 1:  4cd0aa3084 ! 1:  e82ed8cad5 rebase -i: add --ignore-whitespace flag
>      @@ -19,10 +19,13 @@
>        default is `--no-fork-point`, otherwise the default is `--fork-point`.
>        
>        --ignore-whitespace::
>      -+	This flag is either passed to the 'git apply' program
>      -+	(see linkgit:git-apply[1]), or to 'git merge' program
>      -+	(see linkgit:git-merge[1]) as `-Xignore-space-change`,
>      -+	depending on which backend is selected by other options.
>      ++	Behaves differently depending on which backend is selected.
>      +++
>      ++'am' backend: When applying a patch, ignore changes in whitespace in
>      ++context lines if necessary.
>      +++
>      ++'interactive' backend: Treat lines with only whitespace changes as
>      ++unchanged for the sake of a three-way merge.
>       +
>        --whitespace=<option>::
>       -	These flag are passed to the 'git apply' program
>      @@ -63,7 +66,7 @@
>        
>        static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>        {
>      -+	char *strategy_opts = opts->strategy_opts;
>      ++	struct strbuf strategy_buf = STRBUF_INIT;
>        	struct replay_opts replay = REPLAY_OPTS_INIT;
>        
>        	replay.action = REPLAY_INTERACTIVE_REBASE;
>      @@ -71,24 +74,19 @@
>        	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>        	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>        	replay.strategy = opts->strategy;
>      --	if (opts->strategy_opts)
>      --		parse_strategy_opts(&replay, opts->strategy_opts);
>      -+
>      -+	if (opts->ignore_whitespace) {
>      -+		struct strbuf buf = STRBUF_INIT;
>      -+
>      -+		if (strategy_opts)
>      -+			strbuf_addstr(&buf, strategy_opts);
>       +
>      -+		strbuf_addstr(&buf, " --ignore-space-change");
>      -+		free(strategy_opts);
>      -+		strategy_opts = strbuf_detach(&buf, NULL);
>      -+	}
>      -+	if (strategy_opts)
>      -+		parse_strategy_opts(&replay, strategy_opts);
>      + 	if (opts->strategy_opts)
>      +-		parse_strategy_opts(&replay, opts->strategy_opts);
>      ++		strbuf_addstr(&strategy_buf, opts->strategy_opts);
>      ++	if (opts->ignore_whitespace)
>      ++		strbuf_addstr(&strategy_buf, " --ignore-space-change");
>      ++	if (strategy_buf.len)
>      ++		parse_strategy_opts(&replay, strategy_buf.buf);
>        
>      ++	strbuf_release(&strategy_buf);
>        	return replay;
>        }
>      +
>       @@
>        	argc = parse_options(argc, argv, prefix, options,
>        			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
> 2:  e2c0304587 = 2:  209057b361 sequencer: add NULL checks under read_author_script
> 3:  6aed57ae2e ! 3:  a4e6644ef8 rebase -i: support --committer-date-is-author-date
>      @@ -21,10 +21,12 @@
>       +
>        --ignore-date::
>       -	These flags are passed to 'git am' to easily change the dates
>      +-	of the rebased commits (see linkgit:git-am[1]).
>       +	This flag is passed to 'git am' to change the author date
>      - 	of the rebased commits (see linkgit:git-am[1]).
>      ++	of each rebased commit (see linkgit:git-am[1]).
>        +
>        See also INCOMPATIBLE OPTIONS below.
>      +
>       @@
>        
>        The following options:
>      @@ -62,16 +64,6 @@
>        	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>        	replay.strategy = opts->strategy;
>        
>      -@@
>      - 		warning(_("--[no-]rebase-cousins has no effect without "
>      - 			  "--rebase-merges"));
>      -
>      -+	if (opts.committer_date_is_author_date)
>      -+		opts.flags |= REBASE_FORCE;
>      -+
>      - 	return !!run_rebase_interactive(&opts, command);
>      - }
>      -
>       @@
>        
>        	if (opts->ignore_whitespace)
>      @@ -149,14 +141,14 @@
>       +		struct strbuf datebuf = STRBUF_INIT;
>       +		char *date = read_author_date_or_null();
>       +
>      ++		if (!date)
>      ++			return -1;
>      ++
>       +		strbuf_addf(&datebuf, "@%s", date);
>       +		free(date);
>       +
>       +		date = strbuf_detach(&datebuf, &len);
>      -+
>      -+		if (len > 1)
>      -+			res = setenv("GIT_COMMITTER_DATE", date, 1);
>      -+
>      ++		res = setenv("GIT_COMMITTER_DATE", date, 1);
>       +		free(date);
>       +
>       +		if (res)
>      @@ -187,7 +179,7 @@
>       +		if (!ident.date_begin)
>       +			return error(_("corrupted author without date information"));
>       +
>      -+		strbuf_addf(&date, "@%s",ident.date_begin);
>      ++		strbuf_addf(&date, "@%s", ident.date_begin);
>       +		setenv("GIT_COMMITTER_DATE", date.buf, 1);
>       +		strbuf_release(&date);
>       +	}
> 4:  36a0c017c2 = 4:  6ac1885c54 sequencer: rename amend_author to author_to_rename
> 5:  3a4ffeb995 ! 5:  a69749dd67 rebase -i: support --ignore-date
>      @@ -16,9 +16,9 @@
>        
>        --ignore-date::
>       -	This flag is passed to 'git am' to change the author date
>      --	of the rebased commits (see linkgit:git-am[1]).
>      -+	Instead of using the given author date, re-set it to the value
>      -+	same as committer (current) date. This implies --force-rebase.
>      +-	of each rebased commit (see linkgit:git-am[1]).
>      ++	Instead of using the given author date, reset it to the value
>      ++	same as the current time. This implies --force-rebase.
>        +
>        See also INCOMPATIBLE OPTIONS below.
>        
>      @@ -58,18 +58,6 @@
>        	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>        	replay.strategy = opts->strategy;
>        
>      -@@
>      - 		warning(_("--[no-]rebase-cousins has no effect without "
>      - 			  "--rebase-merges"));
>      -
>      --	if (opts.committer_date_is_author_date)
>      -+	if (opts.ignore_date)
>      -+		opts.committer_date_is_author_date = 0;
>      -+	if (opts.committer_date_is_author_date ||
>      -+	    opts.ignore_date)
>      - 		opts.flags |= REBASE_FORCE;
>      -
>      - 	return !!run_rebase_interactive(&opts, command);
>       @@
>        		argv_array_push(&am.args, "--ignore-whitespace");
>        	if (opts->committer_date_is_author_date)
>      @@ -125,18 +113,19 @@
>        	return buf->buf;
>        }
>        
>      -+static void ignore_author_date(const char **author)
>      ++/* Construct a free()able author string with current time as the author date */
>      ++static char *ignore_author_date(const char *author)
>       +{
>      -+	int len = strlen(*author);
>      ++	int len = strlen(author);
>       +	struct ident_split ident;
>       +	struct strbuf new_author = STRBUF_INIT;
>       +
>      -+	split_ident_line(&ident, *author, len);
>      ++	split_ident_line(&ident, author, len);
>       +	len = ident.mail_end - ident.name_begin + 1;
>       +
>      -+	strbuf_addf(&new_author, "%.*s", len, *author);
>      ++	strbuf_addf(&new_author, "%.*s ", len, author);
>       +	datestamp(&new_author);
>      -+	*author = strbuf_detach(&new_author, NULL);
>      ++	return strbuf_detach(&new_author, NULL);
>       +}
>       +
>       +static void push_dates(struct child_process *child)
>      @@ -160,11 +149,13 @@
>       -		else
>       +		else {
>       +			if (opts->ignore_date) {
>      ++				char *new_author = ignore_author_date(author);
>       +				if (!author)
>       +					BUG("ignore-date can only be used with "
>       +					    "rebase, which must set the author "
>       +					    "before committing the tree");
>      -+				ignore_author_date(&author);
>      ++				free((void *)author);
>      ++				author = new_author;
>       +			}
>        			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
>        					  NULL, &root_commit, author,
>      @@ -187,7 +178,7 @@
>        	reset_ident_date();
>        
>       +	if (opts->ignore_date) {
>      -+		ignore_author_date(&author);
>      ++		author = ignore_author_date(author);
>       +		free(author_to_free);
>       +		author_to_free = (char *)author;
>       +	}
> 6:  cb81e6c4e5 ! 6:  210d15cca0 rebase: add --author-date-is-committer-date
>      @@ -1,6 +1,6 @@
>       Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>       
>      -    rebase: add --author-date-is-committer-date
>      +    rebase: add --reset-author-date
>       
>           The previous commit introduced --ignore-date flag to interactive
>           rebase, but the name is actually very vague in context of rebase -i
>      @@ -16,9 +16,9 @@
>        	as the committer date. This implies --force-rebase.
>        
>        --ignore-date::
>      -+--author-date-is-committer-date::
>      - 	Instead of using the given author date, re-set it to the value
>      - 	same as committer (current) date. This implies --force-rebase.
>      ++--reset-author-date::
>      + 	Instead of using the given author date, reset it to the value
>      + 	same as the current time. This implies --force-rebase.
>        +
>       
>        diff --git a/builtin/rebase.c b/builtin/rebase.c
>      @@ -28,7 +28,7 @@
>        		OPT_BOOL(0, "committer-date-is-author-date",
>        			 &options.committer_date_is_author_date,
>        			 N_("make committer date match author date")),
>      -+		OPT_BOOL(0, "author-date-is-committer-date", &options.ignore_date,
>      ++		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
>       +			 "ignore author date and use current date"),
>        		OPT_BOOL(0, "ignore-date", &options.ignore_date,
>        			 "ignore author date and use current date"),
> 

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

* Re: [PATCH v3 5/6] rebase -i: support --ignore-date
  2019-08-20  3:45   ` [PATCH v3 5/6] rebase -i: support --ignore-date Rohit Ashiwal
  2019-08-20 13:45     ` Phillip Wood
@ 2019-08-20 17:42     ` Junio C Hamano
  2019-08-20 18:30       ` Phillip Wood
  1 sibling, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-20 17:42 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +	int len = strlen(author);

Mental note: ignore_author_date() would not allow author==NULL as its input.

> @@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,
>  
>  		if (res <= 0)
>  			res = error_errno(_("could not read '%s'"), defmsg);
> -		else
> +		else {
> +			if (opts->ignore_date) {
> +				char *new_author = ignore_author_date(author);
> +				if (!author)
> +					BUG("ignore-date can only be used with "
> +					    "rebase, which must set the author "
> +					    "before committing the tree");

Yet, author is used and then checked for NULL-ness, which is
backwards.  Before we have a chance to issue this BUG(), we would
already have segfaulted inside ignore_author_date().


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

* Re: [PATCH v3 0/6] rebase -i: support more options
  2019-08-20 13:56   ` Phillip Wood
@ 2019-08-20 17:53     ` Junio C Hamano
  2019-08-20 18:37       ` Phillip Wood
  0 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-08-20 17:53 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

Phillip Wood <phillip.wood123@gmail.com> writes:

> Hi Rohit
>
> On 20/08/2019 04:45, Rohit Ashiwal wrote:
>> I've tries to incorporated all the suggestions.
>
> It is helpful if you can list the changes to remind us all what we
> said. (as a patch author I find composing that is helpful to remind me
> if there's anything I've forgotten to address)
>
> Also there are a couple of things that were discussed such as
> splitting up the author and passing it round as a <name, email, date,
> tz> tuple and testing a non-default timezone which aren't included -
> that's fine but it helps if you take a moment to explain why in the
> cover letter.
>
>>
>> Some points:
>>    - According to v2.0.0's git-am.sh, ignore-date should override
>>      committer-date-is-author-date. Ergo, we are not barfing out
>>      when both flags are provided.
>>    - Should the 'const' qualifier be removed[2]? Since it is leaving
>>      a false impression that author should not be free()'d.
>
> The author returned by read_author_ident() is owned by the strbuf that
> you pass to read_author_ident() which is confusing.
>
> Best Wishes
>
> Phillip

I've looked at this round, but will push out v2 for today's
integration cycle, mostly due to lack of time, but there do not seem
to be great difference between the iterations.

The "ignore-date" step conflicts semantically with b0a31861
("sequencer: simplify root commit creation", 2019-08-19) but in a
good way.  Without the clean-up b0a31861 makes, we need to munge the
timestamp in two places, but with it, there is only one place that
needs to modify the timestamp for the feature (in try_to_commit()).

You may want to see if these "more options" topic can take advantage
of the "simplify root commit creation" by building on top of some
form of it (I do not know offhand if b0a31861 ("sequencer: simplify
root commit creation", 2019-08-19) must build on other two patches
to fix "rebase -i" or it can be split out as an independent
clean-up), and if it is feasible, work with your student to make it
happen, perhaps?

Thanks.


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

* Re: [PATCH v3 5/6] rebase -i: support --ignore-date
  2019-08-20 17:42     ` Junio C Hamano
@ 2019-08-20 18:30       ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-20 18:30 UTC (permalink / raw)
  To: Junio C Hamano, Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, t.gummerer

On 20/08/2019 18:42, Junio C Hamano wrote:
> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:
> 
>> +/* Construct a free()able author string with current time as the author date */
>> +static char *ignore_author_date(const char *author)
>> +{
>> +	int len = strlen(author);
> 
> Mental note: ignore_author_date() would not allow author==NULL as its input.
> 
>> @@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,
>>   
>>   		if (res <= 0)
>>   			res = error_errno(_("could not read '%s'"), defmsg);
>> -		else
>> +		else {
>> +			if (opts->ignore_date) {
>> +				char *new_author = ignore_author_date(author);
>> +				if (!author)
>> +					BUG("ignore-date can only be used with "
>> +					    "rebase, which must set the author "
>> +					    "before committing the tree");
> 
> Yet, author is used and then checked for NULL-ness, which is
> backwards.  Before we have a chance to issue this BUG(), we would
> already have segfaulted inside ignore_author_date().
> 

Good catch!

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

* Re: [PATCH v3 0/6] rebase -i: support more options
  2019-08-20 17:53     ` Junio C Hamano
@ 2019-08-20 18:37       ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-08-20 18:37 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

On 20/08/2019 18:53, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> Hi Rohit
>>
>> On 20/08/2019 04:45, Rohit Ashiwal wrote:
>>> I've tries to incorporated all the suggestions.
>>
>> It is helpful if you can list the changes to remind us all what we
>> said. (as a patch author I find composing that is helpful to remind me
>> if there's anything I've forgotten to address)
>>
>> Also there are a couple of things that were discussed such as
>> splitting up the author and passing it round as a <name, email, date,
>> tz> tuple and testing a non-default timezone which aren't included -
>> that's fine but it helps if you take a moment to explain why in the
>> cover letter.
>>
>>>
>>> Some points:
>>>     - According to v2.0.0's git-am.sh, ignore-date should override
>>>       committer-date-is-author-date. Ergo, we are not barfing out
>>>       when both flags are provided.
>>>     - Should the 'const' qualifier be removed[2]? Since it is leaving
>>>       a false impression that author should not be free()'d.
>>
>> The author returned by read_author_ident() is owned by the strbuf that
>> you pass to read_author_ident() which is confusing.
>>
>> Best Wishes
>>
>> Phillip
> 
> I've looked at this round, but will push out v2 for today's
> integration cycle, mostly due to lack of time, but there do not seem
> to be great difference between the iterations.
> 
> The "ignore-date" step conflicts semantically with b0a31861
> ("sequencer: simplify root commit creation", 2019-08-19) but in a
> good way.  Without the clean-up b0a31861 makes, we need to munge the
> timestamp in two places, but with it, there is only one place that
> needs to modify the timestamp for the feature (in try_to_commit()).

That was my hope

> You may want to see if these "more options" topic can take advantage
> of the "simplify root commit creation" by building on top of some
> form of it (I do not know offhand if b0a31861 ("sequencer: simplify
> root commit creation", 2019-08-19) must build on other two patches
> to fix "rebase -i" or it can be split out as an independent
> clean-up), and if it is feasible, work with your student to make it
> happen, perhaps?

If it is separated out from the first two there will be a minor textual 
conflict as the first patch in that series changes the root commit 
creation to stop it writing CHERRY_PICK_HEAD and then b0a31861 deletes 
the modified version but it shouldn't be a problem to resolve manually. 
Rohit do you want to try cherry-picking b0a31861 onto master and then 
rebasing your patches on top of it? - it would be nice to simplify things.

Best Wishes

Phillip

> Thanks.
> 

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

* Re: [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-20  3:45   ` [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-08-20 18:40     ` Phillip Wood
  2019-08-20 18:47       ` Rohit Ashiwal
  0 siblings, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-08-20 18:40 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 20/08/2019 04:45, Rohit Ashiwal wrote:
> There are two backends available for rebasing, viz, the am and the
> interactive. Naturally, there shall be some features that are
> implemented in one but not in the other. One such flag is
> --ignore-whitespace which indicates merge mechanism to treat lines
> with only whitespace changes as unchanged. Wire the interactive
> rebase to also understand the --ignore-whitespace flag by
> translating it to -Xignore-space-change.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            | 13 ++++-
>   builtin/rebase.c                        | 22 +++++++--
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
>   4 files changed, 94 insertions(+), 7 deletions(-)
>   create mode 100755 t/t3433-rebase-options-compatibility.sh
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 6156609cf7..873eb5768c 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -371,8 +371,16 @@ If either <upstream> or --root is given on the command line, then the
>   default is `--no-fork-point`, otherwise the default is `--fork-point`.
>   
>   --ignore-whitespace::
> +	Behaves differently depending on which backend is selected.
> ++
> +'am' backend: When applying a patch, ignore changes in whitespace in
> +context lines if necessary.
> ++
> +'interactive' backend: Treat lines with only whitespace changes as
> +unchanged for the sake of a three-way merge.
> +

Thanks for spelling out exactly what this does. I had not appreciated 
the difference before. Does this mean that if I have a branch with some 
whitespace cleanups I'll get different results if I rebase it with the 
sequencer compared to am? (I suspect from the description that the 
sequencer will simply ignore all my whitespace changes)

I think this is ready if we can live with the difference - I'm not 
entirely convinced that adding an option with the same name and a 
different behavior is going to improve things though.

Best Wishes

Phillip

>   --whitespace=<option>::
> -	These flag are passed to the 'git apply' program
> +	This flag is passed to the 'git apply' program
>   	(see linkgit:git-apply[1]) that applies the patch.
>   +
>   See also INCOMPATIBLE OPTIONS below.
> @@ -520,7 +528,6 @@ The following options:
>    * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
> - * --ignore-whitespace
>    * -C
>   
>   are incompatible with the following options:
> @@ -543,6 +550,8 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --interactive
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
> + * --preserve-merges and --ignore-whitespace
> + * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
>   
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 670096c065..f8a618d54c 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -79,6 +79,7 @@ struct rebase_options {
>   	int allow_rerere_autoupdate;
>   	int keep_empty;
>   	int autosquash;
> +	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
>   	char *cmd;
> @@ -99,6 +100,7 @@ struct rebase_options {
>   
>   static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   {
> +	struct strbuf strategy_buf = STRBUF_INIT;
>   	struct replay_opts replay = REPLAY_OPTS_INIT;
>   
>   	replay.action = REPLAY_INTERACTIVE_REBASE;
> @@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
> +
>   	if (opts->strategy_opts)
> -		parse_strategy_opts(&replay, opts->strategy_opts);
> +		strbuf_addstr(&strategy_buf, opts->strategy_opts);
> +	if (opts->ignore_whitespace)
> +		strbuf_addstr(&strategy_buf, " --ignore-space-change");
> +	if (strategy_buf.len)
> +		parse_strategy_opts(&replay, strategy_buf.buf);
>   
> +	strbuf_release(&strategy_buf);
>   	return replay;
>   }
>   
> @@ -511,6 +519,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   	argc = parse_options(argc, argv, prefix, options,
>   			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>   
> +	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> +
>   	if (!is_null_oid(&squash_onto))
>   		opts.squash_onto = &squash_onto;
>   
> @@ -964,6 +974,8 @@ static int run_am(struct rebase_options *opts)
>   	am.git_cmd = 1;
>   	argv_array_push(&am.args, "am");
>   
> +	if (opts->ignore_whitespace)
> +		argv_array_push(&am.args, "--ignore-whitespace");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1407,9 +1419,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -				  NULL, N_("passed to 'git am'"),
> -				  PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>   				  &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> @@ -1417,6 +1426,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>   				  N_("passed to 'git apply'"), 0),
> +		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> +			 N_("ignore changes in whitespace")),
>   		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>   				  N_("action"), N_("passed to 'git apply'"), 0),
>   		OPT_BIT('f', "force-rebase", &options.flags,
> @@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   	}
>   
>   	if (options.rebase_merges) {
> +		if (options.ignore_whitespace)
> +			die(_("cannot combine '--rebase-merges' with "
> +			      "'--ignore-whitespace'"));
>   		if (strategy_options.nr)
>   			die(_("cannot combine '--rebase-merges' with "
>   			      "'--strategy-option'"));
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index a5868ea152..4342f79eea 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>   test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> new file mode 100755
> index 0000000000..2e16e00a9d
> --- /dev/null
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -0,0 +1,65 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +	git checkout -b topic &&
> +	q_to_tab >file <<-\EOF &&
> +	line 1
> +	Qline 2
> +	line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	cat >file <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	git commit -am "update file" &&
> +	git tag side &&
> +
> +	git checkout --orphan master &&
> +	sed -e "s/^|//" >file <<-\EOF &&
> +	|line 1
> +	|        line 2
> +	|line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	git tag main
> +'
> +
> +test_expect_success '--ignore-whitespace works with am backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	test_must_fail git rebase main side &&
> +	git rebase --abort &&
> +	git rebase --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace works with interactive backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	test_must_fail git rebase --merge main side &&
> +	git rebase --abort &&
> +	git rebase --merge --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_done
> 

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

* Re: [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-20 18:40     ` Phillip Wood
@ 2019-08-20 18:47       ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-08-20 18:47 UTC (permalink / raw)
  To: Phillip
  Cc: Johannes Schindelin, git, Junio C Hamano, Martin Ågren,
	Elijah Newren, Thomas Gummerer

Hi Phillip

On Wed, Aug 21, 2019 at 12:10 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> Thanks for spelling out exactly what this does. I had not appreciated
> the difference before. Does this mean that if I have a branch with some
> whitespace cleanups I'll get different results if I rebase it with the
> sequencer compared to am? (I suspect from the description that the
> sequencer will simply ignore all my whitespace changes)

I'm afraid that this is the case.

> I think this is ready if we can live with the difference - I'm not
> entirely convinced that adding an option with the same name and a
> different behavior is going to improve things though.

This is the first step to improving consistency. We can
further improve upon the implementation. I have already
mentioned that in the cover letter of previous patches[1].

Thanks
Rohit

[1]: https://public-inbox.org/git/20190712185015.20585-1-rohit.ashiwal265@gmail.com/

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

* Re: [PATCH v3 2/6] sequencer: add NULL checks under read_author_script
  2019-08-20  3:45   ` [PATCH v3 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
@ 2019-08-23 15:20     ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-08-23 15:20 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

> read_author_script reads name, email and author date from the author
> script. However, it does not check if the arguments are NULL. Adding
> NULL checks will allow us to selectively get the required value,...

I had a hard time understanding the argument here without knowing
why I had trouble, and I think I figured it out.  What you wrote may
not be incorrect per-se, but the logic is backwards.

The function has been about reading all three, and it always took
and required the callers to pass three valid pointers to locations
to store these three.  It did not check for NULL; passing NULL was
simply a bug in the caller who deserved a segfault.

This series, however, wants to allow new callers of the function to
selectively read some among the three and ignore the rest, and you
happened to choose "pass NULL for an uninteresting field" as the
new calling convention.

That choice is where "checking for NULL" comes in.

In other words, "checking for NULL" is merely an implementation
detail for a more important change this patch brings in: We now
can read some and ignore the rest, while requiring that the input
file is well formed even for the fields we do not care about.



    sequencer: allow callers of read_author_script() to ignore fields

    The current callers of the read_author_script() function read
    name, email and date from the author script.  Allow callers to
    signal that they are not interested in some among these three
    fields by passing NULL.

    Note that fields that are ignored still must exist and be
    formatted correctly in the author script.

or something like that, perhaps.


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

* [PATCH v4 0/6] rebase -i: support more options
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (7 preceding siblings ...)
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
@ 2019-09-07 11:50 ` " Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
                     ` (6 more replies)
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
  9 siblings, 7 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

Following the suggestion of Phillip I've rebased my patch on master (745f681289)
and cherry-picking b0a3186140.

Base: 745f6812895b31c02b29bdfe4ae8e5498f776c26
      with cherry-picked b0a3186140dbc7bd64cbc6ef733386a0f1eb6a4d

Outline:
  2/6:
      - Change commit message and description
  3/6:
      - add test for rebase -r
      - add strict bounds while pushing ident date
  5/6:
      - bug fix: (following am's code) if --ignore-date is provided,
                 we should setenv GIT_COMMITTER_DATE to "".
      - catch error when ident line is malformed
      - push GIT_AUTHOR_DATE instead of providing it with --date so
        that "git merge" can also use push_dates function
      - add test for rebase -r


Rohit Ashiwal (6):
  rebase -i: add --ignore-whitespace flag
  sequencer: allow callers of read_author_script() to ignore fields
  rebase -i: support --committer-date-is-author-date
  sequencer: rename amend_author to author_to_rename
  rebase -i: support --ignore-date
  rebase: add --reset-author-date

 Documentation/git-rebase.txt            |  26 +++--
 builtin/rebase.c                        |  55 +++++++---
 sequencer.c                             | 134 +++++++++++++++++++++--
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 137 ++++++++++++++++++++++++
 6 files changed, 328 insertions(+), 28 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

Range-diff:
--- snip ---
 1:  e82ed8cad5 = 49:  77af1d66db rebase -i: add --ignore-whitespace flag
 2:  209057b361 ! 50:  1f7f1407b2 sequencer: add NULL checks under read_author_script
    @@ -1,19 +1,14 @@
     Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
     
    -    sequencer: add NULL checks under read_author_script
    +    sequencer: allow callers of read_author_script() to ignore fields
     
    -    read_author_script reads name, email and author date from the author
    -    script. However, it does not check if the arguments are NULL. Adding
    -    NULL checks will allow us to selectively get the required value, for
    -    example:
    +    The current callers of the read_author_script() function read name,
    +    email and date from the author script.  Allow callers to signal that
    +    they are not interested in some among these three fields by passing
    +    NULL.
     
    -        char *date;
    -        if (read_author_script(_path_, NULL, NULL, &date, _int_))
    -                die(_("failed to read author date"));
    -        /* needs to be free()'d */
    -        return date;
    -
    -    Add NULL checks for better control over the information retrieved.
    +    Note that fields that are ignored still must exist and be formatted
    +    correctly in the author script.
     
         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
     
 3:  a4e6644ef8 ! 51:  cc1614154e rebase -i: support --committer-date-is-author-date
    @@ -128,35 +128,34 @@
     +	return date;
     +}
     +
    - /* Read author-script and return an ident line (author <email> timestamp) */
    - static const char *read_author_ident(struct strbuf *buf)
    - {
    + static const char staged_changes_advice[] =
    + N_("you have staged changes in your working tree\n"
    + "If these changes are meant to be squashed into the previous commit, run:\n"
     @@
    - {
    - 	struct child_process cmd = CHILD_PROCESS_INIT;
      
    -+	if (opts->committer_date_is_author_date) {
    -+		size_t len;
    -+		int res = -1;
    -+		struct strbuf datebuf = STRBUF_INIT;
    -+		char *date = read_author_date_or_null();
    + 	cmd.git_cmd = 1;
    + 
    ++        if (opts->committer_date_is_author_date) {
    ++	        int res = -1;
    ++	        struct strbuf datebuf = STRBUF_INIT;
    ++	        char *date = read_author_date_or_null();
     +
    -+		if (!date)
    -+			return -1;
    ++	        if (!date)
    ++	                return -1;
     +
    -+		strbuf_addf(&datebuf, "@%s", date);
    -+		free(date);
    ++	        strbuf_addf(&datebuf, "@%s", date);
    ++	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
     +
    -+		date = strbuf_detach(&datebuf, &len);
    -+		res = setenv("GIT_COMMITTER_DATE", date, 1);
    -+		free(date);
    ++		strbuf_release(&datebuf);
    ++	        free(date);
     +
    -+		if (res)
    -+			return -1;
    -+	}
    - 	if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
    - 		struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
    - 		const char *author = NULL;
    ++	        if (res)
    ++	                return -1;
    ++        }
    ++
    + 	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
    + 		const char *gpg_opt = gpg_sign_opt_quoted(opts);
    + 
     @@
      
      	if (parse_head(r, &current_head))
    @@ -174,14 +173,19 @@
     +		struct ident_split ident;
     +		struct strbuf date = STRBUF_INIT;
     +
    -+		split_ident_line(&ident, author, len);
    -+
    ++		if (split_ident_line(&ident, author, len) < 0)
    ++			return error(_("malformed ident line"));
     +		if (!ident.date_begin)
     +			return error(_("corrupted author without date information"));
     +
    -+		strbuf_addf(&date, "@%s", ident.date_begin);
    -+		setenv("GIT_COMMITTER_DATE", date.buf, 1);
    ++		strbuf_addf(&date, "@%.*s %.*s",
    ++			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
    ++			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
    ++		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
     +		strbuf_release(&date);
    ++
    ++		if (res)
    ++			goto out;
     +	}
     +
      	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
    @@ -256,6 +260,20 @@
      # This is a special case in which both am and interactive backends
      # provide the same output. It was done intentionally because
      # both the backends fall short of optimal behaviour.
    +@@
    + 	EOF
    + 	git commit -am "update file" &&
    + 	git tag side &&
    ++	test_commit commit1 foo foo1 &&
    ++	test_commit commit2 foo foo2 &&
    ++	test_commit commit3 foo foo3 &&
    + 
    + 	git checkout --orphan master &&
    ++	git rm --cached foo &&
    ++	rm foo &&
    + 	sed -e "s/^|//" >file <<-\EOF &&
    + 	|line 1
    + 	|        line 2
     @@
      	test_cmp expect file
      '
    @@ -275,5 +293,18 @@
     +	git show HEAD --pretty="format:%ci" >committertime &&
     +	test_cmp authortime committertime
     +'
    ++
    ++test_expect_success '--committer-date-is-author-date works with rebase -r' '
    ++	git checkout side &&
    ++	git merge commit3 &&
    ++	git rebase -r --root --committer-date-is-author-date &&
    ++	git rev-list HEAD >rev_list &&
    ++	while read HASH
    ++	do
    ++		git show $HASH --pretty="format:%ai" >authortime
    ++		git show $HASH --pretty="format:%ci" >committertime
    ++		test_cmp authortime committertime
    ++	done <rev_list
    ++'
     +
      test_done
 4:  6ac1885c54 = 52:  9e92c79bda sequencer: rename amend_author to author_to_rename
 5:  a69749dd67 ! 53:  fc68e55e78 rebase -i: support --ignore-date
    @@ -83,8 +83,10 @@
      	}
      
     -	if (options.committer_date_is_author_date)
    -+	if (options.ignore_date)
    ++	if (options.ignore_date) {
     +		options.committer_date_is_author_date = 0;
    ++		setenv("GIT_COMMITTER_DATE", "", 1);
    ++	}
     +	if (options.committer_date_is_author_date ||
     +	    options.ignore_date)
      		options.flags |= REBASE_FORCE;
    @@ -110,7 +112,7 @@
      static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
      static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
     @@
    - 	return buf->buf;
    + 	return date;
      }
      
     +/* Construct a free()able author string with current time as the author date */
    @@ -120,7 +122,10 @@
     +	struct ident_split ident;
     +	struct strbuf new_author = STRBUF_INIT;
     +
    -+	split_ident_line(&ident, author, len);
    ++	if (split_ident_line(&ident, author, len) < 0) {
    ++		error(_("malformed ident line"));
    ++		return NULL;
    ++	}
     +	len = ident.mail_end - ident.name_begin + 1;
     +
     +	strbuf_addf(&new_author, "%.*s ", len, author);
    @@ -134,7 +139,7 @@
     +	struct strbuf date = STRBUF_INIT;
     +
     +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
    -+	argv_array_pushf(&child->args, "--date=%s", date.buf);
    ++	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
     +	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
     +	strbuf_release(&date);
     +}
    @@ -143,28 +148,6 @@
      N_("you have staged changes in your working tree\n"
      "If these changes are meant to be squashed into the previous commit, run:\n"
     @@
    - 
    - 		if (res <= 0)
    - 			res = error_errno(_("could not read '%s'"), defmsg);
    --		else
    -+		else {
    -+			if (opts->ignore_date) {
    -+				char *new_author = ignore_author_date(author);
    -+				if (!author)
    -+					BUG("ignore-date can only be used with "
    -+					    "rebase, which must set the author "
    -+					    "before committing the tree");
    -+				free((void *)author);
    -+				author = new_author;
    -+			}
    - 			res = commit_tree(msg.buf, msg.len, cache_tree_oid,
    - 					  NULL, &root_commit, author,
    - 					  opts->gpg_sign);
    -+		}
    - 
    - 		strbuf_release(&msg);
    - 		strbuf_release(&script);
    -@@
      		argv_array_push(&cmd.args, "--amend");
      	if (opts->gpg_sign)
      		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
    @@ -179,6 +162,10 @@
      
     +	if (opts->ignore_date) {
     +		author = ignore_author_date(author);
    ++		if (!author) {
    ++			res = -1;
    ++			goto out;
    ++		}
     +		free(author_to_free);
     +		author_to_free = (char *)author;
     +	}
    @@ -242,7 +229,7 @@
      --- a/t/t3433-rebase-options-compatibility.sh
      +++ b/t/t3433-rebase-options-compatibility.sh
     @@
    - 	test_cmp authortime committertime
    + 	done <rev_list
      '
      
     +# Checking for +0000 in author time is enough since default
    @@ -252,13 +239,32 @@
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --ignore-date HEAD^ &&
     +	git show HEAD --pretty="format:%ai" >authortime &&
    -+	grep "+0000" authortime
    ++	git show HEAD --pretty="format:%ci" >committertime &&
    ++	grep "+0000" authortime &&
    ++	grep "+0000" committertime
     +'
     +
     +test_expect_success '--ignore-date works with interactive backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --ignore-date -i HEAD^ &&
     +	git show HEAD --pretty="format:%ai" >authortime &&
    -+	grep "+0000" authortime
    ++	git show HEAD --pretty="format:%ci" >committertime &&
    ++	grep "+0000" authortime &&
    ++	grep "+0000" committertime
     +'
    ++
    ++test_expect_success '--ignore-date works with rebase -r' '
    ++	git checkout side &&
    ++	git merge commit3 &&
    ++	git rebase -r --root --ignore-date &&
    ++	git rev-list HEAD >rev_list &&
    ++	while read HASH
    ++	do
    ++		git show $HASH --pretty="format:%ai" >authortime
    ++		git show $HASH --pretty="format:%ci" >committertime
    ++		grep "+0000" authortime
    ++		grep "+0000" committertime
    ++	done <rev_list
    ++'
    ++
      test_done
 6:  210d15cca0 = 54:  396d5f16eb rebase: add --reset-author-date
-- 
2.21.0


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

* [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
@ 2019-09-07 11:50   ` Rohit Ashiwal
  2019-10-04  9:29     ` Phillip Wood
  2019-09-07 11:50   ` [PATCH v4 2/6] sequencer: allow callers of read_author_script() to ignore fields Rohit Ashiwal
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

There are two backends available for rebasing, viz, the am and the
interactive. Naturally, there shall be some features that are
implemented in one but not in the other. One such flag is
--ignore-whitespace which indicates merge mechanism to treat lines
with only whitespace changes as unchanged. Wire the interactive
rebase to also understand the --ignore-whitespace flag by
translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 13 ++++-
 builtin/rebase.c                        | 22 +++++++--
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
 4 files changed, 94 insertions(+), 7 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 6156609cf7..873eb5768c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -371,8 +371,16 @@ If either <upstream> or --root is given on the command line, then the
 default is `--no-fork-point`, otherwise the default is `--fork-point`.
 
 --ignore-whitespace::
+	Behaves differently depending on which backend is selected.
++
+'am' backend: When applying a patch, ignore changes in whitespace in
+context lines if necessary.
++
+'interactive' backend: Treat lines with only whitespace changes as
+unchanged for the sake of a three-way merge.
+
 --whitespace=<option>::
-	These flag are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -520,7 +528,6 @@ The following options:
  * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
- * --ignore-whitespace
  * -C
 
 are incompatible with the following options:
@@ -543,6 +550,8 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --interactive
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
+ * --preserve-merges and --ignore-whitespace
+ * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 670096c065..f8a618d54c 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -79,6 +79,7 @@ struct rebase_options {
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -99,6 +100,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
 
+	strbuf_release(&strategy_buf);
 	return replay;
 }
 
@@ -511,6 +519,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -964,6 +974,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1407,9 +1419,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1417,6 +1426,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	if (options.rebase_merges) {
+		if (options.ignore_whitespace)
+			die(_("cannot combine '--rebase-merges' with "
+			      "'--ignore-whitespace'"));
 		if (strategy_options.nr)
 			die(_("cannot combine '--rebase-merges' with "
 			      "'--strategy-option'"));
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index a5868ea152..4342f79eea 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
new file mode 100755
index 0000000000..2e16e00a9d
--- /dev/null
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with am backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase main side &&
+	git rebase --abort &&
+	git rebase --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with interactive backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_done
-- 
2.21.0


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

* [PATCH v4 2/6] sequencer: allow callers of read_author_script() to ignore fields
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-09-07 11:50   ` Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The current callers of the read_author_script() function read name,
email and date from the author script.  Allow callers to signal that
they are not interested in some among these three fields by passing
NULL.

Note that fields that are ignored still must exist and be formatted
correctly in the author script.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index e55550510a..adeff2561e 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -824,9 +824,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-	*name = kv.items[name_i].util;
-	*email = kv.items[email_i].util;
-	*date = kv.items[date_i].util;
+
+	if (name)
+		*name = kv.items[name_i].util;
+	else
+		free(kv.items[name_i].util);
+	if (email)
+		*email = kv.items[email_i].util;
+	else
+		free(kv.items[email_i].util);
+	if (date)
+		*date = kv.items[date_i].util;
+	else
+		free(kv.items[date_i].util);
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
-- 
2.21.0


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

* [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 2/6] sequencer: allow callers of read_author_script() to ignore fields Rohit Ashiwal
@ 2019-09-07 11:50   ` Rohit Ashiwal
  2019-10-24 13:28     ` Phillip Wood
  2019-09-07 11:50   ` [PATCH v4 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the committer date
by changing it to the author date. Let's add the same for
interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 10 ++--
 builtin/rebase.c                        | 17 +++++--
 sequencer.c                             | 61 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 37 +++++++++++++++
 6 files changed, 116 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 873eb5768c..e7c0eac18c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of recording the time the rebased commits are
+	created as the committer date, reuse the author date
+	as the committer date. This implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -551,6 +554,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index f8a618d54c..656bc7d7e9 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -82,6 +82,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.allow_empty_message = opts->allow_empty_message;
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -976,6 +979,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1419,9 +1424,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1692,10 +1697,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
+
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
diff --git a/sequencer.c b/sequencer.c
index adeff2561e..fd925f2d72 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -879,6 +880,17 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+/* Returns a "date" string that needs to be free()'d by the caller */
+static char *read_author_date_or_null(void)
+{
+	char *date;
+
+	if (read_author_script(rebase_path_author_script(),
+			       NULL, NULL, &date, 0))
+		return NULL;
+	return date;
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +950,24 @@ static int run_git_commit(struct repository *r,
 
 	cmd.git_cmd = 1;
 
+        if (opts->committer_date_is_author_date) {
+	        int res = -1;
+	        struct strbuf datebuf = STRBUF_INIT;
+	        char *date = read_author_date_or_null();
+
+	        if (!date)
+	                return -1;
+
+	        strbuf_addf(&datebuf, "@%s", date);
+	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
+
+		strbuf_release(&datebuf);
+	        free(date);
+
+	        if (res)
+	                return -1;
+        }
+
 	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
 		const char *gpg_opt = gpg_sign_opt_quoted(opts);
 
@@ -1331,7 +1361,6 @@ static int try_to_commit(struct repository *r,
 
 	if (parse_head(r, &current_head))
 		return -1;
-
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1359,6 +1388,26 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, len) < 0)
+			return error(_("malformed ident line"));
+		if (!ident.date_begin)
+			return error(_("corrupted author without date information"));
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2473,6 +2522,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2555,6 +2609,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
 	if (opts->signoff)
 		write_file(rebase_path_signoff(), "--signoff\n");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3752,7 +3808,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 6704acbb9c..e3881e9275 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -43,6 +43,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 4342f79eea..7402f7e3da 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 2e16e00a9d..6c1fbab4d8 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . ./test-lib.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -26,8 +29,13 @@ test_expect_success 'setup' '
 	EOF
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	git rm --cached foo &&
+	rm foo &&
 	sed -e "s/^|//" >file <<-\EOF &&
 	|line 1
 	|        line 2
@@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with am backend' '
+	git commit --amend &&
+	git rebase --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with interactive backend' '
+	git commit --amend &&
+	git rebase -i --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	git merge commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	git rev-list HEAD >rev_list &&
+	while read HASH
+	do
+		git show $HASH --pretty="format:%ai" >authortime
+		git show $HASH --pretty="format:%ci" >committertime
+		test_cmp authortime committertime
+	done <rev_list
+'
+
 test_done
-- 
2.21.0


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

* [PATCH v4 4/6] sequencer: rename amend_author to author_to_rename
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
                     ` (2 preceding siblings ...)
  2019-09-07 11:50   ` [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-09-07 11:50   ` Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 5/6] rebase -i: support --ignore-date Rohit Ashiwal
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() while amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index fd925f2d72..0d78abeec8 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1354,7 +1354,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1375,7 +1375,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1470,7 +1470,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.21.0


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

* [PATCH v4 5/6] rebase -i: support --ignore-date
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
                     ` (3 preceding siblings ...)
  2019-09-07 11:50   ` [PATCH v4 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-09-07 11:50   ` Rohit Ashiwal
  2019-09-07 20:56     ` Rohit Ashiwal
  2019-09-07 11:50   ` [PATCH v4 6/6] rebase: add --reset-author-date Rohit Ashiwal
  2019-09-09 18:02   ` [PATCH v4 0/6] rebase -i: support more options Junio C Hamano
  6 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the author date
by changing it to the committer (current) date. Let's add the same
for interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  6 +--
 builtin/rebase.c                        | 18 ++++++---
 sequencer.c                             | 53 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3433-rebase-options-compatibility.sh | 35 ++++++++++++++++
 5 files changed, 104 insertions(+), 9 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e7c0eac18c..e7ac9fae0b 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the given author date, reset it to the value
+	same as the current time. This implies --force-rebase.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --ignore-date
  * --whitespace
  * -C
 
@@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --rebase-merges and --ignore-whitespace
  * --rebase-merges and --strategy
  * --rebase-merges and --strategy-option
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 656bc7d7e9..e6f90f61dd 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -83,6 +83,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -981,6 +983,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1427,8 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1697,13 +1701,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
-	if (options.committer_date_is_author_date)
+	if (options.ignore_date) {
+		options.committer_date_is_author_date = 0;
+		setenv("GIT_COMMITTER_DATE", "", 1);
+	}
+	if (options.committer_date_is_author_date ||
+	    options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index 0d78abeec8..188499190f 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -891,6 +892,35 @@ static char *read_author_date_or_null(void)
 	return date;
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line"));
+		return NULL;
+	}
+	len = ident.mail_end - ident.name_begin + 1;
+
+	strbuf_addf(&new_author, "%.*s ", len, author);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
+static void push_dates(struct child_process *child)
+{
+	time_t now = time(NULL);
+	struct strbuf date = STRBUF_INIT;
+
+	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
+	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
+	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
+	strbuf_release(&date);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -983,6 +1013,8 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+	if (opts->ignore_date)
+		push_dates(&cmd);
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -1451,6 +1483,15 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2527,6 +2568,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2611,6 +2657,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_signoff(), "--signoff\n");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3536,6 +3584,8 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
+		if (opts->ignore_date)
+			push_dates(&cmd);
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3809,7 +3859,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index e3881e9275..bf5a79afdb 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -44,6 +44,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 6c1fbab4d8..0ad7bfc6a0 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -99,4 +99,39 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '
 	done <rev_list
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with am backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	grep "+0000" authortime &&
+	grep "+0000" committertime
+'
+
+test_expect_success '--ignore-date works with interactive backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -i HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	grep "+0000" authortime &&
+	grep "+0000" committertime
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge commit3 &&
+	git rebase -r --root --ignore-date &&
+	git rev-list HEAD >rev_list &&
+	while read HASH
+	do
+		git show $HASH --pretty="format:%ai" >authortime
+		git show $HASH --pretty="format:%ci" >committertime
+		grep "+0000" authortime
+		grep "+0000" committertime
+	done <rev_list
+'
+
 test_done
-- 
2.21.0


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

* [PATCH v4 6/6] rebase: add --reset-author-date
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
                     ` (4 preceding siblings ...)
  2019-09-07 11:50   ` [PATCH v4 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-09-07 11:50   ` Rohit Ashiwal
  2019-09-09 18:02   ` [PATCH v4 0/6] rebase -i: support more options Junio C Hamano
  6 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 11:50 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The previous commit introduced --ignore-date flag to interactive
rebase, but the name is actually very vague in context of rebase -i
since there are two dates we can work with. Add an alias to convey
the precise purpose.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt | 1 +
 builtin/rebase.c             | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e7ac9fae0b..ec62ba36b8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -391,6 +391,7 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the given author date, reset it to the value
 	same as the current time. This implies --force-rebase.
 +
diff --git a/builtin/rebase.c b/builtin/rebase.c
index e6f90f61dd..57e411dd59 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1431,6 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_BOOL(0, "ignore-date", &options.ignore_date,
 			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-- 
2.21.0


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

* Re: [PATCH v4 5/6] rebase -i: support --ignore-date
  2019-09-07 11:50   ` [PATCH v4 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-09-07 20:56     ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-09-07 20:56 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

On Sat,  7 Sep 2019 17:20:33 +0530 Rohit Ashiwal <rohit.ashiwal265@gmail.com> wrote:
> [...]
> +test_expect_success '--ignore-date works with rebase -r' '
> +	git checkout side &&
> +	git merge commit3 &&

Should use --no-ff option to be sure that it handles "merge"
commits properly. Same for [3/6]. Please Junio change it while
applying the patch.

> +	git rebase -r --root --ignore-date &&
> +	git rev-list HEAD >rev_list &&
> +	while read HASH
> +	do
> +		git show $HASH --pretty="format:%ai" >authortime
> +		git show $HASH --pretty="format:%ci" >committertime
> +		grep "+0000" authortime
> +		grep "+0000" committertime
> +	done <rev_list
> +'
> [...]

Best
Rohit


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

* Re: [PATCH v4 0/6] rebase -i: support more options
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
                     ` (5 preceding siblings ...)
  2019-09-07 11:50   ` [PATCH v4 6/6] rebase: add --reset-author-date Rohit Ashiwal
@ 2019-09-09 18:02   ` Junio C Hamano
  2019-09-09 18:51     ` Phillip Wood
  6 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-09-09 18:02 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

> Following the suggestion of Phillip I've rebased my patch on master (745f681289)
> and cherry-picking b0a3186140.

Sorry, but that's horrible.  The latter does not even cleanly apply
on the former.

Let me see if I can find time to whip this into a reasonable shape.

Thanks.

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

* Re: [PATCH v4 0/6] rebase -i: support more options
  2019-09-09 18:02   ` [PATCH v4 0/6] rebase -i: support more options Junio C Hamano
@ 2019-09-09 18:51     ` Phillip Wood
  2019-09-09 19:24       ` Junio C Hamano
  0 siblings, 1 reply; 92+ messages in thread
From: Phillip Wood @ 2019-09-09 18:51 UTC (permalink / raw)
  To: Junio C Hamano, Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, t.gummerer

On 09/09/2019 19:02, Junio C Hamano wrote:
> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:
> 
>> Following the suggestion of Phillip I've rebased my patch on master (745f681289)
>> and cherry-picking b0a3186140.
> 
> Sorry, but that's horrible.  The latter does not even cleanly apply
> on the former.

Yes I had assumed that the cherry pick would become the first patch of 
this series and be dropped from pw/rebase-i-show-HEAD-to-reword. I 
should have been more explicit about that.

> Let me see if I can find time to whip this into a reasonable shape.

As pw/rebase-i-show-HEAD-to-reword is slated for next perhaps these 
could build on that. The first patch needs am -3 to apply to that branch 
but the result looks ok and the rest apply as is.

Best Wishes

Phillip

> Thanks.
> 

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

* Re: [PATCH v4 0/6] rebase -i: support more options
  2019-09-09 18:51     ` Phillip Wood
@ 2019-09-09 19:24       ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-09-09 19:24 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, Johannes.Schindelin, git, martin.agren, newren,
	t.gummerer

Phillip Wood <phillip.wood123@gmail.com> writes:

> Yes I had assumed that the cherry pick would become the first patch of
> this series and be dropped from pw/rebase-i-show-HEAD-to-reword.

Ah, such an arrangement would have made a log more sense, indeed.

> As pw/rebase-i-show-HEAD-to-reword is slated for next perhaps these
> could build on that. The first patch needs am -3 to apply to that
> branch but the result looks ok and the rest apply as is.

As this is more or less "new feature" series, I do not mind too much
to make it depend on another topic in flight that is getting solid.

Thanks for helping.

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

* Re: [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag
  2019-09-07 11:50   ` [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-10-04  9:29     ` Phillip Wood
  2019-10-05 18:12       ` Elijah Newren
  2019-10-06 17:57       ` Rohit Ashiwal
  0 siblings, 2 replies; 92+ messages in thread
From: Phillip Wood @ 2019-10-04  9:29 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 07/09/2019 12:50, Rohit Ashiwal wrote:
> There are two backends available for rebasing, viz, the am and the
> interactive. Naturally, there shall be some features that are
> implemented in one but not in the other. One such flag is
> --ignore-whitespace which indicates merge mechanism to treat lines
> with only whitespace changes as unchanged. Wire the interactive
> rebase to also understand the --ignore-whitespace flag by
> translating it to -Xignore-space-change.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> ---
>   Documentation/git-rebase.txt            | 13 ++++-
>   builtin/rebase.c                        | 22 +++++++--
>   t/t3422-rebase-incompatible-options.sh  |  1 -
>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
>   4 files changed, 94 insertions(+), 7 deletions(-)
>   create mode 100755 t/t3433-rebase-options-compatibility.sh
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 6156609cf7..873eb5768c 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -371,8 +371,16 @@ If either <upstream> or --root is given on the command line, then the
>   default is `--no-fork-point`, otherwise the default is `--fork-point`.
>   
>   --ignore-whitespace::
> +	Behaves differently depending on which backend is selected.
> ++
> +'am' backend: When applying a patch, ignore changes in whitespace in
> +context lines if necessary.
> ++
> +'interactive' backend: Treat lines with only whitespace changes as
> +unchanged for the sake of a three-way merge.
> +
>   --whitespace=<option>::
> -	These flag are passed to the 'git apply' program
> +	This flag is passed to the 'git apply' program
>   	(see linkgit:git-apply[1]) that applies the patch.
>   +
>   See also INCOMPATIBLE OPTIONS below.
> @@ -520,7 +528,6 @@ The following options:
>    * --committer-date-is-author-date
>    * --ignore-date
>    * --whitespace
> - * --ignore-whitespace
>    * -C
>   
>   are incompatible with the following options:
> @@ -543,6 +550,8 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --interactive
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
> + * --preserve-merges and --ignore-whitespace
> + * --rebase-merges and --ignore-whitespace
>    * --rebase-merges and --strategy
>    * --rebase-merges and --strategy-option
>   
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 670096c065..f8a618d54c 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -79,6 +79,7 @@ struct rebase_options {
>   	int allow_rerere_autoupdate;
>   	int keep_empty;
>   	int autosquash;
> +	int ignore_whitespace;
>   	char *gpg_sign_opt;
>   	int autostash;
>   	char *cmd;
> @@ -99,6 +100,7 @@ struct rebase_options {
>   
>   static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   {
> +	struct strbuf strategy_buf = STRBUF_INIT;
>   	struct replay_opts replay = REPLAY_OPTS_INIT;
>   
>   	replay.action = REPLAY_INTERACTIVE_REBASE;
> @@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>   	replay.strategy = opts->strategy;
> +
>   	if (opts->strategy_opts)
> -		parse_strategy_opts(&replay, opts->strategy_opts);
> +		strbuf_addstr(&strategy_buf, opts->strategy_opts);
> +	if (opts->ignore_whitespace)
> +		strbuf_addstr(&strategy_buf, " --ignore-space-change");
> +	if (strategy_buf.len)
> +		parse_strategy_opts(&replay, strategy_buf.buf);
>   
> +	strbuf_release(&strategy_buf);
>   	return replay;
>   }
>   
> @@ -511,6 +519,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>   	argc = parse_options(argc, argv, prefix, options,
>   			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>   
> +	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> +
>   	if (!is_null_oid(&squash_onto))
>   		opts.squash_onto = &squash_onto;
>   
> @@ -964,6 +974,8 @@ static int run_am(struct rebase_options *opts)
>   	am.git_cmd = 1;
>   	argv_array_push(&am.args, "am");
>   
> +	if (opts->ignore_whitespace)
> +		argv_array_push(&am.args, "--ignore-whitespace");
>   	if (opts->action && !strcmp("continue", opts->action)) {
>   		argv_array_push(&am.args, "--resolved");
>   		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1407,9 +1419,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>   		OPT_BOOL(0, "signoff", &options.signoff,
>   			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -				  NULL, N_("passed to 'git am'"),
> -				  PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>   				  &options.git_am_opts, NULL,
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> @@ -1417,6 +1426,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>   				  N_("passed to 'git apply'"), 0),
> +		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> +			 N_("ignore changes in whitespace")),
>   		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>   				  N_("action"), N_("passed to 'git apply'"), 0),
>   		OPT_BIT('f', "force-rebase", &options.flags,
> @@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   	}
>   
>   	if (options.rebase_merges) {
> +		if (options.ignore_whitespace)
> +			die(_("cannot combine '--rebase-merges' with "
> +			      "'--ignore-whitespace'"));

--rebase-merges now supports --strategy_option so we should fix this.

>   		if (strategy_options.nr)
>   			die(_("cannot combine '--rebase-merges' with "
>   			      "'--strategy-option'"));
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index a5868ea152..4342f79eea 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>   test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> new file mode 100755
> index 0000000000..2e16e00a9d
> --- /dev/null
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -0,0 +1,65 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. 

I'm still concerned that we have to construct a special test case to get 
both backends to generate the same output. If this series is about 
supporting the behavior of the am backend in the sequencer then I'm 
worried that having the same option name have two different behaviors 
will create more problems than it solves. Do you have a feeling for how 
often the two backends give different results?

Best Wishes

Phillip

It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +	git checkout -b topic &&
> +	q_to_tab >file <<-\EOF &&
> +	line 1
> +	Qline 2
> +	line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	cat >file <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	git commit -am "update file" &&
> +	git tag side &&
> +
> +	git checkout --orphan master &&
> +	sed -e "s/^|//" >file <<-\EOF &&
> +	|line 1
> +	|        line 2
> +	|line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	git tag main
> +'
> +
> +test_expect_success '--ignore-whitespace works with am backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	test_must_fail git rebase main side &&
> +	git rebase --abort &&
> +	git rebase --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace works with interactive backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	test_must_fail git rebase --merge main side &&
> +	git rebase --abort &&
> +	git rebase --merge --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_done
> 

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

* Re: [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag
  2019-10-04  9:29     ` Phillip Wood
@ 2019-10-05 18:12       ` Elijah Newren
  2019-10-06 17:57       ` Rohit Ashiwal
  1 sibling, 0 replies; 92+ messages in thread
From: Elijah Newren @ 2019-10-05 18:12 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Rohit Ashiwal, Johannes Schindelin, Git Mailing List,
	Junio C Hamano, Martin Ågren, Thomas Gummerer

On Fri, Oct 4, 2019 at 2:29 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> Hi Rohit
>
> On 07/09/2019 12:50, Rohit Ashiwal wrote:
> > There are two backends available for rebasing, viz, the am and the
> > interactive. Naturally, there shall be some features that are
> > implemented in one but not in the other. One such flag is
> > --ignore-whitespace which indicates merge mechanism to treat lines
> > with only whitespace changes as unchanged. Wire the interactive
> > rebase to also understand the --ignore-whitespace flag by
> > translating it to -Xignore-space-change.
> >
> > Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> > ---
> >   Documentation/git-rebase.txt            | 13 ++++-
> >   builtin/rebase.c                        | 22 +++++++--
> >   t/t3422-rebase-incompatible-options.sh  |  1 -
> >   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
> >   4 files changed, 94 insertions(+), 7 deletions(-)
> >   create mode 100755 t/t3433-rebase-options-compatibility.sh
> >
> > diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> > index 6156609cf7..873eb5768c 100644
> > --- a/Documentation/git-rebase.txt
> > +++ b/Documentation/git-rebase.txt
> > @@ -371,8 +371,16 @@ If either <upstream> or --root is given on the command line, then the
> >   default is `--no-fork-point`, otherwise the default is `--fork-point`.
> >
> >   --ignore-whitespace::
> > +     Behaves differently depending on which backend is selected.
> > ++
> > +'am' backend: When applying a patch, ignore changes in whitespace in
> > +context lines if necessary.
> > ++
> > +'interactive' backend: Treat lines with only whitespace changes as
> > +unchanged for the sake of a three-way merge.
> > +
> >   --whitespace=<option>::
> > -     These flag are passed to the 'git apply' program
> > +     This flag is passed to the 'git apply' program
> >       (see linkgit:git-apply[1]) that applies the patch.
> >   +
> >   See also INCOMPATIBLE OPTIONS below.
> > @@ -520,7 +528,6 @@ The following options:
> >    * --committer-date-is-author-date
> >    * --ignore-date
> >    * --whitespace
> > - * --ignore-whitespace
> >    * -C
> >
> >   are incompatible with the following options:
> > @@ -543,6 +550,8 @@ In addition, the following pairs of options are incompatible:
> >    * --preserve-merges and --interactive
> >    * --preserve-merges and --signoff
> >    * --preserve-merges and --rebase-merges
> > + * --preserve-merges and --ignore-whitespace
> > + * --rebase-merges and --ignore-whitespace
> >    * --rebase-merges and --strategy
> >    * --rebase-merges and --strategy-option
> >
> > diff --git a/builtin/rebase.c b/builtin/rebase.c
> > index 670096c065..f8a618d54c 100644
> > --- a/builtin/rebase.c
> > +++ b/builtin/rebase.c
> > @@ -79,6 +79,7 @@ struct rebase_options {
> >       int allow_rerere_autoupdate;
> >       int keep_empty;
> >       int autosquash;
> > +     int ignore_whitespace;
> >       char *gpg_sign_opt;
> >       int autostash;
> >       char *cmd;
> > @@ -99,6 +100,7 @@ struct rebase_options {
> >
> >   static struct replay_opts get_replay_opts(const struct rebase_options *opts)
> >   {
> > +     struct strbuf strategy_buf = STRBUF_INIT;
> >       struct replay_opts replay = REPLAY_OPTS_INIT;
> >
> >       replay.action = REPLAY_INTERACTIVE_REBASE;
> > @@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
> >       replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> >       replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
> >       replay.strategy = opts->strategy;
> > +
> >       if (opts->strategy_opts)
> > -             parse_strategy_opts(&replay, opts->strategy_opts);
> > +             strbuf_addstr(&strategy_buf, opts->strategy_opts);
> > +     if (opts->ignore_whitespace)
> > +             strbuf_addstr(&strategy_buf, " --ignore-space-change");
> > +     if (strategy_buf.len)
> > +             parse_strategy_opts(&replay, strategy_buf.buf);
> >
> > +     strbuf_release(&strategy_buf);
> >       return replay;
> >   }
> >
> > @@ -511,6 +519,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
> >       argc = parse_options(argc, argv, prefix, options,
> >                       builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
> >
> > +     opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> > +
> >       if (!is_null_oid(&squash_onto))
> >               opts.squash_onto = &squash_onto;
> >
> > @@ -964,6 +974,8 @@ static int run_am(struct rebase_options *opts)
> >       am.git_cmd = 1;
> >       argv_array_push(&am.args, "am");
> >
> > +     if (opts->ignore_whitespace)
> > +             argv_array_push(&am.args, "--ignore-whitespace");
> >       if (opts->action && !strcmp("continue", opts->action)) {
> >               argv_array_push(&am.args, "--resolved");
> >               argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> > @@ -1407,9 +1419,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
> >                       PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
> >               OPT_BOOL(0, "signoff", &options.signoff,
> >                        N_("add a Signed-off-by: line to each commit")),
> > -             OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> > -                               NULL, N_("passed to 'git am'"),
> > -                               PARSE_OPT_NOARG),
> >               OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> >                                 &options.git_am_opts, NULL,
> >                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
> > @@ -1417,6 +1426,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
> >                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
> >               OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> >                                 N_("passed to 'git apply'"), 0),
> > +             OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> > +                      N_("ignore changes in whitespace")),
> >               OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
> >                                 N_("action"), N_("passed to 'git apply'"), 0),
> >               OPT_BIT('f', "force-rebase", &options.flags,
> > @@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
> >       }
> >
> >       if (options.rebase_merges) {
> > +             if (options.ignore_whitespace)
> > +                     die(_("cannot combine '--rebase-merges' with "
> > +                           "'--ignore-whitespace'"));
>
> --rebase-merges now supports --strategy_option so we should fix this.
>
> >               if (strategy_options.nr)
> >                       die(_("cannot combine '--rebase-merges' with "
> >                             "'--strategy-option'"));
> > diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> > index a5868ea152..4342f79eea 100755
> > --- a/t/t3422-rebase-incompatible-options.sh
> > +++ b/t/t3422-rebase-incompatible-options.sh
> > @@ -61,7 +61,6 @@ test_rebase_am_only () {
> >   }
> >
> >   test_rebase_am_only --whitespace=fix
> > -test_rebase_am_only --ignore-whitespace
> >   test_rebase_am_only --committer-date-is-author-date
> >   test_rebase_am_only -C4
> >
> > diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> > new file mode 100755
> > index 0000000000..2e16e00a9d
> > --- /dev/null
> > +++ b/t/t3433-rebase-options-compatibility.sh
> > @@ -0,0 +1,65 @@
> > +#!/bin/sh
> > +#
> > +# Copyright (c) 2019 Rohit Ashiwal
> > +#
> > +
> > +test_description='tests to ensure compatibility between am and interactive backends'
> > +
> > +. ./test-lib.sh
> > +
> > +# This is a special case in which both am and interactive backends
> > +# provide the same output.
>
> I'm still concerned that we have to construct a special test case to get
> both backends to generate the same output. If this series is about
> supporting the behavior of the am backend in the sequencer then I'm
> worried that having the same option name have two different behaviors
> will create more problems than it solves. Do you have a feeling for how
> often the two backends give different results?

I think the wording choice of "special case" was unfortunate; it's
actually a common case.  Most the time the two backends will give the
same results, it's only in special cases that they don't.  See
https://public-inbox.org/git/CABPp-BE+D-GFJaucgCCsBA8E7nQAxc0vNE92HaCpOTQrUp=mPA@mail.gmail.com/

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

* Re: [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag
  2019-10-04  9:29     ` Phillip Wood
  2019-10-05 18:12       ` Elijah Newren
@ 2019-10-06 17:57       ` Rohit Ashiwal
  1 sibling, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-10-06 17:57 UTC (permalink / raw)
  To: phillip.wood123
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood, rohit.ashiwal265, t.gummerer

Hi Phillip

On Fri, 4 Oct 2019 10:29:36 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> [...]
> --rebase-merges now supports --strategy_option so we should fix this.

Yes, now that it supports --strategy_options I'll remove it from
here.

> [...]


Thanks
Rohit


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

* Re: [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date
  2019-10-04  9:37 [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2019-10-06 17:57 ` Rohit Ashiwal
  0 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-10-06 17:57 UTC (permalink / raw)
  To: phillip.wood123
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood, rohit.ashiwal265, t.gummerer

On Fri, 4 Oct 2019 10:37:43 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> > +	if (opts->committer_date_is_author_date) {
> > +		int len = strlen(author);
> > +		struct ident_split ident;
> > +		struct strbuf date = STRBUF_INIT;
> > +
> > +		if (split_ident_line(&ident, author, len) < 0)
> > +			return error(_("malformed ident line"));
>
> Here (and just below) we return if there is an error but later on we 
> `goto out` should we be doing that here to clean something up?

Yes, a mistake indeed. This should be replace with an error and a
goto statement.

> Best Wishes
>
> Phillip
>
> > +		if (!ident.date_begin)
> > +			return error(_("corrupted author without date information"));
> > +
> > +		strbuf_addf(&date, "@%.*s %.*s",
> > +			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
> > +			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> > +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> > +		strbuf_release(&date);
> > +
> > +		if (res)
> > +			goto out;
> > +	}
> > +

Thanks
Rohit


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

* Re: [PATCH v4 5/6] rebase -i: support --ignore-date
  2019-09-27 10:00 [PATCH v4 5/6] rebase -i: support --ignore-date Phillip Wood
@ 2019-10-06 17:57 ` Rohit Ashiwal
  2019-10-24 20:36   ` Phillip Wood
  0 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-10-06 17:57 UTC (permalink / raw)
  To: phillip.wood123
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	rohit.ashiwal265, t.gummerer

On Fri, 27 Sep 2019 11:00:58 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> [...]

Thanks for all the advice and improvements.

> [...]
> It's good to see the new test. Did you see Stolee's email [4] about the
> test coverage of the previous version of this series? You should check
> that this series tests all the untested non-error handling lines.
>
> [4]
> https://public-inbox.org/git/1ed86989-9ba2-0cd7-b6f7-654d1943b1d7@gmail.com/

Yes, I've seen it and have improved the test since.

Thanks
Rohit


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

* Re: [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date
  2019-09-07 11:50   ` [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-10-24 13:28     ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-10-24 13:28 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 07/09/2019 12:50, Rohit Ashiwal wrote:
> rebase am already has this flag to "lie" about the committer date
> by changing it to the author date. Let's add the same for
> interactive machinery.
> [...]> diff --git a/sequencer.c b/sequencer.c
> index adeff2561e..fd925f2d72 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>    * command-line.
>    */
>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -879,6 +880,17 @@ static char *get_author(const char *message)
>   	return NULL;
>   }
>   
> +/* Returns a "date" string that needs to be free()'d by the caller */
> +static char *read_author_date_or_null(void)
> +{
> +	char *date;
> +
> +	if (read_author_script(rebase_path_author_script(),
> +			       NULL, NULL, &date, 0))
> +		return NULL;
> +	return date;
> +}

This function and the hunk below are untested according to Stolee's 
latest test email [1]. We need a test that gets the sequencer to fork 
'git commit' rewording a commit should do that.

Best Wishes

Phillip

[1] 
https://public-inbox.org/git/ed8e65a2-72e8-210c-d4a4-eacdb5c7b0e8@gmail.com/

>   static const char staged_changes_advice[] =
>   N_("you have staged changes in your working tree\n"
>   "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -938,6 +950,24 @@ static int run_git_commit(struct repository *r,
>   
>   	cmd.git_cmd = 1;
>   
> +        if (opts->committer_date_is_author_date) {
> +	        int res = -1;
> +	        struct strbuf datebuf = STRBUF_INIT;
> +	        char *date = read_author_date_or_null();
> +
> +	        if (!date)
> +	                return -1;
> +
> +	        strbuf_addf(&datebuf, "@%s", date);
> +	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
> +
> +		strbuf_release(&datebuf);
> +	        free(date);
> +
> +	        if (res)
> +	                return -1;
> +        }
> +
>   	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
>   		const char *gpg_opt = gpg_sign_opt_quoted(opts);
>   
> @@ -1331,7 +1361,6 @@ static int try_to_commit(struct repository *r,
>   
>   	if (parse_head(r, &current_head))
>   		return -1;
> -
>   	if (flags & AMEND_MSG) {
>   		const char *exclude_gpgsig[] = { "gpgsig", NULL };
>   		const char *out_enc = get_commit_output_encoding();
> @@ -1359,6 +1388,26 @@ static int try_to_commit(struct repository *r,
>   		commit_list_insert(current_head, &parents);
>   	}
>   
> +	if (opts->committer_date_is_author_date) {
> +		int len = strlen(author);
> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		if (split_ident_line(&ident, author, len) < 0)
> +			return error(_("malformed ident line"));
> +		if (!ident.date_begin)
> +			return error(_("corrupted author without date information"));
> +
> +		strbuf_addf(&date, "@%.*s %.*s",
> +			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
> +			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		strbuf_release(&date);
> +
> +		if (res)
> +			goto out;
> +	}
> +
>   	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>   		res = error(_("git write-tree failed to write a tree"));
>   		goto out;
> @@ -2473,6 +2522,11 @@ static int read_populate_opts(struct replay_opts *opts)
>   			opts->signoff = 1;
>   		}
>   
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> @@ -2555,6 +2609,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
>   	if (opts->signoff)
>   		write_file(rebase_path_signoff(), "--signoff\n");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> @@ -3752,7 +3808,8 @@ static int pick_commits(struct repository *r,
>   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>   	if (opts->allow_ff)
>   		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>   	if (read_and_refresh_cache(r, opts))
>   		return -1;
>   
> diff --git a/sequencer.h b/sequencer.h
> index 6704acbb9c..e3881e9275 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -43,6 +43,7 @@ struct replay_opts {
>   	int verbose;
>   	int quiet;
>   	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>   
>   	int mainline;
>   
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 4342f79eea..7402f7e3da 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>   }
>   
>   test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>   test_rebase_am_only -C4
>   
>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 2e16e00a9d..6c1fbab4d8 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>   
>   . ./test-lib.sh
>   
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>   # This is a special case in which both am and interactive backends
>   # provide the same output. It was done intentionally because
>   # both the backends fall short of optimal behaviour.
> @@ -26,8 +29,13 @@ test_expect_success 'setup' '
>   	EOF
>   	git commit -am "update file" &&
>   	git tag side &&
> +	test_commit commit1 foo foo1 &&
> +	test_commit commit2 foo foo2 &&
> +	test_commit commit3 foo foo3 &&
>   
>   	git checkout --orphan master &&
> +	git rm --cached foo &&
> +	rm foo &&
>   	sed -e "s/^|//" >file <<-\EOF &&
>   	|line 1
>   	|        line 2
> @@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>   	test_cmp expect file
>   '
>   
> +test_expect_success '--committer-date-is-author-date works with am backend' '
> +	git commit --amend &&
> +	git rebase --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
> +	git commit --amend &&
> +	git rebase -i --committer-date-is-author-date HEAD^ &&
> +	git show HEAD --pretty="format:%ai" >authortime &&
> +	git show HEAD --pretty="format:%ci" >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> +	git checkout side &&
> +	git merge commit3 &&
> +	git rebase -r --root --committer-date-is-author-date &&
> +	git rev-list HEAD >rev_list &&
> +	while read HASH
> +	do
> +		git show $HASH --pretty="format:%ai" >authortime
> +		git show $HASH --pretty="format:%ci" >committertime
> +		test_cmp authortime committertime
> +	done <rev_list
> +'
> +
>   test_done
> 

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

* Re: [PATCH v4 5/6] rebase -i: support --ignore-date
  2019-10-06 17:57 ` Rohit Ashiwal
@ 2019-10-24 20:36   ` Phillip Wood
  0 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-10-24 20:36 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 06/10/2019 18:57, Rohit Ashiwal wrote:
> On Fri, 27 Sep 2019 11:00:58 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> [...]
> 
> Thanks for all the advice and improvements.
> 
>> [...]
>> It's good to see the new test. Did you see Stolee's email [4] about the
>> test coverage of the previous version of this series? You should check
>> that this series tests all the untested non-error handling lines.
>>
>> [4]
>> https://public-inbox.org/git/1ed86989-9ba2-0cd7-b6f7-654d1943b1d7@gmail.com/
> 
> Yes, I've seen it and have improved the test since.

Have you improved it since v4? Stolee's latest email [1] still shows 
push_date() as completely untested. We need a test that gets the 
sequencer to fork git-commit, the easiest way is probably to reword a 
commit. Also the new code for ignoring the date when we fork 'git merge' 
is untested. Having a test that does an octopus merge or sets a merge 
strategy (or merge strategy option) should fix that.

Best Wishes

Phillip

[1] 
https://public-inbox.org/git/ed8e65a2-72e8-210c-d4a4-eacdb5c7b0e8@gmail.com/


> Thanks
> Rohit
> 

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

* [PATCH v5 0/6] rebase -i: support more options
  2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
                   ` (8 preceding siblings ...)
  2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
@ 2019-11-01 13:59 ` " Rohit Ashiwal
  2019-11-01 13:59   ` [PATCH v5 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
                     ` (7 more replies)
  9 siblings, 8 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 13:59 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

Hey Everyone

I got really busy lately, posting the patch now.
 - Now handles the combination of --ignore-date and
   --committer-date-is-author-date properly.
 - Improved code coverage
 - addressed the compatibility of --rebase-merges with --strategy

Thanks
Rohit

Rohit Ashiwal (6):
  rebase -i: add --ignore-whitespace flag
  sequencer: allow callers of read_author_script() to ignore fields
  rebase -i: support --committer-date-is-author-date
  sequencer: rename amend_author to author_to_rename
  rebase -i: support --ignore-date
  rebase: add --reset-author-date

 Documentation/git-rebase.txt            |  25 ++++-
 builtin/rebase.c                        |  48 ++++++--
 sequencer.c                             | 141 ++++++++++++++++++++++--
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++
 6 files changed, 321 insertions(+), 28 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

Range-diff:
  2:  77af1d66db ! 491:  e155af5a39 rebase -i: add --ignore-whitespace flag
    @@ -16,7 +16,7 @@
      --- a/Documentation/git-rebase.txt
      +++ b/Documentation/git-rebase.txt
     @@
    - default is `--no-fork-point`, otherwise the default is `--fork-point`.
    + with `--keep-base` in order to drop those commits from your branch.
      
      --ignore-whitespace::
     +	Behaves differently depending on which backend is selected.
    @@ -46,9 +46,8 @@
       * --preserve-merges and --signoff
       * --preserve-merges and --rebase-merges
     + * --preserve-merges and --ignore-whitespace
    -+ * --rebase-merges and --ignore-whitespace
    -  * --rebase-merges and --strategy
    -  * --rebase-merges and --strategy-option
    +  * --keep-base and --onto
    +  * --keep-base and --root
      
     
      diff --git a/builtin/rebase.c b/builtin/rebase.c
    @@ -124,16 +123,6 @@
      		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
      				  N_("action"), N_("passed to 'git apply'"), 0),
      		OPT_BIT('f', "force-rebase", &options.flags,
    -@@
    - 	}
    - 
    - 	if (options.rebase_merges) {
    -+		if (options.ignore_whitespace)
    -+			die(_("cannot combine '--rebase-merges' with "
    -+			      "'--ignore-whitespace'"));
    - 		if (strategy_options.nr)
    - 			die(_("cannot combine '--rebase-merges' with "
    - 			      "'--strategy-option'"));
     
      diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
      --- a/t/t3422-rebase-incompatible-options.sh
  3:  1f7f1407b2 = 492:  7ec673ebcb sequencer: allow callers of read_author_script() to ignore fields
  4:  cc1614154e ! 493:  5af0d628de rebase -i: support --committer-date-is-author-date
    @@ -40,9 +40,9 @@
       * --preserve-merges and --rebase-merges
       * --preserve-merges and --ignore-whitespace
     + * --preserve-merges and --committer-date-is-author-date
    -  * --rebase-merges and --ignore-whitespace
    -  * --rebase-merges and --strategy
    -  * --rebase-merges and --strategy-option
    +  * --keep-base and --onto
    +  * --keep-base and --root
    + 
     
      diff --git a/builtin/rebase.c b/builtin/rebase.c
      --- a/builtin/rebase.c
    @@ -173,10 +173,14 @@
     +		struct ident_split ident;
     +		struct strbuf date = STRBUF_INIT;
     +
    -+		if (split_ident_line(&ident, author, len) < 0)
    -+			return error(_("malformed ident line"));
    -+		if (!ident.date_begin)
    -+			return error(_("corrupted author without date information"));
    ++		if (split_ident_line(&ident, author, len) < 0) {
    ++			res = error(_("malformed ident line"));
    ++			goto out;
    ++		}
    ++		if (!ident.date_begin) {
    ++			res = error(_("corrupted author without date information"));
    ++			goto out;
    ++		}
     +
     +		strbuf_addf(&date, "@%.*s %.*s",
     +			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
    @@ -296,7 +300,7 @@
     +
     +test_expect_success '--committer-date-is-author-date works with rebase -r' '
     +	git checkout side &&
    -+	git merge commit3 &&
    ++	git merge --no-ff commit3 &&
     +	git rebase -r --root --committer-date-is-author-date &&
     +	git rev-list HEAD >rev_list &&
     +	while read HASH
  5:  9e92c79bda = 494:  c7846945dd sequencer: rename amend_author to author_to_rename
  6:  fc68e55e78 ! 495:  02f797b84d rebase -i: support --ignore-date
    @@ -17,8 +17,8 @@
      --ignore-date::
     -	This flag is passed to 'git am' to change the author date
     -	of each rebased commit (see linkgit:git-am[1]).
    -+	Instead of using the given author date, reset it to the value
    -+	same as the current time. This implies --force-rebase.
    ++	Instead of using the given author date, reset it to the
    ++	current time. This implies --force-rebase.
      +
      See also INCOMPATIBLE OPTIONS below.
      
    @@ -35,9 +35,9 @@
       * --preserve-merges and --ignore-whitespace
       * --preserve-merges and --committer-date-is-author-date
     + * --preserve-merges and --ignore-date
    -  * --rebase-merges and --ignore-whitespace
    -  * --rebase-merges and --strategy
    -  * --rebase-merges and --strategy-option
    +  * --keep-base and --onto
    +  * --keep-base and --root
    + 
     
      diff --git a/builtin/rebase.c b/builtin/rebase.c
      --- a/builtin/rebase.c
    @@ -83,10 +83,6 @@
      	}
      
     -	if (options.committer_date_is_author_date)
    -+	if (options.ignore_date) {
    -+		options.committer_date_is_author_date = 0;
    -+		setenv("GIT_COMMITTER_DATE", "", 1);
    -+	}
     +	if (options.committer_date_is_author_date ||
     +	    options.ignore_date)
      		options.flags |= REBASE_FORCE;
    @@ -128,35 +124,56 @@
     +	}
     +	len = ident.mail_end - ident.name_begin + 1;
     +
    -+	strbuf_addf(&new_author, "%.*s ", len, author);
    ++	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
     +	datestamp(&new_author);
     +	return strbuf_detach(&new_author, NULL);
     +}
     +
    -+static void push_dates(struct child_process *child)
    ++static void push_dates(struct child_process *child, int change_committer_date)
     +{
     +	time_t now = time(NULL);
     +	struct strbuf date = STRBUF_INIT;
     +
     +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
     +	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
    -+	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
    ++	if (change_committer_date)
    ++		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
     +	strbuf_release(&date);
     +}
     +
      static const char staged_changes_advice[] =
      N_("you have staged changes in your working tree\n"
      "If these changes are meant to be squashed into the previous commit, run:\n"
    +@@
    + 	                return -1;
    + 
    + 	        strbuf_addf(&datebuf, "@%s", date);
    +-	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
    ++		res = setenv("GIT_COMMITTER_DATE",
    ++			     opts->ignore_date ? "" : datebuf.buf, 1);
    + 
    + 		strbuf_release(&datebuf);
    + 	        free(date);
     @@
      		argv_array_push(&cmd.args, "--amend");
      	if (opts->gpg_sign)
      		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
     +	if (opts->ignore_date)
    -+		push_dates(&cmd);
    ++		push_dates(&cmd, opts->committer_date_is_author_date);
      	if (defmsg)
      		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
      	else if (!(flags & EDIT_MSG))
     @@
    + 		strbuf_addf(&date, "@%.*s %.*s",
    + 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
    + 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
    +-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
    ++		res = setenv("GIT_COMMITTER_DATE",
    ++			     opts->ignore_date ? "" : date.buf, 1);
    + 		strbuf_release(&date);
    + 
    + 		if (res)
    +@@
      
      	reset_ident_date();
      
    @@ -198,7 +215,7 @@
      		if (opts->gpg_sign)
      			argv_array_push(&cmd.args, opts->gpg_sign);
     +		if (opts->ignore_date)
    -+			push_dates(&cmd);
    ++			push_dates(&cmd, opts->committer_date_is_author_date);
      
      		/* Add the tips to be merged */
      		for (j = to_merge; j; j = j->next)
    @@ -239,31 +256,25 @@
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --ignore-date HEAD^ &&
     +	git show HEAD --pretty="format:%ai" >authortime &&
    -+	git show HEAD --pretty="format:%ci" >committertime &&
    -+	grep "+0000" authortime &&
    -+	grep "+0000" committertime
    ++	grep "+0000" authortime
     +'
     +
     +test_expect_success '--ignore-date works with interactive backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --ignore-date -i HEAD^ &&
     +	git show HEAD --pretty="format:%ai" >authortime &&
    -+	git show HEAD --pretty="format:%ci" >committertime &&
    -+	grep "+0000" authortime &&
    -+	grep "+0000" committertime
    ++	grep "+0000" authortime
     +'
     +
     +test_expect_success '--ignore-date works with rebase -r' '
     +	git checkout side &&
    -+	git merge commit3 &&
    ++	git merge --no-ff commit3 &&
     +	git rebase -r --root --ignore-date &&
     +	git rev-list HEAD >rev_list &&
     +	while read HASH
     +	do
     +		git show $HASH --pretty="format:%ai" >authortime
    -+		git show $HASH --pretty="format:%ci" >committertime
     +		grep "+0000" authortime
    -+		grep "+0000" committertime
     +	done <rev_list
     +'
     +
  7:  396d5f16eb ! 496:  7a9fe1e612 rebase: add --reset-author-date
    @@ -17,8 +17,8 @@
      
      --ignore-date::
     +--reset-author-date::
    - 	Instead of using the given author date, reset it to the value
    - 	same as the current time. This implies --force-rebase.
    + 	Instead of using the given author date, reset it to the
    + 	current time. This implies --force-rebase.
      +
     
      diff --git a/builtin/rebase.c b/builtin/rebase.c
-- 
2.21.0


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

* [PATCH v5 1/6] rebase -i: add --ignore-whitespace flag
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
@ 2019-11-01 13:59   ` Rohit Ashiwal
  2019-11-01 13:59   ` [PATCH v5 2/6] sequencer: allow callers of read_author_script() to ignore fields Rohit Ashiwal
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 13:59 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

There are two backends available for rebasing, viz, the am and the
interactive. Naturally, there shall be some features that are
implemented in one but not in the other. One such flag is
--ignore-whitespace which indicates merge mechanism to treat lines
with only whitespace changes as unchanged. Wire the interactive
rebase to also understand the --ignore-whitespace flag by
translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 12 ++++-
 builtin/rebase.c                        | 19 ++++++--
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++
 4 files changed, 90 insertions(+), 7 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 639a4179d1..b4de299e6f 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -393,8 +393,16 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Behaves differently depending on which backend is selected.
++
+'am' backend: When applying a patch, ignore changes in whitespace in
+context lines if necessary.
++
+'interactive' backend: Treat lines with only whitespace changes as
+unchanged for the sake of a three-way merge.
+
 --whitespace=<option>::
-	These flag are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 +
 See also INCOMPATIBLE OPTIONS below.
@@ -542,7 +550,6 @@ The following options:
  * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
- * --ignore-whitespace
  * -C
 
 are incompatible with the following options:
@@ -565,6 +572,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --interactive
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 4a20582e72..2f2ba3e8e7 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -79,6 +79,7 @@ struct rebase_options {
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -99,6 +100,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
 
+	strbuf_release(&strategy_buf);
 	return replay;
 }
 
@@ -512,6 +520,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -965,6 +975,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1431,9 +1443,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1441,6 +1450,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
new file mode 100755
index 0000000000..2e16e00a9d
--- /dev/null
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with am backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase main side &&
+	git rebase --abort &&
+	git rebase --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with interactive backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_done
-- 
2.21.0


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

* [PATCH v5 2/6] sequencer: allow callers of read_author_script() to ignore fields
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
  2019-11-01 13:59   ` [PATCH v5 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
@ 2019-11-01 13:59   ` Rohit Ashiwal
  2019-11-01 14:00   ` [PATCH v5 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 13:59 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The current callers of the read_author_script() function read name,
email and date from the author script.  Allow callers to signal that
they are not interested in some among these three fields by passing
NULL.

Note that fields that are ignored still must exist and be formatted
correctly in the author script.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 9d5964fd81..6954b9eea9 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -823,9 +823,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-	*name = kv.items[name_i].util;
-	*email = kv.items[email_i].util;
-	*date = kv.items[date_i].util;
+
+	if (name)
+		*name = kv.items[name_i].util;
+	else
+		free(kv.items[name_i].util);
+	if (email)
+		*email = kv.items[email_i].util;
+	else
+		free(kv.items[email_i].util);
+	if (date)
+		*date = kv.items[date_i].util;
+	else
+		free(kv.items[date_i].util);
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
-- 
2.21.0


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

* [PATCH v5 3/6] rebase -i: support --committer-date-is-author-date
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
  2019-11-01 13:59   ` [PATCH v5 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
  2019-11-01 13:59   ` [PATCH v5 2/6] sequencer: allow callers of read_author_script() to ignore fields Rohit Ashiwal
@ 2019-11-01 14:00   ` Rohit Ashiwal
  2019-11-01 14:00   ` [PATCH v5 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 14:00 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the committer date
by changing it to the author date. Let's add the same for
interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            | 10 ++--
 builtin/rebase.c                        | 17 +++++--
 sequencer.c                             | 65 ++++++++++++++++++++++++-
 sequencer.h                             |  1 +
 t/t3422-rebase-incompatible-options.sh  |  1 -
 t/t3433-rebase-options-compatibility.sh | 37 ++++++++++++++
 6 files changed, 120 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b4de299e6f..e948a24433 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -408,9 +408,13 @@ unchanged for the sake of a three-way merge.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of recording the time the rebased commits are
+	created as the committer date, reuse the author date
+	as the committer date. This implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -547,7 +551,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -573,6 +576,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 2f2ba3e8e7..9227801ef6 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -82,6 +82,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -114,6 +115,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.allow_empty_message = opts->allow_empty_message;
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -977,6 +980,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1443,9 +1448,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1723,10 +1728,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
+
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
diff --git a/sequencer.c b/sequencer.c
index 6954b9eea9..e2c324b3a6 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -147,6 +147,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -878,6 +879,17 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+/* Returns a "date" string that needs to be free()'d by the caller */
+static char *read_author_date_or_null(void)
+{
+	char *date;
+
+	if (read_author_script(rebase_path_author_script(),
+			       NULL, NULL, &date, 0))
+		return NULL;
+	return date;
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -937,6 +949,24 @@ static int run_git_commit(struct repository *r,
 
 	cmd.git_cmd = 1;
 
+        if (opts->committer_date_is_author_date) {
+	        int res = -1;
+	        struct strbuf datebuf = STRBUF_INIT;
+	        char *date = read_author_date_or_null();
+
+	        if (!date)
+	                return -1;
+
+	        strbuf_addf(&datebuf, "@%s", date);
+	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
+
+		strbuf_release(&datebuf);
+	        free(date);
+
+	        if (res)
+	                return -1;
+        }
+
 	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
 		const char *gpg_opt = gpg_sign_opt_quoted(opts);
 
@@ -1330,7 +1360,6 @@ static int try_to_commit(struct repository *r,
 
 	if (parse_head(r, &current_head))
 		return -1;
-
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1358,6 +1387,30 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, len) < 0) {
+			res = error(_("malformed ident line"));
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2480,6 +2533,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2562,6 +2620,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
 	if (opts->signoff)
 		write_file(rebase_path_signoff(), "--signoff\n");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3769,7 +3829,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 574260f621..ffddf011cc 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -43,6 +43,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 2e16e00a9d..a98cfe18b7 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . ./test-lib.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -26,8 +29,13 @@ test_expect_success 'setup' '
 	EOF
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	git rm --cached foo &&
+	rm foo &&
 	sed -e "s/^|//" >file <<-\EOF &&
 	|line 1
 	|        line 2
@@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with am backend' '
+	git commit --amend &&
+	git rebase --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with interactive backend' '
+	git commit --amend &&
+	git rebase -i --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	git rev-list HEAD >rev_list &&
+	while read HASH
+	do
+		git show $HASH --pretty="format:%ai" >authortime
+		git show $HASH --pretty="format:%ci" >committertime
+		test_cmp authortime committertime
+	done <rev_list
+'
+
 test_done
-- 
2.21.0


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

* [PATCH v5 4/6] sequencer: rename amend_author to author_to_rename
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
                     ` (2 preceding siblings ...)
  2019-11-01 14:00   ` [PATCH v5 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
@ 2019-11-01 14:00   ` Rohit Ashiwal
  2019-11-01 14:00   ` [PATCH v5 5/6] rebase -i: support --ignore-date Rohit Ashiwal
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 14:00 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() while amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index e2c324b3a6..34e45246f7 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1353,7 +1353,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1374,7 +1374,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1473,7 +1473,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.21.0


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

* [PATCH v5 5/6] rebase -i: support --ignore-date
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
                     ` (3 preceding siblings ...)
  2019-11-01 14:00   ` [PATCH v5 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
@ 2019-11-01 14:00   ` Rohit Ashiwal
  2019-11-02  7:32     ` Junio C Hamano
  2019-11-01 14:00   ` [PATCH v5 6/6] rebase: add --reset-author-date Rohit Ashiwal
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 14:00 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

rebase am already has this flag to "lie" about the author date
by changing it to the committer (current) date. Let's add the same
for interactive machinery.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt            |  6 +--
 builtin/rebase.c                        | 14 +++---
 sequencer.c                             | 60 +++++++++++++++++++++++--
 sequencer.h                             |  1 +
 t/t3433-rebase-options-compatibility.sh | 29 ++++++++++++
 5 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e948a24433..3580447f2f 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -413,8 +413,8 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the given author date, reset it to the
+	current time. This implies --force-rebase.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -551,7 +551,6 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --ignore-date
  * --whitespace
  * -C
 
@@ -577,6 +576,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 9227801ef6..7edae668f8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -83,6 +83,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -982,6 +984,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1451,8 +1455,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1728,13 +1732,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date ||
+	    options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index 34e45246f7..a4c6a47bea 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -890,6 +891,36 @@ static char *read_author_date_or_null(void)
 	return date;
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line"));
+		return NULL;
+	}
+	len = ident.mail_end - ident.name_begin + 1;
+
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
+static void push_dates(struct child_process *child, int change_committer_date)
+{
+	time_t now = time(NULL);
+	struct strbuf date = STRBUF_INIT;
+
+	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
+	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
+	if (change_committer_date)
+		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
+	strbuf_release(&date);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -958,7 +989,8 @@ static int run_git_commit(struct repository *r,
 	                return -1;
 
 	        strbuf_addf(&datebuf, "@%s", date);
-	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : datebuf.buf, 1);
 
 		strbuf_release(&datebuf);
 	        free(date);
@@ -982,6 +1014,8 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+	if (opts->ignore_date)
+		push_dates(&cmd, opts->committer_date_is_author_date);
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -1404,7 +1438,8 @@ static int try_to_commit(struct repository *r,
 		strbuf_addf(&date, "@%.*s %.*s",
 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1454,6 +1489,15 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2538,6 +2582,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_signoff(), "--signoff\n");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3557,6 +3608,8 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
+		if (opts->ignore_date)
+			push_dates(&cmd, opts->committer_date_is_author_date);
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3830,7 +3883,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index ffddf011cc..3e6275272a 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -44,6 +44,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index a98cfe18b7..5166f158dd 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -99,4 +99,33 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '
 	done <rev_list
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with am backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with interactive backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -i HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	git rev-list HEAD >rev_list &&
+	while read HASH
+	do
+		git show $HASH --pretty="format:%ai" >authortime
+		grep "+0000" authortime
+	done <rev_list
+'
+
 test_done
-- 
2.21.0


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

* [PATCH v5 6/6] rebase: add --reset-author-date
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
                     ` (4 preceding siblings ...)
  2019-11-01 14:00   ` [PATCH v5 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-11-01 14:00   ` Rohit Ashiwal
  2019-11-02  7:34     ` Junio C Hamano
  2019-11-21  6:14   ` [PATCH v5 0/6] rebase -i: support more options Junio C Hamano
  2019-11-28 11:14   ` Phillip Wood
  7 siblings, 1 reply; 92+ messages in thread
From: Rohit Ashiwal @ 2019-11-01 14:00 UTC (permalink / raw)
  To: rohit.ashiwal265
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren,
	phillip.wood123, t.gummerer

The previous commit introduced --ignore-date flag to interactive
rebase, but the name is actually very vague in context of rebase -i
since there are two dates we can work with. Add an alias to convey
the precise purpose.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt | 1 +
 builtin/rebase.c             | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 3580447f2f..cb4ab43998 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -413,6 +413,7 @@ See also INCOMPATIBLE OPTIONS below.
 	as the committer date. This implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the given author date, reset it to the
 	current time. This implies --force-rebase.
 +
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 7edae668f8..edefdd016b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1455,6 +1455,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_BOOL(0, "ignore-date", &options.ignore_date,
 			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-- 
2.21.0


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

* Re: [PATCH v5 5/6] rebase -i: support --ignore-date
  2019-11-01 14:00   ` [PATCH v5 5/6] rebase -i: support --ignore-date Rohit Ashiwal
@ 2019-11-02  7:32     ` Junio C Hamano
  2019-11-02  7:48       ` Junio C Hamano
  0 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-11-02  7:32 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

>  --ignore-date::
> +	Instead of using the given author date, reset it to the
> +	current time. This implies --force-rebase.

The first sentence is unclear and puzzles me with "for what?".  IOW,
you are saying that by default the command uses the given (I presume
that you meant what is recorded in the original commits being
rebased---but we should find a way to explain it more clearly)
author date, but with this option what is used is reset to the
current time.  It is left unspecified what the command is using that
time for.

Perhaps (I am writing this paragraph after writing the rest of the
message, i.e. after reading the patch through):

	By default, the author date recorded in the commit being
	rebased as the author date is used as the author date of the
	rebased commits.  The option tells Git to use the current
	timestamp as the author date of the rebased commits instead.
	This implies `--force-rebase`.

The committer-date-is-author-date is indirectly also affected by
this option, because it (re)uses the "author date", but by making it
clear where the "author date" comes from in the description of this
option, it would make the interaction between these two options
obvious, hopefully ;-)

>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")

It probably is a good idea to use dash not underscore for
cdate-is-adata and ignore-date, the two files you are adding.

It would be good to eventually fix the existing gpg-sign-opt to
follow suit, but not as a part of this series.

> +static void push_dates(struct child_process *child, int change_committer_date)
> +{
> +	time_t now = time(NULL);
> +	struct strbuf date = STRBUF_INIT;

I am tempted to suggest adding a /* NEEDSWORK */ comment to remind
us that we'd want to eventually use date.c::get_time() here, but not
as part of this series.  But grepping for "\<time(" is easy enough
so I can live without it.

> +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
> +	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);

OK, so we get author-date of "now" (which we do not do normally)
when the caller decides to call us (which is, under
"--ignore-date").

> +	if (change_committer_date)
> +		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);

And when we are using --committer-date-is-author-date, we muck with
the committer-date as well.

Makes sense.

> @@ -958,7 +989,8 @@ static int run_git_commit(struct repository *r,
>  	                return -1;
>  
>  	        strbuf_addf(&datebuf, "@%s", date);
> -	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
> +		res = setenv("GIT_COMMITTER_DATE",
> +			     opts->ignore_date ? "" : datebuf.buf, 1);

This is the codepath that handles committer-date-is-author-date
option.  We read the author date into "date", and used to
unconditionally use it as the committer date.  With --ignore-date,
we behave differently.

It may happen that an empty string in GIT_COMMITTER_DATE is treated
the same way as missing GIT_COMMITTER_DATE, i.e. unspecified.

	if (opts->ignore_date)
		res = unsetenv("GIT_COMMITTER_DATE");
	else
        	res = setenv(...);

would be conceptually clearer.

But then we would notice that there is no reason to even read the
author-date into date if ignore-date is set, no?  So the whole thing
now becomes

	-	if (opts->committer_date_is_author_date) {
	+	if (!opts->ignore_date && opts->committer_date_is_author_date) {

which feels even cleaner.  Am I missing some subtleties (e.g. are we
worried about the case where the user has GIT_COMMITTER_DATE set and
exported to the environment of the shell that starts "git rebase", or
something like that?)???

> @@ -982,6 +1014,8 @@ static int run_git_commit(struct repository *r,
>  		argv_array_push(&cmd.args, "--amend");
>  	if (opts->gpg_sign)
>  		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> +	if (opts->ignore_date)
> +		push_dates(&cmd, opts->committer_date_is_author_date);
>  	if (defmsg)
>  		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>  	else if (!(flags & EDIT_MSG))
> @@ -1404,7 +1438,8 @@ static int try_to_commit(struct repository *r,
>  		strbuf_addf(&date, "@%.*s %.*s",
>  			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
>  			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> -		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		res = setenv("GIT_COMMITTER_DATE",
> +			     opts->ignore_date ? "" : date.buf, 1);

The same comment as the early half of the above, on relying on the
empty date string instead of an explicit unsetenv().

> @@ -1454,6 +1489,15 @@ static int try_to_commit(struct repository *r,
>  
>  	reset_ident_date();
>  
> +	if (opts->ignore_date) {
> +		author = ignore_author_date(author);

The helper function called here begins with this comment:

"Construct a free()able author string with current time as the author date"

but without reading (and memorizing) it, ignore_author_date()
function sounds like a boolean that tells us "are we told to
ignore the author date?"

It sorely wants a better name to tell the reader that it is the
author ident with current timestamp.

> +		if (!author) {
> +			res = -1;
> +			goto out;
> +		}
> +		free(author_to_free);
> +		author_to_free = (char *)author;
> +	}

> @@ -2538,6 +2582,11 @@ static int read_populate_opts(struct replay_opts *opts)
>  			opts->committer_date_is_author_date = 1;
>  		}
>  
> +		if (file_exists(rebase_path_ignore_date())) {
> +			opts->allow_ff = 0;
> +			opts->ignore_date = 1;
> +		}

OK.

> @@ -3557,6 +3608,8 @@ static int do_merge(struct repository *r,
>  		argv_array_push(&cmd.args, git_path_merge_msg(r));
>  		if (opts->gpg_sign)
>  			argv_array_push(&cmd.args, opts->gpg_sign);
> +		if (opts->ignore_date)
> +			push_dates(&cmd, opts->committer_date_is_author_date);

OK, we've seen the callee above already and we know what this does.

> @@ -3830,7 +3883,8 @@ static int pick_commits(struct repository *r,
>  	if (opts->allow_ff)
>  		assert(!(opts->signoff || opts->no_commit ||
>  				opts->record_origin || opts->edit ||
> -				opts->committer_date_is_author_date));
> +				opts->committer_date_is_author_date ||
> +				opts->ignore_date));

We may want to switch this assert(...) and others to "if (!(...))
BUG()" someday, but not as part of this patch.


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

* Re: [PATCH v5 6/6] rebase: add --reset-author-date
  2019-11-01 14:00   ` [PATCH v5 6/6] rebase: add --reset-author-date Rohit Ashiwal
@ 2019-11-02  7:34     ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-11-02  7:34 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:

>  --ignore-date::
> +--reset-author-date::
>  	Instead of using the given author date, reset it to the
>  	current time. This implies --force-rebase.
>  +
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 7edae668f8..edefdd016b 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -1455,6 +1455,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		OPT_BOOL(0, "committer-date-is-author-date",
>  			 &options.committer_date_is_author_date,
>  			 N_("make committer date match author date")),
> +		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
> +			 "ignore author date and use current date"),
>  		OPT_BOOL(0, "ignore-date", &options.ignore_date,
>  			 "ignore author date and use current date"),

One of them should say it is a mere synonym to the other (or hide
from the "git rebase -h" listing altogether).  Otherwise readers
would be puzzled what the difference between the two are.

Thanks.


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

* Re: [PATCH v5 5/6] rebase -i: support --ignore-date
  2019-11-02  7:32     ` Junio C Hamano
@ 2019-11-02  7:48       ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-11-02  7:48 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, martin.agren, newren, phillip.wood123,
	t.gummerer

Junio C Hamano <gitster@pobox.com> writes:

> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:
>
>>  --ignore-date::
>> +	Instead of using the given author date, reset it to the
>> +	current time. This implies --force-rebase.
>
> The first sentence is unclear and puzzles me with "for what?".  IOW,
> you are saying that by default the command uses the given (I presume
> that you meant what is recorded in the original commits being
> rebased---but we should find a way to explain it more clearly)
> author date, but with this option what is used is reset to the
> current time.  It is left unspecified what the command is using that
> time for.
>
> Perhaps (I am writing this paragraph after writing the rest of the
> message, i.e. after reading the patch through):

Oops, too much re-editing without final proofreading.  Sorry.

> 	By default, the author date recorded in the commit being
> 	rebased as the author date is used as the author date of the
> 	rebased commits.  The option tells Git to use the current
> 	timestamp as the author date of the rebased commits instead.
> 	This implies `--force-rebase`.

	By default, the author date of the original commit is used
	as the author date for the resulting commit.  This option
	tells Git to use the current timestamp instead and implies
	`--force-rebase`.

would be much less redundant without losing clarity.

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

* Re: [PATCH v5 0/6] rebase -i: support more options
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
                     ` (5 preceding siblings ...)
  2019-11-01 14:00   ` [PATCH v5 6/6] rebase: add --reset-author-date Rohit Ashiwal
@ 2019-11-21  6:14   ` Junio C Hamano
  2019-11-21  8:17     ` Alban Gruin
  2019-11-28 11:14   ` Phillip Wood
  7 siblings, 1 reply; 92+ messages in thread
From: Junio C Hamano @ 2019-11-21  6:14 UTC (permalink / raw)
  To: git
  Cc: Johannes.Schindelin, Rohit Ashiwal, martin.agren, newren,
	phillip.wood123, t.gummerer

As I hate to leave a mostly done topic hanging around forever, I am
tempted to queue these fixups on top (instead of squash them in) to
tie the loose ends after a few weeks' inactivity.

Thanks.

-- >8 --
Subject: rebase -i: finishes touches to --reset-author-date

Clarify the way the `--reset-author-date` option is described,
and mark its usage string translatable.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-rebase.txt | 6 ++++--
 builtin/rebase.c             | 6 +++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index c8d54d221d..03809da835 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -392,8 +392,10 @@ See also INCOMPATIBLE OPTIONS below.
 
 --ignore-date::
 --reset-author-date::
-	Instead of using the given author date, reset it to the
-	current time. This implies --force-rebase.
+	By default, the author date of the original commit is used
+	as the author date for the resulting commit.  This option
+	tells Git to use the current timestamp instead and implies
+	`--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 44768082b8..d5c09f159c 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1437,9 +1437,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
 		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
-			 "ignore author date and use current date"),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
-			 "ignore author date and use current date"),
+			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-autohr-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,



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

* Re: [PATCH v5 0/6] rebase -i: support more options
  2019-11-21  6:14   ` [PATCH v5 0/6] rebase -i: support more options Junio C Hamano
@ 2019-11-21  8:17     ` Alban Gruin
  2019-11-22  6:32       ` Junio C Hamano
  0 siblings, 1 reply; 92+ messages in thread
From: Alban Gruin @ 2019-11-21  8:17 UTC (permalink / raw)
  To: Junio C Hamano, git
  Cc: Johannes.Schindelin, Rohit Ashiwal, martin.agren, newren,
	phillip.wood123, t.gummerer

Hi Junio,

Le 21/11/2019 à 07:14, Junio C Hamano a écrit :
> As I hate to leave a mostly done topic hanging around forever, I am
> tempted to queue these fixups on top (instead of squash them in) to
> tie the loose ends after a few weeks' inactivity.
> 
> Thanks.
> 
> -- >8 --
> Subject: rebase -i: finishes touches to --reset-author-date
> 
> Clarify the way the `--reset-author-date` option is described,
> and mark its usage string translatable.
> 
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  Documentation/git-rebase.txt | 6 ++++--
>  builtin/rebase.c             | 6 +++---
>  2 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index c8d54d221d..03809da835 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -392,8 +392,10 @@ See also INCOMPATIBLE OPTIONS below.
>  
>  --ignore-date::
>  --reset-author-date::
> -	Instead of using the given author date, reset it to the
> -	current time. This implies --force-rebase.
> +	By default, the author date of the original commit is used
> +	as the author date for the resulting commit.  This option
> +	tells Git to use the current timestamp instead and implies
> +	`--force-rebase`.
>  +
>  See also INCOMPATIBLE OPTIONS below.
>  
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 44768082b8..d5c09f159c 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -1437,9 +1437,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  			 &options.committer_date_is_author_date,
>  			 N_("make committer date match author date")),
>  		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
> -			 "ignore author date and use current date"),
> -		OPT_BOOL(0, "ignore-date", &options.ignore_date,
> -			 "ignore author date and use current date"),
> +			 N_("ignore author date and use current date")),
> +		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
> +				N_("synonym of --reset-autohr-date")),

There is a typo here.

>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>  				  N_("passed to 'git apply'"), 0),
>  		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> 
> 

Cheers,
Alban


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

* Re: [PATCH v5 0/6] rebase -i: support more options
  2019-11-21  8:17     ` Alban Gruin
@ 2019-11-22  6:32       ` Junio C Hamano
  0 siblings, 0 replies; 92+ messages in thread
From: Junio C Hamano @ 2019-11-22  6:32 UTC (permalink / raw)
  To: Alban Gruin
  Cc: git, Johannes.Schindelin, Rohit Ashiwal, martin.agren, newren,
	phillip.wood123, t.gummerer

Alban Gruin <alban.gruin@gmail.com> writes:

>> +		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
>> +				N_("synonym of --reset-autohr-date")),
>
> There is a typo here.

Oops. I think you meant s/autohr/author/, so I've fixed it up
locally---if you spotted something else, please let me know.

Thanks.

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

* Re: [PATCH v5 0/6] rebase -i: support more options
  2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
                     ` (6 preceding siblings ...)
  2019-11-21  6:14   ` [PATCH v5 0/6] rebase -i: support more options Junio C Hamano
@ 2019-11-28 11:14   ` Phillip Wood
  7 siblings, 0 replies; 92+ messages in thread
From: Phillip Wood @ 2019-11-28 11:14 UTC (permalink / raw)
  To: Rohit Ashiwal
  Cc: Johannes.Schindelin, git, gitster, martin.agren, newren, t.gummerer

Hi Rohit

On 01/11/2019 13:59, Rohit Ashiwal wrote:
> Hey Everyone
> 
> I got really busy lately, posting the patch now.
>   - Now handles the combination of --ignore-date and
>     --committer-date-is-author-date properly.
>   - Improved code coverage

Looking at the range-diff there's only a one line change to the tests. I 
sound like a broken record but Stolee's latest test report[1] shows 
there are still uncovered lines.

 > Rohit Ashiwal	c068bcc5 sequencer: allow callers of 
read_author_script() to ignore fields
 > sequencer.c
 > c068bcc5 840) free(kv.items[date_i].util);
 >
 > Rohit Ashiwal	cbd8db17 rebase -i: support --committer-date-is-author-date
 > sequencer.c
 > cbd8db17 890) return NULL;
 > cbd8db17 989) return -1;
 > cbd8db17 1428) goto out;
 > cbd8db17 1432) goto out;
 > cbd8db17 2603) opts->allow_ff = 0;
 > cbd8db17 2604) opts->committer_date_is_author_date = 1;

These last two should be tested I think

 > Rohit Ashiwal	08187b4c rebase -i: support --ignore-date
 > sequencer.c
 > 08187b4c 903) return NULL;
 > 08187b4c 920) argv_array_pushf(&child->env_array, 
"GIT_COMMITTER_DATE=%s", date.buf);

This should be tested

 > 08187b4c 1508) res = -1;
 > 08187b4c 1509) goto out;
 > 08187b4c 2608) opts->allow_ff = 0;
 > 08187b4c 2609) opts->ignore_date = 1;
 > 08187b4c 3639) push_dates(&cmd, opts->committer_date_is_author_date);

As should these three

Best Wishes

Phillip

[1] 
https://lore.kernel.org/git/1cb7ddbf-020e-d63a-85b6-5a9267c0a5a3@gmail.com/


>   - addressed the compatibility of --rebase-merges with --strategy
> 
> Thanks
> Rohit
> 
> Rohit Ashiwal (6):
>    rebase -i: add --ignore-whitespace flag
>    sequencer: allow callers of read_author_script() to ignore fields
>    rebase -i: support --committer-date-is-author-date
>    sequencer: rename amend_author to author_to_rename
>    rebase -i: support --ignore-date
>    rebase: add --reset-author-date
> 
>   Documentation/git-rebase.txt            |  25 ++++-
>   builtin/rebase.c                        |  48 ++++++--
>   sequencer.c                             | 141 ++++++++++++++++++++++--
>   sequencer.h                             |   2 +
>   t/t3422-rebase-incompatible-options.sh  |   2 -
>   t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++
>   6 files changed, 321 insertions(+), 28 deletions(-)
>   create mode 100755 t/t3433-rebase-options-compatibility.sh
> 
> Range-diff:
>    2:  77af1d66db ! 491:  e155af5a39 rebase -i: add --ignore-whitespace flag
>      @@ -16,7 +16,7 @@
>        --- a/Documentation/git-rebase.txt
>        +++ b/Documentation/git-rebase.txt
>       @@
>      - default is `--no-fork-point`, otherwise the default is `--fork-point`.
>      + with `--keep-base` in order to drop those commits from your branch.
>        
>        --ignore-whitespace::
>       +	Behaves differently depending on which backend is selected.
>      @@ -46,9 +46,8 @@
>         * --preserve-merges and --signoff
>         * --preserve-merges and --rebase-merges
>       + * --preserve-merges and --ignore-whitespace
>      -+ * --rebase-merges and --ignore-whitespace
>      -  * --rebase-merges and --strategy
>      -  * --rebase-merges and --strategy-option
>      +  * --keep-base and --onto
>      +  * --keep-base and --root
>        
>       
>        diff --git a/builtin/rebase.c b/builtin/rebase.c
>      @@ -124,16 +123,6 @@
>        		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>        				  N_("action"), N_("passed to 'git apply'"), 0),
>        		OPT_BIT('f', "force-rebase", &options.flags,
>      -@@
>      - 	}
>      -
>      - 	if (options.rebase_merges) {
>      -+		if (options.ignore_whitespace)
>      -+			die(_("cannot combine '--rebase-merges' with "
>      -+			      "'--ignore-whitespace'"));
>      - 		if (strategy_options.nr)
>      - 			die(_("cannot combine '--rebase-merges' with "
>      - 			      "'--strategy-option'"));
>       
>        diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>        --- a/t/t3422-rebase-incompatible-options.sh
>    3:  1f7f1407b2 = 492:  7ec673ebcb sequencer: allow callers of read_author_script() to ignore fields
>    4:  cc1614154e ! 493:  5af0d628de rebase -i: support --committer-date-is-author-date
>      @@ -40,9 +40,9 @@
>         * --preserve-merges and --rebase-merges
>         * --preserve-merges and --ignore-whitespace
>       + * --preserve-merges and --committer-date-is-author-date
>      -  * --rebase-merges and --ignore-whitespace
>      -  * --rebase-merges and --strategy
>      -  * --rebase-merges and --strategy-option
>      +  * --keep-base and --onto
>      +  * --keep-base and --root
>      +
>       
>        diff --git a/builtin/rebase.c b/builtin/rebase.c
>        --- a/builtin/rebase.c
>      @@ -173,10 +173,14 @@
>       +		struct ident_split ident;
>       +		struct strbuf date = STRBUF_INIT;
>       +
>      -+		if (split_ident_line(&ident, author, len) < 0)
>      -+			return error(_("malformed ident line"));
>      -+		if (!ident.date_begin)
>      -+			return error(_("corrupted author without date information"));
>      ++		if (split_ident_line(&ident, author, len) < 0) {
>      ++			res = error(_("malformed ident line"));
>      ++			goto out;
>      ++		}
>      ++		if (!ident.date_begin) {
>      ++			res = error(_("corrupted author without date information"));
>      ++			goto out;
>      ++		}
>       +
>       +		strbuf_addf(&date, "@%.*s %.*s",
>       +			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
>      @@ -296,7 +300,7 @@
>       +
>       +test_expect_success '--committer-date-is-author-date works with rebase -r' '
>       +	git checkout side &&
>      -+	git merge commit3 &&
>      ++	git merge --no-ff commit3 &&
>       +	git rebase -r --root --committer-date-is-author-date &&
>       +	git rev-list HEAD >rev_list &&
>       +	while read HASH
>    5:  9e92c79bda = 494:  c7846945dd sequencer: rename amend_author to author_to_rename
>    6:  fc68e55e78 ! 495:  02f797b84d rebase -i: support --ignore-date
>      @@ -17,8 +17,8 @@
>        --ignore-date::
>       -	This flag is passed to 'git am' to change the author date
>       -	of each rebased commit (see linkgit:git-am[1]).
>      -+	Instead of using the given author date, reset it to the value
>      -+	same as the current time. This implies --force-rebase.
>      ++	Instead of using the given author date, reset it to the
>      ++	current time. This implies --force-rebase.
>        +
>        See also INCOMPATIBLE OPTIONS below.
>        
>      @@ -35,9 +35,9 @@
>         * --preserve-merges and --ignore-whitespace
>         * --preserve-merges and --committer-date-is-author-date
>       + * --preserve-merges and --ignore-date
>      -  * --rebase-merges and --ignore-whitespace
>      -  * --rebase-merges and --strategy
>      -  * --rebase-merges and --strategy-option
>      +  * --keep-base and --onto
>      +  * --keep-base and --root
>      +
>       
>        diff --git a/builtin/rebase.c b/builtin/rebase.c
>        --- a/builtin/rebase.c
>      @@ -83,10 +83,6 @@
>        	}
>        
>       -	if (options.committer_date_is_author_date)
>      -+	if (options.ignore_date) {
>      -+		options.committer_date_is_author_date = 0;
>      -+		setenv("GIT_COMMITTER_DATE", "", 1);
>      -+	}
>       +	if (options.committer_date_is_author_date ||
>       +	    options.ignore_date)
>        		options.flags |= REBASE_FORCE;
>      @@ -128,35 +124,56 @@
>       +	}
>       +	len = ident.mail_end - ident.name_begin + 1;
>       +
>      -+	strbuf_addf(&new_author, "%.*s ", len, author);
>      ++	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
>       +	datestamp(&new_author);
>       +	return strbuf_detach(&new_author, NULL);
>       +}
>       +
>      -+static void push_dates(struct child_process *child)
>      ++static void push_dates(struct child_process *child, int change_committer_date)
>       +{
>       +	time_t now = time(NULL);
>       +	struct strbuf date = STRBUF_INIT;
>       +
>       +	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
>       +	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
>      -+	argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
>      ++	if (change_committer_date)
>      ++		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
>       +	strbuf_release(&date);
>       +}
>       +
>        static const char staged_changes_advice[] =
>        N_("you have staged changes in your working tree\n"
>        "If these changes are meant to be squashed into the previous commit, run:\n"
>      +@@
>      + 	                return -1;
>      +
>      + 	        strbuf_addf(&datebuf, "@%s", date);
>      +-	        res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
>      ++		res = setenv("GIT_COMMITTER_DATE",
>      ++			     opts->ignore_date ? "" : datebuf.buf, 1);
>      +
>      + 		strbuf_release(&datebuf);
>      + 	        free(date);
>       @@
>        		argv_array_push(&cmd.args, "--amend");
>        	if (opts->gpg_sign)
>        		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>       +	if (opts->ignore_date)
>      -+		push_dates(&cmd);
>      ++		push_dates(&cmd, opts->committer_date_is_author_date);
>        	if (defmsg)
>        		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>        	else if (!(flags & EDIT_MSG))
>       @@
>      + 		strbuf_addf(&date, "@%.*s %.*s",
>      + 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
>      + 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
>      +-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
>      ++		res = setenv("GIT_COMMITTER_DATE",
>      ++			     opts->ignore_date ? "" : date.buf, 1);
>      + 		strbuf_release(&date);
>      +
>      + 		if (res)
>      +@@
>        
>        	reset_ident_date();
>        
>      @@ -198,7 +215,7 @@
>        		if (opts->gpg_sign)
>        			argv_array_push(&cmd.args, opts->gpg_sign);
>       +		if (opts->ignore_date)
>      -+			push_dates(&cmd);
>      ++			push_dates(&cmd, opts->committer_date_is_author_date);
>        
>        		/* Add the tips to be merged */
>        		for (j = to_merge; j; j = j->next)
>      @@ -239,31 +256,25 @@
>       +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
>       +	git rebase --ignore-date HEAD^ &&
>       +	git show HEAD --pretty="format:%ai" >authortime &&
>      -+	git show HEAD --pretty="format:%ci" >committertime &&
>      -+	grep "+0000" authortime &&
>      -+	grep "+0000" committertime
>      ++	grep "+0000" authortime
>       +'
>       +
>       +test_expect_success '--ignore-date works with interactive backend' '
>       +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
>       +	git rebase --ignore-date -i HEAD^ &&
>       +	git show HEAD --pretty="format:%ai" >authortime &&
>      -+	git show HEAD --pretty="format:%ci" >committertime &&
>      -+	grep "+0000" authortime &&
>      -+	grep "+0000" committertime
>      ++	grep "+0000" authortime
>       +'
>       +
>       +test_expect_success '--ignore-date works with rebase -r' '
>       +	git checkout side &&
>      -+	git merge commit3 &&
>      ++	git merge --no-ff commit3 &&
>       +	git rebase -r --root --ignore-date &&
>       +	git rev-list HEAD >rev_list &&
>       +	while read HASH
>       +	do
>       +		git show $HASH --pretty="format:%ai" >authortime
>      -+		git show $HASH --pretty="format:%ci" >committertime
>       +		grep "+0000" authortime
>      -+		grep "+0000" committertime
>       +	done <rev_list
>       +'
>       +
>    7:  396d5f16eb ! 496:  7a9fe1e612 rebase: add --reset-author-date
>      @@ -17,8 +17,8 @@
>        
>        --ignore-date::
>       +--reset-author-date::
>      - 	Instead of using the given author date, reset it to the value
>      - 	same as the current time. This implies --force-rebase.
>      + 	Instead of using the given author date, reset it to the
>      + 	current time. This implies --force-rebase.
>        +
>       
>        diff --git a/builtin/rebase.c b/builtin/rebase.c
> 

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

end of thread, back to index

Thread overview: 92+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-06 17:36 [GSoC][PATCHl 0/6] rebase -i: support more options Rohit Ashiwal
2019-08-06 17:36 ` [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
2019-08-07  5:38   ` Junio C Hamano
2019-08-07 20:25     ` Rohit Ashiwal
2019-08-06 17:36 ` [GSoC][PATCHl 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
2019-08-06 17:36 ` [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
2019-08-08 11:29   ` Phillip Wood
2019-08-08 16:00     ` Junio C Hamano
2019-08-06 17:36 ` [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
2019-08-08 11:30   ` Phillip Wood
2019-08-06 17:36 ` [GSoC][PATCHl 5/6] rebase -i: support --ignore-date Rohit Ashiwal
2019-08-07 19:41   ` Johannes Schindelin
2019-08-07 20:22     ` Junio C Hamano
2019-08-07 20:33       ` Rohit Ashiwal
2019-08-08 11:42   ` Phillip Wood
2019-08-08 16:53     ` Phillip Wood
2019-08-06 17:36 ` [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
2019-08-08 11:42   ` Phillip Wood
2019-08-12 19:42 ` [GSoC][PATCH v2 0/6] rebase -i: support more options Rohit Ashiwal
2019-08-12 19:42   ` [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
2019-08-13 12:07     ` Phillip Wood
2019-08-12 19:42   ` [GSoC][PATCH v2 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
2019-08-12 19:42   ` [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
2019-08-13 10:38     ` Phillip Wood
2019-08-13 12:09       ` Phillip Wood
2019-08-13 17:06       ` Junio C Hamano
2019-08-14 18:38         ` Phillip Wood
2019-08-13 13:35     ` Phillip Wood
2019-08-12 19:42   ` [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
2019-08-13 13:29     ` Phillip Wood
2019-08-12 19:42   ` [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date Rohit Ashiwal
2019-08-13 13:28     ` Phillip Wood
2019-08-13 17:21       ` Junio C Hamano
2019-08-14 18:47         ` Phillip Wood
2019-08-13 21:45     ` Junio C Hamano
2019-08-14 18:51       ` Phillip Wood
2019-08-14 19:33         ` Junio C Hamano
2019-08-17  9:28           ` Phillip Wood
2019-08-12 19:43   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
2019-08-13 17:28     ` Junio C Hamano
2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
2019-08-20  3:45   ` [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
2019-08-20 18:40     ` Phillip Wood
2019-08-20 18:47       ` Rohit Ashiwal
2019-08-20  3:45   ` [PATCH v3 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
2019-08-23 15:20     ` Junio C Hamano
2019-08-20  3:45   ` [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
2019-08-20 13:32     ` Phillip Wood
2019-08-20  3:45   ` [PATCH v3 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
2019-08-20  3:45   ` [PATCH v3 5/6] rebase -i: support --ignore-date Rohit Ashiwal
2019-08-20 13:45     ` Phillip Wood
2019-08-20 17:42     ` Junio C Hamano
2019-08-20 18:30       ` Phillip Wood
2019-08-20  3:45   ` [PATCH v3 6/6] rebase: add --reset-author-date Rohit Ashiwal
2019-08-20  3:54   ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
2019-08-20 13:56   ` Phillip Wood
2019-08-20 17:53     ` Junio C Hamano
2019-08-20 18:37       ` Phillip Wood
2019-09-07 11:50 ` [PATCH v4 " Rohit Ashiwal
2019-09-07 11:50   ` [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
2019-10-04  9:29     ` Phillip Wood
2019-10-05 18:12       ` Elijah Newren
2019-10-06 17:57       ` Rohit Ashiwal
2019-09-07 11:50   ` [PATCH v4 2/6] sequencer: allow callers of read_author_script() to ignore fields Rohit Ashiwal
2019-09-07 11:50   ` [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
2019-10-24 13:28     ` Phillip Wood
2019-09-07 11:50   ` [PATCH v4 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
2019-09-07 11:50   ` [PATCH v4 5/6] rebase -i: support --ignore-date Rohit Ashiwal
2019-09-07 20:56     ` Rohit Ashiwal
2019-09-07 11:50   ` [PATCH v4 6/6] rebase: add --reset-author-date Rohit Ashiwal
2019-09-09 18:02   ` [PATCH v4 0/6] rebase -i: support more options Junio C Hamano
2019-09-09 18:51     ` Phillip Wood
2019-09-09 19:24       ` Junio C Hamano
2019-11-01 13:59 ` [PATCH v5 " Rohit Ashiwal
2019-11-01 13:59   ` [PATCH v5 1/6] rebase -i: add --ignore-whitespace flag Rohit Ashiwal
2019-11-01 13:59   ` [PATCH v5 2/6] sequencer: allow callers of read_author_script() to ignore fields Rohit Ashiwal
2019-11-01 14:00   ` [PATCH v5 3/6] rebase -i: support --committer-date-is-author-date Rohit Ashiwal
2019-11-01 14:00   ` [PATCH v5 4/6] sequencer: rename amend_author to author_to_rename Rohit Ashiwal
2019-11-01 14:00   ` [PATCH v5 5/6] rebase -i: support --ignore-date Rohit Ashiwal
2019-11-02  7:32     ` Junio C Hamano
2019-11-02  7:48       ` Junio C Hamano
2019-11-01 14:00   ` [PATCH v5 6/6] rebase: add --reset-author-date Rohit Ashiwal
2019-11-02  7:34     ` Junio C Hamano
2019-11-21  6:14   ` [PATCH v5 0/6] rebase -i: support more options Junio C Hamano
2019-11-21  8:17     ` Alban Gruin
2019-11-22  6:32       ` Junio C Hamano
2019-11-28 11:14   ` Phillip Wood
2019-08-08 16:44 [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag Phillip Wood
2019-08-12 17:43 ` Rohit Ashiwal
2019-08-20  3:45 [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
2019-08-20  4:00 ` Rohit Ashiwal
2019-09-27 10:00 [PATCH v4 5/6] rebase -i: support --ignore-date Phillip Wood
2019-10-06 17:57 ` Rohit Ashiwal
2019-10-24 20:36   ` Phillip Wood
2019-10-04  9:37 [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date Phillip Wood
2019-10-06 17:57 ` Rohit Ashiwal

Git Mailing List Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/git/0 git/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 git git/ https://lore.kernel.org/git \
		git@vger.kernel.org
	public-inbox-index git

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.git


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git