#ifndef LIBPKG_DATA_PACKAGE_H #define LIBPKG_DATA_PACKAGE_H #include "../global.h" #include "../parser/utils.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace LibPkg { /*! * \brief The InstallStatus enum specifies whether a package has been installed explicitly or as dependency. */ enum class InstallStatus { Explicit = 0, AsDependency = 1, Unknown = 20 }; /*! * \brief Either unknown, true or false. */ enum class UnknownTrueFalse : unsigned char { Unknown, True, False }; /*! * \brief The PackageValidation enum specifies methods used to validate a package. * \remarks ALMP type: alpm_pkgvalidation_t */ enum class PackageValidation { Unknown = 0, None = (1 << 0), Md5Sum = (1 << 1), Sha256Sum = (1 << 2), PgpSignature = (1 << 3) }; constexpr PackageValidation operator|(PackageValidation lhs, PackageValidation rhs) { return static_cast(static_cast(lhs) | static_cast(rhs)); } constexpr bool operator&(PackageValidation lhs, PackageValidation rhs) { return (static_cast(lhs) & static_cast(rhs)) != 0; } constexpr int operator~(PackageValidation lhs) { return ~static_cast(lhs); } inline PackageValidation &operator|=(PackageValidation &lhs, PackageValidation rhs) { lhs = static_cast(static_cast(lhs) | static_cast(rhs)); return lhs; } inline PackageValidation &operator&=(PackageValidation &lhs, int rhs) { lhs = static_cast(static_cast(lhs) & rhs); return lhs; } /*! * \brief The DependencyMode enum specifies the version constraints in dependency specs. * \remarks ALPM: alpm_depmod_t */ enum class DependencyMode { Any = 1, /*! No version constraint */ Equal, /*! Test version equality (package=x.y.z) */ GreatherEqual, /*! Test for at least a version (package>=x.y.z) */ LessEqual, /*! Test for at most a version (package<=x.y.z) */ GreatherThan, /*! Test for greater than some version (package>x.y.z) */ LessThan /*! Test for less than some version (package, public ReflectiveRapidJSON::BinarySerializable { explicit Dependency() = default; explicit Dependency(const std::string &name, const std::string &version = std::string(), DependencyMode mode = DependencyMode::Any, const std::string &description = std::string()); explicit Dependency(const char *denotation, std::size_t denotationSize = std::numeric_limits::max()); explicit Dependency(std::string_view denotation); bool operator==(const Dependency &other) const; bool matches(const Dependency &other) const; static bool matches(const DependencyMode mode, const std::string &version1, const std::string &version2); static Dependency fromString(const char *dependency, std::size_t dependencySize = std::numeric_limits::max()); static Dependency fromString(std::string_view dependency); std::string toString() const; std::string name; std::string version; std::string description; DependencyMode mode = DependencyMode::Any; }; inline Dependency::Dependency(const std::string &name, const std::string &version, DependencyMode mode, const std::string &description) : name(name) , version(version) , description(description) , mode(mode) { } inline Dependency::Dependency(std::string_view denotation) : Dependency(denotation.data(), denotation.size()) { } inline bool Dependency::operator==(const Dependency &other) const { return name == other.name && version == other.version && description == other.description && mode == other.mode; } inline bool Dependency::matches(const Dependency &other) const { return name == other.name && matches(other.mode, other.version, version); } inline Dependency Dependency::fromString(const char *denotation, size_t denotationSize) { return Dependency(denotation, denotationSize); } inline Dependency Dependency::fromString(std::string_view dependency) { return Dependency(dependency); } } // namespace LibPkg namespace std { template <> struct hash { std::size_t operator()(const LibPkg::Dependency &dep) const { using std::hash; using DepModeType = typename std::underlying_type::type; return ((hash()(dep.name) ^ (hash()(dep.version) << 1)) >> 1) ^ ((hash()(dep.description) << 4) ^ (hash()(static_cast(dep.mode)) << 1) >> 1); } }; } // namespace std namespace LibPkg { LIBPKG_EXPORT std::ostream &operator<<(std::ostream &o, const DependencyMode &mode); LIBPKG_EXPORT std::ostream &operator<<(std::ostream &o, const Dependency &dependency); LIBPKG_EXPORT std::ostream &operator<<(std::ostream &o, const std::vector &dependencies); struct SourceFile : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::string path; std::string contents; }; struct LIBPKG_EXPORT SourceInfo : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::string name; std::vector archs; // archs specified in base package std::vector makeDependencies; std::vector checkDependencies; std::string maintainer; std::int64_t id = 0; std::int64_t category = 0; std::int64_t votes = 0; CppUtilities::DateTime outOfDate; CppUtilities::DateTime firstSubmitted; CppUtilities::DateTime lastModified; std::string url; std::vector sources; std::string directory; }; struct LIBPKG_EXPORT PackageInfo : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::string fileName; std::vector files; CppUtilities::DateTime buildDate; std::string packager; std::string md5; std::string sha256; std::string pgpSignature; std::string arch; // arch of concrete binary package std::uint32_t size = 0; }; struct LIBPKG_EXPORT InstallInfo : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { CppUtilities::DateTime installDate; std::uint32_t installedSize = 0; std::vector backupFiles; InstallStatus installStatus = InstallStatus::Unknown; PackageValidation validationMethods = PackageValidation::None; }; /*! * \brief The PackageVersionComparison enum defines possible results of packages version comparison. */ enum class PackageVersionComparison { Equal, /*!< The version of this package is the same as the version of the package from the sync db. */ SoftwareUpgrade, /*!< The software version of the package from the sync db is newer. */ PackageUpgradeOnly, /*!< The package release number of the package from the sync db is newer. */ NewerThanSyncVersion /*!< The version of this package is NEWER then the version of the package from the sync db. */ }; LIBPKG_EXPORT std::ostream &operator<<(std::ostream &o, const PackageVersionComparison &res); /*! * \brief The ComparsionResult enum defines possible results of the package version part comparison * provided by PackageVersion::compareParts(). */ enum class PackageVersionPartComparison { Equal, /*!< Both parts are equal. */ Newer, /*!< Part 1 is newer then part 2. */ Older /*!< Part 2 is newer then part 1. */ }; LIBPKG_EXPORT std::ostream &operator<<(std::ostream &o, const PackageVersionPartComparison &res); struct LIBPKG_EXPORT PackageVersion : public ReflectiveRapidJSON::JsonSerializable { static PackageVersion fromString(const char *versionString, std::size_t versionStringSize); static PackageVersion fromString(const std::string &versionString); static PackageVersionPartComparison compareParts(const std::string &part1, const std::string &part2, bool allowImplicitPkgRel = false); static std::string trimPackageVersion(const std::string &versionString); PackageVersionComparison compare(const PackageVersion &other) const; static PackageVersionComparison compare(const std::string &versionString1, const std::string &versionString2); static bool isNewer(PackageVersionComparison comparison); std::string toString() const; std::string epoch; std::string upstream; std::string package; }; inline PackageVersion PackageVersion::fromString(const std::string &versionString) { return fromString(versionString.data(), versionString.size()); } inline PackageVersionComparison PackageVersion::compare(const std::string &versionString1, const std::string &versionString2) { return fromString(versionString1).compare(fromString(versionString2)); } inline bool PackageVersion::isNewer(PackageVersionComparison comparison) { return comparison == PackageVersionComparison::SoftwareUpgrade || comparison == PackageVersionComparison::PackageUpgradeOnly; } /*! * \brief The PackageOrigin enum specifies where the information contained by a Package object come from. * * This is useful to know because the different origins provide a different information. For instance, a Package * which has only been created from a file name (via Package::fromPkgFileName()) will not contain any dependencies. */ enum class PackageOrigin { Default, /*!< The package has been default-constructed. That means the package instance is empty. */ PackageFileName, /*!< A package file name has been parsed via Package::fromPkgFileName(). */ SourceInfo, /*!< A .SRCINFO file has been parsed via Package::fromInfo(). */ PackageInfo, /*!< A .PKGINFO file has been parsed via Package::fromInfo(). */ Database, /*!< A description file from a database has been parsed via Package::fromDescription(). */ PackageContents, /*!< A binary package has been parsed via Package::fromPkgFile(). */ AurRpcInfo, /*!< A JSON document from the AUR RPC (info, multiinfo) has been parsed via Package::fromAurRpcJson(). */ CustomSource, /*! The package info has been populated from a custom source. */ AurRpcSearch, /*!< A JSON document from the AUR RPC (search) has been parsed via Package::fromAurRpcJson(). */ }; struct LIBPKG_EXPORT PackageNameData { std::string compose() const; std::string variant() const; bool isVcsPackage() const; static PackageNameData decompose(std::string_view packageName); std::string_view actualName; std::string_view targetPrefix; std::string_view vcsSuffix; }; struct DependencySet; struct LIBPKG_EXPORT Package : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { Package() = default; Package(const Package &other); Package(Package &&other) = default; bool providesDependency(const Dependency &dependency) const; static void exportProvides( const std::shared_ptr &package, DependencySet &destinationProvides, std::unordered_set &destinationLibProvides); bool isSame(const Package &other) const; PackageVersionComparison compareVersion(const Package &other) const; std::string computeFileName(const char *extension = "pkg.tar.zst") const; std::string computeRegularPackageName() const; PackageNameData decomposeName() const; void addInfoFromPkgInfoFile(const std::string &info); void addDepsAndProvidesFromContainedDirectory(const std::string &directoryPath); void addDepsAndProvidesFromContainedFile(const ArchiveFile &file, std::set &dllsReferencedByImportLibs); void addDepsAndProvidesFromContents(const FileMap &contents); std::vector processDllsReferencedByImportLibs(std::set &&dllsReferencedByImportLibs); bool addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force = false); bool isArchAny() const; static bool isPkgInfoFileOrBinary(const char *filePath, const char *fileName, mode_t mode); static bool isLicense(const char *filePath, const char *fileName, mode_t mode); static std::vector> fromInfo(const std::string &info, bool isPackageInfo = false); static std::shared_ptr fromDescription(const std::vector &descriptionParts); static std::vector> fromDatabaseFile(FileMap &&databaseFile); static std::shared_ptr fromPkgFile(const std::string &path); static std::tuple fileNameComponents(std::string_view fileName); static std::shared_ptr fromPkgFileName(std::string_view fileName); static std::vector> fromAurRpcJson( const char *jsonData, std::size_t jsonSize, PackageOrigin origin = PackageOrigin::AurRpcInfo); PackageOrigin origin = PackageOrigin::Default; CppUtilities::DateTime timestamp; std::string name; std::string version; std::vector archs; // set if a split package overrides the base archs; if empty, archs from sourceInfo apply std::string description; std::string upstreamUrl; std::vector licenses; std::vector groups; std::vector dependencies; std::vector optionalDependencies; std::vector conflicts; std::vector provides; std::vector replaces; std::set libprovides; std::set libdepends; std::shared_ptr sourceInfo; std::unique_ptr packageInfo; std::unique_ptr installInfo; }; inline Package::Package(const Package &other) : origin(other.origin) , timestamp(other.timestamp) , name(other.name) , version(other.version) , description(other.description) , upstreamUrl(other.upstreamUrl) , licenses(other.licenses) , groups(other.groups) , dependencies(other.dependencies) , optionalDependencies(other.optionalDependencies) , conflicts(other.conflicts) , provides(other.provides) , replaces(other.replaces) , sourceInfo(other.sourceInfo) , packageInfo() , installInfo() { } inline bool Package::isSame(const Package &other) const { return name == other.name && version == other.version; } inline PackageNameData Package::decomposeName() const { return PackageNameData::decompose(name); } struct LIBPKG_EXPORT DependencyDetail : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { DependencyDetail(const std::string &version = std::string(), DependencyMode mode = DependencyMode::Any, const std::unordered_set> &relevantPackages = std::unordered_set>()); DependencyDetail(std::string &&version, DependencyMode mode); std::string version; DependencyMode mode = DependencyMode::Any; std::unordered_set> relevantPackages; }; inline DependencyDetail::DependencyDetail( const std::string &version, DependencyMode mode, const std::unordered_set> &relevantPackages) : version(version) , mode(mode) , relevantPackages(relevantPackages) { } inline DependencyDetail::DependencyDetail(std::string &&version, DependencyMode mode) : version(move(version)) , mode(mode) { } using DependencySetBase = std::unordered_multimap; struct LIBPKG_EXPORT DependencySet : public DependencySetBase { DependencySetBase::iterator find(const Dependency &dependency); DependencySetBase::iterator find(const std::string &dependencyName, const DependencyDetail &dependencyDetail); DependencySetBase::iterator findExact(const Dependency &dependency); DependencySetBase::iterator findExact(const std::string &dependencyName, const DependencyDetail &dependencyDetail); bool provides(const Dependency &dependency) const; bool provides(const std::string &dependencyName, const DependencyDetail &dependencyDetail) const; DependencySetBase::iterator add(const Dependency &dependency, const std::shared_ptr &relevantPackage); DependencySetBase::iterator add( const std::string &dependencyName, const DependencyDetail &dependencyDetail, const std::shared_ptr &relevantPackage); DependencySetBase::iterator add(std::string &&dependencyName, DependencyDetail &&dependencyDetail); void remove(const Dependency &dependency, const std::shared_ptr &relevantPackage); void remove(const std::string &name); }; } // namespace LibPkg namespace ReflectiveRapidJSON { REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_MAP_OR_HASH(LibPkg::DependencySet); } #endif // LIBPKG_DATA_PACKAGE_H