NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
notmuch.c File Reference

Notmuch virtual mailbox type. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <notmuch.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "hcache/lib.h"
#include "index/lib.h"
#include "maildir/lib.h"
#include "progress/lib.h"
#include "adata.h"
#include "command_parse.h"
#include "edata.h"
#include "maildir/edata.h"
#include "mdata.h"
#include "mutt_commands.h"
#include "mutt_globals.h"
#include "mutt_thread.h"
#include "mx.h"
#include "protos.h"
#include "query.h"
#include "tag.h"
#include <libintl.h>
+ Include dependency graph for notmuch.c:

Go to the source code of this file.

Functions

void nm_init (void)
 Setup feature commands. More...
 
static struct HeaderCachenm_hcache_open (struct Mailbox *m)
 Open a header cache. More...
 
static void nm_hcache_close (struct HeaderCache *h)
 Close the header cache. More...
 
static char * nm_get_default_url (void)
 Create a Mailbox with default Notmuch settings. More...
 
static struct NmMboxDatanm_get_default_data (void)
 Create a Mailbox with default Notmuch settings. More...
 
static int init_mailbox (struct Mailbox *m)
 Add Notmuch data to the Mailbox. More...
 
static char * email_get_id (struct Email *e)
 Get the unique Notmuch Id. More...
 
static char * email_get_fullpath (struct Email *e, char *buf, size_t buflen)
 Get the full path of an email. More...
 
static void query_window_reset (void)
 Restore vfolder's search window to its original position. More...
 
static bool windowed_query_from_query (const char *query, char *buf, size_t buflen)
 transforms a vfolder search query into a windowed one More...
 
static char * get_query_string (struct NmMboxData *mdata, bool window)
 builds the notmuch vfolder search string More...
 
static int get_limit (struct NmMboxData *mdata)
 Get the database limit. More...
 
static void apply_exclude_tags (notmuch_query_t *query)
 Exclude the configured tags. More...
 
static notmuch_query_t * get_query (struct Mailbox *m, bool writable)
 Create a new query. More...
 
static int update_email_tags (struct Email *e, notmuch_message_t *msg)
 Update the Email's tags from Notmuch. More...
 
static int update_message_path (struct Email *e, const char *path)
 Set the path for a message. More...
 
static char * get_folder_from_path (const char *path)
 Find an email's folder from its path. More...
 
static char * nm2mutt_message_id (const char *id)
 converts notmuch message Id to neomutt message Id More...
 
static int init_email (struct Email *e, const char *path, notmuch_message_t *msg)
 Set up an email's Notmuch data. More...
 
static const char * get_message_last_filename (notmuch_message_t *msg)
 Get a message's last filename. More...
 
static void progress_setup (struct Mailbox *m)
 Set up the Progress Bar. More...
 
static void nm_progress_update (struct Mailbox *m)
 Update the progress counter. More...
 
static struct Emailget_mutt_email (struct Mailbox *m, notmuch_message_t *msg)
 Get the Email of a Notmuch message. More...
 
static void append_message (struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *msg, bool dedup)
 Associate a message. More...
 
static void append_replies (struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *top, bool dedup)
 add all the replies to a given messages into the display More...
 
static void append_thread (struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_thread_t *thread, bool dedup)
 add each top level reply in the thread More...
 
static notmuch_messages_t * get_messages (notmuch_query_t *query)
 load messages for a query More...
 
static bool read_mesgs_query (struct Mailbox *m, notmuch_query_t *q, bool dedup)
 Search for matching messages. More...
 
static notmuch_threads_t * get_threads (notmuch_query_t *query)
 load threads for a query More...
 
static bool read_threads_query (struct Mailbox *m, notmuch_query_t *q, bool dedup, int limit)
 Perform a query with threads. More...
 
static notmuch_message_t * get_nm_message (notmuch_database_t *db, struct Email *e)
 Find a Notmuch message. More...
 
static bool nm_message_has_tag (notmuch_message_t *msg, char *tag)
 Does a message have this tag? More...
 
static void sync_email_path_with_nm (struct Email *e, notmuch_message_t *msg)
 Synchronize Neomutt's Email path with notmuch. More...
 
static int update_tags (notmuch_message_t *msg, const char *tag_str)
 Update the tags on a message. More...
 
static int update_email_flags (struct Mailbox *m, struct Email *e, const char *tag_str)
 Update the Email's flags. More...
 
static int rename_maildir_filename (const char *old, char *buf, size_t buflen, struct Email *e)
 Rename a Maildir file. More...
 
static int remove_filename (struct Mailbox *m, const char *path)
 Delete a file. More...
 
static int rename_filename (struct Mailbox *m, const char *old_file, const char *new_file, struct Email *e)
 Rename the file. More...
 
static unsigned int count_query (notmuch_database_t *db, const char *qstr, int limit)
 Count the results of a query. More...
 
char * nm_email_get_folder (struct Email *e)
 Get the folder for a Email. More...
 
char * nm_email_get_folder_rel_db (struct Mailbox *m, struct Email *e)
 Get the folder for a Email from the same level as the notmuch database. More...
 
int nm_read_entire_thread (struct Mailbox *m, struct Email *e)
 Get the entire thread of an email. More...
 
char * nm_url_from_query (struct Mailbox *m, char *buf, size_t buflen)
 Turn a query into a URL. More...
 
bool nm_query_window_available (void)
 Are windowed queries enabled for use? More...
 
void nm_query_window_forward (void)
 Function to move the current search window forward in time. More...
 
void nm_query_window_backward (void)
 Function to move the current search window backward in time. More...
 
void nm_query_window_reset (void)
 Resets the vfolder window position to the present. More...
 
bool nm_message_is_still_queried (struct Mailbox *m, struct Email *e)
 Is a message still visible in the query? More...
 
int nm_update_filename (struct Mailbox *m, const char *old_file, const char *new_file, struct Email *e)
 Change the filename. More...
 
static enum MxStatus nm_mbox_check_stats (struct Mailbox *m, uint8_t flags)
 Check the Mailbox statistics - Implements MxOps::mbox_check_stats() -. More...
 
static struct Mailboxget_default_mailbox (void)
 Get Mailbox for notmuch without any parameters. More...
 
int nm_record_message (struct Mailbox *m, char *path, struct Email *e)
 Add a message to the Notmuch database. More...
 
int nm_get_all_tags (struct Mailbox *m, char **tag_list, int *tag_count)
 Fill a list with all notmuch tags. More...
 
static bool nm_ac_owns_path (struct Account *a, const char *path)
 Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() -. More...
 
static bool nm_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() -. More...
 
static enum MxOpenReturns nm_mbox_open (struct Mailbox *m)
 Open a Mailbox - Implements MxOps::mbox_open() -. More...
 
static enum MxStatus nm_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus nm_mbox_sync (struct Mailbox *m)
 Save changes to the Mailbox - Implements MxOps::mbox_sync() -. More...
 
static enum MxStatus nm_mbox_close (struct Mailbox *m)
 Close a Mailbox - Implements MxOps::mbox_close() -Nothing to do. More...
 
static bool nm_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static int nm_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() -. More...
 
static int nm_msg_close (struct Mailbox *m, struct Message *msg)
 Close an email - Implements MxOps::msg_close() -. More...
 
static int nm_tags_edit (struct Mailbox *m, const char *tags, char *buf, size_t buflen)
 Prompt and validate new messages tags - Implements MxOps::tags_edit() -. More...
 
static int nm_tags_commit (struct Mailbox *m, struct Email *e, char *buf)
 Save the tags to a message - Implements MxOps::tags_commit() -. More...
 
enum MailboxType nm_path_probe (const char *path, const struct stat *st)
 Is this a Notmuch Mailbox? - Implements MxOps::path_probe() -. More...
 
static int nm_path_canon (char *buf, size_t buflen)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() -. More...
 
static int nm_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a Mailbox path - Implements MxOps::path_pretty() -. More...
 
static int nm_path_parent (char *buf, size_t buflen)
 Find the parent of a Mailbox path - Implements MxOps::path_parent() -. More...
 

Variables

static const struct Command nm_commands []
 
const char NmUrlProtocol [] = "notmuch://"
 
const int NmUrlProtocolLen = sizeof(NmUrlProtocol) - 1
 
struct MxOps MxNotmuchOps
 Notmuch Mailbox - Implements MxOps -. More...
 

Detailed Description

Notmuch virtual mailbox type.

Authors
  • Karel Zak
  • Richard Russon
  • Kevin Velghe
  • Bernard 'Guyzmo' Pratz

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file notmuch.c.

Function Documentation

◆ nm_init()

void nm_init ( void  )

Setup feature commands.

Definition at line 99 of file notmuch.c.

100 {
102 }
#define COMMANDS_REGISTER(cmds)
Definition: mutt_commands.h:82
static const struct Command nm_commands[]
Definition: notmuch.c:86
+ Here is the caller graph for this function:

◆ nm_hcache_open()

static struct HeaderCache* nm_hcache_open ( struct Mailbox m)
static

Open a header cache.

Parameters
mMailbox
Return values
ptrHeader cache handle

Definition at line 109 of file notmuch.c.

110 {
111 #ifdef USE_HCACHE
112  const char *const c_header_cache =
113  cs_subset_path(NeoMutt->sub, "header_cache");
114  return mutt_hcache_open(c_header_cache, mailbox_path(m), NULL);
115 #else
116  return NULL;
117 #endif
118 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:332
Container for Accounts, Notifications.
Definition: neomutt.h:36
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_hcache_close()

static void nm_hcache_close ( struct HeaderCache h)
static

Close the header cache.

Parameters
hHeader cache handle

Definition at line 124 of file notmuch.c.

125 {
126 #ifdef USE_HCACHE
128 #endif
129 }
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:435
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_get_default_url()

static char* nm_get_default_url ( void  )
static

Create a Mailbox with default Notmuch settings.

Return values
ptrMailbox with default Notmuch settings
NULLError, it's impossible to create an NmMboxData

Definition at line 136 of file notmuch.c.

137 {
138  // path to DB + query + url "decoration"
139  size_t len = PATH_MAX + 1024 + 32;
140  char *url = mutt_mem_malloc(len);
141 
142  // Try to use `$nm_default_url` or `$folder`.
143  // If neither are set, it is impossible to create a Notmuch URL.
144  const char *const c_nm_default_url =
145  cs_subset_string(NeoMutt->sub, "nm_default_url");
146  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
147  if (c_nm_default_url)
148  snprintf(url, len, "%s", c_nm_default_url);
149  else if (c_folder)
150  snprintf(url, len, "notmuch://%s", c_folder);
151  else
152  {
153  FREE(&url);
154  return NULL;
155  }
156 
157  return url;
158 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define PATH_MAX
Definition: mutt.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_get_default_data()

static struct NmMboxData* nm_get_default_data ( void  )
static

Create a Mailbox with default Notmuch settings.

Return values
ptrMailbox with default Notmuch settings
NULLError, it's impossible to create an NmMboxData

Definition at line 165 of file notmuch.c.

166 {
167  // path to DB + query + url "decoration"
168  char *url = nm_get_default_url();
169  if (!url)
170  return NULL;
171 
172  struct NmMboxData *default_data = nm_mdata_new(url);
173  FREE(&url);
174 
175  return default_data;
176 }
struct NmMboxData * nm_mdata_new(const char *url)
Create a new NmMboxData object from a query.
Definition: mdata.c:69
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
static char * nm_get_default_url(void)
Create a Mailbox with default Notmuch settings.
Definition: notmuch.c:136
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_mailbox()

static int init_mailbox ( struct Mailbox m)
static

Add Notmuch data to the Mailbox.

Parameters
mMailbox
Return values
0Success
-1Error Bad format

Create a new NmMboxData struct and add it Mailbox::data. Notmuch-specific data will be stored in this struct. This struct can be freed using nm_mdata_free().

Definition at line 188 of file notmuch.c.

189 {
190  if (!m || (m->type != MUTT_NOTMUCH))
191  return -1;
192 
193  if (m->mdata)
194  return 0;
195 
197  if (!m->mdata)
198  return -1;
199 
201  return 0;
202 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
struct NmMboxData * nm_mdata_new(const char *url)
Create a new NmMboxData object from a query.
Definition: mdata.c:69
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
void nm_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: mdata.c:46
void(* mdata_free)(void **ptr)
Free the private data attached to the Mailbox.
Definition: mailbox.h:146
void * mdata
Driver specific data.
Definition: mailbox.h:136
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ email_get_id()

static char* email_get_id ( struct Email e)
static

Get the unique Notmuch Id.

Parameters
eEmail
Return values
ptrID string
NULLError

Definition at line 210 of file notmuch.c.

211 {
212  struct NmEmailData *edata = nm_edata_get(e);
213  if (!edata)
214  return NULL;
215 
216  return edata->virtual_id;
217 }
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
char * virtual_id
Unique Notmuch Id.
Definition: edata.h:37
Notmuch-specific Email data -.
Definition: edata.h:33
void * edata
Driver-specific data.
Definition: email.h:111
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ email_get_fullpath()

static char* email_get_fullpath ( struct Email e,
char *  buf,
size_t  buflen 
)
static

Get the full path of an email.

Parameters
eEmail
bufBuffer for the path
buflenLength of the buffer
Return values
ptrPath string

Definition at line 226 of file notmuch.c.

227 {
228  snprintf(buf, buflen, "%s/%s", nm_email_get_folder(e), e->path);
229  return buf;
230 }
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition: notmuch.c:1458
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_window_reset()

static void query_window_reset ( void  )
static

Restore vfolder's search window to its original position.

After moving a vfolder search window backward and forward, calling this function will reset the search position to its original value, setting to 0 the user settable variable:

nm_query_window_current_position

Definition at line 241 of file notmuch.c.

242 {
243  mutt_debug(LL_DEBUG2, "entering\n");
244  cs_subset_str_native_set(NeoMutt->sub, "nm_query_window_current_position", 0, NULL);
245 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
Log at debug level 2.
Definition: logging.h:41
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ windowed_query_from_query()

static bool windowed_query_from_query ( const char *  query,
char *  buf,
size_t  buflen 
)
static

transforms a vfolder search query into a windowed one

Parameters
[in]queryvfolder search string
[out]bufallocated string buffer to receive the modified search query
[in]buflenallocated maximum size of the buf string buffer
Return values
trueTransformed search query is available as a string in buf
falseSearch query shall not be transformed

Creates a date: search term window from the following user settings:

  • nm_query_window_enable (only required for nm_query_window_duration = 0)
  • nm_query_window_duration
  • nm_query_window_timebase
  • nm_query_window_current_position

The window won't be applied:

  • If the duration of the search query is set to 0 this function will be disabled unless a user explicitly enables windowed queries.
  • If the timebase is invalid, it will show an error message and do nothing.

If there's no search registered in nm_query_window_current_search or this is a new search, it will reset the window and do the search.

Definition at line 271 of file notmuch.c.

272 {
273  mutt_debug(LL_DEBUG2, "nm: %s\n", query);
274 
275  const bool c_nm_query_window_enable =
276  cs_subset_bool(NeoMutt->sub, "nm_query_window_enable");
277  const short c_nm_query_window_duration =
278  cs_subset_number(NeoMutt->sub, "nm_query_window_duration");
279  const short c_nm_query_window_current_position =
280  cs_subset_number(NeoMutt->sub, "nm_query_window_current_position");
281  const char *const c_nm_query_window_current_search =
282  cs_subset_string(NeoMutt->sub, "nm_query_window_current_search");
283  const char *const c_nm_query_window_timebase =
284  cs_subset_string(NeoMutt->sub, "nm_query_window_timebase");
285  const char *const c_nm_query_window_or_terms =
286  cs_subset_string(NeoMutt->sub, "nm_query_window_or_terms");
287 
288  /* if the query has changed, reset the window position */
289  if (!c_nm_query_window_current_search ||
290  (strcmp(query, c_nm_query_window_current_search) != 0))
291  {
293  }
294 
296  buf, buflen, c_nm_query_window_enable, c_nm_query_window_duration,
297  c_nm_query_window_current_position, c_nm_query_window_current_search,
298  c_nm_query_window_timebase, c_nm_query_window_or_terms);
299 
300  switch (rc)
301  {
303  {
304  mutt_debug(LL_DEBUG2, "nm: %s -> %s\n", query, buf);
305  break;
306  }
308  {
310  return false;
311  }
313  {
314  mutt_message(
315  // L10N: The values 'hour', 'day', 'week', 'month', 'year' are literal.
316  // They should not be translated.
317  _("Invalid nm_query_window_timebase value (valid values are: "
318  "hour, day, week, month, year)"));
319  mutt_debug(LL_DEBUG2, "Invalid nm_query_window_timebase value\n");
320  return false;
321  }
322  }
323 
324  return true;
325 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
enum NmWindowQueryRc nm_windowed_query_from_query(char *buf, size_t buflen, const bool force_enable, const short duration, const short cur_pos, const char *cur_search, const char *timebase, const char *or_terms)
Windows buf with notmuch date: search term.
Definition: query.c:206
Invalid duration.
Definition: query.h:48
#define _(a)
Definition: message.h:28
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
Invalid timebase.
Definition: query.h:47
Log at debug level 2.
Definition: logging.h:41
NmWindowQueryRc
Return codes for nm_windowed_query_from_query()
Definition: query.h:44
Query was successful.
Definition: query.h:46
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:87
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
static void query_window_reset(void)
Restore vfolder&#39;s search window to its original position.
Definition: notmuch.c:241
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_query_string()

static char* get_query_string ( struct NmMboxData mdata,
bool  window 
)
static

builds the notmuch vfolder search string

Parameters
mdataNotmuch Mailbox data
windowIf true enable application of the window on the search string
Return values
ptrString containing a notmuch search query
NULLNone can be generated

This function parses the internal representation of a search, and returns a search query string ready to be fed to the notmuch API, given the search is valid.

Note
The window parameter here is here to decide contextually whether we want to return a search query with window applied (for the actual search result in mailbox) or not (for the count in the sidebar). It is not aimed at enabling/disabling the feature.

Definition at line 343 of file notmuch.c.

344 {
345  mutt_debug(LL_DEBUG2, "nm: %s\n", window ? "true" : "false");
346 
347  if (!mdata)
348  return NULL;
349  if (mdata->db_query && !window)
350  return mdata->db_query;
351 
352  const char *const c_nm_query_type =
353  cs_subset_string(NeoMutt->sub, "nm_query_type");
354  mdata->query_type = nm_string_to_query_type(c_nm_query_type); /* user's default */
355 
356  struct UrlQuery *item = NULL;
357  STAILQ_FOREACH(item, &mdata->db_url->query_strings, entries)
358  {
359  if (!item->value || !item->name)
360  continue;
361 
362  if (strcmp(item->name, "limit") == 0)
363  {
364  if (mutt_str_atoi(item->value, &mdata->db_limit))
365  mutt_error(_("failed to parse notmuch limit: %s"), item->value);
366  }
367  else if (strcmp(item->name, "type") == 0)
368  mdata->query_type = nm_string_to_query_type(item->value);
369  else if (strcmp(item->name, "query") == 0)
370  mdata->db_query = mutt_str_dup(item->value);
371  }
372 
373  if (!mdata->db_query)
374  return NULL;
375 
376  if (window)
377  {
378  char buf[1024];
379  cs_subset_str_string_set(NeoMutt->sub, "nm_query_window_current_search",
380  mdata->db_query, NULL);
381 
382  /* if a date part is defined, do not apply windows (to avoid the risk of
383  * having a non-intersected date frame). A good improvement would be to
384  * accept if they intersect */
385  if (!strstr(mdata->db_query, "date:") &&
386  windowed_query_from_query(mdata->db_query, buf, sizeof(buf)))
387  {
388  mdata->db_query = mutt_str_dup(buf);
389  }
390 
391  mutt_debug(LL_DEBUG2, "nm: query (windowed) '%s'\n", mdata->db_query);
392  }
393  else
394  mutt_debug(LL_DEBUG2, "nm: query '%s'\n", mdata->db_query);
395 
396  return mdata->db_query;
397 }
char * name
Query name.
Definition: url.h:59
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
#define mutt_error(...)
Definition: logging.h:88
static bool windowed_query_from_query(const char *query, char *buf, size_t buflen)
transforms a vfolder search query into a windowed one
Definition: notmuch.c:271
Parsed Query String.
Definition: url.h:57
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
char * value
Query value.
Definition: url.h:60
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:408
Log at debug level 2.
Definition: logging.h:41
enum NmQueryType nm_string_to_query_type(const char *str)
Lookup a query type.
Definition: query.c:109
struct UrlQueryList query_strings
List of query strings.
Definition: url.h:76
char * db_query
Previous query.
Definition: mdata.h:36
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct Url * db_url
Parsed view url of the Notmuch database.
Definition: mdata.h:35
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
enum NmQueryType query_type
Messages or Threads.
Definition: mdata.h:38
int db_limit
Maximum number of results to return.
Definition: mdata.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_limit()

static int get_limit ( struct NmMboxData mdata)
static

Get the database limit.

Parameters
mdataNotmuch Mailbox data
Return values
numCurrent limit

Definition at line 404 of file notmuch.c.

405 {
406  return mdata ? mdata->db_limit : 0;
407 }
int db_limit
Maximum number of results to return.
Definition: mdata.h:37
+ Here is the caller graph for this function:

◆ apply_exclude_tags()

static void apply_exclude_tags ( notmuch_query_t *  query)
static

Exclude the configured tags.

Parameters
queryNotmuch query

Definition at line 413 of file notmuch.c.

414 {
415  const char *const c_nm_exclude_tags =
416  cs_subset_string(NeoMutt->sub, "nm_exclude_tags");
417  if (!c_nm_exclude_tags || !query)
418  return;
419 
420  struct TagArray tags = nm_tag_str_to_tags(c_nm_exclude_tags);
421 
422  char **tag = NULL;
423  ARRAY_FOREACH(tag, &tags.tags)
424  {
425  mutt_debug(LL_DEBUG2, "nm: query exclude tag '%s'\n", *tag);
426  notmuch_query_add_tag_exclude(query, *tag);
427  }
428 
429  notmuch_query_set_omit_excluded(query, 1);
430  nm_tag_array_free(&tags);
431 }
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
Container for Accounts, Notifications.
Definition: neomutt.h:36
Log at debug level 2.
Definition: logging.h:41
void nm_tag_array_free(struct TagArray *tags)
Free all memory of a TagArray.
Definition: tag.c:39
struct TagArray nm_tag_str_to_tags(const char *tag_str)
Converts a comma and/or space-delimited string of tags into an array.
Definition: tag.c:50
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Array of Notmuch tags.
Definition: tag.h:34
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_query()

static notmuch_query_t* get_query ( struct Mailbox m,
bool  writable 
)
static

Create a new query.

Parameters
mMailbox
writableShould the query be updateable?
Return values
ptrNotmuch query
NULLError

Definition at line 440 of file notmuch.c.

441 {
442  struct NmMboxData *mdata = nm_mdata_get(m);
443  if (!mdata)
444  return NULL;
445 
446  notmuch_database_t *db = nm_db_get(m, writable);
447  const char *str = get_query_string(mdata, true);
448 
449  if (!db || !str)
450  goto err;
451 
452  notmuch_query_t *q = notmuch_query_create(db, str);
453  if (!q)
454  goto err;
455 
457  notmuch_query_set_sort(q, NOTMUCH_SORT_NEWEST_FIRST);
458  mutt_debug(LL_DEBUG2, "nm: query successfully initialized (%s)\n", str);
459  return q;
460 err:
461  nm_db_release(m);
462  return NULL;
463 }
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
Log at debug level 2.
Definition: logging.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
static char * get_query_string(struct NmMboxData *mdata, bool window)
builds the notmuch vfolder search string
Definition: notmuch.c:343
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:196
static void apply_exclude_tags(notmuch_query_t *query)
Exclude the configured tags.
Definition: notmuch.c:413
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_email_tags()

static int update_email_tags ( struct Email e,
notmuch_message_t *  msg 
)
static

Update the Email's tags from Notmuch.

Parameters
eEmail
msgNotmuch message
Return values
0Success
1Tags unchanged

Definition at line 472 of file notmuch.c.

473 {
474  struct NmEmailData *edata = nm_edata_get(e);
475  char *new_tags = NULL;
476  char *old_tags = NULL;
477 
478  mutt_debug(LL_DEBUG2, "nm: tags update requested (%s)\n", edata->virtual_id);
479 
480  for (notmuch_tags_t *tags = notmuch_message_get_tags(msg);
481  tags && notmuch_tags_valid(tags); notmuch_tags_move_to_next(tags))
482  {
483  const char *t = notmuch_tags_get(tags);
484  if (!t || (*t == '\0'))
485  continue;
486 
487  mutt_str_append_item(&new_tags, t, ' ');
488  }
489 
490  old_tags = driver_tags_get(&e->tags);
491 
492  if (new_tags && old_tags && (strcmp(old_tags, new_tags) == 0))
493  {
494  FREE(&old_tags);
495  FREE(&new_tags);
496  mutt_debug(LL_DEBUG2, "nm: tags unchanged\n");
497  return 1;
498  }
499 
500  /* new version */
501  driver_tags_replace(&e->tags, new_tags);
502  FREE(&new_tags);
503 
504  new_tags = driver_tags_get_transformed(&e->tags);
505  mutt_debug(LL_DEBUG2, "nm: new tags: '%s'\n", new_tags);
506  FREE(&new_tags);
507 
508  new_tags = driver_tags_get(&e->tags);
509  mutt_debug(LL_DEBUG2, "nm: new tag transforms: '%s'\n", new_tags);
510  FREE(&new_tags);
511 
512  return 0;
513 }
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
Log at debug level 2.
Definition: logging.h:41
char * virtual_id
Unique Notmuch Id.
Definition: edata.h:37
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
Notmuch-specific Email data -.
Definition: edata.h:33
char * driver_tags_get(struct TagList *list)
Get tags.
Definition: tags.c:145
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
char * driver_tags_get_transformed(struct TagList *list)
Get transformed tags.
Definition: tags.c:133
void * edata
Driver-specific data.
Definition: email.h:111
#define FREE(x)
Definition: memory.h:40
bool driver_tags_replace(struct TagList *head, char *tags)
Replace all tags.
Definition: tags.c:186
void mutt_str_append_item(char **str, const char *item, char sep)
Add string to another separated by sep.
Definition: string.c:466
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_message_path()

static int update_message_path ( struct Email e,
const char *  path 
)
static

Set the path for a message.

Parameters
eEmail
pathPath
Return values
0Success
1Failure

Definition at line 522 of file notmuch.c.

523 {
524  struct NmEmailData *edata = nm_edata_get(e);
525 
526  mutt_debug(LL_DEBUG2, "nm: path update requested path=%s, (%s)\n", path, edata->virtual_id);
527 
528  char *p = strrchr(path, '/');
529  if (p && ((p - path) > 3) &&
530  (mutt_strn_equal(p - 3, "cur", 3) || mutt_strn_equal(p - 3, "new", 3) ||
531  mutt_strn_equal(p - 3, "tmp", 3)))
532  {
533  edata->type = MUTT_MAILDIR;
534 
535  FREE(&e->path);
536  FREE(&edata->folder);
537 
538  p -= 3; /* skip subfolder (e.g. "new") */
539  e->old = mutt_str_startswith(p, "cur");
540  e->path = mutt_str_dup(p);
541 
542  for (; (p > path) && (*(p - 1) == '/'); p--)
543  ; // do nothing
544 
545  edata->folder = mutt_strn_dup(path, p - path);
546 
547  mutt_debug(LL_DEBUG2, "nm: folder='%s', file='%s'\n", edata->folder, e->path);
548  return 0;
549  }
550 
551  return 1;
552 }
enum MailboxType type
Type of Mailbox the Email is in.
Definition: edata.h:38
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
Log at debug level 2.
Definition: logging.h:41
bool old
Email is seen, but unread.
Definition: email.h:50
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
char * virtual_id
Unique Notmuch Id.
Definition: edata.h:37
char * folder
Location of the Email.
Definition: edata.h:35
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
Notmuch-specific Email data -.
Definition: edata.h:33
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
void * edata
Driver-specific data.
Definition: email.h:111
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_folder_from_path()

static char* get_folder_from_path ( const char *  path)
static

Find an email's folder from its path.

Parameters
pathPath
Return values
ptrPath string
NULLError

Definition at line 560 of file notmuch.c.

561 {
562  char *p = strrchr(path, '/');
563 
564  if (p && ((p - path) > 3) &&
565  (mutt_strn_equal(p - 3, "cur", 3) || mutt_strn_equal(p - 3, "new", 3) ||
566  mutt_strn_equal(p - 3, "tmp", 3)))
567  {
568  p -= 3;
569  for (; (p > path) && (*(p - 1) == '/'); p--)
570  ; // do nothing
571 
572  return mutt_strn_dup(path, p - path);
573  }
574 
575  return NULL;
576 }
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm2mutt_message_id()

static char* nm2mutt_message_id ( const char *  id)
static

converts notmuch message Id to neomutt message Id

Parameters
idNotmuch ID to convert
Return values
ptrNeoMutt message ID

Caller must free the NeoMutt Message ID

Definition at line 585 of file notmuch.c.

586 {
587  size_t sz;
588  char *mid = NULL;
589 
590  if (!id)
591  return NULL;
592  sz = strlen(id) + 3;
593  mid = mutt_mem_malloc(sz);
594 
595  snprintf(mid, sz, "<%s>", id);
596  return mid;
597 }
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_email()

static int init_email ( struct Email e,
const char *  path,
notmuch_message_t *  msg 
)
static

Set up an email's Notmuch data.

Parameters
eEmail
pathPath to email
msgNotmuch message
Return values
0Success
-1Failure

Definition at line 607 of file notmuch.c.

608 {
609  if (nm_edata_get(e))
610  return 0;
611 
612  struct NmEmailData *edata = nm_edata_new();
613  e->nm_edata = edata;
614 
615  /* Notmuch ensures that message Id exists (if not notmuch Notmuch will
616  * generate an ID), so it's more safe than use neomutt Email->env->id */
617  const char *id = notmuch_message_get_message_id(msg);
618  edata->virtual_id = mutt_str_dup(id);
619 
620  mutt_debug(LL_DEBUG2, "nm: [e=%p, edata=%p] (%s)\n", (void *) e, (void *) edata, id);
621 
622  char *nm_msg_id = nm2mutt_message_id(id);
623  if (!e->env->message_id)
624  {
625  e->env->message_id = nm_msg_id;
626  }
627  else if (!mutt_str_equal(e->env->message_id, nm_msg_id))
628  {
629  FREE(&e->env->message_id);
630  e->env->message_id = nm_msg_id;
631  }
632  else
633  {
634  FREE(&nm_msg_id);
635  }
636 
637  if (update_message_path(e, path) != 0)
638  return -1;
639 
640  update_email_tags(e, msg);
641 
642  return 0;
643 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
static int update_message_path(struct Email *e, const char *path)
Set the path for a message.
Definition: notmuch.c:522
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
Log at debug level 2.
Definition: logging.h:41
char * virtual_id
Unique Notmuch Id.
Definition: edata.h:37
Notmuch-specific Email data -.
Definition: edata.h:33
struct NmEmailData * nm_edata_new(void)
Create a new NmEmailData for an email.
Definition: edata.c:61
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void * edata
Driver-specific data.
Definition: email.h:111
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
#define FREE(x)
Definition: memory.h:40
static int update_email_tags(struct Email *e, notmuch_message_t *msg)
Update the Email&#39;s tags from Notmuch.
Definition: notmuch.c:472
static char * nm2mutt_message_id(const char *id)
converts notmuch message Id to neomutt message Id
Definition: notmuch.c:585
void * nm_edata
Notmuch private data.
Definition: email.h:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_message_last_filename()

static const char* get_message_last_filename ( notmuch_message_t *  msg)
static

Get a message's last filename.

Parameters
msgNotmuch message
Return values
ptrFilename
NULLError

Definition at line 651 of file notmuch.c.

652 {
653  const char *name = NULL;
654 
655  for (notmuch_filenames_t *ls = notmuch_message_get_filenames(msg);
656  ls && notmuch_filenames_valid(ls); notmuch_filenames_move_to_next(ls))
657  {
658  name = notmuch_filenames_get(ls);
659  }
660 
661  return name;
662 }
+ Here is the caller graph for this function:

◆ progress_setup()

static void progress_setup ( struct Mailbox m)
static

Set up the Progress Bar.

Parameters
mMailbox

Definition at line 668 of file notmuch.c.

669 {
670  if (!m->verbose)
671  return;
672 
673  struct NmMboxData *mdata = nm_mdata_get(m);
674  if (!mdata)
675  return;
676 
677  mdata->oldmsgcount = m->msg_count;
678  mdata->ignmsgcount = 0;
679  mdata->progress =
680  progress_new(_("Reading messages..."), MUTT_PROGRESS_READ, mdata->oldmsgcount);
681 }
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define _(a)
Definition: message.h:28
Progress tracks elements, according to $read_inc
Definition: lib.h:46
int oldmsgcount
Definition: mdata.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
struct Progress * progress
A progress bar.
Definition: mdata.h:40
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
bool verbose
Display status messages?
Definition: mailbox.h:118
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:246
int ignmsgcount
Ignored messages.
Definition: mdata.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_progress_update()

static void nm_progress_update ( struct Mailbox m)
static

Update the progress counter.

Parameters
mMailbox

Definition at line 687 of file notmuch.c.

688 {
689  struct NmMboxData *mdata = nm_mdata_get(m);
690 
691  if (!m->verbose || !mdata || !mdata->progress)
692  return;
693 
694  progress_update(mdata->progress, m->msg_count + mdata->ignmsgcount, -1);
695 }
int msg_count
Total number of messages.
Definition: mailbox.h:91
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
struct Progress * progress
A progress bar.
Definition: mdata.h:40
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
bool verbose
Display status messages?
Definition: mailbox.h:118
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:175
int ignmsgcount
Ignored messages.
Definition: mdata.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_mutt_email()

static struct Email* get_mutt_email ( struct Mailbox m,
notmuch_message_t *  msg 
)
static

Get the Email of a Notmuch message.

Parameters
mMailbox
msgNotmuch message
Return values
ptrEmail
NULLError

Definition at line 704 of file notmuch.c.

705 {
706  if (!m || !msg)
707  return NULL;
708 
709  const char *id = notmuch_message_get_message_id(msg);
710  if (!id)
711  return NULL;
712 
713  mutt_debug(LL_DEBUG2, "nm: neomutt email, id='%s'\n", id);
714 
715  if (!m->id_hash)
716  {
717  mutt_debug(LL_DEBUG2, "nm: init hash\n");
718  m->id_hash = mutt_make_id_hash(m);
719  if (!m->id_hash)
720  return NULL;
721  }
722 
723  char *mid = nm2mutt_message_id(id);
724  mutt_debug(LL_DEBUG2, "nm: neomutt id='%s'\n", mid);
725 
726  struct Email *e = mutt_hash_find(m->id_hash, mid);
727  FREE(&mid);
728  return e;
729 }
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
The envelope/body of an email.
Definition: email.h:37
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1658
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
Log at debug level 2.
Definition: logging.h:41
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define FREE(x)
Definition: memory.h:40
static char * nm2mutt_message_id(const char *id)
converts notmuch message Id to neomutt message Id
Definition: notmuch.c:585
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ append_message()

static void append_message ( struct HeaderCache h,
struct Mailbox m,
notmuch_query_t *  q,
notmuch_message_t *  msg,
bool  dedup 
)
static

Associate a message.

Parameters
hHeader cache handle
mMailbox
qNotmuch query
msgNotmuch message
dedupDe-duplicate results

Definition at line 739 of file notmuch.c.

741 {
742  struct NmMboxData *mdata = nm_mdata_get(m);
743  if (!mdata)
744  return;
745 
746  char *newpath = NULL;
747  struct Email *e = NULL;
748 
749  /* deduplicate */
750  if (dedup && get_mutt_email(m, msg))
751  {
752  mdata->ignmsgcount++;
754  mutt_debug(LL_DEBUG2, "nm: ignore id=%s, already in the m\n",
755  notmuch_message_get_message_id(msg));
756  return;
757  }
758 
759  const char *path = get_message_last_filename(msg);
760  if (!path)
761  return;
762 
763  mutt_debug(LL_DEBUG2, "nm: appending message, i=%d, id=%s, path=%s\n",
764  m->msg_count, notmuch_message_get_message_id(msg), path);
765 
766  if (m->msg_count >= m->email_max)
767  {
768  mutt_debug(LL_DEBUG2, "nm: allocate mx memory\n");
769  mx_alloc_memory(m);
770  }
771 
772 #ifdef USE_HCACHE
773  e = mutt_hcache_fetch(h, path, mutt_str_len(path), 0).email;
774  if (!e)
775 #endif
776  {
777  if (access(path, F_OK) == 0)
778  {
779  /* We pass is_old=false as argument here, but e->old will be updated later
780  * by update_message_path() (called by init_email() below). */
781  e = maildir_parse_message(MUTT_MAILDIR, path, false, NULL);
782  }
783  else
784  {
785  /* maybe moved try find it... */
786  char *folder = get_folder_from_path(path);
787 
788  if (folder)
789  {
790  FILE *fp = maildir_open_find_message(folder, path, &newpath);
791  if (fp)
792  {
793  e = maildir_parse_stream(MUTT_MAILDIR, fp, newpath, false, NULL);
794  mutt_file_fclose(&fp);
795 
796  mutt_debug(LL_DEBUG1, "nm: not up-to-date: %s -> %s\n", path, newpath);
797  }
798  }
799  FREE(&folder);
800  }
801 
802  if (!e)
803  {
804  mutt_debug(LL_DEBUG1, "nm: failed to parse message: %s\n", path);
805  goto done;
806  }
807 
808 #ifdef USE_HCACHE
809  mutt_hcache_store(h, newpath ? newpath : path,
810  mutt_str_len(newpath ? newpath : path), e, 0);
811 #endif
812  }
813 
814  if (init_email(e, newpath ? newpath : path, msg) != 0)
815  {
816  email_free(&e);
817  mutt_debug(LL_DEBUG1, "nm: failed to append email!\n");
818  goto done;
819  }
820 
821  e->active = true;
822  e->index = m->msg_count;
823  mailbox_size_add(m, e);
824  m->emails[m->msg_count] = e;
825  m->msg_count++;
826 
827  if (newpath)
828  {
829  /* remember that file has been moved -- nm_mbox_sync() will update the DB */
830  struct NmEmailData *edata = nm_edata_get(e);
831  if (edata)
832  {
833  mutt_debug(LL_DEBUG1, "nm: remember obsolete path: %s\n", path);
834  edata->oldpath = mutt_str_dup(path);
835  }
836  }
838 done:
839  FREE(&newpath);
840 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
void mailbox_size_add(struct Mailbox *m, const struct Email *e)
Add an email&#39;s size to the total size of a Mailbox.
Definition: mailbox.c:223
struct Email * maildir_parse_message(enum MailboxType type, const char *fname, bool is_old, struct Email *e)
Actually parse a maildir message.
Definition: maildir.c:926
char * oldpath
Definition: edata.h:36
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1212
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
static int init_email(struct Email *e, const char *path, notmuch_message_t *msg)
Set up an email&#39;s Notmuch data.
Definition: notmuch.c:607
static const char * get_message_last_filename(notmuch_message_t *msg)
Get a message&#39;s last filename.
Definition: notmuch.c:651
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
Log at debug level 2.
Definition: logging.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a new.
Definition: maildir.c:993
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void * mdata
Driver specific data.
Definition: mailbox.h:136
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
static void nm_progress_update(struct Mailbox *m)
Update the progress counter.
Definition: notmuch.c:687
bool active
Message is not to be removed.
Definition: email.h:59
struct Email * maildir_parse_stream(enum MailboxType type, FILE *fp, const char *fname, bool is_old, struct Email *e)
Parse a Maildir message.
Definition: maildir.c:882
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
Notmuch-specific Email data -.
Definition: edata.h:33
int mutt_hcache_store(struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition: hcache.c:556
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
Log at debug level 1.
Definition: logging.h:40
void * edata
Driver-specific data.
Definition: email.h:111
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
static char * get_folder_from_path(const char *path)
Find an email&#39;s folder from its path.
Definition: notmuch.c:560
int ignmsgcount
Ignored messages.
Definition: mdata.h:42
int index
The absolute (unsorted) message number.
Definition: email.h:86
#define FREE(x)
Definition: memory.h:40
static struct Email * get_mutt_email(struct Mailbox *m, notmuch_message_t *msg)
Get the Email of a Notmuch message.
Definition: notmuch.c:704
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:461
struct Email * email
Retrieved email.
Definition: lib.h:99
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ append_replies()

static void append_replies ( struct HeaderCache h,
struct Mailbox m,
notmuch_query_t *  q,
notmuch_message_t *  top,
bool  dedup 
)
static

add all the replies to a given messages into the display

Parameters
hHeader cache handle
mMailbox
qNotmuch query
topNotmuch message
dedupDe-duplicate the results

Careful, this calls itself recursively to make sure we get everything.

Definition at line 852 of file notmuch.c.

854 {
855  notmuch_messages_t *msgs = NULL;
856 
857  for (msgs = notmuch_message_get_replies(top); notmuch_messages_valid(msgs);
858  notmuch_messages_move_to_next(msgs))
859  {
860  notmuch_message_t *nm = notmuch_messages_get(msgs);
861  append_message(h, m, q, nm, dedup);
862  /* recurse through all the replies to this message too */
863  append_replies(h, m, q, nm, dedup);
864  notmuch_message_destroy(nm);
865  }
866 }
static void append_message(struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *msg, bool dedup)
Associate a message.
Definition: notmuch.c:739
static void append_replies(struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *top, bool dedup)
add all the replies to a given messages into the display
Definition: notmuch.c:852
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ append_thread()

static void append_thread ( struct HeaderCache h,
struct Mailbox m,
notmuch_query_t *  q,
notmuch_thread_t *  thread,
bool  dedup 
)
static

add each top level reply in the thread

Parameters
hHeader cache handle
mMailbox
qNotmuch query
threadNotmuch thread
dedupDe-duplicate the results

add each top level reply in the thread, and then add each reply to the top level replies

Definition at line 879 of file notmuch.c.

881 {
882  notmuch_messages_t *msgs = NULL;
883 
884  for (msgs = notmuch_thread_get_toplevel_messages(thread);
885  notmuch_messages_valid(msgs); notmuch_messages_move_to_next(msgs))
886  {
887  notmuch_message_t *nm = notmuch_messages_get(msgs);
888  append_message(h, m, q, nm, dedup);
889  append_replies(h, m, q, nm, dedup);
890  notmuch_message_destroy(nm);
891  }
892 }
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
static void append_message(struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *msg, bool dedup)
Associate a message.
Definition: notmuch.c:739
static void append_replies(struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *top, bool dedup)
add all the replies to a given messages into the display
Definition: notmuch.c:852
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_messages()

static notmuch_messages_t* get_messages ( notmuch_query_t *  query)
static

load messages for a query

Parameters
queryNotmuch query
Return values
ptrMessages matching query
NULLError occurred

This helper method is to be the single point for retrieving messages. It handles version specific calls, which will make maintenance easier.

Definition at line 903 of file notmuch.c.

904 {
905  if (!query)
906  return NULL;
907 
908  notmuch_messages_t *msgs = NULL;
909 
910 #if LIBNOTMUCH_CHECK_VERSION(5, 0, 0)
911  if (notmuch_query_search_messages(query, &msgs) != NOTMUCH_STATUS_SUCCESS)
912  return NULL;
913 #elif LIBNOTMUCH_CHECK_VERSION(4, 3, 0)
914  if (notmuch_query_search_messages_st(query, &msgs) != NOTMUCH_STATUS_SUCCESS)
915  return NULL;
916 #else
917  msgs = notmuch_query_search_messages(query);
918 #endif
919 
920  return msgs;
921 }
+ Here is the caller graph for this function:

◆ read_mesgs_query()

static bool read_mesgs_query ( struct Mailbox m,
notmuch_query_t *  q,
bool  dedup 
)
static

Search for matching messages.

Parameters
mMailbox
qNotmuch query
dedupDe-duplicate the results
Return values
trueSuccess
falseFailure

Definition at line 931 of file notmuch.c.

932 {
933  struct NmMboxData *mdata = nm_mdata_get(m);
934  if (!mdata)
935  return false;
936 
937  int limit = get_limit(mdata);
938 
939  notmuch_messages_t *msgs = get_messages(q);
940 
941  if (!msgs)
942  return false;
943 
944  struct HeaderCache *h = nm_hcache_open(m);
945 
946  for (; notmuch_messages_valid(msgs) && ((limit == 0) || (m->msg_count < limit));
947  notmuch_messages_move_to_next(msgs))
948  {
949  if (SigInt)
950  {
951  nm_hcache_close(h);
952  SigInt = false;
953  return false;
954  }
955  notmuch_message_t *nm = notmuch_messages_get(msgs);
956  append_message(h, m, q, nm, dedup);
957  notmuch_message_destroy(nm);
958  }
959 
960  nm_hcache_close(h);
961  return true;
962 }
int msg_count
Total number of messages.
Definition: mailbox.h:91
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:67
header cache structure
Definition: lib.h:84
static int get_limit(struct NmMboxData *mdata)
Get the database limit.
Definition: notmuch.c:404
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
static notmuch_messages_t * get_messages(notmuch_query_t *query)
load messages for a query
Definition: notmuch.c:903
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
static struct HeaderCache * nm_hcache_open(struct Mailbox *m)
Open a header cache.
Definition: notmuch.c:109
static void nm_hcache_close(struct HeaderCache *h)
Close the header cache.
Definition: notmuch.c:124
static void append_message(struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_message_t *msg, bool dedup)
Associate a message.
Definition: notmuch.c:739
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_threads()

static notmuch_threads_t* get_threads ( notmuch_query_t *  query)
static

load threads for a query

Parameters
queryNotmuch query
Return values
ptrThreads matching query
NULLError occurred

This helper method is to be the single point for retrieving messages. It handles version specific calls, which will make maintenance easier.

Definition at line 973 of file notmuch.c.

974 {
975  if (!query)
976  return NULL;
977 
978  notmuch_threads_t *threads = NULL;
979 #if LIBNOTMUCH_CHECK_VERSION(5, 0, 0)
980  if (notmuch_query_search_threads(query, &threads) != NOTMUCH_STATUS_SUCCESS)
981  return false;
982 #elif LIBNOTMUCH_CHECK_VERSION(4, 3, 0)
983  if (notmuch_query_search_threads_st(query, &threads) != NOTMUCH_STATUS_SUCCESS)
984  return false;
985 #else
986  threads = notmuch_query_search_threads(query);
987 #endif
988 
989  return threads;
990 }
+ Here is the caller graph for this function:

◆ read_threads_query()

static bool read_threads_query ( struct Mailbox m,
notmuch_query_t *  q,
bool  dedup,
int  limit 
)
static

Perform a query with threads.

Parameters
mMailbox
qQuery type
dedupShould the results be de-duped?
limitMaximum number of results
Return values
trueSuccess
falseFailure

Definition at line 1001 of file notmuch.c.

1002 {
1003  struct NmMboxData *mdata = nm_mdata_get(m);
1004  if (!mdata)
1005  return false;
1006 
1007  notmuch_threads_t *threads = get_threads(q);
1008  if (!threads)
1009  return false;
1010 
1011  struct HeaderCache *h = nm_hcache_open(m);
1012 
1013  for (; notmuch_threads_valid(threads) && ((limit == 0) || (m->msg_count < limit));
1014  notmuch_threads_move_to_next(threads))
1015  {
1016  if (SigInt)
1017  {
1018  nm_hcache_close(h);
1019  SigInt = false;
1020  return false;
1021  }
1022  notmuch_thread_t *thread = notmuch_threads_get(threads);
1023  append_thread(h, m, q, thread, dedup);
1024  notmuch_thread_destroy(thread);
1025  }
1026 
1027  nm_hcache_close(h);
1028  return true;
1029 }
int msg_count
Total number of messages.
Definition: mailbox.h:91
static notmuch_threads_t * get_threads(notmuch_query_t *query)
load threads for a query
Definition: notmuch.c:973
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:67
header cache structure
Definition: lib.h:84
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
static struct HeaderCache * nm_hcache_open(struct Mailbox *m)
Open a header cache.
Definition: notmuch.c:109
static void append_thread(struct HeaderCache *h, struct Mailbox *m, notmuch_query_t *q, notmuch_thread_t *thread, bool dedup)
add each top level reply in the thread
Definition: notmuch.c:879
static void nm_hcache_close(struct HeaderCache *h)
Close the header cache.
Definition: notmuch.c:124
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_nm_message()

static notmuch_message_t* get_nm_message ( notmuch_database_t *  db,
struct Email e 
)
static

Find a Notmuch message.

Parameters
dbNotmuch database
eEmail
Return values
ptrHandle to the Notmuch message

Definition at line 1037 of file notmuch.c.

1038 {
1039  notmuch_message_t *msg = NULL;
1040  char *id = email_get_id(e);
1041 
1042  mutt_debug(LL_DEBUG2, "nm: find message (%s)\n", id);
1043 
1044  if (id && db)
1045  notmuch_database_find_message(db, id, &msg);
1046 
1047  return msg;
1048 }
Log at debug level 2.
Definition: logging.h:41
static char * email_get_id(struct Email *e)
Get the unique Notmuch Id.
Definition: notmuch.c:210
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_message_has_tag()

static bool nm_message_has_tag ( notmuch_message_t *  msg,
char *  tag 
)
static

Does a message have this tag?

Parameters
msgNotmuch message
tagTag
Return values
trueIt does

Definition at line 1056 of file notmuch.c.

1057 {
1058  const char *possible_match_tag = NULL;
1059  notmuch_tags_t *tags = NULL;
1060 
1061  for (tags = notmuch_message_get_tags(msg); notmuch_tags_valid(tags);
1062  notmuch_tags_move_to_next(tags))
1063  {
1064  possible_match_tag = notmuch_tags_get(tags);
1065  if (mutt_str_equal(possible_match_tag, tag))
1066  {
1067  return true;
1068  }
1069  }
1070  return false;
1071 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sync_email_path_with_nm()

static void sync_email_path_with_nm ( struct Email e,
notmuch_message_t *  msg 
)
static

Synchronize Neomutt's Email path with notmuch.

Parameters
eEmail in Neomutt
msgEmail from notmuch

Definition at line 1078 of file notmuch.c.

1079 {
1080  const char *new_file = get_message_last_filename(msg);
1081  char old_file[PATH_MAX];
1082  email_get_fullpath(e, old_file, sizeof(old_file));
1083 
1084  if (!mutt_str_equal(old_file, new_file))
1085  update_message_path(e, new_file);
1086 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
static int update_message_path(struct Email *e, const char *path)
Set the path for a message.
Definition: notmuch.c:522
static const char * get_message_last_filename(notmuch_message_t *msg)
Get a message&#39;s last filename.
Definition: notmuch.c:651
#define PATH_MAX
Definition: mutt.h:40
static char * email_get_fullpath(struct Email *e, char *buf, size_t buflen)
Get the full path of an email.
Definition: notmuch.c:226
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_tags()

static int update_tags ( notmuch_message_t *  msg,
const char *  tag_str 
)
static

Update the tags on a message.

Parameters
msgNotmuch message
tag_strString of tags (space separated)
Return values
0Success
-1Failure

Definition at line 1095 of file notmuch.c.

1096 {
1097  if (!tag_str)
1098  return -1;
1099 
1100  notmuch_message_freeze(msg);
1101 
1102  struct TagArray tags = nm_tag_str_to_tags(tag_str);
1103  char **tag_elem = NULL;
1104  ARRAY_FOREACH(tag_elem, &tags.tags)
1105  {
1106  char *tag = *tag_elem;
1107 
1108  if (tag[0] == '-')
1109  {
1110  mutt_debug(LL_DEBUG1, "nm: remove tag: '%s'\n", tag + 1);
1111  notmuch_message_remove_tag(msg, tag + 1);
1112  }
1113  else if (tag[0] == '!')
1114  {
1115  mutt_debug(LL_DEBUG1, "nm: toggle tag: '%s'\n", tag + 1);
1116  if (nm_message_has_tag(msg, tag + 1))
1117  {
1118  notmuch_message_remove_tag(msg, tag + 1);
1119  }
1120  else
1121  {
1122  notmuch_message_add_tag(msg, tag + 1);
1123  }
1124  }
1125  else
1126  {
1127  mutt_debug(LL_DEBUG1, "nm: add tag: '%s'\n", (tag[0] == '+') ? tag + 1 : tag);
1128  notmuch_message_add_tag(msg, (tag[0] == '+') ? tag + 1 : tag);
1129  }
1130  }
1131 
1132  notmuch_message_thaw(msg);
1133  nm_tag_array_free(&tags);
1134 
1135  return 0;
1136 }
char * tag_str
Source string.
Definition: tag.h:37
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
void nm_tag_array_free(struct TagArray *tags)
Free all memory of a TagArray.
Definition: tag.c:39
struct TagArray nm_tag_str_to_tags(const char *tag_str)
Converts a comma and/or space-delimited string of tags into an array.
Definition: tag.c:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
Array of Notmuch tags.
Definition: tag.h:34
static bool nm_message_has_tag(notmuch_message_t *msg, char *tag)
Does a message have this tag?
Definition: notmuch.c:1056
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_email_flags()

static int update_email_flags ( struct Mailbox m,
struct Email e,
const char *  tag_str 
)
static

Update the Email's flags.

Parameters
mMailbox
eEmail
tag_strString of tags (space separated)
Return values
0Success
-1Failure

TODO: join update_email_tags and update_email_flags, which are given an array of tags.

Definition at line 1149 of file notmuch.c.

1150 {
1151  if (!tag_str)
1152  return -1;
1153 
1154  const char *const c_nm_unread_tag =
1155  cs_subset_string(NeoMutt->sub, "nm_unread_tag");
1156  const char *const c_nm_replied_tag =
1157  cs_subset_string(NeoMutt->sub, "nm_replied_tag");
1158  const char *const c_nm_flagged_tag =
1159  cs_subset_string(NeoMutt->sub, "nm_flagged_tag");
1160 
1161  struct TagArray tags = nm_tag_str_to_tags(tag_str);
1162  char **tag_elem = NULL;
1163  ARRAY_FOREACH(tag_elem, &tags.tags)
1164  {
1165  char *tag = *tag_elem;
1166 
1167  if (tag[0] == '-')
1168  {
1169  tag++;
1170  if (strcmp(tag, c_nm_unread_tag) == 0)
1171  mutt_set_flag(m, e, MUTT_READ, true);
1172  else if (strcmp(tag, c_nm_replied_tag) == 0)
1173  mutt_set_flag(m, e, MUTT_REPLIED, false);
1174  else if (strcmp(tag, c_nm_flagged_tag) == 0)
1175  mutt_set_flag(m, e, MUTT_FLAG, false);
1176  }
1177  else
1178  {
1179  tag = (tag[0] == '+') ? tag + 1 : tag;
1180  if (strcmp(tag, c_nm_unread_tag) == 0)
1181  mutt_set_flag(m, e, MUTT_READ, false);
1182  else if (strcmp(tag, c_nm_replied_tag) == 0)
1183  mutt_set_flag(m, e, MUTT_REPLIED, true);
1184  else if (strcmp(tag, c_nm_flagged_tag) == 0)
1185  mutt_set_flag(m, e, MUTT_FLAG, true);
1186  }
1187  }
1188 
1189  nm_tag_array_free(&tags);
1190 
1191  return 0;
1192 }
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
char * tag_str
Source string.
Definition: tag.h:37
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
Flagged messages.
Definition: mutt.h:98
Container for Accounts, Notifications.
Definition: neomutt.h:36
Messages that have been replied to.
Definition: mutt.h:91
void nm_tag_array_free(struct TagArray *tags)
Free all memory of a TagArray.
Definition: tag.c:39
struct TagArray nm_tag_str_to_tags(const char *tag_str)
Converts a comma and/or space-delimited string of tags into an array.
Definition: tag.c:50
Messages that have been read.
Definition: mutt.h:92
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Array of Notmuch tags.
Definition: tag.h:34
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rename_maildir_filename()

static int rename_maildir_filename ( const char *  old,
char *  buf,
size_t  buflen,
struct Email e 
)
static

Rename a Maildir file.

Parameters
oldOld path
bufBuffer for new path
buflenLength of buffer
eEmail
Return values
0Success, renamed
1Success, no change
-1Failure

Definition at line 1204 of file notmuch.c.

1205 {
1206  char filename[PATH_MAX];
1207  char suffix[PATH_MAX];
1208  char folder[PATH_MAX];
1209 
1210  mutt_str_copy(folder, old, sizeof(folder));
1211  char *p = strrchr(folder, '/');
1212  if (p)
1213  {
1214  *p = '\0';
1215  p++;
1216  }
1217  else
1218  p = folder;
1219 
1220  mutt_str_copy(filename, p, sizeof(filename));
1221 
1222  /* remove (new,cur,...) from folder path */
1223  p = strrchr(folder, '/');
1224  if (p)
1225  *p = '\0';
1226 
1227  /* remove old flags from filename */
1228  p = strchr(filename, ':');
1229  if (p)
1230  *p = '\0';
1231 
1232  /* compose new flags */
1233  maildir_gen_flags(suffix, sizeof(suffix), e);
1234 
1235  snprintf(buf, buflen, "%s/%s/%s%s", folder,
1236  (e->read || e->old) ? "cur" : "new", filename, suffix);
1237 
1238  if (strcmp(old, buf) == 0)
1239  return 1;
1240 
1241  if (rename(old, buf) != 0)
1242  {
1243  mutt_debug(LL_DEBUG1, "nm: rename(2) failed %s -> %s\n", old, buf);
1244  return -1;
1245  }
1246 
1247  return 0;
1248 }
bool read
Email is read.
Definition: email.h:51
bool old
Email is seen, but unread.
Definition: email.h:50
#define PATH_MAX
Definition: mutt.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void maildir_gen_flags(char *dest, size_t destlen, struct Email *e)
Generate the Maildir flags for an email.
Definition: maildir.c:186
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_filename()

static int remove_filename ( struct Mailbox m,
const char *  path 
)
static

Delete a file.

Parameters
mMailbox
pathPath of file
Return values
0Success
-1Failure

Definition at line 1257 of file notmuch.c.

1258 {
1259  struct NmMboxData *mdata = nm_mdata_get(m);
1260  if (!mdata)
1261  return -1;
1262 
1263  mutt_debug(LL_DEBUG2, "nm: remove filename '%s'\n", path);
1264 
1265  notmuch_database_t *db = nm_db_get(m, true);
1266  if (!db)
1267  return -1;
1268 
1269  notmuch_message_t *msg = NULL;
1270  notmuch_status_t st = notmuch_database_find_message_by_filename(db, path, &msg);
1271  if (st || !msg)
1272  return -1;
1273 
1274  int trans = nm_db_trans_begin(m);
1275  if (trans < 0)
1276  return -1;
1277 
1278  /* note that unlink() is probably unnecessary here, it's already removed
1279  * by mh_sync_mailbox_message(), but for sure... */
1280  notmuch_filenames_t *ls = NULL;
1281  st = notmuch_database_remove_message(db, path);
1282  switch (st)
1283  {
1284  case NOTMUCH_STATUS_SUCCESS:
1285  mutt_debug(LL_DEBUG2, "nm: remove success, call unlink\n");
1286  unlink(path);
1287  break;
1288  case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
1289  mutt_debug(LL_DEBUG2, "nm: remove success (duplicate), call unlink\n");
1290  unlink(path);
1291  for (ls = notmuch_message_get_filenames(msg);
1292  ls && notmuch_filenames_valid(ls); notmuch_filenames_move_to_next(ls))
1293  {
1294  path = notmuch_filenames_get(ls);
1295 
1296  mutt_debug(LL_DEBUG2, "nm: remove duplicate: '%s'\n", path);
1297  unlink(path);
1298  notmuch_database_remove_message(db, path);
1299  }
1300  break;
1301  default:
1302  mutt_debug(LL_DEBUG1, "nm: failed to remove '%s' [st=%d]\n", path, (int) st);
1303  break;
1304  }
1305 
1306  notmuch_message_destroy(msg);
1307  if (trans)
1308  nm_db_trans_end(m);
1309  return 0;
1310 }
int nm_db_trans_begin(struct Mailbox *m)
Start a Notmuch database transaction.
Definition: db.c:229
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
Log at debug level 2.
Definition: logging.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
int nm_db_trans_end(struct Mailbox *m)
End a database transaction.
Definition: db.c:251
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rename_filename()

static int rename_filename ( struct Mailbox m,
const char *  old_file,
const char *  new_file,
struct Email e 
)
static

Rename the file.

Parameters
mNotmuch Mailbox data
old_fileOld filename
new_fileNew filename
eEmail
Return values
0Success
-1Failure

Definition at line 1321 of file notmuch.c.

1323 {
1324  struct NmMboxData *mdata = nm_mdata_get(m);
1325  if (!mdata)
1326  return -1;
1327 
1328  notmuch_database_t *db = nm_db_get(m, true);
1329  if (!db || !new_file || !old_file || (access(new_file, F_OK) != 0))
1330  return -1;
1331 
1332  int rc = -1;
1333  notmuch_status_t st;
1334  notmuch_filenames_t *ls = NULL;
1335  notmuch_message_t *msg = NULL;
1336 
1337  mutt_debug(LL_DEBUG1, "nm: rename filename, %s -> %s\n", old_file, new_file);
1338  int trans = nm_db_trans_begin(m);
1339  if (trans < 0)
1340  return -1;
1341 
1342  mutt_debug(LL_DEBUG2, "nm: rename: add '%s'\n", new_file);
1343 #ifdef HAVE_NOTMUCH_DATABASE_INDEX_FILE
1344  st = notmuch_database_index_file(db, new_file, NULL, &msg);
1345 #else
1346  st = notmuch_database_add_message(db, new_file, &msg);
1347 #endif
1348 
1349  if ((st != NOTMUCH_STATUS_SUCCESS) && (st != NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID))
1350  {
1351  mutt_debug(LL_DEBUG1, "nm: failed to add '%s' [st=%d]\n", new_file, (int) st);
1352  goto done;
1353  }
1354 
1355  mutt_debug(LL_DEBUG2, "nm: rename: rem '%s'\n", old_file);
1356  st = notmuch_database_remove_message(db, old_file);
1357  switch (st)
1358  {
1359  case NOTMUCH_STATUS_SUCCESS:
1360  break;
1361  case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
1362  mutt_debug(LL_DEBUG2, "nm: rename: syncing duplicate filename\n");
1363  notmuch_message_destroy(msg);
1364  msg = NULL;
1365  notmuch_database_find_message_by_filename(db, new_file, &msg);
1366 
1367  for (ls = notmuch_message_get_filenames(msg);
1368  msg && ls && notmuch_filenames_valid(ls); notmuch_filenames_move_to_next(ls))
1369  {
1370  const char *path = notmuch_filenames_get(ls);
1371  char newpath[PATH_MAX];
1372 
1373  if (strcmp(new_file, path) == 0)
1374  continue;
1375 
1376  mutt_debug(LL_DEBUG2, "nm: rename: syncing duplicate: %s\n", path);
1377 
1378  if (rename_maildir_filename(path, newpath, sizeof(newpath), e) == 0)
1379  {
1380  mutt_debug(LL_DEBUG2, "nm: rename dup %s -> %s\n", path, newpath);
1381  notmuch_database_remove_message(db, path);
1382 #ifdef HAVE_NOTMUCH_DATABASE_INDEX_FILE
1383  notmuch_database_index_file(db, newpath, NULL, NULL);
1384 #else
1385  notmuch_database_add_message(db, newpath, NULL);
1386 #endif
1387  }
1388  }
1389  notmuch_message_destroy(msg);
1390  msg = NULL;
1391  notmuch_database_find_message_by_filename(db, new_file, &msg);
1392  st = NOTMUCH_STATUS_SUCCESS;
1393  break;
1394  default:
1395  mutt_debug(LL_DEBUG1, "nm: failed to remove '%s' [st=%d]\n", old_file, (int) st);
1396  break;
1397  }
1398 
1399  if ((st == NOTMUCH_STATUS_SUCCESS) && e && msg)
1400  {
1401  notmuch_message_maildir_flags_to_tags(msg);
1402  update_email_tags(e, msg);
1403 
1404  char *tags = driver_tags_get(&e->tags);
1405  update_tags(msg, tags);
1406  FREE(&tags);
1407  }
1408 
1409  rc = 0;
1410 done:
1411  if (msg)
1412  notmuch_message_destroy(msg);
1413  if (trans)
1414  nm_db_trans_end(m);
1415  return rc;
1416 }
int nm_db_trans_begin(struct Mailbox *m)
Start a Notmuch database transaction.
Definition: db.c:229
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
Log at debug level 2.
Definition: logging.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
static int update_tags(notmuch_message_t *msg, const char *tag_str)
Update the tags on a message.
Definition: notmuch.c:1095
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
int nm_db_trans_end(struct Mailbox *m)
End a database transaction.
Definition: db.c:251
#define PATH_MAX
Definition: mutt.h:40
char * driver_tags_get(struct TagList *list)
Get tags.
Definition: tags.c:145
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
#define FREE(x)
Definition: memory.h:40
static int update_email_tags(struct Email *e, notmuch_message_t *msg)
Update the Email&#39;s tags from Notmuch.
Definition: notmuch.c:472
static int rename_maildir_filename(const char *old, char *buf, size_t buflen, struct Email *e)
Rename a Maildir file.
Definition: notmuch.c:1204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ count_query()

static unsigned int count_query ( notmuch_database_t *  db,
const char *  qstr,
int  limit 
)
static

Count the results of a query.

Parameters
dbNotmuch database
qstrQuery to execute
limitMaximum number of results
Return values
numNumber of results

Definition at line 1425 of file notmuch.c.

1426 {
1427  notmuch_query_t *q = notmuch_query_create(db, qstr);
1428  if (!q)
1429  return 0;
1430 
1431  unsigned int res = 0;
1432 
1433  apply_exclude_tags(q);
1434 #if LIBNOTMUCH_CHECK_VERSION(5, 0, 0)
1435  if (notmuch_query_count_messages(q, &res) != NOTMUCH_STATUS_SUCCESS)
1436  res = 0; /* may not be defined on error */
1437 #elif LIBNOTMUCH_CHECK_VERSION(4, 3, 0)
1438  if (notmuch_query_count_messages_st(q, &res) != NOTMUCH_STATUS_SUCCESS)
1439  res = 0; /* may not be defined on error */
1440 #else
1441  res = notmuch_query_count_messages(q);
1442 #endif
1443  notmuch_query_destroy(q);
1444  mutt_debug(LL_DEBUG1, "nm: count '%s', result=%d\n", qstr, res);
1445 
1446  if ((limit > 0) && (res > limit))
1447  res = limit;
1448 
1449  return res;
1450 }
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
static void apply_exclude_tags(notmuch_query_t *query)
Exclude the configured tags.
Definition: notmuch.c:413
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_email_get_folder()

char* nm_email_get_folder ( struct Email e)

Get the folder for a Email.

Parameters
eEmail
Return values
ptrFolder containing email
NULLError

Definition at line 1458 of file notmuch.c.

1459 {
1460  struct NmEmailData *edata = nm_edata_get(e);
1461  if (!edata)
1462  return NULL;
1463 
1464  return edata->folder;
1465 }
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
char * folder
Location of the Email.
Definition: edata.h:35
Notmuch-specific Email data -.
Definition: edata.h:33
void * edata
Driver-specific data.
Definition: email.h:111
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_email_get_folder_rel_db()

char* nm_email_get_folder_rel_db ( struct Mailbox m,
struct Email e 
)

Get the folder for a Email from the same level as the notmuch database.

Parameters
mMailbox containing Email
eEmail
Return values
ptrFolder containing email from the same level as the notmuch db
NULLError

Instead of returning a path like /var/mail/account/Inbox, this returns account/Inbox. If wanting the full path, use nm_email_get_folder().

Definition at line 1477 of file notmuch.c.

1478 {
1479  char *full_folder = nm_email_get_folder(e);
1480  if (!full_folder)
1481  return NULL;
1482 
1483  const char *db_path = nm_db_get_filename(m);
1484  if (!db_path)
1485  return NULL;
1486 
1487  return full_folder + strlen(db_path);
1488 }
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition: notmuch.c:1458
const char * nm_db_get_filename(struct Mailbox *m)
Get the filename of the Notmuch database.
Definition: db.c:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_read_entire_thread()

int nm_read_entire_thread ( struct Mailbox m,
struct Email e 
)

Get the entire thread of an email.

Parameters
mMailbox
eEmail
Return values
0Success
-1Failure

Definition at line 1497 of file notmuch.c.

1498 {
1499  if (!m)
1500  return -1;
1501 
1502  struct NmMboxData *mdata = nm_mdata_get(m);
1503  if (!mdata)
1504  return -1;
1505 
1506  notmuch_query_t *q = NULL;
1507  notmuch_database_t *db = NULL;
1508  notmuch_message_t *msg = NULL;
1509  int rc = -1;
1510 
1511  if (!(db = nm_db_get(m, false)) || !(msg = get_nm_message(db, e)))
1512  goto done;
1513 
1514  mutt_debug(LL_DEBUG1, "nm: reading entire-thread messages...[current count=%d]\n",
1515  m->msg_count);
1516 
1517  progress_setup(m);
1518  const char *id = notmuch_message_get_thread_id(msg);
1519  if (!id)
1520  goto done;
1521 
1522  char *qstr = NULL;
1523  mutt_str_append_item(&qstr, "thread:", '\0');
1524  mutt_str_append_item(&qstr, id, '\0');
1525 
1526  q = notmuch_query_create(db, qstr);
1527  FREE(&qstr);
1528  if (!q)
1529  goto done;
1530  apply_exclude_tags(q);
1531  notmuch_query_set_sort(q, NOTMUCH_SORT_NEWEST_FIRST);
1532 
1533  read_threads_query(m, q, true, 0);
1534  m->mtime.tv_sec = mutt_date_epoch();
1535  m->mtime.tv_nsec = 0;
1536  rc = 0;
1537 
1538  if (m->msg_count > mdata->oldmsgcount)
1540 done:
1541  if (q)
1542  notmuch_query_destroy(q);
1543 
1544  nm_db_release(m);
1545 
1546  if (m->msg_count == mdata->oldmsgcount)
1547  mutt_message(_("No more messages in the thread"));
1548 
1549  mdata->oldmsgcount = 0;
1550  mutt_debug(LL_DEBUG1, "nm: reading entire-thread messages... done [rc=%d, count=%d]\n",
1551  rc, m->msg_count);
1552  progress_free(&mdata->progress);
1553  return rc;
1554 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
int msg_count
Total number of messages.
Definition: mailbox.h:91
static void progress_setup(struct Mailbox *m)
Set up the Progress Bar.
Definition: notmuch.c:668
struct timespec mtime
Time Mailbox was last changed.
Definition: mailbox.h:107
#define _(a)
Definition: message.h:28
Email list was changed.
Definition: mailbox.h:180
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
time_t tv_sec
Definition: file.h:50
int oldmsgcount
Definition: mdata.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
long tv_nsec
Definition: file.h:51
struct Progress * progress
A progress bar.
Definition: mdata.h:40
void * mdata
Driver specific data.
Definition: mailbox.h:136
static notmuch_message_t * get_nm_message(notmuch_database_t *db, struct Email *e)
Find a Notmuch message.
Definition: notmuch.c:1037
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
Log at debug level 1.
Definition: logging.h:40
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:196
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
void mutt_str_append_item(char **str, const char *item, char sep)
Add string to another separated by sep.
Definition: string.c:466
static void apply_exclude_tags(notmuch_query_t *query)
Exclude the configured tags.
Definition: notmuch.c:413
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:208
static bool read_threads_query(struct Mailbox *m, notmuch_query_t *q, bool dedup, int limit)
Perform a query with threads.
Definition: notmuch.c:1001
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_url_from_query()

char* nm_url_from_query ( struct Mailbox m,
char *  buf,
size_t  buflen 
)

Turn a query into a URL.

Parameters
mMailbox
bufBuffer for URL
buflenLength of buffer
Return values
ptrQuery as a URL
NULLError

Definition at line 1564 of file notmuch.c.

1565 {
1566  mutt_debug(LL_DEBUG2, "(%s)\n", buf);
1567  struct NmMboxData *mdata = nm_mdata_get(m);
1568  char url[PATH_MAX + 1024 + 32]; /* path to DB + query + URL "decoration" */
1569  int added;
1570  bool using_default_data = false;
1571 
1572  // No existing data. Try to get a default NmMboxData.
1573  if (!mdata)
1574  {
1575  mdata = nm_get_default_data();
1576 
1577  // Failed to get default data.
1578  if (!mdata)
1579  return NULL;
1580 
1581  using_default_data = true;
1582  }
1583 
1584  mdata->query_type = nm_parse_type_from_query(buf);
1585 
1586  const short c_nm_db_limit = cs_subset_number(NeoMutt->sub, "nm_db_limit");
1587  if (get_limit(mdata) == c_nm_db_limit)
1588  {
1589  added = snprintf(url, sizeof(url), "%s%s?type=%s&query=", NmUrlProtocol,
1591  }
1592  else
1593  {
1594  added = snprintf(url, sizeof(url), "%s%s?type=%s&limit=%d&query=", NmUrlProtocol,
1595  nm_db_get_filename(m),
1596  nm_query_type_to_string(mdata->query_type), get_limit(mdata));
1597  }
1598 
1599  if (added >= sizeof(url))
1600  {
1601  // snprintf output was truncated, so can't create URL
1602  return NULL;
1603  }
1604 
1605  url_pct_encode(&url[added], sizeof(url) - added, buf);
1606 
1607  mutt_str_copy(buf, url, buflen);
1608  buf[buflen - 1] = '\0';
1609 
1610  if (using_default_data)
1611  nm_mdata_free((void **) &mdata);
1612 
1613  mutt_debug(LL_DEBUG1, "nm: url from query '%s'\n", buf);
1614  return buf;
1615 }
const char * nm_query_type_to_string(enum NmQueryType query_type)
Turn a query type into a string.
Definition: query.c:95
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
void nm_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: mdata.c:46
Log at debug level 2.
Definition: logging.h:41
static int get_limit(struct NmMboxData *mdata)
Get the database limit.
Definition: notmuch.c:404
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
enum NmQueryType nm_parse_type_from_query(char *buf)
Parse a query type out of a query.
Definition: query.c:48
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
void url_pct_encode(char *buf, size_t buflen, const char *src)
Percent-encode a string.
Definition: url.c:151
#define PATH_MAX
Definition: mutt.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
const char NmUrlProtocol[]
Definition: notmuch.c:93
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
static struct NmMboxData * nm_get_default_data(void)
Create a Mailbox with default Notmuch settings.
Definition: notmuch.c:165
enum NmQueryType query_type
Messages or Threads.
Definition: mdata.h:38
const char * nm_db_get_filename(struct Mailbox *m)
Get the filename of the Notmuch database.
Definition: db.c:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_query_window_available()

bool nm_query_window_available ( void  )

Are windowed queries enabled for use?

Return values
trueWindowed queries in use

Definition at line 1621 of file notmuch.c.

1622 {
1623  const short c_nm_query_window_duration =
1624  cs_subset_number(NeoMutt->sub, "nm_query_window_duration");
1625  const bool c_nm_query_window_enable =
1626  cs_subset_bool(NeoMutt->sub, "nm_query_window_enable");
1627 
1628  return c_nm_query_window_enable || (c_nm_query_window_duration > 0);
1629 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_query_window_forward()

void nm_query_window_forward ( void  )

Function to move the current search window forward in time.

Updates nm_query_window_current_position by decrementing it by 1, or does nothing if the current window already is set to 0.

The lower the value of nm_query_window_current_position is, the more recent the result will be.

Definition at line 1640 of file notmuch.c.

1641 {
1642  const short c_nm_query_window_current_position =
1643  cs_subset_number(NeoMutt->sub, "nm_query_window_current_position");
1644  if (c_nm_query_window_current_position != 0)
1645  {
1646  cs_subset_str_native_set(NeoMutt->sub, "nm_query_window_current_position",
1647  c_nm_query_window_current_position - 1, NULL);
1648  }
1649 
1650  mutt_debug(LL_DEBUG2, "(%d)\n", c_nm_query_window_current_position - 1);
1651 }
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
Log at debug level 2.
Definition: logging.h:41
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_query_window_backward()

void nm_query_window_backward ( void  )

Function to move the current search window backward in time.

Updates nm_query_window_current_position by incrementing it by 1

The higher the value of nm_query_window_current_position is, the less recent the result will be.

Definition at line 1661 of file notmuch.c.

1662 {
1663  const short c_nm_query_window_current_position =
1664  cs_subset_number(NeoMutt->sub, "nm_query_window_current_position");
1665  cs_subset_str_native_set(NeoMutt->sub, "nm_query_window_current_position",
1666  c_nm_query_window_current_position + 1, NULL);
1667  mutt_debug(LL_DEBUG2, "(%d)\n", c_nm_query_window_current_position + 1);
1668 }
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
Log at debug level 2.
Definition: logging.h:41
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_query_window_reset()

void nm_query_window_reset ( void  )

Resets the vfolder window position to the present.

Definition at line 1673 of file notmuch.c.

1674 {
1675  cs_subset_str_native_set(NeoMutt->sub, "nm_query_window_current_position", 0, NULL);
1676  mutt_debug(LL_DEBUG2, "Reset nm_query_window_current_position to 0\n");
1677 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
Log at debug level 2.
Definition: logging.h:41
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_message_is_still_queried()

bool nm_message_is_still_queried ( struct Mailbox m,
struct Email e 
)

Is a message still visible in the query?

Parameters
mMailbox
eEmail
Return values
trueMessage is still in query

Definition at line 1685 of file notmuch.c.

1686 {
1687  struct NmMboxData *mdata = nm_mdata_get(m);
1688  notmuch_database_t *db = nm_db_get(m, false);
1689  char *orig_str = get_query_string(mdata, true);
1690 
1691  if (!db || !orig_str)
1692  return false;
1693 
1694  char *new_str = NULL;
1695  bool rc = false;
1696  if (mutt_str_asprintf(&new_str, "id:%s and (%s)", email_get_id(e), orig_str) < 0)
1697  return false;
1698 
1699  mutt_debug(LL_DEBUG2, "nm: checking if message is still queried: %s\n", new_str);
1700 
1701  notmuch_query_t *q = notmuch_query_create(db, new_str);
1702 
1703  switch (mdata->query_type)
1704  {
1705  case NM_QUERY_TYPE_UNKNOWN: // UNKNOWN should never occur, but MESGS is default
1706  case NM_QUERY_TYPE_MESGS:
1707  {
1708  notmuch_messages_t *messages = get_messages(q);
1709 
1710  if (!messages)
1711  return false;
1712 
1713  rc = notmuch_messages_valid(messages);
1714  notmuch_messages_destroy(messages);
1715  break;
1716  }
1717  case NM_QUERY_TYPE_THREADS:
1718  {
1719  notmuch_threads_t *threads = get_threads(q);
1720 
1721  if (!threads)
1722  return false;
1723 
1724  rc = notmuch_threads_valid(threads);
1725  notmuch_threads_destroy(threads);
1726  break;
1727  }
1728  }
1729 
1730  notmuch_query_destroy(q);
1731 
1732  mutt_debug(LL_DEBUG2, "nm: checking if message is still queried: %s = %s\n",
1733  new_str, rc ? "true" : "false");
1734 
1735  return rc;
1736 }
static notmuch_threads_t * get_threads(notmuch_query_t *query)
load threads for a query
Definition: notmuch.c:973
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
Log at debug level 2.
Definition: logging.h:41
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
static char * email_get_id(struct Email *e)
Get the unique Notmuch Id.
Definition: notmuch.c:210
static notmuch_messages_t * get_messages(notmuch_query_t *query)
load messages for a query
Definition: notmuch.c:903
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
static char * get_query_string(struct NmMboxData *mdata, bool window)
builds the notmuch vfolder search string
Definition: notmuch.c:343
Default: Messages only.
Definition: query.h:36
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Unknown query type. Error in notmuch query.
Definition: query.h:38
Whole threads.
Definition: query.h:37
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1128
enum NmQueryType query_type
Messages or Threads.
Definition: mdata.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_update_filename()

int nm_update_filename ( struct Mailbox m,
const char *  old_file,
const char *  new_file,
struct Email e 
)

Change the filename.

Parameters
mMailbox
old_fileOld filename
new_fileNew filename
eEmail
Return values
0Success
-1Failure

Definition at line 1747 of file notmuch.c.

1749 {
1750  char buf[PATH_MAX];
1751  struct NmMboxData *mdata = nm_mdata_get(m);
1752  if (!mdata || !new_file)
1753  return -1;
1754 
1755  if (!old_file && nm_edata_get(e))
1756  {
1757  email_get_fullpath(e, buf, sizeof(buf));
1758  old_file = buf;
1759  }
1760 
1761  int rc = rename_filename(m, old_file, new_file, e);
1762 
1763  nm_db_release(m);
1764  m->mtime.tv_sec = mutt_date_epoch();
1765  m->mtime.tv_nsec = 0;
1766  return rc;
1767 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
struct timespec mtime
Time Mailbox was last changed.
Definition: mailbox.h:107
time_t tv_sec
Definition: file.h:50
struct NmEmailData * nm_edata_get(struct Email *e)
Get the Notmuch Email data.
Definition: edata.c:72
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
long tv_nsec
Definition: file.h:51
void * mdata
Driver specific data.
Definition: mailbox.h:136
static int rename_filename(struct Mailbox *m, const char *old_file, const char *new_file, struct Email *e)
Rename the file.
Definition: notmuch.c:1321
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
#define PATH_MAX
Definition: mutt.h:40
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:196
static char * email_get_fullpath(struct Email *e, char *buf, size_t buflen)
Get the full path of an email.
Definition: notmuch.c:226
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_default_mailbox()

static struct Mailbox* get_default_mailbox ( void  )
static

Get Mailbox for notmuch without any parameters.

Return values
ptrMailbox pointer.

Definition at line 1871 of file notmuch.c.

1872 {
1873  // Create a new notmuch mailbox from scratch and add plumbing for DB access.
1874  char *default_url = nm_get_default_url();
1875  struct Mailbox *m = mx_path_resolve(default_url);
1876 
1877  FREE(&default_url);
1878 
1879  // These are no-ops for an initialized mailbox.
1880  init_mailbox(m);
1881  mx_mbox_ac_link(m);
1882 
1883  return m;
1884 }
A mailbox.
Definition: mailbox.h:81
static int init_mailbox(struct Mailbox *m)
Add Notmuch data to the Mailbox.
Definition: notmuch.c:188
static char * nm_get_default_url(void)
Create a Mailbox with default Notmuch settings.
Definition: notmuch.c:136
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1668
bool mx_mbox_ac_link(struct Mailbox *m)
Link a Mailbox to an existing or new Account.
Definition: mx.c:267
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_record_message()

int nm_record_message ( struct Mailbox m,
char *  path,
struct Email e 
)

Add a message to the Notmuch database.

Parameters
mMailbox
pathPath of the email
eEmail
Return values
0Success
-1Failure

Definition at line 1894 of file notmuch.c.

1895 {
1896  notmuch_database_t *db = NULL;
1897  notmuch_status_t st;
1898  notmuch_message_t *msg = NULL;
1899  int rc = -1;
1900 
1901  struct NmMboxData *mdata = nm_mdata_get(m);
1902 
1903  // If no notmuch data, fall back to the default mailbox.
1904  //
1905  // IMPORTANT: DO NOT FREE THIS MAILBOX. Two reasons:
1906  // 1) If user has default mailbox in config, we'll be removing it. That's not
1907  // good program behavior!
1908  // 2) If not in user's config, keep mailbox around for future nm_record calls.
1909  // It saves NeoMutt from allocating/deallocating repeatedly.
1910  if (!mdata)
1911  {
1912  mutt_debug(LL_DEBUG1, "nm: non-nm mailbox. trying the default nm mailbox.");
1913  m = get_default_mailbox();
1914  mdata = nm_mdata_get(m);
1915  }
1916 
1917  if (!path || !mdata || (access(path, F_OK) != 0))
1918  return 0;
1919  db = nm_db_get(m, true);
1920  if (!db)
1921  return -1;
1922 
1923  mutt_debug(LL_DEBUG1, "nm: record message: %s\n", path);
1924  int trans = nm_db_trans_begin(m);
1925  if (trans < 0)
1926  goto done;
1927 
1928 #ifdef HAVE_NOTMUCH_DATABASE_INDEX_FILE
1929  st = notmuch_database_index_file(db, path, NULL, &msg);
1930 #else
1931  st = notmuch_database_add_message(db, path, &msg);
1932 #endif
1933 
1934  if ((st != NOTMUCH_STATUS_SUCCESS) && (st != NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID))
1935  {
1936  mutt_debug(LL_DEBUG1, "nm: failed to add '%s' [st=%d]\n", path, (int) st);
1937  goto done;
1938  }
1939 
1940  if ((st == NOTMUCH_STATUS_SUCCESS) && msg)
1941  {
1942  notmuch_message_maildir_flags_to_tags(msg);
1943  if (e)
1944  {
1945  char *tags = driver_tags_get(&e->tags);
1946  update_tags(msg, tags);
1947  FREE(&tags);
1948  }
1949  const char *const c_nm_record_tags =
1950  cs_subset_string(NeoMutt->sub, "nm_record_tags");
1951  if (c_nm_record_tags)
1952  update_tags(msg, c_nm_record_tags);
1953  }
1954 
1955  rc = 0;
1956 done:
1957  if (msg)
1958  notmuch_message_destroy(msg);
1959  if (trans == 1)
1960  nm_db_trans_end(m);
1961 
1962  nm_db_release(m);
1963 
1964  return rc;
1965 }
static struct Mailbox * get_default_mailbox(void)
Get Mailbox for notmuch without any parameters.
Definition: notmuch.c:1871
int nm_db_trans_begin(struct Mailbox *m)
Start a Notmuch database transaction.
Definition: db.c:229
Container for Accounts, Notifications.
Definition: neomutt.h:36
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
static int update_tags(notmuch_message_t *msg, const char *tag_str)
Update the tags on a message.
Definition: notmuch.c:1095
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
int nm_db_trans_end(struct Mailbox *m)
End a database transaction.
Definition: db.c:251
char * driver_tags_get(struct TagList *list)
Get tags.
Definition: tags.c:145
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:196
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_get_all_tags()

int nm_get_all_tags ( struct Mailbox m,
char **  tag_list,
int *  tag_count 
)

Fill a list with all notmuch tags.

Parameters
[in]mMailbox
[out]tag_listList of tags
[out]tag_countNumber of tags
Return values
0Success
-1Failure

If tag_list is NULL, just count the tags.

Definition at line 1977 of file notmuch.c.

1978 {
1979  struct NmMboxData *mdata = nm_mdata_get(m);
1980  if (!mdata)
1981  return -1;
1982 
1983  notmuch_database_t *db = NULL;
1984  notmuch_tags_t *tags = NULL;
1985  const char *tag = NULL;
1986  int rc = -1;
1987 
1988  if (!(db = nm_db_get(m, false)) || !(tags = notmuch_database_get_all_tags(db)))
1989  goto done;
1990 
1991  *tag_count = 0;
1992  mutt_debug(LL_DEBUG1, "nm: get all tags\n");
1993 
1994  while (notmuch_tags_valid(tags))
1995  {
1996  tag = notmuch_tags_get(tags);
1997  /* Skip empty string */
1998  if (*tag)
1999  {
2000  if (tag_list)
2001  tag_list[*tag_count] = mutt_str_dup(tag);
2002  (*tag_count)++;
2003  }
2004  notmuch_tags_move_to_next(tags);
2005  }
2006 
2007  rc = 0;
2008 done:
2009  if (tags)
2010  notmuch_tags_destroy(tags);
2011 
2012  nm_db_release(m);
2013 
2014  mutt_debug(LL_DEBUG1, "nm: get all tags done [rc=%d tag_count=%u]\n", rc, *tag_count);
2015  return rc;
2016 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:172
Notmuch-specific Mailbox data -.
Definition: mdata.h:33
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:98
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:196
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ nm_commands

const struct Command nm_commands[]
static
Initial value:
= {
{ "unvirtual-mailboxes", parse_unmailboxes, 0 },
{ "virtual-mailboxes", parse_mailboxes, MUTT_NAMED },
}
#define MUTT_NAMED
Definition: mutt_commands.h:79
enum CommandResult parse_mailboxes(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;mailboxes&#39; command - Implements Command::parse() -This is also used by &#39;virtual-mailboxes&#39;...
enum CommandResult parse_unmailboxes(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unmailboxes&#39; command - Implements Command::parse() -This is also used by &#39;unvirtual-mailbo...

Definition at line 86 of file notmuch.c.

◆ NmUrlProtocol

const char NmUrlProtocol[] = "notmuch://"

Definition at line 93 of file notmuch.c.

◆ NmUrlProtocolLen

const int NmUrlProtocolLen = sizeof(NmUrlProtocol) - 1

Definition at line 94 of file notmuch.c.