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

IJHack / QtPass / 36413043641

28 Sep 2026 11:00AM UTC coverage: 68.476% (+0.2%) from 68.298%
36413043641

Pull #1952

github

web-flow
Merge fa6ef88e2 into b987bc7a1
Pull Request #1952: 1.8: keep the entry when saving it fails (ported from #1951)

49 of 60 new or added lines in 6 files covered. (81.67%)

73 existing lines in 2 files now uncovered.

5122 of 7480 relevant lines covered (68.48%)

68.05 hits per line

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

1.28
/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 "util.h"
6

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

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

24
RealPass::RealPass() = default;
3 ✔
25

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

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

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

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

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

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

76
/**
77
 * @brief RealPass::Insert pass insert
78
 */
79
void RealPass::Insert(QString file, QString newValue, bool overwrite) {
×
80
  m_insertTarget =
NEW
81
      QDir::cleanPath(QDir::isAbsolutePath(file)
×
NEW
82
                          ? file + ".gpg"
×
NEW
83
                          : QDir(m_settings.passStore).filePath(file) + ".gpg");
×
NEW
84
  m_insertTargetExisted = QFileInfo::exists(m_insertTarget);
×
85
  QStringList args = {"insert", "-m"};
×
86
  if (overwrite) {
×
87
    args.append("-f");
×
88
  }
89
  args.append(file);
90
  executePass(PASS_INSERT, args, newValue);
×
91
}
×
92

NEW
93
auto RealPass::insertWritten() const -> bool {
×
NEW
94
  return !m_insertTarget.isEmpty() && !m_insertTargetExisted &&
×
NEW
95
         QFileInfo::exists(m_insertTarget);
×
96
}
97

98
/**
99
 * @brief RealPass::Remove pass remove wrapper
100
 */
101
void RealPass::Remove(QString file, bool isDir) {
×
102
  executePass(PASS_REMOVE, {"rm", (isDir ? "-rf" : "-f"), file});
×
103
}
×
104

105
/**
106
 * @brief RealPass::Init initialize pass repository
107
 *
108
 * @param path  Absolute path to new password-store
109
 * @param users list of users with ability to decrypt new password-store
110
 */
111
void RealPass::Init(QString path, const QList<UserInfo> &users) {
×
112
  // remove the passStore directory otherwise,
113
  // pass would create a passStore/passStore/dir
114
  // but you want passStore/dir
115
  QString normalizedPath = QDir::cleanPath(path);
×
116
  QString normalizedStore = QDir::cleanPath(m_settings.passStore);
×
117
  QString dirWithoutPassdir;
×
118
  if (normalizedPath.startsWith(normalizedStore)) {
×
119
    dirWithoutPassdir = normalizedPath.mid(normalizedStore.size());
×
120
    if (dirWithoutPassdir.startsWith('/')) {
×
121
      dirWithoutPassdir.remove(0, 1);
×
122
    }
123
  } else {
124
    dirWithoutPassdir = normalizedPath;
×
125
  }
126
  QStringList args = {"init", "--path=" + dirWithoutPassdir};
×
127
  foreach (const UserInfo &user, users) {
×
128
    if (user.enabled) {
×
129
      args.append(user.key_id);
×
130
    }
131
  }
132
  executePass(PASS_INIT, args);
×
133
}
×
134

135
/**
136
 * @brief RealPass::Move move a file (or folder)
137
 * @param src source file or folder
138
 * @param dest destination file or folder
139
 * @param force overwrite
140
 */
141
void RealPass::Move(const QString src, const QString dest, const bool force) {
×
142
  passMoveOrCopy(PASS_MOVE, QStringLiteral("mv"), src, dest, force);
×
143
}
×
144

145
/**
146
 * @brief RealPass::Copy copy a file (or folder)
147
 * @param src source file or folder
148
 * @param dest destination file or folder
149
 * @param force overwrite
150
 */
151
void RealPass::Copy(const QString src, const QString dest, const bool force) {
×
152
  passMoveOrCopy(PASS_COPY, QStringLiteral("cp"), src, dest, force);
×
153
}
×
154

155
/**
156
 * @brief RealPass::passMoveOrCopy shared `pass mv` / `pass cp` implementation.
157
 * @param id PASS_MOVE or PASS_COPY.
158
 * @param subcommand "mv" or "cp".
159
 * @param src source file or folder.
160
 * @param dest destination file or folder.
161
 * @param force overwrite.
162
 */
163
void RealPass::passMoveOrCopy(PROCESS id, const QString &subcommand,
×
164
                              const QString &src, const QString &dest,
165
                              const bool force) {
166
  QFileInfo srcFileInfo = QFileInfo(src);
×
167
  QFileInfo destFileInfo = QFileInfo(dest);
×
168

169
  // force mode?
170
  // pass uses always the force mode, when call from eg. QT. so we have to
171
  // check if this are to files and the user didn't want to move force
172
  if (!force && srcFileInfo.isFile() && destFileInfo.isFile()) {
×
173
    return;
174
  }
175

176
  QString normalizedStore = QDir::cleanPath(m_settings.passStore);
×
177
  QString normalizedSrc = QDir::cleanPath(QDir(src).absolutePath());
×
178
  QString normalizedDest = QDir::cleanPath(QDir(dest).absolutePath());
×
179

180
  QString passSrc = QDir(normalizedStore).relativeFilePath(normalizedSrc);
×
181
  QString passDest = QDir(normalizedStore).relativeFilePath(normalizedDest);
×
182

183
  // remove the .gpg because pass will not work
184
  if (srcFileInfo.isFile() && srcFileInfo.suffix() == "gpg") {
×
185
    passSrc.replace(Util::endsWithGpg(), "");
×
186
  }
187
  if (destFileInfo.isFile() && destFileInfo.suffix() == "gpg") {
×
188
    passDest.replace(Util::endsWithGpg(), "");
×
189
  }
190

191
  QStringList args;
×
192
  args << subcommand;
193
  if (force) {
×
194
    args << "-f";
×
195
  }
196
  args << passSrc;
197
  args << passDest;
198
  executePass(id, args);
×
199
}
×
200

201
/**
202
 * @brief Search all password content via 'pass grep'.
203
 *
204
 * The pattern is interpreted by `pass grep` (GNU grep, **POSIX BRE**), which
205
 * differs from the PCRE dialect used by the native backend — see
206
 * Pass::Grep for the cross-backend caveat.
207
 * @param pattern Search pattern (POSIX BRE).
208
 * @param caseInsensitive true for case-insensitive search.
209
 */
210
void RealPass::Grep(QString pattern, bool caseInsensitive) {
×
211
  QStringList args = {"grep"};
×
212
  if (caseInsensitive)
×
213
    args << "-i";
×
214
  args << "--" << pattern;
×
215
  executePass(PASS_GREP, args, QString(), true);
×
216
}
×
217

218
/**
219
 * @brief Wrapper for executing pass commands.
220
 * @param id Process identifier for this operation
221
 * @param args Command-line arguments for pass
222
 * @param input Input to pass to the process (typically empty)
223
 * @param readStdout Whether to capture standard output
224
 * @param readStderr Whether to capture standard error output
225
 */
226
void RealPass::executePass(PROCESS id, const QStringList &args, QString input,
×
227
                           bool readStdout, bool readStderr) {
228
  executeWrapper(id, m_settings.passExecutable, args, std::move(input),
×
229
                 readStdout, readStderr);
230
}
×
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