Only scan one filesystem by default (can configure 'cross_filesystems' if needed)
ci/woodpecker/push/build Pipeline was successful Details
ci/woodpecker/push/release Pipeline was successful Details

This commit is contained in:
Olivier 'reivilibre' 2022-05-31 09:39:25 +01:00
parent e8fc448ace
commit af553d1fed
8 changed files with 52 additions and 19 deletions

View File

@ -195,10 +195,10 @@ fn main() -> anyhow::Result<()> {
unimplemented!();
}
DatmanCommand::InteractiveLabelling { source_name } => {
interactive_labelling_session(Path::new("."), source_name).unwrap();
interactive_labelling_session(Path::new("."), source_name)?;
}
DatmanCommand::InteractiveBrowsing { source_name } => {
datman::commands::ibrowse::session(Path::new("."), source_name).unwrap();
datman::commands::ibrowse::session(Path::new("."), source_name)?;
}
DatmanCommand::BackupOne {
source_name,
@ -317,7 +317,7 @@ fn main() -> anyhow::Result<()> {
let descriptor = load_descriptor(Path::new(".")).unwrap();
let destination = &descriptor.piles[&pile_name];
let report = datman::commands::report::generate_report(destination, &descriptor)?;
datman::commands::report::print_report(&report)?;
datman::commands::report::print_filesystem_space(&destination.path)?;
}

View File

@ -147,10 +147,12 @@ pub fn backup_source_to_destination<PT: ProgressTracker>(
SourceDescriptor::DirectorySource {
hostname: _,
directory,
cross_filesystems,
} => {
info!("Looking to backup {} to {}", source_name, dest_name);
info!("Scanning.");
let tree = scan(directory)?.ok_or_else(|| anyhow!("Source does not exist."))?;
let tree = scan(directory, !*cross_filesystems)?
.ok_or_else(|| anyhow!("Source does not exist."))?;
let absolute_source_path = desc_path.join(directory);
let absolute_dest_path = desc_path.join(&dest.path);

View File

@ -68,15 +68,19 @@ pub fn session(path: &Path, source_name: String) -> anyhow::Result<()> {
.get(&source_name)
.ok_or_else(|| anyhow!("Could not find source {:?}!", source_name))?;
let directory = match source_descriptor {
SourceDescriptor::DirectorySource { directory, .. } => directory,
let (directory, one_filesystem) = match source_descriptor {
SourceDescriptor::DirectorySource {
directory,
cross_filesystems,
..
} => (directory, !*cross_filesystems),
SourceDescriptor::VirtualSource { .. } => {
bail!("Cannot browse virtual source.");
}
};
println!("Scanning source; this might take a little while...");
let mut dir_scan: FileTree1<Option<State>> = scan(directory)?
let mut dir_scan: FileTree1<Option<State>> = scan(directory, one_filesystem)?
.ok_or_else(|| anyhow!("Empty source."))?
.replace_meta(&None);

View File

@ -186,12 +186,13 @@ pub fn interactive_labelling_session(path: &Path, source_name: String) -> anyhow
if let SourceDescriptor::DirectorySource {
hostname,
directory,
cross_filesystems,
} = source
{
let my_hostname = get_hostname();
let mut dir_scan = if &my_hostname == hostname {
info!("Scanning source; this might take a little while...");
scan(directory)?
scan(directory, !*cross_filesystems)?
.ok_or_else(|| anyhow!("Empty source."))?
.replace_meta(&None)
} else {
@ -206,10 +207,14 @@ pub fn interactive_labelling_session(path: &Path, source_name: String) -> anyhow
// then request to scan
info!("Requesting scan from remote source... (this may take some time)");
let scan =
backup_source_requester::scanning(&mut read, &mut write, directory.as_ref())?
.ok_or_else(|| anyhow!("Remote scan failed (does the directory exist?)"))?
.replace_meta(&None);
let scan = backup_source_requester::scanning(
&mut read,
&mut write,
directory.as_ref(),
!*cross_filesystems,
)?
.ok_or_else(|| anyhow!("Remote scan failed (does the directory exist?)"))?
.replace_meta(&None);
backup_source_requester::quit(&mut read, &mut write)?;

View File

@ -52,6 +52,8 @@ pub enum SourceDescriptor {
DirectorySource {
hostname: String,
directory: PathBuf,
#[serde(default)]
cross_filesystems: bool,
},
VirtualSource {
/// The name of the helper program that will be used to do this backup.

View File

@ -47,10 +47,12 @@ pub fn scanning<R: Read, W: Write>(
read: &mut R,
write: &mut W,
path: &Path,
one_filesystem: bool,
) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
info!("Scanning.");
write_message(write, &"scan")?;
write_message(write, &path)?;
write_message(write, &one_filesystem)?;
write.flush()?;
let scan_result: Option<FileTree<(), (), (), ()>> = read_message(read)?;
@ -177,6 +179,7 @@ pub fn backup_remote_source_to_destination<PT: ProgressTracker + Send + 'static>
SourceDescriptor::DirectorySource {
hostname,
directory,
cross_filesystems,
} => {
let remote_host_descriptor = descriptor
.remote_hosts
@ -198,8 +201,13 @@ pub fn backup_remote_source_to_destination<PT: ProgressTracker + Send + 'static>
// then request to scan
info!("Requesting scan... (this may take some time)");
let scan_result = scanning(&mut read, &mut write, directory.as_ref())?
.ok_or_else(|| anyhow!("Remote scan failed (does the directory exist?)"))?;
let scan_result = scanning(
&mut read,
&mut write,
directory.as_ref(),
!*cross_filesystems,
)?
.ok_or_else(|| anyhow!("Remote scan failed (does the directory exist?)"))?;
let mut root =
label_filter_and_convert(scan_result, descriptor, desc_path, source_name, dest)?

View File

@ -42,7 +42,8 @@ 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<()> {
let path: PathBuf = read_message(read)?;
let scan_result = scan(&path)?;
let one_filesystem: bool = read_message(read)?;
let scan_result = scan(&path, one_filesystem)?;
write_message(write, &scan_result)?;
write.flush()?;
Ok(())

View File

@ -24,7 +24,7 @@ use std::path::Path;
use anyhow::anyhow;
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use log::warn;
use log::{info, warn};
use serde::{Deserialize, Serialize};
pub use yama::definitions::FilesystemOwnership;
@ -216,12 +216,14 @@ pub fn mtime_msec(metadata: &Metadata) -> u64 {
}
/// Scan the filesystem to produce a Tree, using a default progress bar.
pub fn scan(path: &Path) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
pub fn scan(path: &Path, one_filesystem: bool) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
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_message("dir scan");
let result = scan_with_progress_bar(path, &pbar);
let one_filesystem = if one_filesystem { Some(None) } else { None };
let result = scan_with_progress_bar(path, &pbar, one_filesystem);
pbar.finish_at_current_pos();
result
}
@ -230,6 +232,7 @@ pub fn scan(path: &Path) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
pub fn scan_with_progress_bar(
path: &Path,
progress_bar: &ProgressBar,
mut one_filesystem: Option<Option<u64>>,
) -> anyhow::Result<Option<FileTree<(), (), (), ()>>> {
let metadata_res = symlink_metadata(path);
progress_bar.inc(1);
@ -249,6 +252,14 @@ pub fn scan_with_progress_bar(
let metadata = metadata_res?;
let filetype = metadata.file_type();
if let Some(one_filesystem) = one_filesystem.as_mut() {
let this_fs = metadata.dev();
if *one_filesystem.get_or_insert(this_fs) != this_fs {
info!("Stopping at filesystem boundary: {:?}", path);
return Ok(None);
}
}
/*let name = path
.file_name()
.ok_or(anyhow!("No filename, wat"))?
@ -294,7 +305,7 @@ pub fn scan_with_progress_bar(
for entry in dir_read? {
let entry: DirEntry = entry?;
let scanned = scan_with_progress_bar(&entry.path(), progress_bar)?;
let scanned = scan_with_progress_bar(&entry.path(), progress_bar, one_filesystem)?;
if let Some(scanned) = scanned {
children.insert(
entry