[geary/geary-0.6] Prevent losing emails during move operation: Bug #731561



commit 7c206095b7de73596b76e3db27b77e41c96d7f52
Author: Jim Nelson <jim yorba org>
Date:   Mon Jun 30 15:29:46 2014 -0700

    Prevent losing emails during move operation: Bug #731561
    
    Move operation could lose emails if the copy destination doesn't
    exist (or quota reached, etc.)  This de-pipelines the move operation
    into a copy and a delete, guaranteeing the delete only occurs if the
    copy succeeds.

 .../replay-ops/imap-engine-move-email.vala         |   17 +++++++---
 src/engine/imap/api/imap-folder.vala               |   31 --------------------
 2 files changed, 12 insertions(+), 36 deletions(-)
---
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala
index 40157d3..04d5a19 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala
@@ -59,11 +59,18 @@ private class Geary.ImapEngine.MoveEmail : Geary.ImapEngine.SendReplayOperation
     }
     
     public override async ReplayOperation.Status replay_remote_async() throws Error {
-        if (moved_ids.size > 0) {
-            yield engine.remote_folder.move_email_async(
-                new Imap.MessageSet.uid_sparse(ImapDB.EmailIdentifier.to_uids(moved_ids).to_array()),
-                destination, cancellable);
-        }
+        if (moved_ids.size == 0)
+            return ReplayOperation.Status.COMPLETED;
+        
+        // don't use Cancellable throughout I/O operations in order to assure transaction completes
+        // fully
+        if (cancellable != null && cancellable.is_cancelled())
+            throw new IOError.CANCELLED("Move email to %s cancelled", engine.remote_folder.to_string());
+        
+        Imap.MessageSet msg_set = new 
Imap.MessageSet.uid_sparse(ImapDB.EmailIdentifier.to_uids(moved_ids).to_array());
+        
+        yield engine.remote_folder.copy_email_async(msg_set, destination, null);
+        yield engine.remote_folder.remove_email_async(msg_set, null);
         
         return ReplayOperation.Status.COMPLETED;
     }
diff --git a/src/engine/imap/api/imap-folder.vala b/src/engine/imap/api/imap-folder.vala
index da6005e..2e37881 100644
--- a/src/engine/imap/api/imap-folder.vala
+++ b/src/engine/imap/api/imap-folder.vala
@@ -652,37 +652,6 @@ private class Geary.Imap.Folder : BaseObject {
             null, cancellable);
     }
     
-    // TODO: Support MOVE extension
-    public async void move_email_async(MessageSet msg_set, Geary.FolderPath destination,
-        Cancellable? cancellable) throws Error {
-        check_open();
-        
-        Gee.Collection<Command> cmds = new Gee.ArrayList<Command>();
-        
-        // Don't use copy_email_async followed by remove_email_async; this needs to be one
-        // set of commands executed in order without releasing the cmd_mutex; this is especially
-        // vital if positional addressing is used
-        cmds.add(new CopyCommand(msg_set, new MailboxSpecifier.from_folder_path(destination, null)));
-        
-        Gee.List<MessageFlag> flags = new Gee.ArrayList<MessageFlag>();
-        flags.add(MessageFlag.DELETED);
-        cmds.add(new StoreCommand(msg_set, flags, true, false));
-        
-        // TODO: Only use old-school EXPUNGE when closing folder (or rely on CLOSE to do that work
-        // for us).  See:
-        // http://redmine.yorba.org/issues/7532
-        //
-        // However, current client implementation doesn't properly close INBOX when application
-        // shuts down, which means deleted messages return at application start.  See:
-        // http://redmine.yorba.org/issues/6865
-        if (msg_set.is_uid && session.capabilities.supports_uidplus())
-            cmds.add(new ExpungeCommand.uid(msg_set));
-        else
-            cmds.add(new ExpungeCommand());
-        
-        yield exec_commands_async(cmds, null, null, cancellable);
-    }
-    
     public async Gee.SortedSet<Imap.UID>? search_async(SearchCriteria criteria, Cancellable? cancellable)
         throws Error {
         check_open();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]