Introduce 'exclusions' parameter to scanner
This commit is contained in:
parent
4aa1948350
commit
e25e92b273
|
@ -8,5 +8,6 @@ Features:
|
||||||
* (optional) Compression using Zstd and a specifiable dictionary
|
* (optional) Compression using Zstd and a specifiable dictionary
|
||||||
* (optional) Encryption
|
* (optional) Encryption
|
||||||
* Ability to back up to remote machines over SSH
|
* Ability to back up to remote machines over SSH
|
||||||
|
* Labelling of files in a backup source; different destinations can choose to backup either all or a subset of the labels.
|
||||||
|
|
||||||
See the documentation for more information.
|
See the documentation for more information.
|
||||||
|
|
|
@ -23,7 +23,7 @@ use anyhow::{anyhow, bail};
|
||||||
use arc_interner::ArcIntern;
|
use arc_interner::ArcIntern;
|
||||||
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
|
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -151,7 +151,7 @@ pub fn backup_source_to_destination<PT: ProgressTracker>(
|
||||||
} => {
|
} => {
|
||||||
info!("Looking to backup {} to {}", source_name, dest_name);
|
info!("Looking to backup {} to {}", source_name, dest_name);
|
||||||
info!("Scanning.");
|
info!("Scanning.");
|
||||||
let tree = scan(directory, !*cross_filesystems)?
|
let tree = scan(directory, !*cross_filesystems, &BTreeSet::new())?
|
||||||
.ok_or_else(|| anyhow!("Source does not exist."))?;
|
.ok_or_else(|| anyhow!("Source does not exist."))?;
|
||||||
|
|
||||||
let absolute_source_path = desc_path.join(directory);
|
let absolute_source_path = desc_path.join(directory);
|
||||||
|
|
|
@ -15,6 +15,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with Yama. If not, see <https://www.gnu.org/licenses/>.
|
along with Yama. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
|
@ -80,7 +81,7 @@ pub fn session(path: &Path, source_name: String) -> anyhow::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Scanning source; this might take a little while...");
|
println!("Scanning source; this might take a little while...");
|
||||||
let mut dir_scan: FileTree1<Option<State>> = scan(directory, one_filesystem)?
|
let mut dir_scan: FileTree1<Option<State>> = scan(directory, one_filesystem, &BTreeSet::new())?
|
||||||
.ok_or_else(|| anyhow!("Empty source."))?
|
.ok_or_else(|| anyhow!("Empty source."))?
|
||||||
.replace_meta(&None);
|
.replace_meta(&None);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with Yama. If not, see <https://www.gnu.org/licenses/>.
|
along with Yama. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{StdinLock, Stdout, Write};
|
use std::io::{StdinLock, Stdout, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -192,7 +193,7 @@ pub fn interactive_labelling_session(path: &Path, source_name: String) -> anyhow
|
||||||
let my_hostname = get_hostname();
|
let my_hostname = get_hostname();
|
||||||
let mut dir_scan = if &my_hostname == hostname {
|
let mut dir_scan = if &my_hostname == hostname {
|
||||||
info!("Scanning source; this might take a little while...");
|
info!("Scanning source; this might take a little while...");
|
||||||
scan(directory, !*cross_filesystems)?
|
scan(directory, !*cross_filesystems, &BTreeSet::new())?
|
||||||
.ok_or_else(|| anyhow!("Empty source."))?
|
.ok_or_else(|| anyhow!("Empty source."))?
|
||||||
.replace_meta(&None)
|
.replace_meta(&None)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// This file implements the responder side of the backup source protocol -- the protocol used
|
// This file implements the responder side of the backup source protocol -- the protocol used
|
||||||
// to connect to remote backup sources.
|
// to connect to remote backup sources.
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::io::{stdin, stdout, Read, Write};
|
use std::io::{stdin, stdout, Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -43,7 +44,7 @@ pub fn introduction<R: Read, W: Write>(read: &mut R, write: &mut W) -> anyhow::R
|
||||||
pub fn scanning<R: Read, W: Write>(read: &mut R, write: &mut W) -> anyhow::Result<()> {
|
pub fn scanning<R: Read, W: Write>(read: &mut R, write: &mut W) -> anyhow::Result<()> {
|
||||||
let path: PathBuf = read_message(read)?;
|
let path: PathBuf = read_message(read)?;
|
||||||
let one_filesystem: bool = read_message(read)?;
|
let one_filesystem: bool = read_message(read)?;
|
||||||
let scan_result = scan(&path, one_filesystem)?;
|
let scan_result = scan(&path, one_filesystem, &BTreeSet::new())?;
|
||||||
write_message(write, &scan_result)?;
|
write_message(write, &scan_result)?;
|
||||||
write.flush()?;
|
write.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -15,12 +15,12 @@ You should have received a copy of the GNU General Public License
|
||||||
along with Yama. If not, see <https://www.gnu.org/licenses/>.
|
along with Yama. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs::{read_link, symlink_metadata, DirEntry, Metadata};
|
use std::fs::{read_link, symlink_metadata, DirEntry, Metadata};
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::os::unix::fs::MetadataExt;
|
use std::os::unix::fs::MetadataExt;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
|
||||||
|
@ -216,14 +216,18 @@ pub fn mtime_msec(metadata: &Metadata) -> u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan the filesystem to produce a Tree, using a default progress bar.
|
/// Scan the filesystem to produce a Tree, using a default progress bar.
|
||||||
pub fn scan(path: &Path, one_filesystem: bool) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
|
pub fn scan(
|
||||||
|
path: &Path,
|
||||||
|
one_filesystem: bool,
|
||||||
|
exclusions: &BTreeSet<PathBuf>,
|
||||||
|
) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
|
||||||
let pbar = ProgressBar::with_draw_target(0, ProgressDrawTarget::stdout_with_hz(2));
|
let pbar = ProgressBar::with_draw_target(0, ProgressDrawTarget::stdout_with_hz(2));
|
||||||
pbar.set_style(ProgressStyle::default_spinner().template("{spinner} {pos:7} {msg}"));
|
pbar.set_style(ProgressStyle::default_spinner().template("{spinner} {pos:7} {msg}"));
|
||||||
pbar.set_message("dir scan");
|
pbar.set_message("dir scan");
|
||||||
|
|
||||||
let one_filesystem = if one_filesystem { Some(None) } else { None };
|
let one_filesystem = if one_filesystem { Some(None) } else { None };
|
||||||
|
|
||||||
let result = scan_with_progress_bar(path, &pbar, one_filesystem);
|
let result = scan_with_progress_bar(path, &pbar, one_filesystem, exclusions);
|
||||||
pbar.finish_at_current_pos();
|
pbar.finish_at_current_pos();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -233,7 +237,13 @@ pub fn scan_with_progress_bar(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
progress_bar: &ProgressBar,
|
progress_bar: &ProgressBar,
|
||||||
mut one_filesystem: Option<Option<u64>>,
|
mut one_filesystem: Option<Option<u64>>,
|
||||||
|
exclusions: &BTreeSet<PathBuf>,
|
||||||
) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
|
) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
|
||||||
|
if exclusions.contains(path) {
|
||||||
|
// Don't enter excluded paths.
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
let metadata_res = symlink_metadata(path);
|
let metadata_res = symlink_metadata(path);
|
||||||
progress_bar.inc(1);
|
progress_bar.inc(1);
|
||||||
if let Err(e) = &metadata_res {
|
if let Err(e) = &metadata_res {
|
||||||
|
@ -305,7 +315,8 @@ pub fn scan_with_progress_bar(
|
||||||
|
|
||||||
for entry in dir_read? {
|
for entry in dir_read? {
|
||||||
let entry: DirEntry = entry?;
|
let entry: DirEntry = entry?;
|
||||||
let scanned = scan_with_progress_bar(&entry.path(), progress_bar, one_filesystem)?;
|
let scanned =
|
||||||
|
scan_with_progress_bar(&entry.path(), progress_bar, one_filesystem, exclusions)?;
|
||||||
if let Some(scanned) = scanned {
|
if let Some(scanned) = scanned {
|
||||||
if let Ok(filename) = entry.file_name().into_string() {
|
if let Ok(filename) = entry.file_name().into_string() {
|
||||||
children.insert(filename, scanned);
|
children.insert(filename, scanned);
|
||||||
|
|
Loading…
Reference in New Issue