presentation/ComposeDraftFiles.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ComposeDraftFiles.h" | ||
| 2 | |||
| 3 | #include <QDir> | ||
| 4 | #include <QFile> | ||
| 5 | #include <QFileInfo> | ||
| 6 | #include <QJsonDocument> | ||
| 7 | #include <QSaveFile> | ||
| 8 | #include <QUuid> | ||
| 9 | #include <algorithm> | ||
| 10 | |||
| 11 | namespace ComposeDraftFiles { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | constexpr auto OwnerDirectory = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner; | ||
| 15 | 332 | QString draftPath(const QString &profile, const QString &session) { | |
| 16 |
3/3✓ Branch 2 → 3 taken 332 times.
✓ Branch 3 → 4 taken 332 times.
✓ Branch 7 → 8 taken 332 times.
|
664 | return QDir(sessionDirectory(profile, session)).filePath(QStringLiteral("draft.json")); |
| 17 | } | ||
| 18 | } // namespace | ||
| 19 | |||
| 20 | 2522 | QString root(const QString &profileDirectory) { | |
| 21 |
2/2✓ Branch 2 → 3 taken 2522 times.
✓ Branch 6 → 7 taken 2522 times.
|
5044 | return QDir(profileDirectory).filePath(QStringLiteral("compose-drafts")); |
| 22 | } | ||
| 23 | |||
| 24 | 753 | QString sessionDirectory(const QString &profileDirectory, const QString &sessionId) { | |
| 25 |
3/3✓ Branch 2 → 3 taken 753 times.
✓ Branch 3 → 4 taken 753 times.
✓ Branch 4 → 5 taken 753 times.
|
753 | return QDir(root(profileDirectory)).filePath(sessionId); |
| 26 | } | ||
| 27 | |||
| 28 | 193 | QString filesDirectory(const QString &profileDirectory, const QString &sessionId) { | |
| 29 |
3/3✓ Branch 2 → 3 taken 193 times.
✓ Branch 3 → 4 taken 193 times.
✓ Branch 7 → 8 taken 193 times.
|
386 | return QDir(sessionDirectory(profileDirectory, sessionId)).filePath(QStringLiteral("files")); |
| 30 | } | ||
| 31 | |||
| 32 | 382 | bool validSessionId(const QString &sessionId) { | |
| 33 |
2/3✓ Branch 8 → 9 taken 382 times.
✓ Branch 9 → 10 taken 382 times.
✗ Branch 9 → 17 not taken.
|
764 | return !QUuid::fromString(sessionId).isNull() && !sessionId.contains(QLatin1Char('/')) && |
| 34 |
4/7✓ Branch 5 → 6 taken 382 times.
✗ Branch 5 → 17 not taken.
✓ Branch 12 → 13 taken 382 times.
✓ Branch 13 → 14 taken 382 times.
✗ Branch 13 → 17 not taken.
✓ Branch 15 → 16 taken 382 times.
✗ Branch 15 → 17 not taken.
|
764 | !sessionId.contains(QLatin1Char('\\')) && sessionId.size() <= 40; |
| 35 | } | ||
| 36 | |||
| 37 | 181 | bool save(const QString &profileDirectory, const QString &sessionId, const QJsonObject &draft, QString *error) { | |
| 38 |
4/7✓ Branch 3 → 4 taken 181 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 181 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 181 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 18 taken 181 times.
|
181 | if (profileDirectory.isEmpty() || !validSessionId(sessionId)) { |
| 39 | ✗ | if (error) *error = QStringLiteral("invalid draft session"); | |
| 40 | ✗ | return false; | |
| 41 | } | ||
| 42 | 181 | QJsonObject document = draft; | |
| 43 |
2/2✓ Branch 19 → 20 taken 181 times.
✓ Branch 23 → 24 taken 181 times.
|
362 | document.insert(QStringLiteral("version"), SchemaVersion); |
| 44 |
2/2✓ Branch 27 → 28 taken 181 times.
✓ Branch 31 → 32 taken 181 times.
|
362 | document.insert(QStringLiteral("sessionId"), sessionId); |
| 45 |
4/4✓ Branch 35 → 36 taken 181 times.
✓ Branch 36 → 37 taken 181 times.
✓ Branch 37 → 38 taken 181 times.
✓ Branch 41 → 42 taken 181 times.
|
362 | document.insert(QStringLiteral("savedAt"), QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs)); |
| 46 |
2/2✓ Branch 47 → 48 taken 181 times.
✓ Branch 48 → 49 taken 181 times.
|
181 | const QByteArray bytes = QJsonDocument(document).toJson(QJsonDocument::Compact); |
| 47 |
1/2✗ Branch 51 → 52 not taken.
✓ Branch 51 → 61 taken 181 times.
|
181 | if (bytes.size() > MaxDraftBytes) { |
| 48 | ✗ | if (error) *error = QStringLiteral("too large"); | |
| 49 | ✗ | return false; | |
| 50 | } | ||
| 51 |
1/1✓ Branch 61 → 62 taken 181 times.
|
181 | const QString directory = sessionDirectory(profileDirectory, sessionId); |
| 52 |
4/4✓ Branch 63 → 64 taken 181 times.
✓ Branch 64 → 65 taken 181 times.
✓ Branch 67 → 68 taken 3 times.
✓ Branch 67 → 77 taken 178 times.
|
181 | if (!QDir().mkpath(directory)) { |
| 53 |
1/2✓ Branch 68 → 69 taken 3 times.
✗ Branch 68 → 76 not taken.
|
6 | if (error) *error = QStringLiteral("cannot create the draft folder"); |
| 54 | 3 | return false; | |
| 55 | } | ||
| 56 |
2/2✓ Branch 77 → 78 taken 178 times.
✓ Branch 78 → 79 taken 178 times.
|
178 | QFile::setPermissions(root(profileDirectory), OwnerDirectory); |
| 57 |
1/1✓ Branch 80 → 81 taken 178 times.
|
178 | QFile::setPermissions(directory, OwnerDirectory); |
| 58 |
2/2✓ Branch 81 → 82 taken 178 times.
✓ Branch 82 → 83 taken 178 times.
|
178 | QSaveFile file(draftPath(profileDirectory, sessionId)); |
| 59 |
4/6✓ Branch 85 → 86 taken 178 times.
✓ Branch 88 → 89 taken 178 times.
✓ Branch 89 → 90 taken 178 times.
✗ Branch 89 → 95 not taken.
✓ Branch 92 → 93 taken 178 times.
✗ Branch 92 → 95 not taken.
|
534 | if (!file.open(QIODevice::WriteOnly) || !file.setPermissions(QFile::ReadOwner | QFile::WriteOwner) || |
| 60 |
5/8✓ Branch 86 → 87 taken 178 times.
✗ Branch 86 → 95 not taken.
✓ Branch 90 → 91 taken 178 times.
✓ Branch 93 → 94 taken 178 times.
✗ Branch 94 → 95 not taken.
✓ Branch 94 → 96 taken 178 times.
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 113 taken 178 times.
|
534 | file.write(bytes) != bytes.size() || !file.commit()) { |
| 61 | ✗ | if (error) *error = file.errorString().isEmpty() ? QStringLiteral("disk full") : file.errorString(); | |
| 62 | ✗ | return false; | |
| 63 | } | ||
| 64 | 178 | return true; | |
| 65 | 181 | } | |
| 66 | |||
| 67 | 143 | std::optional<QJsonObject> load(const QString &profileDirectory, const QString &sessionId) { | |
| 68 |
2/3✓ Branch 2 → 3 taken 143 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 143 times.
|
143 | if (!validSessionId(sessionId)) return std::nullopt; |
| 69 |
2/2✓ Branch 5 → 6 taken 143 times.
✓ Branch 6 → 7 taken 143 times.
|
143 | QFile file(draftPath(profileDirectory, sessionId)); |
| 70 |
7/8✓ Branch 9 → 10 taken 143 times.
✓ Branch 10 → 11 taken 85 times.
✓ Branch 10 → 13 taken 58 times.
✓ Branch 11 → 12 taken 85 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 85 times.
✓ Branch 15 → 16 taken 58 times.
✓ Branch 15 → 17 taken 85 times.
|
143 | if (!file.open(QIODevice::ReadOnly) || file.size() > MaxDraftBytes) return std::nullopt; |
| 71 | 85 | QJsonParseError parseError; | |
| 72 |
2/2✓ Branch 17 → 18 taken 85 times.
✓ Branch 18 → 19 taken 85 times.
|
85 | const QJsonDocument document = QJsonDocument::fromJson(file.read(MaxDraftBytes), &parseError); |
| 73 |
4/7✓ Branch 20 → 21 taken 85 times.
✗ Branch 20 → 23 not taken.
✓ Branch 21 → 22 taken 85 times.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 85 times.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 85 times.
|
85 | if (parseError.error != QJsonParseError::NoError || !document.isObject()) return std::nullopt; |
| 74 |
1/1✓ Branch 27 → 28 taken 85 times.
|
85 | const QJsonObject object = document.object(); |
| 75 |
6/16✓ Branch 31 → 32 taken 85 times.
✓ Branch 32 → 33 taken 85 times.
✓ Branch 33 → 34 taken 85 times.
✗ Branch 33 → 41 not taken.
✓ Branch 53 → 54 taken 85 times.
✗ Branch 53 → 55 not taken.
✓ Branch 55 → 56 taken 85 times.
✗ Branch 55 → 57 not taken.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 59 taken 85 times.
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 90 not taken.
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 94 not taken.
✗ Branch 96 → 97 not taken.
✗ Branch 96 → 98 not taken.
|
340 | if (object.value(QStringLiteral("version")).toInt() != SchemaVersion || |
| 76 |
8/22✓ Branch 37 → 38 taken 85 times.
✓ Branch 38 → 39 taken 85 times.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 85 times.
✓ Branch 43 → 44 taken 85 times.
✗ Branch 43 → 45 not taken.
✓ Branch 45 → 46 taken 85 times.
✗ Branch 45 → 47 not taken.
✓ Branch 47 → 48 taken 85 times.
✗ Branch 47 → 49 not taken.
✓ Branch 49 → 50 taken 85 times.
✗ Branch 49 → 51 not taken.
✓ Branch 51 → 52 taken 85 times.
✗ Branch 51 → 53 not taken.
✗ Branch 72 → 73 not taken.
✗ Branch 72 → 74 not taken.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 82 not taken.
✗ Branch 84 → 85 not taken.
✗ Branch 84 → 86 not taken.
|
170 | object.value(QStringLiteral("sessionId")).toString() != sessionId) |
| 77 | ✗ | return std::nullopt; | |
| 78 | 85 | return object; | |
| 79 | 143 | } | |
| 80 | |||
| 81 | 796 | QStringList sessions(const QString &profileDirectory) { | |
| 82 |
2/2✓ Branch 2 → 3 taken 796 times.
✓ Branch 3 → 4 taken 796 times.
|
796 | const QDir directory(root(profileDirectory)); |
| 83 | 796 | QList<QPair<QDateTime, QString>> found; | |
| 84 |
5/5✓ Branch 7 → 8 taken 796 times.
✓ Branch 8 → 9 taken 796 times.
✓ Branch 9 → 10 taken 796 times.
✓ Branch 31 → 11 taken 6 times.
✓ Branch 31 → 32 taken 796 times.
|
802 | for (const QString &name : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { |
| 85 |
2/3✓ Branch 12 → 13 taken 6 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 6 times.
|
6 | if (!validSessionId(name)) continue; |
| 86 |
2/2✓ Branch 15 → 16 taken 6 times.
✓ Branch 16 → 17 taken 6 times.
|
6 | const QFileInfo info(draftPath(profileDirectory, name)); |
| 87 |
4/5✓ Branch 18 → 19 taken 6 times.
✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 26 not taken.
✓ Branch 20 → 21 taken 6 times.
✓ Branch 22 → 23 taken 6 times.
|
6 | if (info.isFile()) found.append({info.lastModified(), name}); |
| 88 | 802 | } | |
| 89 |
3/3✓ Branch 33 → 34 taken 796 times.
✓ Branch 34 → 35 taken 796 times.
✓ Branch 35 → 36 taken 796 times.
|
797 | std::sort(found.begin(), found.end(), [](const auto &a, const auto &b) { return a.first > b.first; }); |
| 90 | 796 | QStringList out; | |
| 91 |
3/3✓ Branch 40 → 41 taken 6 times.
✓ Branch 43 → 39 taken 6 times.
✓ Branch 43 → 44 taken 796 times.
|
802 | for (const auto &entry : std::as_const(found)) out.append(entry.second); |
| 92 | 796 | return out; | |
| 93 | 796 | } | |
| 94 | |||
| 95 | 47 | bool remove(const QString &profileDirectory, const QString &sessionId) { | |
| 96 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 47 times.
|
47 | if (!validSessionId(sessionId)) return false; |
| 97 |
3/3✓ Branch 5 → 6 taken 47 times.
✓ Branch 6 → 7 taken 47 times.
✓ Branch 7 → 8 taken 47 times.
|
47 | return QDir(sessionDirectory(profileDirectory, sessionId)).removeRecursively(); |
| 98 | } | ||
| 99 | |||
| 100 | 794 | int sweep(const QString &profileDirectory, const QSet<QString> &open, const QDateTime &before) { | |
| 101 | 794 | int removed = 0; | |
| 102 |
2/2✓ Branch 2 → 3 taken 794 times.
✓ Branch 3 → 4 taken 794 times.
|
794 | const QDir directory(root(profileDirectory)); |
| 103 |
5/5✓ Branch 7 → 8 taken 794 times.
✓ Branch 8 → 9 taken 794 times.
✓ Branch 9 → 10 taken 794 times.
✓ Branch 54 → 11 taken 5 times.
✓ Branch 54 → 55 taken 794 times.
|
799 | for (const QString &name : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { |
| 104 |
4/7✓ Branch 12 → 13 taken 5 times.
✓ Branch 13 → 14 taken 5 times.
✗ Branch 13 → 16 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 5 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 5 times.
|
5 | if (!validSessionId(name) || open.contains(name)) continue; |
| 105 |
2/2✓ Branch 20 → 21 taken 5 times.
✓ Branch 21 → 22 taken 5 times.
|
5 | const QFileInfo draft(draftPath(profileDirectory, name)); |
| 106 |
5/15✓ Branch 23 → 24 taken 5 times.
✓ Branch 24 → 25 taken 5 times.
✗ Branch 24 → 26 not taken.
✓ Branch 25 → 29 taken 5 times.
✗ Branch 26 → 27 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 31 taken 5 times.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 5 times.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
✗ Branch 70 → 71 not taken.
✗ Branch 70 → 72 not taken.
|
5 | const QDateTime stamp = draft.isFile() ? draft.lastModified() : QFileInfo(directory.filePath(name)).lastModified(); |
| 107 |
5/18✓ Branch 33 → 34 taken 5 times.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 41 taken 5 times.
✗ Branch 36 → 37 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 39 → 41 not taken.
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 44 taken 5 times.
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 5 times.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 5 times.
✗ Branch 74 → 75 not taken.
✗ Branch 74 → 76 not taken.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 80 not taken.
|
5 | if (stamp < before && QDir(directory.filePath(name)).removeRecursively()) ++removed; |
| 108 | 799 | } | |
| 109 | 794 | return removed; | |
| 110 | 794 | } | |
| 111 | |||
| 112 | } // namespace ComposeDraftFiles | ||
| 113 |