From a07b87fc206a625de2cdb5bc9395a89a6542944d Mon Sep 17 00:00:00 2001
From: Daniel <dhaavi@users.noreply.github.com>
Date: Thu, 1 Aug 2024 14:16:18 +0200
Subject: [PATCH 1/3] [cmd/start] Compile cmdline args after possibly upgrading
 to new UI

---
 cmds/portmaster-start/run.go | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/cmds/portmaster-start/run.go b/cmds/portmaster-start/run.go
index 8cbea78e..f807fd69 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),
 	)

From 188b47c1fb06ddf5e5f779c54a2a4744a3ebe36b Mon Sep 17 00:00:00 2001
From: Daniel <dhaavi@users.noreply.github.com>
Date: Thu, 1 Aug 2024 14:17:01 +0200
Subject: [PATCH 2/3] Update ignore files

---
 .earthlyignore | 1 +
 .gitignore     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/.earthlyignore b/.earthlyignore
index fb7de17a..8953460f 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 d534dccd..e0a6550a 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

From 7a06b0bc1c3faf9c153b6bd3bd5b34c20df1afa9 Mon Sep 17 00:00:00 2001
From: Vladimir Stoilov <vladimir@safing.io>
Date: Thu, 1 Aug 2024 15:25:44 +0300
Subject: [PATCH 3/3] [desktop] Tauri ignore extra cmdline args

---
 desktop/tauri/src-tauri/Cargo.lock  |  16 ---
 desktop/tauri/src-tauri/Cargo.toml  |   3 +-
 desktop/tauri/src-tauri/src/main.rs | 168 ++++++++++++++++------------
 3 files changed, 100 insertions(+), 87 deletions(-)

diff --git a/desktop/tauri/src-tauri/Cargo.lock b/desktop/tauri/src-tauri/Cargo.lock
index d169adc6..dbf71ec6 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 416ab2d5..e58c4dec 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 c1ca3ac4..331b86ac 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<String>,
 
-    #[arg(long)]
-    log: Option<String>,
+    // 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 cli = BasicCli::parse();
-    if let Some(data_dir) = cli.data {
-        target = tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Folder {
-            path: Path::new(&format!("{}/logs/app2", data_dir)).into(),
-            file_name: None,
-        });
+    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::<String>("data") {
+        cli.data = Some(data.to_string());
     }
 
+    if let Some(log) = matches.get_one::<String>("log") {
+        cli.log = log.to_string();
+    }
+
+    if let Some(value) = matches.get_one::<bool>("with_prompts") {
+        cli.with_prompts = *value;
+    }
+
+    if let Some(value) = matches.get_one::<bool>("with_notifications") {
+        cli.with_notifications = *value;
+    }
+
+    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,
             };