aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2014-07-23 14:36:52 +0200
committerChristian Kandeler <christian.kandeler@digia.com>2014-07-23 16:28:36 +0200
commitbbae2f5918ec902533c769387f32d53bf8582bb0 (patch)
treeaceb3a3104218a49608406158de0d19fc0ffd210
parent77ba7c98a81009122e99681dd4e34a4c4309de52 (diff)
API: Be smarter about adding files already matched by wildcards.
The project file does not need an update in this case. Actually, that would even lead to an error on the next project resolving, as the file would then be listed twice (once explicitly and once matched by a pattern). Task-number: QBS-653 Change-Id: If56969c36d1bba3f9194621690c2e1f25229ee9e Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--src/lib/corelib/api/project.cpp60
-rw-r--r--src/lib/corelib/api/project_p.h1
-rw-r--r--src/lib/corelib/api/projectfileupdater.cpp6
-rw-r--r--src/lib/corelib/language/projectresolver.cpp10
-rw-r--r--src/lib/corelib/language/projectresolver.h3
-rw-r--r--tests/auto/api/testdata/project-editing/project.qbs8
-rw-r--r--tests/auto/api/testdata/project-editing/test.wildcard0
-rw-r--r--tests/auto/api/tst_api.cpp44
8 files changed, 109 insertions, 23 deletions
diff --git a/src/lib/corelib/api/project.cpp b/src/lib/corelib/api/project.cpp
index c83471dbb..3e5ea76d9 100644
--- a/src/lib/corelib/api/project.cpp
+++ b/src/lib/corelib/api/project.cpp
@@ -66,6 +66,7 @@
#include <QDir>
#include <QMutex>
#include <QMutexLocker>
+#include <QRegExp>
#include <QSharedData>
namespace qbs {
@@ -323,6 +324,26 @@ ProjectPrivate::GroupUpdateContext ProjectPrivate::getGroupContext(const Product
return context;
}
+static bool matchesWildcard(const QString &filePath, const GroupConstPtr &group)
+{
+ if (!group->wildcards)
+ return false;
+ foreach (const QString &pattern, group->wildcards->patterns) {
+ QString fullPattern;
+ if (QFileInfo(group->prefix).isAbsolute()) {
+ fullPattern = group->prefix;
+ } else {
+ fullPattern = QFileInfo(group->location.fileName()).absolutePath()
+ + QLatin1Char('/') + group->prefix;
+ }
+ fullPattern.append(QLatin1Char('/')).append(pattern);
+ fullPattern = QDir::cleanPath(fullPattern);
+ if (QRegExp(fullPattern, Qt::CaseSensitive, QRegExp::Wildcard).exactMatch(filePath))
+ return true;
+ }
+ return false;
+}
+
ProjectPrivate::FileListUpdateContext ProjectPrivate::getFileListContext(const ProductData &product,
const GroupData &group, const QStringList &filePaths)
{
@@ -352,13 +373,27 @@ ProjectPrivate::FileListUpdateContext ProjectPrivate::getFileListContext(const P
throw ErrorInfo(Tr::tr("File '%1' appears more than once.").arg(absPath));
if (!FileInfo(absPath).exists())
throw ErrorInfo(Tr::tr("File '%1' does not exist.").arg(absPath));
- filesContext.absoluteFilePaths << absPath;
- filesContext.relativeFilePaths << baseDir.relativeFilePath(absPath);
+ if (matchesWildcard(absPath, groupContext.resolvedGroups.first())) {
+ filesContext.absoluteFilePathsFromWildcards << absPath;
+ } else {
+ filesContext.absoluteFilePaths << absPath;
+ filesContext.relativeFilePaths << baseDir.relativeFilePath(absPath);
+ }
}
return filesContext;
}
+static SourceArtifactPtr createSourceArtifact(const QString &filePath,
+ const ResolvedProductPtr &product, const GroupConstPtr &group,
+ QList<SourceArtifactPtr> &artifactList, Logger &logger)
+{
+ const SourceArtifactPtr artifact = ProjectResolver::createSourceArtifact(product,
+ group->properties, filePath, group->fileTags, group->overrideTags, artifactList);
+ ProjectResolver::applyFileTaggers(artifact, product, logger);
+ return artifact;
+}
+
void ProjectPrivate::addFiles(const ProductData &product, const GroupData &group,
const QStringList &filePaths)
{
@@ -392,14 +427,13 @@ void ProjectPrivate::addFiles(const ProductData &product, const GroupData &group
const ResolvedProductPtr &resolvedProduct = groupContext.resolvedProducts.at(i);
const GroupPtr &resolvedGroup = groupContext.resolvedGroups.at(i);
foreach (const QString &file, filesContext.absoluteFilePaths) {
- const SourceArtifactPtr artifact = SourceArtifact::create();
- artifact->absoluteFilePath = file;
- artifact->properties = resolvedGroup->properties;
- artifact->fileTags = resolvedGroup->fileTags;
- artifact->overrideFileTags = resolvedGroup->overrideTags;
- ProjectResolver::applyFileTaggers(artifact, resolvedProduct, logger);
- addedSourceArtifacts << artifact;
- resolvedGroup->files << artifact;
+ addedSourceArtifacts << createSourceArtifact(file, resolvedProduct,
+ resolvedGroup, resolvedGroup->files, logger);
+ }
+ foreach (const QString &file, filesContext.absoluteFilePathsFromWildcards) {
+ QBS_CHECK(resolvedGroup->wildcards);
+ addedSourceArtifacts << createSourceArtifact(file, resolvedProduct,
+ resolvedGroup, resolvedGroup->wildcards->files, logger);
}
if (resolvedProduct->enabled) {
foreach (const SourceArtifactConstPtr &sa, addedSourceArtifacts)
@@ -409,6 +443,7 @@ void ProjectPrivate::addFiles(const ProductData &product, const GroupData &group
doSanityChecks(internalProject, logger);
foreach (const GroupData &g, groupContext.groups) {
g.d->filePaths << filesContext.absoluteFilePaths;
+ g.d->expandedWildcards << filesContext.absoluteFilePathsFromWildcards;
qSort(g.d->filePaths);
}
}
@@ -419,6 +454,11 @@ void ProjectPrivate::removeFiles(const ProductData &product, const GroupData &gr
FileListUpdateContext filesContext = getFileListContext(product, group, filePaths);
GroupUpdateContext &groupContext = filesContext.groupContext;
+ if (!filesContext.absoluteFilePathsFromWildcards.isEmpty()) {
+ throw ErrorInfo(Tr::tr("The following files cannot be removed from the project file, "
+ "because they match wildcard patterns: %1")
+ .arg(filesContext.absoluteFilePathsFromWildcards.join(QLatin1String(", "))));
+ }
QStringList filesNotFound = filesContext.absoluteFilePaths;
QList<SourceArtifactPtr> sourceArtifacts;
foreach (const SourceArtifactPtr &sa, groupContext.resolvedGroups.first()->files) {
diff --git a/src/lib/corelib/api/project_p.h b/src/lib/corelib/api/project_p.h
index 2c6dddf73..30c966dce 100644
--- a/src/lib/corelib/api/project_p.h
+++ b/src/lib/corelib/api/project_p.h
@@ -84,6 +84,7 @@ public:
GroupUpdateContext groupContext;
QStringList absoluteFilePaths;
QStringList relativeFilePaths;
+ QStringList absoluteFilePathsFromWildcards; // Not included in the other two lists.
};
GroupUpdateContext getGroupContext(const ProductData &product, const GroupData &group);
diff --git a/src/lib/corelib/api/projectfileupdater.cpp b/src/lib/corelib/api/projectfileupdater.cpp
index 2deb83264..fd38e87a0 100644
--- a/src/lib/corelib/api/projectfileupdater.cpp
+++ b/src/lib/corelib/api/projectfileupdater.cpp
@@ -269,6 +269,9 @@ ProjectFileFilesAdder::ProjectFileFilesAdder(const ProductData &product, const G
void ProjectFileFilesAdder::doApply(QString &fileContent, UiProgram *ast)
{
+ if (m_files.isEmpty())
+ return;
+
// Find the item containing the "files" binding.
ItemFinder itemFinder(m_group.isValid() ? m_group.location() : m_product.location());
ast->accept(&itemFinder);
@@ -389,6 +392,9 @@ ProjectFileFilesRemover::ProjectFileFilesRemover(const ProductData &product, con
void ProjectFileFilesRemover::doApply(QString &fileContent, UiProgram *ast)
{
+ if (m_files.isEmpty())
+ return;
+
// Find the item containing the "files" binding.
ItemFinder itemFinder(m_group.isValid() ? m_group.location() : m_product.location());
ast->accept(&itemFinder);
diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp
index 5d6a97349..92244f6a4 100644
--- a/src/lib/corelib/language/projectresolver.cpp
+++ b/src/lib/corelib/language/projectresolver.cpp
@@ -425,12 +425,9 @@ void ProjectResolver::resolveModule(const QStringList &moduleName, Item *item,
m_moduleContext = 0;
}
-static void createSourceArtifact(const ResolvedProductConstPtr &rproduct,
- const PropertyMapPtr &properties,
- const QString &fileName,
- const FileTags &fileTags,
- bool overrideTags,
- QList<SourceArtifactPtr> &artifactList)
+SourceArtifactPtr ProjectResolver::createSourceArtifact(const ResolvedProductConstPtr &rproduct,
+ const PropertyMapPtr &properties, const QString &fileName, const FileTags &fileTags,
+ bool overrideTags, QList<SourceArtifactPtr> &artifactList)
{
SourceArtifactPtr artifact = SourceArtifact::create();
artifact->absoluteFilePath = FileInfo::resolvePath(rproduct->sourceDirectory, fileName);
@@ -438,6 +435,7 @@ static void createSourceArtifact(const ResolvedProductConstPtr &rproduct,
artifact->overrideFileTags = overrideTags;
artifact->properties = properties;
artifactList += artifact;
+ return artifact;
}
static bool isSomeModulePropertySet(Item *group)
diff --git a/src/lib/corelib/language/projectresolver.h b/src/lib/corelib/language/projectresolver.h
index 091c932f3..5bb711b15 100644
--- a/src/lib/corelib/language/projectresolver.h
+++ b/src/lib/corelib/language/projectresolver.h
@@ -64,6 +64,9 @@ public:
static void applyFileTaggers(const SourceArtifactPtr &artifact,
const ResolvedProductConstPtr &product, const Logger &logger);
+ static SourceArtifactPtr createSourceArtifact(const ResolvedProductConstPtr &rproduct,
+ const PropertyMapPtr &properties, const QString &fileName,
+ const FileTags &fileTags, bool overrideTags, QList<SourceArtifactPtr> &artifactList);
private:
struct ProjectContext
diff --git a/tests/auto/api/testdata/project-editing/project.qbs b/tests/auto/api/testdata/project-editing/project.qbs
index 9190f846c..57cb30355 100644
--- a/tests/auto/api/testdata/project-editing/project.qbs
+++ b/tests/auto/api/testdata/project-editing/project.qbs
@@ -27,5 +27,13 @@ CppApplication {
prefix: "blubb"
files: []
}
+ Group {
+ name: "Group with wildcards"
+ files: "*.klaus"
+ }
+ Group {
+ name: "Other group with wildcards"
+ files: "*.wildcard"
+ }
files: "main.cpp"
}
diff --git a/tests/auto/api/testdata/project-editing/test.wildcard b/tests/auto/api/testdata/project-editing/test.wildcard
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/api/testdata/project-editing/test.wildcard
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 95ec57264..cc85fd704 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -181,8 +181,9 @@ qbs::GroupData findGroup(const qbs::ProductData &product, const QString &name)
void TestApi::changeContent()
{
qbs::SetupProjectParameters setupParams = defaultSetupParameters();
- setupParams.setProjectFilePath(QDir::cleanPath(m_workingDataDir +
- "/project-editing/project.qbs"));
+ const QString workingDir = m_workingDataDir + "/project-editing";
+ QDir::setCurrent(workingDir);
+ setupParams.setProjectFilePath(QDir::cleanPath(workingDir + "/project.qbs"));
QScopedPointer<qbs::SetupProjectJob> job(qbs::Project().setupProject(setupParams,
m_logSink, 0));
waitForFinished(job.data());
@@ -191,7 +192,7 @@ void TestApi::changeContent()
qbs::ProjectData projectData = project.projectData();
QCOMPARE(projectData.allProducts().count(), 1);
qbs::ProductData product = projectData.allProducts().first();
- QCOMPARE(product.groups().count(), 6);
+ QCOMPARE(product.groups().count(), 8);
// Error handling: Invalid product.
qbs::ErrorInfo errorInfo = project.addGroup(qbs::ProductData(), "blubb");
@@ -224,7 +225,7 @@ void TestApi::changeContent()
projectData = project.projectData();
QVERIFY(projectData.products().count() == 1);
product = projectData.products().first();
- QCOMPARE(product.groups().count(), 8);
+ QCOMPARE(product.groups().count(), 10);
qbs::GroupData group = findGroup(product, "New Group 1");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "file.h" << "file.cpp");
@@ -234,7 +235,7 @@ void TestApi::changeContent()
projectData = project.projectData();
QVERIFY(projectData.products().count() == 1);
product = projectData.products().first();
- QCOMPARE(product.groups().count(), 8);
+ QCOMPARE(product.groups().count(), 10);
group = findGroup(product, "New Group 1");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "file.cpp");
@@ -249,7 +250,7 @@ void TestApi::changeContent()
projectData = project.projectData();
QVERIFY(projectData.products().count() == 1);
product = projectData.products().first();
- QCOMPARE(product.groups().count(), 8);
+ QCOMPARE(product.groups().count(), 10);
group = findGroup(product, "New Group 1");
QVERIFY(group.isValid());
errorInfo = project.removeFiles(product, group, QStringList() << "file.h");
@@ -331,13 +332,42 @@ void TestApi::changeContent()
QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString()));
projectData = project.projectData();
QVERIFY(projectData.products().count() == 1);
- QCOMPARE(projectData.products().first().groups().count(), 7);
+ QCOMPARE(projectData.products().first().groups().count(), 9);
// Error handling: Try to remove the same group again.
errorInfo = project.removeGroup(product, group);
QVERIFY(errorInfo.hasError());
QVERIFY2(errorInfo.toString().contains("does not exist"), qPrintable(errorInfo.toString()));
+ // Add a file to a group where the file name is already matched by a wildcard.
+ projectData = project.projectData();
+ QVERIFY(projectData.products().count() == 1);
+ product = projectData.products().first();
+ group = findGroup(product, "Group with wildcards");
+ QVERIFY(group.isValid());
+ QFile newFile("koerper.klaus");
+ QVERIFY2(newFile.open(QIODevice::WriteOnly), qPrintable(newFile.errorString()));
+ newFile.close();
+ errorInfo = project.addFiles(product, group, QStringList() << newFile.fileName());
+ QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString()));
+ projectData = project.projectData();
+ QVERIFY(projectData.products().count() == 1);
+ product = projectData.products().first();
+ group = findGroup(product, "Group with wildcards");
+ QVERIFY(group.isValid());
+ QCOMPARE(group.expandedWildcards().count(), 1);
+ QCOMPARE(group.expandedWildcards().first(), QFileInfo(newFile).absoluteFilePath());
+
+ // Error checking: Try to remove a file that originates from a wildcard pattern.
+ projectData = project.projectData();
+ QVERIFY(projectData.products().count() == 1);
+ product = projectData.products().first();
+ group = findGroup(product, "Other group with wildcards");
+ QVERIFY(group.isValid());
+ errorInfo = project.removeFiles(product, group, QStringList() << "test.wildcard");
+ QVERIFY(errorInfo.hasError());
+ QVERIFY2(errorInfo.toString().contains("pattern"), qPrintable(errorInfo.toString()));
+
// Check whether building will take the added and removed cpp files into account.
// This must not be moved below the re-resolving test!!!
qbs::BuildOptions buildOptions;