• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IJHack / QtPass / 24100645899

07 Apr 2026 07:36PM UTC coverage: 21.014%. First build
24100645899

Pull #904

github

web-flow
Merge 6c5c75782 into 44219207b
Pull Request #904: refactor: reduce complexity in Pass::listKeys()

46 of 49 new or added lines in 2 files covered. (93.88%)

1107 of 5268 relevant lines covered (21.01%)

7.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.87
/src/gpgkeystate.cpp
1
// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "gpgkeystate.h"
4

5
#include "util.h"
6

7
#include <QRegularExpression>
8

9
constexpr int GPG_MIN_FIELDS = 10;
10
constexpr int GPG_FIELD_VALIDITY = 1;
11
constexpr int GPG_FIELD_KEY_ID = 4;
12
constexpr int GPG_FIELD_CREATED = 5;
13
constexpr int GPG_FIELD_EXPIRY = 6;
14
constexpr int GPG_FIELD_USERID = 9;
15

16
auto classifyRecord(const QString &record_type) -> GpgRecordType {
31✔
17
  if (record_type == "pub") {
31✔
18
    return GpgRecordType::Pub;
19
  }
20
  if (record_type == "sec") {
23✔
21
    return GpgRecordType::Sec;
22
  }
23
  if (record_type == "uid") {
21✔
24
    return GpgRecordType::Uid;
25
  }
26
  if (record_type == "fpr") {
14✔
27
    return GpgRecordType::Fpr;
28
  }
29
  if (record_type == "sub") {
6✔
30
    return GpgRecordType::Sub;
31
  }
32
  if (record_type == "ssb") {
4✔
33
    return GpgRecordType::Ssb;
34
  }
35
  if (record_type == "grp") {
2✔
36
    return GpgRecordType::Grp;
1✔
37
  }
38
  return GpgRecordType::Unknown;
39
}
40

41
void handlePubSecRecord(const QStringList &props, bool secret,
8✔
42
                        UserInfo &current_user) {
43
  current_user.key_id = props[GPG_FIELD_KEY_ID];
8✔
44
  current_user.name = props[GPG_FIELD_USERID].toUtf8();
16✔
45
  current_user.validity = props[GPG_FIELD_VALIDITY][0].toLatin1();
8✔
46

47
  bool okCreated = false;
8✔
48
  const qint64 createdSecs = props[GPG_FIELD_CREATED].toLongLong(&okCreated);
49
  if (okCreated) {
8✔
50
    current_user.created.setSecsSinceEpoch(createdSecs);
8✔
51
  }
52

53
  bool okExpiry = false;
8✔
54
  const qint64 expirySecs = props[GPG_FIELD_EXPIRY].toLongLong(&okExpiry);
55
  if (okExpiry) {
8✔
NEW
56
    current_user.expiry.setSecsSinceEpoch(expirySecs);
×
57
  }
58

59
  current_user.have_secret = secret;
8✔
60
}
8✔
61

62
void handleUidRecord(const QStringList &props, UserInfo &current_user) {
6✔
63
  current_user.name = props[GPG_FIELD_USERID];
6✔
64
}
6✔
65

66
void handleFprRecord(const QStringList &props, UserInfo &current_user) {
7✔
67
  if (props[GPG_FIELD_USERID].endsWith(current_user.key_id)) {
7✔
68
    current_user.key_id = props[GPG_FIELD_USERID];
3✔
69
  }
70
}
7✔
71

72
auto parseGpgColonOutput(const QString &output, bool secret)
5✔
73
    -> QList<UserInfo> {
74
  QList<UserInfo> users;
10✔
75

76
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
77
  const QStringList lines =
78
      output.split(Util::newLinesRegex(), Qt::SkipEmptyParts);
5✔
79
#else
80
  const QStringList lines =
81
      output.split(Util::newLinesRegex(), QString::SkipEmptyParts);
82
#endif
83

84
  UserInfo current_user;
5✔
85

86
  for (const QString &key : lines) {
29✔
87
    QStringList props = key.split(':');
24✔
88
    if (props.size() < GPG_MIN_FIELDS) {
24✔
89
      continue;
90
    }
91

92
    const QString record_type = props[0];
93
    const GpgRecordType type = classifyRecord(record_type);
23✔
94

95
    switch (type) {
23✔
96
    case GpgRecordType::Pub:
97
    case GpgRecordType::Sec:
98
      if (!current_user.key_id.isEmpty()) {
8✔
99
        users.append(current_user);
100
      }
101
      current_user = UserInfo();
8✔
102
      handlePubSecRecord(props, secret == (type == GpgRecordType::Sec),
8✔
103
                         current_user);
104
      break;
105
    case GpgRecordType::Uid:
106
      if (current_user.name.isEmpty()) {
6✔
107
        handleUidRecord(props, current_user);
6✔
108
      }
109
      break;
110
    case GpgRecordType::Fpr:
7✔
111
      handleFprRecord(props, current_user);
7✔
112
      break;
113
    default:
114
      break;
115
    }
116
  }
117

118
  if (!current_user.key_id.isEmpty()) {
5✔
119
    users.append(current_user);
120
  }
121

122
  return users;
5✔
123
}
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc