All of lore.kernel.org
 help / color / mirror / Atom feed
From: Elijah Newren <newren@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Elijah Newren <newren@gmail.com>
Subject: [PATCH v2 07/20] Use write_index_as_tree() in lieu of write_tree_from_memory()
Date: Fri, 26 Jul 2019 08:52:45 -0700	[thread overview]
Message-ID: <20190726155258.28561-8-newren@gmail.com> (raw)
In-Reply-To: <20190726155258.28561-1-newren@gmail.com>

write_tree_from_memory() appeared to be a merge-recursive special that
basically duplicated write_index_as_tree().  The two had a slightly
different call structure but the big difference was just that
write_index_as_tree() would always unconditionally read the index off of
disk instead of working on the current in-memory index.  Add a flag to
allow using the in-memory index, and then switch over to
write_index_as_tree().

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 builtin/checkout.c |  6 +++++-
 cache-tree.c       | 36 +++++++++++++++++++++++-------------
 cache-tree.h       |  3 ++-
 merge-recursive.c  | 42 +++++++++---------------------------------
 merge-recursive.h  |  1 -
 5 files changed, 39 insertions(+), 49 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 20e38c5edc..a7b6454061 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -709,6 +709,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			 * whether the merge flag was used.
 			 */
 			struct tree *work;
+			struct object_id work_oid;
 			struct tree *old_tree;
 			struct merge_options o;
 			struct strbuf sb = STRBUF_INIT;
@@ -759,7 +760,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			 */
 			init_merge_options(&o, the_repository);
 			o.verbosity = 0;
-			work = write_tree_from_memory(&o);
+			if (write_index_as_tree(&work_oid, &the_index, NULL,
+					WRITE_TREE_FROM_MEMORY, NULL) ||
+			    !(work = lookup_tree(the_repository, &work_oid)))
+				die(_("error building trees"));
 
 			ret = reset_tree(new_tree,
 					 opts, 1,
diff --git a/cache-tree.c b/cache-tree.c
index 706ffcf188..99144b1704 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -613,14 +613,19 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
 	int entries, was_valid;
 	struct lock_file lock_file = LOCK_INIT;
 	int ret = 0;
+	int access_disk = !(flags & WRITE_TREE_FROM_MEMORY);
 
-	hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
+	if (access_disk) {
+		hold_lock_file_for_update(&lock_file, index_path,
+					  LOCK_DIE_ON_ERROR);
 
-	entries = read_index_from(index_state, index_path, get_git_dir());
-	if (entries < 0) {
-		ret = WRITE_TREE_UNREADABLE_INDEX;
-		goto out;
+		entries = read_index_from(index_state, index_path, get_git_dir());
+		if (entries < 0) {
+			ret = WRITE_TREE_UNREADABLE_INDEX;
+			goto out;
+		}
 	}
+
 	if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
 		cache_tree_free(&index_state->cache_tree);
 
@@ -633,13 +638,16 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
 			ret = WRITE_TREE_UNMERGED_INDEX;
 			goto out;
 		}
-		write_locked_index(index_state, &lock_file, COMMIT_LOCK);
-		/* Not being able to write is fine -- we are only interested
-		 * in updating the cache-tree part, and if the next caller
-		 * ends up using the old index with unupdated cache-tree part
-		 * it misses the work we did here, but that is just a
-		 * performance penalty and not a big deal.
-		 */
+		if (access_disk) {
+			write_locked_index(index_state, &lock_file, COMMIT_LOCK);
+			/* Not being able to write is fine -- we are only
+			 * interested in updating the cache-tree part, and if
+			 * the next caller ends up using the old index with
+			 * unupdated cache-tree part it misses the work we
+			 * did here, but that is just a performance penalty
+			 * and not a big deal.
+			 */
+		}
 	}
 
 	if (prefix) {
@@ -655,7 +663,9 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
 		oidcpy(oid, &index_state->cache_tree->oid);
 
 out:
-	rollback_lock_file(&lock_file);
+	if (access_disk)
+		rollback_lock_file(&lock_file);
+
 	return ret;
 }
 
