Skip to content

Commit

Permalink
Copying the zyppng branch from Agama
Browse files Browse the repository at this point in the history
Taking the rust/libzypp directory from agama-project/agama#1603
  • Loading branch information
jreidinger authored and mvidner committed Sep 26, 2024
0 parents commit 37990ac
Show file tree
Hide file tree
Showing 28 changed files with 2,728 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "libzypp"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[package.metadata.docs.rs]
all-features = true
# For build.rs scripts
rustc-args = ["--cfg", "docsrs"]
# For rustdoc
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
libc = "0.2"
ffi = { package = "zypp-sys", path = "./zypp-sys" }
glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }

[[bin]]
name = "zypprs"
path = "src/bin.rs"
35 changes: 35 additions & 0 deletions Gir.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[options]
library = "Zypp"
version = "1.0"
min_cfg_version = "1.0"
target_path = "."
girs_directories = ["gir-files", "libzypp/build/zypp-glib"]
work_mode = "normal"
single_version_file = true
generate_safety_asserts = true
deprecate_by_min_version = true
generate_builder = true

generate = [
"Zypp.Context",
"Zypp.Exception",
"Zypp.Expected",
"Zypp.InfoBase",
"Zypp.ManagedFile",
"Zypp.ProgressObserver",
"Zypp.RepoInfo",
"Zypp.RepoInfoType",
"Zypp.RepoManager",
"Zypp.ServiceInfo",
"Zypp.RepoManagerOptions",
"Zypp.RepoManagerError",
"Zypp.RepoRefreshResult",
"Zypp.Repository",
"Zypp.*",
]

manual = [
"GLib.Error",
"GLib.Quark",
"GObject.Value"
]
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## Experimental bindings for libzypp glib

Goal of this crate is to provide direct rust bindings to libzypp to avoid long path over yast component system.

### Code Organization

- zypp-sys dir is low level unsafe libzypp bindings
- libzypp dir git submodule for glib branch of libzypp
- gir dir is gir submodule for gir tool on revision used for code generation
- gir-files dir is git submodule with directory with curated gir files ( see gir book for details )
- ./ is high level libzypp bindings

### Updating bindings

In general follow gir book. Ideally update gir submodule to master. Then regenerate zypp-sys,
then high level bindings and do not forget to also update documentation with `rustdoc-stripper`

### Resources

- gir book: https://gtk-rs.org/gir/book/introduction.html
- git submodules: https://git-scm.com/book/en/v2/Git-Tools-Submodules
108 changes: 108 additions & 0 deletions setup_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/bash

# Script that do initial setup for libzypp ng bindings development.
# To update git submodules use
# git submodule update --remote
#
# It needs TW as dev env. One of option is to use distrobox as shown:
# ```sh
# distrobox create --image tumbleweed --name zyppng
# distrobox enter zyppng # if stuck see https://github.com/89luca89/distrobox/issues/1530 and kill and run again
# # and now you are inside dev env where you run this script
# # to clean use distrobox stop zyppng and if no longer image is needed use distrobox rm zyppng
# ```

set -eu
BASEDIR=$(dirname "$0")

# Helper:
# Ensure root privileges for the installation.
# In a testing container, we are root but there is no sudo.
if [ $(id --user) != 0 ]; then
SUDO=sudo
if [ "$($SUDO id --user)" != 0 ]; then
echo "We are not root and cannot sudo, cannot continue."
exit 1
fi
else
SUDO=""
fi

$SUDO zypper --non-interactive rm rust\* || true

# install all required packages and only required as recommends are really huge
$SUDO zypper --non-interactive install --no-recommends \
git \
cmake \
openssl \
libudev1 \
libboost_headers-devel \
libboost_program_options-devel \
libboost_test-devel \
libboost_thread-devel \
dejagnu \
gcc-c++ \
gettext-devel \
graphviz \
libxml2-devel \
yaml-cpp-devel \
gobject-introspection-devel \
libproxy-devel \
pkg-config \
libsolv-devel \
libsolv-tools-base \
glib2-devel \
libsigc++2-devel \
readline-devel \
nginx \
vsftpd \
rpm \
rpm-devel \
libgpgme-devel \
FastCGI-devel \
libcurl-devel \
"rubygem(asciidoctor)" \
libzck-devel \
libzstd-devel \
libbz2-devel \
xz-devel \
rustup

cd "$BASEDIR"
# checkout submodules
git submodule init
git submodule update --checkout

# lets build libzypp
(
cd libzypp
mkdir -p build
cd build
# With /usr/local, we have to set a path: LD_LIBRARY_PATH=/usr/local/lib64 zypprs
# but the plus side is that the /usr zypper keeps working :)
#
# cmake -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_GLIB_API=ON -D DISABLE_AUTODOCS=ON ..
cmake -D BUILD_GLIB_API=ON -D DISABLE_AUTODOCS=ON ..
make -j$(nproc)
$SUDO make install
)

