Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/rclone path #92

Merged
merged 4 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,46 @@ The UI is navigatable via keyboard shortcuts. To change the focus area, hit `Tab
- `r`: Restore selected file or folder


## Arguments

### Usage
```
Restic-Browser [OPTIONS]
```

### Options
```
-h, --help
Print help information

--insecure-tls
skip TLS certificate verification when connecting to the repo (insecure)

--password <password>
password for the repository - NOT RECOMMENDED - USE password-file/command instead. (default: $RESTIC_PASSWORD)

--password-command <password-command>
shell command to obtain the repository password from (default: $RESTIC_PASSWORD_COMMAND)

--password-file <password-file>
file to read the repository password from (default: $RESTIC_PASSWORD_FILE)

-r, --repo <repo>
repository to show or restore from (default: $RESTIC_REPOSITORY)

--rclone <rclone>
ABS path to the rclone executable that should be used for rclone locations. (default: 'rclone')

--repository-file <repository-file>
file to read the repository location from (default: $RESTIC_REPOSITORY_FILE)

--restic <restic>
ABS path to the restic executable that should be used. (default: find in $PATH)

-V, --version
Print version information
```

## System Requirements

#### All platforms
Expand Down
16 changes: 16 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
},
"devDependencies": {
"@tauri-apps/cli": "^1.5.2",
"@types/node": "^20.10.6",
"typescript": "^5.2.2",
"vite": "^4.4.11"
},
Expand Down
21 changes: 9 additions & 12 deletions src-tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ pub struct AppState {
}

impl AppState {
pub fn new(
restic: restic::Program,
location: restic::Location,
temp_dir: PathBuf,
) -> Self {
pub fn new(restic: restic::Program, location: restic::Location, temp_dir: PathBuf) -> Self {
let snapshot_ids = HashSet::default();
Self {
restic,
Expand All @@ -35,17 +31,17 @@ impl AppState {
}

pub fn verify_restic_path(&self) -> Result<(), String> {
if self.restic.path.as_os_str().is_empty() {
if self.restic.restic_path().as_os_str().is_empty() {
return Err("No restic executable set".to_string());
} else if !self.restic.path.exists() {
} else if !self.restic.restic_path().exists() {
return Err(format!(
"Restic executable '{}' does not exist or can not be accessed.",
self.restic.path.to_string_lossy()
self.restic.restic_path().to_string_lossy()
));
} else if self.restic.version == [0, 0, 0] {
} else if self.restic.restic_version() == [0, 0, 0] {
return Err(format!(
"Failed to query restic version. Is '{}' a valid restic application?",
self.restic.path.to_string_lossy()
self.restic.restic_path().to_string_lossy()
));
}
Ok(())
Expand Down Expand Up @@ -144,7 +140,7 @@ pub fn verify_restic_path(
) -> Result<(), String> {
// verify that restic binary is set
let state = app_state.get()?;
if !state.restic.path.exists() {
if !state.restic.restic_path().exists() {
// aks user to resolve restic path
MessageDialogBuilder::new(
"Restic Binary Missing",
Expand All @@ -163,7 +159,8 @@ Please select your installed restic binary manually in the following dialog.",
restic_path.clone().unwrap_or_default().display()
);
if let Some(restic_path) = restic_path {
app_state.update_restic(restic::Program::new(restic_path))?;
let rclone_path = state.restic.rclone_path().clone();
app_state.update_restic(restic::Program::new(restic_path, rclone_path))?;
}
}
Ok(())
Expand Down
39 changes: 33 additions & 6 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,16 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
// initialize
CombinedLogger::init(loggers).unwrap_or_else(|err| eprintln!("Failed to create logger: {err}"));

// common bin directories on macOS
#[cfg(target_os = "macos")]
let common_path = format!(
"/usr/local/bin:/opt/local/bin:/opt/homebrew/bin:{}/bin",
env::var("HOME").unwrap_or("~".into())
);

// get restic from args or find restic in path
let mut restic_path = None;
let mut rclone_path = None;
match app.get_cli_matches() {
Ok(matches) => {
if let Some(arg) = matches.args.get("restic") {
Expand All @@ -64,6 +72,12 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
log::info!("Got restic as arg {}", path.to_string_lossy());
}
}
if let Some(arg) = matches.args.get("rclone") {
rclone_path = arg.value.as_str().map(PathBuf::from);
if let Some(ref path) = rclone_path {
log::info!("Got rclone as arg {}", path.to_string_lossy());
}
}
}
Err(err) => log::error!("{}", err.to_string()),
}
Expand All @@ -79,11 +93,8 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
if restic_path.is_none() {
if let Ok(restic) = which_in(
restic::RESTIC_EXECTUABLE_NAME,
Some(format!(
"/usr/local/bin:/opt/local/bin:/opt/homebrew/bin:{}/bin",
env::var("HOME").unwrap_or("~".to_string())
)),
"/",
Some(common_path.clone()),
env::current_dir().unwrap_or("/".into()),
) {
restic_path = Some(restic.clone());
log::info!(
Expand All @@ -97,6 +108,22 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
}
}

#[cfg(target_os = "macos")]
// on macOS, try to resolve rclone path in common PATH if it can't be found in path
if rclone_path.is_none() && which(restic::RCLONE_EXECTUABLE_NAME).is_err() {
if let Ok(rclone) = which_in(
restic::RCLONE_EXECTUABLE_NAME,
Some(common_path),
env::current_dir().unwrap_or("/".into()),
) {
rclone_path = Some(rclone.clone());
log::info!(
"Found rclone binary in common PATH at '{}'",
rclone.to_string_lossy()
);
}
}

// get default restic location from args or env
let mut location;
if let Ok(matches) = app.get_cli_matches() {
Expand Down Expand Up @@ -126,7 +153,7 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>

// create new app state
app.manage(app::SharedAppState::new(app::AppState::new(
restic::Program::new(restic_path.unwrap_or(PathBuf::new())),
restic::Program::new(restic_path.unwrap_or_default(), rclone_path),
location,
temp_dir,
)));
Expand Down
Loading