1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
//! # ReBackup program //! //! ReBackup is a simple backup program that doesn't actually create backups //! but instead creates a list of files to backup from a source directory. //! //! It uses a walker to traverse filesystem items, which can be customized through rules (see [`WalkerRule`]). //! //! Its main features are: //! //! * Fast recursive directory traversing //! * Powerful rules system to include, exclude or remap items //! * Handling of symbolic links (requires to enable an option for the walker) //! * Detection of already visited paths //! * Command-line interface //! //! ReBackup can be used either: //! //! * As a library (see [`walk`](walker::walk)) //! * As a standalone binary with the `cli` feature //! //! ## Library usage //! //! ReBackup only exports one single function which is the Walker: [`walk`](walker::walk). //! //! It can be used like this: //! //! ```no_run //! use std::path::PathBuf; //! use rebackup::{fail, walk, WalkerConfig}; //! //! let source = std::env::args().nth(1) //! .unwrap_or_else(|| fail!(exit 1, "Please provide a source directory")); //! //! // NOTE: This can be shortened to `WalkerConfig::new(vec![])` //! // (expanded here for explanations purpose) //! let config = WalkerConfig { //! rules: vec![], //! follow_symlinks: false, //! drop_empty_dirs: false, //! }; //! //! let files_list = walk(&PathBuf::from(source), &config) //! .unwrap_or_else(|err| fail!(exit 2, "Failed to build the files list: {}", err)); //! //! let files_list_str: Vec<_> = files_list //! .iter() //! .map(|item| item.to_string_lossy()) //! .collect(); //! //! println!("{}", files_list_str.join("\n")); //! ``` //! //! ### Rules //! //! You can use powerful rules to configure how the walker behaves. //! //! A rule is defined using [`WalkerRule`](config::WalkerRule), and uses two callbacks: //! //! * One to determine if the rule applies on a specific item //! * One to run the rule itself //! //! Here is a basic rule excluding all directories containing `.nomedia` files: //! //! ``` //! use rebackup::config::*; //! //! let rule = WalkerRule { //! // Name of the rule //! name: "nomedia", //! //! // Optional description of the rule //! description: None, //! //! // The type of items the rule applies to (`None` for all) //! only_for: Some(WalkerItemType::Directory), //! //! // Check if the rule would match a specific item //! matches: Box::new(|path, _, _| path.join(".nomedia").is_file()), //! //! // Apply the rule to determine what to do //! action: Box::new(|_, _, _| Ok(WalkerRuleResult::ExcludeItem)), //! }; //! ``` //! //! You can also build more powerful rules, like excluding files ignored by Git: //! //! ``` //! use std::env; //! use std::process::Command; //! use rebackup::config::*; //! //! let rule = WalkerRule { //! name: "gitignore", //! description: None, //! only_for: None, //! matches: Box::new(|path, _, _| path.ancestors().any(|path| path.join(".git").is_dir())), //! action: Box::new(|dir, _, _| { //! let cwd = env::current_dir()?; //! //! if dir.is_dir() { //! env::set_current_dir(dir)?; //! } else if let Some(parent) = dir.parent() { //! env::set_current_dir(parent)?; //! } //! //! let is_excluded = Command::new("git") //! .arg("check-ignore") //! .arg(dir.to_string_lossy().to_string()) //! .output(); //! //! // Restore the current directory before returning eventual error from the command //! env::set_current_dir(cwd)?; //! //! if is_excluded?.status.success() { //! Ok(WalkerRuleResult::ExcludeItem) //! } else { //! Ok(WalkerRuleResult::IncludeItem) //! } //! }), //! }; //! ``` //! //! You can check more examples of rules in `examples/rules.rs`. //! //! ## Command-line usage //! //! ```shell //! # Build the list of files to backup, and pipe it to 'tar' //! # to create a compressed archive //! # Be aware of not creating the archive inside the directory to backup, or the archive //! # will be listed as well (you can still exclude it from the results afterwards) //! rebackup path_to_backup/ | tar -czf output.tgz -T - //! //! # If you are in another directory, ask for absolute paths instead //! # Please note that the archive's content will have absolute paths as well //! rebackup path_to_backup/ -a | tar -czf output.tgz -T - //! //! # Using filters to exclude items based on patterns //! # Here we're excluding all items ignored by the '.gitignore' file in Git repositories //! rebackup path_to_backup/ -f '! git check-ignore "$REBACKUP_ITEM"' //! //! # To also exclude the ".git" folder (using glob pattern): //! rebackup path_to_backup/ -f '! git check-ignore "$REBACKUP_ITEM"' -e '**/.git' //! //! # Use an alternate shell: //! rebackup path_to_backup/ -f '! git check-ignore "$REBACKUP_ITEM"' --shell zsh --shell-head-args=-c //! //! # To list all available arguments: //! rebackup --help //! ``` #![forbid(unsafe_code)] #![forbid(unused_must_use)] #[macro_use] pub mod logger; pub mod config; pub mod walker; pub use config::*; pub use logger::*; pub use walker::*; // Re-export used crates pub use atomic; pub use lazy_static; pub use thiserror; // Re-export crates used by the CLI #[cfg(feature = "cli")] pub use clap; #[cfg(feature = "cli")] pub use glob;