forked from qt-creator/qt-creator
Utils: Add FilePath::tmpDir and createTempFile
Change-Id: I6f3143e59a87edffeee5e08708ba721293a8a369 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -19,6 +19,8 @@
|
||||
#include <QOperatingSystemVersion>
|
||||
#include <QRegularExpression>
|
||||
#include <QStorageInfo>
|
||||
#include <QTemporaryFile>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#ifdef QTCREATOR_PCH_H
|
||||
@@ -30,6 +32,8 @@
|
||||
#include <qplatformdefs.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
// DeviceFileAccess
|
||||
@@ -397,6 +401,15 @@ void DeviceFileAccess::asyncCopyFile(const FilePath &filePath,
|
||||
cont(copyFile(filePath, target));
|
||||
}
|
||||
|
||||
expected_str<FilePath> DeviceFileAccess::createTempFile(const FilePath &filePath)
|
||||
{
|
||||
Q_UNUSED(filePath)
|
||||
QTC_CHECK(false);
|
||||
return make_unexpected(Tr::tr("createTempFile is not implemented for \"%1\"")
|
||||
.arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
|
||||
// DesktopDeviceFileAccess
|
||||
|
||||
DesktopDeviceFileAccess::~DesktopDeviceFileAccess() = default;
|
||||
@@ -690,6 +703,16 @@ expected_str<qint64> DesktopDeviceFileAccess::writeFileContents(const FilePath &
|
||||
return res;
|
||||
}
|
||||
|
||||
expected_str<FilePath> DesktopDeviceFileAccess::createTempFile(const FilePath &filePath)
|
||||
{
|
||||
QTemporaryFile file(filePath.path());
|
||||
file.setAutoRemove(false);
|
||||
if (!file.open())
|
||||
return make_unexpected(Tr::tr("Could not create temporary file in \"%1\" (%2)").arg(filePath.toUserOutput()).arg(file.errorString()));
|
||||
return FilePath::fromString(file.fileName()).onDevice(filePath);
|
||||
}
|
||||
|
||||
|
||||
QDateTime DesktopDeviceFileAccess::lastModified(const FilePath &filePath) const
|
||||
{
|
||||
return QFileInfo(filePath.path()).lastModified();
|
||||
@@ -965,6 +988,65 @@ expected_str<qint64> UnixDeviceFileAccess::writeFileContents(const FilePath &fil
|
||||
return data.size();
|
||||
}
|
||||
|
||||
expected_str<FilePath> UnixDeviceFileAccess::createTempFile(const FilePath &filePath)
|
||||
{
|
||||
if (!m_hasMkTemp.has_value())
|
||||
m_hasMkTemp = runInShellSuccess({"which", {"mktemp"}, OsType::OsTypeLinux});
|
||||
|
||||
QString tmplate = filePath.path();
|
||||
// Some mktemp implementations require a suffix of XXXXXX.
|
||||
// They will only accept the template if at least the last 6 characters are X.
|
||||
if (!tmplate.endsWith("XXXXXX"))
|
||||
tmplate += ".XXXXXX";
|
||||
|
||||
if (m_hasMkTemp) {
|
||||
const RunResult result = runInShell({"mktemp", {tmplate}, OsType::OsTypeLinux});
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
return make_unexpected(
|
||||
Tr::tr("Failed creating temporary file \"%1\": %2")
|
||||
.arg(filePath.toUserOutput(), QString::fromUtf8(result.stdErr)));
|
||||
}
|
||||
|
||||
return FilePath::fromString(QString::fromUtf8(result.stdOut.trimmed())).onDevice(filePath);
|
||||
}
|
||||
|
||||
// Manually create a temporary/unique file.
|
||||
std::reverse_iterator<QChar *> firstX = std::find_if_not(std::rbegin(tmplate),
|
||||
std::rend(tmplate),
|
||||
[](QChar ch) { return ch == 'X'; });
|
||||
|
||||
static constexpr std::array<QChar, 62> chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
|
||||
'9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
|
||||
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
|
||||
|
||||
std::uniform_int_distribution<> dist(0, chars.size() - 1);
|
||||
|
||||
int maxTries = 10;
|
||||
FilePath newPath;
|
||||
do {
|
||||
for (QChar *it = firstX.base(); it != std::end(tmplate); ++it) {
|
||||
*it = chars[dist(*QRandomGenerator::global())];
|
||||
}
|
||||
newPath = FilePath::fromString(tmplate).onDevice(filePath);
|
||||
if (--maxTries == 0) {
|
||||
return make_unexpected(Tr::tr("Failed creating temporary file \"%1\" (too many tries)")
|
||||
.arg(filePath.toUserOutput()));
|
||||
}
|
||||
} while (newPath.exists());
|
||||
|
||||
const expected_str<qint64> createResult = newPath.writeFileContents({});
|
||||
|
||||
if (!createResult)
|
||||
return make_unexpected(createResult.error());
|
||||
|
||||
return newPath;
|
||||
}
|
||||
|
||||
OsType UnixDeviceFileAccess::osType(const FilePath &filePath) const
|
||||
{
|
||||
Q_UNUSED(filePath)
|
||||
|
||||
Reference in New Issue
Block a user