Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

alpm-package

A library providing low-level functionality for Arch Linux Package Management (ALPM) based packages.

This library offers integration for creating an alpm-package from a prepared input directory, which contains all necessary files (i.e. metadata files, optional install scriptlets and data files).

Documentation

Examples

Library

A package file can be created from a prepared input directory. The input directory must contain at the very least a valid BUILDINFO, a PKGINFO and an ALPM-MTREE file. Then the relevant metadata/data/script files can be read from the package archive using the PackageReader API.

use std::fs::{File, Permissions, create_dir_all};
use std::io::Write;
use std::os::unix::fs::PermissionsExt;

use alpm_mtree::create_mtree_v2_from_input_dir;
use alpm_package::{
    CompressionSettings,
    InputDir,
    MetadataEntry,
    OutputDir,
    Package,
    PackageCreationConfig,
    PackageInput,
};
use alpm_types::MetadataFileName;
use tempfile::TempDir;

fn main() -> testresult::TestResult {
// Create a common temporary directory for input and output.
let temp_dir = TempDir::new()?;
let path = temp_dir.path();
let input_dir = path.join("input");
create_dir_all(&input_dir)?;
let input_dir = InputDir::new(input_dir)?;
let output_dir = OutputDir::new(path.join("output"))?;

// Create a valid, but minimal BUILDINFOv2 file.
let mut file = File::create(&input_dir.join(MetadataFileName::BuildInfo.as_ref()))?;
write!(file, r#"
builddate = 1
builddir = /build
startdir = /startdir/
buildtool = devtools
buildtoolver = 1:1.2.1-1-any
format = 2
installed = other-example-1.2.3-1-any
packager = John Doe <john@example.org>
pkgarch = any
pkgbase = example
pkgbuild_sha256sum = b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
pkgname = example
pkgver = 1:1.0.0-1
"#)?;

// Create a valid, but minimal PKGINFOv2 file.
let mut file = File::create(&input_dir.join(MetadataFileName::PackageInfo.as_ref()))?;
write!(file, r#"
pkgname = example
pkgbase = example
xdata = pkgtype=pkg
pkgver = 1:1.0.0-1
pkgdesc = A project that returns true
url = https://example.org/
builddate = 1
packager = John Doe <john@example.org>
size = 181849963
arch = any
license = GPL-3.0-or-later
depend = bash
"#)?;

// Create a dummy script as package data.
create_dir_all(&input_dir.join("usr/bin"))?;
let mut file = File::create(&input_dir.join("usr/bin/example"))?;
write!(file, r#"!/bin/bash
true
"#)?;
file.set_permissions(Permissions::from_mode(0o755))?;

// Create a valid ALPM-MTREEv2 file from the input directory.
create_mtree_v2_from_input_dir(&input_dir)?;

// Create PackageInput and PackageCreationConfig.
let package_input: PackageInput = input_dir.try_into()?;
let config = PackageCreationConfig::new(
    package_input,
    output_dir,
    Some(CompressionSettings::default()),
)?;
// Create package file.
let package = Package::try_from(&config)?;

// Create a reader for the package.
let mut reader = package.clone().into_reader()?;

// Read all the metadata from the package archive.
let metadata = reader.metadata()?;
let pkginfo = metadata.pkginfo;
let buildinfo = metadata.buildinfo;
let mtree = metadata.mtree;

// Or you can iterate over the metadata entries:
let mut reader = package.clone().into_reader()?;
for entry in reader.metadata_entries()? {
    let entry = entry?;
    match entry {
        MetadataEntry::PackageInfo(pkginfo) => {}
        MetadataEntry::BuildInfo(buildinfo) => {}
        MetadataEntry::Mtree(mtree) => {}
        _ => {}
    }
}

// You can also read specific metadata files directly:
let mut reader = package.clone().into_reader()?;
let pkginfo = reader.read_metadata_file(MetadataFileName::PackageInfo)?;
// let buildinfo = reader.read_metadata_file(MetadataFileName::BuildInfo)?;
// let mtree = reader.read_metadata_file(MetadataFileName::Mtree)?;

// Read the install scriptlet, if present:
let mut reader = package.clone().into_reader()?;
let install_scriptlet = reader.read_install_scriptlet()?;

// Iterate over the data entries in the package archive.
let mut reader = package.clone().into_reader()?;
for data_entry in reader.data_entries()? {
    let mut data_entry = data_entry?;
    let content = data_entry.content()?;
    // Note: data_entry also implements `Read`, so you can read from it directly.
}

// Convenience functions for reading packages without creating a reader:
let pkginfo = package.read_pkginfo()?;
let buildinfo = package.read_buildinfo()?;
let mtree = package.read_mtree()?;
let install_scriptlet = package.read_install_scriptlet()?;
Ok(())
}

Contributing

Please refer to the contribution guidelines to learn how to contribute to this project.

License

This project can be used under the terms of the Apache-2.0 or MIT. Contributions to this project, unless noted otherwise, are automatically licensed under the terms of both of those licenses.