1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
|
/*
* This file is part of libmodulemd
* Copyright (C) 2018-2020 Red Hat, Inc.
*
* Fedora-License-Identifier: MIT
* SPDX-2.0-License-Identifier: MIT
* SPDX-3.0-License-Identifier: MIT
*
* This program is free software.
* For more information on the license, see COPYING.
* For more information on free software, see <https://www.gnu.org/philosophy/free-sw.en.html>.
*/
#pragma once
#include "modulemd-build-config.h"
#include "modulemd-buildopts.h"
#include "modulemd-component-module.h"
#include "modulemd-component-rpm.h"
#include "modulemd-component.h"
#include "modulemd-compression.h"
#include "modulemd-defaults-v1.h"
#include "modulemd-defaults.h"
#include "modulemd-dependencies.h"
#include "modulemd-deprecated.h"
#include "modulemd-errors.h"
#include "modulemd-module-index-merger.h"
#include "modulemd-module-index.h"
#include "modulemd-module-stream-v1.h"
#include "modulemd-module-stream-v2.h"
#include "modulemd-module-stream.h"
#include "modulemd-module.h"
#include "modulemd-packager-v3.h"
#include "modulemd-profile.h"
#include "modulemd-rpm-map-entry.h"
#include "modulemd-service-level.h"
#include "modulemd-subdocument-info.h"
#include "modulemd-translation-entry.h"
#include "modulemd-translation.h"
G_BEGIN_DECLS
/**
* SECTION: modulemd
* @title: Modulemd
* @stability: stable
* @short_description: User's Guide for libmodulemd
*
* # Working with repodata (DNF use-case)
* The libmodulemd API provides a number of convenience tools for interacting
* with repodata (that is, streams of YAML that contains information on multiple
* streams, default data and translations). The documentation will use two
* repositories, called "fedora" and "updates" for demonstrative purposes. It
* will assume that the content of the YAML module metadata from those two
* repositories have been loaded into string variables `fedora_yaml` and
* `updates_yaml`, respectively.
*
* Tools such as DNF that are consuming data from a repository should always
* set `strict=False`, so that it can safely handle minor,
* backwards-compatible changes to the modulemd format.
*
* First step is to load the metadata from these two repositories into
* #ModulemdModuleIndex objects. This is done as follows:
*
* In C:
* |[<!-- language="C" -->
* ModulemdModuleIndex *fedora_index = modulemd_module_index_new ();
* gboolean ret = modulemd_module_index_update_from_string (
* fedora_index, fedora_yaml, FALSE, &failures, &error);
*
* ModulemdModuleIndex *updates_index = modulemd_module_index_new ();
* gboolean ret2 = modulemd_module_index_update_from_string (
* updates_index, updates_yaml, FALSE, &failures, &error);
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* fedora_index = Modulemd.ModuleIndex.new()
* ret, failures = fedora_index.update_from_string(fedora_yaml, False)
*
* updates_index = Modulemd.ModuleIndex.new()
* ret, failures = updates_index.update_from_string(updates_yaml, False)
* ]|
*
* The @failures are a list of subdocuments in the YAML that failed parsing,
* along with the reason they failed. Hence, by checking the return value of
* @failures we will know if the YAML parsing was successful or not.
*
* Since it doesn't really make sense to view the contents from separate
* repositories in isolation (in most cases), the next step is to merge the two
* indexes into a combined one:
*
* In C:
* |[<!-- language="C" -->
* ModulemdModuleIndexMerger *merger = modulemd_module_index_merger_new ();
*
* modulemd_module_index_merger_associate_index (merger, fedora_index, 0);
* modulemd_module_index_merger_associate_index (merger, updates_index, 0);
*
* ModulemdModuleIndex *merged_index =
* modulemd_module_index_merger_resolve (merger, &error);
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* merger = Modulemd.ModuleIndexMerger.new()
*
* merger.associate_index(fedora_index, 0)
* merger.associate_index(updates_index, 0)
*
* merged_index = merger.resolve()
* ]|
*
* At this point, you now have either a complete view of the merged repodata,
* or else have received an error describing why the merge was unable to
* complete successfully. Additionally, it should be noted that the combined
* metadata in any #ModulemdModuleIndex will have all of its component parts
* upgraded to match the highest version of those objects seen. So for example
* if the repodata has a mix of v1 and v2 #ModulemdModuleStream objects, the
* index will contain only v2 objects (with the v1 objects automatically
* upgraded internally).
*
* Now, we can start operating on the retrieved data. This guide will
* give only a brief overview of the most common operations. See the API
* specification for a full list of information that can be retrieved.
*
* ## Discover the default stream for a particular module.
*
* In C:
* |[<!-- language="C" -->
* ModulemdModule *module =
* modulemd_module_index_get_module (merged_index, "modulename");
* ModulemdDefaults *defaults = modulemd_module_get_defaults (module);
* if (defaults)
* {
* printf ("Default stream for modulename is %s\n",
* modulemd_defaults_v1_get_default_stream (
* MODULEMD_DEFAULTS_V1 (defaults), NULL));
* }
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* module = merged_index.get_module("modulename")
* defaults = module.get_defaults()
* print("Default stream for modulename is %s" % defaults.get_default_stream())
* ]|
*
* ## Get the list of RPMs defining the public API for a particular module NSVCA
* First, query the #ModulemdModuleIndex for the module with a given name.
*
* In C:
* |[<!-- language="C" -->
* ModulemdModule *module =
* modulemd_module_index_get_module (merged_index, "modulename");
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* module = merged_index.get_module("modulename")
* ]|
*
* Then, query the #ModulemdModule for the #ModulemdModuleStream associated with the
* provided NSVCA (name-stream-version-context-architecture identifier).
*
* In C:
* |[<!-- language="C" -->
* ModulemdModuleStream *stream = modulemd_module_get_stream_by_NSVCA (
* module, "modulestream", 0, "deadbeef", "coolarch", &error);
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* stream = module.get_stream_by_NSVCA("modulestream", 0, "deadbeef", "coolarch")
* ]|
*
* Lastly, read the RPM API from the #ModulemdModuleStream. Here, `api_list` is
* a list of strings containing package names.
*
* In C:
* |[<!-- language="C" -->
* GStrv api_list = modulemd_module_stream_v2_get_rpm_api_as_strv (
* MODULEMD_MODULE_STREAM_V2 (stream));
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* api_list = stream.get_rpm_api()
* ]|
*
* Also note that in addition to accessor API methods, many objects also have
* properties that can be accessed directly.
*
* In C:
* |[<!-- language="C" -->
* printf ("Documentation for module stream is at %s\n",
* modulemd_module_stream_v2_get_documentation (
* MODULEMD_MODULE_STREAM_V2 (stream)));
* g_autofree gchar *doc;
* g_object_get (MODULEMD_MODULE_STREAM_V2 (stream), "documentation", &doc, NULL);
* printf ("Documentation for module stream is at %s\n", doc);
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* print("Documentation for module stream is at %s" % stream.get_documentation())
* print("Documentation for module stream is at %s" % stream.props.documentation)
* ]|
*
* ## Retrieve the modular runtime dependencies for a particular module NSVCA
*
* In C:
* |[<!-- language="C" -->
* ModulemdModule *module =
* modulemd_module_index_get_module (merged_index, "modulename");
* ModulemdModuleStream *stream = modulemd_module_get_stream_by_NSVCA (
* module, "modulestream", 0, "deadbeef", "coolarch", &error);
* GPtrArray *deps_list = modulemd_module_stream_v2_get_dependencies (
* MODULEMD_MODULE_STREAM_V2 (stream));
*
* for (gint i = 0; i < deps_list->len; i++)
* {
* GStrv depmodules_list =
* modulemd_dependencies_get_runtime_modules_as_strv (
* g_ptr_array_index (deps_list, i));
*
* for (gint j = 0; j < g_strv_length (depmodules_list); j++)
* {
* GStrv depstreams_list =
* modulemd_dependencies_get_runtime_streams_as_strv (
* g_ptr_array_index (deps_list, i), depmodules_list[j]);
*
* for (gint k = 0; k < g_strv_length (depstreams_list); k++)
* {
* // do stuff with depmodules_list[j], depstreams_list[k]
* }
* }
* }
* ]|
*
* In Python:
* |[<!-- language="Python" -->
* module = merged_index.get_module("modulename")
* stream = module.get_stream_by_NSVCA("modulestream", 0, "deadbeef", "coolarch")
* deps_list = stream.get_dependencies()
* for dep in deps_list:
* depmodules_list = dep.get_runtime_modules()
* for depmod in depmodules_list:
* depstream_list = dep.get_runtime_streams(depmod)
* for depstream in depstream_list:
* # do stuff with depmod, depstream
* ]|
*
* # Working with a single module stream (Packager/MBS use-case)
* One limitation of the #ModulemdModuleIndex format is that it requires that
* all module streams loaded into it have both a name and a stream name.
* This however is not possible when dealing with streams such as a packager
* would be using (since the build-system auto-generates the module name and
* stream name from the git repository information. In this case, we need to
* work with a single module stream document at a time. For this, we will
* use the #ModulemdModuleStream interface.
*
* This example will assume that the module name and stream name have
* already been determined from the repodata and that they are stored in
* string variables named `module_name` and `stream_name`, respectively.
*
* In Python:
* |[<!-- language="Python" -->
* stream = Modulemd.ModuleStream.read_file(
* "/path/to/module_name.yaml", True, module_name, stream_name
* )
* v2_stream = stream.upgrade(Modulemd.ModuleStreamVersionEnum.TWO)
* v2_stream.validate()
* ]|
* In the example above, we upgraded the stream to v2, in case we were reading
* from v1 metadata. This will allow us to avoid having to manage multiple
* code-paths and support only the latest we understand. After that, it calls
* validate() to ensure that the content that was read in was valid both
* syntactically and referentially.
*
* Also available is `Modulemd.ModuleStreamVersionEnum.LATEST` which will
* always represent the highest-supported version of the
* #ModulemdModuleStream metadata format. This may change at any time.
*/
/**
* modulemd_get_version:
*
* Returns: (transfer none): A string describing the version of libmodulemd.
*
* Since: 2.0
*/
const gchar *
modulemd_get_version (void);
/**
* modulemd_load_file:
* @yaml_file: (in): A YAML file containing the module metadata and other
* related information such as default streams.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* This is a convenience function that is a wrapper around
* modulemd_module_index_new() and modulemd_module_index_update_from_file()
* with `strict=False`.
*
* It will return the imported module metadata if all subdocuments are
* parseable and valid. If any part of the document is unreadable or fails
* validation, it will return NULL and set @error appropriately. If you need
* more detail about which parts of the document failed, use the lower-level
* functions.
*
* Returns: (transfer full): A newly-allocated #ModulemdModuleIndex object
* initialized with the content from @yaml_file. Returns NULL and sets @error
* if the file is not completely valid.
*
* Since: 2.10
*/
ModulemdModuleIndex *
modulemd_load_file (const gchar *yaml_file, GError **error);
/**
* modulemd_load_string:
* @yaml_string: (in): A YAML string containing the module metadata and other
* related information such as default streams.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* This is a convenience function that is a wrapper around
* modulemd_module_index_new() and modulemd_module_index_update_from_string()
* with `strict=False`.
*
* It will return the imported module metadata if all subdocuments are
* parseable and valid. If any part of the document is unreadable or fails
* validation, it will return NULL and set @error appropriately. If you need
* more detail about which parts of the document failed, use the lower-level
* functions.
*
* Returns: (transfer full): A newly-allocated #ModulemdModuleIndex object
* initialized with the content from @yaml_string. Returns NULL and sets @error
* if the metadata is not completely valid.
*
* Since: 2.10
*/
ModulemdModuleIndex *
modulemd_load_string (const gchar *yaml_string, GError **error);
/**
* modulemd_read_packager_file: (skip)
* @yaml_path: (in): A path to a YAML file containing a packager document.
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
* #ModulemdPackagerV3 object initialized with the content from @yaml_path.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
*
* Since: 2.11
*/
GType
modulemd_read_packager_file (const gchar *yaml_path,
GObject **object,
GError **error);
/**
* modulemd_read_packager_file_ext: (rename-to modulemd_read_packager_file)
* @yaml_path: (in): A path to a YAML file containing a packager document.
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
* #ModulemdPackagerV3 object initialized with the content from @yaml_path.
* @module_name: (in) (nullable): An optional module name to override the
* document on disk. Mostly useful in cases where the name is being
* auto-detected from git.
* @module_stream: (in) (nullable): An optional module stream name to override
* the document on disk. Mostly useful in cases where the name is being
* auto-detected from git.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
*
* Since: 2.11
*/
GType
modulemd_read_packager_file_ext (const gchar *yaml_path,
GObject **object,
const gchar *module_name,
const gchar *module_stream,
GError **error);
/**
* modulemd_read_packager_string: (skip)
* @yaml_string: (in): A YAML string containing a packager document.
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
* #ModulemdPackagerV3 object initialized with the content from @yaml_string.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
*
* Since: 2.11
*/
GType
modulemd_read_packager_string (const gchar *yaml_string,
GObject **object,
GError **error);
/**
* modulemd_read_packager_string_ext: (rename-to modulemd_read_packager_string)
* @yaml_string: (in): A YAML string containing a packager document.
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
* #ModulemdPackagerV3 object initialized with the content from @yaml_string.
* @module_name: (in) (nullable): An optional module name to override the
* document on disk. Mostly useful in cases where the name is being
* auto-detected from git.
* @module_stream: (in) (nullable): An optional module stream name to override
* the document on disk. Mostly useful in cases where the name is being
* auto-detected from git.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
*
* Since: 2.11
*/
GType
modulemd_read_packager_string_ext (const gchar *yaml_string,
GObject **object,
const gchar *module_name,
const gchar *module_stream,
GError **error);
G_END_DECLS
|