diff options
author | Christian Kandeler <christian.kandeler@digia.com> | 2014-07-30 16:19:22 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@digia.com> | 2014-07-30 16:57:02 +0200 |
commit | 59aed7c423ab1ff8e19d34736619cb128cc8b49a (patch) | |
tree | 013307f4243703e342bc89fcdc62ad4647cd5a9f | |
parent | c598241085cd191c3914a4b614f219e7a9a55bbf (diff) |
Invalidate project after certain unsuccessful re-resolving attempts.
Namely, if the build data has been mangled by the re-resolving attempt.
Change-Id: Ibe020a6bda38a335f95e2d2cef4f37fac3199a7d
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r-- | src/lib/corelib/api/jobs.cpp | 6 | ||||
-rw-r--r-- | src/lib/corelib/api/project.cpp | 7 | ||||
-rw-r--r-- | tests/auto/api/api.qbs | 2 | ||||
-rw-r--r-- | tests/auto/api/testdata/project-invalidation/project.early-error.qbs | 6 | ||||
-rw-r--r-- | tests/auto/api/testdata/project-invalidation/project.late-error.qbs | 13 | ||||
-rw-r--r-- | tests/auto/api/testdata/project-invalidation/project.no-error.qbs | 5 | ||||
-rw-r--r-- | tests/auto/api/tst_api.cpp | 32 | ||||
-rw-r--r-- | tests/auto/api/tst_api.h | 1 |
8 files changed, 68 insertions, 4 deletions
diff --git a/src/lib/corelib/api/jobs.cpp b/src/lib/corelib/api/jobs.cpp index 6b8cf702e..00269d947 100644 --- a/src/lib/corelib/api/jobs.cpp +++ b/src/lib/corelib/api/jobs.cpp @@ -252,8 +252,12 @@ void SetupProjectJob::finish() // The invariant is that there must always be at most one valid Project object // for the same build directory, so that exclusive ownership of the build graph lock // is ensured. - if (m_existingProject.isValid() && !error().hasError()) + // We also need to invalidate the project if an error has occurred after the build data was + // already transferred. + if (m_existingProject.isValid() + && (!error().hasError() || !m_existingProject.d->internalProject->buildData)) { m_existingProject.d->internalProject.clear(); + } } /*! diff --git a/src/lib/corelib/api/project.cpp b/src/lib/corelib/api/project.cpp index 3e5ea76d9..93daf433f 100644 --- a/src/lib/corelib/api/project.cpp +++ b/src/lib/corelib/api/project.cpp @@ -717,8 +717,11 @@ Project &Project::operator=(const Project &other) * track the results of the operation. * If the function is called on a valid \c Project object, the build graph will not be loaded * from a file, but will be taken from the existing project. In that case, if resolving - * finishes successfully, the existing project will be invalidated. If resolving fails, the - * existing \c Project object stays as it is. + * finishes successfully, the existing project will be invalidated. If resolving fails, qbs will + * try to keep the existing project valid. However, under certain circumstances, resolving the new + * project will fail at a time where existing project data has already been touched, in which case + * the existing project has to be invalidated (this could be avoided, but it would hurt performance). + * So after an unsuccessful re-resolve job, the existing project may or may not be valid anymore. * \note The qbs plugins will only be loaded once. As a result, the value of * \c parameters.pluginPaths will only have an effect the first time this function is called. * Similarly, the value of \c parameters.searchPaths will not have an effect if diff --git a/tests/auto/api/api.qbs b/tests/auto/api/api.qbs index df42afc89..343325469 100644 --- a/tests/auto/api/api.qbs +++ b/tests/auto/api/api.qbs @@ -2,7 +2,7 @@ import "../autotest.qbs" as AutoTest AutoTest { testName: "api" - files: ["tst_api.h", "tst_api.cpp"] + files: ["../shared.h", "tst_api.h", "tst_api.cpp"] cpp.defines: base .concat(['SRCDIR="' + path + '"']) .concat(project.enableProjectFileUpdates ? ["QBS_ENABLE_PROJECT_FILE_UPDATES"] : []) diff --git a/tests/auto/api/testdata/project-invalidation/project.early-error.qbs b/tests/auto/api/testdata/project-invalidation/project.early-error.qbs new file mode 100644 index 000000000..ecc76c816 --- /dev/null +++ b/tests/auto/api/testdata/project-invalidation/project.early-error.qbs @@ -0,0 +1,6 @@ +import qbs + +Product { + type: "mytype" + files: "nosuchfile.txt" +} diff --git a/tests/auto/api/testdata/project-invalidation/project.late-error.qbs b/tests/auto/api/testdata/project-invalidation/project.late-error.qbs new file mode 100644 index 000000000..b55979ec7 --- /dev/null +++ b/tests/auto/api/testdata/project-invalidation/project.late-error.qbs @@ -0,0 +1,13 @@ +import qbs + +Product { + type: "mytype" + + Transformer { + Artifact { + filePath: "blubb" + fileTags: "mytype" + } + prepare: [] + } +} diff --git a/tests/auto/api/testdata/project-invalidation/project.no-error.qbs b/tests/auto/api/testdata/project-invalidation/project.no-error.qbs new file mode 100644 index 000000000..099553ffc --- /dev/null +++ b/tests/auto/api/testdata/project-invalidation/project.no-error.qbs @@ -0,0 +1,5 @@ +import qbs + +Product { + type: "mytype" +} diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp index cc85fd704..fd2968441 100644 --- a/tests/auto/api/tst_api.cpp +++ b/tests/auto/api/tst_api.cpp @@ -29,6 +29,8 @@ #include "tst_api.h" +#include "../shared.h" + #include <api/jobs.h> #include <api/project.h> #include <api/projectdata.h> @@ -760,6 +762,36 @@ void TestApi::nonexistingProjectPropertyFromCommandLine() qPrintable(job->error().toString())); } +void TestApi::projectInvalidation() +{ + qbs::SetupProjectParameters setupParams = defaultSetupParameters(); + setupParams.setRestoreBehavior(qbs::SetupProjectParameters::RestoreAndTrackChanges); + const QString projectDirPath = QDir::cleanPath(m_workingDataDir + "/project-invalidation"); + setupParams.setProjectFilePath(projectDirPath + "/project.qbs"); + QDir::setCurrent(projectDirPath); + QVERIFY(QFile::copy("project.no-error.qbs", "project.qbs")); + QScopedPointer<qbs::SetupProjectJob> setupJob(qbs::Project().setupProject(setupParams, + m_logSink, 0)); + waitForFinished(setupJob.data()); + QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); + qbs::Project project = setupJob->project(); + QVERIFY(project.isValid()); + waitForNewTimestamp(); + QVERIFY(QFile::remove("project.qbs")); + QVERIFY(QFile::copy("project.early-error.qbs", "project.qbs")); + setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); + waitForFinished(setupJob.data()); + QVERIFY(setupJob->error().hasError()); + QVERIFY(project.isValid()); // Error in Loader, old project still valid. + waitForNewTimestamp(); + QVERIFY(QFile::remove("project.qbs")); + QVERIFY(QFile::copy("project.late-error.qbs", "project.qbs")); + setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); + waitForFinished(setupJob.data()); + QVERIFY(setupJob->error().hasError()); + QVERIFY(!project.isValid()); // Error in build data re-resolving, old project not valid anymore. +} + void TestApi::projectLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters(); diff --git a/tests/auto/api/tst_api.h b/tests/auto/api/tst_api.h index 473b20c80..8285f1b53 100644 --- a/tests/auto/api/tst_api.h +++ b/tests/auto/api/tst_api.h @@ -63,6 +63,7 @@ private slots: void multiArch(); void nonexistingProjectPropertyFromProduct(); void nonexistingProjectPropertyFromCommandLine(); + void projectInvalidation(); void projectLocking(); void references(); void sourceFileInBuildDir(); |