From a4adb124d0c4b28b1256f09f8b28e66a4a71d83d Mon Sep 17 00:00:00 2001
From: Ian Douglas Scott <ian@iandouglasscott.com>
Date: Mon, 21 Aug 2017 13:24:36 -0700
Subject: [PATCH] Support adding symlinks in configuration

I'm not sure if this is the best syntax...
---
 src/config/file.rs |  4 +++-
 src/install.rs     | 20 ++++++++++++++------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/config/file.rs b/src/config/file.rs
index 0b34aeb..86b491e 100644
--- a/src/config/file.rs
+++ b/src/config/file.rs
@@ -1,5 +1,7 @@
 #[derive(Debug, Default, Deserialize)]
 pub struct FileConfig {
     pub path: String,
-    pub data: String
+    pub data: String,
+    #[serde(default)]
+    pub symlink: bool
 }
diff --git a/src/install.rs b/src/install.rs
index 897eab0..a17eb66 100644
--- a/src/install.rs
+++ b/src/install.rs
@@ -12,6 +12,9 @@ use std::{env, fs};
 use std::io::{self, stderr, Write};
 use std::str::FromStr;
 use std::process::{self, Command};
+use std::os::unix::fs::symlink;
+use std::os::unix::ffi::OsStrExt;
+use std::ffi::OsStr;
 
 use config::Config;
 
@@ -134,16 +137,21 @@ pub fn install(config: Config, cookbook: Option<&str>) -> Result<(), String> {
     }
 
     macro_rules! file {
-        ($path:expr, $data:expr) => {{
+        ($path:expr, $data:expr, $symlink:expr) => {{
             let mut path = sysroot.clone();
             path.push($path);
             if let Some(parent) = path.parent() {
                 println!("Create file parent {}", parent.display());
                 fs::create_dir_all(parent).map_err(|err| format!("failed to create file parent {}: {}", parent.display(), err))?;
             }
-            println!("Create file {}", path.display());
-            let mut file = fs::File::create(&path).map_err(|err| format!("failed to create {}: {}", path.display(), err))?;
-            file.write_all($data).map_err(|err| format!("failed to write {}: {}", path.display(), err))?;
+            if $symlink {
+                println!("Create symlink {}", path.display());
+                symlink(&OsStr::from_bytes($data), &path).map_err(|err| format!("failed to symlink {}: {}", path.display(), err))?;
+            } else {
+                println!("Create file {}", path.display());
+                let mut file = fs::File::create(&path).map_err(|err| format!("failed to create {}: {}", path.display(), err))?;
+                file.write_all($data).map_err(|err| format!("failed to write {}: {}", path.display(), err))?;
+            }
         }};
     }
 
@@ -152,7 +160,7 @@ pub fn install(config: Config, cookbook: Option<&str>) -> Result<(), String> {
     install_packages(&config, sysroot.to_str().unwrap(), cookbook);
 
     for file in config.files {
-        file!(file.path.trim_matches('/'), file.data.as_bytes());
+        file!(file.path.trim_matches('/'), file.data.as_bytes(), file.symlink);
     }
 
     let mut passwd = String::new();
@@ -191,7 +199,7 @@ pub fn install(config: Config, cookbook: Option<&str>) -> Result<(), String> {
         passwd.push_str(&format!("{};{};{};{};{};{};{}\n", username, password, uid, gid, name, home, shell));
     }
     if ! passwd.is_empty() {
-        file!("etc/passwd", passwd.as_bytes());
+        file!("etc/passwd", passwd.as_bytes(), false);
     }
 
     Ok(())
-- 
GitLab