From d5271a086d7be7fbf7b07a2ca450b805b229aa15 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Tue, 12 Jan 2010 16:45:21 +0100
Subject: [PATCH] VCS[hg, git]: Add support for repository creation.

Add repository creation operation to IVersionControl, implement for hg
and git, add convenience slot with prompts to VCSBasePlugin.
Add respective menu options and make menus are visible in case no VCS is
active.
Change project wizards extension page to list VCS that are capable of
repository creation in a QComboBox in case the directory is not managed
by another VCS (in which case it lists that one for operation 'add').
On that occasion, polish the Project selection to use a QComboBox as
well and add some smartness to find the most suitable project to add via
path matching.
---
 src/plugins/coreplugin/iversioncontrol.h      |  13 +-
 src/plugins/cvs/cvscontrol.cpp                |   6 +
 src/plugins/cvs/cvscontrol.h                  |   1 +
 src/plugins/cvs/cvsplugin.cpp                 |   2 +-
 src/plugins/git/gitclient.cpp                 |  16 +
 src/plugins/git/gitclient.h                   |   1 +
 src/plugins/git/gitplugin.cpp                 |  15 +-
 src/plugins/git/gitplugin.h                   |   1 +
 src/plugins/git/gitversioncontrol.cpp         |  10 +-
 src/plugins/git/gitversioncontrol.h           |   1 +
 src/plugins/mercurial/constants.h             |   1 +
 src/plugins/mercurial/mercurialclient.cpp     |  12 +
 src/plugins/mercurial/mercurialclient.h       |   1 +
 src/plugins/mercurial/mercurialcontrol.cpp    |   9 +-
 src/plugins/mercurial/mercurialcontrol.h      |   1 +
 src/plugins/mercurial/mercurialplugin.cpp     |   8 +-
 src/plugins/mercurial/mercurialplugin.h       |   1 +
 src/plugins/perforce/perforceplugin.cpp       |   2 +-
 .../perforce/perforceversioncontrol.cpp       |  10 +-
 src/plugins/perforce/perforceversioncontrol.h |   1 +
 .../projectfilewizardextension.cpp            | 293 ++++++++++++++----
 .../projectfilewizardextension.h              |  13 +-
 .../projectexplorer/projectwizardpage.cpp     |  71 +----
 .../projectexplorer/projectwizardpage.h       |  27 +-
 .../projectexplorer/projectwizardpage.ui      |  41 ++-
 src/plugins/subversion/subversioncontrol.cpp  |   6 +
 src/plugins/subversion/subversioncontrol.h    |   1 +
 src/plugins/subversion/subversionplugin.cpp   |   2 +-
 src/plugins/vcsbase/vcsbaseplugin.cpp         |  59 +++-
 src/plugins/vcsbase/vcsbaseplugin.h           |  11 +-
 30 files changed, 451 insertions(+), 185 deletions(-)

diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index ecb1f418c00..90831b2323f 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -41,9 +41,10 @@ class CORE_EXPORT IVersionControl : public QObject
 {
     Q_OBJECT
 public:
-    enum Operation { AddOperation, DeleteOperation, OpenOperation };
+    enum Operation { AddOperation, DeleteOperation, OpenOperation,
+                     CreateRepositoryOperation };
 
-    IVersionControl(QObject *parent = 0) : QObject(parent) {}
+    explicit IVersionControl(QObject *parent = 0) : QObject(parent) {}
     virtual ~IVersionControl() {}
 
     virtual QString displayName() const = 0;
@@ -93,12 +94,14 @@ public:
     /*!
      * Called after a file has been removed from the project (if the user
      * wants), e.g. 'p4 delete', 'svn delete'.
-     *
-     * You probably want to call VcsManager::showDeleteDialog, which asks the
-     * user to confirm the deletion.
      */
     virtual bool vcsDelete(const QString &filename) = 0;
 
+    /*!
+     * Called to initialize the version control systemin a directory.
+     */
+    virtual bool vcsCreateRepository(const QString &directory) = 0;
+
 signals:
     void repositoryChanged(const QString &repository);
     void filesChanged(const QStringList &files);
diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp
index f633e4c7afd..da57f43d5a9 100644
--- a/src/plugins/cvs/cvscontrol.cpp
+++ b/src/plugins/cvs/cvscontrol.cpp
@@ -54,6 +54,7 @@ bool CVSControl::supportsOperation(Operation operation) const
     case DeleteOperation:
         break;
     case OpenOperation:
+    case CreateRepositoryOperation:
         rc = false;
         break;
     }
@@ -78,6 +79,11 @@ bool CVSControl::vcsDelete(const QString &fileName)
     return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
 }
 
+bool CVSControl::vcsCreateRepository(const QString &)
+{
+    return false;
+}
+
 bool CVSControl::managesDirectory(const QString &directory) const
 {
     return m_plugin->managesDirectory(directory);
diff --git a/src/plugins/cvs/cvscontrol.h b/src/plugins/cvs/cvscontrol.h
index e89a292408e..f53c38b9257 100644
--- a/src/plugins/cvs/cvscontrol.h
+++ b/src/plugins/cvs/cvscontrol.h
@@ -52,6 +52,7 @@ public:
     virtual bool vcsOpen(const QString &fileName);
     virtual bool vcsAdd(const QString &fileName);
     virtual bool vcsDelete(const QString &filename);
+    virtual bool vcsCreateRepository(const QString &directory);
 
     void emitRepositoryChanged(const QString &s);
     void emitFilesChanged(const QStringList &l);
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 3a070507b5f..ff6c0050574 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -498,7 +498,7 @@ CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName)
 
 void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
 {
-    if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction))
+    if (!enableMenuAction(as, m_menuAction))
         return;
 
     m_logRepositoryAction->setEnabled(currentState().hasTopLevel());
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index aad68a5ee02..6e45bc7818c 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -446,6 +446,22 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
     return true;
 }
 
+// Initialize repository
+bool GitClient::synchronousInit(const QString &workingDirectory)
+{
+    if (Git::Constants::debug)
+        qDebug() << Q_FUNC_INFO << workingDirectory;
+    QByteArray outputText;
+    QByteArray errorText;
+    const QStringList arguments(QLatin1String("init"));
+    const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
+    // '[Re]Initialized...'
+    VCSBase::VCSBaseOutputWindow::instance()->append(QString::fromLocal8Bit(outputText));
+    if (!rc)
+        VCSBase::VCSBaseOutputWindow::instance()->append(QString::fromLocal8Bit(errorText));
+    return rc;
+}
+
 bool GitClient::synchronousCheckout(const QString &workingDirectory,
                                     const QStringList &files,
                                     QString *errorMessage)
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 54be3a2e382..6d6e0c25373 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -92,6 +92,7 @@ public:
     bool synchronousAdd(const QString &workingDirectory, const QStringList &files);
     bool synchronousReset(const QString &workingDirectory, const QStringList &files);
     bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
