Archive command archives two conversations: Closes #5079

Previously it was possible for the EXPUNGED server data's positional
addressing to be converted to the wrong EmailIdentifier, leading to
the wrong email being deleted, while the one the user asked for
was reported as missing as part of the ReplayQueue's local operation.
This commit is contained in:
Jim Nelson 2012-05-31 14:47:52 -07:00
parent 85bb2ae76a
commit 22b05994b2
2 changed files with 21 additions and 11 deletions

View file

@ -570,8 +570,8 @@ private class Geary.GenericImapFolder : Geary.AbstractFolder {
// This MUST only be called from ReplayRemoval.
internal async void do_replay_remove_message(int remote_position, int new_remote_count) {
debug("do_replay_remove_message: remote_position=%d new_remote_count=%d", remote_position,
new_remote_count);
debug("do_replay_remove_message: remote_position=%d remote_count=%d new_remote_count=%d",
remote_position, remote_count, new_remote_count);
assert(remote_position >= 1);
assert(new_remote_count >= 0);
@ -581,8 +581,12 @@ private class Geary.GenericImapFolder : Geary.AbstractFolder {
Geary.EmailIdentifier? owned_id = null;
try {
local_count = yield local_folder.get_email_count_async();
local_position = remote_position_to_local_position(remote_position, local_count);
local_count = yield local_folder.get_email_count_including_marked_async();
// can't use remote_position_to_local_position() because local_count includes messages
// marked for removal, which that helper function doesn't like
local_position = remote_position - (remote_count - local_count);
debug("do_replay_remove_message: local_count=%d local_position=%d", local_count, local_position);
Gee.List<Geary.Email>? list = yield local_folder.list_email_async(local_position,
1, Geary.Email.Field.NONE, Sqlite.Folder.ListFlags.INCLUDE_MARKED_FOR_REMOVE, null);
@ -612,7 +616,7 @@ private class Geary.GenericImapFolder : Geary.AbstractFolder {
// for debugging
int new_local_count = -1;
try {
new_local_count = yield local_folder.get_email_count_async();
new_local_count = yield local_folder.get_email_count_including_marked_async();
} catch (Error new_count_err) {
debug("Error fetching new local count for %s: %s", to_string(), new_count_err.message);
}

View file

@ -90,16 +90,21 @@ private class Geary.Sqlite.Folder : Object, Geary.ReferenceSemantics {
}
public async int get_email_count_async(Cancellable? cancellable = null) throws Error {
return yield internal_get_email_count_async(null, cancellable);
return yield internal_get_email_count_async(null, false, cancellable);
}
private async int internal_get_email_count_async(Transaction? transaction, Cancellable? cancellable)
public async int get_email_count_including_marked_async(Cancellable? cancellable = null)
throws Error {
return yield internal_get_email_count_async(null, true, cancellable);
}
private async int internal_get_email_count_async(Transaction? transaction, bool include_marked,
Cancellable? cancellable) throws Error {
check_open();
// TODO: This can be cached and updated when changes occur
return yield location_table.fetch_count_for_folder_async(transaction, folder_row.id, false,
cancellable);
return yield location_table.fetch_count_for_folder_async(transaction, folder_row.id,
include_marked, cancellable);
}
public async int get_id_position_async(Geary.EmailIdentifier id, Cancellable? cancellable)
@ -251,8 +256,9 @@ private class Geary.Sqlite.Folder : Object, Geary.ReferenceSemantics {
Transaction transaction = yield db.begin_transaction_async("Folder.list_email_async",
cancellable);
Geary.Folder.normalize_span_specifiers(ref low, ref count,
yield internal_get_email_count_async(transaction, cancellable));
int local_count = yield internal_get_email_count_async(transaction,
flags.is_all_set(ListFlags.INCLUDE_MARKED_FOR_REMOVE), cancellable);
Geary.Folder.normalize_span_specifiers(ref low, ref count, local_count);
if (count == 0)
return null;