diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 26f5158cb..36be25339 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -145,7 +145,7 @@ utils::error::Result pullDependency(const package::FuzzyRefe printReplacedText(QString("%1%2%3%4 %5") .arg(ref->id, -25) .arg(ref->version.toString(), -15) - .arg(develop ? "develop" : "runtime", -15) + .arg(develop ? "develop" : "binary", -15) .arg("downloading") .arg(percentage) .toStdString(), @@ -204,16 +204,16 @@ void Builder::setConfig(const api::types::v1::BuilderConfig &cfg) noexcept this->cfg = cfg; } -// 拆分develop和runtime的文件 +// 拆分develop和binary的文件 utils::error::Result Builder::splitDevelop(QDir developOutput, - QDir runtimeOutput, + QDir binaryOutput, QString prefix) { LINGLONG_TRACE("split layers file"); const QString installFilename = QString("%1.install").arg(QString::fromStdString(project.package.id)); const QString src = developOutput.absolutePath(); - const QString dest = runtimeOutput.absolutePath(); + const QString dest = binaryOutput.absolutePath(); // get install file rule QStringList installRules; @@ -326,7 +326,7 @@ utils::error::Result Builder::splitDevelop(QDir developOutput, } } } - for (auto dir : { developOutput, runtimeOutput }) { + for (auto dir : { developOutput, binaryOutput }) { // save all installed file path to ${appid}.install const auto installRulePath = dir.filePath("../" + installFilename); QFile configFile(installRulePath); @@ -578,11 +578,11 @@ utils::error::Result Builder::build(const QStringList &args) noexcept } printMessage("[Commit Contents]"); - QDir runtimeOutput = this->workingDir.absoluteFilePath("linglong/output/runtime/files"); - if (!runtimeOutput.mkpath(".")) { - return LINGLONG_ERR("make path " + runtimeOutput.absolutePath() + ": failed."); + QDir binaryOutput = this->workingDir.absoluteFilePath("linglong/output/binary/files"); + if (!binaryOutput.mkpath(".")) { + return LINGLONG_ERR("make path " + binaryOutput.absolutePath() + ": failed."); } - qDebug() << "create runtime output success"; + qDebug() << "create binary output success"; // generate application's configure file auto scriptFile = QString(LINGLONG_LIBEXEC_DIR) + "/app-conf-generator"; @@ -605,27 +605,27 @@ utils::error::Result Builder::build(const QStringList &args) noexcept } auto ret = - splitDevelop(developOutput.absolutePath(), runtimeOutput.absolutePath(), installPrefix); + splitDevelop(developOutput.absolutePath(), binaryOutput.absolutePath(), installPrefix); if (!ret) { return LINGLONG_ERR(ret); } if (this->project.package.kind != "runtime") { - QDir runtimeEntries = this->workingDir.absoluteFilePath("linglong/output/runtime/entries"); + QDir binaryEntries = this->workingDir.absoluteFilePath("linglong/output/binary/entries"); QDir developEntries = this->workingDir.absoluteFilePath("linglong/output/develop/entries"); - if (!runtimeEntries.mkpath(".")) { - return LINGLONG_ERR("make path " + runtimeEntries.absolutePath() + ": failed."); + if (!binaryEntries.mkpath(".")) { + return LINGLONG_ERR("make path " + binaryEntries.absolutePath() + ": failed."); } if (!developEntries.mkpath(".")) { return LINGLONG_ERR("make path " + developEntries.absolutePath() + ": failed."); } - if (!QFile::link("../files/share", runtimeEntries.absoluteFilePath("share"))) { + if (!QFile::link("../files/share", binaryEntries.absoluteFilePath("share"))) { return LINGLONG_ERR("link entries share to files share: failed"); } - if (!runtimeOutput.mkpath("share/systemd")) { + if (!binaryOutput.mkpath("share/systemd")) { return LINGLONG_ERR("mkpath files/share/systemd/user: failed"); } if (!QFile::link("../../lib/systemd/user", - runtimeOutput.absoluteFilePath("share/systemd/user"))) { + binaryOutput.absoluteFilePath("share/systemd/user"))) { return LINGLONG_ERR("link systemd user service to files/share/systemd/user: failed"); } if (!QFile::link("../files/share", developEntries.absoluteFilePath("share"))) { @@ -659,12 +659,12 @@ utils::error::Result Builder::build(const QStringList &args) noexcept .description = this->project.package.description, .id = this->project.package.id, .kind = this->project.package.kind, - .packageInfoV2Module = "runtime", + .packageInfoV2Module = "binary", .name = this->project.package.name, .permissions = this->project.permissions, .runtime = {}, .schemaVersion = PACKAGE_INFO_VERSION, - .size = static_cast(util::sizeOfDir(runtimeOutput.absoluteFilePath(".."))), + .size = static_cast(util::sizeOfDir(binaryOutput.absoluteFilePath(".."))), .version = this->project.package.version, }; @@ -678,7 +678,7 @@ utils::error::Result Builder::build(const QStringList &args) noexcept info.runtime = runtime->toString().toStdString(); } - QFile infoFile = runtimeOutput.absoluteFilePath("../info.json"); + QFile infoFile = binaryOutput.absoluteFilePath("../info.json"); if (!infoFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return LINGLONG_ERR(infoFile); } @@ -703,12 +703,12 @@ utils::error::Result Builder::build(const QStringList &args) noexcept return LINGLONG_ERR(infoFile); } infoFile.close(); - package::LayerDir runtimeOutputLayerDir = runtimeOutput.absoluteFilePath(".."); + package::LayerDir binaryOutputLayerDir = binaryOutput.absoluteFilePath(".."); result = this->repo.remove(*ref); if (!result) { qWarning() << "remove" << ref->toString() << result.error().message(); } - result = this->repo.importLayerDir(runtimeOutputLayerDir); + result = this->repo.importLayerDir(binaryOutputLayerDir); if (!result) { return LINGLONG_ERR(result); } @@ -743,16 +743,16 @@ utils::error::Result Builder::exportLayer(const QString &destination) return LINGLONG_ERR(ref); } - auto runtimeLayerDir = this->repo.getLayerDir(*ref); - if (!runtimeLayerDir) { - return LINGLONG_ERR(runtimeLayerDir); + auto binaryLayerDir = this->repo.getLayerDir(*ref); + if (!binaryLayerDir) { + return LINGLONG_ERR(binaryLayerDir); } - const auto runtimeLayerPath = QString("%1/%2_%3_%4_%5.layer") + const auto binaryLayerPath = QString("%1/%2_%3_%4_%5.layer") .arg(destDir.absolutePath(), ref->id, ref->version.toString(), ref->arch.toString(), - "runtime"); + "binary"); auto developLayerDir = this->repo.getLayerDir(*ref, true); const auto develLayerPath = QString("%1/%2_%3_%4_%5.layer") @@ -767,9 +767,9 @@ utils::error::Result Builder::exportLayer(const QString &destination) package::LayerPackager pkger; - auto runtimeLayer = pkger.pack(*runtimeLayerDir, runtimeLayerPath); - if (!runtimeLayer) { - return LINGLONG_ERR(runtimeLayer); + auto binaryLayer = pkger.pack(*binaryLayerDir, binaryLayerPath); + if (!binaryLayer) { + return LINGLONG_ERR(binaryLayer); } auto develLayer = pkger.pack(*developLayerDir, develLayerPath); diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 3fde8b43b..9006e45c1 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -242,6 +242,7 @@ void progress_changed(OstreeAsyncProgress *progress, gpointer user_data) QString ostreeSpecFromReference(const package::Reference &ref, bool develop = false) noexcept { + // deprecated later, should we add Q_DECL_DEPRECATED ? if (develop) { return QString("%1/%2/%3/%4/develop") .arg(ref.channel, ref.id, ref.version.toString(), ref.arch.toString()); @@ -251,6 +252,17 @@ QString ostreeSpecFromReference(const package::Reference &ref, bool develop = fa .arg(ref.channel, ref.id, ref.version.toString(), ref.arch.toString()); } +QString ostreeSpecFromReferenceV2(const package::Reference &ref, bool develop = false) noexcept +{ + if (develop) { + return QString("%1/%2/%3/%4/develop") + .arg(ref.channel, ref.id, ref.version.toString(), ref.arch.toString()); + } + + return QString("%1/%2/%3/%4/binary") + .arg(ref.channel, ref.id, ref.version.toString(), ref.arch.toString()); +} + utils::error::Result removeOstreeRef(OstreeRepo *repo, const char *ref) noexcept { Q_ASSERT(ref); @@ -659,9 +671,16 @@ utils::error::Result clearReferenceRemote(const package::Fuz QDir OSTreeRepo::getLayerQDir(const package::Reference &ref, bool develop) const noexcept { + // for old ref which module is runtime return this->repoDir.absoluteFilePath("layers/" + ostreeSpecFromReference(ref, develop)); } +QDir OSTreeRepo::getLayerQDirV2(const package::Reference &ref, bool develop) const noexcept +{ + // for new ref which module is binary + return this->repoDir.absoluteFilePath("layers/" + ostreeSpecFromReferenceV2(ref, develop)); +} + QDir OSTreeRepo::ostreeRepoDir() const noexcept { Q_ASSERT(!this->repoDir.path().isEmpty()); @@ -806,7 +825,7 @@ utils::error::Result OSTreeRepo::importLayerDir(const package::LayerDir &d return LINGLONG_ERR(reference->toString() + " exists."); } - const auto refspec = ostreeSpecFromReference(*reference, isDevel).toUtf8(); + const auto refspec = ostreeSpecFromReferenceV2(*reference, isDevel).toUtf8(); auto result = commitDirToRepo(gFile, this->ostreeRepo.get(), refspec); if (!result) { @@ -821,7 +840,7 @@ utils::error::Result OSTreeRepo::importLayerDir(const package::LayerDir &d }); result = handleRepositoryUpdate(this->ostreeRepo.get(), - this->getLayerQDir(*reference, isDevel), + this->getLayerQDirV2(*reference, isDevel), refspec); if (!result) { return LINGLONG_ERR(result); @@ -889,7 +908,7 @@ utils::error::Result OSTreeRepo::push(const package::Reference &ref, utils::error::Result result; api::client::Schema_NewUploadTaskReq uploadReq; - uploadReq.setRef(ostreeSpecFromReference(ref, develop)); + uploadReq.setRef(ostreeSpecFromReferenceV2(ref, develop)); uploadReq.setRepoName(QString::fromStdString(this->cfg.defaultRepo)); auto apiClient = this->m_clientFactory.createClient(); @@ -934,7 +953,7 @@ utils::error::Result OSTreeRepo::push(const package::Reference &ref, QStringList args = { "-zcf", tarFilePath, "-C", - this->getLayerQDir(ref, develop).absolutePath(), + this->getLayerQDirV2(ref, develop).absolutePath(), "." }; auto tarStdout = utils::command::Exec("tar", args); if (!tarStdout) { @@ -997,7 +1016,7 @@ utils::error::Result OSTreeRepo::push(const package::Reference &ref, return; } qDebug() << "pushing" << ref.toString() - << (develop ? "develop" : "runtime") + << (develop ? "develop" : "binary") << " status: " << resp.getData().getStatus(); if (resp.getData().getStatus() == "complete") { isFinished = true; @@ -1044,7 +1063,12 @@ utils::error::Result OSTreeRepo::remove(const package::Reference &ref, boo { LINGLONG_TRACE("remove " + ref.toString()); - auto layerDir = this->getLayerQDir(ref, develop); + auto layerDir = this->getLayerQDirV2(ref, develop); + if (!layerDir.exists()) { + // fallback to old ref + layerDir = this->getLayerQDir(ref, develop); + } + if (!layerDir.removeRecursively()) { qCritical() << "Failed to remove layer directory of" << ref.toString() << "develop:" << develop; @@ -1069,10 +1093,18 @@ utils::error::Result OSTreeRepo::remove(const package::Reference &ref, boo } } - auto refspec = ostreeSpecFromReference(ref, develop).toUtf8(); + // remove ref from ostree repo, try new ref first + auto refspec = ostreeSpecFromReferenceV2(ref, develop).toUtf8(); const auto *data = refspec.constData(); auto result = removeOstreeRef(this->ostreeRepo.get(), data); + if (result) { + return LINGLONG_OK; + } + + // fallback to old ref + refspec = ostreeSpecFromReference(ref, develop).toUtf8(); + result = removeOstreeRef(this->ostreeRepo.get(), refspec.constData()); if (!result) { return LINGLONG_ERR(result); } @@ -1084,7 +1116,7 @@ void OSTreeRepo::pull(std::shared_ptr taskContext, const package::Reference &reference, bool develop) noexcept { - const auto refString = ostreeSpecFromReference(reference, develop).toUtf8(); + auto refString = ostreeSpecFromReferenceV2(reference, develop).toUtf8(); LINGLONG_TRACE("pull " + refString); @@ -1098,17 +1130,34 @@ void OSTreeRepo::pull(std::shared_ptr taskContext, Q_ASSERT(progress != nullptr); g_autoptr(GError) gErr = nullptr; - if (ostree_repo_pull(this->ostreeRepo.get(), - this->cfg.defaultRepo.c_str(), - refs, - OSTREE_REPO_PULL_FLAGS_MIRROR, - progress, - cancellable, - &gErr) - == FALSE) { - taskContext->updateStatus(service::InstallTask::Failed, - LINGLONG_ERRV("ostree_repo_pull", gErr)); - return; + auto status = ostree_repo_pull(this->ostreeRepo.get(), + this->cfg.defaultRepo.c_str(), + refs, + OSTREE_REPO_PULL_FLAGS_MIRROR, + progress, + cancellable, + &gErr); + if (status == FALSE) { + // fallback to old ref + qWarning() << gErr->message; + refString = ostreeSpecFromReference(reference, develop).toUtf8(); + qWarning() << "fallback to module runtime, pull " << refString; + + char *oldRefs[] = { (char *)refString.data(), nullptr }; + + g_clear_error(&gErr); + status = ostree_repo_pull(this->ostreeRepo.get(), + this->cfg.defaultRepo.c_str(), + oldRefs, + OSTREE_REPO_PULL_FLAGS_MIRROR, + progress, + cancellable, + &gErr); + if (status == FALSE) { + taskContext->updateStatus(service::InstallTask::Failed, + LINGLONG_ERRV("ostree_repo_pull", gErr)); + return; + } } transaction.addRollBack([this, &reference, &develop]() noexcept { @@ -1120,7 +1169,7 @@ void OSTreeRepo::pull(std::shared_ptr taskContext, }); auto result = handleRepositoryUpdate(this->ostreeRepo.get(), - this->getLayerQDir(reference, develop), + this->getLayerQDirV2(reference, develop), refString); if (!result) { taskContext->updateStatus(service::InstallTask::Failed, LINGLONG_ERRV(result)); @@ -1169,9 +1218,13 @@ OSTreeRepo::listLocal() const noexcept Q_ASSERT(layersDir.exists()); auto pushBackPkgInfos = [&pkgInfos](QDir &dir) noexcept { - const QString runtimePkgInfoFilePath = dir.absoluteFilePath("runtime/info.json"); - if (QFile::exists(runtimePkgInfoFilePath)) { - auto pkgInfo = utils::parsePackageInfo(runtimePkgInfoFilePath); + QString binaryPkgInfoFilePath = dir.absoluteFilePath("binary/info.json"); + if (!QFile::exists(binaryPkgInfoFilePath)) { + // fallback to old ref + binaryPkgInfoFilePath = dir.absoluteFilePath("runtime/info.json"); + } + if (QFile::exists(binaryPkgInfoFilePath)) { + auto pkgInfo = utils::parsePackageInfo(binaryPkgInfoFilePath); if (pkgInfo) { pkgInfos.emplace_back(std::move(*pkgInfo)); } @@ -1313,13 +1366,34 @@ void OSTreeRepo::removeDanglingXDGIntergation() noexcept void OSTreeRepo::unexportReference(const package::Reference &ref) noexcept { - auto layerQDir = this->getLayerQDir(ref); - // if uninstall package, call removeDanglingXDGIntergation() - if (!layerQDir.exists()) { + /* + V1 id/version/arch/{runtime} + V2 id/version/arch/{binary} + + oldLayerQDir.exists() | newLayerQDir.exists() | status + false | false | uninstall + false | true | upgrade V2->V2 + true | false | upgrade V1->V2 + true | true | impossible, this is invalid + */ + QDir layerQDir; + auto oldLayerQDir = this->getLayerQDir(ref); + auto newLayerQDir = this->getLayerQDirV2(ref); + // if no layerQDir exists, this package should have been removed + // call removeDanglingXDGIntergation() to clean symlinks + if (!oldLayerQDir.exists() && !newLayerQDir.exists()) { removeDanglingXDGIntergation(); return; } + if (oldLayerQDir.exists()) { + layerQDir = oldLayerQDir; + } + + if (newLayerQDir.exists()) { + layerQDir = newLayerQDir; + } + // if upgrade package QDir entriesDir = this->repoDir.absoluteFilePath("entries/share"); QDirIterator it(entriesDir.absolutePath(), @@ -1406,7 +1480,7 @@ void OSTreeRepo::exportReference(const package::Reference &ref) noexcept entriesDir.mkpath("."); } - auto layerDir = this->getLayerQDir(ref); + auto layerDir = this->getLayerQDirV2(ref); auto layerEntriesDir = QDir(layerDir.absoluteFilePath("entries/share")); if (!layerEntriesDir.exists()) { Q_ASSERT(false); @@ -1497,7 +1571,13 @@ auto OSTreeRepo::getLayerDir(const package::Reference &ref, bool develop) const -> utils::error::Result { LINGLONG_TRACE("get dir of " + ref.toString()); - auto dir = this->getLayerQDir(ref, develop); + auto dir = this->getLayerQDirV2(ref, develop); + if (dir.exists()) { + return dir.absolutePath(); + } + + // fallback to old ref path, + dir = this->getLayerQDir(ref, develop); if (!dir.exists()) { return LINGLONG_ERR(dir.path() + " not exist."); } diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index 87a640c3c..0468e2d40 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -91,6 +91,7 @@ class OSTreeRepo : public QObject QDir repoDir; QDir ostreeRepoDir() const noexcept; QDir getLayerQDir(const package::Reference &ref, bool develop = false) const noexcept; + QDir getLayerQDirV2(const package::Reference &ref, bool develop = false) const noexcept; ClientFactory &m_clientFactory; };