File indexing completed on 2024-05-12 05:10:35
0001 /* 0002 SPDX-FileCopyrightText: 2013 Sérgio Martins <iamsergio@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0005 */ 0006 0007 #include "backuper.h" 0008 #include "calendarjanitor.h" 0009 #include "options.h" 0010 0011 #include "console-version.h" 0012 0013 #include <KAboutData> 0014 #include <KLocalizedString> 0015 0016 #include <QCommandLineOption> 0017 #include <QCommandLineParser> 0018 #include <QCoreApplication> 0019 #include <QString> 0020 #include <QTextStream> 0021 #include <qglobal.h> 0022 0023 #ifdef Q_OS_UNIX 0024 #include <fcntl.h> 0025 #include <sys/stat.h> 0026 #include <sys/types.h> 0027 #include <unistd.h> 0028 #endif 0029 0030 #ifndef COMPILE_WITH_UNITY_CMAKE_SUPPORT 0031 static void printOut(const QString &message) 0032 { 0033 QTextStream out(stdout); 0034 out << message << "\n"; 0035 } 0036 #endif 0037 0038 static void printCollectionsUsage() 0039 { 0040 printOut(i18n("Error while parsing %1", QStringLiteral("--collections"))); 0041 printOut(i18n("Example usage: %1", QStringLiteral("--collections 90,23,40"))); 0042 } 0043 0044 static void silenceStderr() 0045 { 0046 #ifdef Q_OS_UNIX 0047 if (qgetenv("KDE_CALENDARJANITOR_DEBUG") != "1") { 0048 // krazy:cond=syscalls since UNIX-only code 0049 // Disable stderr so we can actually read what's going on 0050 int fd = ::open("/dev/null", O_WRONLY); 0051 ::dup2(fd, 2); 0052 ::close(fd); 0053 // krazy:endcond=syscalls 0054 } 0055 #endif 0056 } 0057 0058 int main(int argv, char *argc[]) 0059 { 0060 KLocalizedString::setApplicationDomain(QByteArrayLiteral("calendarjanitor")); 0061 KAboutData aboutData(QStringLiteral("calendarjanitor"), i18n("CalendarJanitor"), QStringLiteral(KDEPIM_VERSION)); 0062 aboutData.setLicense(KAboutLicense::GPL_V2, KAboutLicense::OrLaterVersions); 0063 aboutData.addAuthor(i18n("Sérgio Martins"), i18n("Maintainer"), QStringLiteral("iamsergiogmail.com")); 0064 aboutData.setShortDescription(i18n("A command line interface to report and fix errors in your calendar data")); 0065 0066 QCoreApplication app(argv, argc); 0067 0068 QCommandLineParser parser; 0069 QCommandLineOption colsOpt(QStringLiteral("collections"), i18n("Comma-separated list of collection ids to scan"), QStringLiteral("ids")); 0070 QCommandLineOption fixOpt(QStringLiteral("fix"), i18n("Fix broken incidences")); 0071 QCommandLineOption backupOpt(QStringLiteral("backup"), i18n("Backup your calendar"), QStringLiteral("output.ics")); 0072 QCommandLineOption stripOldAlarmsOpt(QStringLiteral("strip-old-alarms"), i18n("Delete alarms older than 365 days")); 0073 parser.addOptions({colsOpt, fixOpt, backupOpt, stripOldAlarmsOpt}); 0074 aboutData.setupCommandLine(&parser); 0075 0076 parser.process(app); 0077 aboutData.processCommandLine(&parser); 0078 0079 Options janitorOptions; 0080 if (parser.isSet(colsOpt)) { 0081 QString option = parser.value(colsOpt); 0082 const QStringList collections = option.split(QLatin1Char(',')); 0083 QList<Akonadi::Collection::Id> ids; 0084 for (const QString &collection : collections) { 0085 bool ok = false; 0086 int num = collection.toInt(&ok); 0087 if (ok) { 0088 ids << num; 0089 } else { 0090 printCollectionsUsage(); 0091 return -1; 0092 } 0093 0094 if (ids.isEmpty()) { 0095 printCollectionsUsage(); 0096 return -1; 0097 } else { 0098 janitorOptions.setCollections(ids); 0099 } 0100 } 0101 } 0102 0103 if (parser.isSet(fixOpt) && parser.isSet(backupOpt)) { 0104 printOut(i18n("--fix is incompatible with --backup")); 0105 return -1; 0106 } 0107 0108 if (parser.isSet(stripOldAlarmsOpt) && parser.isSet(backupOpt)) { 0109 printOut(i18n("--strip-old-alarms is incompatible with --backup")); 0110 return -1; 0111 } 0112 0113 if (parser.isSet(stripOldAlarmsOpt) && parser.isSet(fixOpt)) { 0114 printOut(i18n("--strip-old-alarms is incompatible with --fix")); 0115 return -1; 0116 } 0117 0118 silenceStderr(); // Switching off mobile phones, movie is about to start 0119 0120 janitorOptions.setStripOldAlarms(parser.isSet(stripOldAlarmsOpt)); 0121 0122 QString backupFile; 0123 if (parser.isSet(fixOpt)) { 0124 janitorOptions.setAction(Options::ActionScanAndFix); 0125 printOut(i18n("Running in fix mode.")); 0126 } else if (parser.isSet(backupOpt)) { 0127 backupFile = parser.value(backupOpt); 0128 if (backupFile.isEmpty()) { 0129 printOut(i18n("Please specify a output file.")); 0130 return -1; 0131 } 0132 janitorOptions.setAction(Options::ActionBackup); 0133 } else { 0134 printOut(i18n("Running in scan only mode.")); 0135 janitorOptions.setAction(Options::ActionScan); 0136 } 0137 0138 switch (janitorOptions.action()) { 0139 case Options::ActionBackup: { 0140 auto backuper = new Backuper(); 0141 backuper->backup(backupFile, janitorOptions.collections()); 0142 break; 0143 } 0144 case Options::ActionScan: 0145 case Options::ActionScanAndFix: { 0146 auto janitor = new CalendarJanitor(janitorOptions); 0147 janitor->start(); 0148 break; 0149 } 0150 default: 0151 Q_ASSERT(false); 0152 } 0153 0154 return app.exec(); 0155 }