aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.rs44
-rw-r--r--src/main.rs57
2 files changed, 101 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..6fd790a
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,44 @@
+use std::env;
+use std::path::PathBuf;
+use serde::Deserialize;
+
+#[derive(Deserialize, Debug)]
+pub struct Config {
+ #[serde(default = "default_dots_dir")]
+ pub dots_dir: PathBuf,
+ #[serde(rename = "dot")]
+ pub dots: Vec<Dot>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Dot {
+ #[serde(rename = "src")]
+ pub source: PathBuf,
+ #[serde(rename = "dest")]
+ pub destination: PathBuf,
+}
+
+pub enum ConfigLoadError {
+ IOError(std::io::Error),
+ DeserializationError(toml::de::Error),
+}
+
+impl Config {
+ pub fn load(from: Option<PathBuf>) -> Result<Config, ConfigLoadError> {
+ let path = from.unwrap_or(PathBuf::from("dots.toml"));
+ match std::fs::read_to_string(path).map_err(ConfigLoadError::IOError) {
+ Ok(string) => match toml::from_str(&string) {
+ Ok(config) => Ok(config),
+ Err(err) => Err(ConfigLoadError::DeserializationError(err)),
+ }
+ Err(e) => {
+ Err(e)
+ }
+ }
+ }
+}
+
+fn default_dots_dir() -> PathBuf {
+ env::current_dir().expect("failed to get current dir")
+}
+
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..151ee8a
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,57 @@
+use std::env;
+use std::os::unix::fs::symlink;
+use std::path::PathBuf;
+use std::process::exit;
+use dirs::{home_dir};
+use crate::config::{Config, ConfigLoadError, Dot};
+
+mod config;
+
+fn main() {
+ let args = env::args().skip(1).collect::<Vec<String>>();
+
+ if args.len() > 1 {
+ eprintln!("usage: {} [config]", args[0]);
+ exit(1);
+ }
+
+ if args.len() == 1 && (args[0] == "-h" || args[0] == "--help") {
+ println!("Usage: {} [config]", args[0]);
+ println!("options:");
+ println!(" -h, --help Print help information");
+ println!("By default, dots will look for a bummsdots.toml file in the current directory");
+ println!("This can be changed by passing the filename");
+ exit(0);
+ }
+
+ let config = Config::load(args.get(0).map(|o| PathBuf::from(o))).map_err(|err|
+ match err {
+ ConfigLoadError::IOError(err) => {
+ eprintln!("failed to load config file: {}", err);
+ exit(1)
+ }
+ ConfigLoadError::DeserializationError(err) => {
+ eprintln!("failed to deserialize config file: {}", err);
+ exit(1)
+ }
+ }
+ ).unwrap();
+
+ let prepended_mappings = config.dots.iter().map(|m|
+ Dot {
+ source: env::current_dir().expect("failed to get current dir").join(&m.source),
+ destination: prepend_user_dir(&m.destination)
+ }
+ );
+
+ for dot in prepended_mappings {
+ println!("linking from {} to {}", dot.source.display(), dot.destination.display());
+ let _ = symlink(&dot.source, &dot.destination).map_err(|err|
+ eprintln!("failed to symlink: {}", err.to_string())
+ );
+ }
+}
+
+fn prepend_user_dir(path: &PathBuf) -> PathBuf {
+ home_dir().unwrap().join(path)
+} \ No newline at end of file