diff --git a/cache-tree.h b/cache-tree.h
index 757bbc48bc..481ec45dfa 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -34,12 +34,13 @@ int cache_tree_fully_valid(struct cache_tree *);
 int cache_tree_update(struct index_state *, int);
 void cache_tree_verify(struct repository *, struct index_state *);
 
-/* bitmasks to write_cache_as_tree flags */
+/* bitmasks to write_index_as_tree flags */
 #define WRITE_TREE_MISSING_OK 1
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
 #define WRITE_TREE_DRY_RUN 4
 #define WRITE_TREE_SILENT 8
 #define WRITE_TREE_REPAIR 16
+#define WRITE_TREE_FROM_MEMORY 32
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
diff --git a/merge-recursive.c b/merge-recursive.c
index 308e350ff1..6c38c02e3f 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -412,37 +412,6 @@ static void unpack_trees_finish(struct merge_options *opt)
 	clear_unpack_trees_porcelain(&opt->unpack_opts);
 }
 
-struct tree *write_tree_from_memory(struct merge_options *opt)
-{
-	struct tree *result = NULL;
-	struct index_state *istate = opt->repo->index;
-
-	if (unmerged_index(istate)) {
-		int i;
-		fprintf(stderr, "BUG: There are unmerged index entries:\n");
-		for (i = 0; i < istate->cache_nr; i++) {
-			const struct cache_entry *ce = istate->cache[i];
-			if (ce_stage(ce))
-				fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
-					(int)ce_namelen(ce), ce->name);
-		}
-		BUG("unmerged index entries in merge-recursive.c");
-	}
-
-	if (!istate->cache_tree)
-		istate->cache_tree = cache_tree();
-
-	if (!cache_tree_fully_valid(istate->cache_tree) &&
-	    cache_tree_update(istate, 0) < 0) {
-		err(opt, _("error building trees"));
-		return NULL;
-	}
-
-	result = lookup_tree(opt->repo, &istate->cache_tree->oid);
-
-	return result;
-}
-
 static int save_files_dirs(const struct object_id *oid,
 			   struct strbuf *base, const char *path,
 			   unsigned int mode, int stage, void *context)
@@ -3471,8 +3440,15 @@ static int merge_trees_internal(struct merge_options *opt,
 
 	unpack_trees_finish(opt);
 
-	if (opt->call_depth && !(*result = write_tree_from_memory(opt)))
-		return -1;
+	if (opt->call_depth) {
+		struct object_id tree_id;
+		if (write_index_as_tree(&tree_id, opt->repo->index, NULL,
+					WRITE_TREE_FROM_MEMORY, NULL) ||
+		    !(*result = lookup_tree(opt->repo, &tree_id))) {
+			err(opt, _("error building trees"));
+			return -1;
+		}
+	}
 
 	return clean;
 }
