From 5ea1efb55fcfb76c8846c309ad86d1bd7cf0d3a6 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Tue, 7 Sep 2010 11:28:00 +0200
Subject: [PATCH] Custom wizard: Add a 'workingdirectory' attribute to
 generator script.

enabling scripts that completely generate the project directory.
Default to %TargetPath%.
---
 .../customwizard/customwizard.cpp             | 33 ++++++++++++++-----
 .../customwizard/customwizardparameters.cpp   |  4 +++
 .../customwizard/customwizardparameters.h     |  1 +
 .../customwizardscriptgenerator.cpp           | 14 ++++++--
 4 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp
index 7f4c5107b61..2943e55dfd3 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp
@@ -182,6 +182,18 @@ template <class WizardPage>
     return 0;
 }
 
+// Determine where to run the generator script. The user may specify
+// an expression subject to field replacement, default is the target path.
+static inline QString scriptWorkingDirectory(const QSharedPointer<Internal::CustomWizardContext> &ctx,
+                                             const QSharedPointer<Internal::CustomWizardParameters> &p)
+{
+    if (p->filesGeneratorScriptWorkingDirectory.isEmpty())
+        return ctx->targetPath;
+    QString path = p->filesGeneratorScriptWorkingDirectory;
+    Internal::CustomWizardContext::replaceFields(ctx->replacements, &path);
+    return path;
+}
+
 Core::GeneratedFiles CustomWizard::generateFiles(const QWizard *dialog, QString *errorMessage) const
 {
     // Look for the Custom field page to find the path
@@ -215,17 +227,18 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM
     // project wizard that is entirely created by a script,
     // the target project directory might not exist.
     const CustomWizardContextPtr ctx = context();
-    QDir targetPathDir(ctx->targetPath);
-    if (!targetPathDir.exists()) {
+    const QString scriptWorkingDir = scriptWorkingDirectory(ctx, d->m_parameters);
+    const QDir scriptWorkingDirDir(scriptWorkingDir);
+    if (!scriptWorkingDirDir.exists()) {
         if (CustomWizardPrivate::verbose)
-            qDebug("Creating directory %s", qPrintable(ctx->targetPath));
-        if (!targetPathDir.mkpath(ctx->targetPath)) {
-            *errorMessage = QString::fromLatin1("Unable to create the target directory '%1'").arg(ctx->targetPath);
+            qDebug("Creating directory %s", qPrintable(scriptWorkingDir));
+        if (!scriptWorkingDirDir.mkpath(scriptWorkingDir)) {
+            *errorMessage = QString::fromLatin1("Unable to create the target directory '%1'").arg(scriptWorkingDir);
             return false;
         }
     }
     // Run the custom script to actually generate the files.
-    if (!Internal::runCustomWizardGeneratorScript(ctx->targetPath,
+    if (!Internal::runCustomWizardGeneratorScript(scriptWorkingDir,
                                                   d->m_parameters->filesGeneratorScript,
                                                   d->m_parameters->filesGeneratorScriptArguments,
                                                   ctx->replacements, errorMessage))
@@ -254,10 +267,11 @@ Core::GeneratedFiles CustomWizard::generateWizardFiles(QString *errorMessage) co
 
     // If generator script is non-empty, do a dry run to get it's files.
     if (!d->m_parameters->filesGeneratorScript.isEmpty()) {
-        rc += Internal::dryRunCustomWizardGeneratorScript(ctx->targetPath,
+        rc += Internal::dryRunCustomWizardGeneratorScript(scriptWorkingDirectory(ctx, d->m_parameters),
                                                           d->m_parameters->filesGeneratorScript,
                                                           d->m_parameters->filesGeneratorScriptArguments,
-                                                          ctx->replacements, errorMessage);
+                                                          ctx->replacements,
+                                                          errorMessage);
         if (rc.isEmpty())
             return rc;
     }
@@ -276,6 +290,9 @@ CustomWizard::FieldReplacementMap CustomWizard::replacementMap(const QWizard *w)
         const QString value = w->field(field.name).toString();
         fieldReplacementMap.insert(field.name, value);
     }
+    // Insert paths for generator scripts.
+    fieldReplacementMap.insert(QLatin1String("Path"), QDir::toNativeSeparators(context()->path));
+    fieldReplacementMap.insert(QLatin1String("TargetPath"), QDir::toNativeSeparators(context()->targetPath));
     return fieldReplacementMap;
 }
 
diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
index 6efcd8d6ec2..6ccca044989 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
@@ -72,6 +72,7 @@ static const char comboEntryTextElementC[] = "comboentrytext";
 
 static const char generatorScriptElementC[] = "generatorscript";
 static const char generatorScriptBinaryAttributeC[] = "binary";
+static const char generatorScriptWorkingDirectoryAttributeC[] = "workingdirectory";
 static const char generatorScriptArgumentElementC[] = "argument";
 static const char generatorScriptArgumentValueAttributeC[] = "value";
 static const char generatorScriptArgumentOmitEmptyAttributeC[] = "omit-empty";
@@ -557,6 +558,7 @@ CustomWizardParameters::ParseResult
                         *errorMessage = QString::fromLatin1("No binary specified for generator script.");
                         return ParseFailed;
                     }
+                    filesGeneratorScriptWorkingDirectory = attributeValue(reader, generatorScriptWorkingDirectoryAttributeC);
                     break;
                 case ParseWithinScriptArguments: {
                     GeneratorScriptArgument argument(attributeValue(reader, generatorScriptArgumentValueAttributeC));
@@ -623,6 +625,8 @@ QString CustomWizardParameters::toString() const
         str << "Script:";
         foreach(const QString &a, filesGeneratorScript)
             str << " '" << a << '\'';
+        if (!filesGeneratorScriptWorkingDirectory.isEmpty())
+            str << "\nrun in '" <<  filesGeneratorScriptWorkingDirectory << '\'';
         str << "\nArguments: ";
         foreach(const GeneratorScriptArgument &a, filesGeneratorScriptArguments) {
             str << " '" << a.value  << '\'';
diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.h b/src/plugins/projectexplorer/customwizard/customwizardparameters.h
index 59ee8599ccc..732098ff35e 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardparameters.h
+++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.h
@@ -104,6 +104,7 @@ public:
     QString klass;
     QList<CustomWizardFile> files;
     QStringList filesGeneratorScript; // Complete binary, such as 'cmd /c myscript.pl'.
+    QString filesGeneratorScriptWorkingDirectory;
     QList<GeneratorScriptArgument> filesGeneratorScriptArguments;
 
     QString fieldPageTitle;
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
index 5b6c2bef19a..72f91696429 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
@@ -178,7 +178,12 @@ Core::GeneratedFiles
                             attributes |= Core::GeneratedFile::OpenProjectAttribute;
                 } else {
                     // Token 0 is file name. Wizard wants native names.
-                    const QString fullPath = targetPath + QLatin1Char('/') + token;
+                    // Expand to full path if relative
+                    const QFileInfo fileInfo(token);
+                    const QString fullPath =
+                            fileInfo.isAbsolute() ?
+                            token :
+                            (targetPath + QLatin1Char('/') + token);
                     file.setPath(QDir::toNativeSeparators(fullPath));
                 }
             }
@@ -186,9 +191,12 @@ Core::GeneratedFiles
             files.push_back(file);
         }
     }
-    if (CustomWizard::verbose())
+    if (CustomWizard::verbose()) {
+        QDebug nospace = qDebug().nospace();
+        nospace << script << " generated:\n";
         foreach(const Core::GeneratedFile &f, files)
-            qDebug() << script << " generated: " << f.path() << f.attributes();
+            nospace << ' ' << f.path() << f.attributes() << '\n';
+    }
     return files;
 }
 
-- 
GitLab