swift
swiftdirectories.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2020 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
7 
8 #include <QCoreApplication>
9 #include <QDir>
10 #include <QRegularExpression>
11 #include <QSet>
12 #include <QStandardPaths>
13 #include <QUrl>
14 
15 #include "config/buildconfig.h"
16 #include "misc/directoryutils.h"
17 #include "misc/fileutils.h"
18 #include "misc/range.h"
19 #include "misc/stringutils.h"
20 
21 using namespace swift::config;
22 
23 namespace swift::misc
24 {
25  QString binDirectoryImpl()
26  {
27  QString appDirectoryString(qApp->applicationDirPath());
28  if (appDirectoryString.endsWith("Contents/MacOS")) { appDirectoryString += "/../../.."; }
29  QDir appDirectory(appDirectoryString);
30  return appDirectory.absolutePath();
31  }
32 
33  const QString &CSwiftDirectories::binDirectory()
34  {
35  static const QString binDir(binDirectoryImpl());
36  return binDir;
37  }
38 
39  const QString &CSwiftDirectories::pluginsDirectory()
40  {
41  static const QString pDir(CFileUtils::appendFilePaths(binDirectory(), "plugins"));
42  return pDir;
43  }
44 
45  const QString &CSwiftDirectories::audioPluginDirectory()
46  {
47  static const QString pDir(CFileUtils::appendFilePaths(binDirectory(), "audio"));
48  return pDir;
49  }
50 
51  const QString &CSwiftDirectories::getXSwiftBusBuildDirectory()
52  {
54  {
55  static const QString e;
56  return e;
57  }
58 
59  // the xswiftbus directory in out, not in dist
60  static const QString bd = [] {
61  QDir dir(binDirectory());
62  if (!dir.cdUp()) { return QString(); }
63  if (!dir.cd("xswiftbus")) { return QString(); }
64  return dir.absolutePath();
65  }();
66  return bd;
67  }
68 
69  QString CSwiftDirectories::executableFilePath(const QString &executable)
70  {
71  Q_ASSERT_X(!executable.isEmpty(), Q_FUNC_INFO, "Missing executable file path");
72 
73  QString s = CFileUtils::appendFilePaths(binDirectory(), executable);
75  {
76  // MacOS bundle may or may not be a bundle
77  const QDir dir(s + QLatin1String(".app/Contents/MacOS"));
78  if (dir.exists()) { s += QLatin1String(".app/Contents/MacOS/") + executable; }
79  }
80  else if (CBuildConfig::isRunningOnWindowsNtPlatform()) { s += QLatin1String(".exe"); }
81  return s;
82  }
83 
84  QString normalizedApplicationDirectoryImpl()
85  {
86  QString appDir = CSwiftDirectories::binDirectory();
87  Q_ASSERT(appDir.size() > 0);
88  // Remove leading '/' on Unix
89  if (appDir.at(0) == '/') { appDir.remove(0, 1); }
90  return QUrl::toPercentEncoding(appDir);
91  }
92 
93  const QString &CSwiftDirectories::normalizedApplicationDirectory()
94  {
95  static const QString appDir(normalizedApplicationDirectoryImpl());
96  return appDir;
97  }
98 
99  const QString &CSwiftDirectories::applicationDataDirectory()
100  {
101  static const QString p = CFileUtils::appendFilePaths(
102  QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "/org.swift-project/");
103  return p;
104  }
105 
106  const QFileInfoList &CSwiftDirectories::applicationDataDirectories()
107  {
108  static QFileInfoList fileInfoList = currentApplicationDataDirectories();
109  return fileInfoList;
110  }
111 
112  QFileInfoList CSwiftDirectories::currentApplicationDataDirectories()
113  {
114  const QDir swiftAppData(applicationDataDirectory()); // contains 1..n subdirs
115  if (!swiftAppData.isReadable()) { return QFileInfoList(); }
116  return swiftAppData.entryInfoList({}, QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time);
117  }
118 
119  int CSwiftDirectories::applicationDataDirectoriesCount() { return applicationDataDirectories().size(); }
120 
121  QStringList CSwiftDirectories::applicationDataDirectoryList(bool withoutCurrent, bool decodedDirName)
122  {
123  QStringList dirs;
124  for (const QFileInfo &info : applicationDataDirectories())
125  {
126  if (withoutCurrent && info.filePath().contains(normalizedApplicationDirectory(), Qt::CaseInsensitive))
127  continue;
128  dirs.append(decodedDirName ? CDirectoryUtils::decodeNormalizedDirectory(info.filePath()) : info.filePath());
129  }
130  return dirs;
131  }
132 
133  const QString &CSwiftDirectories::normalizedApplicationDataDirectory()
134  {
135  static const QString p =
136  CFileUtils::appendFilePaths(applicationDataDirectory(), normalizedApplicationDirectory());
137  return p;
138  }
139 
140  const QString &CSwiftDirectories::logDirectory()
141  {
142  static const QString p = CFileUtils::appendFilePaths(normalizedApplicationDataDirectory(), "/logs");
143  return p;
144  }
145 
146  QString getSwiftShareDirImpl()
147  {
148  QDir dir(CSwiftDirectories::binDirectory());
149  const bool success = dir.cd("../share");
150  if (success)
151  {
152  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
153  return dir.absolutePath();
154  }
155  Q_ASSERT_X(false, Q_FUNC_INFO, "missing dir");
156  return {};
157  }
158 
159  const QString &CSwiftDirectories::shareDirectory()
160  {
161  static const QString s(getSwiftShareDirImpl());
162  return s;
163  }
164 
165  const QString &CSwiftDirectories::shareTestDirectory()
166  {
167  static const QString test(CFileUtils::appendFilePaths(shareDirectory(), "test"));
168  return test;
169  }
170 
171  const QString &CSwiftDirectories::shareTerrainProbeDirectory()
172  {
173  static const QString tpd(CFileUtils::appendFilePaths(shareDirectory(), "simulator/swiftTerrainProbe"));
174  return tpd;
175  }
176 
177  const QString &CSwiftDirectories::shareMatchingScriptDirectory()
178  {
179  static const QString ms(CFileUtils::appendFilePaths(shareDirectory(), "matchingscript"));
180  return ms;
181  }
182 
183  const QString &CSwiftDirectories::bootstrapFileName()
184  {
185  static const QString n("bootstrap.json");
186  return n;
187  }
188 
189  QString getBootstrapResourceFileImpl()
190  {
191  const QString d(CSwiftDirectories::shareDirectory());
192  if (d.isEmpty()) { return {}; }
193  const QFile file(
194  QDir::cleanPath(d + QDir::separator() + "shared/bootstrap/" + CSwiftDirectories::bootstrapFileName()));
195  Q_ASSERT_X(file.exists(), Q_FUNC_INFO, "missing bootstrap file");
196  return QFileInfo(file).absoluteFilePath();
197  }
198 
199  const QString &CSwiftDirectories::bootstrapResourceFilePath()
200  {
201  static const QString s(getBootstrapResourceFileImpl());
202  return s;
203  }
204 
205  QString getSwiftStaticDbFilesDirImpl()
206  {
207  const QString d(CSwiftDirectories::shareDirectory());
208  if (d.isEmpty()) { return {}; }
209  const QDir dir(QDir::cleanPath(d + QDir::separator() + "shared/dbdata"));
210  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
211  return dir.absolutePath();
212  }
213 
214  const QString &CSwiftDirectories::staticDbFilesDirectory()
215  {
216  static const QString s(getSwiftStaticDbFilesDirImpl());
217  return s;
218  }
219 
220  QString getSoundFilesDirImpl()
221  {
222  const QString d(CSwiftDirectories::shareDirectory());
223  if (d.isEmpty()) { return {}; }
224  const QDir dir(QDir::cleanPath(d + QDir::separator() + "sounds"));
225  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
226  return dir.absolutePath();
227  }
228 
229  const QString &CSwiftDirectories::soundFilesDirectory()
230  {
231  static const QString s(getSoundFilesDirImpl());
232  return s;
233  }
234 
235  QString getStylesheetsDirImpl()
236  {
237  const QString d(CSwiftDirectories::shareDirectory());
238  if (d.isEmpty()) { return {}; }
239  const QDir dir(QDir::cleanPath(d + QDir::separator() + "qss"));
240  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
241  return dir.absolutePath();
242  }
243 
244  const QString &CSwiftDirectories::stylesheetsDirectory()
245  {
246  static const QString s(getStylesheetsDirImpl());
247  return s;
248  }
249 
250  QString getHtmlDirImpl()
251  {
252  const QString d(CSwiftDirectories::shareDirectory());
253  const QDir dir(QDir::cleanPath(d + QDir::separator() + "html"));
254  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
255  return dir.absolutePath();
256  }
257 
258  const QString &CSwiftDirectories::htmlDirectory()
259  {
260  static const QString s(getHtmlDirImpl());
261  return s;
262  }
263 
264  QString getLegalDirImpl()
265  {
266  const QString d(CSwiftDirectories::shareDirectory());
267  const QDir dir(QDir::cleanPath(d + QDir::separator() + "legal"));
268  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
269  return dir.absolutePath();
270  }
271 
272  const QString &CSwiftDirectories::legalDirectory()
273  {
274  static const QString s(getLegalDirImpl());
275  return s;
276  }
277 
278  const QString &CSwiftDirectories::aboutFilePath()
279  {
280  static const QString about = QDir::cleanPath(legalDirectory() + QDir::separator() + "about.html");
281  return about;
282  }
283 
284  QString testFilesDirImpl()
285  {
286  const QString d(CSwiftDirectories::shareDirectory());
287  if (d.isEmpty()) { return {}; }
288  const QDir dir(QDir::cleanPath(d + QDir::separator() + "test"));
289  Q_ASSERT_X(dir.exists(), Q_FUNC_INFO, "missing dir");
290  return dir.absolutePath();
291  }
292 
293  const QString &CSwiftDirectories::testFilesDirectory()
294  {
295  static QString s(testFilesDirImpl());
296  return s;
297  }
298 
299  const QString &CSwiftDirectories::htmlTemplateFilePath()
300  {
301  static const QString s(htmlDirectory() + QDir::separator() + "swifttemplate.html");
302  return s;
303  }
304 
305  QString getDocumentationDirectoryImpl()
306  {
307  const QStringList pathes(QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation));
308  QString d = pathes.first();
309  d = QDir::cleanPath(CFileUtils::appendFilePaths(d, "swift"));
310  QDir dir(d);
311  if (dir.exists()) { return dir.absolutePath(); }
312  return pathes.first();
313  }
314 
315  const QString &CSwiftDirectories::documentationDirectory()
316  {
317  static const QString d(getDocumentationDirectoryImpl());
318  return d;
319  }
320 
321  const QString &CSwiftDirectories::crashpadDirectory()
322  {
323  static const QString p = CFileUtils::appendFilePaths(normalizedApplicationDataDirectory(), "/crashpad");
324  return p;
325  }
326 
327  const QString &CSwiftDirectories::crashpadDatabaseDirectory()
328  {
329  static const QString p = CFileUtils::appendFilePaths(crashpadDirectory(), "/database");
330  return p;
331  }
332 
333  const QString &CSwiftDirectories::crashpadMetricsDirectory()
334  {
335  static const QString p = CFileUtils::appendFilePaths(crashpadDirectory(), "/metrics");
336  return p;
337  }
338 
339  QStringList CSwiftDirectories::verifyRuntimeDirectoriesAndFiles()
340  {
341  QStringList failed;
342  QDir d(binDirectory());
343  if (!d.isReadable()) { failed.append(d.absolutePath()); }
344 
345  d = QDir(stylesheetsDirectory());
346  if (!d.isReadable()) { failed.append(d.absolutePath()); }
347 
348  d = QDir(applicationDataDirectory());
349  if (!d.isReadable()) { failed.append(d.absolutePath()); }
350 
351  // check if the executables are avialable
352  QString fn = executableFilePath(CBuildConfig::swiftCoreExecutableName());
353  if (!QFile::exists(fn)) { failed.append(fn); }
354 
355  fn = executableFilePath(CBuildConfig::swiftDataExecutableName());
356  if (!QFile::exists(fn)) { failed.append(fn); }
357 
358  fn = executableFilePath(CBuildConfig::swiftGuiExecutableName());
359  if (!QFile::exists(fn)) { failed.append(fn); }
360 
361  return failed;
362  }
363 
364  QString CSwiftDirectories::soundFilePathOrDefaultPath(const QString &directory, const QString &fileName)
365  {
366  if (!directory.isEmpty())
367  {
368  const QString fp = CFileUtils::appendFilePathsAndFixUnc(directory, fileName);
369  const QFileInfo fi(fp);
370  if (fi.exists()) { return fi.absoluteFilePath(); }
371  }
372  const QString fp = CFileUtils::appendFilePathsAndFixUnc(CSwiftDirectories::soundFilesDirectory(), fileName);
373  const QFileInfo fi(fp);
374  return (fi.exists()) ? fi.absoluteFilePath() : QString();
375  }
376 
377 } // namespace swift::misc
378 
static constexpr bool isRunningOnMacOSPlatform()
Running on MacOS platform?
static bool isLocalDeveloperDebugBuild()
Local build for developers.
static constexpr bool isRunningOnWindowsNtPlatform()
Running on Windows NT platform?
static const QString & swiftCoreExecutableName()
Executable name for swift core, no(!) appendix.
static const QString & swiftGuiExecutableName()
Executable name for swift GUI, no(!) appendix.
static const QString & swiftDataExecutableName()
Executable name for swift data, no(!) appendix.
Free functions in swift::misc.