[PATCH 2/4] Maildir synchronization

2010-10-22 Thread Michal Sojka
On Wed, 13 Oct 2010, Sebastian Spaeth wrote:
> > +/* ASCII ordered table of Maildir flags and associated tags */
> > +struct maildir_flag_tag flag2tag[] = {
> > +{ 'D', "draft",   false},
> > +{ 'F', "flagged", false},
> > +{ 'P', "passed",  false},
> > +{ 'R', "replied", false},
> > +{ 'S', "unread",  true },
> > +{ 'T', "delete",  false},
> > +};
> 
> [...]
> 
> with one caveat: you use the tag "delete" to mark the state "trashed". I
> think people have slowly settled on the convention "deleted" which is
> also more consistent with a state, such as unread, replied, etc...

Hi,

I changed "delete" to "deleted" and the updated patch series is
reachable by:

git pull git://rtime.felk.cvut.cz/notmuch maildir-sync-v3

-Michal


[PATCH 2/4] Maildir synchronization

2010-10-13 Thread Sebastian Spaeth
> +/* ASCII ordered table of Maildir flags and associated tags */
> +struct maildir_flag_tag flag2tag[] = {
> +{ 'D', "draft",   false},
> +{ 'F', "flagged", false},
> +{ 'P', "passed",  false},
> +{ 'R', "replied", false},
> +{ 'S', "unread",  true },
> +{ 'T', "delete",  false},
> +};

for all of the 4 patches a:

Signed-off-by: Sebastian Spaeth 

with one caveat: you use the tag "delete" to mark the state "trashed". I
think people have slowly settled on the convention "deleted" which is
also more consistent with a state, such as unread, replied, etc...

They work fine and obsolete my notmuchsync (except for the pruning of
deleted mails and the tagging based on folder names). +1 for merging in
notmuch-next or wherever we collect that stuff.

Sebastian
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: 



[PATCH 2/4] Maildir synchronization

2010-10-13 Thread Michal Sojka
This patch allows bi-directional synchronization between maildir
flags and certain tags. The flag-to-tag mapping is defined by flag2tag
array.

The synchronization works this way:

1) Whenever notmuch new is executed, the following happens:
   o New messages are tagged with configured new_tags.
   o For new or renamed messages with maildir info present in the file
 name, the tags defined in flag2tag are either added or removed
 depending on the flags from the file name.

2) Whenever notmuch tag (or notmuch restore) is executed, a new set of
   flags based on the tags is constructed for every message and a new
   file name is prepared based on the old file name but with the new
   flags. If the flags differs and the old message was in 'new'
   directory then this is replaced with 'cur' in the new file name. If
   the new and old file names differ, the file is renamed and notmuch
   database is updated accordingly.

   The rename happens before the database is updated. In case of crash
   between rename and database update, the next run of notmuch new
   brings the database in sync with the mail store again.

There is currenlty one known issue: Viewing/storing of attachments of
unread messages doesn't work. The reason is that when you view the
message its unread tag is removed which leads to rename of the file,
but Emacs still uses the original name to access the attachment.

Workaround: close the message and open it again.
---
 lib/database.cc   |7 ++
 lib/message.cc|  226 +
 lib/notmuch-private.h |4 +
 lib/notmuch.h |7 ++
 notmuch-new.c |3 +-
 5 files changed, 246 insertions(+), 1 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 9a4f715..9652013 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1643,6 +1643,13 @@ notmuch_database_add_message (notmuch_database_t 
*notmuch,

_notmuch_message_add_filename (message, filename);

+   /* This is a new message or it has a new filename and as such,
+* its tags in database either do not exists or might be out
+* of date. We assign the tags later in notmuch new, but until
+* then we should not synchronize the tags back to the maildir
+* flags (if notmuch is configured to do so). */
+   notmuch_message_set_flag(message, NOTMUCH_MESSAGE_FLAG_TAGS_INVALID, 
TRUE);
+
/* Is this a newly created message object? */
if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
_notmuch_message_add_term (message, "type", "mail");
diff --git a/lib/message.cc b/lib/message.cc
index 71f5619..96c402c 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -43,6 +43,24 @@ struct _notmuch_message {
 Xapian::Document doc;
 };

+#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))
+
+struct maildir_flag_tag {
+char flag;
+const char *tag;
+bool inverse;
+};
+
+/* ASCII ordered table of Maildir flags and associated tags */
+struct maildir_flag_tag flag2tag[] = {
+{ 'D', "draft",   false},
+{ 'F', "flagged", false},
+{ 'P', "passed",  false},
+{ 'R', "replied", false},
+{ 'S', "unread",  true },
+{ 'T', "delete",  false},
+};
+
 /* We end up having to call the destructor explicitly because we had
  * to use "placement new" in order to initialize C++ objects within a
  * block that we allocated with talloc. So C++ is making talloc
@@ -595,15 +613,29 @@ _notmuch_message_set_date (notmuch_message_t *message,
Xapian::sortable_serialise (time_value));
 }

+static notmuch_private_status_t
+_notmuch_message_tags_to_maildir (notmuch_message_t *message);
+
 /* Synchronize changes made to message->doc out into the database. */
 void
 _notmuch_message_sync (notmuch_message_t *message)
 {
 Xapian::WritableDatabase *db;
+notmuch_private_status_t status;

 if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
return;

+if (// todo_sync_enabled &&
+   !notmuch_message_get_flag(message, NOTMUCH_MESSAGE_FLAG_TAGS_INVALID)) {
+   status = _notmuch_message_tags_to_maildir (message);
+   if (status != NOTMUCH_PRIVATE_STATUS_SUCCESS) {
+   fprintf (stderr, "Error: Cannot sync tags to maildir (%s)\n",
+notmuch_status_to_string ((notmuch_status_t)status));
+   /* Exit to avoid unsynchronized mailstore. */
+   exit(1);
+   }
+}
 db = static_cast  
(message->notmuch->xapian_db);
 db->replace_document (message->doc_id, message->doc);
 }
@@ -715,6 +747,44 @@ _notmuch_message_remove_term (notmuch_message_t *message,
 return NOTMUCH_PRIVATE_STATUS_SUCCESS;
 }

+/* Change the message filename stored in the database.
+ *
+ * This change will not be reflected in the database until the next
+ * call to _notmuch_message_sync.
+ */
+notmuch_private_status_t
+_notmuch_message_rename (notmuch_message_t *message,
+const char 

Re: [PATCH 2/4] Maildir synchronization

2010-10-13 Thread Sebastian Spaeth
 +/* ASCII ordered table of Maildir flags and associated tags */
 +struct maildir_flag_tag flag2tag[] = {
 +{ 'D', draft,   false},
 +{ 'F', flagged, false},
 +{ 'P', passed,  false},
 +{ 'R', replied, false},
 +{ 'S', unread,  true },
 +{ 'T', delete,  false},
 +};

for all of the 4 patches a:

Signed-off-by: Sebastian Spaeth sebast...@sspaeth.de

with one caveat: you use the tag delete to mark the state trashed. I
think people have slowly settled on the convention deleted which is
also more consistent with a state, such as unread, replied, etc...

They work fine and obsolete my notmuchsync (except for the pruning of
deleted mails and the tagging based on folder names). +1 for merging in
notmuch-next or wherever we collect that stuff.

Sebastian


pgpNLrh1HgxKD.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 2/4] Maildir synchronization

2010-05-11 Thread Michal Sojka
This patch allows bi-directional synchronization between maildir
flags and certain tags. The flag-to-tag mapping is defined by flag2tag
array.

The synchronization works this way:

1) Whenever notmuch new is executed, the following happens:
   o New messages are tagged with configured new_tags.
   o For new or renamed messages with maildir info present in the file
 name, the tags defined in flag2tag are either added or removed
 depending on the flags from the file name.

2) Whenever notmuch tag (or notmuch restore) is executed, a new set of
   flags based on the tags is constructed for every message and a new
   file name is prepared based on the old file name but with the new
   flags. If the flags differs and the old message was in 'new'
   directory then this is replaced with 'cur' in the new file name. If
   the new and old file names differ, the file is renamed and notmuch
   database is updated accordingly.

   The rename happens before the database is updated. In case of crash
   between rename and database update, the next run of notmuch new
   brings the database in sync with the mail store again.

There is currenlty one known issue: Viewing/storing of attachments of
unread messages doesn't work. The reason is that when you view the
message its unread tag is removed which leads to rename of the file,
but Emacs still uses the original name to access the attachment.

Workaround: close the message and open it again.
---
 lib/database.cc   |7 ++
 lib/message.cc|  226 +
 lib/notmuch-private.h |4 +
 lib/notmuch.h |7 ++
 notmuch-new.c |3 +-
 5 files changed, 246 insertions(+), 1 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 694b7ec..908bbaa 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1585,6 +1585,13 @@ notmuch_database_add_message (notmuch_database_t 
*notmuch,

_notmuch_message_add_filename (message, filename);

+   /* This is a new message or it has a new filename and as such,
+* its tags in database either do not exists or might be out
+* of date. We assign the tags later in notmuch new, but until
+* then we should not synchronize the tags back to the maildir
+* flags (if notmuch is configured to do so). */
+   notmuch_message_set_flag(message, NOTMUCH_MESSAGE_FLAG_TAGS_INVALID, 
TRUE);
+
/* Is this a newly created message object? */
if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
_notmuch_message_add_term (message, "type", "mail");
diff --git a/lib/message.cc b/lib/message.cc
index 4b2f98f..0de3f01 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -43,6 +43,24 @@ struct _notmuch_message {
 Xapian::Document doc;
 };

+#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))
+
+struct maildir_flag_tag {
+char flag;
+const char *tag;
+bool inverse;
+};
+
+/* ASCII ordered table of Maildir flags and associated tags */
+struct maildir_flag_tag flag2tag[] = {
+{ 'D', "draft",   false},
+{ 'F', "flagged", false},
+{ 'P', "passed",  false},
+{ 'R', "replied", false},
+{ 'S', "unread",  true },
+{ 'T', "delete",  false},
+};
+
 /* We end up having to call the destructor explicitly because we had
  * to use "placement new" in order to initialize C++ objects within a
  * block that we allocated with talloc. So C++ is making talloc
@@ -568,15 +586,29 @@ _notmuch_message_set_date (notmuch_message_t *message,
Xapian::sortable_serialise (time_value));
 }

+static notmuch_private_status_t
+_notmuch_message_tags_to_maildir (notmuch_message_t *message);
+
 /* Synchronize changes made to message->doc out into the database. */
 void
 _notmuch_message_sync (notmuch_message_t *message)
 {
 Xapian::WritableDatabase *db;
+notmuch_private_status_t status;

 if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
return;

+if (// todo_sync_enabled &&
+   !notmuch_message_get_flag(message, NOTMUCH_MESSAGE_FLAG_TAGS_INVALID)) {
+   status = _notmuch_message_tags_to_maildir (message);
+   if (status != NOTMUCH_PRIVATE_STATUS_SUCCESS) {
+   fprintf (stderr, "Error: Cannot sync tags to maildir (%s)\n",
+notmuch_status_to_string ((notmuch_status_t)status));
+   /* Exit to avoid unsynchronized mailstore. */
+   exit(1);
+   }
+}
 db = static_cast  
(message->notmuch->xapian_db);
 db->replace_document (message->doc_id, message->doc);
 }
@@ -688,6 +720,44 @@ _notmuch_message_remove_term (notmuch_message_t *message,
 return NOTMUCH_PRIVATE_STATUS_SUCCESS;
 }

+/* Change the message filename stored in the database.
+ *
+ * This change will not be reflected in the database until the next
+ * call to _notmuch_message_sync.
+ */
+notmuch_private_status_t
+_notmuch_message_rename (notmuch_message_t *message,
+const char 

[PATCH 2/4] Maildir synchronization

2010-05-11 Thread Michal Sojka
This patch allows bi-directional synchronization between maildir
flags and certain tags. The flag-to-tag mapping is defined by flag2tag
array.

The synchronization works this way:

1) Whenever notmuch new is executed, the following happens:
   o New messages are tagged with configured new_tags.
   o For new or renamed messages with maildir info present in the file
 name, the tags defined in flag2tag are either added or removed
 depending on the flags from the file name.

2) Whenever notmuch tag (or notmuch restore) is executed, a new set of
   flags based on the tags is constructed for every message and a new
   file name is prepared based on the old file name but with the new
   flags. If the flags differs and the old message was in 'new'
   directory then this is replaced with 'cur' in the new file name. If
   the new and old file names differ, the file is renamed and notmuch
   database is updated accordingly.

   The rename happens before the database is updated. In case of crash
   between rename and database update, the next run of notmuch new
   brings the database in sync with the mail store again.

There is currenlty one known issue: Viewing/storing of attachments of
unread messages doesn't work. The reason is that when you view the
message its unread tag is removed which leads to rename of the file,
but Emacs still uses the original name to access the attachment.

Workaround: close the message and open it again.
---
 lib/database.cc   |7 ++
 lib/message.cc|  226 +
 lib/notmuch-private.h |4 +
 lib/notmuch.h |7 ++
 notmuch-new.c |3 +-
 5 files changed, 246 insertions(+), 1 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 694b7ec..908bbaa 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1585,6 +1585,13 @@ notmuch_database_add_message (notmuch_database_t 
*notmuch,
 
_notmuch_message_add_filename (message, filename);
 
+   /* This is a new message or it has a new filename and as such,
+* its tags in database either do not exists or might be out
+* of date. We assign the tags later in notmuch new, but until
+* then we should not synchronize the tags back to the maildir
+* flags (if notmuch is configured to do so). */
+   notmuch_message_set_flag(message, NOTMUCH_MESSAGE_FLAG_TAGS_INVALID, 
TRUE);
+
/* Is this a newly created message object? */
if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
_notmuch_message_add_term (message, type, mail);
diff --git a/lib/message.cc b/lib/message.cc
index 4b2f98f..0de3f01 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -43,6 +43,24 @@ struct _notmuch_message {
 Xapian::Document doc;
 };
 
+#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))
+
+struct maildir_flag_tag {
+char flag;
+const char *tag;
+bool inverse;
+};
+
+/* ASCII ordered table of Maildir flags and associated tags */
+struct maildir_flag_tag flag2tag[] = {
+{ 'D', draft,   false},
+{ 'F', flagged, false},
+{ 'P', passed,  false},
+{ 'R', replied, false},
+{ 'S', unread,  true },
+{ 'T', delete,  false},
+};
+
 /* We end up having to call the destructor explicitly because we had
  * to use placement new in order to initialize C++ objects within a
  * block that we allocated with talloc. So C++ is making talloc
@@ -568,15 +586,29 @@ _notmuch_message_set_date (notmuch_message_t *message,
Xapian::sortable_serialise (time_value));
 }
 
+static notmuch_private_status_t
+_notmuch_message_tags_to_maildir (notmuch_message_t *message);
+
 /* Synchronize changes made to message-doc out into the database. */
 void
 _notmuch_message_sync (notmuch_message_t *message)
 {
 Xapian::WritableDatabase *db;
+notmuch_private_status_t status;
 
 if (message-notmuch-mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
return;
 
+if (// todo_sync_enabled 
+   !notmuch_message_get_flag(message, NOTMUCH_MESSAGE_FLAG_TAGS_INVALID)) {
+   status = _notmuch_message_tags_to_maildir (message);
+   if (status != NOTMUCH_PRIVATE_STATUS_SUCCESS) {
+   fprintf (stderr, Error: Cannot sync tags to maildir (%s)\n,
+notmuch_status_to_string ((notmuch_status_t)status));
+   /* Exit to avoid unsynchronized mailstore. */
+   exit(1);
+   }
+}
 db = static_cast Xapian::WritableDatabase * 
(message-notmuch-xapian_db);
 db-replace_document (message-doc_id, message-doc);
 }
@@ -688,6 +720,44 @@ _notmuch_message_remove_term (notmuch_message_t *message,
 return NOTMUCH_PRIVATE_STATUS_SUCCESS;
 }
 
+/* Change the message filename stored in the database.
+ *
+ * This change will not be reflected in the database until the next
+ * call to _notmuch_message_sync.
+ */
+notmuch_private_status_t
+_notmuch_message_rename (notmuch_message_t *message,
+const