Calling Message.tags_to_maildir_flags() when the database has been opened with a relative path results in a corrupted filename entry in the database. The actual filename is changed properly but the filename in the database gets the relative path prepended.
As I understand it's expected that the database path should be absolute but corrupting the database when the path is relative sounds dangerous. Attached is a python script showing the problem. Run it as follows: python ./retag_bug.py db_path +tag,-tag search_query Also attached is the output showing the problem.
$ notmuch search thread:00000000000005a2 thread:00000000000005a2 March 07 [1/1] Mathieu de Verdiere; [fablab brest] Echange PC DUINO contre ARDUINO MEGA+ramp? (inbox unread) $ python2 ./test.py ./maildir/ -unread thread:00000000000005a2 Using db at ./maildir/ Changing tags: -unread Search query: thread:00000000000005a2 Adding tags: [] Removing tags: ['unread'] Filename: ./maildir/cur/1425822991_0.10764.minux,U=2618,FMD5=7b0d668e0b18d8601b8bce4eec0ed930:2, Retagging thread:00000000000005a2 Adding [] Removing ['unread'] Sync maildir: True Found 1 messages to retag Retag done Filename: ./maildir/./maildir/cur/1425822991_0.10764.minux,U=2618,FMD5=7b0d668e0b18d8601b8bce4eec0ed930:2,S
import notmuch import sys def retag(db,search_query,add_list,remove_list,sync_maildir): query = db.create_query(search_query) print "Retagging %s"%search_query print "Adding %s"%add_list print "Removing %s"%remove_list print "Sync maildir: %s"%sync_maildir try: msg_list = list(query.search_messages()) print "Found %d messages to retag"%len(msg_list) db.begin_atomic() for msg in msg_list: msg.freeze() if remove_list == True: msg.remove_all_tags() else: for t in remove_list: msg.remove_tag(t) for t in add_list: msg.add_tag(t) msg.thaw() if sync_maildir: if msg.tags_to_maildir_flags() != notmuch.STATUS.SUCCESS: raise notmuch.NotmuchError() if db.end_atomic() != notmuch.STATUS.SUCCESS: raise notmuch.NotmuchError() print "Retag done" except notmuch.NotmuchError as e: print "Failed to retag" print e return False return True def show_filename(db,search_query): query = db.create_query(search_query) for msg in query.search_messages(): print "Filename: %s"%msg.get_filename() notmuch_path = sys.argv[1] notmuch_tags = sys.argv[2] notmuch_query = ' '.join(sys.argv[3:]) print "Using db at %s"%notmuch_path print "Changing tags: %s"%notmuch_tags print "Search query: %s"%notmuch_query add_list = list() remove_list = list() for it in notmuch_tags.split(','): if it[0] == '+': add_list.append(it[1:]) elif it[0] == '-': remove_list.append(it[1:]) print "Adding tags: %s"%add_list print "Removing tags: %s"%remove_list db = notmuch.Database(path=notmuch_path, mode=notmuch.Database.MODE.READ_ONLY) show_filename(db,notmuch_query) db.close() db = notmuch.Database(path=notmuch_path, mode=notmuch.Database.MODE.READ_WRITE) retag(db,notmuch_query,add_list,remove_list,True) db.close() db = notmuch.Database(path=notmuch_path, mode=notmuch.Database.MODE.READ_ONLY) show_filename(db,notmuch_query) db.close()
_______________________________________________ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch