Repository: tauri-apps/tauri
File: crates/tauri-utils/src/acl/build.rs (Rust)

Code before:
  println!("cargo:rerun-if-env-changed=TAURI_CONFIG");

  // Set working directory to where `tauri.config.json` is, so that relative paths in it are parsed correctly.
  let old_cwd = std::env::current_dir()?;
  std::env::set_current_dir(config_directory)?;

  let config: Config = serde_json::from_value(config)?;

  // Reset working directory.
  std::env::set_current_dir(old_cwd)?;

  let acl: BTreeMap<String, crate::acl::manifest::Manifest> = permissions_map
    .into_iter()
    .map(|(key, permissions)| {
      let key = key
        .strip_prefix("tauri-plugin-")
        .unwrap_or(&key)
        .to_string();
      let manifest = crate::acl::manifest::Manifest::new(permissions, None);
      (key, manifest)
    })
    .collect();

  let capabilities_file_path = out_dir.join(CAPABILITIES_FILE_NAME);
  // the capabilities file only exist in the tauri-build context
  if !capabilities_file_path.exists() {
    let capabilities = crate::acl::build::parse_capabilities(&format!(
      "{}/**/*",
      glob::Pattern::escape(&capabilities_path.to_string_lossy())
    ))?;
    // write to capabilities path because we still want to go through acl::get_capabilities because it filters based on the config
    std::fs::write(
      &capabilities_file_path,
      serde_json::to_string(&capabilities)?,
    )?;
  }
  let capabilities = crate::acl::get_capabilities(&config, &capabilities_file_path, None)?;

  let permission_entries = capabilities
    .clone()
    .into_iter()
    .flat_map(|(_, capabilities)| capabilities.permissions);
  let mut allowed_commands = AllowedCommands {
    has_app_acl: has_app_manifest(&acl),
    ..Default::default()
  };
  for permission_entry in permission_entries {
    let Ok(permissions) =
      crate::acl::resolved::get_permissions(permission_entry.identifier(), &acl)
    else {
      continue;

Review comment (bug):
Would this call be a problem when the build script re-runs? I think maybe we could move back the 

```rust
  if let Some(capabilities_file_path) = pre_built_capabilities_file_path {
    if capabilities_file_path.exists() {
      let capabilities_file =
        std::fs::read_to_string(capabilities_file_path).context("failed to read capabilities")?;
      capabilities_from_files =
        serde_json::from_str(&capabilities_file).context("failed to parse capabilities")?;
    }
  }
```

part to `tauri-codegen`, and replace `pre_built_capabilities_file_path` param with `capabilities_from_files: BTreeMap<String, Capability>`, and we don't have to save the files here (this file should only be used for passing the data from `tauri-build` to `tauri-codegen` right? (maybe we should document this, I'm having a hard time revisiting this code 😂))

Code after:

  println!("cargo:rerun-if-env-changed=TAURI_CONFIG");

  // Set working directory to where `tauri.config.json` is, so that relative paths in it are parsed correctly.
  let old_cwd = std::env::current_dir()?;
  std::env::set_current_dir(config_directory)?;

  let config: Config = serde_json::from_value(config)?;

  // Reset working directory.
  std::env::set_current_dir(old_cwd)?;

  let acl: BTreeMap<String, crate::acl::manifest::Manifest> = permissions_map
    .into_iter()
    .map(|(key, permissions)| {
      let key = key
        .strip_prefix("tauri-plugin-")
        .unwrap_or(&key)
        .to_string();
      let manifest = crate::acl::manifest::Manifest::new(permissions, None);
      (key, manifest)
    })
    .collect();

  let capabilities_from_files = if let Some(capabilities) = capabilities_from_files {
    capabilities
  } else {
    crate::acl::build::parse_capabilities(&format!(
      "{}/**/*",
      glob::Pattern::escape(&capabilities_path.to_string_lossy())
    ))?
  };
  let capabilities = crate::acl::get_capabilities(&config, capabilities_from_files, None)?;

  let permission_entries = capabilities
    .into_iter()
    .flat_map(|(_, capabilities)| capabilities.permissions);
  let mut allowed_commands = AllowedCommands {
    has_app_acl: has_app_manifest(&acl),
    ..Default::default()
  };
  for permission_entry in permission_entries {
    let Ok(permissions) =
      crate::acl::resolved::get_permissions(permission_entry.identifier(), &acl)
    else {
      continue;
    };
    for permission in permissions {
      let plugin_name = permission.key;
      let allowed_command_names = &permission.permission.commands.allow;
      for allowed_command in allowed_command_names {