ronantakizawa/codereview-bench huggingface dataset:
Repository: tauri-apps/tauri
File: tooling/cli/templates/plugin/src/mobile.rs (Rust)

Code before:
{{#if license_header}}
{{ license_header }}
{{/if}}
use serde::de::DeserializeOwned;
use tauri::{
  plugin::{PluginApi, PluginHandle},
  AppHandle, Runtime,
};

use crate::models::*;

#[cfg(target_os = "ios")]
tauri::ios_plugin_binding!(init_plugin_{{ plugin_name_snake_case }});

// initializes the Kotlin or Swift plugin classes
pub fn init<R: Runtime, C: DeserializeOwned>(
  _app: &AppHandle<R>,
  api: PluginApi<R, C>,
) -> crate::Result<{{ plugin_name_pascal_case }}<R>> {
  #[cfg(target_os = "android")]
  let handle = api.register_android_plugin({{ android_package_id }}, "ExamplePlugin")?;
  #[cfg(target_os = "ios")]
  let handle = api.register_ios_plugin(init_plugin_{{ plugin_name_snake_case }})?;
  Ok({{ plugin_name_pascal_case }}(handle))
}

/// Access to the {{ plugin_name }} APIs.
pub struct {{ plugin_name_pascal_case }}<R: Runtime>(PluginHandle<R>);

impl<R: Runtime> {{ plugin_name_pascal_case }}<R> {
  pub fn ping(&self, payload: PingRequest) -> crate::Result<PingResponse> {
    self
      .0
      .run_mobile_plugin("ping", payload)
      .map_err(Into::into)
  }
}


Review comment (suggestion):
```suggestion
  let handle = api.register_android_plugin("{{ android_package_id }}", "ExamplePlugin")?;
```

Code after:
{{#if license_header}}
{{ license_header }}
{{/if}}
use serde::de::DeserializeOwned;
use tauri::{
  plugin::{PluginApi, PluginHandle},
  AppHandle, Runtime,
};

use crate::models::*;

#[cfg(target_os = "ios")]
tauri::ios_plugin_binding!(init_plugin_{{ plugin_name_snake_case }});

// initializes the Kotlin or Swift plugin classes
pub fn init<R: Runtime, C: DeserializeOwned>(
  _app: &AppHandle<R>,
  api: PluginApi<R, C>,
) -> crate::Result<{{ plugin_name_pascal_case }}<R>> {
  #[cfg(target_os = "android")]
  let handle = api.register_android_plugin("{{ android_package_id }}", "ExamplePlugin")?;
  #[cfg(target_os = "ios")]
  let handle = api.register_ios_plugin(init_plugin_{{ plugin_name_snake_case }})?;
  Ok({{ plugin_name_pascal_case }}(handle))
}

/// Access to the {{ plugin_name }} APIs.
pub struct {{ plugin_name_pascal_case }}<R: Runtime>(PluginHandle<R>);

impl<R: Runtime> {{ plugin_name_pascal_case }}<R> {
  pub fn ping(&self, payload: PingRequest) -> crate::Result<PingResponse> {
    self
      .0
      .run_mobile_plugin("ping", payload)
      .map_err(Into::into)
  }
}
Repository: tauri-apps/tauri
File: crates/tauri-bundler/src/bundle/windows/util.rs (Rust)

Code before:
    WEBVIEW2_OFFLINE_INSTALLER_X64_URL
  } else {
    WEBVIEW2_OFFLINE_INSTALLER_X86_URL
  };
  let (guid, filename) = webview2_guid_path(url)?;
  let dir_path = base_path.join(guid);
  let file_path = dir_path.join(filename);
  if !file_path.exists() {
    create_dir_all(dir_path)?;
    std::fs::write(&file_path, download(url)?)?;
  }
  Ok(file_path)
}

pub fn download(url: &str) -> crate::Result<Vec<u8>> {
  log::info!(action = "Downloading"; "{}", url);

  let (agent, url) = match std::env::var("GITHUB_CDN") {
    Ok(cdn) => {
      let mut parsed_cdn = url::Url::parse(&cdn).expect("Invalid cdn");
      parsed_cdn.set_path(url);

      (ureq::AgentBuilder::new().build(), parsed_cdn.to_string())
    }
    Err(_) => (
      ureq::AgentBuilder::new().try_proxy_from_env(true).build(),
      url.to_owned(),
    ),
  };

  let response = agent.get(&url).call().map_err(Box::new)?;
  let mut bytes = Vec::new();
  response.into_reader().read_to_end(&mut bytes)?;
  Ok(bytes)
}

#[derive(Clone, Copy)]
pub enum HashAlgorithm {
  #[cfg(target_os = "windows")]
  Sha256,
  Sha1,
}

/// Function used to download a file and checks SHA256 to verify the download.
pub fn download_and_verify(
  url: &str,
  hash: &str,
  hash_algorithm: HashAlgorithm,
) -> crate::Result<Vec<u8>> {
  let data = download(url)?;
  log::info!("validating hash");

Review comment (suggestion):
we can keep using `AgentBuilder` with `try_proxy_from_env` in the two cases, no need to make distinction, only `url` should be changed based on the new env var

Code after:
pub fn download_webview2_offline_installer(base_path: &Path, arch: &str) -> crate::Result<PathBuf> {
  let url = if arch == "x64" {
    WEBVIEW2_OFFLINE_INSTALLER_X64_URL
  } else {
    WEBVIEW2_OFFLINE_INSTALLER_X86_URL
  };
  let (guid, filename) = webview2_guid_path(url)?;
  let dir_path = base_path.join(guid);
  let file_path = dir_path.join(filename);
  if !file_path.exists() {
    create_dir_all(dir_path)?;
    std::fs::write(&file_path, download(url)?)?;
  }
  Ok(file_path)
}

fn create_agent_and_url(url: &str) -> crate::Result<(ureq::Agent, String)> {
  match std::env::var("TAURI_BUNDLER_TOOLS_GITHUB_MIRROR") {
    Ok(cdn) if url.starts_with("https://github.com/") => {
      let mut parsed_cdn = Url::parse(&cdn)?;
      parsed_cdn.set_path(url);
      Ok((AgentBuilder::new().build(), parsed_cdn.into()))
    }
    _ => Ok((
      AgentBuilder::new().try_proxy_from_env(true).build(),
      url.to_owned(),
    )),
  }
}

pub fn download(url: &str) -> crate::Result<Vec<u8>> {
  log::info!(action = "Downloading"; "{}", url);

  let (agent, final_url) = create_agent_and_url(url)?;

  let response = agent.get(&final_url).call().map_err(Box::new)?;
  let mut bytes = Vec::new();
  response.into_reader().read_to_end(&mut bytes)?;
  Ok(bytes)
}

#[derive(Clone, Copy)]
pub enum HashAlgorithm {
  #[cfg(target_os = "windows")]
  Sha256,
  Sha1,
}

/// Function used to download a file and checks SHA256 to verify the download.
pub fn download_and_verify(
  url: &str,
Repository: tauri-apps/tauri
File: crates/tauri-runtime-wry/src/webview.rs (Rust)

Code before:
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#[cfg(any(
  target_os = "linux",
  target_os = "dragonfly",
  target_os = "freebsd",
  target_os = "netbsd",
  target_os = "openbsd"
))]
mod imp {
  pub type Webview = webkit2gtk::WebView;
}

#[cfg(target_vendor = "apple")]
mod imp {
  use std::ffi::c_void;

  pub struct Webview {
    pub webview: *mut c_void,
    pub manager: *mut c_void,
    #[cfg(target_os = "macos")]
    pub ns_window: *mut c_void,
    #[cfg(not(target_os = "macos"))]
    pub view_controller: *mut c_void,
  }
}

#[cfg(windows)]
mod imp {
  use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Controller;
  pub struct Webview {
    pub controller: ICoreWebView2Controller,
  }
}

#[cfg(target_os = "android")]
mod imp {
  use wry::JniHandle;
  pub type Webview = JniHandle;
}

pub use imp::*;


Review comment (suggestion):
```suggestion
    #[cfg(target_os = "ios")]
```
just for consistency with the usage

Code after:
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#[cfg(any(
  target_os = "linux",
  target_os = "dragonfly",
  target_os = "freebsd",
  target_os = "netbsd",
  target_os = "openbsd"
))]
mod imp {
  pub type Webview = webkit2gtk::WebView;
}

#[cfg(target_vendor = "apple")]
mod imp {
  use std::ffi::c_void;

  pub struct Webview {
    pub webview: *mut c_void,
    pub manager: *mut c_void,
    #[cfg(target_os = "macos")]
    pub ns_window: *mut c_void,
    #[cfg(target_os = "ios")]
    pub view_controller: *mut c_void,
  }
}

#[cfg(windows)]
mod imp {
  use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Controller;
  pub struct Webview {
    pub controller: ICoreWebView2Controller,
  }
}

#[cfg(target_os = "android")]
mod imp {
  use wry::JniHandle;
  pub type Webview = JniHandle;
}

pub use imp::*;
Repository: tauri-apps/tauri
File: crates/tauri-bundler/src/bundle/windows/util.rs (Rust)

Code before:
}

fn generate_mirror_url_from_base(github_url: &str) -> crate::Result<Option<String>> {
  std::env::var("TAURI_BUNDLER_TOOLS_GITHUB_MIRROR")
    .ok()
    .map(|cdn| {
      let mut parsed_cdn = Url::parse(&cdn)?;
      parsed_cdn.set_path(github_url);
      Ok(parsed_cdn.into())
    })
    .transpose()
}

fn generate_alternative_url(url: &str) -> crate::Result<Option<(ureq::Agent, String)>> {
  if !url.starts_with("https://github.com/") {
    return Ok(None);
  }

  let mirror_url = generate_mirror_url_from_template(url);
  let cdn_url = generate_mirror_url_from_base(url)?;

  Ok(
    mirror_url
      .or(cdn_url)
      .map(|alternative_url| (ureq::AgentBuilder::new().build(), alternative_url)),
  )
}

