ClearCase: Replace FilePath::toString

Replace occurrences of FilePath::toString with more sensible alternatives.
Use FilePath capabilities instead of QDir/QFile's where applicable.
Use FilePath instead of QString where it makes sense.

Change-Id: I06f7a324c3f8c4071e48b79a4689884d08ac17db
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Andrii Semkiv
2024-09-11 15:01:44 +02:00
parent 91d0bf1993
commit 3ed8b46554
2 changed files with 126 additions and 133 deletions

View File

@@ -175,14 +175,14 @@ public:
QString ccGetComment(const FilePath &workingDir, const QString &fileName) const; QString ccGetComment(const FilePath &workingDir, const QString &fileName) const;
bool ccFileOp(const FilePath &workingDir, const QString &title, const QStringList &args, bool ccFileOp(const FilePath &workingDir, const QString &title, const QStringList &args,
const QString &fileName, const QString &file2 = {}); const QString &fileName, const QString &file2 = {});
FileStatus vcsStatus(const QString &file) const; FileStatus vcsStatus(const FilePath &file) const;
void checkAndReIndexUnknownFile(const QString &file); void checkAndReIndexUnknownFile(const FilePath &file);
QString currentView() const { return m_viewData.name; } QString currentView() const { return m_viewData.name; }
QString viewRoot() const { return m_viewData.root; } QString viewRoot() const { return m_viewData.root; }
void refreshActivities(); void refreshActivities();
inline bool isUcm() const { return m_viewData.isUcm; } inline bool isUcm() const { return m_viewData.isUcm; }
inline bool isDynamic() const { return m_viewData.isDynamic; } inline bool isDynamic() const { return m_viewData.isDynamic; }
void setStatus(const QString &file, FileStatus::Status status, bool update = true); void setStatus(const FilePath &file, FileStatus::Status status, bool update = true);
bool ccCheckUcm(const QString &viewname, const FilePath &workingDir) const; bool ccCheckUcm(const QString &viewname, const FilePath &workingDir) const;
#ifdef WITH_TESTS #ifdef WITH_TESTS
@@ -230,10 +230,10 @@ private:
void closing(); void closing();
inline bool isCheckInEditorOpen() const; inline bool isCheckInEditorOpen() const;
QStringList getVobList() const; FilePaths getVobList() const;
QString ccManagesDirectory(const FilePath &directory) const; FilePath ccManagesDirectory(const FilePath &directory) const;
QString ccViewRoot(const FilePath &directory) const; FilePath ccViewRoot(const FilePath &directory) const;
QString findTopLevel(const FilePath &directory) const; FilePath findTopLevel(const FilePath &directory) const;
IEditor *showOutputInEditor(const QString& title, const QString &output, Id id, IEditor *showOutputInEditor(const QString& title, const QString &output, Id id,
const FilePath &source, QTextCodec *codec) const; const FilePath &source, QTextCodec *codec) const;
CommandResult runCleartoolProc(const FilePath &workingDir, CommandResult runCleartoolProc(const FilePath &workingDir,
@@ -241,7 +241,7 @@ private:
CommandResult runCleartool(const FilePath &workingDir, const QStringList &arguments, CommandResult runCleartool(const FilePath &workingDir, const QStringList &arguments,
VcsBase::RunFlags flags = VcsBase::RunFlags::None, VcsBase::RunFlags flags = VcsBase::RunFlags::None,
QTextCodec *codec = nullptr, int timeoutMultiplier = 1) const; QTextCodec *codec = nullptr, int timeoutMultiplier = 1) const;
static void sync(QPromise<void> &promise, QStringList files); static void sync(QPromise<void> &promise, FilePaths files);
void history(const FilePath &workingDir, void history(const FilePath &workingDir,
const QStringList &file = {}, const QStringList &file = {},
@@ -258,11 +258,11 @@ private:
QString getFile(const QString &nativeFile, const QString &prefix); QString getFile(const QString &nativeFile, const QString &prefix);
QString runExtDiff(const FilePath &workingDir, const QStringList &arguments, int timeOutS, QString runExtDiff(const FilePath &workingDir, const QStringList &arguments, int timeOutS,
QTextCodec *outputCodec = nullptr); QTextCodec *outputCodec = nullptr);
static QString getDriveLetterOfPath(const QString &directory); static FilePath getDriveLetterOfPath(FilePath directory);
FileStatus::Status getFileStatus(const QString &fileName) const; FileStatus::Status getFileStatus(const FilePath &fileName) const;
void updateStatusForFile(const QString &absFile); void updateStatusForFile(const FilePath &absFile);
void updateEditDerivedObjectWarning(const QString &fileName, const FileStatus::Status status); void updateEditDerivedObjectWarning(const FilePath &fileName, const FileStatus::Status status);
public: public:
ClearCaseSettings m_settings; ClearCaseSettings m_settings;
@@ -356,32 +356,33 @@ bool ClearCasePluginPrivate::isCheckInEditorOpen() const
} }
/// Files in this directories are under ClearCase control /// Files in this directories are under ClearCase control
QStringList ClearCasePluginPrivate::getVobList() const FilePaths ClearCasePluginPrivate::getVobList() const
{ {
const CommandResult result = runCleartoolProc(currentState().topLevel(), {"lsvob", "-s"}); const CommandResult result = runCleartoolProc(currentState().topLevel(), {"lsvob", "-s"});
return result.cleanedStdOut().split(QLatin1Char('\n'), Qt::SkipEmptyParts); return transform(
result.cleanedStdOut().split(QLatin1Char('\n'), Qt::SkipEmptyParts),
FilePath::fromUserInput);
} }
/// Get the drive letter of a path /// Get the drive letter of a path
/// Necessary since QDir(directory).rootPath() returns C:/ in all cases /// Necessary since QDir(directory).rootPath() returns C:/ in all cases
QString ClearCasePluginPrivate::getDriveLetterOfPath(const QString &directory) FilePath ClearCasePluginPrivate::getDriveLetterOfPath(FilePath directory)
{ {
// cdUp until we get just the drive letter // Go up until we get just the drive letter
QDir dir(directory); while (!directory.isRootPath() && directory.parentDir().exists())
while (!dir.isRoot() && dir.cdUp()) directory = directory.parentDir();
;
return dir.path(); return directory;
} }
void ClearCasePluginPrivate::updateStatusForFile(const QString &absFile) void ClearCasePluginPrivate::updateStatusForFile(const FilePath &absFile)
{ {
setStatus(absFile, getFileStatus(absFile), false); setStatus(absFile, getFileStatus(absFile), false);
} }
/// Give warning if a derived object is edited /// Give warning if a derived object is edited
void ClearCasePluginPrivate::updateEditDerivedObjectWarning(const QString &fileName, void ClearCasePluginPrivate::updateEditDerivedObjectWarning(
const FileStatus::Status status) const FilePath &fileName, const FileStatus::Status status)
{ {
if (!isDynamic()) if (!isDynamic())
return; return;
@@ -397,26 +398,26 @@ void ClearCasePluginPrivate::updateEditDerivedObjectWarning(const QString &fileN
if (!infoBar->canInfoBeAdded(derivedObjectWarning)) if (!infoBar->canInfoBeAdded(derivedObjectWarning))
return; return;
infoBar->addInfo(InfoBarEntry(derivedObjectWarning, infoBar->addInfo(InfoBarEntry(
Tr::tr("Editing Derived Object: %1").arg(fileName))); derivedObjectWarning,
Tr::tr("Editing Derived Object: %1").arg(fileName.toUserOutput())));
} else { } else {
infoBar->removeInfo(derivedObjectWarning); infoBar->removeInfo(derivedObjectWarning);
} }
} }
FileStatus::Status ClearCasePluginPrivate::getFileStatus(const QString &fileName) const FileStatus::Status ClearCasePluginPrivate::getFileStatus(const FilePath &fileName) const
{ {
QTC_CHECK(!fileName.isEmpty()); QTC_CHECK(!fileName.isEmpty());
const QDir viewRootDir = QFileInfo(fileName).dir(); const FilePath viewRootDir = fileName.parentDir();
const QString buffer = runCleartoolProc(FilePath::fromString(viewRootDir.path()), const QString buffer
{"ls", fileName}).cleanedStdOut(); = runCleartoolProc(FilePath::fromString(viewRootDir.path()), {"ls", fileName.nativePath()})
.cleanedStdOut();
const int atatpos = buffer.indexOf(QLatin1String("@@")); const int atatpos = buffer.indexOf(QLatin1String("@@"));
if (atatpos != -1) { // probably a managed file if (atatpos != -1) { // probably a managed file
const QString absFile = const FilePath absFile = viewRootDir.pathAppended(buffer.left(atatpos)).absolutePath();
viewRootDir.absoluteFilePath( QTC_CHECK(absFile.exists());
QDir::fromNativeSeparators(buffer.left(atatpos)));
QTC_CHECK(QFileInfo::exists(absFile));
QTC_CHECK(!absFile.isEmpty()); QTC_CHECK(!absFile.isEmpty());
// "cleartool ls" of a derived object looks like this: // "cleartool ls" of a derived object looks like this:
@@ -433,7 +434,7 @@ FileStatus::Status ClearCasePluginPrivate::getFileStatus(const QString &fileName
else else
return FileStatus::CheckedIn; return FileStatus::CheckedIn;
} else { } else {
QTC_CHECK(QFileInfo::exists(fileName)); QTC_CHECK(fileName.exists());
QTC_CHECK(!fileName.isEmpty()); QTC_CHECK(!fileName.isEmpty());
return FileStatus::NotManaged; return FileStatus::NotManaged;
} }
@@ -473,7 +474,7 @@ FileStatus::Status ClearCasePluginPrivate::getFileStatus(const QString &fileName
/// snapshot views. /// snapshot views.
/// ///
/// Returns the ClearCase topLevel/VOB directory for this directory. /// Returns the ClearCase topLevel/VOB directory for this directory.
QString ClearCasePluginPrivate::ccManagesDirectory(const FilePath &directory) const FilePath ClearCasePluginPrivate::ccManagesDirectory(const FilePath &directory) const
{ {
const CommandResult result = runCleartoolProc(directory, {"pwv"}); const CommandResult result = runCleartoolProc(directory, {"pwv"});
if (result.result() != ProcessResult::FinishedWithSuccess) if (result.result() != ProcessResult::FinishedWithSuccess)
@@ -494,21 +495,18 @@ QString ClearCasePluginPrivate::ccManagesDirectory(const FilePath &directory) co
const QString workingDirectoryView = output[0].mid(workingDirPattern.size()); const QString workingDirectoryView = output[0].mid(workingDirPattern.size());
const QString setView = output[1].mid(setViewDirPattern.size()); const QString setView = output[1].mid(setViewDirPattern.size());
const QString none(QLatin1String("** NONE **")); const QString none(QLatin1String("** NONE **"));
QString rootDir; if (setView == none && workingDirectoryView == none)
if (setView != none || workingDirectoryView != none)
rootDir = ccViewRoot(directory);
else
return {}; return {};
const FilePath rootDir = ccViewRoot(directory);
// Check if the directory is inside one of the known VOBs. // Check if the directory is inside one of the known VOBs.
static QStringList vobs; static FilePaths vobs;
if (vobs.empty()) if (vobs.empty())
vobs = getVobList(); vobs = getVobList();
for (const QString &relativeVobDir : std::as_const(vobs)) { for (const FilePath &relativeVobDir : std::as_const(vobs)) {
const QString vobPath = QDir::cleanPath(rootDir + QDir::fromNativeSeparators(relativeVobDir)); const FilePath vobPath = rootDir.resolvePath(relativeVobDir).cleanPath();
const bool isManaged = (vobPath == directory.toString()) const bool isManaged = (vobPath == directory) || directory.isChildOf(vobPath);
|| directory.isChildOf(FilePath::fromString(vobPath));
if (isManaged) if (isManaged)
return vobPath; return vobPath;
} }
@@ -516,30 +514,30 @@ QString ClearCasePluginPrivate::ccManagesDirectory(const FilePath &directory) co
} }
/// Find the root path of a clearcase view. Precondition: This is a clearcase managed dir /// Find the root path of a clearcase view. Precondition: This is a clearcase managed dir
QString ClearCasePluginPrivate::ccViewRoot(const FilePath &directory) const FilePath ClearCasePluginPrivate::ccViewRoot(const FilePath &directory) const
{ {
const CommandResult result = runCleartoolProc(directory, {"pwv", "-root"}); const CommandResult result = runCleartoolProc(directory, {"pwv", "-root"});
QString root = result.cleanedStdOut().trimmed(); auto root = FilePath::fromUserInput(result.cleanedStdOut().trimmed());
if (root.isEmpty()) { if (root.isEmpty()) {
if (HostOsInfo::isWindowsHost()) if (HostOsInfo::isWindowsHost())
root = getDriveLetterOfPath(directory.toString()); root = getDriveLetterOfPath(directory);
else else
root = QLatin1Char('/'); root = FilePath::fromUserInput("/");
} }
return QDir::fromNativeSeparators(root); return root;
} }
/*! Find top level for view that contains \a directory /*! Find top level for view that contains \a directory
* *
* Handles both dynamic views and snapshot views. * Handles both dynamic views and snapshot views.
*/ */
QString ClearCasePluginPrivate::findTopLevel(const FilePath &directory) const FilePath ClearCasePluginPrivate::findTopLevel(const FilePath &directory) const
{ {
// Do not check again if we've already tested that the dir is managed, // Do not check again if we've already tested that the dir is managed,
// or if it is a child of a managed dir (top level). // or if it is a child of a managed dir (top level).
if (directory == m_topLevel || directory.isChildOf(m_topLevel)) if (directory == m_topLevel || directory.isChildOf(m_topLevel))
return m_topLevel.toString(); return m_topLevel;
return ccManagesDirectory(directory); return ccManagesDirectory(directory);
} }
@@ -844,19 +842,20 @@ QStringList ClearCasePluginPrivate::ccGetActiveVobs() const
return res; return res;
} }
void ClearCasePluginPrivate::checkAndReIndexUnknownFile(const QString &file) void ClearCasePluginPrivate::checkAndReIndexUnknownFile(const FilePath &file)
{ {
if (isDynamic()) { if (isDynamic()) {
// reindex unknown files // reindex unknown files
if (m_statusMap->value(file, FileStatus(FileStatus::Unknown)).status == FileStatus::Unknown) if (m_statusMap->value(file.path(), FileStatus(FileStatus::Unknown)).status
== FileStatus::Unknown)
updateStatusForFile(file); updateStatusForFile(file);
} }
} }
// file must be absolute, and using '/' path separator // file must be absolute, and using '/' path separator
FileStatus ClearCasePluginPrivate::vcsStatus(const QString &file) const FileStatus ClearCasePluginPrivate::vcsStatus(const FilePath &file) const
{ {
return m_statusMap->value(file, FileStatus(FileStatus::Unknown)); return m_statusMap->value(file.path(), FileStatus(FileStatus::Unknown));
} }
QString ClearCasePluginPrivate::ccGetFileActivity(const FilePath &workingDir, const QString &file) QString ClearCasePluginPrivate::ccGetFileActivity(const FilePath &workingDir, const QString &file)
@@ -903,7 +902,7 @@ void ClearCasePluginPrivate::updateStatusActions()
FileStatus fileStatus = FileStatus::Unknown; FileStatus fileStatus = FileStatus::Unknown;
bool hasFile = currentState().hasFile(); bool hasFile = currentState().hasFile();
if (hasFile) { if (hasFile) {
const QString absoluteFileName = currentState().currentFile().toString(); const FilePath absoluteFileName = currentState().currentFile();
checkAndReIndexUnknownFile(absoluteFileName); checkAndReIndexUnknownFile(absoluteFileName);
fileStatus = vcsStatus(absoluteFileName); fileStatus = vcsStatus(absoluteFileName);
@@ -998,12 +997,12 @@ void ClearCasePluginPrivate::addCurrentFile()
} }
// Set the FileStatus of file given in absolute path // Set the FileStatus of file given in absolute path
void ClearCasePluginPrivate::setStatus(const QString &file, FileStatus::Status status, bool update) void ClearCasePluginPrivate::setStatus(const FilePath &file, FileStatus::Status status, bool update)
{ {
QTC_CHECK(!file.isEmpty()); QTC_CHECK(!file.isEmpty());
m_statusMap->insert(file, FileStatus(status, QFileInfo(file).permissions())); m_statusMap->insert(file.path(), FileStatus(status, file.permissions()));
if (update && currentState().currentFile().toString() == file) if (update && currentState().currentFile() == file)
QMetaObject::invokeMethod(this, &ClearCasePluginPrivate::updateStatusActions); QMetaObject::invokeMethod(this, &ClearCasePluginPrivate::updateStatusActions);
} }
@@ -1096,10 +1095,10 @@ bool ClearCasePluginPrivate::vcsUndoCheckOut(const FilePath &workingDir, const Q
if (result.result() != ProcessResult::FinishedWithSuccess) if (result.result() != ProcessResult::FinishedWithSuccess)
return false; return false;
const QString absPath = workingDir.pathAppended(fileName).toString(); const FilePath absPath = workingDir.pathAppended(fileName);
if (!m_settings.disableIndexer) if (!m_settings.disableIndexer)
setStatus(absPath, FileStatus::CheckedIn); setStatus(absPath, FileStatus::CheckedIn);
emit filesChanged(QStringList(absPath)); emit filesChanged(QStringList(absPath.path()));
return true; return true;
} }
@@ -1129,7 +1128,7 @@ bool ClearCasePluginPrivate::vcsUndoHijack(const FilePath &workingDir, const QSt
if (m_settings.disableIndexer) if (m_settings.disableIndexer)
return true; return true;
const QString absPath = workingDir.pathAppended(fileName).toString(); const FilePath absPath = workingDir.pathAppended(fileName);
setStatus(absPath, FileStatus::CheckedIn); setStatus(absPath, FileStatus::CheckedIn);
return true; return true;
} }
@@ -1161,7 +1160,7 @@ void ClearCasePluginPrivate::undoHijackCurrent()
// revert // revert
if (vcsUndoHijack(state.currentFileTopLevel(), fileName, keep)) if (vcsUndoHijack(state.currentFileTopLevel(), fileName, keep))
emit filesChanged(QStringList(state.currentFile().toString())); emit filesChanged(QStringList(state.currentFile().path()));
} }
QString ClearCasePluginPrivate::ccGetFileVersion(const FilePath &workingDir, const QString &file) const QString ClearCasePluginPrivate::ccGetFileVersion(const FilePath &workingDir, const QString &file) const
@@ -1179,7 +1178,7 @@ void ClearCasePluginPrivate::ccDiffWithPred(const FilePath &workingDir, const QS
if ((m_settings.diffType == GraphicalDiff) && (files.count() == 1)) { if ((m_settings.diffType == GraphicalDiff) && (files.count() == 1)) {
const QString file = files.first(); const QString file = files.first();
const QString absFilePath = workingDir.pathAppended(file).toString(); const FilePath absFilePath = workingDir.pathAppended(file);
if (vcsStatus(absFilePath).status == FileStatus::Hijacked) if (vcsStatus(absFilePath).status == FileStatus::Hijacked)
diffGraphical(ccGetFileVersion(workingDir, file), file); diffGraphical(ccGetFileVersion(workingDir, file), file);
else else
@@ -1192,8 +1191,8 @@ void ClearCasePluginPrivate::ccDiffWithPred(const FilePath &workingDir, const QS
} }
QString result; QString result;
for (const QString &file : files) { for (const QString &file : files) {
const QString absFilePath = workingDir.pathAppended(file).toString(); const FilePath absFilePath = workingDir.pathAppended(file);
if (vcsStatus(QDir::fromNativeSeparators(absFilePath)).status == FileStatus::Hijacked) if (vcsStatus(absFilePath).status == FileStatus::Hijacked)
result += diffExternal(ccGetFileVersion(workingDir, file), file); result += diffExternal(ccGetFileVersion(workingDir, file), file);
else else
result += diffExternal(file); result += diffExternal(file);
@@ -1257,7 +1256,7 @@ void ClearCasePluginPrivate::diffActivity()
QString result; QString result;
// map from fileName to (first, latest) pair // map from fileName to (first, latest) pair
QMap<QString, QStringPair> filever; QMap<QString, QStringPair> filever;
int topLevelLen = topLevel.toString().length(); int topLevelLen = topLevel.path().length();
for (const QString &version : versions) { for (const QString &version : versions) {
QString shortver = version.mid(topLevelLen + 1); QString shortver = version.mid(topLevelLen + 1);
int atatpos = shortver.indexOf(QLatin1String("@@")); int atatpos = shortver.indexOf(QLatin1String("@@"));
@@ -1352,7 +1351,7 @@ void ClearCasePluginPrivate::startCheckInActivity()
return; return;
FilePath topLevel = state.topLevel(); FilePath topLevel = state.topLevel();
int topLevelLen = topLevel.toString().length(); int topLevelLen = topLevel.path().length();
const QStringList versions = ccGetActivityVersions(topLevel, actSelector->activity()); const QStringList versions = ccGetActivityVersions(topLevel, actSelector->activity());
QStringList files; QStringList files;
QString last; QString last;
@@ -1577,9 +1576,8 @@ void ClearCasePluginPrivate::vcsDescribe(const FilePath &source, const QString &
if (Constants::debug) if (Constants::debug)
qDebug() << Q_FUNC_INFO << source << topLevel << changeNr; qDebug() << Q_FUNC_INFO << source << topLevel << changeNr;
QString description; QString description;
const QString relPath = QDir::toNativeSeparators(QDir(topLevel.toString()) const FilePath relPath = source.relativePathFrom(topLevel);
.relativeFilePath(source.toString())); const QString id = QString::fromLatin1("%1@@%2").arg(relPath.toUserOutput(), changeNr);
const QString id = QString::fromLatin1("%1@@%2").arg(relPath, changeNr);
QTextCodec *codec = VcsBaseEditor::getCodec(source); QTextCodec *codec = VcsBaseEditor::getCodec(source);
const CommandResult result = runCleartool(topLevel, {"describe", id}, RunFlags::None, codec); const CommandResult result = runCleartool(topLevel, {"describe", id}, RunFlags::None, codec);
@@ -1681,21 +1679,20 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
if (Constants::debug) if (Constants::debug)
qDebug() << Q_FUNC_INFO << workingDir << fileName; qDebug() << Q_FUNC_INFO << workingDir << fileName;
const QFileInfo fi(workingDir.toString(), fileName);
const FilePath topLevel = currentState().topLevel(); const FilePath topLevel = currentState().topLevel();
const QString absPath = fi.absoluteFilePath(); const FilePath absPath = workingDir.pathAppended(fileName).absolutePath();
if (!m_settings.disableIndexer && if (!m_settings.disableIndexer
(fi.isWritable() || vcsStatus(absPath).status == FileStatus::Unknown)) && (absPath.isWritableFile() || vcsStatus(absPath).status == FileStatus::Unknown))
Utils::asyncRun(sync, QStringList(absPath)).waitForFinished(); Utils::asyncRun(sync, FilePaths{absPath}).waitForFinished();
if (vcsStatus(absPath).status == FileStatus::CheckedOut) { if (vcsStatus(absPath).status == FileStatus::CheckedOut) {
QMessageBox::information(ICore::dialogParent(), Tr::tr("ClearCase Checkout"), QMessageBox::information(ICore::dialogParent(), Tr::tr("ClearCase Checkout"),
Tr::tr("File is already checked out.")); Tr::tr("File is already checked out."));
return true; return true;
} }
const QString relFile = QDir(topLevel.toString()).relativeFilePath(absPath); const FilePath relFile = absPath.relativePathFrom(topLevel);
const QString file = QDir::toNativeSeparators(relFile); const QString file = relFile.nativePath();
const QString title = QString::fromLatin1("Checkout %1").arg(file); const QString title = QString::fromLatin1("Checkout %1").arg(file);
CheckOutDialog coDialog(title, m_viewData.isUcm, !m_settings.noComment); CheckOutDialog coDialog(title, m_viewData.isUcm, !m_settings.noComment);
@@ -1709,7 +1706,7 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
if (m_viewData.isUcm && !vcsSetActivity(topLevel, title, coDialog.activity())) if (m_viewData.isUcm && !vcsSetActivity(topLevel, title, coDialog.activity()))
return false; return false;
FileChangeBlocker fcb(FilePath::fromString(absPath)); FileChangeBlocker fcb(absPath);
QStringList args(QLatin1String("checkout")); QStringList args(QLatin1String("checkout"));
const QString comment = coDialog.comment(); const QString comment = coDialog.comment();
@@ -1721,6 +1718,7 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
args << QLatin1String("-query"); args << QLatin1String("-query");
const bool reserved = coDialog.isReserved(); const bool reserved = coDialog.isReserved();
const bool unreserved = !reserved || coDialog.isUnreserved(); const bool unreserved = !reserved || coDialog.isUnreserved();
const FilePath hijackedPath = absPath.stringAppended(QLatin1String(".hijack"));
if (reserved) if (reserved)
args << QLatin1String("-reserved"); args << QLatin1String("-reserved");
if (unreserved) if (unreserved)
@@ -1739,8 +1737,8 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
// -usehijack not supported in old cleartool versions... // -usehijack not supported in old cleartool versions...
// args << QLatin1String("-usehijack"); // args << QLatin1String("-usehijack");
if (coDialog.isUseHijacked()) if (coDialog.isUseHijacked())
QFile::rename(absPath, absPath + QLatin1String(".hijack")); absPath.renameFile(hijackedPath);
vcsUndoHijack(topLevel, relFile, false); // don't keep, we've already kept a copy vcsUndoHijack(topLevel, relFile.path(), false); // don't keep, we've already kept a copy
} }
args << file; args << file;
CommandResult result = runCleartool(topLevel, args, CommandResult result = runCleartool(topLevel, args,
@@ -1763,8 +1761,8 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
const bool success = result.result() == ProcessResult::FinishedWithSuccess; const bool success = result.result() == ProcessResult::FinishedWithSuccess;
if (success && isHijacked && coDialog.isUseHijacked()) { // rename back if (success && isHijacked && coDialog.isUseHijacked()) { // rename back
QFile::remove(absPath); absPath.removeFile();
QFile::rename(absPath + QLatin1String(".hijack"), absPath); hijackedPath.renameFile(absPath);
} }
if ((success || result.cleanedStdErr().contains(QLatin1String("already checked out"))) if ((success || result.cleanedStdErr().contains(QLatin1String("already checked out")))
@@ -1772,7 +1770,7 @@ bool ClearCasePluginPrivate::vcsOpen(const FilePath &workingDir, const QString &
setStatus(absPath, FileStatus::CheckedOut); setStatus(absPath, FileStatus::CheckedOut);
} }
if (DocumentModel::Entry *e = DocumentModel::entryForFilePath(FilePath::fromString(absPath))) if (DocumentModel::Entry *e = DocumentModel::entryForFilePath(absPath))
e->document->checkPermissions(); e->document->checkPermissions();
return success; return success;
@@ -1805,18 +1803,16 @@ bool ClearCasePluginPrivate::vcsCheckIn(const FilePath &messageFile, const QStri
replaceActivity &= (activity != QLatin1String(Constants::KEEP_ACTIVITY)); replaceActivity &= (activity != QLatin1String(Constants::KEEP_ACTIVITY));
if (replaceActivity && !vcsSetActivity(m_checkInView, title, activity)) if (replaceActivity && !vcsSetActivity(m_checkInView, title, activity))
return false; return false;
QString message; expected_str<QByteArray> messageFileContents = messageFile.fileContents();
QFile msgFile(messageFile.toString()); const QString message = messageFileContents
if (msgFile.open(QFile::ReadOnly | QFile::Text)) { ? QString::fromLocal8Bit(*std::move(messageFileContents))
message = QString::fromLocal8Bit(msgFile.readAll().trimmed()); : QString{};
msgFile.close();
}
QStringList args; QStringList args;
args << QLatin1String("checkin"); args << QLatin1String("checkin");
if (message.isEmpty()) if (message.isEmpty())
args << QLatin1String("-nc"); args << QLatin1String("-nc");
else else
args << QLatin1String("-cfile") << messageFile.toString(); args << QLatin1String("-cfile") << messageFile.nativePath();
if (isIdentical) if (isIdentical)
args << QLatin1String("-identical"); args << QLatin1String("-identical");
if (isPreserve) if (isPreserve)
@@ -1824,8 +1820,7 @@ bool ClearCasePluginPrivate::vcsCheckIn(const FilePath &messageFile, const QStri
args << files; args << files;
QList<FCBPointer> blockers; QList<FCBPointer> blockers;
for (const QString &fileName : files) { for (const QString &fileName : files) {
FCBPointer fcb(new FileChangeBlocker( FCBPointer fcb(new FileChangeBlocker(m_checkInView.pathAppended(fileName).canonicalPath()));
FilePath::fromString(QFileInfo(m_checkInView.toString(), fileName).canonicalFilePath())));
blockers.append(fcb); blockers.append(fcb);
} }
const CommandResult result = runCleartool(m_checkInView, args, RunFlags::ShowStdOut, nullptr, const CommandResult result = runCleartool(m_checkInView, args, RunFlags::ShowStdOut, nullptr,
@@ -1836,11 +1831,10 @@ bool ClearCasePluginPrivate::vcsCheckIn(const FilePath &messageFile, const QStri
int offset = match.capturedStart(); int offset = match.capturedStart();
while (match.hasMatch()) { while (match.hasMatch()) {
const QString file = match.captured(1); const QString file = match.captured(1);
const QFileInfo fi(m_checkInView.toString(), file); const FilePath absPath = m_checkInView.pathAppended(file).absolutePath();
const QString absPath = fi.absoluteFilePath();
if (!m_settings.disableIndexer) if (!m_settings.disableIndexer)
setStatus(QDir::fromNativeSeparators(absPath), FileStatus::CheckedIn); setStatus(absPath, FileStatus::CheckedIn);
emit filesChanged(files); emit filesChanged(files);
anySucceeded = true; anySucceeded = true;
match = checkedIn.match(result.cleanedStdOut(), offset + 12); match = checkedIn.match(result.cleanedStdOut(), offset + 12);
@@ -1886,8 +1880,7 @@ bool ClearCasePluginPrivate::ccFileOp(const FilePath &workingDir, const QString
if (m_viewData.isUcm && actSelector->changed()) if (m_viewData.isUcm && actSelector->changed())
vcsSetActivity(workingDir, fileOpDlg.windowTitle(), actSelector->activity()); vcsSetActivity(workingDir, fileOpDlg.windowTitle(), actSelector->activity());
const QString dirName = QDir::toNativeSeparators(QFileInfo(workingDir.toString(), const QString dirName = workingDir.resolvePath(fileName).absolutePath().nativePath();
fileName).absolutePath());
QStringList commentArg; QStringList commentArg;
if (comment.isEmpty()) if (comment.isEmpty())
commentArg << QLatin1String("-nc"); commentArg << QLatin1String("-nc");
@@ -1963,13 +1956,13 @@ bool ClearCasePluginPrivate::managesDirectory(const FilePath &directory, FilePat
{ {
#ifdef WITH_TESTS #ifdef WITH_TESTS
// If running with tests and fake ClearTool is enabled, then pretend we manage every directory // If running with tests and fake ClearTool is enabled, then pretend we manage every directory
const QString topLevelFound = m_fakeClearTool ? directory.toString() : findTopLevel(directory); const FilePath topLevelFound = m_fakeClearTool ? directory : findTopLevel(directory);
#else #else
const QString topLevelFound = findTopLevel(directory); const FilePath topLevelFound = findTopLevel(directory);
#endif #endif
if (topLevel) if (topLevel)
*topLevel = FilePath::fromString(topLevelFound); *topLevel = topLevelFound;
return !topLevelFound.isEmpty(); return !topLevelFound.isEmpty();
} }
@@ -2075,7 +2068,7 @@ bool ClearCasePluginPrivate::ccCheckUcm(const QString &viewname, const FilePath
bool ClearCasePluginPrivate::managesFile(const FilePath &workingDirectory, const QString &fileName) const bool ClearCasePluginPrivate::managesFile(const FilePath &workingDirectory, const QString &fileName) const
{ {
const QString absFile = QFileInfo(QDir(workingDirectory.toString()), fileName).absoluteFilePath(); const FilePath absFile = workingDirectory.pathAppended(fileName).absoluteFilePath();
const FileStatus::Status status = getFileStatus(absFile); const FileStatus::Status status = getFileStatus(absFile);
return status != FileStatus::NotManaged && status != FileStatus::Derived; return status != FileStatus::NotManaged && status != FileStatus::Derived;
} }
@@ -2091,7 +2084,7 @@ ViewData ClearCasePluginPrivate::ccGetView(const FilePath &workingDir) const
res.isDynamic = !data.isEmpty() && (data.at(0) == QLatin1Char('*')); res.isDynamic = !data.isEmpty() && (data.at(0) == QLatin1Char('*'));
res.name = data.mid(2, data.indexOf(QLatin1Char(' '), 2) - 2); res.name = data.mid(2, data.indexOf(QLatin1Char(' '), 2) - 2);
res.isUcm = ccCheckUcm(res.name, workingDir); res.isUcm = ccCheckUcm(res.name, workingDir);
res.root = ccViewRoot(workingDir); res.root = ccViewRoot(workingDir).toUserOutput();
} }
return res; return res;
@@ -2126,9 +2119,8 @@ void ClearCasePluginPrivate::projectChanged(Project *project)
ProgressManager::cancelTasks(ClearCase::Constants::TASK_INDEX); ProgressManager::cancelTasks(ClearCase::Constants::TASK_INDEX);
if (project) { if (project) {
const FilePath projDir = project->projectDirectory(); const FilePath projDir = project->projectDirectory();
const QString topLevel = findTopLevel(projDir); m_topLevel = findTopLevel(projDir);
m_topLevel = FilePath::fromString(topLevel); if (m_topLevel.isEmpty())
if (topLevel.isEmpty())
return; return;
connect(qApp, &QApplication::applicationStateChanged, connect(qApp, &QApplication::applicationStateChanged,
this, [this](Qt::ApplicationState state) { this, [this](Qt::ApplicationState state) {
@@ -2159,8 +2151,7 @@ void ClearCasePluginPrivate::updateIndex()
return; return;
m_checkInAllAction->setEnabled(false); m_checkInAllAction->setEnabled(false);
m_statusMap->clear(); m_statusMap->clear();
QFuture<void> result = Utils::asyncRun(sync, transform(project->files(Project::SourceFiles), QFuture<void> result = Utils::asyncRun(sync, project->files(Project::SourceFiles));
&FilePath::toString));
if (!m_settings.disableIndexer) if (!m_settings.disableIndexer)
ProgressManager::addTask(result, Tr::tr("Updating ClearCase Index"), ClearCase::Constants::TASK_INDEX); ProgressManager::addTask(result, Tr::tr("Updating ClearCase Index"), ClearCase::Constants::TASK_INDEX);
} }
@@ -2189,7 +2180,7 @@ QString ClearCasePluginPrivate::getFile(const QString &nativeFile, const QString
if (Constants::debug) if (Constants::debug)
qDebug() << Q_FUNC_INFO << nativeFile; qDebug() << Q_FUNC_INFO << nativeFile;
if ((atatpos != -1) && (nativeFile.indexOf(QLatin1String("CHECKEDOUT"), atatpos) != -1)) { if ((atatpos != -1) && (nativeFile.indexOf(QLatin1String("CHECKEDOUT"), atatpos) != -1)) {
bool res = QFile::copy(QDir(m_topLevel.toString()).absoluteFilePath(file), tempFile); bool res = QFile::copy(QDir(m_topLevel.toFSPathString()).absoluteFilePath(file), tempFile);
return res ? tempFile : QString(); return res ? tempFile : QString();
} }
const CommandResult result = runCleartoolProc(m_topLevel, {"get", "-to", tempFile, nativeFile}); const CommandResult result = runCleartoolProc(m_topLevel, {"get", "-to", tempFile, nativeFile});
@@ -2287,7 +2278,7 @@ void ClearCasePluginPrivate::syncSlot()
FilePath topLevel = state.topLevel(); FilePath topLevel = state.topLevel();
if (topLevel != state.currentProjectTopLevel()) if (topLevel != state.currentProjectTopLevel())
return; return;
Utils::asyncRun(sync, QStringList()); // TODO: make use of returned QFuture Utils::asyncRun(sync, FilePaths{}); // TODO: make use of returned QFuture
} }
void ClearCasePluginPrivate::closing() void ClearCasePluginPrivate::closing()
@@ -2297,12 +2288,17 @@ void ClearCasePluginPrivate::closing()
disconnect(qApp, &QApplication::applicationStateChanged, nullptr, nullptr); disconnect(qApp, &QApplication::applicationStateChanged, nullptr, nullptr);
} }
void ClearCasePluginPrivate::sync(QPromise<void> &promise, QStringList files) void ClearCasePluginPrivate::sync(QPromise<void> &promise, FilePaths files)
{ {
ClearCasePluginPrivate *plugin = ClearCasePluginPrivate::instance(); ClearCasePluginPrivate *plugin = ClearCasePluginPrivate::instance();
ClearCaseSync ccSync(plugin->m_statusMap); ClearCaseSync ccSync(plugin->m_statusMap);
connect(&ccSync, &ClearCaseSync::updateStreamAndView, plugin, &ClearCasePluginPrivate::updateStreamAndView); connect(
ccSync.run(promise, files); &ccSync,
&ClearCaseSync::updateStreamAndView,
plugin,
&ClearCasePluginPrivate::updateStreamAndView);
QStringList transformed = transform(std::move(files), &FilePath::path);
ccSync.run(promise, transformed);
} }
Id ClearCasePluginPrivate::id() const Id ClearCasePluginPrivate::id() const
@@ -2349,7 +2345,7 @@ IVersionControl::OpenSupportMode ClearCasePluginPrivate::openSupportMode(const F
// NB! Has to use managesFile() and not vcsStatus() since the index can only be guaranteed // NB! Has to use managesFile() and not vcsStatus() since the index can only be guaranteed
// to be up to date if the file has been explicitly opened, which is not the case when // to be up to date if the file has been explicitly opened, which is not the case when
// doing a search and replace as a part of a refactoring. // doing a search and replace as a part of a refactoring.
if (managesFile(FilePath::fromString(filePath.toFileInfo().absolutePath()), filePath.toString())) { if (managesFile(FilePath::fromString(filePath.toFileInfo().absolutePath()), filePath.path())) {
// Checkout is the only option for managed files in dynamic views // Checkout is the only option for managed files in dynamic views
return IVersionControl::OpenMandatory; return IVersionControl::OpenMandatory;
} else { } else {
@@ -2446,7 +2442,7 @@ const ViewData viewData()
void setStatus(const QString &file, FileStatus::Status status, bool update) void setStatus(const QString &file, FileStatus::Status status, bool update)
{ {
dd->setStatus(file, status, update); dd->setStatus(FilePath::fromUserInput(file), status, update);
} }
const ClearCaseSettings &settings() const ClearCaseSettings &settings()
@@ -2606,17 +2602,16 @@ namespace {
class TestCase class TestCase
{ {
public: public:
TestCase(const QString &fileName) : TestCase(const FilePath &fileName)
m_fileName(fileName) : m_fileName(fileName)
{ {
ClearCasePluginPrivate::instance()->setFakeCleartool(true); ClearCasePluginPrivate::instance()->setFakeCleartool(true);
VcsManager::clearVersionControlCache(); VcsManager::clearVersionControlCache();
const auto filePath = FilePath::fromString(fileName); FileSaver srcSaver(fileName);
FileSaver srcSaver(filePath);
srcSaver.write(QByteArray()); srcSaver.write(QByteArray());
srcSaver.finalize(); srcSaver.finalize();
m_editor = EditorManager::openEditor(filePath); m_editor = EditorManager::openEditor(fileName);
QCoreApplication::processEvents(); // process any pending events QCoreApplication::processEvents(); // process any pending events
} }
@@ -2635,15 +2630,14 @@ public:
EditorManager::closeDocuments({m_editor->document()}, false); EditorManager::closeDocuments({m_editor->document()}, false);
QCoreApplication::processEvents(); // process any pending events QCoreApplication::processEvents(); // process any pending events
QFile file(m_fileName); if (!m_fileName.isWritableFile())
if (!file.isWritable()) // Windows can't delete read only files m_fileName.setPermissions(m_fileName.permissions() | QFile::WriteUser);
file.setPermissions(file.permissions() | QFile::WriteUser); QVERIFY(m_fileName.removeFile());
QVERIFY(file.remove());
ClearCasePluginPrivate::instance()->setFakeCleartool(false); ClearCasePluginPrivate::instance()->setFakeCleartool(false);
} }
private: private:
QString m_fileName; FilePath m_fileName;
IEditor *m_editor; IEditor *m_editor;
}; };
} }
@@ -2671,7 +2665,7 @@ void ClearCaseTest::testStatusActions_data()
void ClearCaseTest::testStatusActions() void ClearCaseTest::testStatusActions()
{ {
const QString fileName = QDir::currentPath() + QLatin1String("/clearcase_file.cpp"); const auto fileName = FilePath::currentWorkingPath().pathAppended("clearcase_file.cpp");
TestCase testCase(fileName); TestCase testCase(fileName);
dd->m_viewData = testCase.dummyViewData(); dd->m_viewData = testCase.dummyViewData();
@@ -2707,15 +2701,14 @@ void ClearCaseTest::testVcsStatusDynamicReadonlyNotManaged()
ClearCasePluginPrivate::instance(); ClearCasePluginPrivate::instance();
dd->m_statusMap = std::shared_ptr<StatusMap>(new StatusMap); dd->m_statusMap = std::shared_ptr<StatusMap>(new StatusMap);
const QString fileName = QDir::currentPath() + QLatin1String("/readonly_notmanaged_file.cpp"); const auto fileName = FilePath::currentWorkingPath().pathAppended(
"readonly_notmanaged_file.cpp");
dd->m_viewData.isDynamic = true; dd->m_viewData.isDynamic = true;
TestCase testCase(fileName); TestCase testCase(fileName);
QFile::setPermissions(fileName, QFile::ReadOwner | fileName.setPermissions(
QFile::ReadUser | QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther);
QFile::ReadGroup |
QFile::ReadOther);
dd->m_viewData = testCase.dummyViewData(); dd->m_viewData = testCase.dummyViewData();
dd->m_viewData.isDynamic = true; dd->m_viewData.isDynamic = true;
@@ -2729,7 +2722,7 @@ void ClearCaseTest::testVcsStatusDynamicNotManaged()
ClearCasePluginPrivate::instance(); ClearCasePluginPrivate::instance();
dd->m_statusMap = std::shared_ptr<StatusMap>(new StatusMap); dd->m_statusMap = std::shared_ptr<StatusMap>(new StatusMap);
const QString fileName = QDir::currentPath() + QLatin1String("/notmanaged_file.cpp"); const auto fileName = FilePath::currentWorkingPath().pathAppended("notmanaged_file.cpp");
dd->m_viewData.isDynamic = true; dd->m_viewData.isDynamic = true;
TestCase testCase(fileName); TestCase testCase(fileName);

View File

@@ -177,7 +177,7 @@ SettingsPageWidget::SettingsPageWidget()
void SettingsPageWidget::apply() void SettingsPageWidget::apply()
{ {
ClearCaseSettings rc; ClearCaseSettings rc;
rc.ccCommand = commandPathChooser->unexpandedFilePath().toString(); rc.ccCommand = commandPathChooser->unexpandedFilePath().toUserOutput();
rc.ccBinaryPath = commandPathChooser->filePath(); rc.ccBinaryPath = commandPathChooser->filePath();
rc.timeOutS = timeOutSpinBox->value(); rc.timeOutS = timeOutSpinBox->value();
rc.autoCheckOut = autoCheckOutCheckBox->isChecked(); rc.autoCheckOut = autoCheckOutCheckBox->isChecked();