1 From 53ad3b6d73d92ea289cf0183c10e2b8a35c8127a Mon Sep 17 00:00:00 2001
2 From: David Faure <faure@kde.org>
3 Date: Thu, 21 Mar 2019 23:37:36 +0100
4 Subject: Fix collection detaching at the wrong time in attribute()
7 Found in FatCRM where changes to collection attributes were not stored
11 New unittest to ensure that we get the attribute from the
12 detached collection, not from the original one.
22 Differential Revision: https://phabricator.kde.org/D19741
24 autotests/libs/collectionattributetest.cpp | 15 +++++++++++++++
25 autotests/libs/collectionattributetest.h | 1 +
26 src/core/collection.h | 8 ++------
27 3 files changed, 18 insertions(+), 6 deletions(-)
29 diff --git a/autotests/libs/collectionattributetest.cpp b/autotests/libs/collectionattributetest.cpp
30 index e264a37..9c46561 100644
31 --- a/autotests/libs/collectionattributetest.cpp
32 +++ b/autotests/libs/collectionattributetest.cpp
33 @@ -240,3 +240,18 @@ void CollectionAttributeTest::testCollectionIdentificationAttribute()
34 QCOMPARE(parsed.identifier(), id);
35 QCOMPARE(parsed.collectionNamespace(), ns);
38 +void CollectionAttributeTest::testDetach()
40 + // GIVEN a collection with an attribute
42 + col.attribute<TestAttribute>(Akonadi::Collection::AddIfMissing);
43 + Collection col2 = col; // and a copy, so that non-const access detaches
46 + TestAttribute *attr = col2.attribute<TestAttribute>(Akonadi::Collection::AddIfMissing);
47 + TestAttribute *attr2 = col2.attribute<TestAttribute>();
50 + QCOMPARE(attr, attr2);
52 diff --git a/autotests/libs/collectionattributetest.h b/autotests/libs/collectionattributetest.h
53 index 420df78..2afa9eb 100644
54 --- a/autotests/libs/collectionattributetest.h
55 +++ b/autotests/libs/collectionattributetest.h
56 @@ -32,6 +32,7 @@ private Q_SLOTS:
57 void testDefaultAttributes();
58 void testCollectionRightsAttribute();
59 void testCollectionIdentificationAttribute();
64 diff --git a/src/core/collection.h b/src/core/collection.h
65 index b5a496c..9c19cc9 100644
66 --- a/src/core/collection.h
67 +++ b/src/core/collection.h
68 @@ -565,10 +565,10 @@ inline T *Akonadi::Collection::attribute(Collection::CreateOption option)
72 + markAttributesChanged();
73 if (hasAttribute(dummy.type())) {
74 T *attr = dynamic_cast<T *>(attribute(dummy.type()));
76 - markAttributesChanged();
80 @@ -585,14 +585,10 @@ template <typename T>
81 inline T *Akonadi::Collection::attribute() const
83 const QByteArray type = T().type();
84 + const_cast<Collection*>(this)->markAttributesChanged();
85 if (hasAttribute(type)) {
86 T *attr = dynamic_cast<T *>(attribute(type));
88 - // FIXME: This method returns a non-const pointer, so callers may still modify the
89 - // attribute. Unfortunately, just making this function return a const pointer and
90 - // creating a non-const overload does not work, as many users of this function abuse the
91 - // non-const pointer and modify the attribute even on a const object.
92 - const_cast<Collection*>(this)->markAttributesChanged();