File indexing completed on 2024-05-05 04:38:45
0001 /* 0002 SPDX-FileCopyrightText: 2016 Anton Anikin <anton.anikin@htower.ru> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kdevformatfile.h" 0008 #include "wildcardhelpers.h" 0009 0010 #include <QDir> 0011 #include <QFile> 0012 #include <QFileInfo> 0013 #include <QProcess> 0014 0015 #include <utility> 0016 0017 namespace KDevelop { 0018 0019 KDevFormatFile::KDevFormatFile(const QString& origFilePath, const QString& tempFilePath) 0020 : formatFileName{QStringLiteral("format_sources")} 0021 , m_origFilePath(origFilePath) 0022 , m_tempFilePath(tempFilePath) 0023 { 0024 } 0025 0026 bool KDevFormatFile::find() 0027 { 0028 QDir srcDir(QFileInfo(m_origFilePath).canonicalPath()); 0029 0030 do { 0031 if (srcDir.exists(formatFileName)) { 0032 QDir::setCurrent(srcDir.canonicalPath()); 0033 0034 qStdOut() << "found \"" 0035 << QFileInfo(srcDir.canonicalPath() + QDir::separator() + formatFileName).canonicalFilePath() 0036 << "\"\n"; 0037 return true; 0038 } 0039 } while (!srcDir.isRoot() && srcDir.cdUp()); 0040 0041 return false; 0042 } 0043 0044 bool KDevFormatFile::read() 0045 { 0046 constexpr QChar delimiter = QLatin1Char(':'); 0047 0048 QFile formatFile(formatFileName); 0049 if (!formatFile.open(QIODevice::ReadOnly | QIODevice::Text)) { 0050 qStdOut() << "unable to open \"" << formatFileName << "\"\n"; 0051 return false; 0052 } 0053 0054 int lineNumber = 0; 0055 while (!formatFile.atEnd()) { 0056 ++lineNumber; 0057 0058 QString line = QString::fromUtf8(formatFile.readLine().trimmed()); 0059 if (line.isEmpty() || line.startsWith(QLatin1Char('#'))) 0060 continue; 0061 0062 if (line.indexOf(delimiter) < 0) { 0063 // We found the simple syntax without wildcards, and only with the command 0064 m_formatLines.append({QStringList{}, std::move(line)}); 0065 } else { 0066 // We found the correct syntax with "wildcards : command" 0067 0068 QStringList wildcards = line.section(delimiter, 0, 0).split(QLatin1Char(' '), Qt::SkipEmptyParts); 0069 QString command = line.section(delimiter, 1).trimmed(); 0070 0071 if (wildcards.isEmpty()) { 0072 qStdOut() << formatFileName << ":" << lineNumber 0073 << ": error: empty wildcard, skip the line\n"; 0074 continue; 0075 } 0076 m_formatLines.append({std::move(wildcards), std::move(command)}); 0077 } 0078 } 0079 0080 if (m_formatLines.isEmpty()) { 0081 qStdOut() << formatFileName << ": error: no commands are found\n"; 0082 return false; 0083 } 0084 0085 return true; 0086 } 0087 0088 bool KDevFormatFile::apply() 0089 { 0090 for (const KDevFormatLine& formatLine : qAsConst(m_formatLines)) { 0091 if (formatLine.wildcards.isEmpty()) { 0092 qStdOut() << "matched \"" << m_origFilePath << "\" without wildcard"; 0093 return executeCommand(formatLine.command); 0094 } 0095 0096 const QChar dirSeparator = QDir::separator(); 0097 for (const QString& wildcard : formatLine.wildcards) { 0098 const QString pattern = QDir::current().canonicalPath() + dirSeparator + wildcard.trimmed(); 0099 if (WildcardHelpers::matchSinglePattern(pattern, m_origFilePath)) { 0100 qStdOut() << "matched \"" << m_origFilePath << "\" with wildcard \"" << wildcard << '\"'; 0101 return executeCommand(formatLine.command); 0102 } 0103 } 0104 } 0105 0106 qStdOut() << formatFileName << ": error: no commands applicable to \"" << m_origFilePath << "\"\n"; 0107 return false; 0108 } 0109 0110 bool KDevFormatFile::executeCommand(QString command) 0111 { 0112 if (command.isEmpty()) { 0113 qStdOut() << ", empty command => nothing to do\n"; 0114 return true; 0115 } 0116 qStdOut() << ", using command \"" << command << "\"\n"; 0117 0118 command.replace(QLatin1String("$ORIGFILE"), m_origFilePath); 0119 command.replace(QLatin1String("$TMPFILE"), m_tempFilePath); 0120 0121 #ifdef Q_OS_WIN 0122 const QString interpreter = QStringLiteral("cmd"); 0123 const QStringList arguments{QStringLiteral("/c"), command}; 0124 #else 0125 const QString interpreter = QStringLiteral("sh"); 0126 const QStringList arguments{QStringLiteral("-c"), command}; 0127 #endif 0128 const int execResult = QProcess::execute(interpreter, arguments); 0129 0130 if (execResult != 0) { 0131 const QString interpreterDescription = QLatin1String("interpreter ") + interpreter; 0132 if (execResult == -2) { 0133 qStdOut() << "error: " << interpreterDescription << " failed to start\n"; 0134 return false; 0135 } 0136 if (execResult == -1) { 0137 qStdOut() << "error: " << interpreterDescription << " crashed\n"; 0138 return false; 0139 } 0140 qStdOut() << "warning: " << interpreterDescription << " exited with code " << execResult << '\n'; 0141 } 0142 0143 return true; 0144 } 0145 0146 }