From a9e3bc7e13eecabf5494367d440aaa9ee2df5af0 Mon Sep 17 00:00:00 2001 From: Alexis Mousset Date: Sat, 21 Dec 2024 17:28:43 +0100 Subject: [PATCH] Add a touch method (#22) --- raugeas/src/lib.rs | 37 ++++++++++++++++++++++++++++++++++++- raugeas/src/util.rs | 2 +- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/raugeas/src/lib.rs b/raugeas/src/lib.rs index c06338c..99d8db8 100644 --- a/raugeas/src/lib.rs +++ b/raugeas/src/lib.rs @@ -10,11 +10,17 @@ //! The main differences with the C API are: //! //! * Add `clear` and `clearm` methods clear values (instead of passing an `Option` to `set`/`setm`). +//! * Add `touch` method to create a node if it does not exist. //! * Use a `Span` struct to represent the span of a node in a file. //! * Use a `Position` enum to indicate where to insert a new node. //! * Use an `Attr` struct to represent the attributes of a node. //! * Use a `SaveMode` enum to indicate how to save changes. //! +//! The main references: +//! +//! * https://github.com/hercules-team/augeas/blob/master/src/augeas.h +//! * https://github.com/hercules-team/ruby-augeas/tree/master/lib +//! //! ## Usage //! //! In `Cargo.toml`: @@ -542,6 +548,20 @@ impl Augeas { Ok(()) } + /// Create the `path` with empty value if it doesn't exist. + pub fn touch>(&mut self, path: T) -> Result<()> { + let path = path.as_ref(); + let path_c = CString::new(path.as_bytes())?; + + let no_matches = self.matches_os(path)?.is_empty(); + if no_matches { + unsafe { aug_set(self.ptr, path_c.as_ptr(), ptr::null()) }; + } + self.check_error()?; + + Ok(()) + } + /// Insert a new node: find the node matching `path` and create a new /// sibling for it with the given `label`. The sibling is created /// before or after the node `path`, depending on the value of `pos`. @@ -1452,13 +1472,28 @@ mod tests { } #[test] - fn set_clear() { + fn clear_test() { let mut aug = Augeas::init(Some("tests/test_root"), "", Flags::NONE).unwrap(); aug.clear("etc/passwd/root/uid").unwrap(); let uid = aug.get("etc/passwd/root/uid").unwrap(); assert_eq!(None, uid); } + #[test] + fn touch_test() { + let mut aug = Augeas::init(Some("tests/test_root"), "", Flags::NONE).unwrap(); + let exists = aug.matches("etc/passwd/epicaste/uid").unwrap(); + assert_eq!(exists.len(), 0); + // Creates missing nodes. + aug.touch("etc/passwd/epicaste/uid").unwrap(); + let exists = aug.matches("etc/passwd/epicaste/uid").unwrap(); + assert_eq!(exists.len(), 1); + // Does not overwrite existing nodes. + aug.touch("etc/passwd/root/uid").unwrap(); + let uid = aug.get("etc/passwd/root/uid").unwrap().unwrap(); + assert_eq!("0", uid); + } + #[test] fn get_nonutf8_test() { let invalid: &[u8; 2] = &[0xc3, 0x28]; diff --git a/raugeas/src/util.rs b/raugeas/src/util.rs index 5556f5d..40a42eb 100644 --- a/raugeas/src/util.rs +++ b/raugeas/src/util.rs @@ -109,7 +109,7 @@ mod tests { let hello = "Hello, World!"; let s = CString::new(hello).unwrap(); - libc::fprintf(file, s.as_ptr() as *const i8); + libc::fprintf(file, s.as_ptr()); let res = read_memstream(&mut buf, &mut size, file).unwrap(); assert_eq!(res, hello);