make VFS aware of exact vs. cumulative evaluation

the cumulative evaluation has a good chance to make a mess of the
virtual file contents created by the exact parsing, so better contain it
to its own namespace.

the ProFile cache also needs to keep the files separate. this
specifically addresses the side issue discussed in QTCREATORBUG-10779.
it also fixes attempts to deploy the wrong build when the variant is
selected through a cache file, as in QTCREATORBUG-15815.

in the project explorer, we don't track from which evaluation pass
particular files came from, so we try the cumulative first to get the
most contents, and fall back to the exact one if the former file is
empty (or does not exist at all).

Task-number: QTCREATORBUG-15815
Change-Id: I2c1eb16c97526fa275a1c6a2eae9266d385859ac
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Oswald Buddenhagen
2016-10-27 16:36:06 +02:00
parent cf82f21080
commit a8010b0fff
12 changed files with 156 additions and 55 deletions

View File

@@ -581,7 +581,12 @@ struct InternalNode
foreach (const FileName &file, resourcesToAdd) { foreach (const FileName &file, resourcesToAdd) {
auto vfs = static_cast<QmakePriFileNode *>(folder->projectNode())->m_project->qmakeVfs(); auto vfs = static_cast<QmakePriFileNode *>(folder->projectNode())->m_project->qmakeVfs();
QString contents; QString contents;
vfs->readVirtualFile(file.toString(), &contents); // Prefer the cumulative file if it's non-empty, based on the assumption
// that it contains more "stuff".
vfs->readVirtualFile(file.toString(), QMakeVfs::VfsCumulative, &contents);
// If the cumulative evaluation botched the file too much, try the exact one.
if (contents.isEmpty())
vfs->readVirtualFile(file.toString(), QMakeVfs::VfsExact, &contents);
nodesToAdd.append(new ResourceEditor::ResourceTopLevelNode(file, contents, folder)); nodesToAdd.append(new ResourceEditor::ResourceTopLevelNode(file, contents, folder));
} }
@@ -1953,10 +1958,10 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
result->newVarValues[HeaderExtensionVar] = QStringList() << input.readerExact->value(QLatin1String("QMAKE_EXT_H")); result->newVarValues[HeaderExtensionVar] = QStringList() << input.readerExact->value(QLatin1String("QMAKE_EXT_H"));
result->newVarValues[CppExtensionVar] = QStringList() << input.readerExact->value(QLatin1String("QMAKE_EXT_CPP")); result->newVarValues[CppExtensionVar] = QStringList() << input.readerExact->value(QLatin1String("QMAKE_EXT_CPP"));
result->newVarValues[MocDirVar] = QStringList() << mocDirPath(input.readerExact, input.buildDirectory); result->newVarValues[MocDirVar] = QStringList() << mocDirPath(input.readerExact, input.buildDirectory);
result->newVarValues[ResourceVar] = fileListForVar(input.readerExact, input.readerCumulative,
QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory);
result->newVarValues[ExactResourceVar] = fileListForVar(input.readerExact, 0, result->newVarValues[ExactResourceVar] = fileListForVar(input.readerExact, 0,
QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory); QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory);
result->newVarValues[CumulativeResourceVar] = fileListForVar(input.readerCumulative, 0,
QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory);
result->newVarValues[PkgConfigVar] = input.readerExact->values(QLatin1String("PKGCONFIG")); result->newVarValues[PkgConfigVar] = input.readerExact->values(QLatin1String("PKGCONFIG"));
result->newVarValues[PrecompiledHeaderVar] = input.readerExact->fixifiedValues( result->newVarValues[PrecompiledHeaderVar] = input.readerExact->fixifiedValues(
QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory); QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory);

View File

