From c46adee48d6babbad9a2293e5f05232ceca6eed4 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jul 2024 19:43:55 -0400 Subject: [PATCH] Make `--directory` a global argument (#5579) ## Summary Cargo makes this global (and uses the same technique). It's still hidden so we can always decide to remove it. --- crates/uv-cli/src/lib.rs | 16 ++++------------ crates/uv/src/commands/project/lock.rs | 12 ++---------- crates/uv/src/commands/project/run.rs | 13 +++---------- crates/uv/src/commands/project/sync.rs | 13 ++----------- crates/uv/src/lib.rs | 8 +++++--- crates/uv/src/settings.rs | 9 --------- crates/uv/tests/run.rs | 6 ++---- 7 files changed, 18 insertions(+), 59 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 2553205039b0..6d4ca7b62f75 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -164,6 +164,10 @@ pub struct GlobalArgs { /// Hides all progress outputs when set #[arg(global = true, long)] pub no_progress: bool, + + /// Change to the given directory prior to running the command. + #[arg(global = true, long, hide = true)] + pub directory: Option, } #[derive(Debug, Copy, Clone, clap::ValueEnum)] @@ -1932,10 +1936,6 @@ pub struct RunArgs { /// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path. #[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)] pub python: Option, - - /// The path to the project. Defaults to the current working directory. - #[arg(long, hide = true)] - pub directory: Option, } #[derive(Args)] @@ -2000,10 +2000,6 @@ pub struct SyncArgs { /// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path. #[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)] pub python: Option, - - /// The path to the project. Defaults to the current working directory. - #[arg(long, hide = true)] - pub directory: Option, } #[derive(Args)] @@ -2039,10 +2035,6 @@ pub struct LockArgs { /// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path. #[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)] pub python: Option, - - /// The path to the project. Defaults to the current working directory. - #[arg(long, hide = true)] - pub directory: Option, } #[derive(Args)] diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index 6088add9f353..1edbbbe94731 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -2,7 +2,6 @@ use std::collections::BTreeSet; use std::fmt::Write; -use std::path::PathBuf; use anstream::eprint; use owo_colors::OwoColorize; @@ -17,7 +16,7 @@ use uv_client::{Connectivity, FlatIndexClient, RegistryClientBuilder}; use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, Reinstall, SetupPyStrategy}; use uv_dispatch::BuildDispatch; use uv_distribution::DEV_DEPENDENCIES; -use uv_fs::{Simplified, CWD}; +use uv_fs::CWD; use uv_git::ResolvedRepositoryReference; use uv_normalize::PackageName; use uv_python::{Interpreter, PythonFetch, PythonPreference, PythonRequest}; @@ -49,7 +48,6 @@ pub(crate) async fn lock( frozen: bool, python: Option, settings: ResolverSettings, - directory: Option, preview: PreviewMode, python_preference: PythonPreference, python_fetch: PythonFetch, @@ -63,14 +61,8 @@ pub(crate) async fn lock( warn_user_once!("`uv lock` is experimental and may change without warning"); } - let directory = if let Some(directory) = directory { - directory.simple_canonicalize()? - } else { - CWD.to_path_buf() - }; - // Find the project requirements. - let workspace = Workspace::discover(&directory, &DiscoveryOptions::default()).await?; + let workspace = Workspace::discover(&CWD, &DiscoveryOptions::default()).await?; // Find an interpreter for the project let interpreter = FoundInterpreter::discover( diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index bcdc1ae74fca..b20dbd22a087 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -44,7 +44,6 @@ pub(crate) async fn run( extras: ExtrasSpecification, dev: bool, python: Option, - directory: Option, settings: ResolverInstallerSettings, isolated: bool, preview: PreviewMode, @@ -90,12 +89,6 @@ pub(crate) async fn run( let reporter = PythonDownloadReporter::single(printer); - let directory = if let Some(directory) = directory { - directory.simple_canonicalize()? - } else { - CWD.to_path_buf() - }; - // Determine whether the command to execute is a PEP 723 script. let script_interpreter = if let RunCommand::Python(target, _) = &command { if let Some(metadata) = uv_scripts::read_pep723_metadata(&target).await? { @@ -109,7 +102,7 @@ pub(crate) async fn run( let python_request = if let Some(request) = python.as_deref() { Some(PythonRequest::parse(request)) // (2) Request from `.python-version` - } else if let Some(request) = request_from_version_file(&directory).await? { + } else if let Some(request) = request_from_version_file(&CWD).await? { Some(request) // (3) `Requires-Python` in `pyproject.toml` } else { @@ -174,13 +167,13 @@ pub(crate) async fn run( // We need a workspace, but we don't need to have a current package, we can be e.g. in // the root of a virtual workspace and then switch into the selected package. Some(VirtualProject::Project( - Workspace::discover(&directory, &DiscoveryOptions::default()) + Workspace::discover(&CWD, &DiscoveryOptions::default()) .await? .with_current_project(package.clone()) .with_context(|| format!("Package `{package}` not found in workspace"))?, )) } else { - match VirtualProject::discover(&directory, &DiscoveryOptions::default()).await { + match VirtualProject::discover(&CWD, &DiscoveryOptions::default()).await { Ok(project) => Some(project), Err(WorkspaceError::MissingPyprojectToml) => None, Err(WorkspaceError::NonWorkspace(_)) => None, diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index 42c64530482f..7726cdb2a4d6 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -1,5 +1,3 @@ -use std::path::PathBuf; - use anyhow::Result; use uv_auth::store_credentials_from_url; @@ -10,7 +8,7 @@ use uv_configuration::{ }; use uv_dispatch::BuildDispatch; use uv_distribution::DEV_DEPENDENCIES; -use uv_fs::{Simplified, CWD}; +use uv_fs::CWD; use uv_installer::SitePackages; use uv_python::{PythonEnvironment, PythonFetch, PythonPreference, PythonRequest}; use uv_resolver::{FlatIndex, Lock}; @@ -37,7 +35,6 @@ pub(crate) async fn sync( python_preference: PythonPreference, python_fetch: PythonFetch, settings: ResolverInstallerSettings, - directory: Option, preview: PreviewMode, connectivity: Connectivity, concurrency: Concurrency, @@ -49,14 +46,8 @@ pub(crate) async fn sync( warn_user_once!("`uv sync` is experimental and may change without warning"); } - let directory = if let Some(directory) = directory { - directory.simple_canonicalize()? - } else { - CWD.to_path_buf() - }; - // Identify the project - let project = VirtualProject::discover(&directory, &DiscoveryOptions::default()).await?; + let project = VirtualProject::discover(&CWD, &DiscoveryOptions::default()).await?; // Discover or create the virtual environment. let venv = project::get_or_init_environment( diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 8c1956b95d1c..3139d978f1ca 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -62,6 +62,11 @@ async fn run(cli: Cli) -> Result { uv_warnings::enable(); } + // Switch directories as early as possible. + if let Some(directory) = cli.global_args.directory.as_ref() { + std::env::set_current_dir(directory)?; + } + // Load configuration from the filesystem, prioritizing (in order): // 1. The configuration file specified on the command-line. // 2. The configuration file in the current workspace (i.e., the `pyproject.toml` or `uv.toml` @@ -915,7 +920,6 @@ async fn run_project( args.extras, args.dev, args.python, - args.directory, args.settings, globals.isolated, globals.preview, @@ -949,7 +953,6 @@ async fn run_project( globals.python_preference, globals.python_fetch, args.settings, - args.directory, globals.preview, globals.connectivity, Concurrency::default(), @@ -972,7 +975,6 @@ async fn run_project( args.frozen, args.python, args.settings, - args.directory, globals.preview, globals.python_preference, globals.python_fetch, diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index f6e014cdb59d..880f3d4f7c2a 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -193,7 +193,6 @@ pub(crate) struct RunSettings { pub(crate) with_requirements: Vec, pub(crate) package: Option, pub(crate) python: Option, - pub(crate) directory: Option, pub(crate) refresh: Refresh, pub(crate) settings: ResolverInstallerSettings, } @@ -218,7 +217,6 @@ impl RunSettings { refresh, package, python, - directory, } = args; Self { @@ -237,7 +235,6 @@ impl RunSettings { .collect(), package, python, - directory, refresh: Refresh::from(refresh), settings: ResolverInstallerSettings::combine( resolver_installer_options(installer, build), @@ -530,7 +527,6 @@ pub(crate) struct SyncSettings { pub(crate) python: Option, pub(crate) refresh: Refresh, pub(crate) settings: ResolverInstallerSettings, - pub(crate) directory: Option, } impl SyncSettings { @@ -550,7 +546,6 @@ impl SyncSettings { build, refresh, python, - directory, } = args; let modifications = if no_clean { @@ -574,7 +569,6 @@ impl SyncSettings { resolver_installer_options(installer, build), filesystem, ), - directory, } } } @@ -588,7 +582,6 @@ pub(crate) struct LockSettings { pub(crate) python: Option, pub(crate) refresh: Refresh, pub(crate) settings: ResolverSettings, - pub(crate) directory: Option, } impl LockSettings { @@ -602,7 +595,6 @@ impl LockSettings { build, refresh, python, - directory, } = args; Self { @@ -611,7 +603,6 @@ impl LockSettings { python, refresh: Refresh::from(refresh), settings: ResolverSettings::combine(resolver_options(resolver, build), filesystem), - directory, } } } diff --git a/crates/uv/tests/run.rs b/crates/uv/tests/run.rs index 0c11785a18a1..ebea994e4a5a 100644 --- a/crates/uv/tests/run.rs +++ b/crates/uv/tests/run.rs @@ -865,9 +865,7 @@ fn run_from_directory() -> Result<()> { .arg("project") .arg("main"); - let mut filters = context.filters(); - filters.push((r"project(\\|/).venv", "[VENV]")); - uv_snapshot!(filters, command_with_args, @r###" + uv_snapshot!(context.filters(), command_with_args, @r###" success: true exit_code: 0 ----- stdout ----- @@ -875,7 +873,7 @@ fn run_from_directory() -> Result<()> { ----- stderr ----- Using Python 3.12.[X] interpreter at: [PYTHON-3.12] - Creating virtualenv at: [VENV] + Creating virtualenv at: .venv Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME]