[geary/wip/766133-gnotification: 14/18] Make it possible to distinguish between different folder roots



commit 9f1d0b3032eec9f3274c6211a0a4b7fb534c13c0
Author: Michael Gratton <mike vee net>
Date:   Sun Apr 14 20:55:42 2019 +1000

    Make it possible to distinguish between different folder roots
    
    Add a label to Geary.FolderRoot so it different instances can be
    differenciated.

 src/engine/api/geary-account-information.vala      |  2 +-
 src/engine/api/geary-folder-path.vala              | 52 +++++++++++++++++++---
 src/engine/imap-db/imap-db-account.vala            |  2 +-
 .../imap-engine/imap-engine-generic-account.vala   | 24 +++++++---
 src/engine/imap/api/imap-folder-root.vala          |  4 +-
 test/engine/api/geary-folder-path-test.vala        | 49 ++++++++++++++------
 test/engine/app/app-conversation-monitor-test.vala |  2 +-
 test/engine/app/app-conversation-set-test.vala     |  2 +-
 test/engine/app/app-conversation-test.vala         |  2 +-
 test/engine/imap-db/imap-db-account-test.vala      |  2 +-
 .../imap/message/imap-mailbox-specifier-test.vala  |  4 +-
 11 files changed, 109 insertions(+), 36 deletions(-)
