Baloo

tools/experimental/baloodb/main.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Michael Heidelbach <heidelbach@web.de>
3
4 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5*/
6
7#include "global.h"
8#include "experimental/databasesanitizer.h"
9
10#include <KAboutData>
11#include <KLocalizedString>
12
13#include <QCoreApplication>
14#include <QCommandLineOption>
15#include <QCommandLineParser>
16#include <QStandardPaths>
17#include <QTextStream>
18#include <QList>
19#include <QElapsedTimer>
20
21using namespace Baloo;
22
23struct Command {
24 const QString name;
25 const QString description;
26 const QStringList args;
27 const QStringList options;
28};
29
30const auto options = QList<QCommandLineOption>{
32 QStringList{QStringLiteral("i"), QStringLiteral("device-id")},
33 i18n("Filter by device id."
34 "\n0 (default) does not filter and everything is printed."
35 "\nPositive numbers are including filters printing only the mentioned device id."
36 "\nNegative numbers are excluding filters printing everything but the mentioned device id."
37 "\nMay be given multiple times."),
38 i18n("integer"),
39 nullptr
40 },
42 QStringList{QStringLiteral("m"), QStringLiteral("missing-only")},
43 i18n("List only inaccessible entries.\nOnly applies to \"%1\"", QStringLiteral("list"))
44 },
46 QStringList{QStringLiteral("u"), QStringLiteral("mounted-only")},
47 i18n("Act only on item on mounted devices")
48 },
50 QStringList{QStringLiteral("D"), QStringLiteral("dry-run")},
51 i18n("Print results of a cleaning operation, but do not change anything."
52 "\nOnly applies to \"%1\" command", QStringLiteral("clean"))
53 }
54};
55
56const auto commands = std::vector<Command>{
57 Command{
58 QStringLiteral("list"),
59 i18n("List database contents. Use a regular expression as argument to filter output"),
61 QStringLiteral("pattern")
62 },
64 QStringLiteral("missing-only"),
65 QStringLiteral("device-id")
66 }
67 },
68 Command{
69 QStringLiteral("devices"),
70 i18n("List devices"),
72 QStringList{QStringLiteral("missing-only")}
73 },
74 /*TODO:
75 Command{
76 QStringLiteral("check"),
77 i18n("Check database contents. "
78 "Beware this may take very long to execute"),
79 QStringList{},
80 QStringList{}
81 },
82 */
83 Command{
84 QStringLiteral("clean"),
85 i18n("Remove stale database entries"),
87 QStringLiteral("pattern")
88 },
90 QStringLiteral("dry-run"),
91 QStringLiteral("device-id"),
92 QStringLiteral("mounted-only")
93 }
94 }
95};
96
97const QStringList allowedCommands()
98{
99 QStringList names;
100 for (const auto& c : commands) {
101 names.append(c.name);
102 }
103 return names;
104}
105const QStringList getOptions(const QString& name)
106{
107 for (const auto& c : commands) {
108 if (c.name == name) {
109 return c.options;
110 }
111 }
112 return QStringList();
113}
114QString createDescription()
115{
116 QStringList allowedcommands;
117 for (const auto& c: commands) {
118 auto options = getOptions(c.name);
119 const QString optionStr = options.isEmpty()
120 ? QString()
121 : QStringLiteral(" [--%1]").arg(options.join(QLatin1String("] [--")));
122
123 QString argumentStr;
124 if (!c.args.isEmpty() ) {
125 argumentStr = QStringLiteral(" [%1]").arg(c.args.join(QStringLiteral("] [")));
126 }
127
128 const QString commandStr = QStringLiteral("%1%2%3")
129 .arg(c.name)
130 .arg(optionStr)
131 .arg(argumentStr);
132
133 const QString str = QStringLiteral("%1 %2")
134 .arg(commandStr, -58)
135 .arg(c.description);
136
137 allowedcommands.append(str);
138 }
139 const QString allCommandsStr = allowedcommands.join(QLatin1String("\n "));
140 return i18n("\n\nCommands:\n %1", allCommandsStr);
141}
142
143int main(int argc, char* argv[])
144{
145 QCoreApplication app(argc, argv);
146 KAboutData aboutData(QStringLiteral("baloodb"),
147 i18n("Baloo Database Sanitizer"),
148 PROJECT_VERSION,
149 i18n("The Baloo Database Lister & Sanitizer"),
151 i18n("(c) 2018, Michael Heidelbach"));
152 aboutData.addAuthor(i18n("Michael Heidelbach"), i18n("Maintainer"), QStringLiteral("ottwolt@gmail.com"));
154
155 QCommandLineParser parser;
156 parser.addOptions(options);
157 parser.addPositionalArgument(QStringLiteral("command"),
158 i18n("The command to execute"),
159 allowedCommands().join(QLatin1Char('|'))
160 );
161 parser.addPositionalArgument(QStringLiteral("pattern"),
162 i18nc("Command", "A regular expression applied to the URL of database items"
163 "\nExample: %1"
164 , "baloodb list '^/media/videos/series'"
165 )
166 );
167 const QString warnExperiment = QStringLiteral(
168 "===\nPlease note: This is an experimental tool. Command line switches or their meaning may change.\n===");
169
170 parser.setApplicationDescription(warnExperiment + createDescription());
171 parser.addVersionOption();
172 parser.addHelpOption();
173
174 parser.process(app);
175 if (parser.positionalArguments().isEmpty()) {
176 qDebug() << "No command";
177 parser.showHelp(1);
178 }
179
180 auto args = parser.positionalArguments();
181 auto command = args.at(0);
182 args.removeFirst();
183
184 if(!allowedCommands().contains(command)) {
185 qDebug() << "Unknown command" << command;
186 parser.showHelp(1);
187 }
188
189 const auto optNames = parser.optionNames();
190 const auto allowedOptions = getOptions(command);
191
192 QVector<qint64> deviceIds;
193 for (const auto& dev : parser.values(QStringLiteral("device-id"))) {
194 deviceIds.append(dev.toInt());
195 }
196 const DatabaseSanitizer::ItemAccessFilters accessFilter = (
197 parser.isSet(QStringLiteral("missing-only"))
198 ? DatabaseSanitizer::IgnoreAvailable
199 : DatabaseSanitizer::IgnoreNone
200 ) | (
201 parser.isSet(QStringLiteral("mounted-only"))
202 ? DatabaseSanitizer::IgnoreUnmounted
203 : DatabaseSanitizer::IgnoreNone
204 );
205 const QString pattern = args.isEmpty()
206 ? QString()
207 : args.at(0);
208 const QSharedPointer<QRegularExpression> urlFilter(pattern.isEmpty()
209 ? nullptr
210 : new QRegularExpression{pattern});
211
212 auto db = globalDatabaseInstance();
213 QTextStream err(stderr);
214 QElapsedTimer timer;
215 timer.start();
216
217 if (command == QLatin1String("list")) {
218 if (!db->open(Database::ReadOnlyDatabase)) {
219 err << i18n("Baloo Index could not be opened") << endl;
220 return 1;
221 }
222 DatabaseSanitizer san(db, Transaction::ReadOnly);
223 err << i18n("Listing database contents...") << endl;
224 san.printList(deviceIds, accessFilter, urlFilter);
225 } else if (command == QLatin1String("devices")) {
226 if (!db->open(Database::ReadOnlyDatabase)) {
227 err << i18n("Baloo Index could not be opened") << endl;
228 return 1;
229 }
230 DatabaseSanitizer san(db, Transaction::ReadOnly);
231 err << i18n("Listing database contents...") << endl;
232 san.printDevices(deviceIds, accessFilter);
233
234 } else if (command == QLatin1String("clean")) {
235 auto dbMode = Database::ReadWriteDatabase;
236 if (!db->open(dbMode)) {
237 err << i18n("Baloo Index could not be opened") << endl;
238 return 1;
239 }
240 DatabaseSanitizer san(db, Transaction::ReadWrite);
241 err << i18n("Removing stale database contents...") << endl;
242 san.removeStaleEntries(deviceIds, accessFilter, parser.isSet(QStringLiteral("dry-run")), urlFilter);
243
244 } else if (command == QLatin1String("check")) {
245 parser.showHelp(1);
246 /* TODO: After check methods are improved
247 Database *db = globalDatabaseInstance();
248 if (!db->open(Database::ReadOnlyDatabase)) {
249 err << i18n("Baloo Index could not be opened") << endl;
250 return 1;
251 }
252 Transaction tr(db, Transaction::ReadOnly);
253 err << i18n("Checking file paths ... ") << endl;
254 tr.checkFsTree();
255
256 err << i18n("Checking postings ... ") << endl;
257 tr.checkTermsDbinPostingDb();
258
259 err << i18n("Checking terms ... ") << endl;
260 tr.checkPostingDbinTermsDb();
261 */
262 }
263 err << i18n("Elapsed: %1 secs", timer.nsecsElapsed() / 1000000000.0) << endl;
264
265 return 0;
266}
An Abstract class from which all other balooctl commands can inherit from.
Definition command.h:20
Provide methods to show database problems and sanitize them.
static void setApplicationData(const KAboutData &aboutData)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Implements storage for docIds without any associated data Instantiated for:
Definition coding.cpp:11
QCommandLineOption addHelpOption()
bool addOptions(const QList< QCommandLineOption > &options)
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
QCommandLineOption addVersionOption()
bool isSet(const QCommandLineOption &option) const const
QStringList optionNames() const const
QStringList positionalArguments() const const
void process(const QCoreApplication &app)
void setApplicationDescription(const QString &description)
void showHelp(int exitCode)
QStringList values(const QCommandLineOption &option) const const
qint64 nsecsElapsed() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool isEmpty() const const
QString arg(Args &&... args) const const
bool isEmpty() const const
QString join(QChar separator) const const
QTextStream & endl(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:18:13 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.