Skip to content

Commit

Permalink
Add support for relative paths
Browse files Browse the repository at this point in the history
  • Loading branch information
marius committed Mar 30, 2024
1 parent 92e8fa0 commit c4b81fc
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 12 deletions.
53 changes: 53 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
chrono = "0.4"
clap = { version = "4.5.4", features = ["derive"] }
dirs = "5.0.1"
env_logger = "0.11.3"
generic-array = "1.0.0"
Expand Down
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,47 @@ Only the fantastic [restic](https://github.com/restic/restic) is supported at th

Set the `RESTIC_REPOSITORY` and `RESTIC_PASSWORD` environment variables and run `cargo run`.

### Example (assuming you cloned Bacify into *$HOME/dev/bacify*):
### Examples

NOTE: Assuming you cloned Bacify into *$HOME/dev/bacify*

#### Backup snapshot with an absolute path

Create backup and verify the data in the repository:
```
$ cd $HOME/dev/bacify
$ export RESTIC_REPOSITORY="$HOME/tmp/restic-repo"
$ export RESTIC_PASSWORD="foo"
$ restic init
$ restic backup $HOME/dev/bacify
$ restic check --read-data
```

Verify the backup against the local files:
```
$ cd ~/dev/bacify
$ cargo run
```

#### Backup snapshot with a relative path

Create backup and verify the data in the repository:
```
$ cd $HOME/dev/bacify
$ export RESTIC_REPOSITORY="$HOME/tmp/restic-repo"
$ export RESTIC_PASSWORD="foo"
$ export LOG_LEVEL=debug
$ cargo run
$ restic init
$ restic backup .
```

Verify the backup against the local files:
```
$ cargo run -- --relative-path
```

*--relative-path* is needed as the snapshot metadata lists absolute paths,
but the files are actually restored without the leading path components.

### Excludes

> [!WARNING]
> Read this is you get a lot of errors about missing files!<br>
> At the moment there is only support for a hard-coded, single exclude file named `$HOME/.backup_exclude`.<br>
Expand Down
32 changes: 25 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use chrono::prelude::*;
use clap::Parser;
use env_logger::{Builder, Env, Target};
use log::{debug, info, warn};
use serde_json::Value;
Expand All @@ -19,10 +20,17 @@ struct BackupVerifier {
source_dir: PathBuf,
id: String,
excludes: Vec<String>,
relative_path: bool,
}

#[derive(Parser, Debug)]
struct Args {
#[arg(short, long)]
relative_path: bool,
}

impl BackupVerifier {
fn new() -> BackupVerifier {
fn new(relative_path: bool) -> BackupVerifier {
BackupVerifier {
missing: HashSet::new(),
corrupt: HashSet::new(),
Expand All @@ -31,6 +39,7 @@ impl BackupVerifier {
source_dir: PathBuf::new(),
id: String::new(),
excludes: Vec::new(),
relative_path,
}
}

Expand All @@ -53,11 +62,18 @@ impl BackupVerifier {

// Verify the source file against the backup
fn verify_source_file(&mut self, file: &Path) -> io::Result<()> {
// If file is an absolute Path we need to strip the leading slash, otherwise
// backup_dir.join(file) will return file, instead of the joined paths.
// See https://doc.rust-lang.org/std/path/struct.Path.html#method.join.
// TODO: Add support for relative paths.
let relative_file = file.strip_prefix("/").unwrap_or(file);
// Relative paths restore right into the temporary directory, but in the snapshot metadata
// there is an absolute path.
// Use --relative-path (or -r) to remove the leading path components.
let relative_file = if self.relative_path {
file.strip_prefix(self.source_dir.as_path())
.expect("Could not strip prefix")
} else {
// If file is an absolute Path we need to strip the leading slash, otherwise
// backup_dir.join(file) will return file, instead of the joined paths.
// See https://doc.rust-lang.org/std/path/struct.Path.html#method.join.
file.strip_prefix("/").unwrap_or(file)
};
let counterpart = self.backup_dir.join(relative_file);

let file_metadata = fs::metadata(file)?;
Expand Down Expand Up @@ -216,12 +232,14 @@ fn main() {
.target(Target::Stdout)
.init();

let args = Args::parse();

// We want to see some output during restore, needs at least restic version 0.16.0
if std::env::var_os("RESTIC_PROGRESS_FPS").is_none() {
std::env::set_var("RESTIC_PROGRESS_FPS", "0.5");
}

let mut verifier = BackupVerifier::new();
let mut verifier = BackupVerifier::new(args.relative_path);
match verifier.main() {
Err(e) => {
info!("Error: {}", e);
Expand Down

0 comments on commit c4b81fc

Please sign in to comment.