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

IJHack / QtPass / 27480142055

13 Jun 2026 09:50PM UTC coverage: 56.384% (+0.8%) from 55.569%
27480142055

push

github

web-flow
refactor: introduce AppSettings struct + SettingsSerializer (#1511) (#1528)

First stage of the QtPassSettings boilerplate reduction (#1511). Adds the
foundation without touching existing behaviour:

- AppSettings (src/appsettings.h): a plain value object with one field per
  flat setting, carrying the same defaults the legacy getters apply
  (PasswordConfiguration length 16, clipBoardType NEVER, etc.). No QSettings
  dependency.
- SettingsSerializer (src/settingsserializer.{h,cpp}): pure, side-effect-free
  load()/save() between AppSettings and a QSettings store, using the exact
  same keys QtPassSettings uses so existing config files keep working.
  Unlike the old getters it performs no path normalisation, directory
  creation, screen-centring or .git auto-detection — those stay in the
  consumers.
- Tests in tst_settings: load-defaults, full save/load round-trip across
  every field, and key-compatibility against SettingsConstants.

Nested/keyed settings (profiles, per-dialog geometry, splitter positions)
are intentionally out of scope and still go through QtPassSettings; the
profile type is tracked separately. No existing getters are rewired yet —
that is staged in follow-up PRs (ConfigDialog, then other readers, then
deleting the wrappers). #1511 stays open.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

132 of 133 new or added lines in 1 file covered. (99.25%)

292 existing lines in 3 files now uncovered.

3864 of 6853 relevant lines covered (56.38%)

36.36 hits per line

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

1.59
/src/realpass.cpp
1
// SPDX-FileCopyrightText: 2016 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "realpass.h"
4
#include "debughelper.h"
5
#include "qtpasssettings.h"
6
#include "util.h"
7

8
#include <QDir>
9
#include <QFileInfo>
10
#include <QRegularExpression>
11
#include <utility>
12

13
using Enums::GIT_INIT;
14
using Enums::GIT_PULL;
15
using Enums::GIT_PUSH;
16
using Enums::PASS_COPY;
17
using Enums::PASS_GREP;
18
using Enums::PASS_INIT;
19
using Enums::PASS_INSERT;
20
using Enums::PASS_MOVE;
21
using Enums::PASS_OTP_GENERATE;
22
using Enums::PASS_REMOVE;
23
using Enums::PASS_SHOW;
24

25
RealPass::RealPass() = default;
1✔
26

27
/**
28
 * @brief RealPass::GitInit pass git init wrapper
29
 */
30
void RealPass::GitInit() { executePass(GIT_INIT, {"git", "init"}); }
×
31

32
/**
33
 * @brief RealPass::GitInit pass git pull wrapper which blocks until process
34
 *                          finishes
35
 */
36
void RealPass::GitPull_b() {
×
37
  int result = Executor::executeBlocking(QtPassSettings::getPassExecutable(),
×
38
                                         {"git", "pull"});
39
  if (result != 0) {
40
#ifdef QT_DEBUG
41
    dbg() << "Git pull failed with code:" << result;
42
#endif
43
  }
44
}
×
45

46
/**
47
 * @brief RealPass::GitPull pass git pull wrapper
48
 */
49
void RealPass::GitPull() { executePass(GIT_PULL, {"git", "pull"}); }
×
50

51
/**
52
 * @brief RealPass::GitPush pass git push wrapper
53
 */
54
void RealPass::GitPush() { executePass(GIT_PUSH, {"git", "push"}); }
×
55

56
/**
57
 * @brief RealPass::Show pass show
58
 *
59
 * @param file      file to decrypt
60
 *
61
 * @return  if block is set, returns exit status of internal decryption
62
 * process
63
 *          otherwise returns QProcess::NormalExit
64
 */
65
void RealPass::Show(QString file) {
×
66
  executePass(PASS_SHOW, {"show", file}, "", true);
×
67
}
×
68

69
/**
70
 * @brief RealPass::OtpGenerate pass otp
71
 * @param file      file containing OTP uri
72
 */
73
void RealPass::OtpGenerate(QString file) {
×
74
  executePass(PASS_OTP_GENERATE, {"otp", file}, "", true);
×
75
}
×
76

77
/**
78
 * @brief RealPass::Insert pass insert
79
 */
80
void RealPass::Insert(QString file, QString newValue, bool overwrite) {
×
81
  QStringList args = {"insert", "-m"};
×
82
  if (overwrite) {
×
83
    args.append("-f");
×
84
  }
85
  args.append(file);
86
  executePass(PASS_INSERT, args, newValue);
×
87
}
×
88

89
/**
90
 * @brief RealPass::Remove pass remove wrapper
91
 */
92
void RealPass::Remove(QString file, bool isDir) {
×
93
  executePass(PASS_REMOVE, {"rm", (isDir ? "-rf" : "-f"), file});
×
94
}
×
95

96
/**
97
 * @brief RealPass::Init initialize pass repository
98
 *
99
 * @param path  Absolute path to new password-store
100
 * @param users list of users with ability to decrypt new password-store
101
 */
102
void RealPass::Init(QString path, const QList<UserInfo> &users) {
×
103
  // remove the passStore directory otherwise,
104
  // pass would create a passStore/passStore/dir
105
  // but you want passStore/dir
106
  QString dirWithoutPassdir =
107
      path.remove(0, QtPassSettings::getPassStore().size());
×
108
  QStringList args = {"init", "--path=" + dirWithoutPassdir};
×
109
  foreach (const UserInfo &user, users) {
×
110
    if (user.enabled) {
×
111
      args.append(user.key_id);
×
112
    }
113
  }
114
  executePass(PASS_INIT, args);
×
115
}
×
116

117
/**
118
 * @brief RealPass::Move move a file (or folder)
119
 * @param src source file or folder
120
 * @param dest destination file or folder
121
 * @param force overwrite
122
 */
123
void RealPass::Move(const QString src, const QString dest, const bool force) {
×
124
  passMoveOrCopy(PASS_MOVE, QStringLiteral("mv"), src, dest, force);
×
125
}
×
126

127
/**
128
 * @brief RealPass::Copy copy a file (or folder)
129
 * @param src source file or folder
130
 * @param dest destination file or folder
131
 * @param force overwrite
132
 */
133
void RealPass::Copy(const QString src, const QString dest, const bool force) {
×
134
  passMoveOrCopy(PASS_COPY, QStringLiteral("cp"), src, dest, force);
×
135
}
×
136

137
/**
138
 * @brief RealPass::passMoveOrCopy shared `pass mv` / `pass cp` implementation.
139
 * @param id PASS_MOVE or PASS_COPY.
140
 * @param subcommand "mv" or "cp".
141
 * @param src source file or folder.
142
 * @param dest destination file or folder.
143
 * @param force overwrite.
144
 */
145
void RealPass::passMoveOrCopy(PROCESS id, const QString &subcommand,
×
146
                              const QString &src, const QString &dest,
147
                              const bool force) {
148
  QFileInfo srcFileInfo = QFileInfo(src);
×
149
  QFileInfo destFileInfo = QFileInfo(dest);
×
150

151
  // force mode?
152
  // pass uses always the force mode, when call from eg. QT. so we have to
153
  // check if this are to files and the user didn't want to move force
154
  if (!force && srcFileInfo.isFile() && destFileInfo.isFile()) {
×
155
    return;
156
  }
157

158
  QString passSrc = QDir(QtPassSettings::getPassStore())
×
159
                        .relativeFilePath(QDir(src).absolutePath());
×
160
  QString passDest = QDir(QtPassSettings::getPassStore())
×
161
                         .relativeFilePath(QDir(dest).absolutePath());
×
162

163
  // remove the .gpg because pass will not work
164
  if (srcFileInfo.isFile() && srcFileInfo.suffix() == "gpg") {
×
165
    passSrc.replace(Util::endsWithGpg(), "");
×
166
  }
167
  if (destFileInfo.isFile() && destFileInfo.suffix() == "gpg") {
×
168
    passDest.replace(Util::endsWithGpg(), "");
×
169
  }
170

171
  QStringList args;
×
172
  args << subcommand;
173
  if (force) {
×
174
    args << "-f";
×
175
  }
176
  args << passSrc;
177
  args << passDest;
178
  executePass(id, args);
×
179
}
×
180

181
/**
182
 * @brief Search all password content via 'pass grep'.
183
 *
184
 * The pattern is interpreted by `pass grep` (GNU grep, **POSIX BRE**), which
185
 * differs from the PCRE dialect used by the native backend — see
186
 * Pass::Grep for the cross-backend caveat.
187
 * @param pattern Search pattern (POSIX BRE).
188
 * @param caseInsensitive true for case-insensitive search.
189
 */
190
void RealPass::Grep(QString pattern, bool caseInsensitive) {
×
191
  QStringList args = {"grep"};
×
192
  if (caseInsensitive)
×
UNCOV
193
    args << "-i";
×
UNCOV
194
  args << "--" << pattern;
×
UNCOV
195
  executePass(PASS_GREP, args, QString(), true);
×
UNCOV
196
}
×
197

198
/**
199
 * @brief Wrapper for executing pass commands.
200
 * @param id Process identifier for this operation
201
 * @param args Command-line arguments for pass
202
 * @param input Input to pass to the process (typically empty)
203
 * @param readStdout Whether to capture standard output
204
 * @param readStderr Whether to capture standard error output
205
 */
206
void RealPass::executePass(PROCESS id, const QStringList &args, QString input,
×
207
                           bool readStdout, bool readStderr) {
UNCOV
208
  executeWrapper(id, QtPassSettings::getPassExecutable(), args,
×
209
                 std::move(input), readStdout, readStderr);
UNCOV
210
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc