repo_data.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright (c) 2023, QuantStack and Mamba Contributors
  2. //
  3. // Distributed under the terms of the BSD 3-Clause License.
  4. //
  5. // The full license is in the file LICENSE, distributed with this software.
  6. #include <map>
  7. #include <optional>
  8. #include <string>
  9. #include <vector>
  10. #include <nlohmann/json_fwd.hpp>
  11. #include "mamba/specs/version.hpp"
  12. namespace mamba::specs
  13. {
  14. /**
  15. * Noarch packages are packages that are not architecture specific.
  16. *
  17. * Noarch packages only have to be built once.
  18. */
  19. enum struct NoArchType
  20. {
  21. /** Noarch generic packages allow users to distribute docs, datasets, and source code. */
  22. Generic,
  23. /**
  24. * A noarch python package is a python package without any precompiled python files.
  25. *
  26. * Normally, precompiled files (`.pyc` or `__pycache__`) are bundled with the package.
  27. * However, these files are tied to a specific version of Python and must therefore be
  28. * generated for every target platform and architecture.
  29. * This complicates the build process.
  30. * For noarch Python packages these files are generated when installing the package by
  31. * invoking the compilation process through the python binary that is installed in the
  32. * same environment.
  33. *
  34. * @see https://www.anaconda.com/blog/condas-new-noarch-packages
  35. * @see
  36. * https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/packages.html#noarch-python
  37. */
  38. Python,
  39. };
  40. /**
  41. * A single record in the Conda ``repodata.json``.
  42. *
  43. * A single record refers to a single binary distribution of a package on a Conda channel.
  44. *
  45. * Looking at the `RepoDataPackage` class in the Conda source code a record can also include
  46. * the following fields but it is unclear what they do.
  47. * - std::optional<std::string> preferred_env;
  48. * - std::optional<std::string> date;
  49. * - ? package_type
  50. * Repodata also contains some of the following keys, although they are not parsed by Conda.
  51. * - std::optional<std::string> app_type;
  52. * - std::optional<std::string> app_entry;
  53. *
  54. * @see conda.models.records
  55. * https://github.com/conda/conda/blob/main/conda/models/records.py
  56. * @see rattler_conda_types::repo_data::PackageRecord
  57. * https://github.com/mamba-org/rattler/blob/main/crates/rattler_conda_types/src/repo_data/mod.rs
  58. */
  59. struct RepoDataPackage
  60. {
  61. /** The name of the package. */
  62. std::string name = {};
  63. /** The version of the package. */
  64. Version version = Version(0, { { { 0 } } });
  65. /** The build string of the package. */
  66. std::string build_string = {};
  67. /** The build number of the package. */
  68. std::size_t build_number = {};
  69. /** The subdirectory where the package can be found. */
  70. std::string subdir = {};
  71. /** Optionally a MD5 hash of the package archive. */
  72. std::optional<std::string> md5 = {};
  73. /** Optionally a SHA256 hash of the package archive. */
  74. std::optional<std::string> sha256 = {};
  75. /** A deprecated md5 hash. */
  76. std::optional<std::string> legacy_bz2_md5 = {};
  77. /** A deprecated package archive size. */
  78. std::optional<std::size_t> legacy_bz2_size = {};
  79. /** Optionally the size of the package archive in bytes. */
  80. std::optional<std::size_t> size = {};
  81. /** Optionally the architecture the package supports. */
  82. std::optional<std::string> arch = {};
  83. /** Optionally the platform the package supports. */
  84. std::optional<std::string> platform = {};
  85. /** Specification of packages this package depends on. */
  86. std::vector<std::string> depends = {};
  87. /**
  88. * Additional constraints on packages.
  89. *
  90. * `constrains` are different from `depends` in that packages specified in `depends` must
  91. * be installed next to this package, whereas packages specified in `constrains` are not
  92. * required to be installed, but if they are installed they must follow these constraints.
  93. */
  94. std::vector<std::string> constrains = {};
  95. /**
  96. * Track features are nowadays only used to deprioritize packages.
  97. *
  98. * To that effect, the number of track features is counted (number of commas) and the
  99. * package is downweighted by the number of track_features.
  100. */
  101. std::vector<std::string> track_features = {};
  102. /**
  103. * Features are a deprecated way to specify different feature sets for the conda solver.
  104. *
  105. * This is not supported anymore and should not be used.
  106. * Instead, `mutex` packages should be used to specify mutually exclusive features.
  107. */
  108. std::optional<std::string> features = {};
  109. /** If this package is independent of architecture this field specifies in what way. */
  110. std::optional<NoArchType> noarch = {};
  111. /** The specific license of the package. */
  112. std::optional<std::string> license = {};
  113. /** The license family. */
  114. std::optional<std::string> license_family = {};
  115. /**
  116. * The UNIX Epoch timestamp when this package was created.
  117. *
  118. * Note that sometimes this is specified in seconds and sometimes in milliseconds.
  119. */
  120. std::optional<std::size_t> timestamp = {};
  121. };
  122. /**
  123. * Serialize to JSON.
  124. *
  125. * Optional members are omitted from json.
  126. */
  127. void to_json(nlohmann::json& j, const RepoDataPackage& p);
  128. /**
  129. * Deserialize from JSON
  130. *
  131. * Missing json entries fill optionals with a null values and collections as empty.
  132. * Special handling of the following fields is performed:
  133. * - ``"noarch"`` can be a string or a boolean (old behaviour), in which case ``false``
  134. * parse to ``std::nullopt`` and ``true`` to ``NoArchType::Generic``.
  135. * - ``"track_features"`` can be a string or list of string. In the former case, it is
  136. * considered as a single element list.
  137. */
  138. void from_json(const nlohmann::json& j, RepoDataPackage& p);
  139. /** Information about subdirectory of channel in the Conda RepoData. */
  140. struct ChannelInfo
  141. {
  142. /** The channel's subdirectory. */
  143. std::string subdir = {};
  144. };
  145. /** Serialize to JSON. */
  146. void to_json(nlohmann::json& j, const ChannelInfo& info);
  147. /** Deserialize from JSON. */
  148. void from_json(const nlohmann::json& j, ChannelInfo& info);
  149. /**
  150. * The repository data structure.
  151. *
  152. * This schema maps to the repository ``repodata.json``.
  153. **/
  154. struct RepoData
  155. {
  156. /** The version of the repodata format. */
  157. std::optional<std::size_t> version = {};
  158. /** The channel information contained in the repodata.json file.
  159. */
  160. std::optional<ChannelInfo> info = {};
  161. /**
  162. * The tar.bz2 packages contained in the repodata.json file.
  163. *
  164. * Maps a filename sucha as ``libmamba-0.13.0-h3a044de_0.tar.bz2`` to its RepoDataPackage.
  165. **/
  166. std::map<std::string, RepoDataPackage> packages = {};
  167. /**
  168. * The conda packages contained in the repodata.json file.
  169. *
  170. * Maps a filename such as ``libmamba-1.3.0-hcea66bb_1.conda`` to its RepoDataPackage.
  171. * This is put under a different key for backwards compatibility with previous conda
  172. * versions.
  173. */
  174. std::map<std::string, RepoDataPackage> conda_packages = {};
  175. /**
  176. * Removed packages
  177. *
  178. * These files are still accessible, but they are not installable like regular packages.
  179. */
  180. std::vector<std::string> removed = {};
  181. };
  182. /**
  183. * Serialize to JSON.
  184. *
  185. * Optional members are omitted from json.
  186. */
  187. void to_json(nlohmann::json& j, const RepoData& data);
  188. /**
  189. * Deserialize from JSON
  190. *
  191. * Missing json entries fill optionals with a null values and collections as empty.
  192. */
  193. void from_json(const nlohmann::json& j, RepoData& data);
  194. }