Skip to content

Commit

Permalink
feat: add file symlink atom (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
rawkode committed May 13, 2021
1 parent c0aad0c commit 35c7e27
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ fmt:
deny:
cargo install --locked cargo-deny
cargo deny check

test:
cargo test -- --nocapture --color=always
112 changes: 112 additions & 0 deletions src/atoms/file/link.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use super::super::Atom;
use super::FileAtom;
use std::path::PathBuf;
use tracing::{debug, error, warn};

pub struct FileLink {
from: PathBuf,
to: PathBuf,
}

impl FileAtom for FileLink {
fn get_path(&self) -> &PathBuf {
&self.from
}
}

impl std::fmt::Display for FileLink {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"The file {} contents needs to be linked from {}",
self.to.to_str().unwrap(),
self.from.to_str().unwrap(),
)
}
}

impl Atom for FileLink {
fn plan(&self) -> bool {
// First, ensure self.to exists and can be linked to
if !self.to.exists() {
error!(
"Cannot plan: file to link to is missing: {}",
self.to.to_str().unwrap()
);
return false;
}

// File doesn't exist, we can run safely
if !self.from.exists() {
return true;
}

// File exists, lets check if it's a symlink which can be safely updated
// or return a false and emit some logging that we can't create the link
// without purging a file
let link = match std::fs::read_link(&self.from) {
Ok(link) => link,
Err(err) => {
warn!(
"Cannot plan: file to link from already exists and isn't a link: {}",
self.from.to_str().unwrap()
);
debug!("Cannot plan: {}", err);
return false;
}
};

// If this file doesn't link to what we expect, lets make it so
!link.eq(&self.to)
}

#[cfg(unix)]
fn execute(&self) -> anyhow::Result<()> {
std::os::unix::fs::symlink(&self.to, &self.from)?;

Ok(())
}

#[cfg(windows)]
fn execute(&self) -> anyhow::Result<()> {
if self.to.is_dir() {
std::os::windows::fs::symlink_dir(&self.to, &self.from)?;
} else {
std::os::windows::fs::symlink_file(&self.to, &self.from)?;
}
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_can() {
let from_dir = match tempfile::tempdir() {
Ok(dir) => dir,
Err(_) => {
assert_eq!(false, true);
return;
}
};

let to_file = match tempfile::NamedTempFile::new() {
std::result::Result::Ok(file) => file,
std::result::Result::Err(_) => {
assert_eq!(false, true);
return;
}
};

let atom = FileLink {
from: from_dir.path().join("symlink"),
to: to_file.path().to_path_buf(),
};

assert_eq!(true, atom.plan());
assert_eq!(true, atom.execute().is_ok());
assert_eq!(false, atom.plan());
}
}
1 change: 1 addition & 0 deletions src/atoms/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod chown;
mod contents;
mod copy;
mod create;
mod link;

use super::Atom;

Expand Down

0 comments on commit 35c7e27

Please sign in to comment.