| You can also list your dependencies as an inline string in your CMakeLists.txt | You can also list your dependencies as an inline string in your CMakeLists.txt | ||||
| instead of a separate file:: | instead of a separate file:: | ||||
| pmm(DDS DEPENDS "neo-sqlite3 ^0.2.2") | |||||
| pmm(DDS DEPENDS neo-sqlite3^0.2.2) | |||||
| Since you'll probably want to be using ``libman.cmake`` at the same time, the | Since you'll probably want to be using ``libman.cmake`` at the same time, the | ||||
| calls for ``CMakeCM`` and ``DDS`` can simply be combined. This is how our new | calls for ``CMakeCM`` and ``DDS`` can simply be combined. This is how our new | ||||
| include(pmm.cmake) | include(pmm.cmake) | ||||
| pmm(CMakeCM ROLLING | pmm(CMakeCM ROLLING | ||||
| DDS DEPENDS "neo-sqlite3 ^0.2.2" | |||||
| DDS DEPENDS neo-sqlite3^0.2.2 | |||||
| ) | ) | ||||
| include(libman) | include(libman) |
| using namespace dds; | using namespace dds; | ||||
| dependency dependency::parse_depends_string(std::string_view str) { | dependency dependency::parse_depends_string(std::string_view str) { | ||||
| const auto str_begin = str.data(); | |||||
| auto str_iter = str_begin; | |||||
| const auto str_end = str_iter + str.size(); | |||||
| while (str_iter != str_end && !std::isspace(*str_iter)) { | |||||
| ++str_iter; | |||||
| auto sep_pos = str.find_first_of("=@^~+"); | |||||
| if (sep_pos == str.npos) { | |||||
| throw_user_error<errc::invalid_version_range_string>("Invalid dependency string '{}'", str); | |||||
| } | } | ||||
| auto name = trim_view(std::string_view(str_begin, str_iter - str_begin)); | |||||
| auto version_str = trim_view(std::string_view(str_iter, str_end - str_iter)); | |||||
| auto name = str.substr(0, sep_pos); | |||||
| if (str[sep_pos] == '@') { | |||||
| ++sep_pos; | |||||
| } | |||||
| auto range_str = str.substr(sep_pos); | |||||
| try { | try { | ||||
| auto rng = semver::range::parse_restricted(version_str); | |||||
| auto rng = semver::range::parse_restricted(range_str); | |||||
| return dependency{std::string(name), {rng.low(), rng.high()}}; | return dependency{std::string(name), {rng.low(), rng.high()}}; | ||||
| } catch (const semver::invalid_range&) { | } catch (const semver::invalid_range&) { | ||||
| throw_user_error<errc::invalid_version_range_string>( | throw_user_error<errc::invalid_version_range_string>( | ||||
| "Invalid version range string '{}' in dependency declaration '{}'", version_str, str); | |||||
| "Invalid version range string '{}' in dependency string '{}'", range_str, str); | |||||
| } | } | ||||
| } | } | ||||
| #include <dds/deps.hpp> | |||||
| #include <catch2/catch.hpp> | |||||
| TEST_CASE("Parse dependency strings") { | |||||
| struct case_ { | |||||
| std::string depstr; | |||||
| std::string name; | |||||
| std::string low; | |||||
| std::string high; | |||||
| }; | |||||
| auto cur = GENERATE(Catch::Generators::values<case_>({ | |||||
| {"foo@1.2.3", "foo", "1.2.3", "1.2.4"}, | |||||
| {"foo=1.2.3", "foo", "1.2.3", "1.2.4"}, | |||||
| {"foo^1.2.3", "foo", "1.2.3", "2.0.0"}, | |||||
| {"foo~1.2.3", "foo", "1.2.3", "1.3.0"}, | |||||
| {"foo+1.2.3", "foo", "1.2.3", semver::version::max_version().to_string()}, | |||||
| })); | |||||
| auto dep = dds::dependency::parse_depends_string(cur.depstr); | |||||
| CHECK(dep.name == cur.name); | |||||
| CHECK(dep.versions.num_intervals() == 1); | |||||
| auto ver_iv = *dep.versions.iter_intervals().begin(); | |||||
| CHECK(ver_iv.low == semver::version::parse(cur.low)); | |||||
| CHECK(ver_iv.high == semver::version::parse(cur.high)); | |||||
| } |
| def test_build_deps_from_cmd(dds: DDS): | def test_build_deps_from_cmd(dds: DDS): | ||||
| assert not dds.deps_build_dir.is_dir() | assert not dds.deps_build_dir.is_dir() | ||||
| dds.catalog_import(dds.source_root / 'catalog.json') | dds.catalog_import(dds.source_root / 'catalog.json') | ||||
| dds.build_deps(['neo-sqlite3 =0.2.2']) | |||||
| dds.build_deps(['neo-sqlite3=0.2.2']) | |||||
| assert (dds.deps_build_dir / 'neo-sqlite3@0.2.2').is_dir() | assert (dds.deps_build_dir / 'neo-sqlite3@0.2.2').is_dir() | ||||
| assert (dds.scratch_dir / 'INDEX.lmi').is_file() | assert (dds.scratch_dir / 'INDEX.lmi').is_file() | ||||
| assert (dds.deps_build_dir / '_libman/neo-sqlite3.lmp').is_file() | assert (dds.deps_build_dir / '_libman/neo-sqlite3.lmp').is_file() | ||||
| def test_multiple_deps(dds: DDS): | def test_multiple_deps(dds: DDS): | ||||
| assert not dds.deps_build_dir.is_dir() | assert not dds.deps_build_dir.is_dir() | ||||
| dds.catalog_import(dds.source_root / 'catalog.json') | dds.catalog_import(dds.source_root / 'catalog.json') | ||||
| dds.build_deps(['neo-sqlite3 ^0.2.2', 'neo-sqlite3 ~0.2.0']) | |||||
| dds.build_deps(['neo-sqlite3^0.2.2', 'neo-sqlite3~0.2.0']) | |||||
| assert (dds.deps_build_dir / 'neo-sqlite3@0.2.2').is_dir() | assert (dds.deps_build_dir / 'neo-sqlite3@0.2.2').is_dir() | ||||
| assert (dds.scratch_dir / 'INDEX.lmi').is_file() | assert (dds.scratch_dir / 'INDEX.lmi').is_file() | ||||
| assert (dds.deps_build_dir / '_libman/neo-sqlite3.lmp').is_file() | assert (dds.deps_build_dir / '_libman/neo-sqlite3.lmp').is_file() |