[geary/mjog/imap-command-cancellation: 2/6] Geary.Imap: Make command cancellable a property of the command object
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/imap-command-cancellation: 2/6] Geary.Imap: Make command cancellable a property of the command object
- Date: Wed, 2 Sep 2020 06:03:49 +0000 (UTC)
commit 85e9046c717e520ee55e927e8709251f1ec1ff4e
Author: Michael Gratton <mike vee net>
Date: Tue Sep 1 22:42:41 2020 +1000
Geary.Imap: Make command cancellable a property of the command object
Since both submitting a command no longer requires a cancellable, and it
is desirable to avoid sending a queued command that has already been
cancelled beforehand, add a new `Command.should_send` Cancellable
property to specify if a command should (still) be sent or not, and stop
passing a cancellable to ClientSession when submitting commands.
Allow call sites to pass in existing cancellable objects, and thus also
add it it as a ctor property to the Command class and all subclasses.
Lastly, throw a cancelled exception in `wait_until_complete` if send
was cancelled so that the caller knows what happened.
Remove redundant cancellable argument from
`Imap.Client.command_transaction_async` and rename it to
`submit_command` to make it more obvious about what it does.
src/console/main.vala | 84 +++++++++----
src/engine/imap/api/imap-account-session.vala | 26 ++--
src/engine/imap/api/imap-client-service.vala | 2 +-
src/engine/imap/api/imap-folder-session.vala | 136 +++++++++++++++------
src/engine/imap/command/imap-append-command.vala | 9 +-
.../imap/command/imap-authenticate-command.vala | 12 +-
.../imap/command/imap-capability-command.vala | 7 +-
src/engine/imap/command/imap-close-command.vala | 7 +-
src/engine/imap/command/imap-command.vala | 32 ++++-
src/engine/imap/command/imap-compress-command.vala | 8 +-
src/engine/imap/command/imap-copy-command.vala | 6 +-
src/engine/imap/command/imap-create-command.vala | 9 +-
src/engine/imap/command/imap-delete-command.vala | 5 +-
src/engine/imap/command/imap-examine-command.vala | 5 +-
src/engine/imap/command/imap-expunge-command.vala | 9 +-
src/engine/imap/command/imap-fetch-command.vala | 20 +--
src/engine/imap/command/imap-id-command.vala | 9 +-
src/engine/imap/command/imap-idle-command.vala | 4 +-
src/engine/imap/command/imap-list-command.vala | 16 ++-
src/engine/imap/command/imap-login-command.vala | 9 +-
src/engine/imap/command/imap-logout-command.vala | 7 +-
.../imap/command/imap-namespace-command.vala | 4 +-
src/engine/imap/command/imap-noop-command.vala | 7 +-
src/engine/imap/command/imap-search-command.vala | 10 +-
src/engine/imap/command/imap-select-command.vala | 5 +-
src/engine/imap/command/imap-starttls-command.vala | 7 +-
src/engine/imap/command/imap-status-command.vala | 6 +-
src/engine/imap/command/imap-store-command.vala | 7 +-
.../imap/transport/imap-client-connection.vala | 2 +-
src/engine/imap/transport/imap-client-session.vala | 82 +++++++------
.../imap/command/imap-create-command-test.vala | 5 +-
.../imap/command/imap-fetch-command-test.vala | 10 +-
.../transport/imap-client-connection-test.vala | 2 +-
33 files changed, 381 insertions(+), 188 deletions(-)
---
diff --git a/src/console/main.vala b/src/console/main.vala
index b114c7e3a..015859862 100644
--- a/src/console/main.vala
+++ b/src/console/main.vala
@@ -290,13 +290,13 @@ class ImapConsole : Gtk.Window {
private void capabilities(string cmd, string[] args) throws Error {
check_connected(cmd, args, 0, null);
- this.cx.send_command(new Geary.Imap.CapabilityCommand());
+ this.cx.send_command(new Geary.Imap.CapabilityCommand(null));
}
- private void noop(string cmd, string[] args) throws Error {
+ private void noop(string cmd, string[] args) throws GLib.Error {
check_connected(cmd, args, 0, null);
- this.cx.send_command(new Geary.Imap.NoopCommand());
+ this.cx.send_command(new Geary.Imap.NoopCommand(null));
}
private void connect_cmd(string cmd, string[] args) throws Error {
@@ -370,7 +370,7 @@ class ImapConsole : Gtk.Window {
}
private async void do_starttls_async() throws Error {
- Geary.Imap.StarttlsCommand cmd = new Geary.Imap.StarttlsCommand();
+ Geary.Imap.StarttlsCommand cmd = new Geary.Imap.StarttlsCommand(null);
this.cx.send_command(cmd);
Geary.Imap.StatusResponse response = yield wait_for_response_async(cmd.tag);
@@ -394,14 +394,18 @@ class ImapConsole : Gtk.Window {
check_connected(cmd, args, 2, "user pass");
status("Logging in...");
- this.cx.send_command(new Geary.Imap.LoginCommand(args[0], args[1]));
+ this.cx.send_command(
+ new Geary.Imap.LoginCommand(args[0], args[1], null)
+ );
}
private void logout(string cmd, string[] args) throws Error {
check_connected(cmd, args, 0, null);
status("Logging out...");
- this.cx.send_command(new Geary.Imap.LogoutCommand());
+ this.cx.send_command(
+ new Geary.Imap.LogoutCommand(null)
+ );
}
private void id(string cmd, string[] args) throws Error {
@@ -413,14 +417,16 @@ class ImapConsole : Gtk.Window {
fields.set("name", "geary-console");
fields.set("version", _VERSION);
- this.cx.send_command(new Geary.Imap.IdCommand(fields));
+ this.cx.send_command(
+ new Geary.Imap.IdCommand(fields, null)
+ );
}
private void namespace(string cmd, string[] args) throws Error {
check_connected(cmd, args, 0, null);
status("Retrieving NAMESPACE...");
- this.cx.send_command(new Geary.Imap.NamespaceCommand());
+ this.cx.send_command(new Geary.Imap.NamespaceCommand(null));
}
private void list(string cmd, string[] args) throws Error {
@@ -437,7 +443,8 @@ class ImapConsole : Gtk.Window {
args[0],
new Geary.Imap.MailboxSpecifier(args[1]),
(cmd.down() == "xlist"),
- return_param
+ return_param,
+ null
)
);
}
@@ -446,7 +453,12 @@ class ImapConsole : Gtk.Window {
check_connected(cmd, args, 1, "<mailbox>");
status("Opening %s read-only".printf(args[0]));
- this.cx.send_command(new Geary.Imap.ExamineCommand(new Geary.Imap.MailboxSpecifier(args[0])));
+ this.cx.send_command(
+ new Geary.Imap.ExamineCommand(
+ new Geary.Imap.MailboxSpecifier(args[0]),
+ null
+ )
+ );
}
private void create(string cmd, string[] args) throws Error {
@@ -455,7 +467,8 @@ class ImapConsole : Gtk.Window {
status("Creating %s".printf(args[0]));
this.cx.send_command(
new Geary.Imap.CreateCommand(
- new Geary.Imap.MailboxSpecifier(args[0])
+ new Geary.Imap.MailboxSpecifier(args[0]),
+ null
)
);
}
@@ -466,7 +479,8 @@ class ImapConsole : Gtk.Window {
status("Deleting %s".printf(args[0]));
this.cx.send_command(
new Geary.Imap.DeleteCommand(
- new Geary.Imap.MailboxSpecifier(args[0])
+ new Geary.Imap.MailboxSpecifier(args[0]),
+ null
)
);
}
@@ -487,7 +501,9 @@ class ImapConsole : Gtk.Window {
data_items.add(data_type);
}
- this.cx.send_command(new Geary.Imap.FetchCommand(msg_set, data_items, null));
+ this.cx.send_command(
+ new Geary.Imap.FetchCommand(msg_set, data_items, null, null)
+ );
}
private void fetch_fields(string cmd, string[] args) throws Error {
@@ -501,8 +517,11 @@ class ImapConsole : Gtk.Window {
Gee.List<Geary.Imap.FetchBodyDataSpecifier> list = new
Gee.ArrayList<Geary.Imap.FetchBodyDataSpecifier>();
list.add(fields);
- this.cx.send_command(new Geary.Imap.FetchCommand(
- new Geary.Imap.MessageSet.custom(args[0]), null, list));
+ this.cx.send_command(
+ new Geary.Imap.FetchCommand(
+ new Geary.Imap.MessageSet.custom(args[0]), null, list, null
+ )
+ );
}
private void append(string cmd, string[] args) throws Error {
@@ -510,8 +529,15 @@ class ImapConsole : Gtk.Window {
status("Appending %s to %s".printf(args[1], args[0]));
- this.cx.send_command(new Geary.Imap.AppendCommand(new Geary.Imap.MailboxSpecifier(args[0]),
- null, null, new Geary.Memory.FileBuffer(File.new_for_path(args[1]), true)));
+ this.cx.send_command(
+ new Geary.Imap.AppendCommand(
+ new Geary.Imap.MailboxSpecifier(args[0]),
+ null,
+ null,
+ new Geary.Memory.FileBuffer(File.new_for_path(args[1]), true),
+ null
+ )
+ );
}
private void search(string cmd, string[] args) throws Error {
@@ -525,9 +551,9 @@ class ImapConsole : Gtk.Window {
Geary.Imap.SearchCommand search;
if (cmd == "uid-search")
- search = new Geary.Imap.SearchCommand.uid(criteria);
+ search = new Geary.Imap.SearchCommand.uid(criteria, null);
else
- search = new Geary.Imap.SearchCommand(criteria);
+ search = new Geary.Imap.SearchCommand(criteria, null);
this.cx.send_command(search);
}
@@ -537,7 +563,9 @@ class ImapConsole : Gtk.Window {
status("Closing");
- this.cx.send_command(new Geary.Imap.CloseCommand());
+ this.cx.send_command(
+ new Geary.Imap.CloseCommand(null)
+ );
}
private void folder_status(string cmd, string[] args) throws Error {
@@ -551,8 +579,13 @@ class ImapConsole : Gtk.Window {
data_items += Geary.Imap.StatusDataType.from_parameter(stringp);
}
- this.cx.send_command(new Geary.Imap.StatusCommand(new Geary.Imap.MailboxSpecifier(args[0]),
- data_items));
+ this.cx.send_command(
+ new Geary.Imap.StatusCommand(
+ new Geary.Imap.MailboxSpecifier(args[0]),
+ data_items,
+ null
+ )
+ );
}
private void preview(string cmd, string[] args) throws Error {
@@ -567,8 +600,11 @@ class ImapConsole : Gtk.Window {
Gee.ArrayList<Geary.Imap.FetchBodyDataSpecifier> list = new
Gee.ArrayList<Geary.Imap.FetchBodyDataSpecifier>();
list.add(preview_data_type);
- this.cx.send_command(new Geary.Imap.FetchCommand(
- new Geary.Imap.MessageSet.custom(args[0]), null, list));
+ this.cx.send_command(
+ new Geary.Imap.FetchCommand(
+ new Geary.Imap.MessageSet.custom(args[0]), null, list, null
+ )
+ );
}
private void quit(string cmd, string[] args) throws Error {
diff --git a/src/engine/imap/api/imap-account-session.vala b/src/engine/imap/api/imap-account-session.vala
index 7c12f4d18..238bd85cc 100644
--- a/src/engine/imap/api/imap-account-session.vala
+++ b/src/engine/imap/api/imap-account-session.vala
@@ -97,9 +97,11 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
ClientSession session = claim_session();
MailboxSpecifier mailbox = session.get_mailbox_for_path(path);
bool can_create_special = session.capabilities.has_capability(Capabilities.CREATE_SPECIAL_USE);
- CreateCommand cmd = (use != null && can_create_special)
- ? new CreateCommand.special_use(mailbox, use)
- : new CreateCommand(mailbox);
+ CreateCommand cmd = (
+ use != null && can_create_special
+ ? new CreateCommand.special_use(mailbox, use, cancellable)
+ : new CreateCommand(mailbox, cancellable)
+ );
StatusResponse response = yield send_command_async(
session, cmd, null, null, cancellable
@@ -187,7 +189,9 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
// Mailbox needs a SELECT
info_map.set(mailbox_info.mailbox, mailbox_info);
cmd_map.set(
- new StatusCommand(mailbox_info.mailbox, StatusDataType.all()),
+ new StatusCommand(
+ mailbox_info.mailbox, StatusDataType.all(), cancellable
+ ),
mailbox_info.mailbox
);
} else {
@@ -323,7 +327,10 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
if (folder.is_root) {
// List the server root
cmd = new ListCommand.wildcarded(
- "", new MailboxSpecifier("%"), use_xlist, return_param
+ "", new MailboxSpecifier("%"),
+ use_xlist,
+ return_param,
+ cancellable
);
} else {
// List either the given folder or its children
@@ -335,7 +342,12 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
}
specifier = specifier + delim + "%";
}
- cmd = new ListCommand(new MailboxSpecifier(specifier), use_xlist, return_param);
+ cmd = new ListCommand(
+ new MailboxSpecifier(specifier),
+ use_xlist,
+ return_param,
+ cancellable
+ );
}
Gee.List<MailboxInformation> list_results = new Gee.ArrayList<MailboxInformation>();
@@ -372,7 +384,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
Gee.List<StatusData> status_results = new Gee.ArrayList<StatusData>();
StatusResponse response = yield send_command_async(
session,
- new StatusCommand(mailbox, status_types),
+ new StatusCommand(mailbox, status_types, cancellable),
null,
status_results,
cancellable
diff --git a/src/engine/imap/api/imap-client-service.vala b/src/engine/imap/api/imap-client-service.vala
index b20da56c0..e0aad41b3 100644
--- a/src/engine/imap/api/imap-client-service.vala
+++ b/src/engine/imap/api/imap-client-service.vala
@@ -430,7 +430,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
try {
debug("Sending NOOP when claiming a session");
yield target.send_command_async(
- new NoopCommand(), this.close_cancellable
+ new NoopCommand(this.close_cancellable)
);
} catch (Error err) {
debug("Error sending NOOP: %s", err.message);
diff --git a/src/engine/imap/api/imap-folder-session.vala b/src/engine/imap/api/imap-folder-session.vala
index 9bc61aca8..092c06cde 100644
--- a/src/engine/imap/api/imap-folder-session.vala
+++ b/src/engine/imap/api/imap-folder-session.vala
@@ -159,7 +159,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
public async void send_noop(GLib.Cancellable? cancellable)
throws GLib.Error {
yield exec_commands_async(
- Collection.single(new NoopCommand()),
+ Collection.single(new NoopCommand(cancellable)),
null,
null,
cancellable
@@ -334,12 +334,13 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
}
// Utility method for listing UIDs on the remote within the supplied range
- public async Gee.Set<Imap.UID>? list_uids_async(MessageSet msg_set, Cancellable? cancellable)
- throws Error {
+ public async Gee.Set<Imap.UID>? list_uids_async(MessageSet msg_set,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
// Although FETCH could be used, SEARCH is more efficient in returning pure UID results,
// which is all we're interested in here
SearchCriteria criteria = new SearchCriteria(SearchCriterion.message_set(msg_set));
- SearchCommand cmd = new SearchCommand.uid(criteria);
+ SearchCommand cmd = new SearchCommand.uid(criteria, cancellable);
Gee.Set<Imap.UID> search_results = new Gee.HashSet<Imap.UID>();
yield exec_commands_async(
@@ -355,6 +356,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
private Gee.Collection<FetchCommand> assemble_list_commands(
Imap.MessageSet msg_set,
Geary.Email.Field fields,
+ GLib.Cancellable? cancellable,
out FetchBodyDataSpecifier[]? header_specifiers,
out FetchBodyDataSpecifier? body_specifier,
out FetchBodyDataSpecifier? preview_specifier,
@@ -369,8 +371,13 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
// pulled down, not a guarantee); if request is for NONE, that guarantees that the
// EmailIdentifier will be set, and so fetch UIDs (which looks funny but works when
// listing a range for contents: UID FETCH x:y UID)
- if (!msg_set.is_uid || fields == Geary.Email.Field.NONE)
- cmds.add(new FetchCommand.data_type(msg_set, FetchDataSpecifier.UID));
+ if (!msg_set.is_uid || fields == Geary.Email.Field.NONE) {
+ cmds.add(
+ new FetchCommand.data_type(
+ msg_set, FetchDataSpecifier.UID, cancellable
+ )
+ );
+ }
// convert bulk of the "basic" fields into a one or two FETCH commands (some servers have
// exhibited bugs or return NO when too many FETCH data types are combined on a single
@@ -385,7 +392,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
// Add all simple data types as one FETCH command
if (!basic_types.is_empty) {
- cmds.add(new FetchCommand(msg_set, basic_types, null));
+ cmds.add(
+ new FetchCommand(msg_set, basic_types, null, cancellable)
+ );
}
// Add all header field requests as separate FETCH
@@ -424,7 +433,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
if (this.quirks.fetch_header_part_no_space) {
header.omit_request_header_fields_space();
}
- cmds.add(new FetchCommand.body_data_type(msg_set, header));
+ cmds.add(
+ new FetchCommand.body_data_type(
+ msg_set, header, cancellable
+ )
+ );
}
}
}
@@ -434,7 +447,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
body_specifier = new FetchBodyDataSpecifier.peek(FetchBodyDataSpecifier.SectionPart.TEXT,
null, -1, -1, null);
- cmds.add(new FetchCommand.body_data_type(msg_set, body_specifier));
+ cmds.add(
+ new FetchCommand.body_data_type(
+ msg_set, body_specifier, cancellable
+ )
+ );
} else {
body_specifier = null;
}
@@ -453,12 +470,20 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
preview_specifier = new FetchBodyDataSpecifier.peek(FetchBodyDataSpecifier.SectionPart.NONE,
{ 1 }, 0, Geary.Email.MAX_PREVIEW_BYTES, null);
- cmds.add(new FetchCommand.body_data_type(msg_set, preview_specifier));
+ cmds.add(
+ new FetchCommand.body_data_type(
+ msg_set, preview_specifier, cancellable
+ )
+ );
// Also get the character set to properly decode it
preview_charset_specifier = new FetchBodyDataSpecifier.peek(
FetchBodyDataSpecifier.SectionPart.MIME, { 1 }, -1, -1, null);
- cmds.add(new FetchCommand.body_data_type(msg_set, preview_charset_specifier));
+ cmds.add(
+ new FetchCommand.body_data_type(
+ msg_set, preview_charset_specifier, cancellable
+ )
+ );
} else {
preview_specifier = null;
preview_charset_specifier = null;
@@ -476,7 +501,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
if (fields.require(Geary.Email.Field.FLAGS))
data_types.add(FetchDataSpecifier.FLAGS);
- cmds.add(new FetchCommand(msg_set, data_types, null));
+ cmds.add(new FetchCommand(msg_set, data_types, null, cancellable));
}
return cmds;
@@ -498,6 +523,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
Gee.Collection<FetchCommand> cmds = assemble_list_commands(
msg_set,
fields,
+ cancellable,
out header_specifiers,
out body_specifier,
out preview_specifier,
@@ -593,7 +619,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
}
Gee.List<Command> cmds = new Gee.ArrayList<Command>();
- cmds.add(new FetchCommand.data_type(msg_set, FetchDataSpecifier.UID));
+ cmds.add(
+ new FetchCommand.data_type(
+ msg_set, FetchDataSpecifier.UID, cancellable
+ )
+ );
Gee.HashMap<SequenceNumber, FetchedData> fetched =
new Gee.HashMap<SequenceNumber, FetchedData>();
@@ -613,8 +643,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
return map;
}
- public async void remove_email_async(Gee.List<MessageSet> msg_sets, Cancellable? cancellable)
- throws Error {
+ public async void remove_email_async(Gee.List<MessageSet> msg_sets,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
ClientSession session = claim_session();
Gee.List<MessageFlag> flags = new Gee.ArrayList<MessageFlag>();
flags.add(MessageFlag.DELETED);
@@ -627,7 +658,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
if (!msg_set.is_uid)
all_uid = false;
- cmds.add(new StoreCommand(msg_set, flags, StoreCommand.Option.ADD_FLAGS));
+ cmds.add(
+ new StoreCommand(msg_set, flags, StoreCommand.Option.ADD_FLAGS, cancellable)
+ );
}
// TODO: Only use old-school EXPUNGE when closing folder (or rely on CLOSE to do that work
@@ -638,10 +671,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
// shuts down, which means deleted messages return at application start. See:
// http://redmine.yorba.org/issues/6865
if (all_uid && session.capabilities.supports_uidplus()) {
- foreach (MessageSet msg_set in msg_sets)
- cmds.add(new ExpungeCommand.uid(msg_set));
+ foreach (MessageSet msg_set in msg_sets) {
+ cmds.add(new ExpungeCommand.uid(msg_set, cancellable));
+ }
} else {
- cmds.add(new ExpungeCommand());
+ cmds.add(new ExpungeCommand(cancellable));
}
yield exec_commands_async(cmds, null, null, cancellable);
@@ -659,11 +693,21 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
Gee.Collection<Command> cmds = new Gee.ArrayList<Command>();
foreach (MessageSet msg_set in msg_sets) {
- if (msg_flags_add.size > 0)
- cmds.add(new StoreCommand(msg_set, msg_flags_add, StoreCommand.Option.ADD_FLAGS));
+ if (msg_flags_add.size > 0) {
+ cmds.add(
+ new StoreCommand(
+ msg_set, msg_flags_add, ADD_FLAGS, cancellable
+ )
+ );
+ }
- if (msg_flags_remove.size > 0)
- cmds.add(new StoreCommand(msg_set, msg_flags_remove, StoreCommand.Option.REMOVE_FLAGS));
+ if (msg_flags_remove.size > 0) {
+ cmds.add(
+ new StoreCommand(
+ msg_set, msg_flags_remove, REMOVE_FLAGS, cancellable
+ )
+ );
+ }
}
yield exec_commands_async(cmds, null, null, cancellable);
@@ -671,12 +715,14 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
// Returns a mapping of the source UID to the destination UID. If the MessageSet is not for
// UIDs, then null is returned. If the server doesn't support COPYUID, null is returned.
- public async Gee.Map<UID, UID>? copy_email_async(MessageSet msg_set, FolderPath destination,
- Cancellable? cancellable) throws Error {
+ public async Gee.Map<UID, UID>? copy_email_async(MessageSet msg_set,
+ FolderPath destination,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
ClientSession session = claim_session();
MailboxSpecifier mailbox = session.get_mailbox_for_path(destination);
- CopyCommand cmd = new CopyCommand(msg_set, mailbox);
+ CopyCommand cmd = new CopyCommand(msg_set, mailbox, cancellable);
Gee.Map<Command, StatusResponse>? responses = yield exec_commands_async(
Geary.iterate<Command>(cmd).to_array_list(), null, null, cancellable);
@@ -718,11 +764,12 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
return null;
}
- public async Gee.SortedSet<Imap.UID>? search_async(SearchCriteria criteria, Cancellable? cancellable)
- throws Error {
+ public async Gee.SortedSet<Imap.UID>? search_async(SearchCriteria criteria,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
// always perform a UID SEARCH
Gee.Collection<Command> cmds = new Gee.ArrayList<Command>();
- cmds.add(new SearchCommand.uid(criteria));
+ cmds.add(new SearchCommand.uid(criteria, cancellable));
Gee.Set<Imap.UID> search_results = new Gee.HashSet<Imap.UID>();
yield exec_commands_async(cmds, null, search_results, cancellable);
@@ -1044,12 +1091,22 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
return email;
}
- // Returns a no-message-id ImapDB.EmailIdentifier with the UID stored in it.
- // This method does not take a cancellable; there is currently no way to tell if an email was
- // created or not if exec_commands_async() is cancelled during the append. For atomicity's sake,
- // callers need to remove the returned email ID if a cancel occurred.
- public async Geary.EmailIdentifier? create_email_async(RFC822.Message message, Geary.EmailFlags? flags,
- DateTime? date_received) throws Error {
+ /**
+ * Stores a new message in the remote mailbox.
+ *
+ * Returns a no-message-id ImapDB.EmailIdentifier with the UID
+ * stored in it.
+ *
+ * This method does not take a cancellable; there is currently no
+ * way to tell if an email was created or not if {@link
+ * exec_commands_async} is cancelled during the append. For
+ * atomicity's sake, callers need to remove the returned email ID
+ * if a cancel occurred.
+ */
+ public async Geary.EmailIdentifier? create_email_async(RFC822.Message message,
+ Geary.EmailFlags? flags,
+ GLib.DateTime? date_received)
+ throws GLib.Error {
ClientSession session = claim_session();
MessageFlags? msg_flags = null;
@@ -1066,11 +1123,16 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
MailboxSpecifier mailbox = session.get_mailbox_for_path(this.folder.path);
AppendCommand cmd = new AppendCommand(
- mailbox, msg_flags, internaldate, message.get_rfc822_buffer()
+ mailbox,
+ msg_flags,
+ internaldate,
+ message.get_rfc822_buffer(),
+ null
);
Gee.Map<Command, StatusResponse> responses = yield exec_commands_async(
- Geary.iterate<AppendCommand>(cmd).to_array_list(), null, null, null);
+ Geary.iterate<AppendCommand>(cmd).to_array_list(), null, null, null
+ );
// Grab the response and parse out the UID, if available.
StatusResponse response = responses.get(cmd);
diff --git a/src/engine/imap/command/imap-append-command.vala
b/src/engine/imap/command/imap-append-command.vala
index d0cc6c780..44dec83f6 100644
--- a/src/engine/imap/command/imap-append-command.vala
+++ b/src/engine/imap/command/imap-append-command.vala
@@ -14,9 +14,12 @@ public class Geary.Imap.AppendCommand : Command {
public const string NAME = "append";
- public AppendCommand(MailboxSpecifier mailbox, MessageFlags? flags, InternalDate? internal_date,
- Memory.Buffer message) {
- base (NAME);
+ public AppendCommand(MailboxSpecifier mailbox,
+ MessageFlags? flags,
+ InternalDate? internal_date,
+ Memory.Buffer message,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.args.add(mailbox.to_parameter());
diff --git a/src/engine/imap/command/imap-authenticate-command.vala
b/src/engine/imap/command/imap-authenticate-command.vala
index 041de90e3..a7a0c1866 100644
--- a/src/engine/imap/command/imap-authenticate-command.vala
+++ b/src/engine/imap/command/imap-authenticate-command.vala
@@ -27,17 +27,21 @@ public class Geary.Imap.AuthenticateCommand : Command {
private GLib.Cancellable error_cancellable = new GLib.Cancellable();
- private AuthenticateCommand(string method, string data) {
- base(NAME, { method, data });
+ private AuthenticateCommand(string method,
+ string data,
+ GLib.Cancellable? should_send) {
+ base(NAME, { method, data }, should_send);
this.method = method;
this.error_lock = new Geary.Nonblocking.Spinlock(this.error_cancellable);
}
- public AuthenticateCommand.oauth2(string user, string token) {
+ public AuthenticateCommand.oauth2(string user,
+ string token,
+ GLib.Cancellable? should_send) {
string encoded_token = Base64.encode(
OAUTH2_RESP.printf(user, token).data
);
- this(OAUTH2_METHOD, encoded_token);
+ this(OAUTH2_METHOD, encoded_token, should_send);
}
internal override async void send(Serializer ser,
diff --git a/src/engine/imap/command/imap-capability-command.vala
b/src/engine/imap/command/imap-capability-command.vala
index 0f353997d..f32731553 100644
--- a/src/engine/imap/command/imap-capability-command.vala
+++ b/src/engine/imap/command/imap-capability-command.vala
@@ -11,10 +11,11 @@
*/
public class Geary.Imap.CapabilityCommand : Command {
+
public const string NAME = "capability";
- public CapabilityCommand() {
- base (NAME);
+ public CapabilityCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
-}
+}
diff --git a/src/engine/imap/command/imap-close-command.vala b/src/engine/imap/command/imap-close-command.vala
index 1dac6a97b..96f154270 100644
--- a/src/engine/imap/command/imap-close-command.vala
+++ b/src/engine/imap/command/imap-close-command.vala
@@ -9,10 +9,11 @@
*/
public class Geary.Imap.CloseCommand : Command {
+
public const string NAME = "close";
- public CloseCommand() {
- base (NAME);
+ public CloseCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
-}
+}
diff --git a/src/engine/imap/command/imap-command.vala b/src/engine/imap/command/imap-command.vala
index 581636710..94d877620 100644
--- a/src/engine/imap/command/imap-command.vala
+++ b/src/engine/imap/command/imap-command.vala
@@ -60,6 +60,20 @@ public abstract class Geary.Imap.Command : BaseObject {
/** The status response for the command, once it has been received. */
public StatusResponse? status { get; private set; default = null; }
+ /**
+ * A guard to allow cancelling a command before it is sent.
+ *
+ * Since IMAP does not allow commands that have been sent to the
+ * server to be cancelled, cancelling a command before sending it
+ * is the last opportunity to prevent it from being executed. A
+ * command queued to be sent will be sent as long as the
+ * connection it was queued is open and this cancellable is null
+ * or is not cancelled.
+ *
+ * @see Command.Command
+ */
+ public GLib.Cancellable? should_send { get; private set; default = null; }
+
/**
* The command's arguments as parameters.
*
@@ -93,11 +107,15 @@ public abstract class Geary.Imap.Command : BaseObject {
* Constructs a new command with an unassigned tag.
*
* Any arguments provided here will be converted to appropriate
- * string arguments
+ * string arguments. The given cancellable will be set as {@link
+ * should_send}.
*
* @see Tag
+ * @see should_send
*/
- protected Command(string name, string[]? args = null) {
+ protected Command(string name,
+ string[]? args,
+ GLib.Cancellable? should_send) {
this.tag = Tag.get_unassigned();
this.name = name;
if (args != null) {
@@ -105,6 +123,7 @@ public abstract class Geary.Imap.Command : BaseObject {
this.args.add(Parameter.get_for_string(arg));
}
}
+ this.should_send = should_send;
this.response_timer = new TimeoutManager.seconds(
this._response_timeout, on_response_timeout
@@ -269,6 +288,15 @@ public abstract class Geary.Imap.Command : BaseObject {
this.status.to_string()
);
}
+
+ // If everything else looks fine, but sending was cancelled,
+ // throw an error here so the caller knows that was the case.
+ if (this.should_send != null &&
+ this.should_send.is_cancelled()) {
+ throw new GLib.IOError.CANCELLED(
+ "Sent command was cancelled: %s", to_brief_string()
+ );
+ }
}
public virtual string to_string() {
diff --git a/src/engine/imap/command/imap-compress-command.vala
b/src/engine/imap/command/imap-compress-command.vala
index 98ca05fff..20ea0aa5a 100644
--- a/src/engine/imap/command/imap-compress-command.vala
+++ b/src/engine/imap/command/imap-compress-command.vala
@@ -9,12 +9,14 @@
*/
public class Geary.Imap.CompressCommand : Command {
+
public const string NAME = "compress";
public const string ALGORITHM_DEFLATE = "deflate";
- public CompressCommand(string algorithm) {
- base (NAME, { algorithm });
+
+ public CompressCommand(string algorithm, GLib.Cancellable? should_send) {
+ base(NAME, { algorithm }, should_send);
}
-}
+}
diff --git a/src/engine/imap/command/imap-copy-command.vala b/src/engine/imap/command/imap-copy-command.vala
index 2b25264c1..45a864751 100644
--- a/src/engine/imap/command/imap-copy-command.vala
+++ b/src/engine/imap/command/imap-copy-command.vala
@@ -13,8 +13,10 @@ public class Geary.Imap.CopyCommand : Command {
public const string NAME = "copy";
public const string UID_NAME = "uid copy";
- public CopyCommand(MessageSet message_set, MailboxSpecifier destination) {
- base(message_set.is_uid ? UID_NAME : NAME);
+ public CopyCommand(MessageSet message_set,
+ MailboxSpecifier destination,
+ GLib.Cancellable? should_send) {
+ base(message_set.is_uid ? UID_NAME : NAME, null, should_send);
this.args.add(message_set.to_parameter());
this.args.add(destination.to_parameter());
diff --git a/src/engine/imap/command/imap-create-command.vala
b/src/engine/imap/command/imap-create-command.vala
index 3cbf3feee..4a56712b6 100644
--- a/src/engine/imap/command/imap-create-command.vala
+++ b/src/engine/imap/command/imap-create-command.vala
@@ -55,15 +55,16 @@ public class Geary.Imap.CreateCommand : Command {
}
}
- public CreateCommand(MailboxSpecifier mailbox) {
- base(NAME_ATOM);
+ public CreateCommand(MailboxSpecifier mailbox, GLib.Cancellable? should_send) {
+ base(NAME_ATOM, null, should_send);
this.mailbox = mailbox;
this.args.add(mailbox.to_parameter());
}
public CreateCommand.special_use(MailboxSpecifier mailbox,
- Geary.Folder.SpecialUse use) {
- this(mailbox);
+ Geary.Folder.SpecialUse use,
+ GLib.Cancellable? should_send) {
+ this(mailbox, should_send);
this.use = use;
MailboxAttribute? attr = get_special_folder_type(use);
diff --git a/src/engine/imap/command/imap-delete-command.vala
b/src/engine/imap/command/imap-delete-command.vala
index e183f5107..dc35f58c2 100644
--- a/src/engine/imap/command/imap-delete-command.vala
+++ b/src/engine/imap/command/imap-delete-command.vala
@@ -18,8 +18,9 @@ public class Geary.Imap.DeleteCommand : Command {
public const string NAME = "DELETE";
- public DeleteCommand(MailboxSpecifier mailbox) {
- base(NAME);
+ public DeleteCommand(MailboxSpecifier mailbox,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.args.add(mailbox.to_parameter());
}
diff --git a/src/engine/imap/command/imap-examine-command.vala
b/src/engine/imap/command/imap-examine-command.vala
index 5b2e28376..4820bf334 100644
--- a/src/engine/imap/command/imap-examine-command.vala
+++ b/src/engine/imap/command/imap-examine-command.vala
@@ -16,8 +16,9 @@ public class Geary.Imap.ExamineCommand : Command {
public MailboxSpecifier mailbox { get; private set; }
- public ExamineCommand(MailboxSpecifier mailbox) {
- base(NAME);
+ public ExamineCommand(MailboxSpecifier mailbox,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.mailbox = mailbox;
this.args.add(mailbox.to_parameter());
}
diff --git a/src/engine/imap/command/imap-expunge-command.vala
b/src/engine/imap/command/imap-expunge-command.vala
index be5b3445a..7eb533160 100644
--- a/src/engine/imap/command/imap-expunge-command.vala
+++ b/src/engine/imap/command/imap-expunge-command.vala
@@ -14,12 +14,13 @@ public class Geary.Imap.ExpungeCommand : Command {
public const string NAME = "expunge";
public const string UID_NAME = "uid expunge";
- public ExpungeCommand() {
- base(NAME);
+ public ExpungeCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
- public ExpungeCommand.uid(MessageSet message_set) {
- base(UID_NAME);
+ public ExpungeCommand.uid(MessageSet message_set,
+ GLib.Cancellable? should_send) {
+ base(UID_NAME, null, should_send);
assert(message_set.is_uid);
this.args.add(message_set.to_parameter());
}
diff --git a/src/engine/imap/command/imap-fetch-command.vala b/src/engine/imap/command/imap-fetch-command.vala
index 498b6779e..601494d75 100644
--- a/src/engine/imap/command/imap-fetch-command.vala
+++ b/src/engine/imap/command/imap-fetch-command.vala
@@ -34,9 +34,11 @@ public class Geary.Imap.FetchCommand : Command {
public Gee.List<FetchBodyDataSpecifier> for_body_data_specifiers { get; private set;
default = new Gee.ArrayList<FetchBodyDataSpecifier>(); }
- public FetchCommand(MessageSet msg_set, Gee.List<FetchDataSpecifier>? data_items,
- Gee.List<FetchBodyDataSpecifier>? body_data_items) {
- base (msg_set.is_uid ? UID_NAME : NAME);
+ public FetchCommand(MessageSet msg_set,
+ Gee.List<FetchDataSpecifier>? data_items,
+ Gee.List<FetchBodyDataSpecifier>? body_data_items,
+ GLib.Cancellable? should_send) {
+ base(msg_set.is_uid ? UID_NAME : NAME, null, should_send);
this.args.add(msg_set.to_parameter());
@@ -71,8 +73,10 @@ public class Geary.Imap.FetchCommand : Command {
for_body_data_specifiers.add_all(body_data_items);
}
- public FetchCommand.data_type(MessageSet msg_set, FetchDataSpecifier data_type) {
- base (msg_set.is_uid ? UID_NAME : NAME);
+ public FetchCommand.data_type(MessageSet msg_set,
+ FetchDataSpecifier data_type,
+ GLib.Cancellable? should_send) {
+ base(msg_set.is_uid ? UID_NAME : NAME, null, should_send);
for_data_types.add(data_type);
@@ -80,8 +84,10 @@ public class Geary.Imap.FetchCommand : Command {
this.args.add(data_type.to_parameter());
}
- public FetchCommand.body_data_type(MessageSet msg_set, FetchBodyDataSpecifier body_data_specifier) {
- base (msg_set.is_uid ? UID_NAME : NAME);
+ public FetchCommand.body_data_type(MessageSet msg_set,
+ FetchBodyDataSpecifier body_data_specifier,
+ GLib.Cancellable? should_send) {
+ base(msg_set.is_uid ? UID_NAME : NAME, null, should_send);
for_body_data_specifiers.add(body_data_specifier);
diff --git a/src/engine/imap/command/imap-id-command.vala b/src/engine/imap/command/imap-id-command.vala
index b3be2451c..459c3c2f2 100644
--- a/src/engine/imap/command/imap-id-command.vala
+++ b/src/engine/imap/command/imap-id-command.vala
@@ -12,8 +12,9 @@ public class Geary.Imap.IdCommand : Command {
public const string NAME = "id";
- public IdCommand(Gee.HashMap<string, string> fields) {
- base(NAME);
+ public IdCommand(Gee.HashMap<string, string> fields,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
ListParameter list = new ListParameter();
foreach (string key in fields.keys) {
@@ -24,8 +25,8 @@ public class Geary.Imap.IdCommand : Command {
this.args.add(list);
}
- public IdCommand.nil() {
- base(NAME);
+ public IdCommand.nil(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.args.add(NilParameter.instance);
}
diff --git a/src/engine/imap/command/imap-idle-command.vala b/src/engine/imap/command/imap-idle-command.vala
index 069bea5b9..df36b2df8 100644
--- a/src/engine/imap/command/imap-idle-command.vala
+++ b/src/engine/imap/command/imap-idle-command.vala
@@ -25,8 +25,8 @@ public class Geary.Imap.IdleCommand : Command {
private GLib.Cancellable? exit_cancellable = new GLib.Cancellable();
- public IdleCommand() {
- base(NAME);
+ public IdleCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.exit_lock = new Geary.Nonblocking.Semaphore(this.exit_cancellable);
}
diff --git a/src/engine/imap/command/imap-list-command.vala b/src/engine/imap/command/imap-list-command.vala
index 48eba3323..5ca6d232f 100644
--- a/src/engine/imap/command/imap-list-command.vala
+++ b/src/engine/imap/command/imap-list-command.vala
@@ -38,16 +38,22 @@ public class Geary.Imap.ListCommand : Command {
*
* See [[http://redmine.yorba.org/issues/7624]] for more information.
*/
- public ListCommand(MailboxSpecifier mailbox, bool use_xlist, ListReturnParameter? return_param) {
- base(use_xlist ? XLIST_NAME : NAME, { "" });
+ public ListCommand(MailboxSpecifier mailbox,
+ bool use_xlist,
+ ListReturnParameter? return_param,
+ GLib.Cancellable? should_send) {
+ base(use_xlist ? XLIST_NAME : NAME, { "" }, should_send);
this.args.add(mailbox.to_parameter());
add_return_parameter(return_param);
}
- public ListCommand.wildcarded(string reference, MailboxSpecifier mailbox, bool use_xlist,
- ListReturnParameter? return_param) {
- base(use_xlist ? XLIST_NAME : NAME, { reference });
+ public ListCommand.wildcarded(string reference,
+ MailboxSpecifier mailbox,
+ bool use_xlist,
+ ListReturnParameter? return_param,
+ GLib.Cancellable? should_send) {
+ base(use_xlist ? XLIST_NAME : NAME, { reference }, should_send);
this.args.add(mailbox.to_parameter());
add_return_parameter(return_param);
diff --git a/src/engine/imap/command/imap-login-command.vala b/src/engine/imap/command/imap-login-command.vala
index c31147806..48bb4d8ef 100644
--- a/src/engine/imap/command/imap-login-command.vala
+++ b/src/engine/imap/command/imap-login-command.vala
@@ -9,14 +9,17 @@
*/
public class Geary.Imap.LoginCommand : Command {
+
public const string NAME = "login";
- public LoginCommand(string user, string pass) {
- base (NAME, { user, pass });
+ public LoginCommand(string user,
+ string pass,
+ GLib.Cancellable? should_send) {
+ base(NAME, { user, pass }, should_send);
}
public override string to_string() {
return "%s %s <user> <pass>".printf(tag.to_string(), name);
}
-}
+}
diff --git a/src/engine/imap/command/imap-logout-command.vala
b/src/engine/imap/command/imap-logout-command.vala
index 7e81fc541..9ff7d83c2 100644
--- a/src/engine/imap/command/imap-logout-command.vala
+++ b/src/engine/imap/command/imap-logout-command.vala
@@ -9,10 +9,11 @@
*/
public class Geary.Imap.LogoutCommand : Command {
+
public const string NAME = "logout";
- public LogoutCommand() {
- base (NAME);
+ public LogoutCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
-}
+}
diff --git a/src/engine/imap/command/imap-namespace-command.vala
b/src/engine/imap/command/imap-namespace-command.vala
index 8cf26b264..8e80a5d0e 100644
--- a/src/engine/imap/command/imap-namespace-command.vala
+++ b/src/engine/imap/command/imap-namespace-command.vala
@@ -17,8 +17,8 @@ public class Geary.Imap.NamespaceCommand : Command {
public const string NAME = "NAMESPACE";
- public NamespaceCommand() {
- base(NAME);
+ public NamespaceCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
}
diff --git a/src/engine/imap/command/imap-noop-command.vala b/src/engine/imap/command/imap-noop-command.vala
index 4d894723d..ccf440b7d 100644
--- a/src/engine/imap/command/imap-noop-command.vala
+++ b/src/engine/imap/command/imap-noop-command.vala
@@ -11,10 +11,11 @@
*/
public class Geary.Imap.NoopCommand : Command {
+
public const string NAME = "noop";
- public NoopCommand() {
- base (NAME);
+ public NoopCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
-}
+}
diff --git a/src/engine/imap/command/imap-search-command.vala
b/src/engine/imap/command/imap-search-command.vala
index 86448b741..4ea44f807 100644
--- a/src/engine/imap/command/imap-search-command.vala
+++ b/src/engine/imap/command/imap-search-command.vala
@@ -15,8 +15,9 @@ public class Geary.Imap.SearchCommand : Command {
public const string NAME = "search";
public const string UID_NAME = "uid search";
- public SearchCommand(SearchCriteria criteria) {
- base(NAME);
+ public SearchCommand(SearchCriteria criteria,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
// Extend rather than append the criteria, so the top-level
// criterion appear in the top-level list and not as a child
@@ -24,8 +25,9 @@ public class Geary.Imap.SearchCommand : Command {
this.args.extend(criteria);
}
- public SearchCommand.uid(SearchCriteria criteria) {
- base(UID_NAME);
+ public SearchCommand.uid(SearchCriteria criteria,
+ GLib.Cancellable? should_send) {
+ base(UID_NAME, null, should_send);
// Extend rather than append the criteria, so the top-level
// criterion appear in the top-level list and not as a child
diff --git a/src/engine/imap/command/imap-select-command.vala
b/src/engine/imap/command/imap-select-command.vala
index 5e7013a01..cb6844bae 100644
--- a/src/engine/imap/command/imap-select-command.vala
+++ b/src/engine/imap/command/imap-select-command.vala
@@ -16,8 +16,9 @@ public class Geary.Imap.SelectCommand : Command {
public MailboxSpecifier mailbox { get; private set; }
- public SelectCommand(MailboxSpecifier mailbox) {
- base(NAME);
+ public SelectCommand(MailboxSpecifier mailbox,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.mailbox = mailbox;
this.args.add(mailbox.to_parameter());
}
diff --git a/src/engine/imap/command/imap-starttls-command.vala
b/src/engine/imap/command/imap-starttls-command.vala
index 74e5ad714..24ba4d700 100644
--- a/src/engine/imap/command/imap-starttls-command.vala
+++ b/src/engine/imap/command/imap-starttls-command.vala
@@ -9,10 +9,11 @@
*/
public class Geary.Imap.StarttlsCommand : Command {
+
public const string NAME = "STARTTLS";
- public StarttlsCommand() {
- base (NAME);
+ public StarttlsCommand(GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
}
-}
+}
diff --git a/src/engine/imap/command/imap-status-command.vala
b/src/engine/imap/command/imap-status-command.vala
index 388588b56..da2b3c23e 100644
--- a/src/engine/imap/command/imap-status-command.vala
+++ b/src/engine/imap/command/imap-status-command.vala
@@ -18,8 +18,10 @@ public class Geary.Imap.StatusCommand : Command {
public const string NAME = "STATUS";
- public StatusCommand(MailboxSpecifier mailbox, StatusDataType[] data_items) {
- base (NAME);
+ public StatusCommand(MailboxSpecifier mailbox,
+ StatusDataType[] data_items,
+ GLib.Cancellable? should_send) {
+ base(NAME, null, should_send);
this.args.add(mailbox.to_parameter());
diff --git a/src/engine/imap/command/imap-store-command.vala b/src/engine/imap/command/imap-store-command.vala
index 4264e03bb..4fbd614a1 100644
--- a/src/engine/imap/command/imap-store-command.vala
+++ b/src/engine/imap/command/imap-store-command.vala
@@ -30,8 +30,11 @@ public class Geary.Imap.StoreCommand : Command {
SILENT
}
- public StoreCommand(MessageSet message_set, Gee.List<MessageFlag> flag_list, Option options) {
- base (message_set.is_uid ? UID_NAME : NAME);
+ public StoreCommand(MessageSet message_set,
+ Gee.List<MessageFlag> flag_list,
+ Option options,
+ GLib.Cancellable? should_send) {
+ base(message_set.is_uid ? UID_NAME : NAME, null, should_send);
bool add_flag = (options & Option.ADD_FLAGS) != 0;
bool silent = (options & Option.SILENT) != 0;
diff --git a/src/engine/imap/transport/imap-client-connection.vala
b/src/engine/imap/transport/imap-client-connection.vala
index 927ac3bdc..82822d311 100644
--- a/src/engine/imap/transport/imap-client-connection.vala
+++ b/src/engine/imap/transport/imap-client-connection.vala
@@ -576,8 +576,8 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source {
private void on_idle_timeout() {
debug("Initiating IDLE");
try {
- this.send_command(new IdleCommand());
} catch (ImapError err) {
+ this.send_command(new IdleCommand(this.open_cancellable));
warning("Error sending IDLE: %s", err.message);
}
}
diff --git a/src/engine/imap/transport/imap-client-session.vala
b/src/engine/imap/transport/imap-client-session.vala
index 6edbacf09..f42112f26 100644
--- a/src/engine/imap/transport/imap-client-session.vala
+++ b/src/engine/imap/transport/imap-client-session.vala
@@ -159,10 +159,13 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
this.cmd = cmd;
}
- public override async Object? execute_async(Cancellable? cancellable) throws Error {
- response = yield owner.command_transaction_async(cmd, cancellable);
-
- return response;
+ public override async Object? execute_async(GLib.Cancellable? cancellable)
+ throws GLib.Error {
+ // The command's should_send cancellable will be used to
+ // cancel the command if needed, so don't need to check or
+ // pass this method's cancellable through.
+ this.response = yield owner.submit_command(cmd);
+ return this.response;
}
}
@@ -903,7 +906,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
switch (credentials.supported_method) {
case Geary.Credentials.Method.PASSWORD:
cmd = new LoginCommand(
- credentials.user, credentials.token
+ credentials.user,
+ credentials.token,
+ cancellable
);
break;
@@ -915,7 +920,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
);
}
cmd = new AuthenticateCommand.oauth2(
- credentials.user, credentials.token
+ credentials.user,
+ credentials.token,
+ cancellable
);
break;
@@ -936,10 +943,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// should always proceed; only an Error could change this
assert(params.proceed);
- StatusResponse response = yield command_transaction_async(
- cmd, cancellable
- );
-
+ StatusResponse response = yield submit_command(cmd);
if (response.status != Status.OK) {
// Throw an error indicating auth failed here, unless
// there is a status response and it indicates that the
@@ -987,7 +991,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
throws GLib.Error {
// If no capabilities available, get them now
if (this.capabilities.is_empty()) {
- yield send_command_async(new CapabilityCommand(), cancellable);
+ yield send_command_async(new CapabilityCommand(cancellable));
}
var last_capabilities = this.capabilities.revision;
@@ -1000,7 +1004,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
debug("Attempting STARTTLS...");
StatusResponse resp = yield send_command_async(
- new StarttlsCommand(), cancellable
+ new StarttlsCommand(cancellable)
);
if (resp.status == Status.OK) {
@@ -1021,7 +1025,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// mitigate main-in-the-middle attacks. If the TLS
// command response did not update capabilities,
// explicitly do so now.
- yield send_command_async(new CapabilityCommand(), cancellable);
+ yield send_command_async(new CapabilityCommand(cancellable));
last_capabilities = this.capabilities.revision;
}
}
@@ -1031,7 +1035,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// if new capabilities not offered after login, get them now
if (last_capabilities == capabilities.revision) {
- yield send_command_async(new CapabilityCommand(), cancellable);
+ yield send_command_async(new CapabilityCommand(cancellable));
}
var list_results = new Gee.ArrayList<MailboxInformation>();
@@ -1041,8 +1045,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
try {
// Determine what this connection calls the inbox
Imap.StatusResponse response = yield send_command_async(
- new ListCommand(MailboxSpecifier.inbox, false, null),
- cancellable
+ new ListCommand(MailboxSpecifier.inbox, false, null, cancellable)
);
if (response.status == Status.OK && !list_results.is_empty) {
this.inbox = list_results[0];
@@ -1055,8 +1058,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// Try to determine what the connection's namespaces are
if (this.capabilities.has_capability(Capabilities.NAMESPACE)) {
response = yield send_command_async(
- new NamespaceCommand(),
- cancellable
+ new NamespaceCommand(cancellable)
);
if (response.status != Status.OK) {
warning("NAMESPACE command failed");
@@ -1082,8 +1084,12 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// it. In particular, uw-imap sends a null prefix
// for the inbox.
response = yield send_command_async(
- new ListCommand(new MailboxSpecifier(prefix), false, null),
- cancellable
+ new ListCommand(
+ new MailboxSpecifier(prefix),
+ false,
+ null,
+ cancellable
+ )
);
if (response.status == Status.OK && !list_results.is_empty) {
MailboxInformation list = list_results[0];
@@ -1243,7 +1249,10 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// is now dead
keepalive_id = 0;
- send_command_async.begin(new NoopCommand(), null, on_keepalive_completed);
+ send_command_async.begin(
+ new NoopCommand(null),
+ on_keepalive_completed
+ );
debug("Sending keepalive...");
// No need to reschedule keepalive, as the notification that the command was sent should
@@ -1264,8 +1273,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// send commands
//
- public async StatusResponse send_command_async(Command cmd,
- GLib.Cancellable? cancellable)
+ public async StatusResponse send_command_async(Command cmd)
throws GLib.Error {
check_unsupported_send_command(cmd);
@@ -1277,7 +1285,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
assert(params.proceed);
- return yield command_transaction_async(cmd, cancellable);
+ return yield submit_command(cmd);
}
public async Gee.Map<Command, StatusResponse>
@@ -1402,9 +1410,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// Ternary troubles
Command cmd;
if (is_select)
- cmd = new SelectCommand(mailbox);
+ cmd = new SelectCommand(mailbox, cancellable);
else
- cmd = new ExamineCommand(mailbox);
+ cmd = new ExamineCommand(mailbox, cancellable);
MachineParams params = new MachineParams(cmd);
fsm.issue(Event.SELECT, null, params);
@@ -1414,7 +1422,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
assert(params.proceed);
- return yield command_transaction_async(cmd, cancellable);
+ return yield submit_command(cmd);
}
private uint on_select(uint state, uint event, void *user, Object? object) {
@@ -1471,7 +1479,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
public async StatusResponse close_mailbox_async(GLib.Cancellable? cancellable)
throws GLib.Error {
- CloseCommand cmd = new CloseCommand();
+ CloseCommand cmd = new CloseCommand(cancellable);
MachineParams params = new MachineParams(cmd);
fsm.issue(Event.CLOSE_MAILBOX, null, params);
@@ -1479,7 +1487,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
if (params.err != null)
throw params.err;
- return yield command_transaction_async(cmd, cancellable);
+ return yield submit_command(cmd);
}
private uint on_close_mailbox(uint state, uint event, void *user, Object? object) {
@@ -1527,7 +1535,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
*/
public async void logout_async(GLib.Cancellable? cancellable)
throws GLib.Error {
- LogoutCommand cmd = new LogoutCommand();
+ LogoutCommand cmd = new LogoutCommand(cancellable);
MachineParams params = new MachineParams(cmd);
fsm.issue(Event.LOGOUT, null, params);
@@ -1536,7 +1544,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
throw params.err;
if (params.proceed) {
- yield command_transaction_async(cmd, cancellable);
+ yield submit_command(cmd);
yield do_disconnect(DisconnectReason.LOCAL_CLOSE);
}
}
@@ -1779,11 +1787,13 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
// command submission
//
- private async StatusResponse command_transaction_async(Command cmd, Cancellable? cancellable)
- throws Error {
- if (this.cx == null)
- throw new ImapError.NOT_CONNECTED("Not connected to %s", imap_endpoint.to_string());
-
+ private async StatusResponse submit_command(Command cmd)
+ throws GLib.Error {
+ if (this.cx == null) {
+ throw new ImapError.NOT_CONNECTED(
+ "Not connected to %s", imap_endpoint.to_string()
+ );
+ }
this.cx.send_command(cmd);
// Once a command has been sent over the wire, it can't be
diff --git a/test/engine/imap/command/imap-create-command-test.vala
b/test/engine/imap/command/imap-create-command-test.vala
index 91933c7a7..03cd9b63e 100644
--- a/test/engine/imap/command/imap-create-command-test.vala
+++ b/test/engine/imap/command/imap-create-command-test.vala
@@ -16,7 +16,7 @@ class Geary.Imap.CreateCommandTest : TestCase {
public void basic_create() throws Error {
assert_equal(
- new CreateCommand(new MailboxSpecifier("owatagusiam/")).to_string(),
+ new CreateCommand(new MailboxSpecifier("owatagusiam/"), null).to_string(),
"---- create owatagusiam/"
);
}
@@ -25,7 +25,8 @@ class Geary.Imap.CreateCommandTest : TestCase {
assert_equal(
new CreateCommand.special_use(
new MailboxSpecifier("Everything"),
- ALL_MAIL
+ ALL_MAIL,
+ null
).to_string(),
"---- create Everything (use (\\All))"
);
diff --git a/test/engine/imap/command/imap-fetch-command-test.vala
b/test/engine/imap/command/imap-fetch-command-test.vala
index fdb56d4d0..8731943c3 100644
--- a/test/engine/imap/command/imap-fetch-command-test.vala
+++ b/test/engine/imap/command/imap-fetch-command-test.vala
@@ -30,7 +30,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
data_items.add(FetchDataSpecifier.UID);
assert_equal(
- new FetchCommand(this.msg_set, data_items, null).to_string(),
+ new FetchCommand(this.msg_set, data_items, null, null).to_string(),
"---- fetch 1 uid"
);
}
@@ -45,7 +45,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
);
assert_equal(
- new FetchCommand(this.msg_set, null, body_items).to_string(),
+ new FetchCommand(this.msg_set, null, body_items, null).to_string(),
"---- fetch 1 body[text]"
);
}
@@ -57,7 +57,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
data_items.add(FetchDataSpecifier.BODY);
assert_equal(
- new FetchCommand(this.msg_set, data_items, null).to_string(),
+ new FetchCommand(this.msg_set, data_items, null, null).to_string(),
"---- fetch 1 (uid body)"
);
}
@@ -77,7 +77,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
);
assert_equal(
- new FetchCommand(this.msg_set, null, body_items).to_string(),
+ new FetchCommand(this.msg_set, null, body_items, null).to_string(),
"---- fetch 1 (body[header] body[text])"
);
}
@@ -102,7 +102,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
);
assert_equal(
- new FetchCommand(this.msg_set, data_items, body_items).to_string(),
+ new FetchCommand(this.msg_set, data_items, body_items, null).to_string(),
"---- fetch 1 (uid flags body[header] body[text])"
);
}
diff --git a/test/engine/imap/transport/imap-client-connection-test.vala
b/test/engine/imap/transport/imap-client-connection-test.vala
index 9bc745dab..2038221ff 100644
--- a/test/engine/imap/transport/imap-client-connection-test.vala
+++ b/test/engine/imap/transport/imap-client-connection-test.vala
@@ -11,7 +11,7 @@ class Geary.Imap.ClientConnectionTest : TestCase {
private class TestCommand : Command {
public TestCommand() {
- base("TEST");
+ base("TEST", null, null);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]