fn create_agent_and_url(url: &str) -> crate::Result<(ureq::Agent, String)> {
  generate_alternative_url(url)?.map_or_else(
    || {
      Ok((
        ureq::AgentBuilder::new().try_proxy_from_env(true).build(),
        url.to_owned(),
      ))
    },
    Ok,
  )
}

pub fn download(url: &str) -> crate::Result<Vec<u8>> {
  log::info!(action = "Downloading"; "{}", url);

  let (agent, final_url) = create_agent_and_url(url)?;

  let response = agent.get(&final_url).call().map_err(Box::new)?;
  let mut bytes = Vec::new();
  response.into_reader().read_to_end(&mut bytes)?;
  Ok(bytes)
}


Review comment (suggestion):
This can be simplified into

```suggestion
  generate_mirror_url_from_template(url)
    .or_else(|_| generate_mirror_url_from_base(url))
    .map(|alt_url| {
      alt_url.map(|alt_url| (ureq::AgentBuilder::new().build(), alt_url))
    })
```

also notice usage of `or_else` instead of `or` which will lazily evaluate `generate_mirror_url_from_base` only if needed.

Code after:
}

fn generate_github_mirror_url_from_base(github_url: &str) -> Option<String> {
  std::env::var("TAURI_BUNDLER_TOOLS_GITHUB_MIRROR")
    .ok()
    .and_then(|cdn| Url::parse(&cdn).ok())
    .map(|mut cdn| {
      cdn.set_path(github_url);
      cdn.to_string()
    })
}

fn generate_github_alternative_url(url: &str) -> Option<(ureq::Agent, String)> {
  if !url.starts_with("https://github.com/") {
    return None;
  }

  generate_github_mirror_url_from_template(url)
    .or_else(|| generate_github_mirror_url_from_base(url))
    .map(|alt_url| (ureq::AgentBuilder::new().build(), alt_url))
}

fn create_agent_and_url(url: &str) -> (ureq::Agent, String) {
  generate_github_alternative_url(url).unwrap_or((
    ureq::AgentBuilder::new().try_proxy_from_env(true).build(),
    url.to_owned(),
  ))
}

pub fn download(url: &str) -> crate::Result<Vec<u8>> {
  let (agent, final_url) = create_agent_and_url(url);

  log::info!(action = "Downloading"; "{}", final_url);

  let response = agent.get(&final_url).call().map_err(Box::new)?;
  let mut bytes = Vec::new();
  response.into_reader().read_to_end(&mut bytes)?;
  Ok(bytes)
}

#[derive(Clone, Copy)]
pub enum HashAlgorithm {
  #[cfg(target_os = "windows")]
  Sha256,
  Sha1,
}

/// Function used to download a file and checks SHA256 to verify the download.
pub fn download_and_verify(
  url: &str,
  hash: &str,
Repository: tauri-apps/tauri
File: packages/api/src/tray.ts (TypeScript)

Code before:
  LogicalPosition,
  LogicalSize,
  PhysicalPosition,
  PhysicalSize
} from './dpi'

