diff --git a/Makefile b/Makefile index 57e0ca9..9bd934a 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ TEST_RULES=test/rules TEST_DOTFILES=test/dotfiles TEST_DEST_DIR=test/dest TEST_EXPECTED_DIR=test/expected +TEST_IGNORE_ARG=--ignore ignored_file DIFF_FLAGS=-qNr @@ -26,7 +27,7 @@ $(EXECFILE): release test: $(EXECFILE) rm -rf $(TEST_DEST_DIR) mkdir $(TEST_DEST_DIR) - ./$(EXECFILE) $(TEST_RULES) $(TEST_DOTFILES) $(TEST_DEST_DIR); \ + ./$(EXECFILE) $(TEST_RULES) $(TEST_DOTFILES) $(TEST_DEST_DIR) $(TEST_IGNORE_ARG); \ diff $(DIFF_FLAGS) $(TEST_DEST_DIR) $(TEST_EXPECTED_DIR) if [ ! -x "$(TEST_DEST_DIR)/binary_file" ]; then \ @echo "Expected binary_file to be executable."; \ diff --git a/README.md b/README.md index 4a1650d..6319fca 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,11 @@ dot-templater --diff CONFIG SRC_DIR DEST_DIR Compares files from `SRC_DIR` modified according to rules in `CONFIG` against the contents of `DEST_DIR`. +### Parameters +* `-i [...files]` or `--ignore [...files]` + Excludes a file or directory (and all children) from templating, ie. they will not be copied to the destination directory. + For example, use `-i .git` for git controlled dotfile repositories. + ### Config Format Any line beginning with `#` is ignored. Config file can contain key/value substitutions and feature flags. diff --git a/src/lib.rs b/src/lib.rs index e3122be..97940fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,6 +144,7 @@ pub struct Arguments<'a> { pub source: &'a str, pub dest: &'a str, pub diff: Mode, + pub ignore: Vec<&'a str>, } impl<'a> Arguments<'a> { @@ -159,12 +160,17 @@ impl<'a> Arguments<'a> { source = Self::trim_trailing_slash(&source); dest = Self::trim_trailing_slash(&dest); + let ignore = match args.values_of("ignore") { + Some(value) => value.collect(), + None => vec![], + }; Self { rules, source, dest, diff, + ignore, } } @@ -236,8 +242,13 @@ pub fn template( source_dir: &str, dest_dir: &str, mode: Mode, + ignore: Vec<&str>, ) -> Result<(), Box> { - for entry in WalkDir::new(source_dir) { + for entry in WalkDir::new(source_dir).into_iter().filter_entry(|entry| { + let ignore_list: Vec<&Path> = ignore.iter().map(|fname| Path::new(fname)).collect(); + + !ignore_list.contains(&entry.path().strip_prefix(&source_dir).unwrap()) + }) { let source_file = entry?; let source_file = source_file.path(); let dest_file = source_file.to_str().unwrap().replace(source_dir, dest_dir); diff --git a/src/main.rs b/src/main.rs index 45eca13..1902982 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,15 @@ fn main() { .long("diff") .help("Diff mode"), ) + .arg( + Arg::with_name("ignore") + .short("i") + .long("ignore") + .help("Ignore file") + .multiple(true) + .min_values(0) + .takes_value(true), + ) .after_help(concat!( "Copy files from SRC_DIR to DEST_DIR using rules defined in CONFIG.\n\n", "Rules configuration:\n", @@ -65,8 +74,9 @@ fn main() { process::exit(1); }); - dot_templater::template(&config, &args.source, &args.dest, args.diff).unwrap_or_else(|err| { - eprintln!("Error while performing templating: {}", err); - process::exit(1); - }); + dot_templater::template(&config, &args.source, &args.dest, args.diff, args.ignore) + .unwrap_or_else(|err| { + eprintln!("Error while performing templating: {}", err); + process::exit(1); + }); } diff --git a/test/dotfiles/ignored_file b/test/dotfiles/ignored_file new file mode 100644 index 0000000..c439d50 --- /dev/null +++ b/test/dotfiles/ignored_file @@ -0,0 +1 @@ +I am ignored \ No newline at end of file