diff options
-rw-r--r-- | bpkg/manifest | 20 | ||||
-rw-r--r-- | bpkg/manifest.cxx | 49 | ||||
-rw-r--r-- | tests/manifest/repositories | 2 |
3 files changed, 71 insertions, 0 deletions
diff --git a/bpkg/manifest b/bpkg/manifest index dfbe5af..75f87bd 100644 --- a/bpkg/manifest +++ b/bpkg/manifest @@ -438,10 +438,18 @@ namespace bpkg return os << l.string (); } + enum class repository_role + { + base, + prerequisite, + complement + }; + class repository_manifest { public: repository_location location; + butl::optional<repository_role> role; public: repository_manifest (manifest_parser&); @@ -449,6 +457,18 @@ namespace bpkg void serialize (manifest_serializer&) const; + + // Return the effective role of the repository. If the role is not + // explicitly specified (see the role member above), then calculate + // the role based on the location. Specifically, if the location is + // empty, then the effective role is base. Otherwise -- prerequisite. + // If the role is specified, then verify that it is consistent with + // the location value (that is, base if the location is empty and + // prerequisite or complete if not) and return that. Otherwise, + // throw logic_error. + // + repository_role + effective_role () const; }; class repository_manifests: public std::vector<repository_manifest> diff --git a/bpkg/manifest.cxx b/bpkg/manifest.cxx index 1ab9c72..bc1531d 100644 --- a/bpkg/manifest.cxx +++ b/bpkg/manifest.cxx @@ -36,6 +36,9 @@ namespace bpkg // Utility functions // static const strings priority_names ({"low", "medium", "high", "security"}); + static const strings repository_role_names ( + {"base", "prerequisite", "complement"}); + static const string spaces (" \t"); inline static bool @@ -1126,6 +1129,20 @@ namespace bpkg bad_value (e.what ()); } } + else if (n == "role") + { + if (role) + bad_name ("role redefinition"); + + auto b (repository_role_names.cbegin ()); + auto e (repository_role_names.cend ()); + auto i (find (b, e, v)); + + if (i == e) + bad_value ("unrecognized role"); + + role = static_cast<repository_role> (i - b); + } else bad_name ("unknown name '" + n + "' in repository manifest"); } @@ -1133,6 +1150,10 @@ namespace bpkg // Verify all non-optional values were specified. // // - location can be omitted + // - role can be omitted + // + if (role && location.empty () != (*role == repository_role::base)) + bad_value ("invalid role"); } void repository_manifest:: @@ -1143,9 +1164,34 @@ namespace bpkg if (!location.empty ()) s.next ("location", location.string ()); + if (role) + { + if (location.empty () != (*role == repository_role::base)) + throw serialization (s.name (), "invalid role"); + + auto r (static_cast<size_t> (*role)); + assert (r < repository_role_names.size ()); + s.next ("role", repository_role_names[r]); + } + s.next ("", ""); // End of manifest. } + repository_role repository_manifest:: + effective_role () const + { + if (role) + { + if (location.empty () != (*role == repository_role::base)) + throw logic_error ("invalid role"); + + return *role; + } + else + return location.empty () ? + repository_role::base : repository_role::prerequisite; + } + // repository_manifests // repository_manifests:: @@ -1175,6 +1221,9 @@ namespace bpkg if (empty () || !back ().location.empty ()) throw serialization (s.name (), "base repository manifest expected"); + // @@ Should we check that there is location in all except the last + // entry? + // for (const repository_manifest& r: *this) r.serialize (s); diff --git a/tests/manifest/repositories b/tests/manifest/repositories index b446dd4..184a15f 100644 --- a/tests/manifest/repositories +++ b/tests/manifest/repositories @@ -1,5 +1,7 @@ : 1 location: http://pkg.example.org/1/math +role: prerequisite : location: ../stable +role: complement : |