export type MouseButtonState = 'Up' | 'Down'
export type MouseButton = 'Left' | 'Right' | 'Middle'
export type TrayIconEventType =
  | 'Click'
  | 'DoubleClick'
  | 'Enter'
  | 'Move'
  | 'Leave'

export type TrayIconEventBase<T extends TrayIconEventType> = {
  /** The tray icon event type */
  type: T
  /** Id of the tray icon which triggered this event. */
  id: string
  /** Physical position of the click the triggered this event. */
  position: PhysicalPosition
  /** Position and size of the tray icon. */
  rect: {
    position: PhysicalPosition | LogicalPosition
    size: PhysicalSize | LogicalSize
  }
}

export type TrayIconClickEvent = {
  /** Mouse button that triggered this event. */
  button: MouseButton
  /** Mouse button state when this event was triggered. */
  buttonState: MouseButtonState
}

/**
 * Describes a tray icon event.
 *
 * #### Platform-specific:
 *
 * - **Linux**: Unsupported. The event is not emitted even though the icon is shown,
 * the icon will still show a context menu on right click.
 */
export type TrayIconEvent =
  | (TrayIconEventBase<'Click'> & TrayIconClickEvent)
  | (TrayIconEventBase<'DoubleClick'> & Omit<TrayIconClickEvent, 'buttonState'>)
  | TrayIconEventBase<'Enter'>
  | TrayIconEventBase<'Move'>
  | TrayIconEventBase<'Leave'>


Review comment (suggestion):
```suggestion
    position: PhysicalPosition
    size: PhysicalSize
```

Code after:

export type MouseButtonState = 'Up' | 'Down'
export type MouseButton = 'Left' | 'Right' | 'Middle'
export type TrayIconEventType =
  | 'Click'
  | 'DoubleClick'
  | 'Enter'
  | 'Move'
  | 'Leave'

export type TrayIconEventBase<T extends TrayIconEventType> = {
  /** The tray icon event type */
  type: T
  /** Id of the tray icon which triggered this event. */
  id: string
  /** Physical position of the click the triggered this event. */
  position: PhysicalPosition
  /** Position and size of the tray icon. */
  rect: {
    position: PhysicalPosition
    size: PhysicalSize
  }
}

export type TrayIconClickEvent = {
  /** Mouse button that triggered this event. */
  button: MouseButton
  /** Mouse button state when this event was triggered. */
  buttonState: MouseButtonState
}

/**
 * Describes a tray icon event.
 *
 * #### Platform-specific:
 *
 * - **Linux**: Unsupported. The event is not emitted even though the icon is shown,
 * the icon will still show a context menu on right click.
 */
export type TrayIconEvent =
  | (TrayIconEventBase<'Click'> & TrayIconClickEvent)
  | (TrayIconEventBase<'DoubleClick'> & Omit<TrayIconClickEvent, 'buttonState'>)
  | TrayIconEventBase<'Enter'>
  | TrayIconEventBase<'Move'>
  | TrayIconEventBase<'Leave'>

type RustTrayIconEvent = Omit<TrayIconEvent, 'rect'> & {
  rect: {
    position: {
      Physical: { x: number; y: number }
    }
Repository: tauri-apps/tauri
File: crates/tauri/src/tray/mod.rs (Rust)

Code before:
  /// Get tray icon rect.
  ///
  /// ## Platform-specific:
  ///
  /// - **Linux**: Unsupported, always returns `None`.
  pub fn rect(&self) -> crate::Result<Option<crate::Rect>> {
    run_item_main_thread!(self, |self_: Self| self_.inner.rect().map(|rect| {
      Rect {
        position: rect.position.into(),
        size: rect.size.into(),
      }
    }))
  }
}

impl<R: Runtime> Resource for TrayIcon<R> {
  fn close(self: std::sync::Arc<Self>) {
    self.app_handle.remove_tray_by_id(&self.id);
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn tray_event_json_serialization() {
    // NOTE: if this is test is ever changed, you probably need to change `TrayIconEvent` in JS as well

    use super::*;
    let event = TrayIconEvent::Click {
      button: MouseButton::Left,
      button_state: MouseButtonState::Down,
      id: TrayIconId::new("id"),
      position: crate::PhysicalPosition::default(),
      rect: crate::Rect {
        position: tray_icon::Rect::default().position.into(),
        size: tray_icon::Rect::default().size.into(),
      },
    };

    let value = serde_json::to_value(&event).unwrap();
    assert_eq!(
      value,
      serde_json::json!({
          "type": "Click",
          "button": "Left",
          "buttonState": "Down",
          "id": "id",
          "position": {
              "x": 0.0,
              "y": 0.0,
          },

Review comment (suggestion):
```suggestion
    // NOTE: if this test is ever changed, you probably need to change `TrayIconEvent` in JS as well
```

Code after:
  /// Get tray icon rect.
  ///
  /// ## Platform-specific:
  ///
  /// - **Linux**: Unsupported, always returns `None`.
  pub fn rect(&self) -> crate::Result<Option<crate::Rect>> {
    run_item_main_thread!(self, |self_: Self| self_.inner.rect().map(|rect| {
      Rect {
        position: rect.position.into(),
        size: rect.size.into(),
      }
    }))
  }
}

impl<R: Runtime> Resource for TrayIcon<R> {
  fn close(self: std::sync::Arc<Self>) {
    self.app_handle.remove_tray_by_id(&self.id);
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn tray_event_json_serialization() {
    // NOTE: if this test is ever changed, you probably need to change `TrayIconEvent` in JS as well

    use super::*;
    let event = TrayIconEvent::Click {
      button: MouseButton::Left,
      button_state: MouseButtonState::Down,
      id: TrayIconId::new("id"),
      position: crate::PhysicalPosition::default(),
      rect: crate::Rect {
        position: tray_icon::Rect::default().position.into(),
        size: tray_icon::Rect::default().size.into(),
      },
    };

    let value = serde_json::to_value(&event).unwrap();
    assert_eq!(
      value,
      serde_json::json!({
          "type": "Click",
          "button": "Left",
          "buttonState": "Down",
          "id": "id",
          "position": {
              "x": 0.0,
              "y": 0.0,
          },
Repository: tauri-apps/tauri
File: core/tauri/src/window.rs (Rust)

Code before:
      manager.eval_script_all(format!(
        "window.__TAURI_METADATA__.__windows = {window_labels_array}.map(function (label) {{ return {{ label: label }} }})",
        window_labels_array = serde_json::to_string(&manager.labels())?,
      ))?;

      manager.emit_filter(
        "tauri://window-created",
        None,
        Some(WindowCreatedEvent {
          label: label.clone(),
        }),
        |w| w.label() != label,
      )?;

      crate::Result::Ok(())
    };

    if cfg!(feature = "tracing") {
      std::thread::spawn(move || {
        if let Err(e) = window_created_hook() {
          log::error!("failed to trigger window creation hooks: {e}");
        }
      });
    } else {
      window_created_hook()?;
    }

    Ok(window)
  }

  // --------------------------------------------- Window builder ---------------------------------------------

  /// Sets the menu for the window.
  #[must_use]
  pub fn menu(mut self, menu: Menu) -> Self {
    self.window_builder = self.window_builder.menu(menu);
    self
  }

  /// Show window in the center of the screen.
  #[must_use]
  pub fn center(mut self) -> Self {
    self.window_builder = self.window_builder.center();
    self
  }

  /// The initial position of the window's.
  #[must_use]
  pub fn position(mut self, x: f64, y: f64) -> Self {
    self.window_builder = self.window_builder.position(x, y);
    self

Review comment (bug):
```suggestion
    #[cfg(not(feature = "tracing")]
    window_created_hook()?;
    #[cfg(feature = "tracing")]
    std::thread::spawn(move || {
      if let Err(e) = window_created_hook() {
        log::error!("failed to trigger window creation hooks: {e}");
      }
    });
```

Code after:
      manager.eval_script_all(format!(
        "window.__TAURI_METADATA__.__windows = {window_labels_array}.map(function (label) {{ return {{ label: label }} }})",
        window_labels_array = serde_json::to_string(&manager.labels())?,
      ))?;

      manager.emit_filter(
        "tauri://window-created",
        None,
        Some(WindowCreatedEvent {
          label: label.clone(),
        }),
        |w| w.label() != label,
      )?;

      crate::Result::Ok(())
    };

    #[cfg(not(feature = "tracing"))]
    window_created_hook()?;
    #[cfg(feature = "tracing")]
    std::thread::spawn(move || {
      if let Err(e) = window_created_hook() {
        log::error!("failed to trigger window creation hooks: {e}");
      }
    });

    Ok(window)
  }

  // --------------------------------------------- Window builder ---------------------------------------------

  /// Sets the menu for the window.
  #[must_use]
  pub fn menu(mut self, menu: Menu) -> Self {
    self.window_builder = self.window_builder.menu(menu);
    self
  }

  /// Show window in the center of the screen.
  #[must_use]
  pub fn center(mut self) -> Self {
    self.window_builder = self.window_builder.center();
    self
  }

  /// The initial position of the window's.
  #[must_use]
  pub fn position(mut self, x: f64, y: f64) -> Self {
    self.window_builder = self.window_builder.position(x, y);
    self
  }
Repository: tauri-apps/tauri
File: crates/tauri-cli/src/remove.rs (Rust)

Code before:
    .desktop_only
    .then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#)
    .or_else(|| {
      metadata
        .mobile_only
        .then_some(r#"cfg(any(target_os = "android", target_os = "ios"))"#)
    });

  cargo::uninstall_one(cargo::CargoUninstallOptions {
    name: &crate_name,
    cwd: Some(tauri_dir),
    target: target_str,
  })?;

  if !metadata.rust_only {
    if let Some(manager) = app_dir
      .map(PackageManager::from_project)
      .and_then(|managers| managers.into_iter().next())
    {
      let npm_name = format!("@tauri-apps/plugin-{plugin}");
      manager.remove(&[npm_name], tauri_dir)?;
    }

    let _ = acl::permission::rm::command(acl::permission::rm::Options {
      identifier: format!("{plugin}:default"),
    });
  }

  log::info!("Now, you must manually remove the plugin from your Rust code.",);

  Ok(())
}


Review comment (bug):
We shouldn't ignore the error here and instead propagate it.

Also there maybe other permissions used that is not necissarily `{plugin}:default`, we should remove these as well.

Code after:
    .desktop_only
    .then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#)
    .or_else(|| {
      metadata
        .mobile_only
        .then_some(r#"cfg(any(target_os = "android", target_os = "ios"))"#)
    });

  cargo::uninstall_one(cargo::CargoUninstallOptions {
    name: &crate_name,
    cwd: Some(tauri_dir),
    target: target_str,
  })?;

  if !metadata.rust_only {
    if let Some(manager) = frontend_dir.map(PackageManager::from_project) {
      let npm_name = format!("@tauri-apps/plugin-{plugin}");
      manager.remove(&[npm_name], tauri_dir)?;
    }

    acl::permission::rm::command(acl::permission::rm::Options {
      identifier: format!("{plugin}:*"),
    })?;
  }

  log::info!("Now, you must manually remove the plugin from your Rust code.",);

  Ok(())
}
Repository: tauri-apps/tauri
File: crates/tauri-cli/src/remove.rs (Rust)

Code before:
    .desktop_only
    .then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#)
    .or_else(|| {
      metadata
        .mobile_only
        .then_some(r#"cfg(any(target_os = "android", target_os = "ios"))"#)
    });

  cargo::uninstall_one(cargo::CargoUninstallOptions {
    name: &crate_name,
    cwd: Some(tauri_dir),
    target: target_str,
  })?;

  if !metadata.rust_only {
    if let Some(manager) = app_dir
      .map(PackageManager::from_project)
      .and_then(|managers| managers.into_iter().next())
    {
      let npm_name = format!("@tauri-apps/plugin-{plugin}");
      manager.remove(&[npm_name], tauri_dir)?;
    }

    let _ = acl::permission::rm::command(acl::permission::rm::Options {
      identifier: format!("{plugin}:*"),
    });
  }

  log::info!("Now, you must manually remove the plugin from your Rust code.",);

  Ok(())
}


Review comment (security):
we should propagate the error not silence it

```suggestion
    acl::permission::rm::command(acl::permission::rm::Options {
      identifier: format!("{plugin}:*"),
    })?;
```

Code after:
    .desktop_only
    .then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#)
    .or_else(|| {
      metadata
        .mobile_only
        .then_some(r#"cfg(any(target_os = "android", target_os = "ios"))"#)
    });

  cargo::uninstall_one(cargo::CargoUninstallOptions {
    name: &crate_name,
    cwd: Some(tauri_dir),
    target: target_str,
  })?;

  if !metadata.rust_only {
    if let Some(manager) = frontend_dir.map(PackageManager::from_project) {
      let npm_name = format!("@tauri-apps/plugin-{plugin}");
      manager.remove(&[npm_name], tauri_dir)?;
    }

    acl::permission::rm::command(acl::permission::rm::Options {
      identifier: format!("{plugin}:*"),
    })?;
  }

  log::info!("Now, you must manually remove the plugin from your Rust code.",);

  Ok(())
}