aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/manifest20
-rw-r--r--bpkg/manifest.cxx49
-rw-r--r--tests/manifest/repositories2
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
: