- Snapcraft support plan step 2

-> support snapcraft.yaml as project format
-> build snap files directly from the IDE
-> basic template
-> support building in containers
This commit is contained in:
Benjamin Zeller
2016-10-18 09:45:16 +02:00
parent 3b4b3b088b
commit b9f0a79f10
36 changed files with 1923 additions and 72 deletions

View File

@@ -64,7 +64,11 @@ add_custom_target(QtCreatorSource
COMMAND ${CMAKE_SOURCE_DIR}/get_bzr_source.py -d "${EXT_SOURCE_DIR}/qtcreator/src/plugins/ubuntu" lp:qtcreator-plugin-ubuntu
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_custom_target(sources DEPENDS QtSource LibDusSource MaliitSource fcitx-qtSource AppmenuSource QtCreatorSource)
add_custom_target(YamlCppSource
${CMAKE_SOURCE_DIR}/get_package_source.py yaml-cpp
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_custom_target(sources DEPENDS QtSource LibDusSource MaliitSource fcitx-qtSource AppmenuSource QtCreatorSource YamlCppSource)
add_custom_command(TARGET sources
PRE_BUILD
@@ -123,6 +127,29 @@ ExternalProject_Add(libdbusmenu-qt
INSTALL_COMMAND sh -c "LD_LIBRARY_PATH=${QT_INSTALL_DIR}/lib make install"
)
ConcatStrings (LIBYAML_BUILD_SCRIPT
"${CMAKE_COMMAND} "
"-DCMAKE_INSTALL_PREFIX=${QT_INSTALL_DIR} "
"-DCMAKE_PREFIX_PATH=${QT_INSTALL_DIR} "
"-DCMAKE_BUILD_TYPE=DEBUG" #${CMAKE_BUILD_TYPE_STRING} "
"-DCMAKE_INSTALL_LIBDIR=lib ${EXT_SOURCE_DIR}/yaml-cpp "
"-DCMAKE_C_FLAGS=-fPIC "
"-DCMAKE_CXX_FLAGS=-fPIC "
)
SET (LIBYAML_PREFIX "${CMAKE_BINARY_DIR}/yaml-cpp")
ExternalProject_Add(libyaml-cpp
DEPENDS ${QT_VERSION}
PREFIX "${LIBYAML_PREFIX}"
SOURCE_DIR "${EXT_SOURCE_DIR}/yaml-cpp"
BINARY_DIR "${LIBYAML_PREFIX}/build"
INSTALL_DIR "${QT_INSTALL_DIR}"
DOWNLOAD_COMMAND sh -c "exit 0"
CONFIGURE_COMMAND sh -c "${LIBYAML_BUILD_SCRIPT}"
BUILD_COMMAND sh -c "LD_LIBRARY_PATH=${QT_INSTALL_DIR}/lib make ${GENERATED_MAKE_FLAGS}"
INSTALL_COMMAND sh -c "LD_LIBRARY_PATH=${QT_INSTALL_DIR}/lib make install"
)
SET (MALIITPLUGIN_PREFIX "${CMAKE_BINARY_DIR}/maliit-plugin-qt-build")
ExternalProject_Add(maliit-plugin
DEPENDS ${QT_VERSION}
@@ -172,7 +199,7 @@ ExternalProject_Add(appmenu-qt5
SET (QTCREATOR_PREFIX "${CMAKE_BINARY_DIR}/qtcreator-build")
ExternalProject_Add(qtcreator_3.5.0
DEPENDS appmenu-qt5 fcitx-qt5 maliit-plugin
DEPENDS appmenu-qt5 fcitx-qt5 maliit-plugin libyaml-cpp
PREFIX "${QTCREATOR_PREFIX}"
SOURCE_DIR "${EXT_SOURCE_DIR}/qtcreator"
BINARY_DIR "${QTCREATOR_PREFIX}/build"

View File

@@ -220,6 +220,8 @@ HEADERS += \
src/ubuntu/device/remote/ubuntudirectuploadstep.h \
src/ubuntu/device/remote/ubuntudeploystepfactory.h
include(src/ubuntu/snap/snap.pri)
FORMS += \
src/ubuntu/device/remote/ubunturemoterunconfigurationwidget.ui \

View File

@@ -1,32 +0,0 @@
# This is the basic qmake template for the Ubuntu-SDK
# it handles creation and installation of the manifest
# file and takes care of subprojects
TEMPLATE = subdirs
SUBDIRS += %{ProjectNameL}
# enables/disabled the extra targets to build a snapcraft package
# also tells the IDE this is a snapcraft project
CONFIG += snapcraft
snapcraft {
SNAPCRAFT_FILE=snapcraft.yaml
#the Ubuntu SDK IDE uses the snap target to create the package
snappy.target = snap
snappy.commands = cd $$OUT_PWD
snappy.commands += && rm -rf \'$$OUT_PWD/snap-deploy\'
snappy.commands += && make INSTALL_ROOT=$$OUT_PWD/snap-deploy install
snappy.commands += && cd $$OUT_PWD/snap-deploy
snappy.commands += && snapcraft
OTHER_FILES+=$$SNAPCRAFT_FILE
QMAKE_EXTRA_TARGETS += snappy
packaging.files = $$SNAPCRAFT_FILE
packaging.path = /
INSTALLS+=packaging
}

View File

@@ -16,33 +16,16 @@ QML_FILES += $$files(*.qml,true) \
CONF_FILES += %{ProjectNameL}.png
AP_TEST_FILES += tests/autopilot/run \
$$files(tests/*.py,true)
#show all the files in QtCreator
OTHER_FILES += $${CONF_FILES} \
$${QML_FILES} \
$${AP_TEST_FILES} \
%{ProjectNameL}.desktop \
%{ProjectNameL}.wrapper
snapcraft {
#specify where the config files are installed to
config_files.path = /setup/gui
config_files.files += $${CONF_FILES}
INSTALLS+=config_files
#install the desktop file
desktop_file.path = /setup/gui
desktop_file.files = $$PWD/%{ProjectNameL}.desktop
desktop_file.CONFIG += no_check_exist
INSTALLS+=desktop_file
# Default rules for deployment.
wrapper.files = %{ProjectNameL}.wrapper
wrapper.path = /deploy/bin
wrapper.path = /bin
target.path = /deploy/bin
target.path = /bin
INSTALLS+=target wrapper
}

View File

@@ -11,13 +11,19 @@ apps:
parts:
%{ProjectNameL}:
plugin: dump
source: deploy/
plugin: qmake
source: %{ProjectNameL}/
qt-version: qt5
options: ["CONFIG+=snapcraft"]
project-files: [%{ProjectNameL}]
build-packages:
- build-essential
- qtbase5-dev
- qt5-qmake
stage-packages:
- ubuntu-sdk-libs
- qtubuntu-desktop
- qtmir-desktop
- mir-graphics-drivers-desktop
after: [qt5conf]

View File

@@ -1,13 +1,13 @@
{
"version": 1,
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
"supportedProjectTypes": [ "SnapcraftProjectManager.SnapcraftProject" ],
"id": "A.QtQuick Snappy Application",
"category": "B.Snapcraft",
"trDescription": "Creates a experimental C++ Ubuntu snappy application project with a sample UI containing a Label and a Button.",
"trDisplayName": "QtQuick App with QML Ubuntu UI",
"trDisplayCategory": "Snapcraft",
"icon": "../share/ubuntu.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
"enabled": "%{JS: [ %{Plugins} ].indexOf('Ubuntu') >= 0}",
"options":
[
@@ -61,14 +61,9 @@
"typeId": "File",
"data":
[
{
"source": "appName.pro",
"target": "%{ProjectFile}",
"openAsProject": true
},
{
"source": "snapcraft.yaml",
"openInEditor": true
"openAsProject": true
},
{
"source": "appName/main.cpp",
@@ -81,12 +76,12 @@
"openInEditor": true
},
{
"source": "appName/appName.desktop",
"target": "%{ProjectDirectory}/%{ProjectNameL}/%{ProjectNameL}.desktop"
"source": "setup/gui/appName.desktop",
"target": "%{ProjectDirectory}/setup/gui/%{ProjectNameL}.desktop"
},
{
"source": "appName/appName.png",
"target": "%{ProjectDirectory}/%{ProjectNameL}/%{ProjectNameL}.png"
"source": "setup/gui/appName.png",
"target": "%{ProjectDirectory}/setup/gui/%{ProjectNameL}.png"
},
{
"source": "appName/appName.pro",

View File

@@ -0,0 +1,29 @@
#!/usr/bin/python3
import os
import sys
import shutil
import subprocess
from optparse import OptionParser
parser = OptionParser(usage="usage: %prog [options] lp:branch")
parser.add_option(
"-s", "--snapcraft", dest="snapcraft")
options, args = parser.parse_args()
if options.snapcraft is None:
options.snapcraft = shutil.which("snapcraft")
if options.snapcraft is None:
parser.error("Snapcraft not found.")
if not os.path.isfile(options.snapcraft) or not os.access(options.snapcraft, os.X_OK):
parser.error("-s must specify a executable file.")
print("Using snapcraft from :"+options.snapcraft)
ret = subprocess.call([options.snapcraft, "clean"])
if ret != 0:
sys.exit(ret)
sys.exit(subprocess.call([options.snapcraft]+args))

View File

@@ -17,4 +17,9 @@
<sub-class-of type="application/json"/>
<glob pattern="manifest.json*"/>
</mime-type>
<mime-type type="application/x-snapcraft">
<comment>Snapcraft project file</comment>
<sub-class-of type="application/x-yaml"/>
<glob pattern="snapcraft.yaml"/>
</mime-type>
</mime-info>

View File

@@ -0,0 +1,41 @@
#include "snapcraftbuildconfiguration.h"
#include <ubuntu/ubuntuconstants.h>
namespace Ubuntu {
namespace Internal {
SnapcraftBuildConfiguration::SnapcraftBuildConfiguration(ProjectExplorer::Target *target)
: ProjectExplorer::BuildConfiguration(target, Constants::SNAPCRAFT_BUILDCONFIGURATION_ID)
{
}
SnapcraftBuildConfiguration::SnapcraftBuildConfiguration(ProjectExplorer::Target *target, ProjectExplorer::BuildConfiguration *source)
: ProjectExplorer::BuildConfiguration(target, source)
{
}
bool SnapcraftBuildConfiguration::fromMap(const QVariantMap &map)
{
return ProjectExplorer::BuildConfiguration::fromMap(map);
}
QVariantMap SnapcraftBuildConfiguration::toMap() const
{
return ProjectExplorer::BuildConfiguration::toMap();
}
ProjectExplorer::NamedWidget *SnapcraftBuildConfiguration::createConfigWidget()
{
return nullptr;
}
ProjectExplorer::BuildConfiguration::BuildType SnapcraftBuildConfiguration::buildType() const
{
return ProjectExplorer::BuildConfiguration::Unknown;
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,33 @@
#ifndef UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATION_H
#define UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATION_H
#include <projectexplorer/buildconfiguration.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftBuildConfigurationFactory;
class SnapcraftBuildConfiguration : public ProjectExplorer::BuildConfiguration
{
Q_OBJECT
public:
friend class SnapcraftBuildConfigurationFactory;
// ProjectConfiguration interface
virtual bool fromMap(const QVariantMap &map) override;
virtual QVariantMap toMap() const override;
// BuildConfiguration interface
virtual ProjectExplorer::NamedWidget *createConfigWidget() override;
virtual BuildType buildType() const override;
protected:
SnapcraftBuildConfiguration(ProjectExplorer::Target *target);
SnapcraftBuildConfiguration(ProjectExplorer::Target *target, BuildConfiguration *source);
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATION_H

View File

@@ -0,0 +1,145 @@
#include "snapcraftbuildconfigurationfactory.h"
#include "snapcraftproject.h"
#include "snapcraftbuildconfiguration.h"
#include "snapcraftrsyncstep.h"
#include "snapcraftstep.h"
#include <ubuntu/ubuntuconstants.h>
#include <projectexplorer/target.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/projectmacroexpander.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/buildsteplist.h>
#include <coreplugin/documentmanager.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
namespace Ubuntu {
namespace Internal {
SnapcraftBuildInfo::SnapcraftBuildInfo(const SnapcraftBuildConfigurationFactory *factory)
:ProjectExplorer::BuildInfo(factory)
{
}
SnapcraftBuildConfigurationFactory::SnapcraftBuildConfigurationFactory()
{
}
QList<ProjectExplorer::BuildInfo *> SnapcraftBuildConfigurationFactory::availableBuilds(const ProjectExplorer::Target *parent) const
{
if (qobject_cast<SnapcraftProject *>(parent->project()))
return {};
QList<ProjectExplorer::BuildInfo *> infoList;
ProjectExplorer::BuildInfo *info = createBuildInfo(parent->kit(), parent->project()->projectFilePath().toString());
if (info)
infoList << info;
return infoList;
}
int SnapcraftBuildConfigurationFactory::priority(const ProjectExplorer::Target *) const
{
return 0;
}
int SnapcraftBuildConfigurationFactory::priority(const ProjectExplorer::Kit *, const QString &) const
{
return 0;
}
QList<ProjectExplorer::BuildInfo *> SnapcraftBuildConfigurationFactory::availableSetups(const ProjectExplorer::Kit *k, const QString &projectPath) const
{
Utils::MimeDatabase db;
auto mimeType = db.mimeTypeForFile(projectPath);
if (!mimeType.matchesName(Constants::SNAPCRAFT_PROJECT_MIMETYPE))
return {};
QList<ProjectExplorer::BuildInfo *> infoList;
ProjectExplorer::BuildInfo *info = createBuildInfo(k, projectPath);
if (info)
infoList << info;
return infoList;
}
ProjectExplorer::BuildConfiguration *SnapcraftBuildConfigurationFactory::create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const
{
SnapcraftBuildConfiguration *conf = new SnapcraftBuildConfiguration(parent);
conf->setDisplayName(info->displayName);
conf->setBuildDirectory(info->buildDirectory);
ProjectExplorer::BuildStepList *bs = conf->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
bs->insertStep(0, new SnapcraftRsyncStep(bs));
bs->insertStep(1, new SnapcraftStep(bs));
return conf;
}
bool SnapcraftBuildConfigurationFactory::canRestore(const ProjectExplorer::Target *, const QVariantMap &map) const
{
return (ProjectExplorer::idFromMap(map) == Constants::SNAPCRAFT_BUILDCONFIGURATION_ID);
}
ProjectExplorer::BuildConfiguration *SnapcraftBuildConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map)
{
QTC_ASSERT(parent, return nullptr);
SnapcraftBuildConfiguration *conf = new SnapcraftBuildConfiguration(parent);
if (conf->fromMap(map))
return conf;
delete conf;
return nullptr;
}
bool SnapcraftBuildConfigurationFactory::canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) const
{
QTC_ASSERT(parent, return false);
QTC_ASSERT(product, return false);
return (product->id() == Constants::SNAPCRAFT_BUILDCONFIGURATION_ID);
}
ProjectExplorer::BuildConfiguration *SnapcraftBuildConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product)
{
QTC_ASSERT(parent, return nullptr);
QTC_ASSERT(product, return nullptr);
SnapcraftBuildConfiguration *conf = new SnapcraftBuildConfiguration(parent, product);
return conf;
}
ProjectExplorer::BuildInfo *SnapcraftBuildConfigurationFactory::createBuildInfo(const ProjectExplorer::Kit *k, const QString &projectPath) const
{
SnapcraftBuildInfo *build = new SnapcraftBuildInfo(this);
build->buildType = ProjectExplorer::BuildConfiguration::Release;
build->typeName = tr("Build");
build->kitId = k->id();
build->displayName = ProjectExplorer::BuildConfiguration::buildTypeName(build->buildType);
build->buildDirectory = shadowBuildDirectory(k, projectPath);
return {build};
}
Utils::FileName SnapcraftBuildConfigurationFactory::shadowBuildDirectory(const ProjectExplorer::Kit *k, const QString &projectPath) const
{
Utils::FileName projectDir = ProjectExplorer::Project::projectDirectory(Utils::FileName::fromString(projectPath));
const QString projectName = projectDir.fileName();
ProjectExplorer::ProjectMacroExpander expander(projectPath, projectName,
k, tr("build"),
ProjectExplorer::BuildConfiguration::Release);
QString buildPath = expander.expand(Core::DocumentManager::buildDirectory());
return Utils::FileName::fromString(QDir::cleanPath(QDir(projectDir.toString()).absoluteFilePath(buildPath)));
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,44 @@
#ifndef UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATIONFACTORY_H
#define UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATIONFACTORY_H
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildinfo.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftBuildConfigurationFactory;
class SnapcraftBuildInfo : public ProjectExplorer::BuildInfo
{
public:
SnapcraftBuildInfo(const SnapcraftBuildConfigurationFactory *factory);
};
class SnapcraftBuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
{
public:
SnapcraftBuildConfigurationFactory();
// IBuildConfigurationFactory interface
virtual QList<ProjectExplorer::BuildInfo *> availableBuilds(const ProjectExplorer::Target *parent) const override;
virtual int priority(const ProjectExplorer::Target *parent) const override;
virtual int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const override;
virtual QList<ProjectExplorer::BuildInfo *> availableSetups(const ProjectExplorer::Kit *k, const QString &projectPath) const override;
virtual ProjectExplorer::BuildConfiguration *create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const override;
virtual bool canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const override;
virtual ProjectExplorer::BuildConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map) override;
virtual bool canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) const override;
virtual ProjectExplorer::BuildConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) override;
private:
ProjectExplorer::BuildInfo *createBuildInfo (const ProjectExplorer::Kit *k, const QString &projectPath) const;
Utils::FileName shadowBuildDirectory(const ProjectExplorer::Kit *k, const QString &projectPath) const;
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATIONFACTORY_H

View File

@@ -0,0 +1,65 @@
#include "snapcraftbuildstepfactory.h"
#include "snapcraftrsyncstep.h"
#include "snapcraftstep.h"
#include "snapcraftproject.h"
#include <ubuntu/ubuntuconstants.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/target.h>
#include <utils/algorithm.h>
namespace Ubuntu {
namespace Internal {
SnapcraftBuildStepFactory::SnapcraftBuildStepFactory(QObject *parent) : ProjectExplorer::IBuildStepFactory (parent)
{
}
QList<ProjectExplorer::BuildStepInfo> SnapcraftBuildStepFactory::availableSteps(ProjectExplorer::BuildStepList *parent) const
{
if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD)
return {};
if (!parent->target() || !qobject_cast<SnapcraftProject *>(parent->target()->project()))
return {};
return {
ProjectExplorer::BuildStepInfo(Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID, tr("Prepare build")),
ProjectExplorer::BuildStepInfo(Constants::SNAPCRAFT_BUILDSTEP_ID, tr("Snapcraft"))
};
}
ProjectExplorer::BuildStep *SnapcraftBuildStepFactory::create(ProjectExplorer::BuildStepList *parent, Core::Id id)
{
if (!Utils::contains(availableSteps(parent), [&id](const ProjectExplorer::BuildStepInfo &step){return id == step.id;}))
return nullptr;
if (id == Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID) {
return new SnapcraftRsyncStep(parent);
} else if (id == Constants::SNAPCRAFT_BUILDSTEP_ID) {
return new SnapcraftStep(parent);
}
return nullptr;
}
ProjectExplorer::BuildStep *SnapcraftBuildStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
{
Core::Id id = product->id();
if (!Utils::contains(availableSteps(parent), [&id](const ProjectExplorer::BuildStepInfo &step){return id == step.id;}))
return nullptr;
if (id == Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID) {
return new SnapcraftRsyncStep(parent, static_cast<SnapcraftRsyncStep *>(product));
} else if (id == Constants::SNAPCRAFT_BUILDSTEP_ID) {
return new SnapcraftStep(parent, static_cast<SnapcraftStep *>(product));
}
return nullptr;
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,25 @@
#ifndef UBUNTU_INTERNAL_SNAPCRAFTBUILDSTEPFACTORY_H
#define UBUNTU_INTERNAL_SNAPCRAFTBUILDSTEPFACTORY_H
#include <projectexplorer/buildstep.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftBuildStepFactory : public ProjectExplorer::IBuildStepFactory
{
Q_OBJECT
public:
SnapcraftBuildStepFactory(QObject *parent = nullptr);
// IBuildStepFactory interface
public:
virtual QList<ProjectExplorer::BuildStepInfo> availableSteps(ProjectExplorer::BuildStepList *parent) const override;
virtual ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id) override;
virtual ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) override;
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTBUILDSTEPFACTORY_H

View File

@@ -0,0 +1,156 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#include "snapcraftproject.h"
#include "snapcraftprojectnode.h"
#include <coreplugin/modemanager.h>
#include <coreplugin/icontext.h>
#include <coreplugin/documentmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectmacroexpander.h>
#include <qmljs/qmljssimplereader.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <yaml-cpp/yaml.h>
#pragma GCC diagnostic pop
using namespace Ubuntu;
using namespace Ubuntu::Internal;
SnapcraftProject::SnapcraftProject(SnapcraftProjectManager *manager, const Utils::FileName &fileName)
: m_manager(manager),
m_fileName(fileName),
m_watcher(new QFileSystemWatcher)
{
setId(Constants::SNAPCRAFT_PROJECT_ID);
setProjectContext(Core::Context(Constants::SNAPCRAFT_PROJECT_PROJECTCONTEXT));
m_file = QPointer<SnapcraftProjectFile>(new SnapcraftProjectFile());
Core::DocumentManager::addDocument(m_file.data(), true);
setDocument(m_file.data());
m_file->setFilePath(fileName);
m_rootNode = QSharedPointer<SnapcraftProjectNode>(new SnapcraftProjectNode(this, fileName, &m_watcher));
ProjectExplorer::FileNode *projectFileNode = new ProjectExplorer::FileNode(fileName, ProjectExplorer::ProjectFileType, false);
m_rootNode->addFileNodes({projectFileNode});
connect(m_file, &SnapcraftProjectFile::changed, this, &SnapcraftProject::asyncUpdate);
//we show magic directories that are not listed in the snapcraft.yaml file, therefore we need to watch the directory
//if one of those is changed or removed
m_watcher.addPath(projectDirectory().toFileInfo().absoluteFilePath());
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &SnapcraftProject::maybeUpdate);
QMetaObject::invokeMethod(this, "asyncUpdate", Qt::QueuedConnection);
}
QString SnapcraftProject::displayName() const {
return m_rootNode->displayName();
}
ProjectExplorer::IProjectManager *SnapcraftProject::projectManager() const {
return m_manager;
}
ProjectExplorer::ProjectNode *SnapcraftProject::rootProjectNode() const {
return m_rootNode.data();
}
QStringList SnapcraftProject::files(FilesMode) const {
QStringList files;
//enumChild(projectDir(), files);
return files;
}
bool SnapcraftProject::supportsKit(ProjectExplorer::Kit *, QString *) const
{
#if 0
UbuntuKitMatcher matcher;
if (!matcher.matches(k)) {
if(errorMessage)
*errorMessage = tr("Only Desktop and Ubuntu Kits are supported");
return false;
}
#endif
return true;
}
bool SnapcraftProject::needsConfiguration() const
{
return targets().size() == 0;
}
bool SnapcraftProject::requiresTargetPanel() const
{
return true;
}
QString SnapcraftProject::shadowBuildDirectory(const QString &proFilePath
, const ProjectExplorer::Kit *k
, const QString &suffix
, const ProjectExplorer::BuildConfiguration::BuildType buildType)
{
if (proFilePath.isEmpty())
return QString();
QFileInfo info(proFilePath);
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
if (version)
return info.absolutePath();
const QString projectName = QFileInfo(proFilePath).completeBaseName();
ProjectExplorer::ProjectMacroExpander expander(proFilePath, projectName, k, suffix, buildType);
QDir projectDir = QDir(projectDirectory(Utils::FileName::fromString(proFilePath)).toString());
QString buildPath = expander.expand(Core::DocumentManager::buildDirectory());
return QDir::cleanPath(projectDir.absoluteFilePath(buildPath));
}
void SnapcraftProject::asyncUpdate()
{
qDebug()<<"Syncing from yaml";
try {
YAML::Node yaml = YAML::LoadFile(m_fileName.toString().toStdString());
if (!m_rootNode->syncFromYAMLNode(yaml)) {
qDebug()<<"Invalid YAML file";
}
} catch (const YAML::Exception &e) {
qDebug() << e.what();
}
emit displayNameChanged();
}
void SnapcraftProject::maybeUpdate(const QString &pathChanged)
{
if (QFileInfo(pathChanged) == projectDirectory().toFileInfo()) {
asyncUpdate();
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#ifndef SNAPCRAFTPROJECT_H
#define SNAPCRAFTPROJECT_H
#include "snapcraftprojectmanager.h"
#include "snapcraftprojectfile.h"
#include <ubuntu/ubuntuconstants.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/project.h>
#include <QPointer>
#include <QFileSystemWatcher>
#include <yaml-cpp/node/node.h>
namespace Ubuntu {
namespace Internal {
class UbuntuProjectManager;
class SnapcraftProjectNode;
class SnapcraftProject : public ProjectExplorer::Project
{
Q_OBJECT
public:
SnapcraftProject(SnapcraftProjectManager *manager, const Utils::FileName &fileName);
QString displayName() const override;
ProjectExplorer::IProjectManager *projectManager() const override;
ProjectExplorer::ProjectNode *rootProjectNode() const override;
QStringList files(FilesMode fileMode) const override;
QDir projectDir() const {
return projectDirectory().toString();
}
QString filesFileName() const {
return m_fileName.toString();
}
// Project interface
bool supportsKit(ProjectExplorer::Kit *k, QString *errorMessage) const override;
bool needsConfiguration() const override;
bool requiresTargetPanel() const override;
static QString shadowBuildDirectory(const QString &proFilePath, const ProjectExplorer::Kit *k,
const QString &suffix = QString(),
const ProjectExplorer::BuildConfiguration::BuildType buildType = ProjectExplorer::BuildConfiguration::Unknown);
protected slots:
void asyncUpdate ();
void maybeUpdate (const QString &pathChanged);
private:
SnapcraftProjectManager *m_manager;
QString m_projectName;
QPointer<SnapcraftProjectFile> m_file;
Utils::FileName m_fileName;
QSharedPointer<SnapcraftProjectNode> m_rootNode;
QFileSystemWatcher m_watcher;
};
}
}
#endif // SNAPCRAFTPROJECT_H

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#include "snapcraftprojectfile.h"
using namespace Ubuntu::Internal;
SnapcraftProjectFile::SnapcraftProjectFile(Core::Id id)
: TextEditor::TextDocument(id)
{
}
Core::IDocument::ReloadBehavior SnapcraftProjectFile::reloadBehavior(Core::IDocument::ChangeTrigger state, Core::IDocument::ChangeType type) const
{
Q_UNUSED(state)
Q_UNUSED(type)
return BehaviorSilent;
}
bool SnapcraftProjectFile::reload(QString *errorString, Core::IDocument::ReloadFlag flag, Core::IDocument::ChangeType type)
{
if (type != TypePermissions) {
emit changed();
}
return TextDocument::reload(errorString, flag, type);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#ifndef SNAPCRAFTPROJECTFILE_H
#define SNAPCRAFTPROJECTFILE_H
#include <QObject>
#include <ubuntu/ubuntuconstants.h>
#include <texteditor/textdocument.h>
#include <utils/fileutils.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftProject;
class SnapcraftProjectFile : public TextEditor::TextDocument
{
Q_OBJECT
public:
SnapcraftProjectFile(Core::Id id = Core::Id());
// IDocument interface
virtual ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override;
virtual bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
signals:
void changed ();
};
}
}
#endif // SNAPCRAFTPROJECTFILE_H

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#include "snapcraftprojectmanager.h"
#include "snapcraftproject.h"
#include <ubuntu/ubuntuconstants.h>
#include <projectexplorer/session.h>
#include <coreplugin/idocument.h>
#include <utils/fileutils.h>
#include <QFileInfo>
namespace Ubuntu {
namespace Internal {
SnapcraftProjectManager::SnapcraftProjectManager()
{
}
QString SnapcraftProjectManager::mimeType() const
{
return QLatin1String(Constants::SNAPCRAFT_PROJECT_MIMETYPE);
}
ProjectExplorer::Project *SnapcraftProjectManager::openProject(const QString &fileName, QString *errorString)
{
QFileInfo fileInfo(fileName);
foreach (ProjectExplorer::Project *pi, ProjectExplorer::SessionManager::projects()) {
if (fileName == pi->document()->filePath().toString()) {
if (errorString)
*errorString = tr("Failed opening project '%1': Project already open") .arg(QDir::toNativeSeparators(fileName));
return 0;
}
}
if (fileInfo.isFile())
return new SnapcraftProject(this, Utils::FileName(fileInfo));
*errorString = tr("Failed opening project '%1': Project file is not a file").arg(QDir::toNativeSeparators(fileName));
return 0;
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#ifndef UBUNTU_INTERNAL_SNAPCRAFTPROJECTMANAGER_H
#define UBUNTU_INTERNAL_SNAPCRAFTPROJECTMANAGER_H
#include <projectexplorer/iprojectmanager.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftProjectManager : public ProjectExplorer::IProjectManager
{
public:
SnapcraftProjectManager();
// IProjectManager interface
virtual QString mimeType() const override;
virtual ProjectExplorer::Project *openProject(const QString &fileName, QString *errorString) override;
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTPROJECTMANAGER_H

View File

@@ -0,0 +1,496 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#include "snapcraftprojectnode.h"
#include <projectexplorer/nodesvisitor.h>
#include <coreplugin/fileiconprovider.h>
#include <ubuntu/ubuntuconstants.h>
#include <QFileInfo>
#include <QDir>
#include <QTimer>
#include <QFileSystemWatcher>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <yaml-cpp/yaml.h>
#pragma GCC diagnostic pop
namespace Ubuntu {
namespace Internal {
static QIcon generateIcon(const QString &overlay) {
const QSize desiredSize = QSize(16, 16);
const QPixmap overlayPixmap(overlay);
const QIcon overlayIcon(overlayPixmap.scaled(12, 12));
const QPixmap pixmap
= Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon, overlayIcon, desiredSize);
QIcon result;
result.addPixmap(pixmap);
return result;
}
static QIcon generateProjectIcon () {
static QIcon projectIcon;
if (projectIcon.isNull())
projectIcon = generateIcon(QString::fromLatin1(Constants::UBUNTU_ICON));
return projectIcon;
}
SnapcraftProjectNode::SnapcraftProjectNode(SnapcraftProject *rootProject, const Utils::FileName &projectFilePath, QFileSystemWatcher *watcher)
: ProjectExplorer::ProjectNode (projectFilePath),
m_rootProject(rootProject),
m_watcher(watcher)
{
setDisplayName(projectFilePath.parentDir().toString());
setIcon(generateProjectIcon());
}
SnapcraftProjectNode::~SnapcraftProjectNode()
{
if (m_watcher) {
}
}
bool SnapcraftProjectNode::syncFromYAMLNode(YAML::Node rootNode)
{
qDebug()<<"Sync from YAML node";
try {
QString displayName = QString::fromStdString(rootNode["name"].as<std::string>());
setDisplayName(displayName);
YAML::Node parts = rootNode["parts"];
if (!parts.IsMap()) {
qDebug()<<"Parts is not a map";
return false;
}
QList<ProjectExplorer::FolderNode *> existingNodes = subFolderNodes();
QList<ProjectExplorer::FolderNode *> nodesToRemove;
QList<ProjectExplorer::FolderNode *> nodesToAdd;
QStringList partsFromYaml;
QStringList existingParts;
for (const auto &part : existingNodes) {
existingParts << part->displayName();
}
//iterate over the parts
for (auto it = parts.begin(); it != parts.end(); ++it) {
YAML::Node subProject = it->second;
QString partName = QString::fromStdString(it->first.as<std::string>());
//QString subType = QString::fromStdString(subProject["plugin"].as<std::string>());
QString source = QDir::cleanPath(QString::fromStdString(subProject["source"].as<std::string>()));
partsFromYaml << partName;
// We only show a part if it locally exists and is a directory
QString sourcePathName = QDir::cleanPath(filePath().parentDir().appendPath(source).toString());
Utils::FileName sourcePath = Utils::FileName::fromString(sourcePathName);
if (sourcePath.exists() && sourcePath.toFileInfo().isDir()) {
int idx = existingParts.indexOf(partName);
if (idx >= 0) {
//check if source is still the same
SnapcraftGenericPartNode *n = static_cast<SnapcraftGenericPartNode *>(existingNodes.at(idx));
if (n->filePath() == sourcePath)
continue;
nodesToRemove << n;
}
SnapcraftGenericPartNode *partNode = new SnapcraftGenericPartNode(partName, sourcePath, m_watcher);
nodesToAdd << partNode;
}
}
//snapcraft has magic directories, like setup, we want to show in the project tree
QStringList magicSnapcraftDirs{
QStringLiteral("setup")
};
for (const QString &magicDir: magicSnapcraftDirs) {
Utils::FileName dirPath = filePath().parentDir().appendPath(magicDir);
if (dirPath.exists()) {
partsFromYaml << magicDir;
if(!existingParts.contains(magicDir)) {
SnapcraftGenericPartNode *partNode = new SnapcraftGenericPartNode(magicDir, dirPath, m_watcher);
nodesToAdd << partNode;
}
}
}
QSet<QString> obsoleteParts = existingParts.toSet() - partsFromYaml.toSet();
qDebug()<<"Parts in yaml"<<partsFromYaml;
qDebug()<<"Currently known parts"<<existingParts;
qDebug()<<"Parts now obsolete: "<<obsoleteParts;
for (const auto &part : obsoleteParts) {
int idx = existingParts.indexOf(part);
if (idx >= 0)
nodesToRemove << existingNodes.at(idx);
}
//remove old nodes
removeFolderNodes(nodesToRemove);
addFolderNodes(nodesToAdd);
} catch (const YAML::Exception &e) {
qDebug()<<"ERRROR ERROR ERROR "<<e.what();
return false;
}
return true;
}
/*!
\class Ubuntu::Internal::SnapcraftGenericPartNode
\brief The SnapcraftGenericPartNode class
Fallback node if the subproject type can not be handled by the plugin directly
*/
static void enumChild(const QDir &dir, QSet<Utils::FileName> &dirs, QSet<Utils::FileName> &res) {
foreach (const QFileInfo &info, dir.entryInfoList(QDir::NoDotAndDotDot|QDir::Dirs|QDir::Files|QDir::Hidden)) {
if (info.isDir()) {
dirs << Utils::FileName(info);
enumChild(QDir(info.absoluteFilePath()), dirs, res);
} else {
res.insert(Utils::FileName(info));
}
}
}
SnapcraftGenericPartNode::SnapcraftGenericPartNode(const QString &partName, const Utils::FileName &folderPath, QFileSystemWatcher *watcher)
: ProjectExplorer::FolderNode (folderPath, ProjectExplorer::FolderNodeType, partName)
, m_watcher(watcher)
{
scheduleProjectScan();
setIcon(generateProjectIcon());
if (watcher->addPath(folderPath.toString())) {
qDebug()<<"Added"<<folderPath.toString()<<"to watcher";
} else {
qDebug()<<"Failed to add"<<folderPath.toString()<<"to watcher";
}
m_watcherConnection = QObject::connect(watcher, &QFileSystemWatcher::directoryChanged, [this](const QString &path){
maybeScheduleProjectScan(path);
});
}
SnapcraftGenericPartNode::~SnapcraftGenericPartNode()
{
//@BUG the watcher is still watching all the subdirs and files!
if (m_watcher) {
QString myPath = filePath().toFileInfo().absoluteFilePath();
QStringList watched = m_watcher->directories();
QStringList toRemove;
for(const QString &path: watched) {
if(path.startsWith(myPath))
toRemove << path;
}
m_watcher->removePaths(toRemove);
QObject::disconnect(m_watcherConnection);
}
}
void SnapcraftGenericPartNode::maybeScheduleProjectScan(const QString &changedPath)
{
Utils::FileName changed = Utils::FileName::fromString(changedPath);
if (filePath().toFileInfo() == changed.toFileInfo())
scheduleProjectScan();
}
void SnapcraftGenericPartNode::scheduleProjectScan()
{
if (m_scanning)
return;
qDebug()<<"Scheduling Project scan";
m_scanning = true;
QTimer *rescanTimer = new QTimer();
rescanTimer->setSingleShot(true);
rescanTimer->start(0);
QObject::connect(rescanTimer, &QTimer::timeout, [this, rescanTimer](){
qDebug()<<"Starting Project scan";
delete rescanTimer;
this->scanProjectDirectory();
m_scanning = false;
});
}
void SnapcraftGenericPartNode::removeFileNodes(const QList<Utils::FileName> &files)
{
foreach(const Utils::FileName &f, files) {
if(f.toFileInfo().isDir())
continue;
FindFileNodesForFileVisitor vis(f);
this->accept(&vis);
for (ProjectExplorer::FileNode *node : vis.nodes()) {
node->parentFolderNode()->removeFileNodes({node});
}
}
}
void SnapcraftGenericPartNode::removeFolderNodes(QList<Utils::FileName> &dirs)
{
qSort(dirs.begin(), dirs.end(),[](const Utils::FileName &a, const Utils::FileName &b){
return a.toFileInfo().absoluteFilePath() > b.toFileInfo().absoluteFilePath();
});
foreach(const Utils::FileName &f, dirs) {
FindNodesForFolderVisitor vis(f);
this->accept(&vis);
FindNodesForFolderVisitor visParent(f.parentDir());
this->accept(&visParent);
if(visParent.nodes().size()) {
m_watcher->removePath(f.toFileInfo().absoluteFilePath());
visParent.nodes()[0]->removeFolderNodes(vis.nodes());
}
}
}
QList<ProjectExplorer::ProjectAction> SnapcraftGenericPartNode::supportedActions(ProjectExplorer::Node *node) const
{
static const QList<ProjectExplorer::ProjectAction> fileActions {
ProjectExplorer::ProjectAction::Rename,
ProjectExplorer::ProjectAction::RemoveFile
};
static const QList<ProjectExplorer::ProjectAction> folderActions {
ProjectExplorer::ProjectAction::AddNewFile,
ProjectExplorer::ProjectAction::RemoveFile
};
switch (node->nodeType()) {
case ProjectExplorer::FileNodeType:
return fileActions;
case ProjectExplorer::FolderNodeType:
case ProjectExplorer::ProjectNodeType:
return folderActions;
default:
return ProjectExplorer::FolderNode::supportedActions(node);
}
}
bool SnapcraftGenericPartNode::addFiles(const QStringList &, QStringList *)
{
return true;
}
bool SnapcraftGenericPartNode::removeFiles(const QStringList &, QStringList *)
{
return true;
}
bool SnapcraftGenericPartNode::deleteFiles(const QStringList &)
{
return true;
}
void SnapcraftGenericPartNode::scanProjectDirectory()
{
QSet<Utils::FileName> dirs;
QSet<Utils::FileName> files;
enumChild(QDir(filePath().toString()), dirs, files);
FindFilesAndDirsVisitor vis;
this->accept(&vis);
QSet<Utils::FileName> oldFiles = QSet<Utils::FileName>::fromList(vis.filePaths());
QSet<Utils::FileName> oldDirs = QSet<Utils::FileName>::fromList(vis.dirPaths());
QSet<Utils::FileName> newFiles(files);
QSet<Utils::FileName> newDirs(dirs);
QSet<Utils::FileName> filesToRemove = oldFiles - newFiles;
QSet<Utils::FileName> filesToAdd = newFiles - oldFiles;
QList<Utils::FileName> dirsToRemove = (oldDirs - newDirs).toList();
QSet<Utils::FileName> dirsToAdd = newDirs - oldDirs;
qDebug()<<"Removing dirs " <<dirsToRemove;
qDebug()<<"Adding dirs " <<dirsToAdd;
qDebug()<<"Removing files" <<filesToRemove;
qDebug()<<"Adding files " <<filesToAdd;
removeFileNodes(filesToRemove.toList());
removeFolderNodes(dirsToRemove);
for (const Utils::FileName &dir : dirsToAdd) {
Utils::FileName relativeName = dir.relativeChildPath(filePath());
QStringList relativeNameList = relativeName.toUserOutput().split(QDir::separator());
createOrFindFolder(relativeNameList);
}
for (const Utils::FileName &file : filesToAdd) {
Utils::FileName folderPath = file.parentDir();
//do not show the project file twice
if (file == projectNode()->filePath())
continue;
ProjectExplorer::FolderNode *parentNode = nullptr;
if (folderPath == filePath()) {
parentNode = this;
} else {
Utils::FileName relativeName = folderPath.relativeChildPath(filePath());
QStringList relativeNameList = relativeName.toUserOutput().split(QDir::separator());
parentNode = createOrFindFolder(relativeNameList);
}
ProjectExplorer::FileNode *fNode = new ProjectExplorer::FileNode(file, ProjectExplorer::UnknownFileType, false);
parentNode->addFileNodes({fNode});
}
}
ProjectExplorer::FolderNode *SnapcraftGenericPartNode::createOrFindFolder(const QStringList &folder)
{
QStringList watches;
ProjectExplorer::FolderNode *currFolder = this;
Utils::FileName currentPath = filePath();
for (const QString &folderName: folder) {
QList<ProjectExplorer::FolderNode *> subnodes = currFolder->subFolderNodes();
currentPath = currentPath.appendPath(folderName);
auto check = [&folderName](ProjectExplorer::FolderNode *f) {
return f->filePath().fileName() == folderName;
};
auto it = std::find_if(subnodes.begin(), subnodes.end(), check);
if (it != subnodes.end()) {
//node exists already
currFolder = *it;
continue;
}
//does not exist lets create a new one
ProjectExplorer::FolderNode *fNode = new SnapcraftGenericPartFolderNode(currentPath, ProjectExplorer::FolderNodeType, folderName);
currFolder->addFolderNodes({fNode});
currFolder = fNode;
watches << currentPath.toFileInfo().absoluteFilePath();
}
qDebug()<<"Failed to add watches: "<<m_watcher->addPaths(watches);
return currFolder;
}
Utils::FileNameList FindFilesAndDirsVisitor::filePaths() const
{
return m_filePaths;
}
Utils::FileNameList FindFilesAndDirsVisitor::dirPaths() const
{
return m_dirPaths;
}
void FindFilesAndDirsVisitor::visitProjectNode(ProjectExplorer::ProjectNode *projectNode)
{
visitFolderNode(projectNode);
}
void FindFilesAndDirsVisitor::visitFolderNode(ProjectExplorer::FolderNode *folderNode)
{
if (folderNode->nodeType() != ProjectExplorer::ProjectNodeType)
m_dirPaths.append(folderNode->filePath());
for (const ProjectExplorer::FileNode *fileNode : folderNode->fileNodes())
m_filePaths.append(fileNode->filePath());
}
FindFileNodesForFileVisitor::FindFileNodesForFileVisitor(const Utils::FileName &f)
: m_file(f)
{
}
QList<ProjectExplorer::FileNode *> FindFileNodesForFileVisitor::nodes() const
{
return m_nodes;
}
void FindFileNodesForFileVisitor::visitProjectNode(ProjectExplorer::ProjectNode *projectNode)
{
visitFolderNode(projectNode);
}
void FindFileNodesForFileVisitor::visitFolderNode(ProjectExplorer::FolderNode *folderNode)
{
for(auto fileNode: folderNode->fileNodes()) {
if (fileNode->filePath() == m_file)
m_nodes.append(fileNode);
}
}
FindNodesForFolderVisitor::FindNodesForFolderVisitor(const Utils::FileName &f)
: m_folder(f)
{
}
QList<ProjectExplorer::FolderNode *> FindNodesForFolderVisitor::nodes() const
{
return m_nodes;
}
void FindNodesForFolderVisitor::visitProjectNode(ProjectExplorer::ProjectNode *)
{
return;
}
void FindNodesForFolderVisitor::visitFolderNode(ProjectExplorer::FolderNode *folderNode)
{
if (m_folder == folderNode->filePath())
m_nodes.append(folderNode);
}
bool SnapcraftGenericPartFolderNode::addFiles(const QStringList &, QStringList *)
{
return true;
}
bool SnapcraftGenericPartFolderNode::removeFiles(const QStringList &, QStringList *)
{
return true;
}
bool SnapcraftGenericPartFolderNode::deleteFiles(const QStringList &)
{
return true;
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2016 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Benjamin Zeller <benjamin.zeller@canonical.com>
*/
#ifndef UBUNTU_INTERNAL_SNAPCRAFTPROJECTNODE_H
#define UBUNTU_INTERNAL_SNAPCRAFTPROJECTNODE_H
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/nodesvisitor.h>
#include <yaml-cpp/node/node.h>
#include <QPointer>
class QFileSystemWatcher;
namespace Ubuntu {
namespace Internal {
class FindFilesAndDirsVisitor : public ProjectExplorer::NodesVisitor {
public:
Utils::FileNameList filePaths() const;
Utils::FileNameList dirPaths() const;
void visitProjectNode(ProjectExplorer::ProjectNode *projectNode) override;
void visitFolderNode(ProjectExplorer::FolderNode *folderNode) override;
private:
Utils::FileNameList m_filePaths;
Utils::FileNameList m_dirPaths;
};
class FindFileNodesForFileVisitor : public ProjectExplorer::NodesVisitor {
public:
FindFileNodesForFileVisitor (const Utils::FileName &f);
QList<ProjectExplorer::FileNode *> nodes () const;
void visitProjectNode(ProjectExplorer::ProjectNode *projectNode) override;
void visitFolderNode(ProjectExplorer::FolderNode *folderNode) override;
private:
Utils::FileName m_file;
QList<ProjectExplorer::FileNode *> m_nodes;
};
class FindNodesForFolderVisitor : public ProjectExplorer::NodesVisitor {
public:
FindNodesForFolderVisitor (const Utils::FileName &f);
QList<ProjectExplorer::FolderNode *> nodes () const;
void visitProjectNode(ProjectExplorer::ProjectNode *projectNode) override;
void visitFolderNode(ProjectExplorer::FolderNode *folderNode) override;
private:
Utils::FileName m_folder;
QList<ProjectExplorer::FolderNode *> m_nodes;
};
class SnapcraftProject;
class SnapcraftGenericPartNode;
class SnapcraftProjectNode : public ProjectExplorer::ProjectNode
{
public:
SnapcraftProjectNode(SnapcraftProject *rootProject, const Utils::FileName &projectFilePath, QFileSystemWatcher *watcher);
~SnapcraftProjectNode();
bool syncFromYAMLNode(YAML::Node rootNode);
private:
SnapcraftProject *m_rootProject = nullptr;
QPointer<QFileSystemWatcher> m_watcher;
};
class SnapcraftGenericPartFolderNode : public ProjectExplorer::FolderNode
{
public:
using ProjectExplorer::FolderNode::FolderNode;
// FolderNode interface
virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) override;
virtual bool deleteFiles(const QStringList &filePaths) override;
};
class SnapcraftGenericPartNode : public ProjectExplorer::FolderNode
{
public:
SnapcraftGenericPartNode(const QString &partName, const Utils::FileName &folderPath, QFileSystemWatcher *watcher);
~SnapcraftGenericPartNode();
void maybeScheduleProjectScan(const QString &changedPath);
void scheduleProjectScan();
using ProjectExplorer::FolderNode::removeFileNodes;
void removeFileNodes (const QList<Utils::FileName> &files);
using ProjectExplorer::FolderNode::removeFolderNodes;
void removeFolderNodes (QList<Utils::FileName> &dirs);
// Node interface
virtual QList<ProjectExplorer::ProjectAction> supportedActions(ProjectExplorer::Node *node) const override;
virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) override;
virtual bool deleteFiles(const QStringList &filePaths) override;
protected:
ProjectExplorer::FolderNode *createOrFindFolder (const QStringList &folder);
void scanProjectDirectory ();
private:
bool m_scanning = false;
QMetaObject::Connection m_watcherConnection;
QPointer<QFileSystemWatcher> m_watcher;
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTPROJECTNODE_H

View File

@@ -0,0 +1,51 @@
#include "snapcraftrsyncstep.h"
#include "snapcraftproject.h"
#include "snapcraftbuildconfiguration.h"
#include <ubuntu/ubuntuconstants.h>
#include <projectexplorer/target.h>
namespace Ubuntu {
namespace Internal {
SnapcraftRsyncStep::SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl)
: ProjectExplorer::AbstractProcessStep(bsl, Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID)
{
setDefaultDisplayName(tr("Prepare build"));
}
SnapcraftRsyncStep::SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl, SnapcraftRsyncStep *bs)
: ProjectExplorer::AbstractProcessStep(bsl, bs)
{
}
bool SnapcraftRsyncStep::init(QList<const ProjectExplorer::BuildStep *> &)
{
QString projectDir = target()->project()->projectDirectory().toString();
ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
if(!bc)
return false;
ProjectExplorer::ProcessParameters *param = processParameters();
param->setWorkingDirectory(bc->buildDirectory().toUserOutput());
param->setCommand(QStringLiteral("rsync"));
param->setArguments(QString::fromLatin1("-a --delete \"%1/\" \"./\"")
.arg(QDir::cleanPath(projectDir)));
param->setMacroExpander(bc->macroExpander());
param->setEnvironment(bc->environment());
return true;
}
ProjectExplorer::BuildStepConfigWidget *SnapcraftRsyncStep::createConfigWidget()
{
return new ProjectExplorer::SimpleBuildStepConfigWidget(this);
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,31 @@
#ifndef UBUNTU_INTERNAL_SNAPCRAFTRSYNCSTEP_H
#define UBUNTU_INTERNAL_SNAPCRAFTRSYNCSTEP_H
#include <projectexplorer/abstractprocessstep.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftBuildStepFactory;
class SnapcraftBuildConfigurationFactory;
class SnapcraftRsyncStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
public:
friend class SnapcraftBuildStepFactory;
friend class SnapcraftBuildConfigurationFactory;
// BuildStep interface
virtual bool init(QList<const ProjectExplorer::BuildStep *> &earlierSteps) override;
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
protected:
SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl);
SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl, SnapcraftRsyncStep *bs);
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTRSYNCSTEP_H

View File

@@ -0,0 +1,67 @@
#include "snapcraftstep.h"
#include "snapcraftproject.h"
#include "snapcraftbuildconfiguration.h"
#include <ubuntu/snap/settings/snapcraftkitinformation.h>
#include <ubuntu/ubuntuconstants.h>
#include <projectexplorer/target.h>
#include <utils/environment.h>
namespace Ubuntu {
namespace Internal {
SnapcraftStep::SnapcraftStep(ProjectExplorer::BuildStepList *bsl)
: ProjectExplorer::AbstractProcessStep(bsl, Constants::SNAPCRAFT_BUILDSTEP_ID)
{
setDefaultDisplayName(tr("Snapcraft"));
}
SnapcraftStep::SnapcraftStep(ProjectExplorer::BuildStepList *bsl, SnapcraftStep *bs)
: ProjectExplorer::AbstractProcessStep(bsl, bs)
{
}
bool SnapcraftStep::init(QList<const ProjectExplorer::BuildStep *> &)
{
//QString projectDir = target()->project()->projectDirectory().toString();
ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
if(!bc)
return false;
Utils::FileName snapcraftBin = Utils::FileName::fromString(Constants::UBUNTU_SCRIPTPATH);
snapcraftBin = snapcraftBin.appendPath(QString::fromLatin1("run_snapcraft.py"));
ProjectExplorer::ProcessParameters *param = processParameters();
param->setWorkingDirectory(bc->buildDirectory().toUserOutput());
param->setCommand(snapcraftBin.toUserOutput());
param->setArguments(QString::fromLatin1("-s '%1'").arg(snapcraftBin.toFileInfo().absoluteFilePath()));
param->setMacroExpander(bc->macroExpander());
param->setEnvironment(bc->environment());
return true;
}
ProjectExplorer::BuildStepConfigWidget *SnapcraftStep::createConfigWidget()
{
return new ProjectExplorer::SimpleBuildStepConfigWidget(this);
}
Utils::FileName SnapcraftStep::snapcraftCommand() const
{
Utils::Environment env = Utils::Environment::systemEnvironment();
Utils::FileName fallback = env.searchInPath(QStringLiteral("snapcraft"));
if (!target())
return fallback;
Utils::FileName bin = SnapcraftKitInformation::snapcraftPath(target()->kit());
if (!bin.exists())
return fallback;
return bin;
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,33 @@
#ifndef UBUNTU_INTERNAL_SNAPCRAFTSTEP_H
#define UBUNTU_INTERNAL_SNAPCRAFTSTEP_H
#include <projectexplorer/abstractprocessstep.h>
namespace Ubuntu {
namespace Internal {
class SnapcraftBuildStepFactory;
class SnapcraftBuildConfigurationFactory;
class SnapcraftStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
public:
friend class SnapcraftBuildStepFactory;
friend class SnapcraftBuildConfigurationFactory;
// BuildStep interface
virtual bool init(QList<const ProjectExplorer::BuildStep *> &earlierSteps) override;
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
Utils::FileName snapcraftCommand () const;
protected:
SnapcraftStep(ProjectExplorer::BuildStepList *bsl);
SnapcraftStep(ProjectExplorer::BuildStepList *bsl, SnapcraftStep *bs);
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTSTEP_H

View File

@@ -0,0 +1,114 @@
#include "snapcraftkitinformation.h"
#include <projectexplorer/kit.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/pathchooser.h>
#include <QFileInfo>
namespace Ubuntu {
namespace Internal {
static const char TOOL_ID[] = "SnapcraftProjectManager.SnapcraftKitInformation";
SnapcraftKitInformation::SnapcraftKitInformation()
{
setObjectName(QStringLiteral("SnapcraftKitInformation"));
setId(TOOL_ID);
setPriority(29000);
}
Utils::FileName SnapcraftKitInformation::snapcraftPath(const ProjectExplorer::Kit *k)
{
return k->value(TOOL_ID, QVariant::fromValue<Utils::FileName>(Utils::FileName())).value<Utils::FileName>();
}
void SnapcraftKitInformation::setSnapcraftPath(ProjectExplorer::Kit *k, const Utils::FileName &snapcraft)
{
if (snapcraft.toFileInfo().isExecutable()) {
k->setValue(TOOL_ID, QVariant::fromValue<Utils::FileName>(snapcraft));
}
}
QVariant SnapcraftKitInformation::defaultValue(const ProjectExplorer::Kit *) const
{
Utils::Environment env = Utils::Environment::systemEnvironment();
return QVariant::fromValue<Utils::FileName>(env.searchInPath(QStringLiteral("snapcraft")));
}
QList<ProjectExplorer::Task> SnapcraftKitInformation::validate(const ProjectExplorer::Kit *) const
{
return QList<ProjectExplorer::Task>();
}
ProjectExplorer::KitInformation::ItemList SnapcraftKitInformation::toUserOutput(const ProjectExplorer::Kit *k) const
{
Utils::FileName snap = snapcraftPath(k);
return ItemList {
qMakePair(tr("Snapcraft"), snap.exists() ? snap.toUserOutput() : tr("Unconfigured"))
};
}
ProjectExplorer::KitConfigWidget *SnapcraftKitInformation::createConfigWidget(ProjectExplorer::Kit *kit) const
{
return new SnapcraftKitInformationWidget(kit, this);
}
SnapcraftKitInformationWidget::SnapcraftKitInformationWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki)
: ProjectExplorer::KitConfigWidget(kit, ki)
, m_chooser(new Utils::PathChooser)
, m_ignoreChange(false)
{
m_chooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_chooser->setFileName(SnapcraftKitInformation::snapcraftPath(kit));
connect(m_chooser, &Utils::PathChooser::pathChanged,
this, &SnapcraftKitInformationWidget::pathWasChanged);
}
SnapcraftKitInformationWidget::~SnapcraftKitInformationWidget()
{
delete m_chooser;
}
QString SnapcraftKitInformationWidget::displayName() const
{
return tr("Snapcraft");
}
void SnapcraftKitInformationWidget::makeReadOnly()
{
m_chooser->setReadOnly(true);
}
void SnapcraftKitInformationWidget::refresh()
{
if (!m_ignoreChange)
m_chooser->setPath(SnapcraftKitInformation::snapcraftPath(kit()).toUserOutput());
}
QWidget *SnapcraftKitInformationWidget::mainWidget() const
{
return m_chooser->lineEdit();
}
QString SnapcraftKitInformationWidget::toolTip() const
{
return tr("The snapcraft binary to use for this kit.");
}
QWidget *SnapcraftKitInformationWidget::buttonWidget() const
{
return m_chooser->buttonAtIndex(0);
}
void SnapcraftKitInformationWidget::pathWasChanged()
{
m_ignoreChange = true;
SnapcraftKitInformation::setSnapcraftPath(kit(), m_chooser->fileName());
m_ignoreChange = false;
}
} // namespace Internal
} // namespace Ubuntu

View File

@@ -0,0 +1,59 @@
#ifndef UBUNTU_INTERNAL_SNAPCRAFTKITINFORMATION_H
#define UBUNTU_INTERNAL_SNAPCRAFTKITINFORMATION_H
#include <projectexplorer/kitconfigwidget.h>
#include <projectexplorer/kitinformation.h>
namespace Utils {
class PathChooser;
}
namespace Ubuntu {
namespace Internal {
class SnapcraftKitInformation : public ProjectExplorer::KitInformation
{
Q_OBJECT
public:
SnapcraftKitInformation();
static Utils::FileName snapcraftPath (const ProjectExplorer::Kit *k);
static void setSnapcraftPath (ProjectExplorer::Kit *k, const Utils::FileName &snapcraft);
// KitInformation interface
virtual QVariant defaultValue(const ProjectExplorer::Kit *) const override;
virtual QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *) const override;
virtual ItemList toUserOutput(const ProjectExplorer::Kit *) const override;
virtual ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
private:
Utils::FileName m_snapcraftPath;
};
class SnapcraftKitInformationWidget : public ProjectExplorer::KitConfigWidget
{
public:
SnapcraftKitInformationWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki);
virtual ~SnapcraftKitInformationWidget();
// KitConfigWidget interface
virtual QString displayName() const override;
virtual void makeReadOnly() override;
virtual void refresh() override;
virtual QWidget *mainWidget() const override;
virtual QString toolTip() const override;
virtual QWidget *buttonWidget() const override;
private:
void pathWasChanged();
private:
Utils::PathChooser *m_chooser;
bool m_ignoreChange;
};
} // namespace Internal
} // namespace Ubuntu
#endif // UBUNTU_INTERNAL_SNAPCRAFTKITINFORMATION_H

View File

@@ -0,0 +1,27 @@
LIBS+=-lyaml-cpp
SOURCES += \
$$PWD/project/snapcraftproject.cpp \
$$PWD/project/snapcraftprojectfile.cpp \
$$PWD/project/snapcraftprojectnode.cpp \
$$PWD/project/snapcraftprojectmanager.cpp \
$$PWD/project/snapcraftbuildconfigurationfactory.cpp \
$$PWD/project/snapcraftbuildconfiguration.cpp \
$$PWD/project/snapcraftrsyncstep.cpp \
$$PWD/project/snapcraftstep.cpp \
$$PWD/project/snapcraftbuildstepfactory.cpp \
$$PWD/settings/snapcraftkitinformation.cpp
HEADERS += \
$$PWD/project/snapcraftproject.h \
$$PWD/project/snapcraftprojectfile.h \
$$PWD/project/snapcraftprojectnode.h \
$$PWD/project/snapcraftprojectmanager.h \
$$PWD/project/snapcraftbuildconfigurationfactory.h \
$$PWD/project/snapcraftbuildconfiguration.h \
$$PWD/project/snapcraftrsyncstep.h \
$$PWD/project/snapcraftstep.h \
$$PWD/project/snapcraftbuildstepfactory.h \
$$PWD/settings/snapcraftkitinformation.h

View File

@@ -471,6 +471,11 @@ QString UbuntuClickTool::findOrCreateMakeWrapper (const UbuntuClickTool::Target
return UbuntuClickTool::findOrCreateToolWrapper(QStringLiteral("make"),target);
}
Utils::FileName UbuntuClickTool::findOrCreateSnapcraftWrapper(const UbuntuClickTool::Target &target)
{
return Utils::FileName::fromString(UbuntuClickTool::findOrCreateToolWrapper(QStringLiteral("snapcraft"),target));
}
QString UbuntuClickTool::mapIncludePathsForCMake(const ProjectExplorer::Kit *k, const QString &in)
{
if (in.isEmpty())

View File

@@ -86,6 +86,7 @@ public:
static QString findOrCreateToolWrapper(const QString &tool, const UbuntuClickTool::Target &target);
static QString findOrCreateQMakeWrapper(const UbuntuClickTool::Target &target);
static QString findOrCreateMakeWrapper(const UbuntuClickTool::Target &target);
static Utils::FileName findOrCreateSnapcraftWrapper(const UbuntuClickTool::Target &target);
static QString mapIncludePathsForCMake(const ProjectExplorer::Kit *k, const QString &in);
static QString hostArchitecture ();
static bool compatibleWithHostArchitecture (const QString &targetArch);

View File

@@ -393,6 +393,16 @@ const char UBUNTU_MIGRATE_QMAKE_PROJECT[] = "UbuntuProjectManager.MigrateQMakePr
const char CHROOT_UPDATE_LIST_SCRIPT[] = "%1/ubuntu/scripts/qtc_chroot_get_upgrades.py %2 %3";
//Snapcraft
const char SNAPCRAFT_PROJECT_MIMETYPE[] = "application/x-snapcraft";
const char SNAPCRAFT_PROJECT_ID[ ] = "SnapcraftProjectManager.SnapcraftProject";
const char SNAPCRAFT_PROJECT_PROJECTCONTEXT[] = "SnapcraftProject.ProjectContext";
const char SNAPCRAFT_BUILDCONFIGURATION_ID[] = "SnapcraftProjectManager.SnapcraftBuildconfiguration.Id";
const char SNAPCRAFT_RSYNCBUILSSTEP_ID[] = "SnapcraftProjectManager.SnapcraftRsyncStep.Id";
const char SNAPCRAFT_BUILDSTEP_ID[] = "SnapcraftProjectManager.SnapcraftStep.Id";
} // namespace Ubuntu
} // namespace Constants

View File

@@ -5,7 +5,8 @@
#include "ubuntuclickdialog.h"
#include "ubuntuqtversion.h"
#include "settings.h"
#include "device/container/containerdevice.h"
#include <ubuntu/device/container/containerdevice.h>
#include <ubuntu/snap/settings/snapcraftkitinformation.h>
#include <coreplugin/icore.h>
#include <projectexplorer/kitmanager.h>
@@ -509,6 +510,8 @@ void UbuntuKitManager::fixKit(ProjectExplorer::Kit *k)
ProjectExplorer::SysRootKitInformation::setSysRoot(k,Utils::FileName::fromString(UbuntuClickTool::targetBasePath(tc->clickTarget())));
}
SnapcraftKitInformation::setSnapcraftPath(k, UbuntuClickTool::findOrCreateSnapcraftWrapper(tc->clickTarget()));
//make sure we point to a ubuntu device
Core::Id devId = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(k);
bool devValid = devId.isValid(); //invalid type

View File

@@ -53,6 +53,11 @@
#include <ubuntu/wizards/ubuntufirstrunwizard.h>
#include <ubuntu/wizards/ubuntuprojectmigrationwizard.h>
#include <ubuntu/snap/project/snapcraftprojectmanager.h>
#include <ubuntu/snap/project/snapcraftbuildconfigurationfactory.h>
#include <ubuntu/snap/project/snapcraftbuildstepfactory.h>
#include <ubuntu/snap/settings/snapcraftkitinformation.h>
#include "ubuntujsextension.h"
#include <coreplugin/modemanager.h>
@@ -175,6 +180,13 @@ bool UbuntuPlugin::initialize(const QStringList &arguments, QString *errorString
addAutoReleasedObject(new UbuntuRemoteRunControlFactory);
addAutoReleasedObject(new UbuntuLocalRunControlFactory);
addAutoReleasedObject(new SnapcraftProjectManager);
addAutoReleasedObject(new SnapcraftBuildConfigurationFactory);
addAutoReleasedObject(new SnapcraftBuildStepFactory);
ProjectExplorer::KitManager::registerKitInformation(new SnapcraftKitInformation);
// Build support
addAutoReleasedObject(new ClickToolChainFactory);
addAutoReleasedObject(new UbuntuHtmlBuildConfigurationFactory);
@@ -379,6 +391,7 @@ bool UbuntuPlugin::checkContainerSetup()
while (!ok) {
QProcess proc;
qDebug()<<"Running "<<Constants::UBUNTU_TARGET_TOOL;
proc.setProgram(Constants::UBUNTU_TARGET_TOOL);
QStringList args{QStringLiteral("initialized")};
@@ -407,8 +420,7 @@ bool UbuntuPlugin::checkContainerSetup()
if (Settings::askForContainerSetup()) {
QString text = tr("The container backend is not completely initialized.\n\n"
"Create default configuration?\n"
"Not setting up the container configuration will\nmake it impossible to run applications locally.\n\n"
"Note: Will override existing LXD configurations."
"Not setting up the container configuration will\nmake it impossible to run applications locally."
);
QMessageBox box(QMessageBox::Question, qApp->applicationName(),text, QMessageBox::Yes | QMessageBox::No | QMessageBox::Abort, Core::ICore::mainWindow());