---
diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala
index 980ef711..cdc05eb6 100644
--- a/src/engine/api/geary-account-information.vala
+++ b/src/engine/api/geary-account-information.vala
@@ -29,7 +29,7 @@ public class Geary.AccountInformation : BaseObject {
         if (parts == null || parts.size == 0)
             return null;
 
-        Geary.FolderPath path = new Imap.FolderRoot();
+        Geary.FolderPath path = new Imap.FolderRoot("#geary-config");
         foreach (string basename in parts) {
             path = path.get_child(basename);
         }
diff --git a/src/engine/api/geary-folder-path.vala b/src/engine/api/geary-folder-path.vala
index 746c5d58..dfd01be0 100644
--- a/src/engine/api/geary-folder-path.vala
+++ b/src/engine/api/geary-folder-path.vala
@@ -19,7 +19,7 @@ public class Geary.FolderPath :
 
 
     /** Type of the GLib.Variant used to represent folder paths */
-    public const string VARIANT_TYPE = "as";
+    public const string VARIANT_TYPE = "(sas)";
 
 
     // Workaround for Vala issue #659. See children below.
@@ -233,7 +233,10 @@ public class Geary.FolderPath :
      * @see FolderRoot.from_folder_path
      */
     public GLib.Variant to_variant() {
-        return new GLib.Variant.strv(as_array());
+        return new GLib.Variant.tuple(new GLib.Variant[] {
+                get_root().label,
+                as_array()
+        });
     }
 
     /**
@@ -278,11 +281,14 @@ public class Geary.FolderPath :
                                      bool allow_case_sensitive,
                                      bool normalize) {
         int cmp = 0;
-        if (a.parent != null && b.parent != null) {
+        if (a.parent == null && b.parent == null) {
+            cmp = strcmp(((FolderRoot) a).label, ((FolderRoot) b).label);
+        } else {
             cmp = compare_names(
                 a.parent, b.parent, allow_case_sensitive, normalize
             );
         }
+
         if (cmp == 0) {
             string a_name = a.name;
             string b_name = b.name;
@@ -318,6 +324,15 @@ public class Geary.FolderPath :
 public class Geary.FolderRoot : FolderPath {
 
 
+    /**
+     * A label for a folder root.
+     *
+     * Since there may be multiple folder roots (for example, local
+     * and remote folders, or for different remote namespaces), the
+     * label can be used to look up a specific root.
+     */
+    public string label { get; private set; }
+
     /**
      * The default case sensitivity of descendant folders.
      *
@@ -329,26 +344,51 @@ public class Geary.FolderRoot : FolderPath {
     /**
      * Constructs a new folder root with given default sensitivity.
      */
-    public FolderRoot(bool default_case_sensitivity) {
+    public FolderRoot(string label, bool default_case_sensitivity) {
         base();
+        this.label = label;
         this.default_case_sensitivity = default_case_sensitivity;
     }
 
+    /**
+     * Copies a folder path using this as the root.
+     *
+     * This method can be used to simply copy a path, or change the
+     * root that a path is attached to.
+     */
+    public FolderPath copy(FolderPath original) {
+        FolderPath copy = this;
+        foreach (string step in original.as_array()) {
+            copy = copy.get_child(step);
+        }
+        return copy;
+    }
+
     /**
      * Reconstructs a path under this root from a GLib variant.
      *
      * @see FolderPath.to_variant
+     * @throws EngineError.BAD_PARAMETERS when the variant is not the
+     * have the correct type or if the given root label does not match
+     * this root's label.
      */
     public FolderPath from_variant(GLib.Variant serialised)
-        throws EngineError {
+        throws EngineError.BAD_PARAMETERS {
         if (serialised.get_type_string() != VARIANT_TYPE) {
             throw new EngineError.BAD_PARAMETERS(
                 "Invalid serialised id type: %s", serialised.get_type_string()
             );
         }
 
+        string label = (string) serialised.get_child_value(0);
+        if (this.label != label) {
+            throw new EngineError.BAD_PARAMETERS(
+                "Invalid serialised folder root label: %s", label
+            );
+        }
+
         FolderPath path = this;
-        foreach (string step in serialised.get_strv()) {
+        foreach (string step in serialised.get_child_value(1).get_strv()) {
             path = path.get_child(step);
         }
         return path;
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index c8341fe8..6b7d5b28 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -86,7 +86,7 @@ private class Geary.ImapDB.Account : BaseObject {
      * @see list_folders_async
      */
     public Imap.FolderRoot imap_folder_root {
-        get; private set; default = new Imap.FolderRoot();
+        get; private set; default = new Imap.FolderRoot("$geary-imap");
     }
 
     // Only available when the Account is opened
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 908d8d94..acb92b48 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -43,7 +43,9 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
      * No folder exists for this path, it merely exists to provide a
      * common root for the paths of all local folders.
      */
-    protected FolderRoot local_folder_root = new Geary.FolderRoot(true);
+    protected FolderRoot local_folder_root = new Geary.FolderRoot(
+        "$geary-local", true
+    );
 
     private bool open = false;
     private Cancellable? open_cancellable = null;
@@ -723,13 +725,20 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
         Folder? special = get_special_folder(type);
         if (special == null) {
             FolderPath? path = information.get_special_folder_path(type);
-            if (path != null && !remote.is_folder_path_valid(path)) {
-                debug("%s: Ignoring bad special folder path '%s' for type %s",
-                      to_string(),
-                      path.to_string(),
-                      type.to_string());
-                path = null;
+            if (path != null) {
+                if (!remote.is_folder_path_valid(path)) {
+                    warning(
+                        "%s: Ignoring bad special folder path '%s' for type %s",
+                        to_string(),
+                        path.to_string(),
+                        type.to_string()
+                    );
+                    path = null;
+                } else {
+                    path = this.local.imap_folder_root.copy(path);
+                }
             }
+
             if (path == null) {
                 FolderPath root =
                     yield remote.get_default_personal_namespace(cancellable);
@@ -1113,6 +1122,7 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
             if (generic.get_special_folder(type) == null) {
                 Geary.FolderPath? path =
                     generic.information.get_special_folder_path(type);
+                path = this.local.imap_folder_root.copy(path);
                 if (path != null) {
                     try {
                         Geary.Folder target = yield generic.fetch_folder_async(
diff --git a/src/engine/imap/api/imap-folder-root.vala b/src/engine/imap/api/imap-folder-root.vala
index bbe525b6..1a1f2e99 100644
--- a/src/engine/imap/api/imap-folder-root.vala
+++ b/src/engine/imap/api/imap-folder-root.vala
@@ -31,8 +31,8 @@ public class Geary.Imap.FolderRoot : Geary.FolderRoot {
     public FolderPath inbox { get; private set; }
 
 
-    public FolderRoot() {
-        base(false);
+    public FolderRoot(string label) {
+        base(label, false);
         this.inbox = base.get_child(
             MailboxSpecifier.CANONICAL_INBOX_NAME,
             Trillian.FALSE
diff --git a/test/engine/api/geary-folder-path-test.vala b/test/engine/api/geary-folder-path-test.vala
index 952ca44c..018a3045 100644
--- a/test/engine/api/geary-folder-path-test.vala
+++ b/test/engine/api/geary-folder-path-test.vala
@@ -8,6 +8,8 @@
 public class Geary.FolderPathTest : TestCase {
 
 
+    private const string TEST_LABEL = "#test";
+
     private FolderRoot? root = null;
 
 
@@ -19,18 +21,19 @@ public class Geary.FolderPathTest : TestCase {
         add_test("child_is_not_root", root_is_root);
         add_test("as_array", as_array);
         add_test("is_top_level", is_top_level);
+        add_test("distinct_roots_compare", distinct_roots_compare);
         add_test("path_to_string", path_to_string);
         add_test("path_parent", path_parent);
         add_test("path_equal", path_equal);
         add_test("path_hash", path_hash);
         add_test("path_compare", path_compare);
         add_test("path_compare_normalised", path_compare_normalised);
-        add_test("distinct_roots_compare", distinct_roots_compare);
+        add_test("root_instances_compare", root_instances_compare);
         add_test("variant_representation", variant_representation);
     }
 
     public override void set_up() {
-        this.root = new FolderRoot(false);
+        this.root = new FolderRoot(TEST_LABEL, false);
     }
 
     public override void tear_down() {
@@ -100,6 +103,17 @@ public class Geary.FolderPathTest : TestCase {
         );
     }
 
+    public void distinct_roots_compare() throws GLib.Error {
+        assert_true(
+            this.root.compare_to(new FolderRoot(TEST_LABEL, false)) == 0,
+            "Root label equality"
+        );
+        assert_true(
+            this.root.compare_to(new FolderRoot("#other", false)) > 0,
+            "Root label inequality"
+        );
+    }
+
     public void path_to_string() throws GLib.Error {
         assert_string(">", this.root.to_string());
         assert_string(">test", this.root.get_child("test").to_string());
@@ -257,50 +271,59 @@ public class Geary.FolderPathTest : TestCase {
         );
     }
 
-    public void distinct_roots_compare() throws GLib.Error {
-        assert_int(0, this.root.compare_to(new FolderRoot(false)), "Root equality");
-        assert_int(0,
-            this.root.get_child("a").compare_to(new FolderRoot(false).get_child("a")),
+    public void root_instances_compare() throws GLib.Error {
+        assert_int(
+            0, this.root.compare_to(new FolderRoot(TEST_LABEL, false)),
+            "Root equality"
+        );
+        assert_int(
+            0, this.root.get_child("a").compare_to(new FolderRoot(TEST_LABEL, false).get_child("a")),
             "Equal child comparison"
         );
 
+        assert_true(
+            this.root.get_child("a").compare_to(
+                new FolderRoot("#other", false).get_child("a")) > 0,
+            "Root label inequality with children"
+        );
+
         // a is less than b
         assert_true(
-            this.root.get_child("a").compare_to(new FolderRoot(false).get_child("b")) < 0,
+            this.root.get_child("a").compare_to(new FolderRoot(TEST_LABEL, false).get_child("b")) < 0,
             "Greater than child comparison"
         );
 
         // b is greater than than a
         assert_true(
-            this.root.get_child("b").compare_to(new FolderRoot(false).get_child("a")) > 0,
+            this.root.get_child("b").compare_to(new FolderRoot(TEST_LABEL, false).get_child("a")) > 0,
             "Less than child comparison"
         );
 
         assert_true(
             this.root.get_child("a").get_child("test")
-            .compare_to(new FolderRoot(false).get_child("a")) > 0,
+            .compare_to(new FolderRoot(TEST_LABEL, false).get_child("a")) > 0,
             "Greater than descendant"
         );
         assert_true(
             this.root.get_child("a")
-            .compare_to(new FolderRoot(false).get_child("a").get_child("test")) < 0,
+            .compare_to(new FolderRoot(TEST_LABEL, false).get_child("a").get_child("test")) < 0,
             "Less than descendant"
         );
 
         assert_true(
             this.root.get_child("a").get_child("b")
-            .compare_to(new FolderRoot(false).get_child("a").get_child("b")) == 0,
+            .compare_to(new FolderRoot(TEST_LABEL, false).get_child("a").get_child("b")) == 0,
             "N-path equality"
         );
 
         assert_true(
             this.root.get_child("a").get_child("a")
-            .compare_to(new FolderRoot(false).get_child("b").get_child("b")) < 0,
+            .compare_to(new FolderRoot(TEST_LABEL, false).get_child("b").get_child("b")) < 0,
             "Less than double disjoint"
         );
         assert_true(
             this.root.get_child("b").get_child("a")
-            .compare_to(new FolderRoot(false).get_child("a").get_child("a")) > 0,
+            .compare_to(new FolderRoot(TEST_LABEL, false).get_child("a").get_child("a")) > 0,
             "Greater than double disjoint"
         );
 
diff --git a/test/engine/app/app-conversation-monitor-test.vala 
b/test/engine/app/app-conversation-monitor-test.vala
index 582aa0b7..a120e714 100644
--- a/test/engine/app/app-conversation-monitor-test.vala
+++ b/test/engine/app/app-conversation-monitor-test.vala
@@ -37,7 +37,7 @@ class Geary.App.ConversationMonitorTest : TestCase {
             new RFC822.MailboxAddress(null, "test1 example com")
         );
         this.account = new MockAccount(this.account_info);
-        this.folder_root = new FolderRoot(false);
+        this.folder_root = new FolderRoot("#test", false);
         this.base_folder = new MockFolder(
             this.account,
             null,
diff --git a/test/engine/app/app-conversation-set-test.vala b/test/engine/app/app-conversation-set-test.vala
index 7a7fedc2..29ac6512 100644
--- a/test/engine/app/app-conversation-set-test.vala
+++ b/test/engine/app/app-conversation-set-test.vala
@@ -28,7 +28,7 @@ class Geary.App.ConversationSetTest : TestCase {
     }
 
     public override void set_up() {
-        this.folder_root = new FolderRoot(false);
+        this.folder_root = new FolderRoot("#test", false);
         this.base_folder = new MockFolder(
             null,
             null,
diff --git a/test/engine/app/app-conversation-test.vala b/test/engine/app/app-conversation-test.vala
index 1ee1f4a4..a20273ac 100644
--- a/test/engine/app/app-conversation-test.vala
+++ b/test/engine/app/app-conversation-test.vala
@@ -28,7 +28,7 @@ class Geary.App.ConversationTest : TestCase {
     }
 
     public override void set_up() {
-        this.folder_root = new FolderRoot(false);
+        this.folder_root = new FolderRoot("#test", false);
         this.base_folder = new MockFolder(
             null,
             null,
diff --git a/test/engine/imap-db/imap-db-account-test.vala b/test/engine/imap-db/imap-db-account-test.vala
index 26ccf91b..85b54c60 100644
--- a/test/engine/imap-db/imap-db-account-test.vala
+++ b/test/engine/imap-db/imap-db-account-test.vala
@@ -49,7 +49,7 @@ class Geary.ImapDB.AccountTest : TestCase {
         );
         this.account.open_async.end(async_result());
 
-        this.root = new FolderRoot(false);
+        this.root = new FolderRoot("#test", false);
     }
 
     public override void tear_down() throws GLib.Error {
diff --git a/test/engine/imap/message/imap-mailbox-specifier-test.vala 
b/test/engine/imap/message/imap-mailbox-specifier-test.vala
index 6488e5e9..d3a52046 100644
--- a/test/engine/imap/message/imap-mailbox-specifier-test.vala
+++ b/test/engine/imap/message/imap-mailbox-specifier-test.vala
@@ -60,7 +60,7 @@ class Geary.Imap.MailboxSpecifierTest : TestCase {
     }
 
     public void from_folder_path() throws Error {
-        FolderRoot root = new FolderRoot();
+        FolderRoot root = new FolderRoot("#test");
         MailboxSpecifier inbox = new MailboxSpecifier("Inbox");
         assert_string(
             "Foo",
@@ -110,7 +110,7 @@ class Geary.Imap.MailboxSpecifierTest : TestCase {
     }
 
     public void folder_path_is_inbox() throws GLib.Error {
-        FolderRoot root = new FolderRoot();
+        FolderRoot root = new FolderRoot("#test");
         assert_true(
             MailboxSpecifier.folder_path_is_inbox(root.get_child("Inbox"))
         );


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