diff --git a/src/manager.cpp b/src/manager.cpp index ca462a2..13475d7 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -20,7 +20,7 @@ optional Manager::getPackage(string name) { bool Manager::install(std::string packageName) { // lookup package name (default to latest version) - auto pkg = package_list->lookup(packageName); + auto pkg = package_list->find_package(packageName); if (!pkg) { std::cerr << "Package " << packageName << " not found." << std::endl; diff --git a/src/package.cpp b/src/package.cpp index f0579e4..2b55335 100644 --- a/src/package.cpp +++ b/src/package.cpp @@ -119,13 +119,24 @@ void from_json(const json& j, PackageVersion& p) { j.at("files").get_to(p.files); } +// find the latest compatible version +// TODO expand filtering criteria beyond OS optional Package::latest_version(string os) { - optional latest; + optional latest_package; + optional latest_version; + + for (PackageVersion pkg_ver : versions) { + if (pkg_ver.os != os) continue; + + Version version = parseVersionString(pkg_ver.version); + + if (version > latest_version) { + latest_package = pkg_ver; + latest_version = version; + } - for (PackageVersion ver : versions) { - if (ver.os != os) continue; } - return {}; + return latest_package; } // converts a string of the format "1.2.3" into a Version struct diff --git a/src/package_list.cpp b/src/package_list.cpp index ecfa90b..d80e7c3 100644 --- a/src/package_list.cpp +++ b/src/package_list.cpp @@ -6,7 +6,9 @@ PackageList::PackageList() { // throw std::runtime_error("not implemented"); } -PackageList::PackageList(string filepath) { +PackageList::PackageList(string filepath, string operating_system) { + os = operating_system; + std::ifstream f(filepath); // TODO better error checks @@ -27,20 +29,35 @@ PackageList::PackageList(string filepath) { } } -optional PackageList::lookup(string name) { - // TODO get highest version (how do I do that?) +optional PackageList::find_package(string name) { for (auto package: packages) { if (package.name == name) { return package; } } + return {}; } -optional PackageList::lookup(string name, string version) { +optional PackageList::find_latest_package_version(string name) { + // TODO get highest version (how do I do that?) for (auto package: packages) { if (package.name == name) { - return package; + string os = whichOS(); + return package.latest_version(os); + } + } + return {}; +} + +optional PackageList::find_package_version(string name, string version) { + for (auto package: packages) { + if (package.name == name) { + for (auto package_version: package.versions) { + if (package_version.version == version) { + return package_version; + } + } } } return {}; diff --git a/src/package_list.h b/src/package_list.h index 59a13bc..e9c8fc1 100644 --- a/src/package_list.h +++ b/src/package_list.h @@ -6,6 +6,7 @@ #include #include "package.h" +#include "util.h" using json = nlohmann::json; using std::string; @@ -17,14 +18,17 @@ using std::optional; class PackageList { public: PackageList(); - PackageList(string filepath); + PackageList(string filepath) : PackageList(filepath, whichOS()) {}; + // set OS explicitly for unit tests + PackageList(string filepath, string operating_system); public: + optional find_package(string name); // return latest (maybe latest && most compatible?) version of package - optional lookup(string name); + optional find_latest_package_version(string name); // return specific version of package - optional lookup(string name, string version); + optional find_package_version(string name, string version); /* static void from_json(const json& j, PackageList& pkg_list); */ @@ -32,6 +36,9 @@ class PackageList { private: // TODO could be a more efficient lookup implementation std::vector packages; + + // set OS at initialization time + string os; }; #endif diff --git a/src/test/data/test-package-list.json b/src/test/data/test-package-list.json index 83d60fe..c0808fa 100644 --- a/src/test/data/test-package-list.json +++ b/src/test/data/test-package-list.json @@ -10,11 +10,18 @@ "keywords": ["KeywordA", "KeywordB"], "versions": [ { - "version": "1.0", + "version": "1.0.0", "api_version": "9.0", "language_version": "1.5.2.1", "os": "linux", "files": ["https://ccrma.stanford.edu/~nshaheed/chugins/Hydra/linux/butt.chug"] + }, + { + "version": "0.9.1", + "api_version": "8.8", + "language_version": "1.5.0.1", + "os": "linux", + "files": ["https://ccrma.stanford.edu/~nshaheed/chugins/Hydra/linux/butt.chug"] } ] } diff --git a/src/test/package_list_test.cpp b/src/test/package_list_test.cpp index c6ff79d..b09e297 100644 --- a/src/test/package_list_test.cpp +++ b/src/test/package_list_test.cpp @@ -5,7 +5,7 @@ using std::optional; TEST_CASE("Load db file", "[PackageList]") { std::string path = "./data/test-package-list.json"; - PackageList pkglist = PackageList(path); + PackageList pkglist = PackageList(path, "linux"); Package want; PackageVersion version; @@ -29,15 +29,50 @@ TEST_CASE("Load db file", "[PackageList]") { // Package want = {"John", "Butt", "1.0", "9.0", {{"linux", {"https://ccrma.stanford.edu/~nshaheed/chugins/Hydra/linux/butt.chug"}}}, "http://example.com", "http://repo.com", "specA", {"AuthorA", "AuthorB"}, "MIT", "DescriptionA", {"KeywordA", "KeywordB"}}; - optional got = pkglist.lookup("Butt"); + optional got = pkglist.find_package("Butt"); + REQUIRE(got.has_value()); - REQUIRE(got == want); + REQUIRE(got.value().name == want.name); + REQUIRE(got.value().versions.size() > 0); +} + +TEST_CASE("Find Package") { + std::string path = "./data/test-package-list.json"; + PackageList pkglist = PackageList(path, "linux"); + + SECTION("Successfully find package") { + optional pkg = pkglist.find_package("Butt"); + REQUIRE(pkg.value().name == "Butt"); + } + + SECTION("Can't find package") { + optional pkg = pkglist.find_package("Fork"); + REQUIRE_FALSE(pkg); + } +} + +TEST_CASE("Find Package Version") { + std::string path = "./data/test-package-list.json"; + PackageList pkglist = PackageList(path, "linux"); + + SECTION("Successfully find package") { + optional version = pkglist.find_latest_package_version("Butt"); + REQUIRE(version.value().version == "1.0.0"); + } - got = pkglist.lookup("Butt", "1.0"); - REQUIRE(got == want); + SECTION("Can't find package") { + optional version = pkglist.find_latest_package_version("Fork"); + REQUIRE_FALSE(version); + } + SECTION("Successfully find version") { + optional version = pkglist.find_package_version("Butt", "1.0.0"); + REQUIRE(version.value().version == "1.0.0"); + } - got = pkglist.lookup("NotReal"); - REQUIRE_FALSE(got); + SECTION("Unsuccessfully find version") { + optional version = pkglist.find_package_version("Butt", "1.2.0"); + REQUIRE_FALSE(version.has_value()); + } } diff --git a/src/uninstaller.cpp b/src/uninstaller.cpp index e082cc2..8c6251c 100644 --- a/src/uninstaller.cpp +++ b/src/uninstaller.cpp @@ -7,7 +7,7 @@ Uninstaller::Uninstaller(PackageList* pkg_list) { bool Uninstaller::uninstall(std::string package_name) { // lookup package name (default to latest version) - auto pkg = package_list->lookup(package_name); + auto pkg = package_list->find_package(package_name); if (!pkg) { std::cerr << "BADBADBAD" << std::endl;