+    bool synchronousInit(const QString &workingDirectory);
     bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
     bool synchronousStash(const QString &workingDirectory, QString *errorMessage);
     bool synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs,
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 7227085a367..a25b5f93c1e 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -122,6 +122,7 @@ GitPlugin::GitPlugin() :
     m_undoFileAction(0),
     m_logRepositoryAction(0),
     m_undoRepositoryAction(0),
+    m_createRepositoryAction(0),
     m_showAction(0),
     m_stageAction(0),
     m_unstageAction(0),
@@ -306,6 +307,11 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
     connect(m_undoRepositoryAction, SIGNAL(triggered()), this, SLOT(undoRepositoryChanges()));
     gitContainer->addAction(command);
 
+    m_createRepositoryAction = new QAction(tr("Create Repository..."), this);
+    command = actionManager->registerAction(m_createRepositoryAction, "Git.CreateRepository", globalcontext);
+    connect(m_createRepositoryAction, SIGNAL(triggered()), this, SLOT(createRepository()));
+    gitContainer->addAction(command);
+
     gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Global"), this));
 
     m_stashAction = new QAction(tr("Stash"), this);
@@ -677,9 +683,10 @@ void GitPlugin::stashList()
 
 void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
 {
-    if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction))
+    if (!enableMenuAction(as, m_menuAction))
         return;
-
+    // Note: This menu is visible if there is no repository. Only
+    // 'Create Repository'/'Show' actions should be available.
     const QString fileName = currentState().currentFileName();
     m_diffAction->setParameter(fileName);
     m_logAction->setParameter(fileName);
@@ -708,9 +715,13 @@ void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
     m_statusRepositoryAction->setEnabled(repositoryEnabled);
     m_branchListAction->setEnabled(repositoryEnabled);
     m_stashListAction->setEnabled(repositoryEnabled);
+    m_stashAction->setEnabled(repositoryEnabled);
+    m_pullAction->setEnabled(repositoryEnabled);
+    m_commitAction->setEnabled(repositoryEnabled);
     m_stashPopAction->setEnabled(repositoryEnabled);
     m_logRepositoryAction->setEnabled(repositoryEnabled);
     m_undoRepositoryAction->setEnabled(repositoryEnabled);
+    m_pushAction->setEnabled(repositoryEnabled);
 
     // Prompts for repo.
     m_showAction->setEnabled(true);
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index d89290841da..415efef5c3d 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -131,6 +131,7 @@ private:
     Utils::ParameterAction *m_undoFileAction;
     QAction *m_logRepositoryAction;
     QAction *m_undoRepositoryAction;
+    QAction *m_createRepositoryAction;
 
     QAction *m_showAction;
     Utils::ParameterAction *m_stageAction;
diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp
index f241396e22d..76541548ccb 100644
--- a/src/plugins/git/gitversioncontrol.cpp
+++ b/src/plugins/git/gitversioncontrol.cpp
@@ -29,6 +29,7 @@
 
 #include "gitversioncontrol.h"
 #include "gitclient.h"
+#include "gitplugin.h"
 
 namespace Git {
 namespace Internal {
@@ -52,6 +53,9 @@ bool GitVersionControl::supportsOperation(Operation operation) const
     case DeleteOperation:
     case OpenOperation:
         break;
+    case CreateRepositoryOperation:
+        rc = true;
+        break;
     }
     return rc;
 }
@@ -72,10 +76,14 @@ bool GitVersionControl::vcsDelete(const QString & /*fileName*/)
     return false;
 }
 
+bool GitVersionControl::vcsCreateRepository(const QString &directory)
+{
+    return GitPlugin::instance()->gitClient()->synchronousInit(directory);
+}
+
 bool GitVersionControl::managesDirectory(const QString &directory) const
 {
     return !GitClient::findRepositoryForDirectory(directory).isEmpty();
-
 }
 
 QString GitVersionControl::findTopLevelForDirectory(const QString &directory) const
diff --git a/src/plugins/git/gitversioncontrol.h b/src/plugins/git/gitversioncontrol.h
index e7dbf0dabec..e5013cce6e0 100644
--- a/src/plugins/git/gitversioncontrol.h
+++ b/src/plugins/git/gitversioncontrol.h
@@ -53,6 +53,7 @@ public:
     virtual bool vcsOpen(const QString &fileName);
     virtual bool vcsAdd(const QString &fileName);
     virtual bool vcsDelete(const QString &filename);
+    virtual bool vcsCreateRepository(const QString &directory);
 
     void emitFilesChanged(const QStringList &);
 
diff --git a/src/plugins/mercurial/constants.h b/src/plugins/mercurial/constants.h
index 070d2c784c4..f091a481f90 100644
--- a/src/plugins/mercurial/constants.h
+++ b/src/plugins/mercurial/constants.h
@@ -107,6 +107,7 @@ const char * const IMPORT = "Mercurial.Action.Import";
 const char * const INCOMING = "Mercurial.Action.Incoming";
 const char * const OUTGOING = "Mercurial.Action.Outgoing";
 const char * const COMMIT = "Mercurial.Action.Commit";
+const char * const CREATE_REPOSITORY = "Mercurial.Action.CreateRepository";
 
 //Repository Management
 const char * const MERGE = "Mercurial.Action.Merge";
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index 205cf76021d..59b13b9eb4b 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -366,6 +366,18 @@ void MercurialClient::revert(const QString &workingDir,
     enqueueJob(job);
 }
 