@@ -82,8 +82,8 @@ enum QmakeVariable {
CppSourceVar, CppSourceVar,
ObjCSourceVar, ObjCSourceVar,
ObjCHeaderVar, ObjCHeaderVar,
ResourceVar,
ExactResourceVar, ExactResourceVar,
CumulativeResourceVar,
UiDirVar, UiDirVar,
HeaderExtensionVar, HeaderExtensionVar,
CppExtensionVar, CppExtensionVar,

View File

@@ -564,11 +564,19 @@ void QmakeProject::updateQmlJSCodeModel()
foreach (const QString &path, node->variableValue(QmlImportPathVar)) foreach (const QString &path, node->variableValue(QmlImportPathVar))
projectInfo.importPaths.maybeInsert(FileName::fromString(path), projectInfo.importPaths.maybeInsert(FileName::fromString(path),
QmlJS::Dialect::Qml); QmlJS::Dialect::Qml);
projectInfo.activeResourceFiles.append(node->variableValue(ExactResourceVar)); const QStringList &exactResources = node->variableValue(ExactResourceVar);
projectInfo.allResourceFiles.append(node->variableValue(ResourceVar)); const QStringList &cumulativeResources = node->variableValue(CumulativeResourceVar);
foreach (const QString &rc, projectInfo.allResourceFiles) { projectInfo.activeResourceFiles.append(exactResources);
projectInfo.allResourceFiles.append(exactResources);
projectInfo.allResourceFiles.append(cumulativeResources);
foreach (const QString &rc, exactResources) {
QString contents; QString contents;
if (m_qmakeVfs->readVirtualFile(rc, &contents)) if (m_qmakeVfs->readVirtualFile(rc, QMakeVfs::VfsExact, &contents))
projectInfo.resourceFileContents[rc] = contents;
}
foreach (const QString &rc, cumulativeResources) {
QString contents;
if (m_qmakeVfs->readVirtualFile(rc, QMakeVfs::VfsCumulative, &contents))
projectInfo.resourceFileContents[rc] = contents; projectInfo.resourceFileContents[rc] = contents;
} }
if (!hasQmlLib) { if (!hasQmlLib) {

View File

@@ -12,5 +12,6 @@ DEFINES *= \
PROPARSER_THREAD_SAFE \ PROPARSER_THREAD_SAFE \
PROEVALUATOR_THREAD_SAFE \ PROEVALUATOR_THREAD_SAFE \
PROEVALUATOR_CUMULATIVE \ PROEVALUATOR_CUMULATIVE \
PROEVALUATOR_DUAL_VFS \
PROEVALUATOR_SETENV PROEVALUATOR_SETENV
INCLUDEPATH *= $$PWD/../../shared INCLUDEPATH *= $$PWD/../../shared

View File

@@ -123,11 +123,12 @@ QStringList ProFileEvaluator::absoluteFileValues(
const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, const QString &variable, const QString &baseDirectory, const QStringList &searchDirs,
const ProFile *pro) const const ProFile *pro) const
{ {
QMakeVfs::VfsFlags flags = (d->m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QStringList result; QStringList result;
foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { foreach (const QString &el, pro ? values(variable, pro) : values(variable)) {
QString absEl; QString absEl;
if (IoUtils::isAbsolutePath(el)) { if (IoUtils::isAbsolutePath(el)) {
if (m_vfs->exists(el)) { if (m_vfs->exists(el, flags)) {
result << el; result << el;
goto next; goto next;
} }
@@ -135,7 +136,7 @@ QStringList ProFileEvaluator::absoluteFileValues(
} else { } else {
foreach (const QString &dir, searchDirs) { foreach (const QString &dir, searchDirs) {
QString fn = QDir::cleanPath(dir + QLatin1Char('/') + el); QString fn = QDir::cleanPath(dir + QLatin1Char('/') + el);
if (m_vfs->exists(fn)) { if (m_vfs->exists(fn, flags)) {
result << fn; result << fn;
goto next; goto next;
} }

View File

@@ -414,10 +414,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json
QMakeEvaluator::VisitReturn QMakeEvaluator::VisitReturn
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
bool exe, const QString &contents) QMakeVfs::VfsFlags flags, const QString &contents)
{ {
QString errStr; QString errStr;
if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) { if (!m_vfs->writeFile(fn, mode, flags, contents, &errStr)) {
evalError(fL1S("Cannot write %1file %2: %3") evalError(fL1S("Cannot write %1file %2: %3")
.arg(ctx, QDir::toNativeSeparators(fn), errStr)); .arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse; return ReturnFalse;
@@ -1714,7 +1714,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse; return ReturnFalse;
} }
QIODevice::OpenMode mode = QIODevice::Truncate; QIODevice::OpenMode mode = QIODevice::Truncate;
bool exe = false; QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString contents; QString contents;
if (args.count() >= 2) { if (args.count() >= 2) {
const ProStringList &vals = values(args.at(1).toKey()); const ProStringList &vals = values(args.at(1).toKey());
@@ -1727,7 +1727,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (m_tmp3 == QLatin1String("append")) { if (m_tmp3 == QLatin1String("append")) {
mode = QIODevice::Append; mode = QIODevice::Append;
} else if (m_tmp3 == QLatin1String("exe")) { } else if (m_tmp3 == QLatin1String("exe")) {
exe = true; flags |= QMakeVfs::VfsExecutable;
} else { } else {
evalError(fL1S("write_file(): invalid flag %1.").arg(m_tmp3)); evalError(fL1S("write_file(): invalid flag %1.").arg(m_tmp3));
return ReturnFalse; return ReturnFalse;
@@ -1737,7 +1737,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
} }
QString path = resolvePath(args.at(0).toQString(m_tmp1)); QString path = resolvePath(args.at(0).toQString(m_tmp1));
path.detach(); // make sure to not leak m_tmp1 into the map of written files. path.detach(); // make sure to not leak m_tmp1 into the map of written files.
return writeFile(QString(), path, mode, exe, contents); return writeFile(QString(), path, mode, flags, contents);
} }
case T_TOUCH: { case T_TOUCH: {
if (args.count() != 2) { if (args.count() != 2) {
@@ -1921,6 +1921,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
varstr += QLatin1Char('\n'); varstr += QLatin1Char('\n');
} }
QString fn; QString fn;
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
if (target == TargetSuper) { if (target == TargetSuper) {
if (m_superfile.isEmpty()) { if (m_superfile.isEmpty()) {
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super")); m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
@@ -1944,12 +1945,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
fn = m_stashfile; fn = m_stashfile;
if (fn.isEmpty()) if (fn.isEmpty())
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash")); fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
if (!m_vfs->exists(fn)) { if (!m_vfs->exists(fn, flags)) {
printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn))); printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn); valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
} }
} }
return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr); return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
} }
default: default:
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1))); evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));

View File

@@ -1082,6 +1082,7 @@ void QMakeEvaluator::loadDefaults()
bool QMakeEvaluator::prepareProject(const QString &inDir) bool QMakeEvaluator::prepareProject(const QString &inDir)
{ {
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString superdir; QString superdir;
if (m_option->do_cache) { if (m_option->do_cache) {
QString conffile; QString conffile;
@@ -1092,7 +1093,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
superdir = m_outputDir; superdir = m_outputDir;
forever { forever {
QString superfile = superdir + QLatin1String("/.qmake.super"); QString superfile = superdir + QLatin1String("/.qmake.super");
if (m_vfs->exists(superfile)) { if (m_vfs->exists(superfile, flags)) {
m_superfile = QDir::cleanPath(superfile); m_superfile = QDir::cleanPath(superfile);
break; break;
} }
@@ -1107,10 +1108,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
QString dir = m_outputDir; QString dir = m_outputDir;
forever { forever {
conffile = sdir + QLatin1String("/.qmake.conf"); conffile = sdir + QLatin1String("/.qmake.conf");
if (!m_vfs->exists(conffile)) if (!m_vfs->exists(conffile, flags))
conffile.clear(); conffile.clear();
cachefile = dir + QLatin1String("/.qmake.cache"); cachefile = dir + QLatin1String("/.qmake.cache");
if (!m_vfs->exists(cachefile)) if (!m_vfs->exists(cachefile, flags))
cachefile.clear(); cachefile.clear();
if (!conffile.isEmpty() || !cachefile.isEmpty()) { if (!conffile.isEmpty() || !cachefile.isEmpty()) {
if (dir != sdir) if (dir != sdir)
@@ -1138,7 +1139,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
QString dir = m_outputDir; QString dir = m_outputDir;
forever { forever {
QString stashfile = dir + QLatin1String("/.qmake.stash"); QString stashfile = dir + QLatin1String("/.qmake.stash");
if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile)) { if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile, flags)) {
m_stashfile = QDir::cleanPath(stashfile); m_stashfile = QDir::cleanPath(stashfile);
break; break;
} }
@@ -1265,7 +1266,8 @@ bool QMakeEvaluator::loadSpec()
m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
return false; return false;
} }
if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile)) { QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile, flags)) {
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile); valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile);
if (evaluateFile( if (evaluateFile(
m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)

View File

@@ -30,6 +30,7 @@
#endif #endif
#include "qmakeparser.h" #include "qmakeparser.h"
#include "qmakevfs.h"
#include "ioutils.h" #include "ioutils.h"
#include <qlist.h> #include <qlist.h>
@@ -232,7 +233,7 @@ public:
VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value); VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value);
VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
bool exe, const QString &contents); QMakeVfs::VfsFlags flags, const QString &contents);
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
void runProcess(QProcess *proc, const QString &command) const; void runProcess(QProcess *proc, const QString &command) const;
#endif #endif

View File

@@ -167,7 +167,13 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&m_cache->mutex); QMutexLocker locker(&m_cache->mutex);
#endif #endif
QHash<QString, ProFileCache::Entry>::Iterator it = m_cache->parsed_files.find(fileName); QHash<QString, ProFileCache::Entry>::Iterator it;
#ifdef PROEVALUATOR_DUAL_VFS
QString virtFileName = ((flags & ParseCumulative) ? '-' : '+') + fileName;
it = m_cache->parsed_files.find(virtFileName);
if (it == m_cache->parsed_files.end())
#endif
it = m_cache->parsed_files.find(fileName);
if (it != m_cache->parsed_files.end()) { if (it != m_cache->parsed_files.end()) {
ent = &*it; ent = &*it;
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
@@ -185,18 +191,27 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
if ((pro = ent->pro)) if ((pro = ent->pro))
pro->ref(); pro->ref();
} else if (!(flags & ParseOnlyCached)) { } else if (!(flags & ParseOnlyCached)) {
QString contents;
QMakeVfs::VfsFlags vfsFlags =
((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
bool virt = false;
#ifdef PROEVALUATOR_DUAL_VFS
virt = m_vfs->readVirtualFile(fileName, vfsFlags, &contents);
if (virt)
ent = &m_cache->parsed_files[virtFileName];
else
#endif
ent = &m_cache->parsed_files[fileName]; ent = &m_cache->parsed_files[fileName];
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
ent->locker = new ProFileCache::Entry::Locker; ent->locker = new ProFileCache::Entry::Locker;
locker.unlock(); locker.unlock();
#endif #endif
pro = new ProFile(fileName); if (virt || readFile(fileName, vfsFlags | QMakeVfs::VfsNoVirtual, flags, &contents)) {
if (!read(pro, flags)) { pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
delete pro;
pro = 0;
} else {
pro->itemsRef()->squeeze(); pro->itemsRef()->squeeze();
pro->ref(); pro->ref();
} else {
pro = 0;
} }
ent->pro = pro; ent->pro = pro;
#ifdef PROPARSER_THREAD_SAFE #ifdef PROPARSER_THREAD_SAFE
@@ -213,11 +228,13 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
pro = 0; pro = 0;
} }
} else if (!(flags & ParseOnlyCached)) { } else if (!(flags & ParseOnlyCached)) {
pro = new ProFile(fileName); QString contents;
if (!read(pro, flags)) { QMakeVfs::VfsFlags vfsFlags =
delete pro; ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
if (readFile(fileName, vfsFlags, flags, &contents))
pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
else
pro = 0; pro = 0;
}
} else { } else {
pro = 0; pro = 0;
} }
@@ -238,18 +255,17 @@ void QMakeParser::discardFileFromCache(const QString &fileName)
m_cache->discardFile(fileName); m_cache->discardFile(fileName);
} }
bool QMakeParser::read(ProFile *pro, ParseFlags flags) bool QMakeParser::readFile(
const QString &fn, QMakeVfs::VfsFlags vfsFlags, ParseFlags flags, QString *contents)
{ {
QString content;
QString errStr; QString errStr;
QMakeVfs::ReadResult result = m_vfs->readFile(pro->fileName(), &content, &errStr); QMakeVfs::ReadResult result = m_vfs->readFile(fn, vfsFlags, contents, &errStr);
if (result != QMakeVfs::ReadOk) { if (result != QMakeVfs::ReadOk) {
if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound)) if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound))
m_handler->message(QMakeParserHandler::ParserIoError, m_handler->message(QMakeParserHandler::ParserIoError,
fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr)); fL1S("Cannot read %1: %2").arg(fn, errStr));
return false; return false;
} }
read(pro, QStringRef(&content), 1, FullGrammar);
return true; return true;
} }

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include "qmake_global.h" #include "qmake_global.h"
#include "qmakevfs.h"
#include "proitems.h" #include "proitems.h"
#include <qhash.h> #include <qhash.h>
@@ -75,7 +76,12 @@ public:
ParseDefault = 0, ParseDefault = 0,
ParseUseCache = 1, ParseUseCache = 1,
ParseOnlyCached = 2, ParseOnlyCached = 2,
ParseReportMissing = 4 ParseReportMissing = 4,
#ifdef PROEVALUATOR_DUAL_VFS
ParseCumulative = 8
#else
ParseCumulative = 0
#endif
}; };
Q_DECLARE_FLAGS(ParseFlags, ParseFlag) Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
@@ -126,7 +132,7 @@ private:
ushort terminator; // '}' if replace function call is braced, ':' if test function ushort terminator; // '}' if replace function call is braced, ':' if test function
}; };
bool read(ProFile *pro, ParseFlags flags); bool readFile(const QString &fn, QMakeVfs::VfsFlags vfsFlags, QMakeParser::ParseFlags flags, QString *contents);
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar); void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);

