Skip to content

Commit

Permalink
uv run: List available scripts when a script is not specified
Browse files Browse the repository at this point in the history
Signed-off-by: Kemal Akkoyun <kakkoyun@gmail.com>
  • Loading branch information
kakkoyun committed Sep 25, 2024
1 parent 82e33c2 commit e95ee42
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 4 deletions.
2 changes: 1 addition & 1 deletion crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,7 @@ pub struct RunArgs {
/// If the path to a Python script (i.e., ending in `.py`), it will be
/// executed with the Python interpreter.
#[command(subcommand)]
pub command: ExternalCommand,
pub command: Option<ExternalCommand>,

/// Run with the given packages installed.
///
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod python_version;
mod target;
mod version_files;
mod virtualenv;
mod which;
pub mod which;

#[cfg(not(test))]
pub(crate) fn current_dir() -> Result<std::path::PathBuf, std::io::Error> {
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-python/src/which.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::Path;
/// Check whether a path in PATH is a valid executable.
///
/// Derived from `which`'s `Checker`.
pub(crate) fn is_executable(path: &Path) -> bool {
pub fn is_executable(path: &Path) -> bool {
#[cfg(any(unix, target_os = "wasi", target_os = "redox"))]
{
if rustix::fs::access(path, rustix::fs::Access::EXEC_OK).is_err() {
Expand Down
34 changes: 34 additions & 0 deletions crates/uv/src/commands/project/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use uv_distribution::LoweredRequirement;
use uv_fs::{PythonExt, Simplified};
use uv_installer::{SatisfiesResult, SitePackages};
use uv_normalize::PackageName;
use uv_python::which::is_executable;
use uv_python::{
EnvironmentPreference, Interpreter, PythonDownloads, PythonEnvironment, PythonInstallation,
PythonPreference, PythonRequest, PythonVersionFile, VersionRequest,
Expand Down Expand Up @@ -717,6 +718,39 @@ pub(crate) async fn run(
.as_ref()
.map_or_else(|| &base_interpreter, |env| env.interpreter());

// Check if any run command is given.
// If not, print the available scripts for the current interpreter.
if let RunCommand::Empty = command {
println!(
"available scripts path: {}",
interpreter.scripts().display()
);

interpreter
.scripts()
.read_dir()
.ok()
.into_iter()
.flatten()
.filter_map(|entry| match entry {
Ok(entry) => Some(entry),
Err(err) => {
warn!("Failed to read entry: {}", err);
None
}
})
.filter(|entry| {
entry
.file_type()
.is_ok_and(|file_type| file_type.is_file() || file_type.is_symlink())
})
.map(|entry| entry.path())
.filter(|path| is_executable(path))
.for_each(|path| println!("{}", path.display()));

return Ok(ExitStatus::Success);
};

debug!("Running `{command}`");
let mut process = command.as_command(interpreter);

Expand Down
5 changes: 4 additions & 1 deletion crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
// Parse the external command, if necessary.
let run_command = if let Commands::Project(command) = &*cli.command {
if let ProjectCommand::Run(uv_cli::RunArgs { command, .. }) = &**command {
Some(RunCommand::try_from(command)?)
match command {
Some(command) => Some(RunCommand::try_from(command)?),
None => Some(RunCommand::Empty),
}
} else {
None
}
Expand Down

0 comments on commit e95ee42

Please sign in to comment.