diff --git a/nixide/src/store/path.rs b/nixide/src/store/path.rs index 5eed4fd..417d2f4 100644 --- a/nixide/src/store/path.rs +++ b/nixide/src/store/path.rs @@ -147,4 +147,66 @@ impl StorePath { }) .is_ok() } + + /// Gets the closure of a specific store path + /// + /// The callback borrows each StorePath only for the duration of the call. + /// + /// # Arguments + /// + /// * flip - If false, compute the forward closure (paths referenced by any store path in the closure). + /// If true, compute the backward closure (paths that reference any store path in the closure). + /// * include_outputs - If flip_direction is false: for any derivation in the closure, include its outputs. + /// If flip_direction is true: for any output in the closure, include derivations that produce it. + /// * include_derivers - If flip_direction is false: for any output in the closure, include the derivation that + /// produced it. + /// If flip_direction is true: for any derivation in the closure, include its outputs. + /// * user_callback - The function to call for every store path, in no particular order + /// + pub fn with_closure( + &self, + flip: bool, + include_outputs: bool, + include_derivers: bool, + user_callback: fn(&StorePath), + ) -> NixideResult<()> { + wrap::nix_callback!( + |context: *mut sys::NixCContext, + ; userdata: (Rc>, fn(&StorePath)); + store_path: *const sys::StorePath, + | -> () { + let callback: fn(&StorePath) = unsafe { (*userdata).inner.1 }; + let store = unsafe { (*userdata).inner.0.clone() }; + + let path = &StorePath { + inner: NonNull::new(unsafe { store.borrow().as_ptr() } as *mut sys::StorePath).unwrap(), + store, + }; + + callback(&path); + }, + |callback, + state: *mut __UserData, + ctx: &ErrorContext| unsafe { + // register userdata + // WARNING: Using `write` instead of assignment via `=` + // WARNING: to not call `drop` on the old, uninitialized value. + (&raw mut (*state).inner).write((self.store.clone(), user_callback)); + + sys::nix_store_get_fs_closure( + ctx.as_ptr(), + self.store.borrow().as_ptr(), + self.as_ptr(), + flip, + include_outputs, + include_derivers, + (*state).inner_ptr() as *mut c_void, + Some(callback)); + } + ) + } + + // XXX: TODO: nix 2.34.4 adds a LOT here (ie especially around derivations) + // XXX: TODO: it also removes nix_store_path* functions (ie nix_store_path_free)? + // XXX: TODO: why?? try and research this, maybe they didn't mean to?? }