Repository: tauri-apps/tauri
File: tooling/bundler/src/bundle.rs (Rust)

Code before:
      #[cfg(target_os = "linux")]
      PackageType::Deb => linux::debian::bundle_project(&settings)?,
      #[cfg(target_os = "linux")]
      PackageType::Rpm => linux::rpm::bundle_project(&settings)?,
      #[cfg(target_os = "linux")]
      PackageType::AppImage => linux::appimage::bundle_project(&settings)?,

      // updater is dependant of multiple bundle, we send our bundles to prevent rebuilding
      PackageType::Updater => updater_bundle::bundle_project(&settings, &bundles)?,
      _ => {
        warn!("ignoring {:?}", package_type);
        continue;
      }
    };

    bundles.push(Bundle {
      package_type: package_type.to_owned(),
      bundle_paths,
    });
  }

  #[cfg(target_os = "macos")]
  {
    // Clean up .app if only building dmg or updater
    if !package_types.contains(&PackageType::MacOsBundle) {
      if let Some(app_bundle_paths) = bundles
        .iter()
        .position(|b| b.package_type == PackageType::MacOsBundle)
        .map(|i| bundles.remove(i))
        .map(|b| b.bundle_paths)
      {
        for app_bundle_path in &app_bundle_paths {
          info!(action = "Cleaning"; "{}", app_bundle_path.display());
          match app_bundle_path.is_dir() {
            true => std::fs::remove_dir_all(app_bundle_path),
            false => std::fs::remove_file(app_bundle_path),
          }
          .with_context(|| {
            format!(
              "Failed to clean the app bundle at {}",
              app_bundle_path.display()
            )
          })?
        }
      }
    }
  }

  let pluralised = if bundles.len() == 1 {
    "bundle"
  } else {

Review comment (bug):
I have just found out that `package_types` is never updated when a macOS DMG bundle is generated (see lines 77-85). Therefore, the updater bundle will not be generated if the macOS .app bundle is not explicitly set in `package_types`, even though the DMG bundle implies the generation of an app bundle and thus `package_types` does not need to explicitly contain a macOS .app bundle.

I'd suggest adding a `| PackageType::Dmg` branch to the `matches!` macro here to better handle this edge case.

Code after:
      #[cfg(target_os = "windows")]
      PackageType::WindowsMsi => windows::msi::bundle_project(&settings, false)?,
      PackageType::Nsis => windows::nsis::bundle_project(&settings, false)?,

      #[cfg(target_os = "linux")]
      PackageType::Deb => linux::debian::bundle_project(&settings)?,
      #[cfg(target_os = "linux")]
      PackageType::Rpm => linux::rpm::bundle_project(&settings)?,
      #[cfg(target_os = "linux")]
      PackageType::AppImage => linux::appimage::bundle_project(&settings)?,

      // updater is dependant of multiple bundle, we send our bundles to prevent rebuilding
      PackageType::Updater => {
        if !package_types.iter().any(|p| {
          matches!(
            p,
            PackageType::AppImage
              | PackageType::MacOsBundle
              | PackageType::Nsis
              | PackageType::WindowsMsi
          )
        }) {
          warn!("The updater bundle target exists but couldn't find any updater-enabled target, so the updater artifacts won't be generated. Please add one of these targets as well: app, appimage, msi, nsis");
          continue;
        }
        updater_bundle::bundle_project(&settings, &bundles)?
      }
      _ => {
        warn!("ignoring {}", package_type.short_name());
        continue;
      }
    };

    bundles.push(Bundle {
      package_type: package_type.to_owned(),
      bundle_paths,
    });
  }

  #[cfg(target_os = "macos")]
  {
    // Clean up .app if only building dmg or updater
    if !package_types.contains(&PackageType::MacOsBundle) {
      if let Some(app_bundle_paths) = bundles
        .iter()
        .position(|b| b.package_type == PackageType::MacOsBundle)
        .map(|i| bundles.remove(i))
        .map(|b| b.bundle_paths)
      {
        for app_bundle_path in &app_bundle_paths {
          info!(action = "Cleaning"; "{}", app_bundle_path.display());