git@vger.kernel.org list mirror (unofficial, one of many)
 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
                   ` (7 more replies)
  0 siblings, 8 replies; 62+ 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] 62+ 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-08 16:44   ` Phillip Wood
  2019-08-06 17:36 ` [GSoC][PATCHl 2/6] sequencer: add NULL checks under read_author_script Rohit Ashiwal
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 62+ 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] 62+ 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
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 62+ 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] 62+ 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
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 62+ 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] 62+ 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
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 62+ 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] 62+ 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
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 62+ 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] 62+ 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
  2019-08-20  3:45 ` [PATCH v3 0/6] rebase -i: support more options Rohit Ashiwal
  7 siblings, 1 reply; 62+ 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] 62+ 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
  2019-08-08 16:44   ` Phillip Wood
  1 sibling, 1 reply; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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-08 16:44   ` Phillip Wood
  2019-08-12 17:43     ` Rohit Ashiwal
  1 sibling, 1 reply; 62+ messages in thread
From: Phillip Wood @ 2019-08-08 16:44 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:
> 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.

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.

> +
>   --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)

It's a shame this changes the rebase_options that are passed in, this 
function should ideally not modify what is passed in.

>   	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);
> +	}

Instead of modifying opts->strategy_opts perhaps we could just use a 
temporary variable

Best Wishes

Phillip

>   	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
> 

^ permalink raw reply	[flat|nested] 62+ 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; 62+ 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] 62+ messages in thread

* Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag
  2019-08-08 16:44   ` Phillip Wood
@ 2019-08-12 17:43     ` Rohit Ashiwal
  0 siblings, 0 replies; 62+ 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] 62+ 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
  7 siblings, 6 replies; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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
                     ` (8 more replies)
  7 siblings, 9 replies; 62+ 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] 62+ 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
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 62+ 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] 62+ 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
                     ` (6 subsequent siblings)
  8 siblings, 1 reply; 62+ 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] 62+ 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
                     ` (5 subsequent siblings)
  8 siblings, 1 reply; 62+ 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] 62+ 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
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 62+ 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] 62+ 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   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
                     ` (3 subsequent siblings)
  8 siblings, 2 replies; 62+ 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] 62+ messages in thread

* [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-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  4:00     ` Rohit Ashiwal
  2019-08-20  3:45   ` [PATCH v3 6/6] rebase: add --reset-author-date Rohit Ashiwal
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 62+ 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 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] 62+ 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
                     ` (5 preceding siblings ...)
  2019-08-20  3:45   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-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
  8 siblings, 0 replies; 62+ 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] 62+ 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: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
  8 siblings, 0 replies; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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
                     ` (7 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
  8 siblings, 1 reply; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ 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; 62+ 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] 62+ messages in thread

end of thread, back to index

Thread overview: 62+ 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-08 16:44   ` Phillip Wood
2019-08-12 17:43     ` 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   ` [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date Rohit Ashiwal
2019-08-20  4:00     ` Rohit Ashiwal
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

git@vger.kernel.org list mirror (unofficial, one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/

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