data/SieveHistory.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "SieveHistory.h" | ||
| 2 | |||
| 3 | #include <QDir> | ||
| 4 | #include <QFile> | ||
| 5 | #include <QFileInfo> | ||
| 6 | #include <QJsonDocument> | ||
| 7 | #include <QJsonObject> | ||
| 8 | #include <QLoggingCategory> | ||
| 9 | #include <QSaveFile> | ||
| 10 | #include <QTimeZone> | ||
| 11 | |||
| 12 |
4/7✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 8 taken 87 times.
✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 6 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
93 | Q_LOGGING_CATEGORY(lcSieveHistory, "mailjd.sieve.history") |
| 13 | |||
| 14 | namespace { | ||
| 15 | constexpr auto kStamp = "yyyyMMdd'T'HHmmsszzz"; | ||
| 16 | } | ||
| 17 | |||
| 18 | 234 | SieveHistory::SieveHistory(const QString &directory, int limit) | |
| 19 | 234 | : m_directory(directory), m_limit(qMax(1, limit)) {} | |
| 20 | |||
| 21 | 412 | QString SieveHistory::historyDirectory() const { | |
| 22 |
2/2✓ Branch 2 → 3 taken 412 times.
✓ Branch 6 → 7 taken 412 times.
|
824 | return QDir(m_directory).filePath(QStringLiteral("history")); |
| 23 | } | ||
| 24 | |||
| 25 | 515 | bool SieveHistory::ensureDirectory(const QString &path) const { | |
| 26 |
1/1✓ Branch 2 → 3 taken 515 times.
|
515 | QDir dir(path); |
| 27 |
11/17✓ Branch 3 → 4 taken 515 times.
✓ Branch 4 → 5 taken 40 times.
✓ Branch 4 → 10 taken 475 times.
✓ Branch 6 → 7 taken 40 times.
✓ Branch 7 → 8 taken 40 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 40 times.
✓ Branch 11 → 12 taken 40 times.
✓ Branch 11 → 13 taken 475 times.
✓ Branch 13 → 14 taken 40 times.
✓ Branch 13 → 15 taken 475 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 515 times.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
|
515 | if (!dir.exists() && !QDir().mkpath(path)) |
| 28 | ✗ | return false; | |
| 29 |
1/1✓ Branch 19 → 20 taken 515 times.
|
515 | QFile::setPermissions(path, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner); |
| 30 | 515 | return true; | |
| 31 | 515 | } | |
| 32 | |||
| 33 | 844 | bool SieveHistory::writePrivate(const QString &path, const QByteArray &bytes) { | |
| 34 |
1/1✓ Branch 2 → 3 taken 844 times.
|
844 | QSaveFile file(path); |
| 35 |
1/1✓ Branch 4 → 5 taken 844 times.
|
844 | return file.open(QIODevice::WriteOnly) && |
| 36 |
3/5✓ Branch 7 → 8 taken 844 times.
✓ Branch 8 → 9 taken 844 times.
✗ Branch 8 → 15 not taken.
✓ Branch 11 → 12 taken 844 times.
✗ Branch 11 → 15 not taken.
|
1688 | file.setPermissions(QFile::ReadOwner | QFile::WriteOwner) && |
| 37 |
4/6✓ Branch 5 → 6 taken 844 times.
✗ Branch 5 → 15 not taken.
✓ Branch 9 → 10 taken 844 times.
✓ Branch 12 → 13 taken 844 times.
✓ Branch 13 → 14 taken 844 times.
✗ Branch 13 → 15 not taken.
|
3376 | file.write(bytes) == bytes.size() && file.commit(); |
| 38 | 844 | } | |
| 39 | |||
| 40 | 93 | QString SieveHistory::add(const QString &scriptName, const QByteArray &script, const QDateTime &when) { | |
| 41 |
8/15✓ Branch 3 → 4 taken 93 times.
✗ Branch 3 → 9 not taken.
✓ Branch 4 → 5 taken 93 times.
✓ Branch 5 → 6 taken 93 times.
✗ Branch 5 → 9 not taken.
✓ Branch 6 → 7 taken 93 times.
✓ Branch 7 → 8 taken 93 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 93 times.
✓ Branch 11 → 12 taken 93 times.
✗ Branch 11 → 13 not taken.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 93 times.
✗ Branch 164 → 165 not taken.
✗ Branch 164 → 166 not taken.
|
93 | if (script.isEmpty() || !ensureDirectory(m_directory) || !ensureDirectory(historyDirectory())) |
| 42 | ✗ | return {}; | |
| 43 |
3/3✓ Branch 15 → 16 taken 93 times.
✓ Branch 17 → 18 taken 93 times.
✓ Branch 18 → 19 taken 93 times.
|
93 | const QString stamp = when.toUTC().toString(QString::fromLatin1(kStamp)); |
| 44 | 93 | QString id; | |
| 45 |
1/2✓ Branch 48 → 22 taken 93 times.
✗ Branch 48 → 49 not taken.
|
93 | for (int n = 0; n < 1000; ++n) { |
| 46 |
3/3✓ Branch 22 → 23 taken 93 times.
✓ Branch 25 → 26 taken 93 times.
✓ Branch 26 → 27 taken 93 times.
|
93 | id = stamp + QLatin1Char('-') + QString::number(n); |
| 47 |
6/7✓ Branch 31 → 32 taken 93 times.
✓ Branch 32 → 33 taken 93 times.
✓ Branch 36 → 37 taken 93 times.
✓ Branch 37 → 38 taken 93 times.
✓ Branch 38 → 39 taken 93 times.
✓ Branch 45 → 46 taken 93 times.
✗ Branch 45 → 47 not taken.
|
186 | if (!QFile::exists(QDir(historyDirectory()).filePath(id + QStringLiteral(".sieve")))) |
| 48 | 93 | break; | |
| 49 | } | ||
| 50 |
2/2✓ Branch 49 → 50 taken 93 times.
✓ Branch 50 → 51 taken 93 times.
|
93 | const QDir dir(historyDirectory()); |
| 51 | 186 | QJsonObject meta{{QStringLiteral("script"), scriptName}, | |
| 52 |
4/6✓ Branch 59 → 60 taken 93 times.
✓ Branch 60 → 61 taken 93 times.
✓ Branch 64 → 65 taken 186 times.
✓ Branch 64 → 66 taken 93 times.
✗ Branch 206 → 207 not taken.
✗ Branch 206 → 208 not taken.
|
372 | {QStringLiteral("savedAt"), when.toUTC().toString(Qt::ISODateWithMs)}}; |
| 53 |
8/21✓ Branch 75 → 76 taken 93 times.
✓ Branch 76 → 77 taken 93 times.
✓ Branch 77 → 78 taken 93 times.
✓ Branch 78 → 79 taken 93 times.
✗ Branch 78 → 88 not taken.
✓ Branch 104 → 105 taken 93 times.
✗ Branch 104 → 106 not taken.
✓ Branch 106 → 107 taken 93 times.
✗ Branch 106 → 108 not taken.
✓ Branch 108 → 109 taken 93 times.
✗ Branch 108 → 110 not taken.
✗ Branch 110 → 111 not taken.
✓ Branch 110 → 112 taken 93 times.
✗ Branch 257 → 258 not taken.
✗ Branch 257 → 259 not taken.
✗ Branch 261 → 262 not taken.
✗ Branch 261 → 263 not taken.
✗ Branch 265 → 266 not taken.
✗ Branch 265 → 267 not taken.
✗ Branch 269 → 270 not taken.
✗ Branch 269 → 271 not taken.
|
465 | if (!writePrivate(dir.filePath(id + QStringLiteral(".sieve")), script) || |
| 54 |
13/33✓ Branch 79 → 80 taken 93 times.
✓ Branch 80 → 81 taken 93 times.
✓ Branch 84 → 85 taken 93 times.
✓ Branch 85 → 86 taken 93 times.
✓ Branch 86 → 87 taken 93 times.
✗ Branch 87 → 88 not taken.
✓ Branch 87 → 89 taken 93 times.
✓ Branch 90 → 91 taken 93 times.
✗ Branch 90 → 92 not taken.
✓ Branch 92 → 93 taken 93 times.
✗ Branch 92 → 94 not taken.
✓ Branch 94 → 95 taken 93 times.
✗ Branch 94 → 96 not taken.
✓ Branch 96 → 97 taken 93 times.
✗ Branch 96 → 98 not taken.
✓ Branch 98 → 99 taken 93 times.
✗ Branch 98 → 100 not taken.
✓ Branch 100 → 101 taken 93 times.
✗ Branch 100 → 102 not taken.
✓ Branch 102 → 103 taken 93 times.
✗ Branch 102 → 104 not taken.
✗ Branch 233 → 234 not taken.
✗ Branch 233 → 235 not taken.
✗ Branch 237 → 238 not taken.
✗ Branch 237 → 239 not taken.
✗ Branch 241 → 242 not taken.
✗ Branch 241 → 243 not taken.
✗ Branch 245 → 246 not taken.
✗ Branch 245 → 247 not taken.
✗ Branch 249 → 250 not taken.
✗ Branch 249 → 251 not taken.
✗ Branch 253 → 254 not taken.
✗ Branch 253 → 255 not taken.
|
279 | !writePrivate(dir.filePath(id + QStringLiteral(".json")), QJsonDocument(meta).toJson())) |
| 55 | ✗ | return {}; | |
| 56 |
1/1✓ Branch 112 → 113 taken 93 times.
|
93 | const QList<Entry> all = entries(); |
| 57 |
2/2✓ Branch 138 → 114 taken 5 times.
✓ Branch 138 → 139 taken 93 times.
|
98 | for (int i = m_limit; i < all.size(); ++i) { |
| 58 |
3/3✓ Branch 118 → 119 taken 5 times.
✓ Branch 119 → 120 taken 5 times.
✓ Branch 120 → 121 taken 5 times.
|
5 | QFile::remove(dir.filePath(all.at(i).id + QStringLiteral(".sieve"))); |
| 59 |
3/3✓ Branch 129 → 130 taken 5 times.
✓ Branch 130 → 131 taken 5 times.
✓ Branch 131 → 132 taken 5 times.
|
5 | QFile::remove(dir.filePath(all.at(i).id + QStringLiteral(".json"))); |
| 60 | } | ||
| 61 |
7/7✓ Branch 139 → 140 taken 93 times.
✓ Branch 143 → 144 taken 88 times.
✓ Branch 144 → 145 taken 88 times.
✓ Branch 146 → 147 taken 88 times.
✓ Branch 147 → 148 taken 88 times.
✓ Branch 155 → 141 taken 88 times.
✓ Branch 155 → 156 taken 93 times.
|
181 | qCInfo(lcSieveHistory) << "Stored replaced version," << script.size() << "bytes; history has" |
| 62 |
2/2✓ Branch 150 → 151 taken 88 times.
✓ Branch 151 → 152 taken 88 times.
|
88 | << qMin(all.size(), m_limit) << "versions"; |
| 63 | 93 | return id; | |
| 64 | 372 | } | |
| 65 | |||
| 66 | 101 | QList<SieveHistory::Entry> SieveHistory::entries() const { | |
| 67 | 101 | QList<Entry> result; | |
| 68 |
2/2✓ Branch 2 → 3 taken 101 times.
✓ Branch 3 → 4 taken 101 times.
|
101 | const QDir dir(historyDirectory()); |
| 69 | const QStringList files = | ||
| 70 |
3/5✓ Branch 11 → 12 taken 101 times.
✓ Branch 14 → 15 taken 101 times.
✓ Branch 14 → 16 taken 101 times.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 106 not taken.
|
303 | dir.entryList({QStringLiteral("*.sieve")}, QDir::Files, QDir::Name | QDir::Reversed); |
| 71 |
2/2✓ Branch 93 → 19 taken 482 times.
✓ Branch 93 → 94 taken 101 times.
|
583 | for (const QString &file : files) { |
| 72 | 482 | Entry entry; | |
| 73 |
1/1✓ Branch 21 → 22 taken 482 times.
|
482 | entry.id = file.chopped(6); |
| 74 |
3/3✓ Branch 24 → 25 taken 482 times.
✓ Branch 25 → 26 taken 482 times.
✓ Branch 26 → 27 taken 482 times.
|
482 | entry.size = QFileInfo(dir.filePath(file)).size(); |
| 75 |
3/3✓ Branch 32 → 33 taken 482 times.
✓ Branch 33 → 34 taken 482 times.
✓ Branch 34 → 35 taken 482 times.
|
482 | QFile meta(dir.filePath(entry.id + QStringLiteral(".json"))); |
| 76 |
2/3✓ Branch 40 → 41 taken 482 times.
✓ Branch 41 → 42 taken 482 times.
✗ Branch 41 → 71 not taken.
|
482 | if (meta.open(QIODevice::ReadOnly)) { |
| 77 |
3/3✓ Branch 42 → 43 taken 482 times.
✓ Branch 43 → 44 taken 482 times.
✓ Branch 44 → 45 taken 482 times.
|
482 | const QJsonObject object = QJsonDocument::fromJson(meta.readAll()).object(); |
| 78 |
2/2✓ Branch 50 → 51 taken 482 times.
✓ Branch 51 → 52 taken 482 times.
|
482 | entry.scriptName = object.value(QStringLiteral("script")).toString(); |
| 79 |
3/3✓ Branch 60 → 61 taken 482 times.
✓ Branch 61 → 62 taken 482 times.
✓ Branch 62 → 63 taken 482 times.
|
964 | entry.savedAt = QDateTime::fromString(object.value(QStringLiteral("savedAt")).toString(), |
| 80 | 482 | Qt::ISODateWithMs); | |
| 81 | 482 | } | |
| 82 |
2/3✓ Branch 71 → 72 taken 482 times.
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 85 taken 482 times.
|
482 | if (!entry.savedAt.isValid()) |
| 83 | ✗ | entry.savedAt = QDateTime::fromString(entry.id.section(QLatin1Char('-'), 0, 0), | |
| 84 | ✗ | QString::fromLatin1(kStamp)); | |
| 85 |
1/1✓ Branch 86 → 87 taken 482 times.
|
482 | entry.savedAt.setTimeZone(QTimeZone::UTC); |
| 86 |
1/1✓ Branch 88 → 89 taken 482 times.
|
482 | result.append(entry); |
| 87 | 482 | } | |
| 88 | 101 | return result; | |
| 89 | 303 | } | |
| 90 | |||
| 91 | 32 | QByteArray SieveHistory::read(const QString &id) const { | |
| 92 |
5/8✓ Branch 4 → 5 taken 32 times.
✓ Branch 5 → 6 taken 32 times.
✗ Branch 5 → 9 not taken.
✓ Branch 7 → 8 taken 32 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 32 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 32 times.
|
32 | if (id.contains(QLatin1Char('/')) || id.contains(QLatin1String(".."))) |
| 93 | ✗ | return {}; | |
| 94 |
5/5✓ Branch 13 → 14 taken 32 times.
✓ Branch 14 → 15 taken 32 times.
✓ Branch 18 → 19 taken 32 times.
✓ Branch 19 → 20 taken 32 times.
✓ Branch 20 → 21 taken 32 times.
|
64 | QFile file(QDir(historyDirectory()).filePath(id + QStringLiteral(".sieve"))); |
| 95 |
4/4✓ Branch 28 → 29 taken 32 times.
✓ Branch 29 → 30 taken 30 times.
✓ Branch 29 → 31 taken 2 times.
✓ Branch 30 → 32 taken 30 times.
|
32 | return file.open(QIODevice::ReadOnly) ? file.readAll() : QByteArray(); |
| 96 | 32 | } | |
| 97 | |||
| 98 | 329 | bool SieveHistory::writeLastDownloaded(const QString &scriptName, const QByteArray &script, | |
| 99 | const QDateTime &when) { | ||
| 100 |
2/3✓ Branch 2 → 3 taken 329 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 329 times.
|
329 | if (!ensureDirectory(m_directory)) |
| 101 | ✗ | return false; | |
| 102 |
1/1✓ Branch 5 → 6 taken 329 times.
|
329 | const QDir dir(m_directory); |
| 103 | 658 | const QJsonObject meta{{QStringLiteral("script"), scriptName}, | |
| 104 |
4/6✓ Branch 13 → 14 taken 329 times.
✓ Branch 14 → 15 taken 329 times.
✓ Branch 18 → 19 taken 658 times.
✓ Branch 18 → 20 taken 329 times.
✗ Branch 63 → 64 not taken.
✗ Branch 63 → 65 not taken.
|
1316 | {QStringLiteral("downloadedAt"), when.toUTC().toString(Qt::ISODateWithMs)}}; |
| 105 |
5/14✓ Branch 29 → 30 taken 329 times.
✓ Branch 30 → 31 taken 329 times.
✓ Branch 31 → 32 taken 329 times.
✗ Branch 31 → 41 not taken.
✓ Branch 54 → 55 taken 329 times.
✗ Branch 54 → 56 not taken.
✓ Branch 56 → 57 taken 329 times.
✗ Branch 56 → 58 not taken.
✗ Branch 110 → 111 not taken.
✗ Branch 110 → 112 not taken.
✗ Branch 114 → 115 not taken.
✗ Branch 114 → 116 not taken.
✗ Branch 118 → 119 not taken.
✗ Branch 118 → 120 not taken.
|
1645 | return writePrivate(dir.filePath(QStringLiteral("last.sieve")), script) && |
| 106 |
11/28✓ Branch 32 → 33 taken 329 times.
✓ Branch 33 → 34 taken 329 times.
✓ Branch 37 → 38 taken 329 times.
✓ Branch 38 → 39 taken 329 times.
✓ Branch 39 → 40 taken 329 times.
✗ Branch 39 → 41 not taken.
✓ Branch 42 → 43 taken 329 times.
✗ Branch 42 → 44 not taken.
✓ Branch 44 → 45 taken 329 times.
✗ Branch 44 → 46 not taken.
✓ Branch 46 → 47 taken 329 times.
✗ Branch 46 → 48 not taken.
✓ Branch 48 → 49 taken 329 times.
✗ Branch 48 → 50 not taken.
✓ Branch 50 → 51 taken 329 times.
✗ Branch 50 → 52 not taken.
✓ Branch 52 → 53 taken 329 times.
✗ Branch 52 → 54 not taken.
✗ Branch 90 → 91 not taken.
✗ Branch 90 → 92 not taken.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 96 not taken.
✗ Branch 98 → 99 not taken.
✗ Branch 98 → 100 not taken.
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 104 not taken.
✗ Branch 106 → 107 not taken.
✗ Branch 106 → 108 not taken.
|
987 | writePrivate(dir.filePath(QStringLiteral("last.json")), QJsonDocument(meta).toJson()); |
| 107 | 1316 | } | |
| 108 | |||
| 109 | 3 | bool SieveHistory::hasLastDownloaded() const { | |
| 110 |
3/3✓ Branch 2 → 3 taken 3 times.
✓ Branch 6 → 7 taken 3 times.
✓ Branch 7 → 8 taken 3 times.
|
6 | return QFile::exists(QDir(m_directory).filePath(QStringLiteral("last.json"))); |
| 111 | } | ||
| 112 | |||
| 113 | 5 | QByteArray SieveHistory::lastDownloaded(QString *scriptName, QDateTime *when) const { | |
| 114 |
1/1✓ Branch 2 → 3 taken 5 times.
|
5 | const QDir dir(m_directory); |
| 115 |
2/2✓ Branch 6 → 7 taken 5 times.
✓ Branch 7 → 8 taken 5 times.
|
5 | QFile meta(dir.filePath(QStringLiteral("last.json"))); |
| 116 |
3/3✓ Branch 12 → 13 taken 5 times.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 15 taken 3 times.
|
5 | if (!meta.open(QIODevice::ReadOnly)) |
| 117 | 2 | return {}; | |
| 118 |
3/3✓ Branch 15 → 16 taken 3 times.
✓ Branch 16 → 17 taken 3 times.
✓ Branch 17 → 18 taken 3 times.
|
3 | const QJsonObject object = QJsonDocument::fromJson(meta.readAll()).object(); |
| 119 |
1/2✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 32 not taken.
|
3 | if (scriptName) |
| 120 |
2/2✓ Branch 24 → 25 taken 3 times.
✓ Branch 25 → 26 taken 3 times.
|
3 | *scriptName = object.value(QStringLiteral("script")).toString(); |
| 121 |
1/2✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 46 not taken.
|
3 | if (when) |
| 122 |
3/3✓ Branch 36 → 37 taken 3 times.
✓ Branch 37 → 38 taken 3 times.
✓ Branch 38 → 39 taken 3 times.
|
6 | *when = QDateTime::fromString(object.value(QStringLiteral("downloadedAt")).toString(), |
| 123 | 3 | Qt::ISODateWithMs); | |
| 124 |
2/2✓ Branch 49 → 50 taken 3 times.
✓ Branch 50 → 51 taken 3 times.
|
3 | QFile file(dir.filePath(QStringLiteral("last.sieve"))); |
| 125 |
3/4✓ Branch 55 → 56 taken 3 times.
✓ Branch 56 → 57 taken 3 times.
✗ Branch 56 → 58 not taken.
✓ Branch 57 → 59 taken 3 times.
|
3 | return file.open(QIODevice::ReadOnly) ? file.readAll() : QByteArray(); |
| 126 | 5 | } | |
| 127 |