diff --git a/src/bundler.rs b/src/bundler.rs index 7ecd6fe..d42be10 100644 --- a/src/bundler.rs +++ b/src/bundler.rs @@ -1329,6 +1329,14 @@ fn resolve_output_path( let base_name = custom_name.unwrap_or(app_name); let mut output_path = PathBuf::from(format!("{base_name}{ext}")); + // On Windows, also consider collision with a directory named without extension + if Platform::current().is_windows() { + let dir_collision = PathBuf::from(base_name); + if dir_collision.exists() && dir_collision.is_dir() { + output_path = PathBuf::from(format!("{base_name}-bundle{ext}")); + } + } + let mut counter = 1; while output_path.exists() { if output_path.is_dir() { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 587f3b4..dc16c40 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -751,17 +751,42 @@ impl BundlerTestHelper { executable_path.parent().unwrap().to_path_buf(), ); - let mut cmd = Command::new(&exec_to_run); - - cmd.args(args); - - for (key, value) in env_vars { - cmd.env(key, value); - } - println!("Executing: {} with args: {:?}", exec_to_run.display(), args); - let output = cmd.current_dir(&work_dir).output().with_context(|| { + // First try direct spawn + let direct = { + let mut cmd = Command::new(&exec_to_run); + cmd.args(args); + for (key, value) in env_vars { + cmd.env(key, value); + } + cmd.current_dir(&work_dir).output() + }; + + // If NotFound on Windows, retry via cmd /C + #[cfg(windows)] + let output = match direct { + Ok(o) => Ok(o), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => { + let mut cmd = Command::new("cmd"); + let mut all_args: Vec = Vec::with_capacity(1 + 1 + args.len()); + all_args.push("/C".to_string()); + all_args.push(exec_to_run.display().to_string()); + all_args.extend(args.iter().map(|a| a.to_string())); + let mut c2 = Command::new("cmd"); + c2.args(&all_args).current_dir(&work_dir); + for (key, value) in env_vars { + c2.env(key, value); + } + c2.output() + } + Err(e) => Err(e), + }; + + #[cfg(not(windows))] + let output = direct; + + let output = output.with_context(|| { format!( "Failed to execute command: {}\nArgs: {:?}\nEnv vars: {:?}\nWorking directory: {:?}", exec_to_run.display(), diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 87ade42..1d1abd2 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -411,23 +411,31 @@ async fn test_output_path_collision_handling() -> Result<(), Box>() - ); + candidates.push(temp_dir.path().join("collision-test-app")); + } + let expected_executable = candidates + .into_iter() + .find(|p| p.exists() && p.is_file()) + .ok_or_else(|| { + let dir = temp_dir.path(); + let listing: Vec<_> = std::fs::read_dir(dir) + .unwrap() + .filter_map(Result::ok) + .map(|e| e.file_name()) + .collect(); + anyhow::anyhow!( + "Executable was not created under {}. Directory contents: {:?}", + dir.display(), + listing + ) + })?; // Test that the executable works let output = Command::new(&expected_executable).output()?;