// file : bbot/bootstrap-manifest.cxx -*- C++ -*- // license : MIT; see accompanying LICENSE file #include #include #include using namespace butl; namespace bbot { using parser = manifest_parser; using parsing = manifest_parsing; using serializer = manifest_serializer; using serialization = manifest_serialization; using name_value = manifest_name_value; // bootstrap_manifest // bootstrap_manifest:: bootstrap_manifest (parser& p, bool iu) : bootstrap_manifest (p, p.next (), iu) { // Make sure this is the end. // name_value nv (p.next ()); if (!nv.empty ()) throw parsing (p.name (), nv.name_line, nv.name_column, "single bootstrap manifest expected"); } bootstrap_manifest:: bootstrap_manifest (parser& p, name_value nv, bool iu) { auto bad_name = [&p, &nv] (const string& d) { throw parsing (p.name (), nv.name_line, nv.name_column, d); }; auto bad_value = [&p, &nv] (const string& d) { throw parsing (p.name (), nv.value_line, nv.value_column, d); }; // Make sure this is the start and we support the version. // if (!nv.name.empty ()) bad_name ("start of bootstrap manifest expected"); if (nv.value != "1") bad_value ("unsupported format version"); // Parse the bootstrap manifest. // for (nv = p.next (); !nv.empty (); nv = p.next ()) { string& n (nv.name); string& v (nv.value); size_t nn (n.size ()); // Name length. // Note: returns false if nothing preceeds a suffix. // auto suffix = [&n, nn] (const char* s, size_t sn) -> bool { return nn > sn && n.compare (nn - sn, sn, s) == 0; }; size_t sn; if (suffix ("-version", sn = 8)) { string pn (n, 0, nn - sn); // Package name. // Package version. // try { // Make sure the package version is not redefined. // if (!versions.emplace (move (pn), standard_version (v)).second) bad_name (n + " redefinition"); } catch (const invalid_argument& e) { bad_value (string ("invalid package version: ") + e.what ()); } } else if (!iu) bad_name ("unknown name '" + n + "' in bootstrap manifest"); } // Verify all non-optional values were specified. // if (versions.empty ()) bad_value ("no package versions specified"); } void bootstrap_manifest:: serialize (serializer& s) const { // @@ Should we check that all non-optional values are specified? // s.next ("", "1"); // Start of manifest. // Serialize *-version values. // for (const auto& v: versions) s.next (v.first + "-version", v.second.string_project ()); s.next ("", ""); // End of manifest. } }