View File

@@ -44,20 +44,24 @@ QMakeVfs::QMakeVfs()
{ {
} }
bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr) const QString &contents, QString *errStr)
{ {
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
#ifdef PROEVALUATOR_DUAL_VFS
QString *cont = &m_files[((flags & VfsCumulative) ? '-' : '+') + fn];
#else
QString *cont = &m_files[fn]; QString *cont = &m_files[fn];
Q_UNUSED(flags)
#endif
if (mode & QIODevice::Append) if (mode & QIODevice::Append)
*cont += contents; *cont += contents;
else else
*cont = contents; *cont = contents;
Q_UNUSED(errStr) Q_UNUSED(errStr)
Q_UNUSED(exe)
return true; return true;
#else #else
QFileInfo qfi(fn); QFileInfo qfi(fn);
@@ -69,7 +73,7 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
QFile cfile(fn); QFile cfile(fn);
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (cfile.readAll() == bytes) { if (cfile.readAll() == bytes) {
if (exe) { if (flags & VfsExecutable) {
cfile.setPermissions(cfile.permissions() cfile.setPermissions(cfile.permissions()
| QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
} else { } else {
@@ -90,7 +94,7 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
*errStr = cfile.errorString(); *errStr = cfile.errorString();
return false; return false;
} }
if (exe) if (flags & VfsExecutable)
cfile.setPermissions(cfile.permissions() cfile.setPermissions(cfile.permissions()
| QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
return true; return true;
@@ -98,29 +102,52 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
} }
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
bool QMakeVfs::readVirtualFile(const QString &fn, QString *contents) bool QMakeVfs::readVirtualFile(const QString &fn, VfsFlags flags, QString *contents)
{ {
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); QHash<QString, QString>::ConstIterator it;
# ifdef PROEVALUATOR_DUAL_VFS
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
if (it != m_files.constEnd()) {
*contents = *it;
return true;
}
# else
it = m_files.constFind(fn);
if (it != m_files.constEnd() if (it != m_files.constEnd()
&& it->constData() != m_magicMissing.constData() && it->constData() != m_magicMissing.constData()
&& it->constData() != m_magicExisting.constData()) { && it->constData() != m_magicExisting.constData()) {
*contents = *it; *contents = *it;
return true; return true;
} }
Q_UNUSED(flags)
# endif
return false; return false;
} }
#endif #endif
QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) QMakeVfs::ReadResult QMakeVfs::readFile(
const QString &fn, VfsFlags flags, QString *contents, QString *errStr)
{ {
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); QHash<QString, QString>::ConstIterator it;
# ifdef PROEVALUATOR_DUAL_VFS
if (!(flags & VfsNoVirtual)) {
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
if (it != m_files.constEnd()) {
*contents = *it;
return ReadOk;
}
}
# else
Q_UNUSED(flags)
# endif
it = m_files.constFind(fn);
if (it != m_files.constEnd()) { if (it != m_files.constEnd()) {
if (it->constData() == m_magicMissing.constData()) { if (it->constData() == m_magicMissing.constData()) {
*errStr = fL1S("No such file or directory"); *errStr = fL1S("No such file or directory");
@@ -131,6 +158,8 @@ QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QS
return ReadOk; return ReadOk;
} }
} }
#else
Q_UNUSED(flags)
#endif #endif
QFile file(fn); QFile file(fn);
@@ -159,15 +188,25 @@ QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QS
return ReadOk; return ReadOk;
} }
bool QMakeVfs::exists(const QString &fn) bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
{ {
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE # ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
# endif # endif
QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); QHash<QString, QString>::ConstIterator it;
# ifdef PROEVALUATOR_DUAL_VFS
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
if (it != m_files.constEnd())
return true;
# else
Q_UNUSED(flags)
# endif
it = m_files.constFind(fn);
if (it != m_files.constEnd()) if (it != m_files.constEnd())
return it->constData() != m_magicMissing.constData(); return it->constData() != m_magicMissing.constData();
#else
Q_UNUSED(flags)
#endif #endif
bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular; bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular;
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL

View File

@@ -36,6 +36,12 @@
# endif # endif
#endif #endif
#ifdef PROEVALUATOR_DUAL_VFS
# ifndef PROEVALUATOR_CUMULATIVE
# error PROEVALUATOR_DUAL_VFS requires PROEVALUATOR_CUMULATIVE
# endif
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QMAKE_EXPORT QMakeVfs class QMAKE_EXPORT QMakeVfs
@@ -47,14 +53,27 @@ public:
ReadOtherError ReadOtherError
}; };
enum VfsFlag {
VfsExecutable = 1,
VfsExact = 0,
#ifdef PROEVALUATOR_DUAL_VFS
VfsCumulative = 2,
VfsNoVirtual = 4
#else
VfsCumulative = 0,
VfsNoVirtual = 0
#endif
};
Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
QMakeVfs(); QMakeVfs();
bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr); bool writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
ReadResult readFile(const QString &fn, QString *contents, QString *errStr); ReadResult readFile(const QString &fn, VfsFlags flags, QString *contents, QString *errStr);
bool exists(const QString &fn); bool exists(const QString &fn, VfsFlags flags);
#ifndef PROEVALUATOR_FULL #ifndef PROEVALUATOR_FULL
bool readVirtualFile(const QString &fn, QString *contents); bool readVirtualFile(const QString &fn, VfsFlags flags, QString *contents);
void invalidateCache(); void invalidateCache();
void invalidateContents(); void invalidateContents();
@@ -71,4 +90,6 @@ private:
#endif #endif
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeVfs::VfsFlags)
QT_END_NAMESPACE QT_END_NAMESPACE