Repository: tauri-apps/tauri
File: crates/tauri-cli/src/info/plugins.rs (Rust)

Code before:
        .keys()
        .map(|plugin_name| format!("tauri-plugin-{plugin_name}")),
    )
    .collect();
  let npm_names: Vec<String> = iter::once("@tauri-apps/api".to_owned())
    .chain(
      know_plugins
        .keys()
        .map(|plugin_name| format!("@tauri-apps/plugin-{plugin_name}")),
    )
    .collect();

  let (manifest, lock) = cargo_manifest_and_lock(tauri_dir);

  let mut rust_plugins: HashMap<String, semver::Version> = crate_names
    .iter()
    .filter_map(|crate_name| {
      let crate_version =
        crate_version(tauri_dir, manifest.as_ref(), lock.as_ref(), crate_name).version?;
      let crate_version = semver::Version::parse(&crate_version)
        .inspect_err(|_| {
          // On first run there's no lockfile yet so we get the version requirement from Cargo.toml
          // In our templates that's `2` which is not a valid semver version but a version requirement.
          // We only print a warning if the version requirement is invalid but cargo will complain as well.
          if semver::VersionReq::parse(&crate_version).is_err() {
            log::error!("Failed to parse version `{crate_version}` for crate `{crate_name}`");
          }
        })
        .ok()?;
      Some((crate_name.clone(), crate_version))
    })
    .collect();

  let mut npm_plugins = package_manager
    .current_package_versions(&npm_names, frontend_dir)
    .unwrap_or_default();

  let installed_plugins = crate_names
    .iter()
    .zip(npm_names.iter())
    .filter_map(|(crate_name, npm_name)| {
      let (crate_name, crate_version) = rust_plugins.remove_entry(crate_name)?;
      let (npm_name, npm_version) = npm_plugins.remove_entry(npm_name)?;
      Some(InstalledPackage {
        npm_name,
        npm_version,
        crate_name,
        crate_version,
      })
    })
    .collect();

Review comment (bug):
I kinda feel like we might want to lower those warnings to `debug` level

Code after:
        .keys()
        .map(|plugin_name| format!("tauri-plugin-{plugin_name}")),
    )
    .collect();
  let npm_names: Vec<String> = iter::once("@tauri-apps/api".to_owned())
    .chain(
      know_plugins
        .keys()
        .map(|plugin_name| format!("@tauri-apps/plugin-{plugin_name}")),
    )
    .collect();

  let (manifest, lock) = cargo_manifest_and_lock(tauri_dir);

  let mut rust_plugins: HashMap<String, semver::Version> = crate_names
    .iter()
    .filter_map(|crate_name| {
      let crate_version =
        crate_version(tauri_dir, manifest.as_ref(), lock.as_ref(), crate_name).version?;
      let crate_version = semver::Version::parse(&crate_version)
        .inspect_err(|_| {
          // On first run there's no lockfile yet so we get the version requirement from Cargo.toml.
          // In our templates that's `2` which is not a valid semver version but a version requirement.
          // log::error confused users so we use log::debug to still be able to see this error if needed.
          log::debug!("Failed to parse version `{crate_version}` for crate `{crate_name}`");
        })
        .ok()?;
      Some((crate_name.clone(), crate_version))
    })
    .collect();

  let mut npm_plugins = package_manager
    .current_package_versions(&npm_names, frontend_dir)
    .unwrap_or_default();

  let installed_plugins = crate_names
    .iter()
    .zip(npm_names.iter())
    .filter_map(|(crate_name, npm_name)| {
      let (crate_name, crate_version) = rust_plugins.remove_entry(crate_name)?;
      let (npm_name, npm_version) = npm_plugins.remove_entry(npm_name)?;
      Some(InstalledPackage {
        npm_name,
        npm_version,
        crate_name,
        crate_version,
      })
    })
    .collect();

  InstalledPackages(installed_plugins)