git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <johannes.schindelin@gmx.de>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Jakub Narębski" <jnareb@gmail.com>,
	"Johannes Sixt" <j6t@kdbg.org>,
	"Ramsay Jones" <ramsay@ramsayjones.plus.com>
Subject: [PATCH v4 08/25] sequencer: completely revamp the "todo" script parsing
Date: Fri, 14 Oct 2016 15:17:50 +0200 (CEST)	[thread overview]
Message-ID: <a5f5d784fcacc16555237b9750380d612387d0cb.1476450940.git.johannes.schindelin@gmx.de> (raw)
In-Reply-To: <cover.1476450940.git.johannes.schindelin@gmx.de>

When we came up with the "sequencer" idea, we really wanted to have
kind of a plumbing equivalent of the interactive rebase. Hence the
choice of words: the "todo" script, a "pick", etc.

However, when it came time to implement the entire shebang, somehow this
idea got lost and the sequencer was used as working horse for
cherry-pick and revert instead. So as not to interfere with the
interactive rebase, it even uses a separate directory to store its
state.

Furthermore, it also is stupidly strict about the "todo" script it
accepts: while it parses commands in a way that was *designed* to be
similar to the interactive rebase, it then goes on to *error out* if the
commands disagree with the overall action (cherry-pick or revert).

Finally, the sequencer code chose to deviate from the interactive rebase
code insofar that when it comes to writing the file with the remaining
commands, it *reformats* the "todo" script instead of just writing the
part of the parsed script that were not yet processed. This is not only
unnecessary churn, but might well lose information that is valuable to
the user (i.e. comments after the commands).

Let's just bite the bullet and rewrite the entire parser; the code now
becomes not only more elegant: it allows us to go on and teach the
sequencer how to parse *true* "todo" scripts as used by the interactive
rebase itself. In a way, the sequencer is about to grow up to do its
older brother's job. Better.

In particular, we choose to maintain the list of commands in an array
instead of a linked list: this is flexible enough to allow us later on to
even implement rebase -i's reordering of fixup!/squash! commits very
easily (and with a very nice speed bonus, at least on Windows).

While at it, do not stop at the first problem, but list *all* of the
problems. This will help the user when the sequencer will do `rebase
-i`'s work by allowing to address all issues in one go rather than going
back and forth until the todo list is valid.

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

diff --git a/sequencer.c b/sequencer.c
index 499f5ee..f797e8a 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -470,7 +470,26 @@ static int allow_empty(struct replay_opts *opts, struct commit *commit)
 		return 1;
 }
 
-static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
+enum todo_command {
+	TODO_PICK = 0,
+	TODO_REVERT
+};
+
+static const char *todo_command_strings[] = {
+	"pick",
+	"revert"
+};
+
+static const char *command_to_string(const enum todo_command command)
+{
+	if (command < ARRAY_SIZE(todo_command_strings))
+		return todo_command_strings[command];
+	die("Unknown command: %d", command);
+}
+
+
+static int do_pick_commit(enum todo_command command, struct commit *commit,
+		struct replay_opts *opts)
 {
 	unsigned char head[20];
 	struct commit *base, *next, *parent;
@@ -529,10 +548,11 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 		return fast_forward_to(commit->object.oid.hash, head, unborn, opts);
 
 	if (parent && parse_commit(parent) < 0)
-		/* TRANSLATORS: The first %s will be "revert" or
-		   "cherry-pick", the second %s a SHA1 */
+		/* TRANSLATORS: The first %s will be a "todo" command like
+		   "revert" or "pick", the second %s a SHA1. */
 		return error(_("%s: cannot parse parent commit %s"),
-			action_name(opts), oid_to_hex(&parent->object.oid));
+			command_to_string(command),
+			oid_to_hex(&parent->object.oid));
 
 	if (get_message(commit, &msg) != 0)
 		return error(_("Cannot get commit message for %s"),
@@ -545,7 +565,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 	 * reverse of it if we are revert.
 	 */
 
-	if (opts->action == REPLAY_REVERT) {
+	if (command == TODO_REVERT) {
 		base = commit;
 		base_label = msg.label;
 		next = parent;
@@ -586,7 +606,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 		}
 	}
 
-	if (!opts->strategy || !strcmp(opts->strategy, "recursive") || opts->action == REPLAY_REVERT) {
+	if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
 		res = do_recursive_merge(base, next, base_label, next_label,
 					 head, &msgbuf, opts);
 		if (res < 0)
@@ -613,17 +633,17 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 	 * However, if the merge did not even start, then we don't want to
 	 * write it at all.
 	 */
-	if (opts->action == REPLAY_PICK && !opts->no_commit && (res == 0 || res == 1) &&
+	if (command == TODO_PICK && !opts->no_commit && (res == 0 || res == 1) &&
 	    update_ref(NULL, "CHERRY_PICK_HEAD", commit->object.oid.hash, NULL,
 		       REF_NODEREF, UPDATE_REFS_MSG_ON_ERR))
 		res = -1;
-	if (opts->action == REPLAY_REVERT && ((opts->no_commit && res == 0) || res == 1) &&
+	if (command == TODO_REVERT && ((opts->no_commit && res == 0) || res == 1) &&
 	    update_ref(NULL, "REVERT_HEAD", commit->object.oid.hash, NULL,
 		       REF_NODEREF, UPDATE_REFS_MSG_ON_ERR))
 		res = -1;
 
 	if (res) {
-		error(opts->action == REPLAY_REVERT
+		error(command == TODO_REVERT
 		      ? _("could not revert %s... %s")
 		      : _("could not apply %s... %s"),
 		      short_commit_name(commit), msg.subject);
@@ -684,116 +704,122 @@ static int read_and_refresh_cache(struct replay_opts *opts)
 	return 0;
 }
 
-static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
-		struct replay_opts *opts)
+struct todo_item {
+	enum todo_command command;
+	struct commit *commit;
+	size_t offset_in_buf;
+};
+
+struct todo_list {
+	struct strbuf buf;
+	struct todo_item *items;
+	int nr, alloc, current;
+};
+
+#define TODO_LIST_INIT { STRBUF_INIT }
+
+static void todo_list_release(struct todo_list *todo_list)
 {
-	struct commit_list *cur = NULL;
-	const char *sha1_abbrev = NULL;
-	const char *action_str = opts->action == REPLAY_REVERT ? "revert" : "pick";
-	const char *subject;
-	int subject_len;
+	strbuf_release(&todo_list->buf);
+	free(todo_list->items);
+	todo_list->items = NULL;
+	todo_list->nr = todo_list->alloc = 0;
+}
 
-	for (cur = todo_list; cur; cur = cur->next) {
-		const char *commit_buffer = get_commit_buffer(cur->item, NULL);
-		sha1_abbrev = find_unique_abbrev(cur->item->object.oid.hash, DEFAULT_ABBREV);
-		subject_len = find_commit_subject(commit_buffer, &subject);
-		strbuf_addf(buf, "%s %s %.*s\n", action_str, sha1_abbrev,
-			subject_len, subject);
-		unuse_commit_buffer(cur->item, commit_buffer);
-	}
-	return 0;
+static struct todo_item *append_new_todo(struct todo_list *todo_list)
+{
+	ALLOC_GROW(todo_list->items, todo_list->nr + 1, todo_list->alloc);
+	return todo_list->items + todo_list->nr++;
 }
 
-static struct commit *parse_insn_line(char *bol, char *eol, struct replay_opts *opts)
+static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
 {
 	unsigned char commit_sha1[20];
-	enum replay_action action;
 	char *end_of_object_name;
-	int saved, status, padding;
-
-	if (starts_with(bol, "pick")) {
-		action = REPLAY_PICK;
-		bol += strlen("pick");
-	} else if (starts_with(bol, "revert")) {
-		action = REPLAY_REVERT;
-		bol += strlen("revert");
-	} else
-		return NULL;
+	int i, saved, status, padding;
+
+	for (i = 0; i < ARRAY_SIZE(todo_command_strings); i++)
+		if (skip_prefix(bol, todo_command_strings[i], &bol)) {
+			item->command = i;
+			break;
+		}
+	if (i >= ARRAY_SIZE(todo_command_strings))
+		return -1;
 
 	/* Eat up extra spaces/ tabs before object name */
 	padding = strspn(bol, " \t");
 	if (!padding)
-		return NULL;
+		return -1;
 	bol += padding;
 
-	end_of_object_name = bol + strcspn(bol, " \t\n");
+	end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
 	saved = *end_of_object_name;
 	*end_of_object_name = '\0';
 	status = get_sha1(bol, commit_sha1);
 	*end_of_object_name = saved;
 
-	/*
-	 * Verify that the action matches up with the one in
-	 * opts; we don't support arbitrary instructions
-	 */
-	if (action != opts->action) {
-		if (action == REPLAY_REVERT)
-		      error((opts->action == REPLAY_REVERT)
-			    ? _("Cannot revert during another revert.")
-			    : _("Cannot revert during a cherry-pick."));
-		else
-		      error((opts->action == REPLAY_REVERT)
-			    ? _("Cannot cherry-pick during a revert.")
-			    : _("Cannot cherry-pick during another cherry-pick."));
-		return NULL;
-	}
-
 	if (status < 0)
-		return NULL;
+		return -1;
 
-	return lookup_commit_reference(commit_sha1);
+	item->commit = lookup_commit_reference(commit_sha1);
+	return !item->commit;
 }
 
-static int parse_insn_buffer(char *buf, struct commit_list **todo_list,
-			struct replay_opts *opts)
+static int parse_insn_buffer(char *buf, struct todo_list *todo_list)
 {
-	struct commit_list **next = todo_list;
-	struct commit *commit;
-	char *p = buf;
-	int i;
+	struct todo_item *item;
+	char *p = buf, *next_p;
+	int i, res = 0;
 
-	for (i = 1; *p; i++) {
+	for (i = 1; *p; i++, p = next_p) {
 		char *eol = strchrnul(p, '\n');
-		commit = parse_insn_line(p, eol, opts);
-		if (!commit)
-			return error(_("Could not parse line %d."), i);
-		next = commit_list_append(commit, next);
-		p = *eol ? eol + 1 : eol;
+
+		next_p = *eol ? eol + 1 /* strip LF */ : eol;
+
+		item = append_new_todo(todo_list);
+		item->offset_in_buf = p - todo_list->buf.buf;
+		if (parse_insn_line(item, p, eol)) {
+			res = error(_("Invalid line %d: %.*s"),
+				i, (int)(eol - p), p);
+			item->command = -1;
+		}
 	}
-	if (!*todo_list)
+	if (!todo_list->nr)
 		return error(_("No commits parsed."));
-	return 0;
+	return res;
 }
 
-static int read_populate_todo(struct commit_list **todo_list,
+static int read_populate_todo(struct todo_list *todo_list,
 			struct replay_opts *opts)
 {
 	const char *todo_file = get_todo_path(opts);
-	struct strbuf buf = STRBUF_INIT;
 	int fd, res;
 
+	strbuf_reset(&todo_list->buf);
 	fd = open(todo_file, O_RDONLY);
 	if (fd < 0)
 		return error_errno(_("Could not open %s"), todo_file);
-	if (strbuf_read(&buf, fd, 0) < 0) {
+	if (strbuf_read(&todo_list->buf, fd, 0) < 0) {
 		close(fd);
-		strbuf_release(&buf);
 		return error(_("Could not read %s."), todo_file);
 	}
 	close(fd);
 
-	res = parse_insn_buffer(buf.buf, todo_list, opts);
-	strbuf_release(&buf);
+	res = parse_insn_buffer(todo_list->buf.buf, todo_list);
+	if (!res) {
+		enum todo_command valid =
+			opts->action == REPLAY_PICK ? TODO_PICK : TODO_REVERT;
+		int i;
+
+		for (i = 0; i < todo_list->nr; i++)
+			if (valid == todo_list->items[i].command)
+				continue;
+			else if (valid == TODO_PICK)
+				return error(_("Cannot cherry-pick during a revert."));
+			else
+				return error(_("Cannot revert during a cherry-pick."));
+	}
+
 	if (res)
 		return error(_("Unusable instruction sheet: %s"), todo_file);
 	return 0;
@@ -860,18 +886,31 @@ static int read_populate_opts(struct replay_opts *opts)
 	return 0;
 }
 
-static int walk_revs_populate_todo(struct commit_list **todo_list,
+static int walk_revs_populate_todo(struct todo_list *todo_list,
 				struct replay_opts *opts)
 {
+	enum todo_command command = opts->action == REPLAY_PICK ?
+		TODO_PICK : TODO_REVERT;
+	const char *command_string = todo_command_strings[command];
 	struct commit *commit;
-	struct commit_list **next;
 
 	if (prepare_revs(opts))
 		return -1;
 
-	next = todo_list;
-	while ((commit = get_revision(opts->revs)))
-		next = commit_list_append(commit, next);
+	while ((commit = get_revision(opts->revs))) {
+		struct todo_item *item = append_new_todo(todo_list);
+		const char *commit_buffer = get_commit_buffer(commit, NULL);
+		const char *subject;
+		int subject_len;
+
+		item->command = command;
+		item->commit = commit;
+		item->offset_in_buf = todo_list->buf.len;
+		subject_len = find_commit_subject(commit_buffer, &subject);
+		strbuf_addf(&todo_list->buf, "%s %s %.*s\n", command_string,
+			short_commit_name(commit), subject_len, subject);
+		unuse_commit_buffer(commit, commit_buffer);
+	}
 	return 0;
 }
 
@@ -979,30 +1018,22 @@ static int sequencer_rollback(struct replay_opts *opts)
 	return -1;
 }
 
-static int save_todo(struct commit_list *todo_list, struct replay_opts *opts)
+static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
 {
 	static struct lock_file todo_lock;
-	struct strbuf buf = STRBUF_INIT;
-	int fd;
+	const char *todo_path = get_todo_path(opts);
+	int next = todo_list->current, offset, fd;
 
-	fd = hold_lock_file_for_update(&todo_lock, git_path_todo_file(), 0);
+	fd = hold_lock_file_for_update(&todo_lock, todo_path, 0);
 	if (fd < 0)
-		return error_errno(_("Could not lock '%s'"),
-				   git_path_todo_file());
-	if (format_todo(&buf, todo_list, opts) < 0) {
-		strbuf_release(&buf);
-		return error(_("Could not format %s."), git_path_todo_file());
-	}
-	if (write_in_full(fd, buf.buf, buf.len) < 0) {
-		strbuf_release(&buf);
-		return error_errno(_("Could not write to %s"),
-				   git_path_todo_file());
-	}
-	if (commit_lock_file(&todo_lock) < 0) {
-		strbuf_release(&buf);
-		return error(_("Error wrapping up %s."), git_path_todo_file());
-	}
-	strbuf_release(&buf);
+		return error_errno(_("Could not lock '%s'"), todo_path);
+	offset = next < todo_list->nr ?
+		todo_list->items[next].offset_in_buf : todo_list->buf.len;
+	if (write_in_full(fd, todo_list->buf.buf + offset,
+			todo_list->buf.len - offset) < 0)
+		return error_errno(_("Could not write to '%s'"), todo_path);
+	if (commit_lock_file(&todo_lock) < 0)
+		return error(_("Error wrapping up %s."), todo_path);
 	return 0;
 }
 
@@ -1041,9 +1072,8 @@ static int save_opts(struct replay_opts *opts)
 	return res;
 }
 
-static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
+static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
 {
-	struct commit_list *cur;
 	int res;
 
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
@@ -1053,10 +1083,12 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
 	if (read_and_refresh_cache(opts))
 		return -1;
 
-	for (cur = todo_list; cur; cur = cur->next) {
-		if (save_todo(cur, opts))
+	while (todo_list->current < todo_list->nr) {
+		struct todo_item *item = todo_list->items + todo_list->current;
+		if (save_todo(todo_list, opts))
 			return -1;
-		res = do_pick_commit(cur->item, opts);
+		res = do_pick_commit(item->command, item->commit, opts);
+		todo_list->current++;
 		if (res)
 			return res;
 	}
@@ -1081,38 +1113,46 @@ static int continue_single_pick(void)
 
 static int sequencer_continue(struct replay_opts *opts)
 {
-	struct commit_list *todo_list = NULL;
+	struct todo_list todo_list = TODO_LIST_INIT;
+	int res;
 
 	if (!file_exists(get_todo_path(opts)))
 		return continue_single_pick();
-	if (read_populate_opts(opts) ||
-			read_populate_todo(&todo_list, opts))
+	if (read_populate_opts(opts))
 		return -1;
+	if ((res = read_populate_todo(&todo_list, opts)))
+		goto release_todo_list;
 
 	/* Verify that the conflict has been resolved */
 	if (file_exists(git_path_cherry_pick_head()) ||
 	    file_exists(git_path_revert_head())) {
-		int ret = continue_single_pick();
-		if (ret)
-			return ret;
+		res = continue_single_pick();
+		if (res)
+			goto release_todo_list;
 	}
-	if (index_differs_from("HEAD", 0))
-		return error_dirty_index(opts);
-	todo_list = todo_list->next;
-	return pick_commits(todo_list, opts);
+	if (index_differs_from("HEAD", 0)) {
+		res = error_dirty_index(opts);
+		goto release_todo_list;
+	}
+	todo_list.current++;
+	res = pick_commits(&todo_list, opts);
+release_todo_list:
+	todo_list_release(&todo_list);
+	return res;
 }
 
 static int single_pick(struct commit *cmit, struct replay_opts *opts)
 {
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
-	return do_pick_commit(cmit, opts);
+	return do_pick_commit(opts->action == REPLAY_PICK ?
+		TODO_PICK : TODO_REVERT, cmit, opts);
 }
 
 int sequencer_pick_revisions(struct replay_opts *opts)
 {
-	struct commit_list *todo_list = NULL;
+	struct todo_list todo_list = TODO_LIST_INIT;
 	unsigned char sha1[20];
-	int i;
+	int i, res;
 
 	if (opts->subcommand == REPLAY_NONE)
 		assert(opts->revs);
@@ -1187,7 +1227,9 @@ int sequencer_pick_revisions(struct replay_opts *opts)
 		return -1;
 	if (save_opts(opts))
 		return -1;
-	return pick_commits(todo_list, opts);
+	res = pick_commits(&todo_list, opts);
+	todo_list_release(&todo_list);
+	return res;
 }
 
 void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)
-- 
2.10.1.513.g00ef6dd



  parent reply	other threads:[~2016-10-14 13:20 UTC|newest]

Thread overview: 352+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-29  8:03 [PATCH 00/22] Prepare the sequencer for the upcoming rebase -i patches Johannes Schindelin
2016-08-29  8:03 ` [PATCH 01/22] sequencer: use static initializers for replay_opts Johannes Schindelin
2016-08-29  9:19   ` Dennis Kaarsemaker
2016-08-29 10:54     ` Johannes Schindelin
2016-08-29 17:41     ` Jakub Narębski
2016-08-29 17:06       ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 02/22] sequencer: use memoized sequencer directory path Johannes Schindelin
2016-08-29 19:54   ` Jakub Narębski
2016-08-29 17:10     ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 03/22] sequencer: avoid unnecessary indirection Johannes Schindelin
2016-08-29 20:22   ` Jakub Narębski
2016-08-29 17:15     ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 04/22] sequencer: future-proof remove_sequencer_state() Johannes Schindelin
2016-08-29  9:24   ` Dennis Kaarsemaker
2016-08-29 10:58     ` Johannes Schindelin
2016-08-29 11:19       ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 05/22] sequencer: allow the sequencer to take custody of malloc()ed data Johannes Schindelin
2016-08-29 21:59   ` Jakub Narębski
2016-08-30  5:33     ` Johannes Sixt
2016-08-30  7:30       ` Johannes Schindelin
2016-08-30  7:29     ` Johannes Schindelin
2016-08-30 11:08       ` Jakub Narębski
2016-08-30 18:25         ` Junio C Hamano
2016-08-31  8:20           ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 06/22] sequencer: release memory that was allocated when reading options Johannes Schindelin
2016-08-30 14:54   ` Jakub Narębski
2016-08-30 17:52     ` Johannes Schindelin
2016-08-30 20:46       ` Johannes Sixt
2016-08-30 22:07         ` Junio C Hamano
2016-08-30 22:00       ` Jakub Narębski
2016-08-30 18:30   ` Junio C Hamano
2016-08-31  8:07     ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 07/22] sequencer: future-proof read_populate_todo() Johannes Schindelin
2016-08-30 16:07   ` Jakub Narębski
2016-08-30 16:48     ` Johannes Schindelin
2016-08-29  8:04 ` [PATCH 08/22] sequencer: remove overzealous assumption Johannes Schindelin
2016-08-31 13:41   ` Jakub Narębski
2016-08-31 18:36     ` Johannes Schindelin
2016-08-31 18:46       ` Jakub Narębski
2016-09-01  8:01         ` Johannes Schindelin
2016-09-01 20:00           ` Jakub Narębski
2016-08-31 19:01       ` Junio C Hamano
2016-09-01  8:02         ` Johannes Schindelin
2016-08-29  8:05 ` [PATCH 09/22] sequencer: completely revamp the "todo" script parsing Johannes Schindelin
2016-08-31 17:29   ` Jakub Narębski
2016-08-31 23:03     ` Stefan Beller
2016-09-01  6:35       ` Johannes Schindelin
2016-09-01 18:37         ` Junio C Hamano
2016-09-01  7:49     ` Johannes Schindelin
2016-09-01 22:05       ` Jakub Narębski
2016-09-09 14:12         ` Johannes Schindelin
2016-08-29  8:05 ` [PATCH 10/22] sequencer: avoid completely different messages for different actions Johannes Schindelin
2016-08-31 17:58   ` Jakub Narębski
2016-09-01  7:52     ` Johannes Schindelin
2016-09-01 22:33       ` Jakub Narębski
2016-09-09 14:23         ` Johannes Schindelin
2016-08-29  8:05 ` [PATCH 11/22] sequencer: get rid of the subcommand field Johannes Schindelin
2016-08-31 18:24   ` Jakub Narębski
2016-09-01  7:55     ` Johannes Schindelin
2016-08-29  8:05 ` [PATCH 12/22] sequencer: refactor the code to obtain a short commit name Johannes Schindelin
2016-08-29  9:39   ` Dennis Kaarsemaker
2016-08-29 11:04     ` Johannes Schindelin
2016-08-29  8:05 ` [PATCH 13/22] sequencer: remember the onelines when parsing the todo file Johannes Schindelin
2016-08-31 18:37   ` Jakub Narębski
2016-08-31 19:10     ` Junio C Hamano
2016-08-31 19:24       ` Jakub Narębski
2016-08-31 19:42         ` Junio C Hamano
2016-09-01 13:14           ` Johannes Schindelin
2016-09-01 13:12         ` Johannes Schindelin
2016-09-01 22:52           ` Jakub Narębski
2016-09-01  9:37       ` Johannes Schindelin
2016-09-01 18:47         ` Junio C Hamano
2016-09-09 15:12           ` Johannes Schindelin
2016-09-09 19:06             ` Jakub Narębski
2016-09-11  8:33               ` Git garden shears, was " Johannes Schindelin
2016-09-21 13:17                 ` Jakub Narębski
2016-09-25 18:16                   ` Johannes Schindelin
2016-09-01 22:46         ` Jakub Narębski
2016-09-01 22:59           ` Junio C Hamano
2016-09-09 14:27             ` Johannes Schindelin
2016-09-01  8:45     ` Johannes Schindelin
2016-08-29  8:06 ` [PATCH 14/22] sequencer: prepare for rebase -i's commit functionality Johannes Schindelin
2016-08-29 21:32   ` Junio C Hamano
2016-08-30  6:53     ` Johannes Schindelin
2016-08-30 17:32       ` Junio C Hamano
2016-08-30 18:18         ` Johannes Schindelin
2016-08-30 22:35         ` Junio C Hamano
2016-08-31  8:19           ` Johannes Schindelin
2016-08-29  8:06 ` [PATCH 15/22] sequencer: introduce a helper to read files written by scripts Johannes Schindelin
2016-08-29  9:47   ` Dennis Kaarsemaker
2016-08-29 11:08     ` Johannes Schindelin
2016-08-29  8:06 ` [PATCH 16/22] sequencer: prepare for rebase -i's GPG settings Johannes Schindelin
2016-08-31 20:10   ` Jakub Narębski
2016-08-31 20:12     ` Junio C Hamano
2016-08-31 20:29       ` Jakub Narębski
2016-08-31 20:33         ` Junio C Hamano
2016-09-01 13:35         ` Johannes Schindelin
2016-09-01 13:33       ` Johannes Schindelin
2016-09-01 13:33     ` Johannes Schindelin
2016-09-01 23:21       ` Jakub Narębski
2016-08-29  8:06 ` [PATCH 17/22] sequencer: allow editing the commit message on a case-by-case basis Johannes Schindelin
2016-08-31 20:56   ` Jakub Narębski
2016-09-01 13:40     ` Johannes Schindelin
2016-08-29  8:06 ` [PATCH 18/22] sequencer: support amending commits Johannes Schindelin
2016-08-31 21:08   ` Jakub Narębski
2016-09-01 13:42     ` Johannes Schindelin
2016-08-29  8:06 ` [PATCH 19/22] sequencer: support cleaning up commit messages Johannes Schindelin
2016-09-01 10:31   ` Jakub Narębski
2016-09-01 13:56     ` Johannes Schindelin
2016-09-01 23:31       ` Jakub Narębski
2016-08-29  8:06 ` [PATCH 20/22] sequencer: remember do_recursive_merge()'s return value Johannes Schindelin
2016-08-29  9:51   ` Dennis Kaarsemaker
2016-08-29 11:09     ` Johannes Schindelin
2016-08-29 20:32   ` Jakub Narębski
2016-08-29 21:13     ` Junio C Hamano
2016-08-29  8:06 ` [PATCH 21/22] sequencer: left-trim the lines read from the script Johannes Schindelin
2016-09-01 10:50   ` Jakub Narębski
2016-09-01 14:13     ` Johannes Schindelin
2016-09-01 17:58       ` Junio C Hamano
2016-09-09 15:08         ` Johannes Schindelin
2016-09-01 23:33       ` Jakub Narębski
2016-09-09 14:31         ` Johannes Schindelin
2016-08-29  8:06 ` [PATCH 22/22] sequencer: refactor write_message() Johannes Schindelin
2016-09-01 11:10   ` Jakub Narębski
2016-09-01 14:20     ` Johannes Schindelin
2016-09-01 23:35       ` Jakub Narębski
2016-09-09 14:40         ` Johannes Schindelin
2016-09-09 19:11           ` Jakub Narębski
2016-09-11  8:26             ` Johannes Schindelin
2016-08-29  9:56 ` [PATCH 00/22] Prepare the sequencer for the upcoming rebase -i patches Dennis Kaarsemaker
2016-08-29 11:10   ` Johannes Schindelin
2016-09-02 11:41 ` Jakub Narębski
2016-09-02 13:56   ` Johannes Schindelin
2016-09-11 10:52 ` [PATCH v2 00/25] " Johannes Schindelin
2016-09-11 10:52   ` [PATCH v2 01/25] sequencer: use static initializers for replay_opts Johannes Schindelin
2016-09-12 19:46     ` Junio C Hamano
2016-09-11 10:52   ` [PATCH v2 02/25] sequencer: use memoized sequencer directory path Johannes Schindelin
2016-09-12 19:48     ` Junio C Hamano
2016-09-11 10:52   ` [PATCH v2 03/25] sequencer: avoid unnecessary indirection Johannes Schindelin
2016-09-12 19:49     ` Junio C Hamano
2016-09-11 10:53   ` [PATCH v2 04/25] sequencer: future-proof remove_sequencer_state() Johannes Schindelin
2016-09-12 19:53     ` Junio C Hamano
2016-10-05 11:46       ` Johannes Schindelin
2016-10-05 17:41         ` Junio C Hamano
2016-09-11 10:53   ` [PATCH v2 05/25] sequencer: allow the sequencer to take custody of malloc()ed data Johannes Schindelin
2016-09-12 19:46     ` Junio C Hamano
2016-10-05 11:41       ` Johannes Schindelin
2016-10-06 19:23         ` Junio C Hamano
2016-10-06 22:40           ` Jakub Narębski
2016-10-06 22:53             ` Junio C Hamano
2016-10-08  9:11           ` Johannes Schindelin
2016-09-11 10:53   ` [PATCH v2 06/25] sequencer: release memory that was allocated when reading options Johannes Schindelin
2016-09-11 10:53   ` [PATCH v2 07/25] sequencer: future-proof read_populate_todo() Johannes Schindelin
2016-09-11 10:53   ` [PATCH v2 08/25] sequencer: completely revamp the "todo" script parsing Johannes Schindelin
2016-09-11 10:53   ` [PATCH v2 09/25] sequencer: avoid completely different messages for different actions Johannes Schindelin
2016-09-11 10:53   ` [PATCH v2 10/25] sequencer: get rid of the subcommand field Johannes Schindelin
2016-09-15 19:15     ` Junio C Hamano
2016-09-11 10:54   ` [PATCH v2 11/25] sequencer: refactor the code to obtain a short commit name Johannes Schindelin
2016-09-11 10:54   ` [PATCH v2 12/25] sequencer: remember the onelines when parsing the todo file Johannes Schindelin
2016-09-11 10:54   ` [PATCH v2 13/25] sequencer: prepare for rebase -i's commit functionality Johannes Schindelin
2016-09-11 10:54   ` [PATCH v2 14/25] sequencer: introduce a helper to read files written by scripts Johannes Schindelin
2016-09-11 10:54   ` [PATCH v2 15/25] sequencer: prepare for rebase -i's GPG settings Johannes Schindelin
2016-09-11 10:54   ` [PATCH v2 16/25] sequencer: allow editing the commit message on a case-by-case basis Johannes Schindelin
2016-09-11 10:55   ` [PATCH v2 17/25] sequencer: support amending commits Johannes Schindelin
2016-09-12 21:36     ` Junio C Hamano
2016-10-05 12:41       ` Johannes Schindelin
2016-09-11 10:55   ` [PATCH v2 18/25] sequencer: support cleaning up commit messages Johannes Schindelin
2016-09-12 21:33     ` Junio C Hamano
2016-09-11 10:55   ` [PATCH v2 19/25] sequencer: remember do_recursive_merge()'s return value Johannes Schindelin
2016-09-12 21:23     ` Junio C Hamano
2016-10-05 12:35       ` Johannes Schindelin
2016-10-05 17:43         ` Junio C Hamano
2016-09-11 10:55   ` [PATCH v2 20/25] sequencer: left-trim lines read from the script Johannes Schindelin
2016-09-11 23:39     ` Junio C Hamano
2016-09-12  8:23       ` Johannes Schindelin
2016-09-12 15:42         ` Junio C Hamano
2016-10-06 13:08           ` Johannes Schindelin
2016-10-06 16:23             ` Johannes Sixt
2016-10-06 18:41               ` Junio C Hamano
2016-10-09  8:57               ` Johannes Schindelin
2016-10-09 10:45                 ` Johannes Sixt
2016-09-11 10:55   ` [PATCH v2 21/25] sequencer: refactor write_message() Johannes Schindelin
2016-09-11 23:38     ` Junio C Hamano
2016-09-12  8:35     ` Johannes Sixt
2016-09-15 19:21       ` Junio C Hamano
2016-10-05 13:08         ` Johannes Schindelin
2016-09-11 10:55   ` [PATCH v2 22/25] sequencer: remove overzealous assumption in rebase -i mode Johannes Schindelin
2016-09-11 23:35     ` Junio C Hamano
2016-09-11 10:55   ` [PATCH v2 23/25] sequencer: mark action_name() for translation Johannes Schindelin
2016-09-11 10:55   ` [PATCH v2 24/25] sequencer: quote filenames in error messages Johannes Schindelin
2016-09-11 23:33     ` Junio C Hamano
2016-10-06 13:41       ` Johannes Schindelin
2016-09-11 10:56   ` [PATCH v2 25/25] sequencer: remove bogus hint for translators Johannes Schindelin
2016-09-11 23:30     ` Junio C Hamano
2016-10-06 14:18       ` Johannes Schindelin
2016-10-10 17:24   ` [PATCH v3 00/25] Prepare the sequencer for the upcoming rebase -i patches Johannes Schindelin
2016-10-10 17:24     ` [PATCH v3 01/25] sequencer: use static initializers for replay_opts Johannes Schindelin
2016-10-10 22:14       ` Junio C Hamano
2016-10-10 17:24     ` [PATCH v3 02/25] sequencer: use memoized sequencer directory path Johannes Schindelin
2016-10-10 17:24     ` [PATCH v3 03/25] sequencer: avoid unnecessary indirection Johannes Schindelin
2016-10-10 22:14       ` Junio C Hamano
2016-10-10 17:24     ` [PATCH v3 04/25] sequencer: future-proof remove_sequencer_state() Johannes Schindelin
2016-10-10 17:24     ` [PATCH v3 05/25] sequencer: eventually release memory allocated for the option values Johannes Schindelin
2016-10-10 22:18       ` Junio C Hamano
2016-10-11 10:07         ` Johannes Schindelin
2016-10-11 16:30         ` Junio C Hamano
2016-10-12 12:06           ` Johannes Schindelin
2016-10-12 18:20             ` Re* " Junio C Hamano
2016-10-13 10:51               ` Johannes Schindelin
2016-10-10 17:24     ` [PATCH v3 06/25] sequencer: future-proof read_populate_todo() Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 07/25] sequencer: completely revamp the "todo" script parsing Johannes Schindelin
2016-10-10 22:13       ` Junio C Hamano
2016-10-11 10:20         ` Johannes Schindelin
2016-10-11 10:22           ` Johannes Schindelin
2016-10-11 10:55             ` Johannes Schindelin
2016-10-11 16:58               ` Junio C Hamano
2016-10-11 16:54           ` Junio C Hamano
2016-10-15 17:03       ` Torsten Bögershausen
2016-10-15 17:19         ` Jeff King
2016-10-15 17:40           ` Torsten Bögershausen
2016-10-15 17:46             ` Jeff King
2016-10-16  8:09               ` Johannes Schindelin
2016-10-16 19:42                 ` Jeff King
2016-10-17  8:37                   ` Johannes Schindelin
2016-10-17  9:36                     ` Jeff King
2016-10-10 17:25     ` [PATCH v3 08/25] sequencer: strip CR from the todo script Johannes Schindelin
2016-10-11 18:54       ` Junio C Hamano
2016-10-12 11:46         ` Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 09/25] sequencer: avoid completely different messages for different actions Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 10/25] sequencer: get rid of the subcommand field Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 11/25] sequencer: refactor the code to obtain a short commit name Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 12/25] sequencer: remember the onelines when parsing the todo file Johannes Schindelin
2016-10-11 19:07       ` Junio C Hamano
2016-10-12 11:49         ` Johannes Schindelin
2016-10-12 16:24           ` Junio C Hamano
2016-10-13 10:41             ` Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 13/25] sequencer: prepare for rebase -i's commit functionality Johannes Schindelin
2016-10-11 19:17       ` Junio C Hamano
2016-10-12 12:00         ` Johannes Schindelin
2016-10-12 16:55           ` Junio C Hamano
2016-10-13 10:50             ` Johannes Schindelin
2016-10-14 16:41               ` Junio C Hamano
2016-10-10 17:25     ` [PATCH v3 14/25] sequencer: introduce a helper to read files written by scripts Johannes Schindelin
2016-10-17 17:17       ` Junio C Hamano
2016-10-18 11:42         ` Johannes Schindelin
2016-10-18 15:54           ` Junio C Hamano
2016-10-20 12:07             ` Johannes Schindelin
2016-10-10 17:25     ` [PATCH v3 15/25] sequencer: allow editing the commit message on a case-by-case basis Johannes Schindelin
2016-10-17 17:18       ` Junio C Hamano
2016-10-10 17:25     ` [PATCH v3 16/25] sequencer: support amending commits Johannes Schindelin
2016-10-17 17:22       ` Junio C Hamano
2016-10-18 11:53         ` Johannes Schindelin
2016-10-18 15:56           ` Junio C Hamano
2016-10-10 17:26     ` [PATCH v3 17/25] sequencer: support cleaning up commit messages Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 18/25] sequencer: do not try to commit when there were merge conflicts Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 19/25] sequencer: left-trim lines read from the script Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 20/25] sequencer: refactor write_message() Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 21/25] sequencer: remove overzealous assumption in rebase -i mode Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 22/25] sequencer: mark action_name() for translation Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 23/25] sequencer: quote filenames in error messages Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 24/25] sequencer: start error messages consistently with lower case Johannes Schindelin
2016-10-10 17:26     ` [PATCH v3 25/25] sequencer: mark all error messages for translation Johannes Schindelin
2016-10-12 20:46       ` Johannes Sixt
2016-10-12 21:24         ` Junio C Hamano
2016-10-13 14:56           ` Johannes Schindelin
2016-10-13 20:35             ` Johannes Sixt
2016-10-14 13:15     ` [PATCH v4 00/25] Prepare the sequencer for the upcoming rebase -i patches Johannes Schindelin
2016-10-14 13:15       ` [PATCH v4 01/25] sequencer: use static initializers for replay_opts Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 02/25] sequencer: use memoized sequencer directory path Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 03/25] sequencer: avoid unnecessary indirection Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 04/25] sequencer: future-proof remove_sequencer_state() Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 05/25] sequencer: eventually release memory allocated for the option values Johannes Schindelin
2016-10-17 19:06         ` Junio C Hamano
2016-10-18 12:03           ` Johannes Schindelin
2016-10-19  1:12             ` Junio C Hamano
2016-10-20 12:16               ` Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 06/25] sequencer: future-proof read_populate_todo() Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 07/25] sequencer: refactor the code to obtain a short commit name Johannes Schindelin
2016-10-14 13:17       ` Johannes Schindelin [this message]
2016-10-17 22:33         ` [PATCH v4 08/25] sequencer: completely revamp the "todo" script parsing Junio C Hamano
2016-10-18 12:25           ` Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 09/25] sequencer: strip CR from the todo script Johannes Schindelin
2016-10-14 13:17       ` [PATCH v4 10/25] sequencer: avoid completely different messages for different actions Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 11/25] sequencer: get rid of the subcommand field Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 12/25] sequencer: remember the onelines when parsing the todo file Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 13/25] sequencer: prepare for rebase -i's commit functionality Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 14/25] sequencer: introduce a helper to read files written by scripts Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 15/25] sequencer: allow editing the commit message on a case-by-case basis Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 16/25] sequencer: support amending commits Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 17/25] sequencer: support cleaning up commit messages Johannes Schindelin
2016-10-20 20:06         ` Junio C Hamano
2016-10-14 13:18       ` [PATCH v4 18/25] sequencer: do not try to commit when there were merge conflicts Johannes Schindelin
2016-10-20 20:11         ` Junio C Hamano
2016-10-21 11:10           ` Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 19/25] sequencer: left-trim lines read from the script Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 20/25] sequencer: refactor write_message() Johannes Schindelin
2016-10-20 20:22         ` Junio C Hamano
2016-10-20 20:26           ` Junio C Hamano
2016-10-21 11:43             ` Johannes Schindelin
2016-10-21 15:40               ` Junio C Hamano
2016-10-23  9:29                 ` Johannes Schindelin
2016-10-14 13:18       ` [PATCH v4 21/25] sequencer: remove overzealous assumption in rebase -i mode Johannes Schindelin
2016-10-14 13:19       ` [PATCH v4 22/25] sequencer: mark action_name() for translation Johannes Schindelin
2016-10-14 13:19       ` [PATCH v4 23/25] sequencer: quote filenames in error messages Johannes Schindelin
2016-10-20 20:27         ` Junio C Hamano
2016-10-20 20:28           ` Junio C Hamano
2016-10-14 13:19       ` [PATCH v4 24/25] sequencer: start error messages consistently with lower case Johannes Schindelin
2016-10-14 13:19       ` [PATCH v4 25/25] sequencer: mark all error messages for translation Johannes Schindelin
2016-10-17 19:08       ` [PATCH v4 00/25] Prepare the sequencer for the upcoming rebase -i patches Junio C Hamano
2016-10-21 12:23       ` [PATCH v5 00/27] " Johannes Schindelin
2016-10-21 12:23         ` [PATCH v5 01/27] sequencer: use static initializers for replay_opts Johannes Schindelin
2016-10-21 12:23         ` [PATCH v5 02/27] sequencer: use memoized sequencer directory path Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 03/27] sequencer: avoid unnecessary indirection Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 04/27] sequencer: future-proof remove_sequencer_state() Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 05/27] sequencer: plug memory leaks for the option values Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 06/27] sequencer: future-proof read_populate_todo() Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 07/27] sequencer: refactor the code to obtain a short commit name Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 08/27] sequencer: completely revamp the "todo" script parsing Johannes Schindelin
2016-11-06 14:05           ` Lars Schneider
2016-10-21 12:24         ` [PATCH v5 09/27] sequencer: strip CR from the todo script Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 10/27] sequencer: avoid completely different messages for different actions Johannes Schindelin
2016-10-21 12:24         ` [PATCH v5 11/27] sequencer: get rid of the subcommand field Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 12/27] sequencer: remember the onelines when parsing the todo file Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 13/27] sequencer: prepare for rebase -i's commit functionality Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 14/27] sequencer: introduce a helper to read files written by scripts Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 15/27] sequencer: allow editing the commit message on a case-by-case basis Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 16/27] sequencer: support amending commits Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 17/27] sequencer: support cleaning up commit messages Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 18/27] sequencer: left-trim lines read from the script Johannes Schindelin
2016-10-21 12:25         ` [PATCH v5 19/27] sequencer: stop releasing the strbuf in write_message() Johannes Schindelin
2016-10-21 18:30           ` Junio C Hamano
2016-10-21 12:26         ` [PATCH v5 20/27] sequencer: roll back lock file if write_message() failed Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 21/27] sequencer: refactor write_message() to take a pointer/length Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 22/27] sequencer: teach write_message() to append an optional LF Johannes Schindelin
2016-10-21 18:32           ` Junio C Hamano
2016-10-23  9:34             ` Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 23/27] sequencer: remove overzealous assumption in rebase -i mode Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 24/27] sequencer: mark action_name() for translation Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 25/27] sequencer: quote filenames in error messages Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 26/27] sequencer: start error messages consistently with lower case Johannes Schindelin
2016-10-21 12:26         ` [PATCH v5 27/27] sequencer: mark all error messages for translation Johannes Schindelin
2016-10-21 18:40         ` [PATCH v5 00/27] Prepare the sequencer for the upcoming rebase -i patches Junio C Hamano
2016-10-23  9:50           ` Johannes Schindelin
2016-10-24 20:00             ` Junio C Hamano
2016-10-22 17:11         ` Junio C Hamano
2016-10-23  9:54           ` Johannes Schindelin
2016-10-23  9:58             ` Johannes Schindelin
2016-10-24 12:24             ` Max Horn
2016-10-24 14:02               ` Johannes Schindelin
2016-10-24 20:03             ` Junio C Hamano
2016-10-24 19:36           ` Stefan Beller
2016-10-24 20:16             ` Junio C Hamano

Reply instructions:

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

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

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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=a5f5d784fcacc16555237b9750380d612387d0cb.1476450940.git.johannes.schindelin@gmx.de \
    --to=johannes.schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=j6t@kdbg.org \
    --cc=jnareb@gmail.com \
    --cc=ramsay@ramsayjones.plus.com \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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