// file : bpkg/manifest -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BPKG_MANIFEST #define BPKG_MANIFEST #include #include #include // uint16 #include // move() #include namespace bpkg { class manifest_parser; class manifest_serializer; class manifest_name_value; using strings = std::vector; struct version { // Create a special empty version. // version (): epoch_ (0), revision_ (0) {} explicit version (const char*); explicit version (const std::string& v): version (v.c_str ()) /* Delegate */ {} std::uint16_t epoch () const noexcept {return epoch_;} std::uint16_t revision () const noexcept {return revision_;} const std::string& upstream () const noexcept {return upstream_;} const std::string& canonical_upstream () const noexcept {return canonical_;} std::string string () const { const std::string& v ( epoch_ != 0 ? std::to_string (epoch_) + "+" + upstream_ : upstream_); return revision_ != 0 ? v + "-" + std::to_string (revision_) : v; } bool operator< (const version& v) const noexcept {return compare (v) < 0;} bool operator> (const version& v) const noexcept {return compare (v) > 0;} bool operator== (const version& v) const noexcept {return compare (v) == 0;} bool operator<= (const version& v) const noexcept {return compare (v) <= 0;} bool operator>= (const version& v) const noexcept {return compare (v) >= 0;} bool operator!= (const version& v) const noexcept {return compare (v) != 0;} int compare (const version& v, bool ignore_revision = false) const noexcept { if (epoch_ != v.epoch_) return epoch_ < v.epoch_ ? -1 : 1; if (int c = canonical_.compare (v.canonical_)) return c; if (!ignore_revision && revision_ != v.revision_) return revision_ < v.revision_ ? -1 : 1; return 0; } bool empty () const noexcept { // No sense to test epoch_ and revision_ for 0 as properly constructed // version object can not have them different from 0 if upstream_ is // empty. Returns true only for objects constructed with the default // constructor. // return upstream_.empty (); } private: std::uint16_t epoch_; std::uint16_t revision_; std::string upstream_; std::string canonical_; // Upstream part canonical representation. }; // priority // class priority { public: enum value_type {low, medium, high, security}; value_type value; // Shouldn't be necessary to access directly. std::string comment; priority (value_type v = low, std::string c = "") : value (v), comment (std::move (c)) {} operator value_type () const {return value;} }; // description // description-file // struct description: std::string { bool file; std::string comment; // Description constructor. // explicit description (std::string d = "") : std::string (std::move (d)), file (false) {} // Description file constructor. // description (std::string f, std::string c) : std::string (std::move (f)), file (true), comment (std::move (c)) {} }; // license // struct licenses: strings { std::string comment; explicit licenses (std::string c = ""): comment (std::move (c)) {} }; // change // change-file // struct change: std::string { bool file; std::string comment; // Change constructor. // explicit change (std::string c = ""): std::string (std::move (c)), file (false) {} // Change file constructor. // change (std::string f, std::string c) : std::string (std::move (f)), file (true), comment (std::move (c)) {} }; // url // package-url // struct url: std::string { std::string comment; explicit url (std::string u = "", std::string c = "") : std::string (std::move (u)), comment (std::move (c)) {} }; // email // package-email // struct email: std::string { std::string comment; explicit email (std::string e = "", std::string c = "") : std::string (std::move (e)), comment (std::move (c)) {} }; // depends // enum class comparison {eq, lt, gt, le, ge}; struct version_comparison { version value; comparison operation; }; struct dependency { std::string name; butl::optional version; }; struct dependency_alternatives: std::vector { bool conditional; std::string comment; explicit dependency_alternatives (bool d = false, std::string c = "") : conditional (d), comment (std::move (c)) {} }; // requires // struct requirement_alternatives: strings { bool conditional; std::string comment; explicit requirement_alternatives (bool d = false, std::string c = "") : conditional (d), comment (std::move (c)) {} }; class package_manifest { public: using version_type = bpkg::version; using priority_type = bpkg::priority; using url_type = bpkg::url; using email_type = bpkg::email; using description_type = bpkg::description; std::string name; version_type version; butl::optional priority; std::string summary; std::vector license_alternatives; strings tags; butl::optional description; std::vector changes; url_type url; butl::optional package_url; email_type email; butl::optional package_email; std::vector dependencies; std::vector requirements; public: package_manifest (manifest_parser&); package_manifest (manifest_parser&, manifest_name_value start); void serialize (manifest_serializer&) const; }; class repository_manifest { public: std::string location; public: repository_manifest (manifest_parser&); repository_manifest (manifest_parser&, manifest_name_value start); void serialize (manifest_serializer&) const; }; class manifests { public: std::vector repositories; std::vector packages; public: manifests (manifest_parser&); void serialize (manifest_serializer&) const; }; } #endif // BPKG_MANIFEST