Skip to content

Commit a1d997f

Browse files
authored
Application Arguments (#81)
* add support for various restic alike arguments - repo, repository-file, password, password-file, password-command - only show help or version when specified and do not launch the app * add "insecure tls" opion for non local repositories
1 parent 637c24a commit a1d997f

File tree

10 files changed

+276
-140
lines changed

10 files changed

+276
-140
lines changed

src-tauri/Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ simplelog = { version = "^0.12" }
2222
anyhow = { version = "^1.0" }
2323
which = { version = "^4.0" }
2424
open = { version = "^5.0" }
25+
shlex = { version = "^1.2" }
2526

2627
#tauri
2728
tauri = { version = "^1.5", features = [ "cli", "api-all"] }

src-tauri/src/app.rs

+6-110
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::{collections::HashSet, env, fs, path, sync::RwLock};
1+
use std::{collections::HashSet, fs, path, sync::RwLock};
22

3-
use anyhow::anyhow;
43
use tauri::api::dialog::blocking::{ask, FileDialogBuilder, MessageDialogBuilder};
54

65
use crate::restic::*;
@@ -116,119 +115,16 @@ impl SharedAppState {
116115

117116
// -------------------------------------------------------------------------------------------------
118117

119-
struct LocationInfo<'a> {
120-
prefix: &'a str,
121-
credentials: Vec<&'a str>,
122-
}
123-
124-
fn location_infos() -> Vec<LocationInfo<'static>> {
125-
vec![
126-
LocationInfo {
127-
prefix: "bs",
128-
credentials: vec![],
129-
},
130-
LocationInfo {
131-
prefix: "sftp",
132-
credentials: vec![],
133-
},
134-
LocationInfo {
135-
prefix: "rest",
136-
credentials: vec![],
137-
},
138-
LocationInfo {
139-
prefix: "rclone",
140-
credentials: vec![],
141-
},
142-
LocationInfo {
143-
prefix: "s3",
144-
credentials: vec!["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
145-
},
146-
LocationInfo {
147-
prefix: "b2",
148-
credentials: vec!["B2_ACCOUNT_ID", "B2_ACCOUNT_KEY"],
149-
},
150-
LocationInfo {
151-
prefix: "azure",
152-
credentials: vec!["AZURE_ACCOUNT_NAME", "AZURE_ACCOUNT_KEY"],
153-
},
154-
]
155-
}
156-
157-
// defaultRepo determines the default restic repository location from the environment.
158-
fn default_repo() -> anyhow::Result<String> {
159-
if let Ok(repository_file) = env::var("RESTIC_REPOSITORY_FILE") {
160-
let content = fs::read_to_string(repository_file.clone());
161-
if let Ok(content) = content {
162-
return Ok(content.trim().replace('\n', ""));
163-
} else {
164-
return Err(anyhow!("{repository_file} does not exist"));
165-
}
166-
}
167-
if let Ok(repository) = env::var("RESTIC_REPOSITORY") {
168-
Ok(repository)
169-
} else {
170-
Err(anyhow!("No repository set"))
171-
}
172-
}
173-
174-
// defaultRepoPassword determines the default restic repository password from the environment.
175-
fn default_repo_password() -> anyhow::Result<String> {
176-
if let Ok(password_file) = env::var("RESTIC_PASSWORD_FILE") {
177-
let content = fs::read_to_string(password_file.clone());
178-
if let Ok(content) = content {
179-
return Ok(content.trim().replace('\n', ""));
180-
} else {
181-
return Err(anyhow!("{password_file} does not exist"));
182-
}
183-
}
184-
if let Ok(repository) = env::var("RESTIC_PASSWORD") {
185-
Ok(repository)
186-
} else {
187-
Err(anyhow!("No repository password set"))
188-
}
118+
#[tauri::command]
119+
pub fn open_file_or_url(path: String) -> Result<(), String> {
120+
open::that(path).map_err(|err| err.to_string())
189121
}
190122

191123
// -------------------------------------------------------------------------------------------------
192124

193125
#[tauri::command]
194-
pub fn default_repo_location() -> Result<Location, String> {
195-
// read default location from env
196-
let mut location = Location {
197-
path: default_repo().unwrap_or_default(),
198-
password: default_repo_password().unwrap_or_default(),
199-
credentials: vec![],
200-
prefix: "".to_string(),
201-
};
202-
if location.path.is_empty() {
203-
// skip reading other location info when no repo is present
204-
return Ok(location);
205-
}
206-
location.prefix = "".to_string();
207-
for location_info in location_infos() {
208-
if location
209-
.path
210-
.starts_with(&(location_info.prefix.to_string() + ":"))
211-
{
212-
location.prefix = location_info.prefix.to_string();
213-
location.path =
214-
location
215-
.path
216-
.replacen(&(location_info.prefix.to_string() + ":"), "", 1);
217-
for credential in location_info.credentials {
218-
location.credentials.push(EnvValue {
219-
name: credential.to_string(),
220-
value: env::var(credential).unwrap_or_default(),
221-
})
222-
}
223-
break;
224-
}
225-
}
226-
Ok(location)
227-
}
228-
229-
#[tauri::command]
230-
pub fn open_file_or_url(path: String) -> Result<(), String> {
231-
open::that(path).map_err(|err| err.to_string())
126+
pub fn default_repo_location(app_state: tauri::State<SharedAppState>) -> Result<Location, String> {
127+
Ok(app_state.get()?.location)
232128
}
233129

234130
// -------------------------------------------------------------------------------------------------

src-tauri/src/main.rs

+47-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
22
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
33

4-
use std::{env, fs, path, process};
4+
use std::{collections::HashMap, env, fs, path, process};
55

66
use anyhow::anyhow;
77
use simplelog::*;
@@ -52,13 +52,14 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
5252

5353
// get restic from args or find restic in path
5454
let mut restic_path = "".to_owned();
55-
if let Ok(matches) = app.get_cli_matches() {
56-
if let Some(arg) = matches.args.get("restic") {
55+
match app.get_cli_matches() {
56+
Ok(matches) => if let Some(arg) = matches.args.get("restic") {
5757
restic_path = arg.value.as_str().unwrap_or("").to_string();
5858
if !restic_path.is_empty() {
5959
log::info!("Got restic as arg {}", restic_path);
6060
}
61-
}
61+
},
62+
Err(err) => log::error!("{}", err.to_string())
6263
}
6364
if restic_path.is_empty() {
6465
if let Ok(restic) = which("restic") {
@@ -84,6 +85,23 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
8485
}
8586
}
8687

88+
// get default restic location from args or env
89+
let mut location;
90+
if let Ok(matches) = app.get_cli_matches() {
91+
location = Location::new_from_args(
92+
matches
93+
.args
94+
.into_iter()
95+
.map(|(k, v)| (k, v.value.as_str().unwrap_or("").to_string()))
96+
.collect::<HashMap<_, _>>(),
97+
);
98+
if location.path.is_empty() {
99+
location = Location::new_from_env();
100+
}
101+
} else {
102+
location = Location::new_from_env();
103+
}
104+
87105
// create temp dir for previews
88106
let mut temp_dir = path::Path::new(&env::temp_dir())
89107
.join(app.package_info().name.clone() + "_" + &process::id().to_string());
@@ -97,7 +115,7 @@ fn initialize_app(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
97115
// create new app state
98116
app.manage(app::SharedAppState::new(app::AppState::new(
99117
ResticCommand::new(&restic_path),
100-
Location::default(),
118+
location,
101119
temp_dir.to_string_lossy().as_ref(),
102120
)));
103121

@@ -129,7 +147,7 @@ fn show_app(app_window: tauri::Window) -> Result<(), String> {
129147

130148
fn main() {
131149
// create new app
132-
tauri::Builder::default()
150+
let app = tauri::Builder::default()
133151
.setup(initialize_app)
134152
.on_window_event(|event| {
135153
if let tauri::WindowEvent::Destroyed = event.event() {
@@ -157,6 +175,28 @@ fn main() {
157175
app::dump_file_to_temp,
158176
app::restore_file
159177
])
160-
.run(tauri::generate_context!())
178+
.build(tauri::generate_context!())
161179
.expect("error while running tauri application");
180+
181+
// show argument help / version only
182+
let mut do_run = true;
183+
if let Ok(matches) = app.get_cli_matches() {
184+
if let Some(arg) = matches.args.get("help") {
185+
print!("{}", arg.value.as_str().unwrap());
186+
do_run = false;
187+
} else if matches.args.get("version").is_some() {
188+
let package = app.config().package.clone();
189+
println!(
190+
"{} v{}",
191+
package.product_name.unwrap_or("Restic Browser".to_string()),
192+
package.version.unwrap_or("[Unknown version]".to_string())
193+
);
194+
do_run = false;
195+
}
196+
}
197+
198+
// run the app
199+
if do_run {
200+
app.run(|_, _| {});
201+
}
162202
}

0 commit comments

Comments
 (0)