### Createrepo Command Example Source: https://github.com/rpm-software-management/createrepo_c/wiki/New-File-Handling Demonstrates the usage of the 'createrepo' command with specific options to generate repository metadata. It shows the resulting contents of the 'repodata/' directory after initial creation and an update operation. ```bash mkdir testrepo && cd testrepo touch comps_a comps_b createrepo --no-database --simple-md-filenames --groupfile comps_a . createrepo --no-database --simple-md-filenames --groupfile comps_b --update . ``` -------------------------------- ### Define Executables and Installation Rules Source: https://github.com/rpm-software-management/createrepo_c/blob/master/src/CMakeLists.txt This snippet defines the primary executables (createrepo_c, mergerepo_c, etc.) and specifies the installation paths for binaries, headers, and development files. ```cmake ADD_EXECUTABLE(createrepo_c createrepo_c.c cmd_parser.c) TARGET_LINK_LIBRARIES(createrepo_c libcreaterepo_c PkgConfig::GLIB2 PkgConfig::GTHREAD2) INSTALL(TARGETS createrepo_c mergerepo_c modifyrepo_c sqliterepo_c RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT Runtime) ``` -------------------------------- ### Createrepo_c Command Example Source: https://github.com/rpm-software-management/createrepo_c/wiki/New-File-Handling Illustrates the usage of the 'createrepo_c' command, highlighting its improved behavior in managing the 'repodata/' directory. It shows the output after initial creation and an update operation, emphasizing the cleaner metadata file handling. ```bash mkdir testrepo && cd testrepo touch comps_a comps_b createrepo_c --no-database --simple-md-filenames --groupfile comps_a . createrepo_c --no-database --simple-md-filenames --groupfile comps_b --update . ``` -------------------------------- ### C Library API for Basic Repository Creation with createrepo_c Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates the basic usage of the createrepo_c C library to generate repository metadata. This example shows how to initialize the library, parse an RPM package, set its location, and then generate primary, filelists, and other XML metadata. It includes essential cleanup steps for allocated resources. Dependencies include createrepo_c headers and standard C libraries. ```c #include #include #include int main(int argc, char *argv[]) { GError *err = NULL; cr_Package *pkg; char *xml; // Initialize library cr_xml_dump_init(); cr_package_parser_init(); // Parse RPM package pkg = cr_package_from_rpm_base("package.rpm", 10, CR_HDRR_NONE, &err); if (!pkg) { fprintf(stderr, "Error: %s\n", err->message); g_error_free(err); return 1; } // Set location pkg->location_href = g_strdup("package.rpm"); // Generate XML metadata struct cr_XmlStruct xml_struct = cr_xml_dump(pkg, &err); if (err) { fprintf(stderr, "Error dumping XML: %s\n", err->message); g_error_free(err); cr_package_free(pkg); return 1; } printf("Primary XML:\n%s\n", xml_struct.primary); printf("Filelists XML:\n%s\n", xml_struct.filelists); printf("Other XML:\n%s\n", xml_struct.other); // Cleanup free(xml_struct.primary); free(xml_struct.filelists); free(xml_struct.other); cr_package_free(pkg); cr_package_parser_cleanup(); cr_xml_dump_cleanup(); return 0; } ``` -------------------------------- ### Example Usage with GError Source: https://github.com/rpm-software-management/createrepo_c/wiki/Createrepo_c-Error-Reporting Demonstrates how to correctly initialize and use a GError pointer when calling createrepo_c functions. ```APIDOC ## Example Usage with GError ### Description This example shows the proper way to initialize a `GError` variable to NULL and check for errors after calling a createrepo_c function. ### Code Example ```c cr_Package *pkg; GError *err = NULL; // It's necessary to set err to NULL! cr_package_parser_init(); pkg = cr_package_from_rpm("foopkg.rpm", CR_SHA256, "packages/foopkg.rpm", NULL, 5, NULL, &err); cr_package_parser_cleanup(); if (err != NULL) { printf("Error occured: %d (%s)", err->code, err->msg); g_error_free(err); return 1; } // Process pkg if no error occurred return 0; ``` ### Notes - Ensure `GError *err` is always initialized to `NULL` before calling any function that might set it. - Always check if `err` is not `NULL` after the function call to detect errors. - Free the `GError` object using `g_error_free(err)` if an error occurred. ``` -------------------------------- ### CMake Project Setup and Build Type Configuration Source: https://github.com/rpm-software-management/createrepo_c/blob/master/CMakeLists.txt Initializes the CMake project, sets C++ standard, and configures build types (Debug, Release, etc.). It also includes options for building shared libraries and installing development files or man-pages. ```cmake CMAKE_MINIMUM_REQUIRED (VERSION 3.7) PROJECT (createrepo_c C) include(GNUInstallDirs) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -ggdb -g -Wall -Wextra -Og") IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) IF(CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL "DEBUG") MESSAGE("Build type is set do DEBUG! (Used flags: \"${CMAKE_C_FLAGS_DEBUG}\")") ENDIF() option(BUILD_LIBCREATEREPO_C_SHARED "Build libcreaterepo_c as a shared library" ON) if(NOT BUILD_LIBCREATEREPO_C_SHARED) set(CMAKE_POSITION_INDEPENDENT_CODE 1) endif() option(CREATEREPO_C_INSTALL_DEVELOPMENT "Install createrepo_c development files." ON) option(CREATEREPO_C_INSTALL_MANPAGES "Install createrepo_c man-pages." ON) ``` -------------------------------- ### Python Compression Utilities with createrepo_c Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates how to use createrepo_c functions for handling file compression. It shows how to get compression suffixes for different compression types, detect the compression type of a file, and compress a file while collecting statistics like size and checksum. Dependencies include the createrepo_c library. ```python import createrepo_c as cr def compression_examples(): """Demonstrate compression functionality.""" # Supported compression types compression_types = [ (cr.GZ_COMPRESSION, "gzip"), (cr.BZ2_COMPRESSION, "bzip2"), (cr.XZ_COMPRESSION, "xz"), (cr.ZSTD_COMPRESSION, "zstd"), (cr.ZCK_COMPRESSION, "zchunk"), (cr.NO_COMPRESSION, "none"), ] # Get compression suffix for ct, name in compression_types: suffix = cr.compression_suffix(ct) print(f"{name}: suffix = '{suffix}'") # Detect compression type of a file detected = cr.detect_compression("/path/to/file.xml.gz") print(f"Detected compression: {detected}") # Compress a file with statistics stats = cr.ContentStat(cr.SHA256) cr.compress_file_with_stat( "/path/to/input.xml", "/path/to/output.xml.gz", cr.GZ_COMPRESSION, stats ) print(f"Uncompressed size: {stats.size}") print(f"Uncompressed checksum: {stats.checksum}") # Usage compression_examples() ``` -------------------------------- ### Checksum Utilities with createrepo_c (Python) Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Provides examples of using createrepo_c's checksum utilities in Python. This includes demonstrating supported checksum types, converting checksum types to their string representations, parsing checksum types from strings, and calculating file checksums. ```python import createrepo_c as cr def checksum_examples(): """Demonstrate checksum functionality.""" # Supported checksum types checksum_types = [ cr.SHA256, cr.SHA512, cr.SHA384, cr.SHA224, ] # Get checksum type name for ct in checksum_types: name = cr.checksum_name_str(ct) print(f"Checksum type {ct}: {name}") # Parse checksum type from string sha256_type = cr.checksum_type("sha256") print(f"'sha256' -> type {sha256_type}") # Calculate file checksum checksum = cr.checksum_file("/path/to/file.rpm", cr.SHA256) print(f"SHA256: {checksum}") # Usage checksum_examples() ``` -------------------------------- ### Configure Bash Autocompletions for createrepo_c Source: https://github.com/rpm-software-management/createrepo_c/blob/master/CMakeLists.txt This CMake code configures and installs Bash autocompletions for createrepo_c and related tools (mergerepo_c, modifyrepo_c, sqliterepo_c). It checks for the 'bash-completion' package and installs the completions to the appropriate directory, creating symlinks for related commands. ```cmake OPTION(ENABLE_BASHCOMP "Install Bash autocompletions?" ON) IF (ENABLE_BASHCOMP) CONFIGURE_FILE(createrepo_c.bash.in ${CMAKE_BINARY_DIR}/createrepo_c.bash @ONLY) pkg_check_modules(BASHCOMP bash-completion) IF (BASHCOMP_FOUND) execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=completionsdir bash-completion OUTPUT_VARIABLE BASHCOMP_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) message("Bash completion directory: ${BASHCOMP_DIR}") INSTALL(FILES ${CMAKE_BINARY_DIR}/createrepo_c.bash DESTINATION ${BASHCOMP_DIR} RENAME createrepo_c) INSTALL(CODE " execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink createrepo_c $ENV{DESTDIR}${BASHCOMP_DIR}/mergerepo_c) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink createrepo_c $ENV{DESTDIR}${BASHCOMP_DIR}/modifyrepo_c) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink createrepo_c $ENV{DESTDIR}${BASHCOMP_DIR}/sqliterepo_c) ") ELSEIF (BASHCOMP_FOUND) INSTALL(FILES ${CMAKE_BINARY_DIR}/createrepo_c.bash DESTINATION "/etc/bash_completion.d") message("Bash completion directory: /etc/bash_completion.d") ENDIF (BASHCOMP_FOUND) ENDIF (ENABLE_BASHCOMP) ``` -------------------------------- ### Build createrepo_c Python Package Source: https://github.com/rpm-software-management/createrepo_c/blob/master/README.md Commands to build Python distributions (wheel and sdist) for createrepo_c. Installing these packages may require the 'scikit-build' Python package for older Pip versions. ```python python setup.py bdist_wheel ``` ```python python setup.py sdist ``` ```python pip install dist/{{ package name }} ``` ```python python setup.py develop ``` -------------------------------- ### Build createrepo_c Documentation Source: https://github.com/rpm-software-management/createrepo_c/blob/master/README.md Instructions to build the project's documentation, which requires doxygen and sphinx. The documentation is built from the build directory. ```bash cd build/ make doc ``` -------------------------------- ### Setting Resource Limits with ulimit Source: https://github.com/rpm-software-management/createrepo_c/wiki/Debugging-&-Profiling-Tips Demonstrates how to set resource limits for a process, specifically the soft limit for virtual memory, using the 'ulimit' command before executing the program. ```bash ulimit -Sv 500000 # Set soft limit of virtual memory to 500Mb prog ``` -------------------------------- ### Create RPM Repository with RepositoryWriter Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates creating an RPM repository using the RepositoryWriter class. It shows both the recommended context manager approach for automatic resource cleanup and the manual configuration method for custom repository settings. ```python import os import createrepo_c as cr def create_repository(path): pkg_list = [entry.path for entry in os.scandir(path) if entry.is_file() and entry.path.endswith(".rpm")] with cr.RepositoryWriter(path) as writer: writer.repomd.add_repo_tag("Fedora 39") writer.repomd.set_revision("1699900000") writer.set_num_of_pkgs(len(pkg_list)) for filename in pkg_list: pkg = writer.add_pkg_from_file(filename) print(f"Added: {pkg.nevra()}") writer = cr.RepositoryWriter(path, unique_md_filenames=True, changelog_limit=10, checksum_type=cr.SHA256, compression=cr.XZ_COMPRESSION) writer.repomd.add_repo_tag("Custom Repository") writer.repomd.add_content_tag("binary-x86_64") writer.repomd.add_distro_tag("cpe:/o:fedoraproject:fedora:39", "Fedora 39") writer.set_num_of_pkgs(len(pkg_list)) for filename in pkg_list: pkg = writer.add_pkg_from_file(filename) print(f"Added: {pkg.nevra()}") writer.finish() ``` -------------------------------- ### gperftools Profiling and Checking Source: https://github.com/rpm-software-management/createrepo_c/wiki/Debugging-&-Profiling-Tips Demonstrates how to use gperftools for heap checking, heap profiling, and CPU profiling by setting environment variables before running the target program. ```bash HEAPCHECK=normal prog # Heap checker HEAPPROFILE=/tmp/netheap prog # Heap profiler CPUPROFILE=/tmp/profile prog # CPU profiler ``` -------------------------------- ### Build and Run createrepo_c Tests Source: https://github.com/rpm-software-management/createrepo_c/blob/master/README.md Commands to build and execute all unit tests for createrepo_c, including both C and Python tests. A verbose output option is available for testing. ```bash make tests && make test ``` ```bash make ARGS="-V" test ``` -------------------------------- ### Generate repomd.xml with Createrepo C Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt This C code snippet demonstrates how to generate a repomd.xml file using the Createrepo C library. It involves initializing the library, creating a repomd object, setting metadata, adding package records, and finally dumping the XML content. Error handling is included for critical operations. ```c #include #include int main() { GError *err = NULL; char *xml; cr_xml_dump_init(); // Create repomd object cr_Repomd *md = cr_repomd_new(); // Set metadata cr_repomd_set_revision(md, "1699900000"); cr_repomd_add_repo_tag(md, "Fedora 39"); cr_repomd_add_content_tag(md, "binary-x86_64"); cr_repomd_add_distro_tag(md, "cpe:/o:fedoraproject:fedora:39", "Fedora 39"); // Create record for primary.xml cr_RepomdRecord *rec = cr_repomd_record_new("primary", "repodata/primary.xml.gz"); cr_repomd_record_fill(rec, CR_CHECKSUM_SHA256, &err); if (err) { fprintf(stderr, "Error: %s\n", err->message); g_error_free(err); return 1; } cr_repomd_record_rename_file(rec, &err); cr_repomd_set_record(md, rec); // Generate repomd.xml content xml = cr_xml_dump_repomd(md, &err); if (xml) { printf("%s\n", xml); free(xml); } // Cleanup cr_repomd_free(md); cr_xml_dump_cleanup(); return 0; } ``` -------------------------------- ### Read Repository Metadata with RepositoryReader Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Shows how to initialize a RepositoryReader from a file path to inspect repository contents. It covers iterating through package NEVRA information and accessing security advisory details. ```python import createrepo_c as cr def read_repository(repo_path): reader = cr.RepositoryReader.from_path(repo_path) print("Packages in repository:") for package in reader.iter_packages(): print(f" {package.nevra()}") print(f" Summary: {package.summary}") print(f" Size: {package.size_package} bytes") print(f" License: {package.rpm_license}") print("\nAdvisories:") for advisory in reader.advisories(): print(f" {advisory.id}: {advisory.title}") print(f" Type: {advisory.type}") print(f" Severity: {advisory.severity}") ``` -------------------------------- ### Generate repomd.xml Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates how to initialize a repomd object, add metadata tags, create records for repository files, and generate the final repomd.xml content. ```APIDOC ## C API: Generate repomd.xml ### Description Initializes a new repository metadata (repomd) object, populates it with revision and distribution tags, and generates the XML output for a repository. ### Method N/A (C Library Function Call) ### Endpoint cr_xml_dump_repomd(cr_Repomd *md, GError **err) ### Parameters #### Path Parameters - **md** (cr_Repomd*) - Required - The repomd object to serialize. - **err** (GError**) - Required - Pointer to a GError structure to capture potential errors. ### Request Example ```c cr_Repomd *md = cr_repomd_new(); cr_repomd_set_revision(md, "1699900000"); char *xml = cr_xml_dump_repomd(md, &err); ``` ### Response #### Success Response (200) - **xml** (char*) - The generated XML string representing the repomd.xml file content. #### Response Example 1699900000 ... ``` -------------------------------- ### Parse RPM Metadata and Generate Repository XML Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates how to load an RPM file into a package object to access detailed metadata and how to generate primary, filelists, and other XML metadata for repository management. ```python import createrepo_c as cr import os def parse_rpm_package(rpm_path): pkg = cr.package_from_rpm(rpm_path) print(f"Name: {pkg.name}") print(f"NEVRA: {pkg.nevra()}") # ... (additional metadata access) return pkg def generate_xml_from_rpm(rpm_path): xml = cr.xml_from_rpm( rpm_path, checksum_type=cr.SHA256, location_href=os.path.basename(rpm_path) ) print(xml.primary) print(xml.filelists) print(xml.other) ``` -------------------------------- ### Manually Create RPM Repository Metadata with Python Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt This Python function demonstrates how to manually create RPM repository metadata files (primary.xml.gz, filelists.xml.gz, other.xml.gz) and their corresponding SQLite databases. It iterates through RPM packages, extracts information, and populates the metadata files and databases using the createrepo_c library. Finally, it generates the repomd.xml index file. ```python import os import createrepo_c as cr def manual_create_repository(path): """Create repository with manual control over metadata files.""" repodata_path = os.path.join(path, "repodata") os.makedirs(repodata_path, exist_ok=True) # Define file paths pri_xml_path = os.path.join(repodata_path, "primary.xml.gz") fil_xml_path = os.path.join(repodata_path, "filelists.xml.gz") oth_xml_path = os.path.join(repodata_path, "other.xml.gz") pri_db_path = os.path.join(repodata_path, "primary.sqlite") fil_db_path = os.path.join(repodata_path, "filelists.sqlite") oth_db_path = os.path.join(repodata_path, "other.sqlite") # Create XML writers and SQLite databases pri_xml = cr.PrimaryXmlFile(pri_xml_path) fil_xml = cr.FilelistsXmlFile(fil_xml_path) oth_xml = cr.OtherXmlFile(oth_xml_path) pri_db = cr.PrimarySqlite(pri_db_path) fil_db = cr.FilelistsSqlite(fil_db_path) oth_db = cr.OtherSqlite(oth_db_path) # Collect packages pkg_list = [ os.path.join(path, f) for f in os.listdir(path) if f.endswith(".rpm") ] # Set package count pri_xml.set_num_of_pkgs(len(pkg_list)) fil_xml.set_num_of_pkgs(len(pkg_list)) oth_xml.set_num_of_pkgs(len(pkg_list)) # Process packages for filename in pkg_list: pkg = cr.package_from_rpm(filename) pkg.location_href = os.path.basename(filename) # Add to XML files pri_xml.add_pkg(pkg) fil_xml.add_pkg(pkg) oth_xml.add_pkg(pkg) # Add to SQLite databases pri_db.add_pkg(pkg) fil_db.add_pkg(pkg) oth_db.add_pkg(pkg) # Close XML files pri_xml.close() fil_xml.close() oth_xml.close() # Create repomd.xml repomd = cr.Repomd() # Add records for each metadata file for name, xml_path, db in [ ("primary", pri_xml_path, pri_db), ("filelists", fil_xml_path, fil_db), ("other", oth_xml_path, oth_db), ("primary_db", pri_db_path, None), ("filelists_db", fil_db_path, None), ("other_db", oth_db_path, None), ]: record = cr.RepomdRecord(name, xml_path) record.fill(cr.SHA256) if db: db.dbinfo_update(record.checksum) db.close() repomd.set_record(record) # Write repomd.xml repomd_path = os.path.join(repodata_path, "repomd.xml") with open(repomd_path, "w") as f: f.write(repomd.xml_dump()) # Usage manual_create_repository("/var/repo/packages") ``` -------------------------------- ### Dependency Discovery and Configuration Source: https://github.com/rpm-software-management/createrepo_c/blob/master/CMakeLists.txt Finds and configures necessary external libraries and packages using PkgConfig and find_package commands. This includes libraries like BZip2, CURL, LibXml2, OpenSSL, ZLIB, GLIB2, GIO, GTHREAD2, LZMA, SQLITE3, RPM, ZSTD, DRPM, ZCHUNK, and LIBMODULEMD. ```cmake # Add path with own cmake modules INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") SET(G_LOG_DOMAIN "C_CREATEREPOLIB") # Find necessary libraries find_package(PkgConfig) find_package(BZip2 REQUIRED) find_package(CURL REQUIRED) find_package(LibXml2 REQUIRED) find_package(OpenSSL REQUIRED) find_package(ZLIB REQUIRED) pkg_check_modules(GLIB2 REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) pkg_check_modules(GTHREAD2 REQUIRED IMPORTED_TARGET gthread-2.0) pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma) pkg_check_modules(SQLITE3 REQUIRED IMPORTED_TARGET sqlite3>=3.6.18) pkg_check_modules(RPM REQUIRED IMPORTED_TARGET rpm) pkg_check_modules(ZSTD REQUIRED IMPORTED_TARGET zstd) # Add include dirs include_directories(${BZIP2_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) include_directories(${GLIB2_INCLUDE_DIRS}) include_directories(${GIO_INCLUDE_DIRS}) include_directories(${LIBXML2_INCLUDE_DIR}) include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${ZLIB_INCLUDE_DIR}) include_directories(${ZSTD_INCLUDE_DIRS}) ``` ```cmake # SuSE/Mageia/Mandriva legacy weak deps support OPTION (ENABLE_LEGACY_WEAKDEPS "Enable legacy SUSE/Mageia/Mandriva weakdeps support?" ON) IF (ENABLE_LEGACY_WEAKDEPS) ADD_DEFINITIONS("-DENABLE_LEGACY_WEAKDEPS=1") ENDIF (ENABLE_LEGACY_WEAKDEPS) # Legacy hash functions OPTION (WITH_LEGACY_HASHES "Build with SHA-1 and MD5 support" OFF) IF (WITH_LEGACY_HASHES) ADD_DEFINITIONS("-DWITH_LEGACY_HASHES=1") ENDIF (WITH_LEGACY_HASHES) # drpm OPTION (ENABLE_DRPM "Enable delta RPM support?" OFF) IF (ENABLE_DRPM) pkg_check_modules(DRPM REQUIRED IMPORTED_TARGET drpm>=0.4.0) include_directories (${DRPM_INCLUDE_DIRS}) ADD_DEFINITIONS("-DCR_DELTA_RPM_SUPPORT") ENDIF (ENABLE_DRPM) IF (ENABLE_DRPM) SET (ENABLE_DRPM_BASH 1) ELSE () SET (ENABLE_DRPM_BASH 0) ENDIF () # option to enable/disable python support OPTION (ENABLE_PYTHON "Enable python support?" ON) OPTION (WITH_ZCHUNK "Build with zchunk support" ON) IF (WITH_ZCHUNK) pkg_check_modules(ZCK REQUIRED IMPORTED_TARGET zck) include_directories(${ZCK_INCLUDE_DIRS}) SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWITH_ZCHUNK") SET (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DWITH_ZCHUNK") ENDIF (WITH_ZCHUNK) OPTION (WITH_LIBMODULEMD "Build with libmodulemd support" ON) IF (WITH_LIBMODULEMD) pkg_check_modules(LIBMODULEMD REQUIRED IMPORTED_TARGET modulemd-2.0) include_directories(${LIBMODULEMD_INCLUDE_DIRS}) SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWITH_LIBMODULEMD") SET (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DWITH_LIBMODULEMD") ENDIF (WITH_LIBMODULEMD) ``` -------------------------------- ### Build createrepo_c RPM Package Source: https://github.com/rpm-software-management/createrepo_c/blob/master/README.md Instructions for building an RPM package for createrepo_c. This involves modifying the .spec file and using the provided script. A link to the current .spec file for Fedora rawhide is also provided. ```bash utils/make_rpm.sh ``` -------------------------------- ### Valgrind Massif Heap Profiler Source: https://github.com/rpm-software-management/createrepo_c/wiki/Debugging-&-Profiling-Tips This snippet illustrates how to use Valgrind's Massif tool to profile heap memory usage of a program and how to print the analysis results using ms_print. ```bash valgrind --tool=massif prog ms_print massif.out.12345 ``` -------------------------------- ### Build createrepo_c with CMake Source: https://github.com/rpm-software-management/createrepo_c/blob/master/README.md Standard build process for createrepo_c using CMake. This involves creating a build directory, configuring with CMake, and then compiling the project. Debug symbols can be included by setting CMAKE_BUILD_TYPE to DEBUG. ```bash mkdir build cd build/ cmake .. make ``` ```bash cmake -DCMAKE_BUILD_TYPE:STRING=DEBUG .. && make ``` -------------------------------- ### Create and Parse Security Advisories with UpdateInfo API (Python) Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates how to create and parse security advisories (updateinfo.xml) using the UpdateInfo API in Python. This includes defining package information, collections, references, and update records. It covers creating an advisory from scratch and parsing an existing XML file. ```python import datetime import createrepo_c as cr def create_updateinfo(): """Create security advisory metadata (updateinfo.xml).""" # Create a package affected by this update pkg = cr.UpdateCollectionPackage() pkg.name = "httpd" pkg.version = "2.4.57" pkg.release = "1.fc39" pkg.epoch = "0" pkg.arch = "x86_64" pkg.src = "httpd-2.4.57-1.fc39.src.rpm" pkg.filename = "httpd-2.4.57-1.fc39.x86_64.rpm" pkg.sum = "abc123def456..." pkg.sum_type = cr.SHA256 pkg.reboot_suggested = False # Create a collection (group of packages) collection = cr.UpdateCollection() collection.shortname = "fedora-39-updates" collection.name = "Fedora 39 Updates" collection.append(pkg) # Create a reference (link to bugzilla, CVE, etc.) ref = cr.UpdateReference() ref.href = "https://bugzilla.redhat.com/show_bug.cgi?id=2234567" ref.id = "2234567" ref.type = "bugzilla" ref.title = "CVE-2023-12345 httpd: vulnerability in mod_ssl" cve_ref = cr.UpdateReference() cve_ref.href = "https://nvd.nist.gov/vuln/detail/CVE-2023-12345" cve_ref.id = "CVE-2023-12345" cve_ref.type = "cve" cve_ref.title = "CVE-2023-12345" # Create the update record record = cr.UpdateRecord() record.fromstr = "security@fedoraproject.org" record.status = "final" record.type = "security" record.version = "1" record.id = "FEDORA-2023-abc123def456" record.title = "httpd security update" record.issued_date = datetime.datetime(2023, 11, 15) record.updated_date = datetime.datetime(2023, 11, 15) record.rights = "Copyright 2023 Fedora Project" record.summary = "An update for httpd is now available." record.description = """ This update fixes a security vulnerability in Apache HTTP Server. Security Fix(es): * httpd: mod_ssl vulnerability allows remote code execution (CVE-2023-12345) """ record.severity = "Important" record.solution = "Update to the latest version using 'dnf update httpd'" record.reboot_suggested = False record.append_collection(collection) record.append_reference(ref) record.append_reference(cve_ref) # Create UpdateInfo and add record updateinfo = cr.UpdateInfo() updateinfo.append(record) # Generate XML xml_content = updateinfo.xml_dump() print(xml_content) # Save to file with open("updateinfo.xml", "w") as f: f.write(xml_content) return updateinfo def parse_updateinfo(path): """Parse existing updateinfo.xml file.""" updateinfo = cr.UpdateInfo(path) for update in updateinfo.updates: print(f"Advisory: {update.id}") print(f" Type: {update.type}") print(f" Severity: {update.severity}") print(f" Title: {update.title}") print(f" Issued: {update.issued_date}") print(f" Status: {update.status}") print(f" Description: {update.description[:200]}...") print(" References:") for ref in update.references: print(f" - [{ref.type}] {ref.id}: {ref.href}") print(" Affected packages:") for collection in update.collections: print(f" Collection: {collection.name}") for pkg in collection.packages: print(f" - {pkg.name}-{pkg.version}-{pkg.release}.{pkg.arch}") # Usage create_updateinfo() parse_updateinfo("updateinfo.xml") ``` -------------------------------- ### Create RPM Repository Metadata with createrepo_c Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Scans a directory for RPM packages and generates repository metadata (primary.xml, filelists.xml, etc.) and repomd.xml. Supports options for checksum types, compression, updating existing repos, custom output, zchunk, and package exclusions. ```bash createrepo_c /path/to/packages/ ``` ```bash createrepo_c --checksum sha512 --compress-type xz /path/to/packages/ ``` ```bash createrepo_c --update /path/to/packages/ ``` ```bash createrepo_c \ --outputdir /var/www/html/repo/ \ --baseurl http://example.com/repo/ \ --groupfile comps.xml \ --workers 8 \ --changelog-limit 10 \ --revision "$(date +%s)" \ /path/to/packages/ ``` ```bash createrepo_c --zck --zck-dict-dir /path/to/dictionaries/ /path/to/packages/ ``` ```bash createrepo_c --excludes "*.src.rpm" --excludes "debug-*" /path/to/packages/ ``` -------------------------------- ### Implementing GError Handling in Createrepo_c Source: https://github.com/rpm-software-management/createrepo_c/wiki/Createrepo_c-Error-Reporting Demonstrates the correct initialization, usage, and cleanup of GError when parsing an RPM package. The snippet shows how to handle potential errors by checking the error pointer and freeing it after use. ```c cr_Package *pkg; GError *err = NULL; // It's necessary to set err to NULL! cr_package_parser_init(); pkg = cr_package_from_rpm("foopkg.rpm", CR_SHA256, "packages/foopkg.rpm", NULL, 5, NULL, &err); cr_package_parser_cleanup(); if (err != NULL) { printf("Error occured: %d (%s)", err->code, err->msg); g_error_free(err); return 1; } return 0; ``` -------------------------------- ### Parse Repository with Callbacks (Python) Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Illustrates parsing repository metadata using custom callbacks for filtering and processing packages. This method allows for fine-grained control over package inclusion and data extraction during the parsing of primary, filelists, and other XML files. ```Python import os import createrepo_c as cr def parse_with_callbacks(repo_path): """Parse repository using callbacks for custom filtering.""" packages = {} def warning_callback(warning_type, message): print(f"Warning: {message}") return True def package_callback(pkg): """Called when a complete package is parsed.""" packages[pkg.pkgId] = pkg return True # Continue parsing def new_package_callback(pkgId, name, arch): """Called when a new package element starts. Return existing package to merge data, or None to skip. """ if name and name.startswith("debug"): return None # Skip debug packages return packages.get(pkgId, cr.Package()) # Parse repomd.xml repomd = cr.Repomd(os.path.join(repo_path, "repodata/repomd.xml")) primary_path = filelists_path = other_path = None for record in repomd.records: if record.type == "primary": primary_path = os.path.join(repo_path, record.location_href) elif record.type == "filelists": filelists_path = os.path.join(repo_path, record.location_href) elif record.type == "other": other_path = os.path.join(repo_path, record.location_href) # Parse primary.xml (use do_files=False if parsing filelists separately) cr.xml_parse_primary( primary_path, pkgcb=package_callback, do_files=False, warningcb=warning_callback ) # Parse filelists.xml (merge into existing packages) cr.xml_parse_filelists( filelists_path, newpkgcb=new_package_callback, warningcb=warning_callback ) # Parse other.xml (merge changelogs into existing packages) cr.xml_parse_other( other_path, newpkgcb=new_package_callback, warningcb=warning_callback ) print(f"Parsed {len(packages)} packages") return packages # Usage # packages = parse_with_callbacks("/var/www/html/repo/") ``` -------------------------------- ### Parse and Create repomd.xml Repository Index with Python Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt This Python code provides functionality to parse an existing repomd.xml file, displaying its revision, content hash, and metadata records including checksums, sizes, and timestamps. It also includes a function to programmatically create a new repomd.xml file, setting metadata like revision, repo tags, content tags, and adding individual metadata records. ```python import os import createrepo_c as cr def parse_repomd(repo_path): """Parse and display repomd.xml information.""" repomd_path = os.path.join(repo_path, "repodata/repomd.xml") repomd = cr.Repomd(repomd_path) print(f"Revision: {repomd.revision}") print(f"Content hash: {repomd.contenthash} ({repomd.contenthash_type})") print(f"Repo tags: {repomd.repo_tags}") print(f"Content tags: {repomd.content_tags}") print(f"Distro tags: {repomd.distro_tags}") print("\nMetadata records:") for rec in repomd.records: print(f" Type: {rec.type}") print(f" Location: {rec.location_href}") print(f" Checksum: {rec.checksum} ({rec.checksum_type})") print(f" Size: {rec.size} bytes (uncompressed: {rec.size_open})") print(f" Timestamp: {rec.timestamp}") if rec.db_ver: print(f" DB Version: {rec.db_ver}") def create_repomd(): """Create a new repomd.xml programmatically.""" repomd = cr.Repomd() # Set metadata repomd.set_revision("1699900000") repomd.add_repo_tag("Fedora 39") repomd.add_content_tag("binary-x86_64") repomd.add_distro_tag("cpe:/o:fedoraproject:fedora:39", "Fedora 39") # Add record for primary.xml record = cr.RepomdRecord("primary", "/path/to/repodata/primary.xml.gz") record.fill(cr.SHA256) # Calculate checksums and sizes record.rename_file() # Add checksum to filename repomd.set_record(record) # Generate XML xml_content = repomd.xml_dump() print(xml_content) return repomd # Usage parse_repomd("/var/www/html/repo/") create_repomd() ``` -------------------------------- ### Add C Executable for Test Source: https://github.com/rpm-software-management/createrepo_c/blob/master/tests/CMakeLists.txt This snippet demonstrates how to add a C executable for testing purposes. It specifies the executable name, its source file, and links it against the necessary libraries, including libcreaterepo_c and PkgConfig::GLib2. It also adds the executable as a dependency to a 'tests' target. ```cmake ADD_EXECUTABLE(test_checksum test_checksum.c) TARGET_LINK_LIBRARIES(test_checksum libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_checksum) ``` ```cmake ADD_EXECUTABLE(test_compression_wrapper test_compression_wrapper.c) TARGET_LINK_LIBRARIES(test_compression_wrapper libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_compression_wrapper) ``` ```cmake ADD_EXECUTABLE(test_load_metadata test_load_metadata.c) TARGET_LINK_LIBRARIES(test_load_metadata libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_load_metadata) ``` ```cmake ADD_EXECUTABLE(test_locate_metadata test_locate_metadata.c) TARGET_LINK_LIBRARIES(test_locate_metadata libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_locate_metadata) ``` ```cmake ADD_EXECUTABLE(test_misc test_misc.c) TARGET_LINK_LIBRARIES(test_misc libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_misc) ``` ```cmake ADD_EXECUTABLE(test_sqlite test_sqlite.c) TARGET_LINK_LIBRARIES(test_sqlite libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_sqlite) ``` ```cmake ADD_EXECUTABLE(test_xml_file test_xml_file.c) TARGET_LINK_LIBRARIES(test_xml_file libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_file) ``` ```cmake ADD_EXECUTABLE(test_xml_parser_filelists test_xml_parser_filelists.c) TARGET_LINK_LIBRARIES(test_xml_parser_filelists libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_parser_filelists) ``` ```cmake ADD_EXECUTABLE(test_xml_parser_repomd test_xml_parser_repomd.c) TARGET_LINK_LIBRARIES(test_xml_parser_repomd libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_parser_repomd) ``` ```cmake ADD_EXECUTABLE(test_xml_parser_updateinfo test_xml_parser_updateinfo.c) TARGET_LINK_LIBRARIES(test_xml_parser_updateinfo libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_parser_updateinfo) ``` ```cmake ADD_EXECUTABLE(test_xml_parser_main_metadata_together test_xml_parser_main_metadata_together.c) TARGET_LINK_LIBRARIES(test_xml_parser_main_metadata_together libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_parser_main_metadata_together) ``` ```cmake ADD_EXECUTABLE(test_xml_dump test_xml_dump.c) TARGET_LINK_LIBRARIES(test_xml_dump libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_dump) ``` ```cmake ADD_EXECUTABLE(test_xml_dump_primary test_xml_dump_primary.c) TARGET_LINK_LIBRARIES(test_xml_dump_primary libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_xml_dump_primary) ``` ```cmake ADD_EXECUTABLE(test_koji test_koji.c) TARGET_LINK_LIBRARIES(test_koji libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_koji) ``` ```cmake ADD_EXECUTABLE(test_modifyrepo_shared test_modifyrepo_shared.c) TARGET_LINK_LIBRARIES(test_modifyrepo_shared libcreaterepo_c PkgConfig::GLib2) ADD_DEPENDENCIES(tests test_modifyrepo_shared) ``` -------------------------------- ### Run only C Unit Tests for createrepo_c Source: https://github.com/rpm-software-management/createrepo_c/blob/master/README.md Specific command to run only the C unit tests for createrepo_c. These tests must be built first using 'make tests'. ```bash build/tests/run_tests.sh ``` -------------------------------- ### Analyzing gperftools Heap Profile Source: https://github.com/rpm-software-management/createrepo_c/wiki/Debugging-&-Profiling-Tips Shows the command to analyze a heap profile generated by gperftools using the pprof tool, displaying the results in text format. ```bash pprof --text prog /tmp/netheap.0001.heap ``` -------------------------------- ### Navigate to Createrepo_c Pages Directory Source: https://github.com/rpm-software-management/createrepo_c/wiki/Online-Documentation-Update-Workflow This command changes the current directory to the cloned createrepo_c-pages directory. This is a necessary step before executing further commands related to documentation updates. ```bash cd createrepo_c-pages/ ``` -------------------------------- ### Configure createrepo_c Library and Dependencies Source: https://github.com/rpm-software-management/createrepo_c/blob/master/src/CMakeLists.txt This snippet handles the conditional compilation of the createrepo_c library, including setting the library type (shared or static) and linking all required system dependencies like GLIB, OpenSSL, and RPM. ```cmake IF (BUILD_LIBCREATEREPO_C_SHARED) SET (createrepo_c_library_type SHARED) ELSE () SET (createrepo_c_library_type STATIC) ENDIF () ADD_LIBRARY(libcreaterepo_c ${createrepo_c_library_type} ${createrepo_c_SRCS}) TARGET_LINK_LIBRARIES(libcreaterepo_c ${BZIP2_LIBRARIES} ${CURL_LIBRARY} PkgConfig::GLIB2 PkgConfig::GIO ${LIBXML2_LIBRARIES} PkgConfig::LZMA ${OPENSSL_LIBRARIES} PkgConfig::RPM PkgConfig::SQLITE3 ${ZLIB_LIBRARY} PkgConfig::ZSTD) ``` -------------------------------- ### Parse Repository with Streaming Iterator (Python) Source: https://context7.com/rpm-software-management/createrepo_c/llms.txt Demonstrates memory-efficient parsing of repository metadata using a streaming iterator. It first parses repomd.xml to find metadata file locations and then uses PackageIterator to process packages one by one, suitable for large repositories. ```Python import os import createrepo_c as cr def parse_repository_streaming(repo_path): """Parse repository using streaming iterator (memory efficient).""" def warning_callback(warning_type, message): print(f"Warning: {message}") return True # Continue parsing # Parse repomd.xml to get metadata file locations repomd = cr.Repomd() cr.xml_parse_repomd( os.path.join(repo_path, "repodata/repomd.xml"), repomd, warning_callback ) # Find metadata file paths primary_path = filelists_path = other_path = None for record in repomd.records: full_path = os.path.join(repo_path, record.location_href) if record.type == "primary": primary_path = full_path elif record.type == "filelists": filelists_path = full_path elif record.type == "other": other_path = full_path # Use PackageIterator for memory-efficient streaming pkg_iterator = cr.PackageIterator( primary_path=primary_path, filelists_path=filelists_path, other_path=other_path, warningcb=warning_callback ) for pkg in pkg_iterator: print(f"Package: {pkg.nevra()}") print(f" Summary: {pkg.summary}") print(f" Files: {len(pkg.files)}") # Package is processed and can be freed after this iteration # Usage # parse_repository_streaming("/var/www/html/repo/") ```