Make it possible to distinguish between different folder roots

Add a label to Geary.FolderRoot so it different instances can be
differenciated.
This commit is contained in:
Michael Gratton 2019-04-14 20:55:42 +10:00 committed by Michael James Gratton
parent dd3a7a1bc8
commit 01a154bc5f
11 changed files with 109 additions and 36 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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

View file

@ -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(

View file

@ -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

View file

@ -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"
);

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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 {

View file

@ -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"))
);