#include <memory>
#include <tuple>
#include <utility>
+#include <vector>
#include <boost/filesystem/path.hpp>
namespace common_installer {
-void DependencyChecker::AddEdge(const std::string& from,
- const std::string& to) {
- dep_graph_[from].push_back(to);
+static bool InvalidDependencyError(const std::string& from,
+ const std::string& to, const std::string& required_version) {
+ LOG(ERROR) << "Dependency [" << from << "] -> [" << to
+ << (required_version.empty() ? "" : "(>=" + required_version + ")")
+ << "] is not met";
+ return false;
}
bool DependencyChecker::AddInstaller(InstallerPtr installer) {
return true;
}
-bool DependencyChecker::CheckInstallPkgDependencyInfo() {
- for (const DependencyInfo& dep_info : dep_info_) {
- std::string from = std::get<0>(dep_info);
- std::string to = std::get<1>(dep_info);
- utils::VersionNumber req_version(std::get<3>(dep_info));
- utils::VersionNumber actual_pkg_version("");
+std::list<InstallerPtr> DependencyChecker::GetSortedAppInstallers() {
+ std::list<InstallerPtr> result;
+ if (!CheckMeetDependency())
+ return {};
+ if (!TopologicalSort(&result))
+ return {};
+
+ return result;
+}
- if (pkg_version_.count(to)) {
- actual_pkg_version = utils::VersionNumber(pkg_version_[to]);
+bool DependencyChecker::CheckMeetDependency() {
+ if (!CheckInstallPkg())
+ return false;
+ if (!CheckUninstallPkg())
+ return false;
+
+ return true;
+}
+
+bool DependencyChecker::CheckRequires(const std::string& pkgid) {
+ for (const auto& dep_info : dep_graph_[pkgid]) {
+ std::string require_pkgid = dep_info.first;
+ std::string require_version = dep_info.second;
+ std::string actual_pkg_version;
+ if (install_pkgs_.count(require_pkgid)) {
+ actual_pkg_version = install_pkgs_[require_pkgid];
} else {
- PkgQueryInterface pkg_query(to, uid_, true);
- if (!pkg_query.IsValid()) {
- LOG(ERROR) << "dependency [" << from << "] -> [" << to
- << "] not met [" << to << "] package is not exist";
- return false;
- }
- actual_pkg_version = utils::VersionNumber(pkg_query.Version());
+ PkgQueryInterface pkg_query(require_pkgid, pkgmgr_->GetUid());
+ if (!pkg_query.IsValid())
+ return InvalidDependencyError(pkgid, require_pkgid, require_version);
+ actual_pkg_version = pkg_query.Version();
}
- if (req_version.ToString().empty())
+ if (utils::VersionNumber(actual_pkg_version).Compare(
+ utils::VersionNumber(require_version)) < 0)
+ return InvalidDependencyError(pkgid, require_pkgid, require_version);
+ }
+ return true;
+}
+
+bool DependencyChecker::CheckRequiredBy(const std::string& pkgid,
+ const std::string& pkg_version) {
+ PkgQueryInterface pkg_query(pkgid, pkgmgr_->GetUid());
+ if (!pkg_query.IsValid())
+ return true;
+
+ std::vector<DependencyInfo> dep_info;
+ if (!pkg_query.PackagesDependsOn(&dep_info)) {
+ LOG(ERROR) << "Failed to get depends on information of package";
+ return false;
+ }
+ for (const auto& info : dep_info) {
+ std::string from = std::get<0>(info);
+ std::string to = std::get<1>(info);
+ std::string type = std::get<2>(info);
+ std::string dependent_version = std::get<3>(info);
+
+ if (to != pkgid || type != kRequiredDependencyType
+ || dependent_version.empty() || install_pkgs_.count(from))
continue;
- if (actual_pkg_version.Compare(req_version) < 0) {
- LOG(ERROR) << "Same or higher version (" << req_version.ToString()
- << ") of " << to
- << " is required but current version of installed package is: "
- << actual_pkg_version.ToString();
- return false;
- }
+ if (utils::VersionNumber(pkg_version).Compare(
+ utils::VersionNumber(dependent_version)) < 0)
+ return InvalidDependencyError(from, to, dependent_version);
}
return true;
}
-bool DependencyChecker::CheckUninstallPkgDependencyInfo() {
- for (const DependencyInfo& dep_info : dep_info_) {
- std::string from = std::get<0>(dep_info);
- std::string to = std::get<1>(dep_info);
- if (uninstall_pkgs_.count(to) && !uninstall_pkgs_.count(from)) {
- LOG(ERROR) << "Pkg[" << from << "] requires Pkg[" << to << "]";
+bool DependencyChecker::CheckInstallPkg() {
+ for (const auto& install_pkg : install_pkgs_) {
+ std::string pkgid = install_pkg.first;
+ std::string pkg_version = install_pkg.second;
+ if (!CheckRequires(pkgid))
+ return false;
+ if (!CheckRequiredBy(pkgid, pkg_version))
return false;
- }
}
return true;
}
-bool DependencyChecker::CheckMeetDependency() {
- if (!CheckInstallPkgDependencyInfo())
- return false;
- if (!CheckUninstallPkgDependencyInfo())
- return false;
-
+bool DependencyChecker::CheckUninstallPkg() {
+ for (const auto& pkgid : uninstall_pkgs_) {
+ PkgQueryInterface pkg_query(pkgid, pkgmgr_->GetUid());
+ std::vector<DependencyInfo> dep_info;
+ if (!pkg_query.PackagesDependsOn(&dep_info)) {
+ LOG(ERROR) << "Failed to get depends on information of package";
+ return false;
+ }
+ for (const auto& info : dep_info) {
+ std::string from = std::get<0>(info);
+ std::string to = std::get<1>(info);
+ std::string type = std::get<2>(info);
+ std::string dependent_version = std::get<3>(info);
+
+ if (to != pkgid || type != kRequiredDependencyType)
+ continue;
+ if (uninstall_pkgs_.count(from) == 0)
+ return InvalidDependencyError(from, to, dependent_version);
+ }
+ }
return true;
}
}
}
visited_.emplace(node);
- bool ret = true;
- for (const std::string& next_node : dep_graph_[node])
- ret &= DFS(next_node, result);
+
+ for (const auto& next_node : dep_graph_[node]) {
+ std::string pkgid = next_node.first;
+ if (!DFS(pkgid, result))
+ return false;
+ }
if (installers_.count(node))
result->emplace_back(std::move(installers_[node]));
finished_.emplace(node);
- return ret;
+ return true;
}
bool DependencyChecker::GetDepInfoFromArchive(InstallerPtr installer) {
std::string pkgid = archive_info->pkgid();
std::string version = archive_info->version();
std::vector<Dependency> dependencies = archive_info->dependencies();
- std::list<DependencyInfo> pkg_dep_info;
for (const Dependency& dep : dependencies) {
std::string dep_pkg = std::get<0>(dep);
if (type != kRequiredDependencyType)
continue;
- pkg_dep_info.emplace_back(pkgid, dep_pkg, type, required_version);
+ dep_graph_[pkgid].emplace(dep_pkg, required_version);
}
- pkg_version_[pkgid] = version;
- dep_info_.splice(dep_info_.end(), pkg_dep_info);
+ install_pkgs_[pkgid] = version;
installers_.emplace(pkgid, std::move(installer));
request_pkgid_.emplace_back(pkgid);
bool DependencyChecker::GetDepInfoFromDB(InstallerPtr installer) {
std::string pkgid = pkgmgr_->GetRequestInfo(installer->GetIndex());
- PkgQueryInterface pkg_query(pkgid, uid_, true);
+ PkgQueryInterface pkg_query(pkgid, pkgmgr_->GetUid());
std::vector<DependencyInfo> dep_info;
if (!pkg_query.PackagesDependsOn(&dep_info)) {
LOG(ERROR) << "get packages depens on fail";
return false;
}
- std::list<DependencyInfo> pkg_dep_info;
for (const auto& info : dep_info) {
std::string from = std::get<0>(info);
if (type != kRequiredDependencyType)
continue;
- pkg_dep_info.emplace_back(from, to, type, version);
+ dep_graph_[from].emplace(to, version);
}
uninstall_pkgs_.emplace(pkgid);
- dep_info_.splice(dep_info_.end(), pkg_dep_info);
installers_.emplace(pkgid, std::move(installer));
request_pkgid_.emplace_back(pkgid);
bool DependencyChecker::GetDepInfoFromXML(InstallerPtr installer) {
std::string pkgid = pkgmgr_->GetRequestInfo(installer->GetIndex());
- PkgQueryInterface pkg_query(pkgid, uid_, true);
+ PkgQueryInterface pkg_query(pkgid, pkgmgr_->GetUid());
bf::path xml_path =
- bf::path(getUserManifestPath(uid_, true)) /
+ bf::path(getUserManifestPath(pkgmgr_->GetUid(), true)) /
bf::path(pkgid + ".xml");
if (!bf::exists(xml_path)) {
LOG(ERROR) << "Package info manifest data has not been found.";
return false;
}
+ install_pkgs_[pkgid] = pkg_info->version();
+ installers_.emplace(pkgid, std::move(installer));
+ request_pkgid_.emplace_back(pkgid);
std::shared_ptr<const tpk::parse::DependenciesInfo> dependencies_info =
std::static_pointer_cast<const tpk::parse::DependenciesInfo>(
parser.GetManifestData(tpk::application_keys::kDependenciesKey));
- if (!dependencies_info) {
- LOG(ERROR) << "dependencies info is null";
- pkg_version_[pkgid] = pkg_info->version();
- installers_.emplace(pkgid, std::move(installer));
- request_pkgid_.emplace_back(pkgid);
+ if (!dependencies_info)
return true;
- }
- std::list<DependencyInfo> pkg_dep_info;
for (const auto& dependency : dependencies_info->dependencies()) {
if (dependency.type() != kRequiredDependencyType)
continue;
- pkg_dep_info.emplace_back(pkgid, dependency.pkgid(),
- dependency.type(), dependency.required_version());
- }
-
- pkg_version_[pkgid] = pkg_info->version();
- dep_info_.splice(dep_info_.end(), pkg_dep_info);
- installers_.emplace(pkgid, std::move(installer));
- request_pkgid_.emplace_back(pkgid);
-
- return true;
-}
-
-std::list<InstallerPtr> DependencyChecker::GetSortedAppInstallers() {
- std::list<InstallerPtr> result;
- if (!CheckMeetDependency())
- return {};
- if (!MakeGraph())
- return {};
- if (!TopologicalSort(&result))
- return {};
-
- return result;
-}
-
-bool DependencyChecker::MakeGraph() {
- for (const DependencyInfo& dep_info : dep_info_) {
- std::string from = std::get<0>(dep_info);
- std::string to = std::get<1>(dep_info);
- AddEdge(from, to);
+ dep_graph_[pkgid].emplace(dependency.pkgid(),
+ dependency.required_version());
}
return true;