Skip to content

Commit

Permalink
feat: check linglong env and json parser
Browse files Browse the repository at this point in the history
Check ll-cli environment before install;
Add json style ll-cli output parser;
Deb package has higher priority than uab pacakge.

Log: Check linglong env and json parser
Influence: uab-package
  • Loading branch information
rb-union committed Sep 23, 2024
1 parent 3857731 commit f450991
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/deb-installer/model/proxy_package_list_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ ProxyPackageListModel::ModelPtr ProxyPackageListModel::addModel(Pkg::PackageType
newInfo.model = newModel;
m_packageModels.append(newInfo);

// sort, ensure uab package model first.
// sort, ensure deb package model first.
std::sort(m_packageModels.begin(), m_packageModels.end(), [](const ModelInfo &info1, const ModelInfo &info2) {
return info1.model->supportPackage() < info2.model->supportPackage();
});
Expand Down
92 changes: 76 additions & 16 deletions src/deb-installer/uab/uab_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <QJsonObject>
#include <QPointer>
#include <QProcess>
#include <QStandardPaths>
#include <QtConcurrent/QtConcurrentRun>

#include "utils/utils.h"
Expand All @@ -23,6 +24,7 @@ namespace Uab {

// bin command
static const QString kUabCliBin = "ll-cli";
static const QString kUabJson = "--json";
static const QString kUabCliList = "list";
// e.g.: [path to package] --print-meta
static const QString kUabPkgCmdPrintMeta = "--print-meta";
Expand Down Expand Up @@ -123,6 +125,20 @@ bool UabBackend::backendInited() const
return m_init;
}

bool UabBackend::linglongExists() const
{
return m_linglongExists;
}

bool UabBackend::recheckLinglongExists()
{
// find ll-cli in $PATH
const QString execPath = QStandardPaths::findExecutable(kUabCliBin);
m_linglongExists = !execPath.isEmpty();

return m_linglongExists;
}

QString UabBackend::lastError() const
{
return m_lastError;
Expand All @@ -138,33 +154,59 @@ void UabBackend::dumpPackageList() const

void UabBackend::backendInitData(const QList<UabPkgInfo::Ptr> &packageList, const QSet<QString> &archs)
{
recheckLinglongExists();

m_packageList = packageList;
m_supportArchSet = archs;
m_init = true;
Q_EMIT backendInitFinsihed();
}

/**
@brief Get Linglong package list from `ll-cli list`
The packages are sorted by package id and package version.
@note This function will be run in QtConcurrent::run()
*/
void UabBackend::backendProcess(const QPointer<Uab::UabBackend> &notifyPtr)
bool UabBackend::parsePackagesFromRawJson(const QByteArray &jsonData, QList<UabPkgInfo::Ptr> &packageList)
{
QProcess process;
process.start(kUabCliBin, {kUabCliList});
process.waitForFinished();
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &jsonError);
if (QJsonParseError::NoError != jsonError.error) {
qWarning() << qPrintable("Parse ll-cli list json data failed:") << jsonError.errorString();
return false;
}

QByteArray output = process.readAllStandardOutput();
QTextStream stream(&output, QIODevice::ReadOnly);
packageList.clear();
QJsonArray rootArray = doc.array();
for (const auto &value : rootArray) {
if (!value.isObject()) {
continue;
}

QJsonObject item = value.toObject();
auto uabPtr = UabPkgInfo::Ptr::create();

uabPtr->id = item.value(kUabId).toString();
uabPtr->appName = item.value(kUabName).toString();
uabPtr->version = item.value(kUabVersion).toString();
uabPtr->channel = item.value(kUabChannel).toString();
uabPtr->description = item.value(kUabDescription).toString();

QJsonArray archArray = item.value(kUabArch).toArray();
for (const auto &archItem : archArray) {
uabPtr->architecture.append(archItem.toString());
}

packageList.append(uabPtr);
}

return true;
}

bool UabBackend::parsePackagesFromRawOutput(const QByteArray &output, QList<UabPkgInfo::Ptr> &packageList)
{
QTextStream stream(output, QIODevice::ReadOnly);

// remove title
stream.readLine();

QString arch;
QString deprecated;
QList<UabPkgInfo::Ptr> packageList;

while (!stream.atEnd()) {
auto uabPtr = UabPkgInfo::Ptr::create();
Expand All @@ -179,11 +221,29 @@ void UabBackend::backendProcess(const QPointer<Uab::UabBackend> &notifyPtr)

uabPtr->architecture.append(arch);
// to the end of the line
uabPtr->shortDescription = stream.readLine().simplified();
uabPtr->description = stream.readLine().simplified();

packageList.append(uabPtr);
}

return true;
}

/**
@brief Get Linglong package list from `ll-cli list`
The packages are sorted by package id and package version.
@note This function will be run in QtConcurrent::run()
*/
void UabBackend::backendProcess(const QPointer<Uab::UabBackend> &notifyPtr)
{
QProcess process;
process.start(kUabCliBin, {kUabJson, kUabCliList});
process.waitForFinished();

QByteArray output = process.readAllStandardOutput();
QList<UabPkgInfo::Ptr> packageList;
parsePackagesFromRawJson(output, packageList);
sortPackages(packageList);

// detect deb package init
Expand Down Expand Up @@ -286,7 +346,7 @@ UabPkgInfo::Ptr UabBackend::packageFromMetaJson(const QByteArray &json, QString
uabPtr->id = info[kUabId].toString();
uabPtr->appName = info[kUabName].toString();
uabPtr->version = info[kUabVersion].toString();
uabPtr->shortDescription = info[kUabDescription].toString();
uabPtr->description = info[kUabDescription].toString();
uabPtr->channel = info[kUabChannel].toString();

const QJsonArray archArray = info[kUabArch].toArray();
Expand Down Expand Up @@ -334,7 +394,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug out, const Uab::UabPkgInfo &uabPkg)
out << Uab::kUabVersion << ":" << uabPkg.version << ";";
out << Uab::kUabArch << ":" << uabPkg.architecture << ";";
out << Uab::kUabChannel << ":" << uabPkg.channel << ";";
out << Uab::kUabDescription << ":" << uabPkg.shortDescription << ";";
out << Uab::kUabDescription << ":" << uabPkg.description << ";";
out << "filePath:" << uabPkg.filePath << ";";

return out;
Expand Down
6 changes: 6 additions & 0 deletions src/deb-installer/uab/uab_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class UabBackend : public QObject
bool backendInited() const;
Q_SIGNAL void backendInitFinsihed();

bool linglongExists() const;
bool recheckLinglongExists();

QString lastError() const;
void dumpPackageList() const;

Expand All @@ -36,6 +39,8 @@ class UabBackend : public QObject
// internal
Q_SLOT void backendInitData(const QList<UabPkgInfo::Ptr> &packageList, const QSet<QString> &archs);
static void backendProcess(const QPointer<Uab::UabBackend> &notifyPtr);
static bool parsePackagesFromRawJson(const QByteArray &jsonData, QList<UabPkgInfo::Ptr> &packageList);
static bool parsePackagesFromRawOutput(const QByteArray &output, QList<UabPkgInfo::Ptr> &packageList);
static void sortPackages(QList<UabPkgInfo::Ptr> &packageList);

// update backend database after controller process finished.
Expand All @@ -48,6 +53,7 @@ class UabBackend : public QObject

private:
bool m_init{false};
bool m_linglongExists{false}; // check Linglong executable (ll-cli) exists.
QList<UabPkgInfo::Ptr> m_packageList;
QSet<QString> m_supportArchSet;
QString m_lastError;
Expand Down
2 changes: 1 addition & 1 deletion src/deb-installer/uab/uab_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct UabPkgInfo
QString appName; // display name
QString version;
QStringList architecture; // uab package may support multiple arch
QString shortDescription;
QString description;
QString channel;
};

Expand Down
23 changes: 22 additions & 1 deletion src/deb-installer/uab/uab_package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ bool UabPackage::isValid() const
return true;
}

void UabPackage::setDependsStatus(Pkg::DependsStatus status)
{
m_dependsStatus = status;
switch (m_dependsStatus) {
case Pkg::DependsBreak:
m_failReason = QObject::tr("The system has not installed Linglong environment, please install it first");
break;
default:
break;
}
}

Pkg::DependsStatus UabPackage::dependsStatus()
{
return m_dependsStatus;
Expand Down Expand Up @@ -62,7 +74,10 @@ UabPackage::Ptr UabPackage::fromFilePath(const QString &filePath)
QString error;
auto infoPtr = Uab::UabBackend::packageFromMetaData(filePath, &error);
auto uabPtr = Uab::UabPackage::Ptr::create(infoPtr);
uabPtr->m_failReason = error;

if (!error.isEmpty()) {
qWarning() << qPrintable("Uab from path:") << error;
}
return uabPtr;
}

Expand All @@ -77,6 +92,12 @@ void UabPackage::reset()
m_installedVersion.clear();
m_installStatus = Pkg::NotInstalled;

if (!Uab::UabBackend::instance()->linglongExists()) {
setDependsStatus(Pkg::DependsBreak);
} else {
setDependsStatus(Pkg::DependsOk);
}

if (Uab::UabBackend::instance()->backendInited()) {
auto uabInfoPtr = Uab::UabBackend::instance()->findPackage(m_metaPtr->id);
if (uabInfoPtr) {
Expand Down
2 changes: 2 additions & 0 deletions src/deb-installer/uab/uab_package.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class UabPackage

bool isValid() const;

void setDependsStatus(Pkg::DependsStatus status);

Pkg::DependsStatus dependsStatus();
Pkg::PackageInstallStatus installStatus();
Pkg::PackageOperationStatus operationStatus();
Expand Down
15 changes: 14 additions & 1 deletion src/deb-installer/uab/uab_package_list_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ QVariant UabPackageListModel::data(const QModelIndex &index, int role) const
case PackageShortDescriptionRole:
Q_FALLTHROUGH();
case PackageLongDescriptionRole:
return uabPtr->info()->shortDescription;
return uabPtr->info()->description;
case PackageVersionStatusRole:
return uabPtr->installStatus();
case PackageDependsStatusRole:
Expand Down Expand Up @@ -144,6 +144,15 @@ void UabPackageListModel::slotInstallPackages()
return;
}

if (!Uab::UabBackend::instance()->recheckLinglongExists()) {
// todo reset status;
for (const auto &uabPtr : m_uabPkgList) {
uabPtr->setDependsStatus(Pkg::DependsBreak);
Q_EMIT dataChanged(index(0), index(m_uabPkgList.size() - 1), {PackageOperateStatusRole});
}
return;
}

// reset, mark package waiting install
resetInstallStatus();
for (auto uabPtr : m_uabPkgList) {
Expand All @@ -157,6 +166,10 @@ void UabPackageListModel::slotInstallPackages()

void UabPackageListModel::slotUninstallPackage(const int i)
{
if (!Uab::UabBackend::instance()->recheckLinglongExists()) {
// todo reset status;
}

bool callRet = false;

do {
Expand Down
Loading

0 comments on commit f450991

Please sign in to comment.