Add a `cap-std-apis` feature with open/create
I'm trying to make more use of `cap-std` in our stack, and this will be a key enabling API. Actually a notable side benefit of this is that we don't need to teach the ostree C code itself to use `openat2`, we inherit cap-std's setup. All of the internal ostree code using the prior `openat()` should continue to work. I only did basic sanity checking of this; there may be bugs in other APIs.
This commit is contained in:
parent
4f7eea6aa7
commit
6940896c4e
|
|
@ -29,6 +29,8 @@ members = [".", "sys"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.2.1"
|
bitflags = "1.2.1"
|
||||||
|
cap-std = { version = "0.24", optional = true}
|
||||||
|
io-lifetimes = { version = "0.5", optional = true}
|
||||||
ffi = { package = "ostree-sys", path = "sys", version = "0.9.1" }
|
ffi = { package = "ostree-sys", path = "sys", version = "0.9.1" }
|
||||||
gio = "0.14"
|
gio = "0.14"
|
||||||
glib = "0.14.4"
|
glib = "0.14.4"
|
||||||
|
|
@ -42,8 +44,10 @@ thiserror = "1.0.20"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
openat = "0.1.19"
|
openat = "0.1.19"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
cap-tempfile = "0.24"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
cap-std-apis = ["cap-std", "io-lifetimes", "v2017_10"]
|
||||||
dox = ["ffi/dox"]
|
dox = ["ffi/dox"]
|
||||||
v2014_9 = ["ffi/v2014_9"]
|
v2014_9 = ["ffi/v2014_9"]
|
||||||
v2015_7 = ["v2014_9", "ffi/v2015_7"]
|
v2015_7 = ["v2014_9", "ffi/v2015_7"]
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
// Re-export our dependencies. See https://gtk-rs.org/blog/2021/06/22/new-release.html
|
// Re-export our dependencies. See https://gtk-rs.org/blog/2021/06/22/new-release.html
|
||||||
// "Dependencies are re-exported". Users will need e.g. `gio::File`, so this avoids
|
// "Dependencies are re-exported". Users will need e.g. `gio::File`, so this avoids
|
||||||
// them needing to update matching versions.
|
// them needing to update matching versions.
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
pub use cap_std;
|
||||||
pub use ffi;
|
pub use ffi;
|
||||||
pub use gio;
|
pub use gio;
|
||||||
pub use glib;
|
pub use glib;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#[cfg(any(feature = "v2016_4", feature = "dox"))]
|
#[cfg(any(feature = "v2016_4", feature = "dox"))]
|
||||||
use crate::RepoListRefsExtFlags;
|
use crate::RepoListRefsExtFlags;
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
use crate::RepoMode;
|
||||||
use crate::{Checksum, ObjectDetails, ObjectName, ObjectType, Repo, RepoTransactionStats};
|
use crate::{Checksum, ObjectDetails, ObjectName, ObjectType, Repo, RepoTransactionStats};
|
||||||
use ffi::OstreeRepoListObjectsFlags;
|
use ffi::OstreeRepoListObjectsFlags;
|
||||||
use glib::ffi as glib_sys;
|
use glib::ffi as glib_sys;
|
||||||
|
|
@ -97,6 +99,26 @@ impl Repo {
|
||||||
Repo::new(&gio::File::for_path(path.as_ref()))
|
Repo::new(&gio::File::for_path(path.as_ref()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
/// A version of [`open_at`] which uses cap-std.
|
||||||
|
pub fn open_at_dir(dir: &cap_std::fs::Dir, path: &str) -> Result<Repo, glib::Error> {
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
crate::Repo::open_at(dir.as_raw_fd(), path, gio::NONE_CANCELLABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
/// A version of [`create_at`] which uses cap-std, and also returns the opened repo.
|
||||||
|
pub fn create_at_dir(
|
||||||
|
dir: &cap_std::fs::Dir,
|
||||||
|
path: &str,
|
||||||
|
mode: RepoMode,
|
||||||
|
options: Option<&glib::Variant>,
|
||||||
|
) -> Result<Repo, glib::Error> {
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
crate::Repo::create_at(dir.as_raw_fd(), path, mode, options, gio::NONE_CANCELLABLE)?;
|
||||||
|
Repo::open_at_dir(dir, path)
|
||||||
|
}
|
||||||
|
|
||||||
/// A wrapper for [`prepare_transaction`] which ensures the transaction will be aborted when the guard goes out of scope.
|
/// A wrapper for [`prepare_transaction`] which ensures the transaction will be aborted when the guard goes out of scope.
|
||||||
pub fn auto_transaction<P: IsA<gio::Cancellable>>(
|
pub fn auto_transaction<P: IsA<gio::Cancellable>>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,26 @@ fn should_commit_content_to_repo_and_list_refs_again() {
|
||||||
assert_eq!(checksum, refs["test"]);
|
assert_eq!(checksum, refs["test"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
fn cap_std_commit() {
|
||||||
|
let test_repo = CapTestRepo::new();
|
||||||
|
|
||||||
|
assert!(test_repo.repo.require_rev("nosuchrev").is_err());
|
||||||
|
|
||||||
|
let mtree = create_mtree(&test_repo.repo);
|
||||||
|
let checksum = commit(&test_repo.repo, &mtree, "test");
|
||||||
|
|
||||||
|
assert_eq!(test_repo.repo.require_rev("test").unwrap(), checksum);
|
||||||
|
|
||||||
|
let repo2 = ostree::Repo::open_at_dir(&test_repo.dir, ".").unwrap();
|
||||||
|
let refs = repo2
|
||||||
|
.list_refs(None, NONE_CANCELLABLE)
|
||||||
|
.expect("failed to list refs");
|
||||||
|
assert_eq!(1, refs.len());
|
||||||
|
assert_eq!(checksum, refs["test"]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn repo_traverse_and_read() {
|
fn repo_traverse_and_read() {
|
||||||
let test_repo = TestRepo::new();
|
let test_repo = TestRepo::new();
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,26 @@ impl TestRepo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
pub struct CapTestRepo {
|
||||||
|
pub dir: cap_tempfile::TempDir,
|
||||||
|
pub repo: ostree::Repo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cap-std-apis")]
|
||||||
|
impl CapTestRepo {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::new_with_mode(ostree::RepoMode::Archive)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_mode(repo_mode: ostree::RepoMode) -> Self {
|
||||||
|
let dir = cap_tempfile::tempdir(cap_std::ambient_authority()).unwrap();
|
||||||
|
let repo = ostree::Repo::create_at_dir(&dir, ".", repo_mode, None).expect("repo create");
|
||||||
|
Self { dir, repo }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_mtree(repo: &ostree::Repo) -> ostree::MutableTree {
|
pub fn create_mtree(repo: &ostree::Repo) -> ostree::MutableTree {
|
||||||
let mtree = ostree::MutableTree::new();
|
let mtree = ostree::MutableTree::new();
|
||||||
let file = gio::File::for_path(
|
let file = gio::File::for_path(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue