query AUR when resolving build order
This commit is contained in:
parent
5e3472c12c
commit
1f1d46c5dd
|
@ -30,6 +30,7 @@ const char *shchar = "";
|
|||
ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
||||
helpArg(parser),
|
||||
buildOrderArg("build-order", "b", "calculates the build order to build the specified packages"),
|
||||
addSourceOnlyDeps("add-src-only-deps", "a", "adds source-only dependencies to build chain"),
|
||||
serverArg("server", "s", "runs a websocket server providing the web interface with information"),
|
||||
upgradeLookupArg("upgrade-lookup", "u", "checks available upgrades for the specified repository"),
|
||||
mingwBundleArg("mingw-w64-bundle", "m", "creates an archive with the runtime-relevant files from the specified mingw-w64-packages and their dependencies"),
|
||||
|
@ -123,7 +124,7 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
|||
repoArg.setValueNames({"repo name"});
|
||||
serverArg.setSecondaryArguments({&rootdirArg, &dbpathArg, &pacmanConfArg, &certFileArg, &keyFileArg, &websocketAddrArg, &websocketPortArg, &insecureArg, &aurArg, &shSyntaxArg});
|
||||
upgradeLookupArg.setSecondaryArguments({&shSyntaxArg});
|
||||
buildOrderArg.setSecondaryArguments({&aurArg, &verboseArg, &shSyntaxArg});
|
||||
buildOrderArg.setSecondaryArguments({&aurArg, &addSourceOnlyDeps, &verboseArg, &shSyntaxArg});
|
||||
mingwBundleArg.setSecondaryArguments({&targetDirArg, &targetNameArg, &targetFormatArg, &iconThemesArg, &defaultIconThemeArg, &extraPackagesArg});
|
||||
parser.setMainArguments({&buildOrderArg, &upgradeLookupArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &helpArg});
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
ConfigArgs(ApplicationUtilities::ArgumentParser &parser);
|
||||
ApplicationUtilities::HelpArgument helpArg;
|
||||
ApplicationUtilities::Argument buildOrderArg;
|
||||
ApplicationUtilities::Argument addSourceOnlyDeps;
|
||||
ApplicationUtilities::Argument serverArg;
|
||||
ApplicationUtilities::Argument upgradeLookupArg;
|
||||
ApplicationUtilities::Argument mingwBundleArg;
|
||||
|
|
|
@ -227,6 +227,16 @@ void getFiles(PkgFileInfo &pkgFileInfo)
|
|||
}
|
||||
}
|
||||
}
|
||||
const auto *iconsEntry = shareDir->entry(QStringLiteral("icons"));
|
||||
if(iconsEntry && iconsEntry->isDirectory()) {
|
||||
const auto *iconsDir = static_cast<const KArchiveDirectory *>(iconsEntry);
|
||||
for(const auto &themeName : iconsDir->entries()) {
|
||||
const auto *themeEntry = iconsDir->entry(themeName);
|
||||
if(themeEntry && themeEntry->isDirectory()) {
|
||||
addEntries(pkgFileInfo, RelevantFileType::IconTheme, static_cast<const KArchiveDirectory *>(themeEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pkgFileInfo.name.compare(QLatin1String("qt"))) {
|
||||
const auto *appEntry = shareDir->entry(pkgFileInfo.name);
|
||||
if(appEntry && appEntry->isDirectory()) {
|
||||
|
|
|
@ -389,7 +389,7 @@ void Package::restoreFromCacheStream(QDataStream &in)
|
|||
* \brief Puts the specified src/pkg info key value pairs; clears current dependencies, provides, ... before inserting new values.
|
||||
* \remarks This method should only be called by the associated repository because it must handle a possible name change.
|
||||
*/
|
||||
void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo)
|
||||
void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo, bool includesSourceRelatedMetaData)
|
||||
{
|
||||
// clear current values
|
||||
m_licenses.clear();
|
||||
|
@ -453,6 +453,7 @@ void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QLi
|
|||
}
|
||||
// consider general information as complete
|
||||
m_hasGeneralInfo = m_hasAllGeneralInfo = true;
|
||||
m_hasSourceRelatedMetaData = includesSourceRelatedMetaData;
|
||||
}
|
||||
|
||||
void Package::putSourceFile(const QString &path, const QByteArray &data)
|
||||
|
|
|
@ -176,7 +176,7 @@ public:
|
|||
void restoreFromCacheStream(QDataStream &in);
|
||||
|
||||
// parsing src/pkg info
|
||||
void putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo);
|
||||
void putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo, bool includesSourceRelatedMetaData = false);
|
||||
void putSourceFile(const QString &path, const QByteArray &data);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -21,14 +21,39 @@ PackageFinder::PackageFinder(Manager &manager, const QList<Dependency> &dependen
|
|||
}
|
||||
if(manager.userRepository()) {
|
||||
QReadLocker locker(manager.userRepository()->lock());
|
||||
auto *reply = manager.userRepository()->requestFullPackageInfo(toRequest);
|
||||
if(reply) {
|
||||
if(auto *reply = manager.userRepository()->requestFullPackageInfo(toRequest)) {
|
||||
++m_remainingReplies;
|
||||
connect(reply, &PackageReply::resultsAvailable, this, &PackageFinder::addResults);
|
||||
} else {
|
||||
for(const Dependency &dependency : dependencies) {
|
||||
if(auto *pkg = manager.userRepository()->packageProviding(dependency)) {
|
||||
m_results << pkg;
|
||||
} else {
|
||||
// shouldn't happen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Package *PackageFinder::packageProviding(const Dependency &dependency)
|
||||
{
|
||||
for(Package *package : m_results) {
|
||||
if(package->matches(dependency)) {
|
||||
// check whether package matches "directly"
|
||||
return package;
|
||||
} else {
|
||||
// check whether at least one of the provides matches
|
||||
for(const auto &provide : package->provides()) {
|
||||
if(Package::matches(provide.name, provide.version, dependency)) {
|
||||
return package;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PackageFinder::addResults()
|
||||
{
|
||||
assert(m_remainingReplies);
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
const QList<Package *> results() const;
|
||||
bool areAllResultsAvailable() const;
|
||||
Package *packageProviding(const Dependency &dependency);
|
||||
|
||||
signals:
|
||||
void resultsAvailable();
|
||||
|
|
|
@ -543,7 +543,8 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
|
|||
FieldName,
|
||||
EquationSign,
|
||||
Pad,
|
||||
FieldValue
|
||||
FieldValue,
|
||||
Comment
|
||||
} state = FieldName;
|
||||
QString currentFieldName;
|
||||
QString currentFieldValue;
|
||||
|
@ -552,19 +553,23 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
|
|||
QList<QPair<QString, QString> > packageInfo;
|
||||
QList<Package *> packages;
|
||||
Package *currentPackage = nullptr;
|
||||
for(char c : srcInfo) {
|
||||
for(const char c : srcInfo) {
|
||||
switch(state) {
|
||||
case FieldName:
|
||||
switch(c) {
|
||||
case '#':
|
||||
// discard truncated line
|
||||
currentFieldName.clear();
|
||||
state = Comment;
|
||||
case ' ':
|
||||
// field name complete, expect equation sign
|
||||
if(!currentFieldName.isEmpty()) {
|
||||
state = EquationSign;
|
||||
}
|
||||
break;
|
||||
case '\n': case '\r': case '\t':
|
||||
if(!currentFieldName.isEmpty()) {
|
||||
// TODO: handle error - field name contains invalid char character
|
||||
}
|
||||
// discard truncated line
|
||||
currentFieldName.clear();
|
||||
break;
|
||||
default:
|
||||
currentFieldName.append(c);
|
||||
|
@ -575,8 +580,12 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
|
|||
case '=':
|
||||
state = Pad;
|
||||
break;
|
||||
case '\n': case '\r': case '\t':
|
||||
// unexpected new line -> discard truncated line
|
||||
currentFieldName.clear();
|
||||
break;
|
||||
default:
|
||||
;// TODO: handle error - no equation sign after pad
|
||||
; // ignore unexpected characters
|
||||
}
|
||||
break;
|
||||
case Pad:
|
||||
|
@ -584,8 +593,12 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
|
|||
case ' ':
|
||||
state = FieldValue;
|
||||
break;
|
||||
case '\n': case '\r': case '\t':
|
||||
// unexpected new line -> discard truncated line
|
||||
currentFieldName.clear();
|
||||
break;
|
||||
default:
|
||||
;// TODO: handle error - no pad after equation sign
|
||||
; // ignore unexpected characters
|
||||
}
|
||||
break;
|
||||
case FieldValue:
|
||||
|
@ -601,7 +614,7 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
|
|||
// TODO: handle error - pkgbase must be present
|
||||
} else {
|
||||
if(currentPackage) {
|
||||
currentPackage->putInfo(baseInfo, packageInfo);
|
||||
currentPackage->putInfo(baseInfo, packageInfo, true);
|
||||
packages << currentPackage;
|
||||
}
|
||||
auto &pkg = m_packages[currentFieldValue];
|
||||
|
@ -624,10 +637,19 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
|
|||
currentFieldValue.append(c);
|
||||
}
|
||||
break;
|
||||
case Comment:
|
||||
switch(c) {
|
||||
case '\n': case '\r': case '\t':
|
||||
state = FieldName;
|
||||
break;
|
||||
default:
|
||||
; // ignore outcommented characters
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(currentPackage) {
|
||||
currentPackage->putInfo(baseInfo, packageInfo);
|
||||
currentPackage->putInfo(baseInfo, packageInfo, true);
|
||||
packages << currentPackage;
|
||||
}
|
||||
return packages;
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#include "./resolvebuildorder.h"
|
||||
|
||||
#include "./packagefinder.h"
|
||||
#include "./manager.h"
|
||||
#include "./config.h"
|
||||
#include "./utilities.h"
|
||||
#include "./repository.h"
|
||||
|
||||
#include <c++utilities/misc/memory.h>
|
||||
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -26,9 +30,12 @@ public:
|
|||
bool isDone() const;
|
||||
bool isVisited() const;
|
||||
bool isOnlyDependency() const;
|
||||
void setIsOnlyDependency(bool isOnlyDependency);
|
||||
bool isPackageRequested() const;
|
||||
void setPackageRequested();
|
||||
void add(QList<TaskInfo *> &results);
|
||||
Package *associatedPackage() const;
|
||||
void associatePackage(Package *package);
|
||||
static void addAll(const QList<TaskInfo *> &tasks, QList<TaskInfo *> &results);
|
||||
static TaskInfo *find(const QList<TaskInfo *> &tasks, const QString &name);
|
||||
|
||||
|
@ -39,6 +46,7 @@ private:
|
|||
bool m_visited;
|
||||
bool m_onlyDep;
|
||||
bool m_pkgRequested;
|
||||
Package *m_associatedPackage;
|
||||
};
|
||||
|
||||
inline TaskInfo::TaskInfo(QString name, bool onlyDependency, const QList<TaskInfo *> &deps) :
|
||||
|
@ -47,7 +55,8 @@ inline TaskInfo::TaskInfo(QString name, bool onlyDependency, const QList<TaskInf
|
|||
m_done(false),
|
||||
m_visited(false),
|
||||
m_onlyDep(onlyDependency),
|
||||
m_pkgRequested(false)
|
||||
m_pkgRequested(false),
|
||||
m_associatedPackage(nullptr)
|
||||
{}
|
||||
|
||||
inline const QString &TaskInfo::name() const
|
||||
|
@ -85,6 +94,11 @@ inline bool TaskInfo::isOnlyDependency() const
|
|||
return m_onlyDep;
|
||||
}
|
||||
|
||||
inline void TaskInfo::setIsOnlyDependency(bool isOnlyDependency)
|
||||
{
|
||||
m_onlyDep = isOnlyDependency;
|
||||
}
|
||||
|
||||
inline bool TaskInfo::isPackageRequested() const
|
||||
{
|
||||
return m_pkgRequested;
|
||||
|
@ -119,6 +133,18 @@ void TaskInfo::add(QList<TaskInfo *> &results)
|
|||
}
|
||||
}
|
||||
|
||||
inline Package *TaskInfo::associatedPackage() const
|
||||
{
|
||||
return m_associatedPackage;
|
||||
}
|
||||
|
||||
void TaskInfo::associatePackage(Package *package)
|
||||
{
|
||||
m_associatedPackage = package;
|
||||
// update the name to ensure we have the acutal package name and not just a "provides" name
|
||||
m_name = package->name();
|
||||
}
|
||||
|
||||
void TaskInfo::addAll(const QList<TaskInfo *> &tasks, QList<TaskInfo *> &results)
|
||||
{
|
||||
for(auto *task : tasks) {
|
||||
|
@ -153,121 +179,211 @@ private:
|
|||
ListType &m_list;
|
||||
};
|
||||
|
||||
BuildOrderResolver::BuildOrderResolver(const Manager &manager) :
|
||||
m_manager(manager)
|
||||
{}
|
||||
|
||||
QStringList BuildOrderResolver::resolve(const StringVector &packages)
|
||||
BuildOrderResolver::BuildOrderResolver(Manager &manager, const StringVector &packages, bool addSourceOnlyDeps) :
|
||||
m_manager(manager),
|
||||
m_finder(nullptr),
|
||||
m_addSourceOnlyDeps(addSourceOnlyDeps)
|
||||
{
|
||||
cerr << shchar << "Getting package information ..." << endl;
|
||||
m_tasks.clear();
|
||||
m_tasks.reserve(packages.size() * 2);
|
||||
m_dependenciesToBeRequested.clear();
|
||||
try {
|
||||
// add a task for each specified package
|
||||
for(const auto &pkgName : packages) {
|
||||
m_tasks << new TaskInfo(QString::fromLocal8Bit(pkgName.data()));
|
||||
}
|
||||
// find specified packages and their dependencies
|
||||
for(int i = 0, size = m_tasks.size(); i != size; ++i) {
|
||||
addDeps(m_tasks.at(i));
|
||||
}
|
||||
//for(auto *task : m_tasks) {
|
||||
// addDeps(task);
|
||||
//}
|
||||
while(!m_dependenciesToBeRequested.isEmpty()) {
|
||||
cerr << shchar << "Dependencies to be requested:";
|
||||
for(const Dependency &dep : m_dependenciesToBeRequested) {
|
||||
cerr << ' ' << dep.name.toStdString();
|
||||
}
|
||||
cerr << endl;
|
||||
// TODO: do requests
|
||||
|
||||
m_dependenciesToBeRequested.clear();
|
||||
}
|
||||
if(m_manager.config().isVerbose()) {
|
||||
cerr << shchar << "Relevant packages:";
|
||||
for(const auto *task : m_tasks) {
|
||||
cerr << ' ' << task->name().toLocal8Bit().data();
|
||||
}
|
||||
cerr << endl;
|
||||
}
|
||||
// topo sort
|
||||
QList<TaskInfo *> results;
|
||||
try {
|
||||
results.reserve(packages.size());
|
||||
TaskInfo::addAll(m_tasks, results);
|
||||
QStringList names;
|
||||
names.reserve(results.size());
|
||||
for(const auto *res : results) {
|
||||
names << res->name();
|
||||
}
|
||||
return names;
|
||||
} catch (const TaskInfo &cyclic) {
|
||||
throw runtime_error("Can't resolve build order; the package " + cyclic.name().toStdString() + " is a cyclic dependency.");
|
||||
}
|
||||
} catch(...) {
|
||||
qDeleteAll(m_tasks);
|
||||
throw;
|
||||
// add a task for each specified package
|
||||
for(const auto &pkgName : packages) {
|
||||
m_tasks << new TaskInfo(QString::fromLocal8Bit(pkgName.data()));
|
||||
}
|
||||
}
|
||||
|
||||
void BuildOrderResolver::printResults(const QStringList &results)
|
||||
BuildOrderResolver::~BuildOrderResolver()
|
||||
{
|
||||
qDeleteAll(m_tasks);
|
||||
}
|
||||
|
||||
void BuildOrderResolver::cli()
|
||||
{
|
||||
if(m_manager.config().isVerbose()) {
|
||||
connect(this, &BuildOrderResolver::ready, this, &BuildOrderResolver::printRelevantPackages);
|
||||
}
|
||||
connect(this, &BuildOrderResolver::ready, this, &BuildOrderResolver::resolve);
|
||||
connect(this, &BuildOrderResolver::resolvingFinished, this, &BuildOrderResolver::printResults);
|
||||
connect(this, &BuildOrderResolver::resolvingFailed, static_cast<void(*)(const QString &)>(Utilities::printError));
|
||||
findDependencies();
|
||||
}
|
||||
|
||||
void BuildOrderResolver::findDependencies()
|
||||
{
|
||||
// find specified packages and their dependencies
|
||||
for(int i = 0, size = m_tasks.size(); i != size; ++i) {
|
||||
addDependenciesToTask(m_tasks.at(i));
|
||||
}
|
||||
// request dependencies to be requested
|
||||
requestDependenciesToBeRequested();
|
||||
}
|
||||
|
||||
QStringList BuildOrderResolver::resultNames()
|
||||
{
|
||||
QStringList names;
|
||||
names.reserve(m_results.size());
|
||||
for(const auto *res : m_results) {
|
||||
names << res->name();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
void BuildOrderResolver::printRelevantPackages()
|
||||
{
|
||||
cerr << shchar << "Relevant packages:";
|
||||
for(const auto *task : m_tasks) {
|
||||
cerr << ' ' << task->name().toLocal8Bit().data();
|
||||
}
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
void BuildOrderResolver::printResults()
|
||||
{
|
||||
if(useShSyntax) {
|
||||
Utilities::printBashArray(cout, "REPOINDEX_RESULTS", results);
|
||||
Utilities::printBashArray(cout, "REPOINDEX_RESULTS", resultNames());
|
||||
} else {
|
||||
Utilities::printValues(cout, "Results", results);
|
||||
Utilities::printValues(cout, "Results", resultNames());
|
||||
}
|
||||
}
|
||||
|
||||
void BuildOrderResolver::resolve()
|
||||
{
|
||||
try {
|
||||
m_results.clear();
|
||||
m_results.reserve(m_tasks.size());
|
||||
TaskInfo::addAll(m_tasks, m_results);
|
||||
emit resolvingFinished();
|
||||
} catch(const TaskInfo &cyclic) {
|
||||
emit resolvingFailed(QStringLiteral("Can't resolve build order; the package ") % cyclic.name() % QStringLiteral(" is a cyclic dependency."));
|
||||
}
|
||||
}
|
||||
|
||||
void BuildOrderResolver::addRequestedPackages()
|
||||
{
|
||||
// find specified packages and their dependencies
|
||||
for(int i = 0, size = m_tasks.size(); i != size; ++i) {
|
||||
if(!addDependenciesToTask(m_tasks.at(i))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// request dependencies to be requested
|
||||
requestDependenciesToBeRequested();
|
||||
}
|
||||
|
||||
Package *BuildOrderResolver::findPackageForDependency(const Dependency &dependency)
|
||||
{
|
||||
Package *pkg;
|
||||
if((pkg = m_manager.packageProviding(dependency))) {
|
||||
return pkg;
|
||||
} else if(m_finder && (pkg = m_finder->packageProviding(dependency))) {
|
||||
return pkg;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Finds the package for the specified \a task and then adds dependencies.
|
||||
*/
|
||||
void BuildOrderResolver::addDeps(TaskInfo *task)
|
||||
bool BuildOrderResolver::addDependenciesToTask(TaskInfo *task)
|
||||
{
|
||||
// check whether dependencies have already been added
|
||||
if(task->associatedPackage()) {
|
||||
// package associated -> dependencies already added
|
||||
return true;
|
||||
}
|
||||
Dependency dep(task->name(), QString());
|
||||
if(const auto pkg = m_manager.packageProviding(dep)) {
|
||||
task->setName(pkg->name()); // update the name to ensure we have the acutal package name and not just a "provides" name
|
||||
addDeps(task, pkg->dependencies());
|
||||
if(const auto pkg = findPackageForDependency(dep)) {
|
||||
task->associatePackage(pkg);
|
||||
if(m_addSourceOnlyDeps && pkg->repository()->isSourceOnly()) {
|
||||
task->setIsOnlyDependency(false);
|
||||
}
|
||||
// add dependencies to task
|
||||
addDependenciesToTask(task, pkg->dependencies());
|
||||
} else if(!task->isPackageRequested()) {
|
||||
task->setPackageRequested();
|
||||
m_dependenciesToBeRequested << dep;
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << "The specified package \"" << task->name().toLocal8Bit().data() << "\" could not be found; TODO: search AUR for package, add AUR deps to the packages we want to build";
|
||||
throw runtime_error(ss.str());
|
||||
emit resolvingFailed(QStringLiteral("The specified package \"") % task->name() % QStringLiteral("\" could not be found."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Finds packages for the the specified \a dependencies and adds them to the specified \a task.
|
||||
*/
|
||||
void BuildOrderResolver::addDeps(TaskInfo *task, const QList<Dependency> &dependencies)
|
||||
bool BuildOrderResolver::addDependenciesToTask(TaskInfo *task, const QList<Dependency> &dependencies)
|
||||
{
|
||||
for(auto &dep : dependencies) {
|
||||
if(const auto depPkg = m_manager.packageProviding(dep)) {
|
||||
auto *depTask = TaskInfo::find(m_tasks, depPkg->name());
|
||||
if(depTask) {
|
||||
// we've already added a task for this dependency
|
||||
// adds dependency task to the dependencies of "parent" task
|
||||
task->addDep(depTask);
|
||||
} else {
|
||||
// create new task
|
||||
m_tasks << (depTask = new TaskInfo(depPkg->name(), true));
|
||||
// adds dependency task to the dependencies of "parent" task
|
||||
task->addDep(depTask);
|
||||
// add dependencies of the dependency
|
||||
addDeps(depTask, depPkg->dependencies());
|
||||
}
|
||||
} else if(!task->isPackageRequested()) {
|
||||
task->setPackageRequested();
|
||||
m_dependenciesToBeRequested << dep;
|
||||
const auto depPkg = findPackageForDependency(dep);
|
||||
const QString taskName = depPkg ? depPkg->name() : dep.name;
|
||||
auto *depTask = TaskInfo::find(m_tasks, taskName);
|
||||
if(depTask) {
|
||||
// we've already added a task for this dependency
|
||||
// -> add dependency task to the dependencies of "parent" task
|
||||
task->addDep(depTask);
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << "The dependency \"" << dep.name.toLocal8Bit().data() << "\" could not be found; TODO: search AUR for package, add AUR deps to the packages we want to build";
|
||||
throw runtime_error(ss.str());
|
||||
// create new task
|
||||
m_tasks << (depTask = new TaskInfo(taskName, true));
|
||||
// adds dependency task to the dependencies of "parent" task
|
||||
task->addDep(depTask);
|
||||
if(depPkg) {
|
||||
depTask->associatePackage(depPkg);
|
||||
if(m_addSourceOnlyDeps && depPkg->repository()->isSourceOnly()) {
|
||||
depTask->setIsOnlyDependency(false);
|
||||
}
|
||||
// add dependencies of the dependency
|
||||
addDependenciesToTask(depTask, depPkg->dependencies());
|
||||
}
|
||||
}
|
||||
if(!depPkg) {
|
||||
if(!depTask->isPackageRequested()) {
|
||||
depTask->setPackageRequested();
|
||||
m_dependenciesToBeRequested << dep;
|
||||
} else {
|
||||
emit resolvingFailed(QStringLiteral("The specified package \"") % task->name() % QStringLiteral("\" could not be found."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Requests dependencies to be requested.
|
||||
*/
|
||||
void BuildOrderResolver::requestDependenciesToBeRequested()
|
||||
{
|
||||
// check whether there are dependencies to be requested
|
||||
if(!m_dependenciesToBeRequested.isEmpty()) {
|
||||
// print dependencies to be requested
|
||||
if(m_manager.config().isVerbose()) {
|
||||
cerr << shchar << "Dependencies to be requested:";
|
||||
for(const Dependency &dep : m_dependenciesToBeRequested) {
|
||||
cerr << ' ' << dep.name.toStdString();
|
||||
}
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
// do requests (using package finder)
|
||||
m_finder = make_unique<PackageFinder>(m_manager, m_dependenciesToBeRequested);
|
||||
|
||||
// all dependencies requested -> clear dependencies to be requested
|
||||
m_dependenciesToBeRequested.clear();
|
||||
|
||||
// add results
|
||||
if(m_finder->areAllResultsAvailable()) {
|
||||
// results are immediately available (already cached)
|
||||
addRequestedPackages();
|
||||
} else {
|
||||
// need to request actually
|
||||
connect(m_finder.get(), &PackageFinder::resultsAvailable, this, &BuildOrderResolver::addRequestedPackages);
|
||||
}
|
||||
|
||||
} else {
|
||||
// there are no dependencies to be requested -> ready to resolve build order
|
||||
emit ready();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,35 +1,59 @@
|
|||
#ifndef PACKAGEMANAGEMENT_RESOLVEBUILDORDER_H
|
||||
#define PACKAGEMANAGEMENT_RESOLVEBUILDORDER_H
|
||||
|
||||
#include "./packagefinder.h"
|
||||
|
||||
#include <c++utilities/application/argumentparser.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace RepoIndex {
|
||||
|
||||
class Manager;
|
||||
class TaskInfo;
|
||||
class Dependency;
|
||||
class Package;
|
||||
class PackageFinder;
|
||||
|
||||
class BuildOrderResolver
|
||||
class BuildOrderResolver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BuildOrderResolver(const Manager &manager);
|
||||
BuildOrderResolver(Manager &manager, const ApplicationUtilities::StringVector &packages, bool addSourceOnlyDeps = false);
|
||||
~BuildOrderResolver();
|
||||
|
||||
QStringList resolve(const ApplicationUtilities::StringVector &packages);
|
||||
static void printResults(const QStringList &results);
|
||||
void cli();
|
||||
|
||||
void findDependencies();
|
||||
QStringList resultNames();
|
||||
|
||||
public slots:
|
||||
void printRelevantPackages();
|
||||
void printResults();
|
||||
void resolve();
|
||||
|
||||
signals:
|
||||
void ready();
|
||||
void resolvingFinished();
|
||||
void resolvingFailed(const QString &message);
|
||||
|
||||
private slots:
|
||||
void addRequestedPackages();
|
||||
|
||||
private:
|
||||
void addDeps(TaskInfo *task);
|
||||
void addDeps(TaskInfo *task, const QList<Dependency> &dependencies);
|
||||
const Manager &m_manager;
|
||||
Package *findPackageForDependency(const Dependency &dependency);
|
||||
bool addDependenciesToTask(TaskInfo *task);
|
||||
bool addDependenciesToTask(TaskInfo *task, const QList<Dependency> &dependencies);
|
||||
void requestDependenciesToBeRequested();
|
||||
|
||||
Manager &m_manager;
|
||||
QList<TaskInfo *> m_tasks;
|
||||
QList<Dependency> m_dependenciesToBeRequested;
|
||||
|
||||
//PackageFinder m_finder;
|
||||
std::unique_ptr<PackageFinder> m_finder;
|
||||
QList<TaskInfo *> m_results;
|
||||
bool m_addSourceOnlyDeps;
|
||||
};
|
||||
|
||||
} // namespace PackageManagement
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include "./utilities.h"
|
||||
#include "./config.h"
|
||||
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
@ -223,6 +226,28 @@ void printBashArray(ostream &output, const char *name, const QStringList &values
|
|||
output << ' ' << ')' << endl;
|
||||
}
|
||||
|
||||
void printError(const exception &ex)
|
||||
{
|
||||
string message(ex.what());
|
||||
printError(message);
|
||||
}
|
||||
|
||||
void printError(const QString &message)
|
||||
{
|
||||
string msg(message.toStdString());
|
||||
printError(msg);
|
||||
}
|
||||
|
||||
void printError(string &message)
|
||||
{
|
||||
if(useShSyntax) {
|
||||
ConversionUtilities::findAndReplace<string>(message, "'", "\'");
|
||||
cerr << "export REPOINDEX_ERROR='" << message << '\'' << endl;
|
||||
} else {
|
||||
cerr << shchar << "Error: " << message << endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Alpm
|
||||
|
|
|
@ -36,11 +36,13 @@ inline QString qstr(const std::string &str)
|
|||
}
|
||||
|
||||
void printValues(std::ostream &output, const char *label, const QStringList &values);
|
||||
|
||||
void printBashArray(std::ostream &output, const char *name, const QStringList &values);
|
||||
void printError(const std::exception &ex);
|
||||
void printError(const QString &message);
|
||||
void printError(std::string &message);
|
||||
|
||||
}
|
||||
|
||||
} // namespace Alpm
|
||||
}
|
||||
|
||||
#endif // ALPM_UTILITIES_H
|
||||
|
|
19
main.cpp
19
main.cpp
|
@ -77,8 +77,13 @@ int main(int argc, char *argv[])
|
|||
// run Qt loop
|
||||
return application.exec();
|
||||
} else if(configArgs.buildOrderArg.isPresent()) {
|
||||
BuildOrderResolver resolver(manager);
|
||||
BuildOrderResolver::printResults(resolver.resolve(configArgs.buildOrderArg.values()));
|
||||
BuildOrderResolver resolver(manager, configArgs.buildOrderArg.values(), configArgs.addSourceOnlyDeps.isPresent());
|
||||
resolver.cli();
|
||||
QObject::connect(&resolver, &BuildOrderResolver::resolvingFinished, &application, &QCoreApplication::quit);
|
||||
QObject::connect(&resolver, &BuildOrderResolver::resolvingFailed, &application, &QCoreApplication::quit);
|
||||
// run Qt loop
|
||||
return application.exec();
|
||||
//BuildOrderResolver::printResults(resolver.resolve(configArgs.buildOrderArg.values()));
|
||||
} else if(configArgs.mingwBundleArg.isPresent()) {
|
||||
MingwBundle bundle(manager, configArgs.mingwBundleArg.values(), configArgs.iconThemesArg.values(), configArgs.extraPackagesArg.values());
|
||||
bundle.createBundle(configArgs.targetDirArg.isPresent() ? configArgs.targetDirArg.values().front() : string("."),
|
||||
|
@ -96,14 +101,8 @@ int main(int argc, char *argv[])
|
|||
cerr << "No command line arguments specified. See --help for available commands." << endl;
|
||||
}
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
if(useShSyntax) {
|
||||
string error = e.what();
|
||||
ConversionUtilities::findAndReplace<string>(error, "'", "\'");
|
||||
cerr << "export REPOINDEX_ERROR='" << error << '\'' << endl;
|
||||
} else {
|
||||
cerr << shchar << "Error: " << e.what() << endl;
|
||||
}
|
||||
} catch (const exception &ex) {
|
||||
Utilities::printError(ex);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ void AurFullPackageReply::processData(QNetworkReply *reply)
|
|||
//QBuffer buffer;
|
||||
//buffer.setData(reply->readAll());
|
||||
QTemporaryFile tmpFile;
|
||||
tmpFile.setFileTemplate(QDir::tempPath() % QStringLiteral("/") % QStringLiteral("repoindex-XXXXXX.tar.gz"));
|
||||
tmpFile.setFileTemplate(QDir::tempPath() % QChar('/') % QStringLiteral("repoindex-XXXXXX.tar.gz"));
|
||||
tmpFile.open();
|
||||
tmpFile.write(reply->readAll());
|
||||
tmpFile.seek(0);
|
||||
|
@ -272,9 +272,7 @@ AurFullPackageReply *UserRepository::requestFullPackageInfo(const QStringList &p
|
|||
}
|
||||
}
|
||||
} catch(const out_of_range &) {
|
||||
if(forceUpdate) {
|
||||
replies << m_networkAccessManager.get(QNetworkRequest(m_aurSnapshotPath.arg(packageName)));
|
||||
}
|
||||
replies << m_networkAccessManager.get(QNetworkRequest(m_aurSnapshotPath.arg(packageName)));
|
||||
}
|
||||
}
|
||||
if(replies.isEmpty()) {
|
||||
|
|
Loading…
Reference in New Issue