aboutsummaryrefslogtreecommitdiff
path: root/git-remote-notmuch.c
diff options
context:
space:
mode:
authorDavid Bremner <david@tethera.net>2026-01-25 07:56:37 +0900
committerDavid Bremner <david@tethera.net>2026-02-16 07:24:18 +0900
commitcfc4af0e2bdf8f82ad14342baa6578d4dd366cd9 (patch)
treeb0bf98718b8ab5663d811bc0df6e3347b1db910f /git-remote-notmuch.c
parentfcc41c82c4596aef1598eb9ea52c4b0cb4bb3c53 (diff)
cli/git-remote: add import command
The output in default.import is based on a modified version of Felipe's git-remote-nm with Blake2 hashing replaced by SHA1 (for portability). This enable fetch/pull/clone, so test that as well.
Diffstat (limited to 'git-remote-notmuch.c')
-rw-r--r--git-remote-notmuch.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/git-remote-notmuch.c b/git-remote-notmuch.c
index fb5cfd55..bfd045a8 100644
--- a/git-remote-notmuch.c
+++ b/git-remote-notmuch.c
@@ -157,6 +157,30 @@ read_lastmod (const char *dir, char **uuid_out, unsigned long *counter_out)
}
static void
+store_lastmod (notmuch_database_t *notmuch, const char *dir)
+{
+ char *filename = NULL;
+ FILE *out;
+ unsigned long lastmod;
+ const char *uuid;
+
+ ASSERT (filename = talloc_asprintf (notmuch, "%s/lastmod", dir));
+
+ out = fopen (filename, "w");
+ ensure (out, "error opening %s for writing: %s", filename, strerror (errno));
+
+ lastmod = notmuch_database_get_revision (notmuch, &uuid);
+ ASSERT (fprintf (out, "%s\t%zu\n", uuid, lastmod) > 0);
+}
+
+static void
+write_data (const char *data)
+{
+ printf ("data %zu\n", strlen (data));
+ fputs (data, stdout);
+}
+
+static void
cmd_capabilities ()
{
fputs ("import\nexport\nrefspec refs/heads/*:refs/notmuch/*\n\n", stdout);
@@ -175,6 +199,91 @@ cmd_list (notmuch_database_t *db, const char *uuid, unsigned long lastmod)
equal_lastmod (uuid, lastmod, db_uuid, db_lastmod) ? " unchanged" : "");
}
+static void
+cmd_import (notmuch_database_t *notmuch,
+ const char *nm_dir,
+ const char *uuid,
+ unsigned long lastmod)
+{
+ const char *ident = NULL;
+ const char *lastmod_str = NULL;
+ notmuch_messages_t *messages;
+ notmuch_status_t status;
+ notmuch_query_t *query;
+ char *mid_buf = NULL;
+ size_t mid_buf_len = 0;
+
+ ident = talloc_asprintf (notmuch, "%s <%s> %zu +0000",
+ notmuch_config_get (notmuch, NOTMUCH_CONFIG_USER_NAME),
+ notmuch_config_get (notmuch, NOTMUCH_CONFIG_PRIMARY_EMAIL),
+ time (NULL));
+
+
+ printf ("feature done\ncommit refs/notmuch/master\nmark :1\ncommitter %s\n", ident);
+
+ ASSERT (lastmod_str = talloc_asprintf (notmuch, "lastmod: %zu\n", lastmod));
+ write_data (lastmod_str);
+ if (uuid)
+ puts ("from refs/notmuch/master^0");
+
+ /* don't send deleteall here, as there may be other files in the
+ * repo outside the database prefix */
+
+ status = notmuch_query_create_with_syntax (notmuch,
+ "",
+ NOTMUCH_QUERY_SYNTAX_XAPIAN,
+ &query);
+
+ if (print_status_database ("git-remote-nm", notmuch, status))
+ exit (EXIT_FAILURE);
+
+ if (debug_flags && strchr (debug_flags, 's'))
+ notmuch_query_set_sort (query, NOTMUCH_SORT_NEWEST_FIRST);
+ else
+ notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED);
+
+ status = notmuch_query_search_messages (query, &messages);
+ if (print_status_query ("git-remote-nm", query, status))
+ exit (EXIT_FAILURE);
+
+ for (;
+ notmuch_messages_valid (messages);
+ notmuch_messages_move_to_next (messages)) {
+ const char *tag_buf = "";
+ const char *mid;
+ const char *hash;
+ const char *prefix = notmuch_config_get (notmuch, NOTMUCH_CONFIG_GIT_METADATA_PREFIX);
+ int ret;
+
+ notmuch_message_t *message = notmuch_messages_get (messages);
+ mid = notmuch_message_get_message_id (message);
+
+ ret = hex_encode (notmuch, mid, &mid_buf, &mid_buf_len);
+ ensure (ret == HEX_SUCCESS, "failed to hex-encode message-id %s\n", mid);
+
+ /* we can't use _notmuch_sha1_from_string because we don't want
+ * to include the null terminator */
+ g_autoptr (GChecksum) sha1 = NULL;
+ sha1 = g_checksum_new (G_CHECKSUM_SHA1);
+ g_checksum_update (sha1, (const guchar *) mid, strlen (mid));
+ hash = g_checksum_get_string (sha1);
+ printf ("M 644 inline %s/%2.2s/%2.2s/%s/tags\n", prefix, hash, hash + 2, mid_buf);
+
+ for (notmuch_tags_t *tags = notmuch_message_get_tags (message);
+ notmuch_tags_valid (tags);
+ notmuch_tags_move_to_next (tags)) {
+ const char *tag_str = notmuch_tags_get (tags);
+ ASSERT (tag_buf = talloc_asprintf (message, "%s%s\n", tag_buf, tag_str));
+ }
+ write_data (tag_buf);
+ notmuch_message_destroy (message);
+ }
+ puts ("");
+ puts ("done");
+ fflush (stdout);
+ store_lastmod (notmuch, nm_dir);
+}
+
/* stubs since we cannot link with notmuch.o */
const notmuch_opt_desc_t notmuch_shared_options[] = {
{ }
@@ -303,6 +412,8 @@ main (int argc, char *argv[])
if (STRNCMP_LITERAL (s, "capabilities") == 0)
cmd_capabilities ();
+ else if (STRNCMP_LITERAL (s, "import") == 0)
+ cmd_import (db, nm_dir, uuid, lastmod);
else if (STRNCMP_LITERAL (s, "list") == 0)
cmd_list (db, uuid, lastmod);