diff --git a/.earthlyignore b/.earthlyignore index fb7de17a1..8953460f1 100644 --- a/.earthlyignore +++ b/.earthlyignore @@ -26,6 +26,7 @@ vendor # testing testing +spn/testing/simple/testdata # Compiled Object files, Static and Dynamic libs (Shared Objects) *.a diff --git a/.gitignore b/.gitignore index d534dccd8..e0a6550a9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ vendor # testing testing +spn/testing/simple/testdata # Compiled Object files, Static and Dynamic libs (Shared Objects) *.a diff --git a/cmds/portmaster-start/run.go b/cmds/portmaster-start/run.go index 8cbea78e9..f807fd69d 100644 --- a/cmds/portmaster-start/run.go +++ b/cmds/portmaster-start/run.go @@ -154,7 +154,7 @@ func getExecArgs(opts *Options, cmdArgs []string) []string { args = append(args, "--input-signals") } - if runtime.GOOS == "linux" && opts.Identifier == "app/portmaster-app.zip" { + if runtime.GOOS == "linux" && opts.ShortIdentifier == "app" { // see https://www.freedesktop.org/software/systemd/man/pam_systemd.html#type= if xdgSessionType := os.Getenv("XDG_SESSION_TYPE"); xdgSessionType == "wayland" { // we're running the Portmaster UI App under Wayland so make sure we add some arguments @@ -180,10 +180,6 @@ func run(opts *Options, cmdArgs []string) (err error) { return nil } - // get original arguments - // additional parameters can be specified using -- --some-parameter - args := getExecArgs(opts, cmdArgs) - // check for duplicate instances if opts.PIDFile { pid, err := checkAndCreateInstanceLock(opts.LockPathPrefix, opts.ShortIdentifier, opts.LockPerUser) @@ -226,7 +222,7 @@ func run(opts *Options, cmdArgs []string) (err error) { } } - return runAndRestart(opts, args) + return runAndRestart(opts, cmdArgs) } func runAndRestart(opts *Options, args []string) error { @@ -342,6 +338,10 @@ func execute(opts *Options, args []string) (cont bool, err error) { opts = &app2Options } + // Compile arguments and add additional arguments based on system configuration. + // Extra parameters can be specified using "-- --some-parameter". + args = getExecArgs(opts, args) + file, err := registry.GetFile( helper.PlatformIdentifier(opts.Identifier), ) diff --git a/desktop/tauri/src-tauri/Cargo.lock b/desktop/tauri/src-tauri/Cargo.lock index d169adc62..dbf71ec68 100644 --- a/desktop/tauri/src-tauri/Cargo.lock +++ b/desktop/tauri/src-tauri/Cargo.lock @@ -236,7 +236,6 @@ dependencies = [ "tauri", "tauri-build", "tauri-cli", - "tauri-plugin-cli", "tauri-plugin-clipboard-manager", "tauri-plugin-dialog", "tauri-plugin-log", @@ -7611,21 +7610,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "tauri-plugin-cli" -version = "2.0.0-beta.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22c997925db64e1cfa748dfc52b25b053c1b74453fd32a800a6b36d4e7a83e0f" -dependencies = [ - "clap 4.5.9", - "log", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror", -] - [[package]] name = "tauri-plugin-clipboard-manager" version = "2.0.0-beta.2" diff --git a/desktop/tauri/src-tauri/Cargo.toml b/desktop/tauri/src-tauri/Cargo.toml index 416ab2d52..e58c4decc 100644 --- a/desktop/tauri/src-tauri/Cargo.toml +++ b/desktop/tauri/src-tauri/Cargo.toml @@ -22,13 +22,12 @@ tauri-plugin-dialog = "2.0.0-beta" tauri-plugin-clipboard-manager = "2.0.0-beta" tauri-plugin-os = "2.0.0-beta" tauri-plugin-single-instance = "2.0.0-beta" -tauri-plugin-cli = "2.0.0-beta" tauri-plugin-notification = "2.0.0-beta" tauri-plugin-log = "2.0.0-beta" tauri-plugin-window-state = "2.0.0-beta" tauri-cli = "2.0.0-beta.21" -clap = { version = "4", features = [ "derive" ] } +clap = { version = "4" } # General serde_json = "1.0" diff --git a/desktop/tauri/src-tauri/src/main.rs b/desktop/tauri/src-tauri/src/main.rs index c1ca3ac48..331b86acb 100644 --- a/desktop/tauri/src-tauri/src/main.rs +++ b/desktop/tauri/src-tauri/src/main.rs @@ -3,9 +3,8 @@ use std::{env, path::Path, time::Duration}; -use clap::{command, Parser}; +use clap::{Arg, Command}; use tauri::{AppHandle, Emitter, Listener, Manager, RunEvent, WindowEvent}; -use tauri_plugin_cli::CliExt; // Library crates mod portapi; @@ -49,14 +48,21 @@ struct WsHandler { is_first_connect: bool, } -#[derive(Parser, Debug)] -#[command(version, about, long_about = None)] -struct BasicCli { - #[arg(long)] +struct CliArguments { + // Path to the installation directory data: Option, - #[arg(long)] - log: Option, + // Log level to use: off, error, warn, info, debug, trace + log: String, + + // Start in the background without opening a window + background: bool, + + // Enable experimental notifications via Tauri. Replaces the notifier app. + with_prompts: bool, + + // Enable experimental prompt support via Tauri. Replaces the notifier app. + with_notifications: bool, } impl portmaster::Handler for WsHandler { @@ -98,7 +104,6 @@ impl portmaster::Handler for WsHandler { // since there's already a main window with the angular application. if !self.background && self.is_first_connect { let _ = window::create_splash_window(&self.handle.clone()); - self.is_first_connect = false } } @@ -132,27 +137,87 @@ fn main() { std::process::exit(show_webview_not_installed_dialog()); } - let mut target = tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Stdout); + let matches = Command::new("Portmaster") + .ignore_errors(true) + .arg( + Arg::new("data") + .short('d') + .long("data") + .required(false) + .help("Path to the installation directory."), + ) + .arg( + Arg::new("log") + .short('l') + .long("log") + .required(false) + .help("Log level to use: off, error, warn, info, debug, trace."), + ) + .arg( + Arg::new("background") + .short('b') + .long("background") + .required(false) + .help("Start in the background without opening a window."), + ) + .arg( + Arg::new("with_prompts") + .long("with_prompts") + .required(false) + .action(clap::ArgAction::SetTrue) + .help("Enable experimental notifications via Tauri. Replaces the notifier app."), + ) + .arg( + Arg::new("with_notifications") + .long("with_notifications") + .required(false) + .action(clap::ArgAction::SetTrue) + .help("Enable experimental prompt support via Tauri. Replaces the notifier app."), + ) + .get_matches(); + + let mut cli = CliArguments { + data: None, + log: LOG_LEVEL.to_string(), + background: false, + with_prompts: false, + with_notifications: false, + }; + + if let Some(data) = matches.get_one::("data") { + cli.data = Some(data.to_string()); + } + + if let Some(log) = matches.get_one::("log") { + cli.log = log.to_string(); + } + + if let Some(value) = matches.get_one::("with_prompts") { + cli.with_prompts = *value; + } + + if let Some(value) = matches.get_one::("with_notifications") { + cli.with_notifications = *value; + } - let cli = BasicCli::parse(); - if let Some(data_dir) = cli.data { - target = tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Folder { + let log_target = if let Some(data_dir) = cli.data { + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Folder { path: Path::new(&format!("{}/logs/app2", data_dir)).into(), file_name: None, - }); - } + }) + } else { + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Stdout) + }; let mut log_level = LOG_LEVEL; - if let Some(level) = cli.log { - match level.as_str() { - "off" => log_level = LevelFilter::Off, - "error" => log_level = LevelFilter::Error, - "warn" => log_level = LevelFilter::Warn, - "info" => log_level = LevelFilter::Info, - "debug" => log_level = LevelFilter::Debug, - "trace" => log_level = LevelFilter::Trace, - _ => {} - } + match cli.log.as_ref() { + "off" => log_level = LevelFilter::Off, + "error" => log_level = LevelFilter::Error, + "warn" => log_level = LevelFilter::Warn, + "info" => log_level = LevelFilter::Info, + "debug" => log_level = LevelFilter::Debug, + "trace" => log_level = LevelFilter::Trace, + _ => {} } let app = tauri::Builder::default() @@ -164,7 +229,7 @@ fn main() { .level(log_level) .rotation_strategy(RotationStrategy::KeepAll) .clear_targets() - .target(target) + .target(log_target) .build(), ) // Clipboard support @@ -177,10 +242,9 @@ fn main() { .plugin(tauri_plugin_window_state::Builder::default().build()) // Single instance guard .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { + // Send info to already dunning instance. let _ = app.emit("single-instance", Payload { args: argv, cwd }); })) - // Custom CLI arguments - .plugin(tauri_plugin_cli::init()) // Notification support .plugin(tauri_plugin_notification::init()) .invoke_handler(tauri::generate_handler![ @@ -193,7 +257,7 @@ fn main() { portmaster::commands::should_handle_prompts ]) // Setup the app an any listeners - .setup(|app| { + .setup(move |app| { setup_tray_menu(app)?; portmaster::setup(app.handle().clone()); // Setup the single-instance event listener that will create/focus the main window @@ -204,50 +268,16 @@ fn main() { }); // Handle cli flags: - // - let mut background = false; - match app.cli().matches() { - Ok(matches) => { - debug!("cli matches={:?}", matches); - - if let Some(bg_flag) = matches.args.get("background") { - match bg_flag.value.as_bool() { - Some(value) => { - background = value; - app.portmaster().set_show_after_bootstrap(!background); - } - None => {} - } - } - - if let Some(nf_flag) = matches.args.get("with-notifications") { - match nf_flag.value.as_bool() { - Some(v) => { - app.portmaster().with_notification_support(v); - } - None => {} - } - } - - if let Some(pf_flag) = matches.args.get("with-prompts") { - match pf_flag.value.as_bool() { - Some(v) => { - app.portmaster().with_connection_prompts(v); - } - None => {} - } - } - } - Err(err) => { - error!("failed to parse cli arguments: {}", err.to_string()); - } - }; + app.portmaster().set_show_after_bootstrap(!cli.background); + app.portmaster() + .with_notification_support(cli.with_notifications); + app.portmaster().with_connection_prompts(cli.with_prompts); // prepare a custom portmaster plugin handler that will show the splash-screen // (if not in --background) and launch the tray-icon handler. let handler = WsHandler { handle: app.handle().clone(), - background, + background: cli.background, is_first_connect: true, };