diff --git a/merge-recursive.h b/merge-recursive.h
index 812c456f1b..b3394502c7 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -109,7 +109,6 @@ int merge_recursive_generic(struct merge_options *o,
 
 void init_merge_options(struct merge_options *o,
 			struct repository *repo);
-struct tree *write_tree_from_memory(struct merge_options *o);
 
 int parse_merge_opt(struct merge_options *out, const char *s);
 
-- 
2.22.0.550.g71c37a0928.dirty


  parent reply	other threads:[~2019-07-26 15:53 UTC|newest]

Thread overview: 157+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-25 17:45 [PATCH 00/19] Cleanup merge API Elijah Newren
2019-07-25 17:45 ` [PATCH 01/19] merge-recursive: fix minor memory leak in error condition Elijah Newren
2019-07-25 17:45 ` [PATCH 02/19] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-07-25 17:45 ` [PATCH 03/19] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-07-25 19:41   ` Johannes Schindelin
2019-07-25 19:58     ` Elijah Newren
2019-07-26 11:23       ` Johannes Schindelin
2019-07-25 17:45 ` [PATCH 04/19] merge-recursive: exit early if index != head Elijah Newren
2019-07-25 19:51   ` Johannes Schindelin
2019-07-25 20:12     ` Elijah Newren
2019-07-25 17:45 ` [PATCH 05/19] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-07-25 17:45 ` [PATCH 06/19] Change call signature of write_tree_from_memory() Elijah Newren
2019-07-25 19:55   ` Johannes Schindelin
2019-07-26  4:58     ` Elijah Newren
2019-07-25 17:45 ` [PATCH 07/19] Move write_tree_from_memory() from merge-recursive to cache-tree Elijah Newren
2019-07-25 17:46 ` [PATCH 08/19] merge-recursive: fix some overly long lines Elijah Newren
2019-07-25 17:46 ` [PATCH 09/19] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-07-25 17:46 ` [PATCH 10/19] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-07-25 20:02   ` Johannes Schindelin
2019-07-25 17:46 ` [PATCH 11/19] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-07-25 17:46 ` [PATCH 12/19] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-07-25 17:46 ` [PATCH 13/19] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-07-25 17:46 ` [PATCH 14/19] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-07-25 17:46 ` [PATCH 15/19] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-07-25 20:12   ` Johannes Schindelin
2019-07-25 20:27     ` Elijah Newren
2019-07-26 11:25       ` Johannes Schindelin
2019-07-26 15:30         ` Elijah Newren
2019-07-25 17:46 ` [PATCH 16/19] merge-recursive: alphabetize include list Elijah Newren
2019-07-25 17:46 ` [PATCH 17/19] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-07-25 17:46 ` [PATCH 18/19] merge-recursive: be consistent with assert Elijah Newren
2019-07-25 17:46 ` [PATCH 19/19] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-07-25 20:28   ` Johannes Schindelin
2019-07-25 18:12 ` [PATCH 00/19] Cleanup merge API Junio C Hamano
2019-07-25 19:06   ` Elijah Newren
2019-07-25 22:50     ` Junio C Hamano
2019-07-26 14:07       ` Johannes Schindelin
2019-07-25 19:15 ` Johannes Schindelin
2019-07-26 15:15   ` Elijah Newren
2019-07-26 15:52 ` [PATCH v2 00/20] " Elijah Newren
2019-07-26 15:52   ` [PATCH v2 01/20] merge-recursive: fix minor memory leak in error condition Elijah Newren
2019-07-26 18:31     ` Junio C Hamano
2019-07-26 23:19       ` Elijah Newren
2019-07-29 14:13       ` Derrick Stolee
2019-07-26 15:52   ` [PATCH v2 02/20] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-07-26 18:42     ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 03/20] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-07-26 19:14     ` Junio C Hamano
2019-07-26 23:22       ` Elijah Newren
2019-07-26 15:52   ` [PATCH v2 04/20] merge-recursive: exit early if index != head Elijah Newren
2019-07-26 19:32     ` Junio C Hamano
2019-07-26 23:26       ` Elijah Newren
2019-07-29 15:56         ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 05/20] merge-recursive: remove useless parameter in merge_trees() Elijah Newren
2019-07-26 19:37     ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 06/20] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-07-26 19:57     ` Junio C Hamano
2019-07-26 23:28       ` Elijah Newren
2019-07-26 15:52   ` Elijah Newren [this message]
2019-07-26 20:11     ` [PATCH v2 07/20] Use write_index_as_tree() in lieu of write_tree_from_memory() Junio C Hamano
2019-07-26 23:39       ` Elijah Newren
2019-07-29  4:46         ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 08/20] merge-recursive: fix some overly long lines Elijah Newren
2019-07-26 15:52   ` [PATCH v2 09/20] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-07-26 15:52   ` [PATCH v2 10/20] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-07-26 15:52   ` [PATCH v2 11/20] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-07-26 15:52   ` [PATCH v2 12/20] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-07-26 15:52   ` [PATCH v2 13/20] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-07-26 15:52   ` [PATCH v2 14/20] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-07-26 15:52   ` [PATCH v2 15/20] merge-recursive: avoid losing output and leaking memory holding that output Elijah Newren
2019-07-26 15:52   ` [PATCH v2 16/20] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-07-26 15:52   ` [PATCH v2 17/20] merge-recursive: alphabetize include list Elijah Newren
2019-07-26 15:52   ` [PATCH v2 18/20] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-07-26 15:52   ` [PATCH v2 19/20] merge-recursive: be consistent with assert Elijah Newren
2019-07-26 15:52   ` [PATCH v2 20/20] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-08-15 21:40   ` [PATCH v3 00/24] Clean up merge API Elijah Newren
2019-08-15 21:40     ` [PATCH v3 01/24] merge-recursive: be consistent with assert Elijah Newren
2019-08-15 21:40     ` [PATCH v3 02/24] checkout: provide better conflict hunk description with detached HEAD Elijah Newren
2019-08-15 21:40     ` [PATCH v3 03/24] merge-recursive: enforce opt->ancestor != NULL when calling merge_trees() Elijah Newren
2019-08-16 21:05       ` Junio C Hamano
2019-08-15 21:40     ` [PATCH v3 04/24] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-08-16 21:33       ` Junio C Hamano
2019-08-16 22:39         ` Elijah Newren
2019-08-15 21:40     ` [PATCH v3 05/24] merge-recursive: introduce an enum for detect_directory_renames values Elijah Newren
2019-08-15 21:40     ` [PATCH v3 06/24] merge-recursive: future-proof update_file_flags() against memory leaks Elijah Newren
2019-08-15 21:40     ` [PATCH v3 07/24] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-08-15 21:40     ` [PATCH v3 08/24] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-08-15 21:40     ` [PATCH v3 09/24] merge-recursive: exit early if index != head Elijah Newren
2019-08-15 21:40     ` [PATCH v3 10/24] merge-recursive: remove useless parameter in merge_trees() Elijah Newren
2019-08-15 21:40     ` [PATCH v3 11/24] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-08-15 21:40     ` [PATCH v3 12/24] cache-tree: share code between functions writing an index as a tree Elijah Newren
2019-08-16 22:01       ` Junio C Hamano
2019-08-16 22:39         ` Elijah Newren
2019-08-15 21:40     ` [PATCH v3 13/24] merge-recursive: fix some overly long lines Elijah Newren
2019-08-15 21:40     ` [PATCH v3 14/24] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-08-15 21:40     ` [PATCH v3 15/24] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-08-15 21:40     ` [PATCH v3 16/24] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-08-15 21:40     ` [PATCH v3 17/24] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-08-15 21:40     ` [PATCH v3 18/24] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-08-16 22:14       ` Junio C Hamano
2019-08-16 22:59         ` Elijah Newren
2019-08-16 23:24           ` Junio C Hamano
2019-08-15 21:40     ` [PATCH v3 19/24] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-08-15 21:40     ` [PATCH v3 20/24] merge-recursive: avoid losing output and leaking memory holding that output Elijah Newren
2019-08-15 21:40     ` [PATCH v3 21/24] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-08-16 21:19       ` SZEDER Gábor
2019-08-16 23:00         ` Elijah Newren
2019-08-16 22:17       ` Junio C Hamano
2019-08-15 21:40     ` [PATCH v3 22/24] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-08-15 21:40     ` [PATCH v3 23/24] merge-recursive: add sanity checks for relevant merge_options Elijah Newren
2019-08-16 19:52       ` Junio C Hamano
2019-08-16 22:08         ` Elijah Newren
2019-08-16 23:15           ` Junio C Hamano
2019-08-16 19:59       ` Junio C Hamano
2019-08-16 22:09         ` Elijah Newren
2019-08-15 21:40     ` [PATCH v3 24/24] merge-recursive: alphabetize include list Elijah Newren
2019-08-17 18:41     ` [PATCH v4 00/24] Clean up merge API Elijah Newren
2019-08-17 18:41       ` [PATCH v4 01/24] merge-recursive: be consistent with assert Elijah Newren
2019-08-17 18:41       ` [PATCH v4 02/24] checkout: provide better conflict hunk description with detached HEAD Elijah Newren
2019-08-17 18:41       ` [PATCH v4 03/24] merge-recursive: enforce opt->ancestor != NULL when calling merge_trees() Elijah Newren
2019-08-17 18:41       ` [PATCH v4 04/24] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-09-30 21:14         ` Jeff King
2019-09-30 21:19           ` Jeff King
2019-09-30 22:54           ` [PATCH] merge-recursive: fix the diff3 common ancestor label for virtual commits Elijah Newren
2019-10-01  6:56             ` Elijah Newren
2019-10-01  6:58             ` [PATCH v2] " Elijah Newren
2019-10-01 14:49               ` Jeff King
2019-10-01 18:17                 ` [PATCH v3] " Elijah Newren
2019-10-07  2:51                   ` Junio C Hamano
2019-10-07 15:52                     ` [PATCH] merge-recursive: fix the fix to the diff3 common ancestor label Elijah Newren
2019-10-08  2:32                       ` Junio C Hamano
2019-10-08  2:36                       ` Junio C Hamano
2019-10-08 16:16                         ` Elijah Newren
2019-08-17 18:41       ` [PATCH v4 05/24] merge-recursive: introduce an enum for detect_directory_renames values Elijah Newren
2019-08-17 18:41       ` [PATCH v4 06/24] merge-recursive: future-proof update_file_flags() against memory leaks Elijah Newren
2019-08-17 18:41       ` [PATCH v4 07/24] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-08-17 18:41       ` [PATCH v4 08/24] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-09-02 23:01         ` Johannes Schindelin
2019-09-03 13:34           ` Johannes Schindelin
2019-09-03 18:17             ` Elijah Newren
2019-08-17 18:41       ` [PATCH v4 09/24] merge-recursive: exit early if index != head Elijah Newren
2019-08-17 18:41       ` [PATCH v4 10/24] merge-recursive: remove useless parameter in merge_trees() Elijah Newren
2019-08-17 18:41       ` [PATCH v4 11/24] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-08-17 18:41       ` [PATCH v4 12/24] cache-tree: share code between functions writing an index as a tree Elijah Newren
2019-08-17 18:41       ` [PATCH v4 13/24] merge-recursive: fix some overly long lines Elijah Newren
2019-08-17 18:41       ` [PATCH v4 14/24] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-08-17 18:41       ` [PATCH v4 15/24] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-08-17 18:41       ` [PATCH v4 16/24] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-08-17 18:41       ` [PATCH v4 17/24] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-08-17 18:41       ` [PATCH v4 18/24] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-08-17 18:41       ` [PATCH v4 19/24] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-08-17 18:41       ` [PATCH v4 20/24] merge-recursive: avoid losing output and leaking memory holding that output Elijah Newren
2019-08-17 18:41       ` [PATCH v4 21/24] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-08-19 17:17         ` Junio C Hamano
2019-08-17 18:41       ` [PATCH v4 22/24] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-08-17 18:41       ` [PATCH v4 23/24] merge-recursive: add sanity checks for relevant merge_options Elijah Newren
2019-08-17 18:41       ` [PATCH v4 24/24] merge-recursive: alphabetize include list Elijah Newren

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20190726155258.28561-8-newren@gmail.com \
    --to=newren@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

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

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