+bool MercurialClient::createRepositorySync(const QString &workingDirectory)
+{
+    const QStringList args(QLatin1String("init"));
+    QByteArray outputData;
+    if (!executeHgSynchronously(workingDirectory, args, &outputData))
+        return false;
+    QString output = QString::fromLocal8Bit(outputData);
+    output.remove(QLatin1Char('\r'));
+    VCSBase::VCSBaseOutputWindow::instance()->append(output);
+    return true;
+}
+
 void MercurialClient::status(const QString &workingDir, const QString &file)
 {
     QStringList args(QLatin1String("status"));
diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h
index 8dbfb073c9c..cd626adfb59 100644
--- a/src/plugins/mercurial/mercurialclient.h
+++ b/src/plugins/mercurial/mercurialclient.h
@@ -88,6 +88,7 @@ public:
     void statusWithSignal(const QString &repository);
     void revertFile(const QString &workingDir, const QString &file, const QString &revision = QString());
     void revertRepository(const QString &workingDir, const QString &revision = QString());
+    bool createRepositorySync(const QString &workingDir);
     void update(const QString &repositoryRoot, const QString &revision = QString());
     void commit(const QString &repositoryRoot,
                 const QStringList &files,
diff --git a/src/plugins/mercurial/mercurialcontrol.cpp b/src/plugins/mercurial/mercurialcontrol.cpp
index 44c6ee04a04..3ca94573be4 100644
--- a/src/plugins/mercurial/mercurialcontrol.cpp
+++ b/src/plugins/mercurial/mercurialcontrol.cpp
@@ -62,17 +62,15 @@ QString MercurialControl::findTopLevelForDirectory(const QString &directory) con
 bool MercurialControl::supportsOperation(Operation operation) const
 {
     bool supported = true;
-
     switch (operation) {
     case Core::IVersionControl::AddOperation:
     case Core::IVersionControl::DeleteOperation:
+    case Core::IVersionControl::CreateRepositoryOperation:
         break;
     case Core::IVersionControl::OpenOperation:
-    default:
         supported = false;
         break;
     }
-
     return supported;
 }
 
@@ -94,6 +92,11 @@ bool MercurialControl::vcsDelete(const QString &filename)
     return mercurialClient->remove(fi.absolutePath(), fi.fileName());
 }
 
+bool MercurialControl::vcsCreateRepository(const QString &directory)
+{
+    return mercurialClient->createRepositorySync(directory);
+}
+
 bool MercurialControl::sccManaged(const QString &filename)
 {
     const QFileInfo fi(filename);
diff --git a/src/plugins/mercurial/mercurialcontrol.h b/src/plugins/mercurial/mercurialcontrol.h
index df3b99ef64c..d447a5bc164 100644
--- a/src/plugins/mercurial/mercurialcontrol.h
+++ b/src/plugins/mercurial/mercurialcontrol.h
@@ -56,6 +56,7 @@ public:
     bool vcsOpen(const QString &fileName);
     bool vcsAdd(const QString &filename);
     bool vcsDelete(const QString &filename);
+    bool vcsCreateRepository(const QString &directory);
     bool sccManaged(const QString &filename);
 
 public slots:
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index 6da681bc283..a3487f76415 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -127,6 +127,7 @@ MercurialPlugin::MercurialPlugin() :
         changeLog(0),
         m_addAction(0),
         m_deleteAction(0),
+        m_createRepositoryAction(0),
         m_menuAction(0)
 {
     m_instance = this;
@@ -429,6 +430,11 @@ void MercurialPlugin::createRepositoryActions(const QList<int> &context)
     command->setDefaultKeySequence(QKeySequence(tr("Alt+H,Alt+C")));
     connect(action, SIGNAL(triggered()), this, SLOT(commit()));
     mercurialContainer->addAction(command);
+
+    m_createRepositoryAction = new QAction(tr("Create Repository..."), this);
+    command = actionManager->registerAction(m_createRepositoryAction, QLatin1String(Constants::CREATE_REPOSITORY), context);
+    connect(m_createRepositoryAction, SIGNAL(triggered()), this, SLOT(createRepository()));
+    mercurialContainer->addAction(command);
 }
 
 void MercurialPlugin::pull()
@@ -675,7 +681,7 @@ void MercurialPlugin::createSeparator(const QList<int> &context, const QString &
 
 void MercurialPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
 {
-    if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction))
+    if (!enableMenuAction(as, m_menuAction))
         return;
 
     const QString filename = currentState().currentFileName();
diff --git a/src/plugins/mercurial/mercurialplugin.h b/src/plugins/mercurial/mercurialplugin.h
index 0a441965ab5..8bc5fe902c9 100644
--- a/src/plugins/mercurial/mercurialplugin.h
+++ b/src/plugins/mercurial/mercurialplugin.h
@@ -166,6 +166,7 @@ private:
     Utils::ParameterAction *revertFile;
     Utils::ParameterAction *statusFile;
 
+    QAction *m_createRepositoryAction;
     //submit editor actions
     QAction *editorCommit;
     QAction *editorDiff;
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 34d2f383d2e..e4e16bd6d6b 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -788,7 +788,7 @@ void PerforcePlugin::filelog(const QString &workingDir, const QStringList &fileN
 
 void PerforcePlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
 {
-    if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction))
+    if (!enableMenuAction(as, m_menuAction))
         return;
 
     m_logRepositoryAction->setEnabled(currentState().hasTopLevel());
diff --git a/src/plugins/perforce/perforceversioncontrol.cpp b/src/plugins/perforce/perforceversioncontrol.cpp
index bfa9f8827af..0be2ef59019 100644
--- a/src/plugins/perforce/perforceversioncontrol.cpp
+++ b/src/plugins/perforce/perforceversioncontrol.cpp
@@ -50,14 +50,15 @@ QString PerforceVersionControl::displayName() const
 
 bool PerforceVersionControl::supportsOperation(Operation operation) const
 {
-    bool rc = true;
     switch (operation) {
     case AddOperation:
     case DeleteOperation:
     case OpenOperation:
+        return true;
+    case CreateRepositoryOperation:
         break;
     }
-    return rc;
+    return false;
 }
 
 bool PerforceVersionControl::vcsOpen(const QString &fileName)
@@ -78,6 +79,11 @@ bool PerforceVersionControl::vcsDelete(const QString &fileName)
     return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
 }
 
+bool PerforceVersionControl::vcsCreateRepository(const QString &)
+{
+    return false;
+}
+
 bool PerforceVersionControl::managesDirectory(const QString &directory) const
 {
     const bool rc = m_plugin->managesDirectory(directory);
diff --git a/src/plugins/perforce/perforceversioncontrol.h b/src/plugins/perforce/perforceversioncontrol.h
index 8d6660fc021..815b7430539 100644
--- a/src/plugins/perforce/perforceversioncontrol.h
+++ b/src/plugins/perforce/perforceversioncontrol.h
@@ -52,6 +52,7 @@ public:
     virtual bool vcsOpen(const QString &fileName);
     virtual bool vcsAdd(const QString &fileName);
     virtual bool vcsDelete(const QString &filename);
+    virtual bool vcsCreateRepository(const QString &directory);
 
     void emitRepositoryChanged(const QString &s);
     void emitFilesChanged(const QStringList &l);
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp
index 5e6b7e575d9..c07894ffb6f 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.cpp
+++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp
@@ -34,17 +34,23 @@
 #include "nodesvisitor.h"
 #include "projectwizardpage.h"
 
+#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
+
 #include <coreplugin/basefilewizard.h>
 #include <coreplugin/dialogs/iwizard.h>
 #include <coreplugin/filemanager.h>
 #include <coreplugin/icore.h>
 #include <coreplugin/iversioncontrol.h>
 #include <coreplugin/vcsmanager.h>
+#include <extensionsystem/pluginmanager.h>
 
 #include <QtCore/QVariant>
+#include <QtCore/QtAlgorithms>
 #include <QtCore/QDebug>
 #include <QtCore/QFileInfo>
 #include <QtCore/QMultiMap>
+#include <QtCore/QDir>
 
 enum { debugExtension = 0 };
 
@@ -54,43 +60,111 @@ typedef QList<ProjectNode *> ProjectNodeList;
 
 namespace Internal {
 
-// --------- AllProjectNodesVisitor. Figure out all projects.
-// No sooner said then done.
+// AllProjectNodesVisitor: Retrieve all projects (*.pri/*.pro).
 class AllProjectNodesVisitor : public NodesVisitor
 {
-    AllProjectNodesVisitor(ProjectNodeList &l) : m_projectNodes(l) {}
 public:
-
-    static ProjectNodeList allProjects(const ProjectExplorerPlugin *pe);
+    static ProjectNodeList allProjects();
 
     virtual void visitProjectNode(ProjectNode *node);
 
 private:
-    ProjectNodeList &m_projectNodes;
+    ProjectNodeList m_projectNodes;
 };
 
-ProjectNodeList AllProjectNodesVisitor::allProjects(const ProjectExplorerPlugin *pe)
+ProjectNodeList AllProjectNodesVisitor::allProjects()
 {
-    ProjectNodeList rc;
-    AllProjectNodesVisitor visitor(rc);
-    pe->session()->sessionNode()->accept(&visitor);
-    return rc;
+    AllProjectNodesVisitor visitor;
+    ProjectExplorerPlugin::instance()->session()->sessionNode()->accept(&visitor);
+    return visitor.m_projectNodes;
 }
 
 void AllProjectNodesVisitor::visitProjectNode(ProjectNode *node)
 {
     if (node->supportedActions().contains(ProjectNode::AddFile))
-        m_projectNodes << node;
+        m_projectNodes.push_back(node);
+}
+
+// ProjectEntry: Context entry for a *.pri/*.pro file. Stores name and path
+// for quick sort and path search, provides operator<() for maps.
+struct ProjectEntry {
+    enum Type { ProFile, PriFile }; // Sort order: 'pro' before 'pri'
+
+    ProjectEntry() : node(0), type(ProFile) {}
+    explicit ProjectEntry(ProjectNode *node);
+
+    int compare(const ProjectEntry &rhs) const;
+
+    ProjectNode *node;
+    QString nativeDirectory; // For matching against wizards' files, which are native.
+    QString fileName;
+    QString baseName;
+    Type type;
+};
+
+ProjectEntry::ProjectEntry(ProjectNode *n) :
+    node(n),
+    type(ProFile)
+{
+    const QFileInfo fi(node->path());
+    fileName = fi.fileName();
+    baseName = fi.baseName();
+    if (fi.suffix() != QLatin1String("pro"))
+        type = PriFile;    
+    nativeDirectory = QDir::toNativeSeparators(fi.absolutePath());
+}
+
+// Sort helper that sorts by base name and puts '*.pro' before '*.pri'
+int ProjectEntry::compare(const ProjectEntry &rhs) const
+{
+    if (const int brc = baseName.compare(rhs.baseName))
+        return brc;
+    if (type < rhs.type)
+        return -1;
+    if (type > rhs.type)
+        return 1;
+    return 0;
+}
+
+inline bool operator<(const ProjectEntry &pe1, const ProjectEntry &pe2)
+{
+    return pe1.compare(pe2) < 0;
+}
+
+QDebug operator<<(QDebug d, const ProjectEntry &e)
+{
+    d.nospace() << e.nativeDirectory << ' ' << e.fileName << ' ' << e.type;
+    return d;
 }
 
 // --------- ProjectWizardContext
 struct ProjectWizardContext
 {
-    Core::IVersionControl *versionControl;
-    ProjectNodeList projects;
+    ProjectWizardContext();
+    void clear();
+
+    QList<Core::IVersionControl*> versionControls;
+    QList<ProjectEntry> projects;
     ProjectWizardPage *page;
+    bool repositoryExists; // Is VCS 'add' sufficient, or should a repository be created?
+    QString commonDirectory;
 };
 
+ProjectWizardContext::ProjectWizardContext() :
+    page(0),
+    repositoryExists(false)
+{
+}
+
+void ProjectWizardContext::clear()
+{
+    versionControls.clear();
+    projects.clear();
+    commonDirectory.clear();
+    page = 0;
+    repositoryExists = false;
+}
+
 // ---- ProjectFileWizardExtension
 ProjectFileWizardExtension::ProjectFileWizardExtension()
   : m_context(0)
@@ -102,85 +176,184 @@ ProjectFileWizardExtension::~ProjectFileWizardExtension()
     delete m_context;
 }
 
+// Find the project the new files should be added to given their common
+// path. Either a direct match on the directory or the directory with
+// the longest matching path (list containing"/project/subproject1" matching
+// common path "/project/subproject1/newuserpath").
+// This relies on 'pro' occurring before 'pri' in the list.
+static int findMatchingProject(const QList<ProjectEntry> &projects,
+                               const QString &commonPath)
+{
+    if (projects.isEmpty() || commonPath.isEmpty())
+        return -1;
+
+    int bestMatch = -1;
+    int bestMatchLength = 0;
+    const int count = projects.size();
+    for (int p = 0; p < count; p++) {
+        // Direct match or better match? (note that the wizards' files are native).
+        const QString &projectDirectory = projects.at(p).nativeDirectory;
+        if (projectDirectory == commonPath)
+            return p;
+        if (projectDirectory.size() > bestMatchLength
+            && commonPath.startsWith(projectDirectory)) {
+            bestMatchLength = projectDirectory.size();
+            bestMatch = p;
+        }
+    }
+    return bestMatch;
+}
+
 void ProjectFileWizardExtension::firstExtensionPageShown(const QList<Core::GeneratedFile> &files)
 {
     if (debugExtension)
         qDebug() << Q_FUNC_INFO << files.size();
-    // Setup files display and version control depending on path
+    // Parametrize wizard page: find best project to add to, set up files display and
+    // version control depending on path
     QStringList fileNames;
     foreach (const Core::GeneratedFile &f, files)
         fileNames.push_back(f.path());
-
-    const QString directory = QFileInfo(fileNames.front()).absolutePath();
-    m_context->versionControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(directory);
-
-    m_context->page->setFilesDisplay(fileNames);
-
-    const bool canAddToVCS = m_context->versionControl && m_context->versionControl->supportsOperation(Core::IVersionControl::AddOperation);
-    if (m_context->versionControl)
-         m_context->page->setVCSDisplay(m_context->versionControl->displayName());
-    m_context->page->setAddToVersionControlEnabled(canAddToVCS);
+    m_context->commonDirectory = Utils::commonPath(fileNames);
+    m_context->page->setFilesDisplay(m_context->commonDirectory, fileNames);
+    // Find best project (Entry at 0 is 'None').
+    const int bestProjectIndex = findMatchingProject(m_context->projects, m_context->commonDirectory);
+    if (bestProjectIndex == -1) {
+        m_context->page->setCurrentProjectIndex(0);
+    } else {
+        m_context->page->setCurrentProjectIndex(bestProjectIndex + 1);
+    }
+    initializeVersionControlChoices();
 }
 
-static ProjectNode *currentProject()
+void ProjectFileWizardExtension::initializeVersionControlChoices()
 {
-    if (Node *currentNode = ProjectExplorerPlugin::instance()->currentNode())
-        if (ProjectNode *currentProjectNode = qobject_cast<ProjectNode *>(currentNode))
-            return currentProjectNode;
-    return 0;
+    // Figure out version control situation:
+    // 1) Directory is managed and VCS supports "Add" -> List it
+    // 2) Directory is managed and VCS does not support "Add" -> None available
+    // 3) Directory is not managed -> Offer all VCS that support "CreateRepository"
+    if (!m_context->commonDirectory.isEmpty()) {
+        Core::IVersionControl *managingControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(m_context->commonDirectory);
+        if (managingControl) {
+            // Under VCS
+            if (managingControl->supportsOperation(Core::IVersionControl::AddOperation)) {
+                m_context->versionControls.push_back(managingControl);
+                m_context->repositoryExists = true;
+            }
+        } else {
+            // Create
+            foreach (Core::IVersionControl *vc, ExtensionSystem::PluginManager::instance()->getObjects<Core::IVersionControl>())
+                if (vc->supportsOperation(Core::IVersionControl::CreateRepositoryOperation))
+                    m_context->versionControls.push_back(vc);
+            m_context->repositoryExists = false;
+        }
+    } // has a common root.
+    // Compile names
+    //: No version control system selected
+    QStringList versionControlChoices = QStringList(tr("<None>"));
+    foreach(const Core::IVersionControl *c, m_context->versionControls)
+        versionControlChoices.push_back(c->displayName());
+    m_context->page->setVersionControls(versionControlChoices);
+    // Enable adding to version control by default.
+    if (m_context->repositoryExists && versionControlChoices.size() >= 2)
+        m_context->page->setVersionControlIndex(1);
 }
 
 QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const Core::IWizard *wizard)
 {
-    if (!m_context)
+    if (!m_context) {
         m_context = new ProjectWizardContext;
+    } else {
+        m_context->clear();
+    }
     // Init context with page and projects
     m_context->page = new ProjectWizardPage;
-    m_context->versionControl = 0;
-    m_context->projects = AllProjectNodesVisitor::allProjects(ProjectExplorerPlugin::instance());
+    // Project list remains the same over duration of wizard execution
+    // Note that projects cannot be added to projects.
+    initProjectChoices(wizard->kind() != Core::IWizard::ProjectWizard);
+    return QList<QWizardPage *>() << m_context->page;
+}
+
+void ProjectFileWizardExtension::initProjectChoices(bool enabled)
+{
     // Set up project list which remains the same over duration of wizard execution
-    // Disable "add project to project"
-    const bool hasProjects = !m_context->projects.empty();
-    if (hasProjects) {
-        m_context->page->setProjects(m_context->projects);
-        m_context->page->setCurrentProject(currentProject());
+    //: No project selected
+    QStringList projectChoices(tr("<None>"));
+    if (enabled) {
+        typedef QMap<ProjectEntry, bool> ProjectEntryMap;
+        // Sort by base name and purge duplicated entries (resulting from dependencies)
+        // via Map.
+        ProjectEntryMap entryMap;
+        foreach(ProjectNode *n, AllProjectNodesVisitor::allProjects())
+            entryMap.insert(ProjectEntry(n), true);
+        // Collect names
+        const ProjectEntryMap::const_iterator cend = entryMap.constEnd();
+        for (ProjectEntryMap::const_iterator it = entryMap.constBegin(); it != cend; ++it) {
+            m_context->projects.push_back(it.key());
+            projectChoices.push_back(it.key().fileName);
+        }
     }
-    m_context->page->setAddToProjectEnabled(hasProjects && wizard->kind() != Core::IWizard::ProjectWizard);
-
-    return QList<QWizardPage *>() << m_context->page;
+    m_context->page->setProjects(projectChoices);
 }
 
 bool ProjectFileWizardExtension::process(const QList<Core::GeneratedFile> &files, QString *errorMessage)
+{
+    return processProject(files, errorMessage) &&
+           processVersionControl(files, errorMessage);
+}
+
+// Add files to project && version control
+bool ProjectFileWizardExtension::processProject(const QList<Core::GeneratedFile> &files, QString *errorMessage)
 {
     typedef QMultiMap<FileType, QString> TypeFileMap;
-    // Add files to project && version control
-    if (m_context->page->addToProject()) {
-        ProjectNode *project = m_context->page->currentProject();
-        // Split into lists by file type and add
-        TypeFileMap typeFileMap;
-        foreach (const Core::GeneratedFile &generatedFile, files) {
-            const QString path = generatedFile.path();
-            typeFileMap.insert(typeForFileName(Core::ICore::instance()->mimeDatabase(), path), path);
+
+    // Add files to  project (Entry at 0 is 'None').
+    const int projectIndex = m_context->page->currentProjectIndex() - 1;
+    if (projectIndex < 0 || projectIndex >= m_context->projects.size())
+        return true;
+    ProjectNode *project = m_context->projects.at(projectIndex).node;
+    // Split into lists by file type and bulk-add them.
+    TypeFileMap typeFileMap;
+    const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
+    foreach (const Core::GeneratedFile &generatedFile, files) {
+        const QString path = generatedFile.path();
+        typeFileMap.insert(typeForFileName(mdb, path), path);
+    }
+    foreach (FileType type, typeFileMap.uniqueKeys()) {
+        const QStringList files = typeFileMap.values(type);
+        if (!project->addFiles(type, files)) {
+            *errorMessage = tr("Failed to add one or more files to project\n'%1' (%2).").
+                            arg(project->path(), files.join(QString(QLatin1Char(','))));
+            return false;
         }
-        foreach (FileType type, typeFileMap.uniqueKeys()) {
-            const QStringList files = typeFileMap.values(type);
-            if (!project->addFiles(type, files)) {
-                *errorMessage = tr("Failed to add one or more files to project\n'%1' (%2).").
-                    arg(project->path(), files.join(QLatin1String(",")));
-                return false;
-            }
+    }
+    return true;
+}
+
+bool ProjectFileWizardExtension::processVersionControl(const QList<Core::GeneratedFile> &files, QString *errorMessage)
+{
+    // Add files to  version control (Entry at 0 is 'None').
+    const int vcsIndex = m_context->page->versionControlIndex() - 1;
+    if (vcsIndex < 0 || vcsIndex >= m_context->versionControls.size())
+        return true;
+    QTC_ASSERT(!m_context->commonDirectory.isEmpty(), return false);
+    Core::IVersionControl *versionControl = m_context->versionControls.at(vcsIndex);
+    // Create repository?
+    if (!m_context->repositoryExists) {
+        QTC_ASSERT(versionControl->supportsOperation(Core::IVersionControl::CreateRepositoryOperation), return false);
+        if (!versionControl->vcsCreateRepository(m_context->commonDirectory)) {
+            *errorMessage = tr("A version control system repository could not be created in '%1'.").arg(m_context->commonDirectory);
+            return false;
         }
     }
-    // Add files to  version control
-    if (m_context->page->addToVersionControl()) {
+    // Add files if supported.
+    if (versionControl->supportsOperation(Core::IVersionControl::AddOperation)) {
         foreach (const Core::GeneratedFile &generatedFile, files) {
-            if (!m_context->versionControl->vcsAdd(generatedFile.path())) {
+            if (!versionControl->vcsAdd(generatedFile.path())) {
                 *errorMessage = tr("Failed to add '%1' to the version control system.").arg(generatedFile.path());
                 return false;
             }
         }
     }
-
     return true;
 }
 
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.h b/src/plugins/projectexplorer/projectfilewizardextension.h
index 487d8cf090a..c5eee0c7b05 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.h
+++ b/src/plugins/projectexplorer/projectfilewizardextension.h
@@ -38,10 +38,10 @@ namespace Internal {
 
 struct ProjectWizardContext;
 
-/*
-  Adds final page allowing the user to add files to project && version control
-  to BaseFileWizard.
-  */
+/* Final file wizard processing steps:
+ * 1) Add to a project file (*.pri/ *.pro)
+ * 2) Initialize a version control repository (unless the path is already
+ *    managed) and do 'add' if the VCS supports it.  */
 class ProjectFileWizardExtension : public Core::IFileWizardExtension
 {
     Q_OBJECT
@@ -56,6 +56,11 @@ public slots:
     virtual void firstExtensionPageShown(const QList<Core::GeneratedFile> &);
 
 private:
+    void initProjectChoices(bool enabled);
+    void initializeVersionControlChoices();
+    bool processProject(const QList<Core::GeneratedFile> &files, QString *errorMessage);
+    bool processVersionControl(const QList<Core::GeneratedFile> &files, QString *errorMessage);
+
     ProjectWizardContext *m_context;
 };
 
diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp
index 58db1e95025..dfc11d7665e 100644
--- a/src/plugins/projectexplorer/projectwizardpage.cpp
+++ b/src/plugins/projectexplorer/projectwizardpage.cpp
@@ -29,27 +29,17 @@
 
 #include "projectwizardpage.h"
 #include "ui_projectwizardpage.h"
-#include "projectnodes.h"
 
-#include <utils/stringutils.h>
-
-#include <QtCore/QDebug>
-#include <QtCore/QFileInfo>
 #include <QtCore/QTextStream>
 
 using namespace ProjectExplorer;
 using namespace Internal;
 
-Q_DECLARE_METATYPE(ProjectExplorer::ProjectNode*)
-
 ProjectWizardPage::ProjectWizardPage(QWidget *parent) :
     QWizardPage(parent),
     m_ui(new Ui::WizardPage)
 {
     m_ui->setupUi(this);
-
-    connect(m_ui->addToProjectCheckBox, SIGNAL(toggled(bool)),
-            m_ui->projectComboBox, SLOT(setEnabled(bool)));
 }
 
 ProjectWizardPage::~ProjectWizardPage()
@@ -57,63 +47,36 @@ ProjectWizardPage::~ProjectWizardPage()
     delete m_ui;
 }
 
-void ProjectWizardPage::setProjects(const QList<ProjectNode*> &projectNodes)
+void ProjectWizardPage::setProjects(const QStringList &p)
 {
-    QMap<QString,ProjectNode*> projectMap;
-    foreach (ProjectNode *node, projectNodes) {
-        QString name = QFileInfo(node->path()).fileName();
-        if (!projectMap.contains(name))
-            projectMap.insert(name, node);
-    }
-
     m_ui->projectComboBox->clear();
-    foreach (const QString &name, projectMap.keys()) {
-        m_ui->projectComboBox->addItem(name, qVariantFromValue(projectMap.value(name)));
-    }
-}
-
-void ProjectWizardPage::setAddToProjectEnabled(bool b)
-{
-    m_ui->projectLabel->setEnabled(b);
-    m_ui->addToProjectLabel->setEnabled(b);
-    m_ui->addToProjectCheckBox->setChecked(b);
-    m_ui->addToProjectCheckBox->setEnabled(b);
-    m_ui->projectComboBox->setEnabled(b);
+    m_ui->projectComboBox->addItems(p);
 }
 
-ProjectNode *ProjectWizardPage::currentProject() const
+int ProjectWizardPage::currentProjectIndex() const
 {
-    QVariant variant = m_ui->projectComboBox->itemData(m_ui->projectComboBox->currentIndex());
-    return qVariantValue<ProjectNode*>(variant);
+    return m_ui->projectComboBox->currentIndex();
 }
 
-void ProjectWizardPage::setCurrentProject(ProjectNode *projectNode)
+void ProjectWizardPage::setCurrentProjectIndex(int idx)
 {
-    if (!projectNode)
-        return;
-    for (int i = 0; i < m_ui->projectComboBox->count(); ++i) {
-        if (qVariantValue<ProjectNode*>(m_ui->projectComboBox->itemData(i)) == projectNode) {
-            m_ui->projectComboBox->setCurrentIndex(i);
-            return;
-        }
-    }
+    m_ui->projectComboBox->setCurrentIndex(idx);
 }
 
-bool ProjectWizardPage::addToProject() const
+void ProjectWizardPage::setVersionControls(const QStringList &vcs)
 {
-    return m_ui->addToProjectCheckBox->isChecked();
+    m_ui->addToVersionControlComboBox->clear();
+    m_ui->addToVersionControlComboBox->addItems(vcs);
 }
 
-bool ProjectWizardPage::addToVersionControl() const
+int ProjectWizardPage::versionControlIndex() const
 {
-    return m_ui->addToVersionControlCheckBox->isChecked();
+    return m_ui->addToVersionControlComboBox->currentIndex();
 }
 
-void ProjectWizardPage::setAddToVersionControlEnabled(bool b)
+void ProjectWizardPage::setVersionControlIndex(int idx)
 {
-    m_ui->addToVersionControlLabel->setEnabled(b);
-    m_ui->addToVersionControlCheckBox->setChecked(b);
-    m_ui->addToVersionControlCheckBox->setEnabled(b);
+    m_ui->addToVersionControlComboBox->setCurrentIndex(idx);
 }
 
 void ProjectWizardPage::changeEvent(QEvent *e)
@@ -128,15 +91,9 @@ void ProjectWizardPage::changeEvent(QEvent *e)
     }
 }
 
-void ProjectWizardPage::setVCSDisplay(const QString &vcsName)
-{
-    m_ui->addToVersionControlLabel->setText(tr("Add to &VCS (%1)").arg(vcsName));
-}
-
-void ProjectWizardPage::setFilesDisplay(const QStringList &files)
+void ProjectWizardPage::setFilesDisplay(const QString &commonPath, const QStringList &files)
 {
     QString fileMessage;
-    const QString commonPath = Utils::commonPath(files);
     {
         QTextStream str(&fileMessage);
         str << "<qt>"
diff --git a/src/plugins/projectexplorer/projectwizardpage.h b/src/plugins/projectexplorer/projectwizardpage.h
index 021b2a4bb5e..5751d1516b0 100644
--- a/src/plugins/projectexplorer/projectwizardpage.h
+++ b/src/plugins/projectexplorer/projectwizardpage.h
@@ -32,16 +32,7 @@
 
 #include <QtGui/QWizardPage>
 
-namespace Core {
-    class IVersionControl;
-    class SCCManager;
-    class FileManager;
-}
-
 namespace ProjectExplorer {
-
-class ProjectNode;
-
 namespace Internal {
 
 namespace Ui {
@@ -55,19 +46,17 @@ public:
     explicit ProjectWizardPage(QWidget *parent = 0);
     virtual ~ProjectWizardPage();
 
-    void setProjects(const QList<ProjectNode *> &);
-    void setCurrentProject(ProjectNode *);
-
-    ProjectNode *currentProject() const;
+    void setProjects(const QStringList &);
+    int currentProjectIndex() const;
+    void setCurrentProjectIndex(int);
 
-    void setAddToProjectEnabled(bool b);
-    bool addToProject() const;
+    void setVersionControls(const QStringList &);
 
-    bool addToVersionControl() const;
-    void setAddToVersionControlEnabled(bool b);
+    int versionControlIndex() const;
+    void setVersionControlIndex(int);
 
-    void setVCSDisplay(const QString &vcsName);
-    void setFilesDisplay(const QStringList &files);
+    // Returns the common path
+    void setFilesDisplay(const QString &commonPath, const QStringList &files);
 
 protected:
     virtual void changeEvent(QEvent *e);
diff --git a/src/plugins/projectexplorer/projectwizardpage.ui b/src/plugins/projectexplorer/projectwizardpage.ui
index 89d15be8683..22dc2f3fbe7 100644
--- a/src/plugins/projectexplorer/projectwizardpage.ui
+++ b/src/plugins/projectexplorer/projectwizardpage.ui
@@ -20,44 +20,43 @@
       <enum>QFormLayout::ExpandingFieldsGrow</enum>
      </property>
      <item row="0" column="0">
-      <widget class="QLabel" name="addToProjectLabel">
+      <widget class="QLabel" name="projectLabel">
        <property name="text">
-        <string>&amp;Add to Project</string>
+        <string>Add to &amp;project:</string>
        </property>
        <property name="buddy">
-        <cstring>addToProjectCheckBox</cstring>
+        <cstring>projectComboBox</cstring>
        </property>
       </widget>
      </item>
      <item row="0" column="1">
-      <widget class="QCheckBox" name="addToProjectCheckBox"/>
+      <widget class="QComboBox" name="projectComboBox">
+       <item>
+        <property name="text">
+         <string notr="true">A very long project name indeed</string>
+        </property>
+       </item>
+      </widget>
      </item>
      <item row="1" column="0">
-      <widget class="QLabel" name="projectLabel">
+      <widget class="QLabel" name="addToVersionControlLabel">
        <property name="text">
-        <string>&amp;Project</string>
+        <string>Add to &amp;version control:</string>
        </property>
        <property name="buddy">
-        <cstring>projectComboBox</cstring>
+        <cstring>addToVersionControlComboBox</cstring>
        </property>
       </widget>
      </item>
      <item row="1" column="1">
-      <widget class="QComboBox" name="projectComboBox"/>
-     </item>
-     <item row="2" column="0">
-      <widget class="QLabel" name="addToVersionControlLabel">
-       <property name="text">
-        <string>Add to &amp;version control</string>
-       </property>
-       <property name="buddy">
-        <cstring>addToVersionControlCheckBox</cstring>
-       </property>
+      <widget class="QComboBox" name="addToVersionControlComboBox">
+       <item>
+        <property name="text">
+         <string notr="true">A very long version control system name</string>
+        </property>
+       </item>
       </widget>
      </item>
-     <item row="2" column="1">
-      <widget class="QCheckBox" name="addToVersionControlCheckBox"/>
-     </item>
     </layout>
    </item>
    <item>
@@ -96,7 +95,7 @@
         <x>0</x>
         <y>0</y>
         <width>611</width>
-        <height>305</height>
+        <height>328</height>
        </rect>
       </property>
       <layout class="QVBoxLayout" name="verticalLayout_2">
diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp
index a3913fe561b..f8b795e5f48 100644
--- a/src/plugins/subversion/subversioncontrol.cpp
+++ b/src/plugins/subversion/subversioncontrol.cpp
@@ -54,6 +54,7 @@ bool SubversionControl::supportsOperation(Operation operation) const
     case DeleteOperation:
         break;
     case OpenOperation:
+    case CreateRepositoryOperation:
         rc = false;
         break;
     }
@@ -78,6 +79,11 @@ bool SubversionControl::vcsDelete(const QString &fileName)
     return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
 }
 
+bool SubversionControl::vcsCreateRepository(const QString &)
+{
+    return false;
+}
+
 bool SubversionControl::managesDirectory(const QString &directory) const
 {
     return m_plugin->managesDirectory(directory);
diff --git a/src/plugins/subversion/subversioncontrol.h b/src/plugins/subversion/subversioncontrol.h
index 99512e53f71..5aa60373ace 100644
--- a/src/plugins/subversion/subversioncontrol.h
+++ b/src/plugins/subversion/subversioncontrol.h
@@ -52,6 +52,7 @@ public:
     virtual bool vcsOpen(const QString &fileName);
     virtual bool vcsAdd(const QString &fileName);
     virtual bool vcsDelete(const QString &filename);
+    virtual bool vcsCreateRepository(const QString &directory);
 
     void emitRepositoryChanged(const QString &);
     void emitFilesChanged(const QStringList &);
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index f0ccf0f6d06..2cab3832665 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -528,7 +528,7 @@ SubversionSubmitEditor *SubversionPlugin::openSubversionSubmitEditor(const QStri
 
 void SubversionPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
 {
-    if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction))
+    if (!enableMenuAction(as, m_menuAction))
         return;
 
     m_logRepositoryAction->setEnabled(currentState().hasTopLevel());
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index b672fba110a..0cb54a70087 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -47,6 +47,8 @@
 
 #include <QtGui/QAction>
 #include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMainWindow>
 
 enum { debug = 0 };
 
@@ -345,6 +347,8 @@ VCSBASE_EXPORT QDebug operator<<(QDebug in, const VCSBasePluginState &state)
 struct VCSBasePluginPrivate {
     explicit VCSBasePluginPrivate(const QString &submitEditorId);
 
+    inline bool supportsRepositoryCreation() const;
+
     const QString m_submitEditorId;
     Core::IVersionControl *m_versionControl;
     VCSBasePluginState m_state;
@@ -360,6 +364,11 @@ VCSBasePluginPrivate::VCSBasePluginPrivate(const QString &submitEditorId) :
 {
 }
 
+bool VCSBasePluginPrivate::supportsRepositoryCreation() const
+{
+    return m_versionControl && m_versionControl->supportsOperation(Core::IVersionControl::CreateRepositoryOperation);
+}
+
 Internal::StateListener *VCSBasePluginPrivate::m_listener = 0;
 
 VCSBasePlugin::VCSBasePlugin(const QString &submitEditorId) :
@@ -427,15 +436,17 @@ const VCSBasePluginState &VCSBasePlugin::currentState() const
     return d->m_state;
 }
 
-bool VCSBasePlugin::enableMenuAction(ActionState as, QAction *menuAction)
+bool VCSBasePlugin::enableMenuAction(ActionState as, QAction *menuAction) const
 {
     if (debug)
         qDebug() << "enableMenuAction" << menuAction->text() << as;
     switch (as) {
-    case VCSBase::VCSBasePlugin::NoVCSEnabled:
+    case VCSBase::VCSBasePlugin::NoVCSEnabled: {
+        const bool supportsCreation = d->supportsRepositoryCreation();
         menuAction->setVisible(true);
-        menuAction->setEnabled(false);
-        return false;
+        menuAction->setEnabled(supportsCreation);
+        return supportsCreation;
+    }
     case VCSBase::VCSBasePlugin::OtherVCSEnabled:
         menuAction->setVisible(false);
         return false;
@@ -456,6 +467,46 @@ void VCSBasePlugin::promptToDeleteCurrentFile()
         QMessageBox::warning(0, tr("Version Control"), tr("The file '%1' could not be deleted.").arg(state.currentFile()), QMessageBox::Ok);
 }
 
+static inline bool ask(QWidget *parent, const QString &title, const QString &question, bool defaultValue = true)
+
+{
+    const QMessageBox::StandardButton defaultButton = defaultValue ? QMessageBox::Yes : QMessageBox::No;
+    return QMessageBox::question(parent, title, question, QMessageBox::Yes|QMessageBox::No, defaultButton) == QMessageBox::Yes;
+}
+
+void VCSBasePlugin::createRepository()
+{
+    QTC_ASSERT(d->m_versionControl->supportsOperation(Core::IVersionControl::CreateRepositoryOperation), return);
+    // Find current starting directory
+    QString directory;
+    if (const ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectExplorerPlugin::instance()->currentProject())
+        directory = QFileInfo(currentProject->file()->fileName()).absolutePath();
+    // Prompt for a directory that is not under version control yet
+    QMainWindow *mw = Core::ICore::instance()->mainWindow();
+    do {
+        directory = QFileDialog::getExistingDirectory(mw, tr("Choose repository directory"), directory);
+        if (directory.isEmpty())
+            return;
+        const Core::IVersionControl *managingControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(directory);
+        if (managingControl == 0)
+            break;
+        const QString question = tr("The directory '%1' is already managed by a version control system (%2)."
+                                    " Would you like to specify another directory?").arg(directory, managingControl->displayName());
+
+        if (!ask(mw, tr("Repository already under version control"), question))
+            return;
+    } while (true);
+    // Create
+    const bool rc = d->m_versionControl->vcsCreateRepository(directory);
+    if (rc) {
+        QMessageBox::information(mw, tr("Repository created"),
+                                 tr("A version control repository has been created in %1.").arg(directory));
+    } else {
+        QMessageBox::warning(mw, tr("Repository creation failed"),
+                                 tr("A version control repository could not be created in %1.").arg(directory));
+    }
+}
+
 } // namespace VCSBase
 
 #include "vcsbaseplugin.moc"
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index c5760032aa1..a9351ed4703 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -153,6 +153,9 @@ public slots:
     // Convenience slot for "Delete current file" action. Prompts to
     // delete the file via VCSManager.
     void promptToDeleteCurrentFile();
+    // Prompt to initalize version control in a directory, initially
+    // pointing to the current project.
+    void createRepository();
 
 protected:
     enum ActionState { NoVCSEnabled, OtherVCSEnabled, VCSEnabled };
@@ -163,9 +166,11 @@ protected:
     virtual bool submitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor) = 0;
 
     // A helper to enable the VCS menu action according to state:
-    // NoVCSEnabled->(visible,disabled), OtherVCSEnabled->(invisible), else
-    // enabled. Returns whether actions should be set up further.
-    static bool enableMenuAction(ActionState as, QAction *in);
+    // NoVCSEnabled    -> visible, enabled if repository creation is supported
+    // OtherVCSEnabled -> invisible
+    // Else:           -> fully enabled.
+    // Returns whether actions should be set up further.
+    bool enableMenuAction(ActionState as, QAction *in) const;
 
 private slots:
     void slotSubmitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor, bool *result);
-- 
GitLab