kornelski / cargo-deb

Make Debian packages directly from Rust/Cargo projects
https://lib.rs/cargo-deb
MIT License
432 stars 52 forks source link

`postinst` uses wrong filename for tmpfiles #143

Open bbx0 opened 1 month ago

bbx0 commented 1 month ago

Thanks for maintaining cargo-deb, it's really handy!

Looks like the postinst script is generated with the source name myunit.tmpfile instead of the target name myunit.conf. This causes a silent failure during install and no tmpfiles will be created. Manually running sudo systemd-tmpfiles --create myunit.conf does create the tmpfiles after install.

The snipped was generated by cargo-deb version 2.7.0.

# Cargo.toml
systemd-units = { enable = false, start = false, restart-after-upgrade = false, stop-on-upgrade = false, unit-scripts = "assets/systemd" }
# postinst
    if [ -d /run/systemd/system ] ; then
        systemd-tmpfiles --create myunit.tmpfile >/dev/null || true
    fi

I made a quick fix, which resolves the issue. Unfortunately I'm not clear why source.path() is used here instead of the target_path. I'm happy to open a PR with the patch, but probably there is more to it for a clean fix.

diff --git a/src/dh/dh_installsystemd.rs b/src/dh/dh_installsystemd.rs
index 879d5b3..6715269 100644
--- a/src/dh/dh_installsystemd.rs
+++ b/src/dh/dh_installsystemd.rs
@@ -224,10 +224,12 @@ pub fn generate(package: &str, assets: &[Asset], options: &Options, listener: &d

     // add postinst code blocks to handle tmpfiles
     // see: https://salsa.debian.org/debian/debhelper/-/blob/master/dh_installsystemd#L305
+    // tmpfiles are installed with .conf as extension
+    // see: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
     let tmp_file_names = assets
         .iter()
         .filter(|a| a.c.target_path.starts_with(USR_LIB_TMPFILES_D_DIR))
-        .map(|v| fname_from_path(v.source.path().unwrap()))
+        .map(|v| fname_from_path(v.source.path().unwrap().with_extension("conf").as_path()))
         .collect::<Vec<String>>()
         .join(" ");

@@ -604,7 +606,7 @@ mod tests {
     fn generate_with_empty_tmp_file_asset() {
         use crate::dh::dh_lib::get_embedded_autoscript;

-        const TMP_FILE_NAME: &str = "my_tmp_file";
+        const TMP_FILE_NAME: &str = "my_tmp_file.tmpfile";
         let tmp_file_path = PathBuf::from(format!("debian/{TMP_FILE_NAME}"));

         let mut mock_listener = crate::listener::MockListener::new();
@@ -644,7 +646,7 @@ mod tests {

         // Check that the autoscript fragment lines were properly copied
         // into the created script complete with expected substitutions
-        let expected_autoscript_text = autoscript_text.replace("#TMPFILES#", TMP_FILE_NAME);
+        let expected_autoscript_text = autoscript_text.replace("#TMPFILES#", TMP_FILE_NAME.replace(".tmpfile", ".conf").as_str());
         let expected_autoscript_text = expected_autoscript_text.trim_end();
         let start1 = 1;
         let end1 = start1 + autoscript_line_count;