# now lets make rust working
rustup install stable
# lets install gir
cd gir
# workaround for badly working exclude in cargo see https://github.com/rust-lang/cargo/issues/6745
if ! grep -q '\[workspace\]' Cargo.toml; then
printf '\n[workspace]' >> Cargo.toml
fi
cargo install --path .
cd -

# to use gir follow https://gtk-rs.org/gir/book/tutorial/sys_library.html

# install doc tool
cargo install rustdoc-stripper

cargo build

echo 'To test if everything work run `../target/debug/zypprs`'
120 changes: 120 additions & 0 deletions src/auto/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files
// DO NOT EDIT

use crate::{ffi};
use glib::{prelude::*,signal::{connect_raw, SignalHandlerId},translate::*};
use std::{boxed::Box as Box_};

glib::wrapper! {
/// This class is the basic building block for the zypp glib API. It defines the path of the
/// root filesystem we are operating on. This is usually "/" but to support chroot use cases it
/// can point to any directory in a filesystem where packages should be installed into. If the rootfs
/// is not defined as "/" then zypp will install packages using chroot into the directory.
///
/// Settings for zypp are loaded from the rootfs directory and locks are also applied relative to it.
/// Meaning that one context can operate on "/" while another one can operate on "/tmp/rootfs".
///
/// \note Currently only one ZyppContext is supported until we have refactored the underlying code to support
/// having multiple of them. Mixing them atm will not work due to locks and libsolv limitations
///
/// ## Properties
///
///
/// #### `versionprop`
/// Readable
///
///
/// #### `zypp-cppObj`
/// Writeable | Construct Only
#[doc(alias = "ZyppContext")]
pub struct Context(Object<ffi::ZyppContext, ffi::ZyppContextClass>);

match fn {
type_ => || ffi::zypp_context_get_type(),
}
}

impl Context {
// rustdoc-stripper-ignore-next
/// Creates a new builder-pattern struct instance to construct [`Context`] objects.
///
/// This method returns an instance of [`ContextBuilder`](crate::builders::ContextBuilder) which can be used to create [`Context`] objects.
pub fn builder() -> ContextBuilder {
ContextBuilder::new()
}


/// Loads the system at the given sysroot, returns TRUE on success, otherwise FALSE
/// ## `sysRoot`
/// The system sysroot to load, if a nullptr is given "/" is used
#[doc(alias = "zypp_context_load_system")]
pub fn load_system(&self, sysRoot: Option<&str>) -> Result<(), glib::Error> {
unsafe {
let mut error = std::ptr::null_mut();
let is_ok = ffi::zypp_context_load_system(self.to_glib_none().0, sysRoot.to_glib_none().0, &mut error);
debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
if error.is_null() { Ok(()) } else { Err(from_glib_full(error)) }
}
}

///
/// # Returns
///
/// The context root as requested when loading the system
#[doc(alias = "zypp_context_sysroot")]
pub fn sysroot(&self) -> Option<glib::GString> {
unsafe {
from_glib_full(ffi::zypp_context_sysroot(self.to_glib_none().0))
}
}

#[doc(alias = "zypp_context_version")]
pub fn version(&self) -> Option<glib::GString> {
unsafe {
from_glib_none(ffi::zypp_context_version(self.to_glib_none().0))
}
}

pub fn versionprop(&self) -> Option<glib::GString> {
ObjectExt::property(self, "versionprop")
}

#[doc(alias = "versionprop")]
pub fn connect_versionprop_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn notify_versionprop_trampoline<F: Fn(&Context) + 'static>(this: *mut ffi::ZyppContext, _param_spec: glib::ffi::gpointer, f: glib::ffi::gpointer) {
let f: &F = &*(f as *const F);
f(&from_glib_borrow(this))
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(self.as_ptr() as *mut _, b"notify::versionprop\0".as_ptr() as *const _,
Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(notify_versionprop_trampoline::<F> as *const ())), Box_::into_raw(f))
}
}
}

// rustdoc-stripper-ignore-next
/// A [builder-pattern] type to construct [`Context`] objects.
///
/// [builder-pattern]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
#[must_use = "The builder must be built to be used"]
pub struct ContextBuilder {
builder: glib::object::ObjectBuilder<'static, Context>,
}

impl ContextBuilder {
fn new() -> Self {
Self { builder: glib::object::Object::builder() }
}

//pub fn zypp_cppObj(self, zypp_cppObj: /*Unimplemented*/Basic: Pointer) -> Self {
// Self { builder: self.builder.property("zypp-cppObj", zypp_cppObj), }
//}

// rustdoc-stripper-ignore-next
/// Build the [`Context`].
#[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
pub fn build(self) -> Context {
self.builder.build() }
}
Loading

0 comments on commit 37990ac

Please sign in to comment.