Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cmd.exe detection heuristic #2226

Merged
merged 3 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions crates/uv/src/commands/venv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,14 @@ async fn venv_impl(
"source {}",
shlex_posix(path.join("bin").join("activate.csh"))
)),
Some(Shell::Powershell) => Some(shlex_windows(path.join("Scripts").join("activate"))),
Some(Shell::Powershell) => Some(shlex_windows(
path.join("Scripts").join("activate"),
Shell::Powershell,
)),
Some(Shell::Cmd) => Some(shlex_windows(
path.join("Scripts").join("activate"),
Shell::Cmd,
)),
};
if let Some(act) = activation {
writeln!(printer, "Activate with: {}", act.green()).into_diagnostic()?;
Expand All @@ -254,15 +261,20 @@ fn shlex_posix(executable: impl AsRef<Path>) -> String {
}
}

/// Quote a path, if necessary, for safe use in `PowerShell`.
fn shlex_windows(executable: impl AsRef<Path>) -> String {
/// Quote a path, if necessary, for safe use in `PowerShell` and `cmd`.
fn shlex_windows(executable: impl AsRef<Path>, shell: Shell) -> String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should just merge shlex_posix and shlex_windows, and pass in Shell to toggle the behavior -- wdyt?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda like the separation between Posix and Windows, but I'm biased 😆

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good :)

// Convert to a display path.
let executable = executable.as_ref().simplified_display().to_string();

// Wrap the executable in quotes (and a `&` invocation) if it contains spaces.
// TODO(charlie): This won't work in `cmd.exe`.
// Wrap the executable in quotes (and a `&` invocation on PowerShell), if it contains spaces.
if executable.contains(' ') {
format!("& \"{executable}\"")
if shell == Shell::Powershell {
// For PowerShell, wrap in a `&` invocation.
format!("& \"{executable}\"")
} else {
// Otherwise, assume `cmd`, which doesn't need the `&`.
format!("\"{executable}\"")
}
} else {
executable
}
Expand Down
11 changes: 10 additions & 1 deletion crates/uv/src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub(crate) enum Shell {
Fish,
/// PowerShell
Powershell,
/// Cmd (Command Prompt)
Cmd,
/// Z SHell (zsh)
Zsh,
/// Nushell
Expand All @@ -34,7 +36,14 @@ impl Shell {
} else if let Some(env_shell) = std::env::var_os("SHELL") {
Shell::from_shell_path(env_shell)
} else if cfg!(windows) {
Some(Shell::Powershell)
// Command Prompt relies on PROMPT for its appearance whereas PowerShell does not.
// See: https://stackoverflow.com/a/66415037.
if std::env::var_os("PROMPT").is_some() {
Some(Shell::Cmd)
} else {
// Fallback to PowerShell if the PROMPT environment variable is not set.
Some(Shell::Powershell)
}
} else {
None
}
Expand Down