mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Accept multiple input files in pip-sync and pip-compile (#140)
Closes https://github.com/astral-sh/puffin/issues/126.
This commit is contained in:
parent
7ef6c0315c
commit
385345807c
4 changed files with 51 additions and 38 deletions
|
@ -1,43 +1,33 @@
|
|||
use fs_err::File;
|
||||
use std::fmt::Write;
|
||||
use std::io::{stdout, BufWriter};
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use fs_err::File;
|
||||
use itertools::Itertools;
|
||||
use owo_colors::OwoColorize;
|
||||
use pubgrub::report::Reporter;
|
||||
use tracing::debug;
|
||||
|
||||
use pep508_rs::Requirement;
|
||||
use platform_host::Platform;
|
||||
use platform_tags::Tags;
|
||||
use puffin_client::PypiClientBuilder;
|
||||
use puffin_interpreter::PythonExecutable;
|
||||
use puffin_package::requirements_txt::RequirementsTxt;
|
||||
|
||||
use crate::commands::{elapsed, ExitStatus};
|
||||
use crate::printer::Printer;
|
||||
use crate::requirements::RequirementsSource;
|
||||
|
||||
/// Resolve a set of requirements into a set of pinned versions.
|
||||
pub(crate) async fn pip_compile(
|
||||
src: &Path,
|
||||
sources: &[RequirementsSource],
|
||||
output_file: Option<&Path>,
|
||||
cache: Option<&Path>,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
// Read the `requirements.txt` from disk.
|
||||
let requirements_txt = RequirementsTxt::parse(src, std::env::current_dir()?)?;
|
||||
let requirements = requirements_txt
|
||||
.requirements
|
||||
.into_iter()
|
||||
.map(|entry| entry.requirement)
|
||||
.collect::<Vec<_>>();
|
||||
if requirements.is_empty() {
|
||||
writeln!(printer, "No requirements found")?;
|
||||
return Ok(ExitStatus::Success);
|
||||
}
|
||||
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
let python = PythonExecutable::from_env(platform, cache)?;
|
||||
|
@ -46,6 +36,13 @@ pub(crate) async fn pip_compile(
|
|||
python.executable().display()
|
||||
);
|
||||
|
||||
// Read all requirements from the provided sources.
|
||||
let requirements = sources
|
||||
.iter()
|
||||
.map(RequirementsSource::requirements)
|
||||
.flatten_ok()
|
||||
.collect::<Result<Vec<Requirement>>>()?;
|
||||
|
||||
// Determine the current environment markers.
|
||||
let markers = python.markers();
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use anyhow::{Context, Result};
|
||||
use itertools::Itertools;
|
||||
use owo_colors::OwoColorize;
|
||||
use tracing::debug;
|
||||
|
@ -16,7 +16,6 @@ use puffin_installer::{
|
|||
};
|
||||
use puffin_interpreter::PythonExecutable;
|
||||
use puffin_package::package_name::PackageName;
|
||||
use puffin_package::requirements_txt::RequirementsTxt;
|
||||
use puffin_resolver::Resolution;
|
||||
|
||||
use crate::commands::reporters::{
|
||||
|
@ -24,23 +23,21 @@ use crate::commands::reporters::{
|
|||
};
|
||||
use crate::commands::{elapsed, ExitStatus};
|
||||
use crate::printer::Printer;
|
||||
use crate::requirements::RequirementsSource;
|
||||
|
||||
/// Install a set of locked requirements into the current Python environment.
|
||||
pub(crate) async fn pip_sync(
|
||||
src: &Path,
|
||||
sources: &[RequirementsSource],
|
||||
cache: Option<&Path>,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
// Read the `requirements.txt` from disk.
|
||||
let requirements_txt = RequirementsTxt::parse(src, std::env::current_dir()?)?;
|
||||
if !requirements_txt.constraints.is_empty() {
|
||||
bail!("Constraints in requirements.txt are not supported");
|
||||
}
|
||||
let requirements = requirements_txt
|
||||
.requirements
|
||||
.into_iter()
|
||||
.map(|entry| entry.requirement)
|
||||
.collect::<Vec<_>>();
|
||||
// Read all requirements from the provided sources.
|
||||
let requirements = sources
|
||||
.iter()
|
||||
.map(RequirementsSource::requirements)
|
||||
.flatten_ok()
|
||||
.collect::<Result<Vec<Requirement>>>()?;
|
||||
|
||||
if requirements.is_empty() {
|
||||
writeln!(printer, "No requirements found")?;
|
||||
return Ok(ExitStatus::Success);
|
||||
|
|
|
@ -55,17 +55,20 @@ enum Commands {
|
|||
|
||||
#[derive(Args)]
|
||||
struct PipCompileArgs {
|
||||
/// Output `requirements.txt` file
|
||||
/// Include all packages listed in the given `requirements.in` files.
|
||||
#[clap(required(true))]
|
||||
src_file: Vec<PathBuf>,
|
||||
|
||||
/// Write the compiled requirements to the given `requirements.txt` file.
|
||||
#[clap(short, long)]
|
||||
output_file: Option<PathBuf>,
|
||||
/// Path to the `requirements.txt` file to compile.
|
||||
src: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
struct PipSyncArgs {
|
||||
/// Path to the `requirements.txt` file to install.
|
||||
src: PathBuf,
|
||||
/// Include all packages listed in the given `requirements.txt` files.
|
||||
#[clap(required(true))]
|
||||
src_file: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
@ -121,12 +124,16 @@ async fn main() -> ExitCode {
|
|||
printer::Printer::Default
|
||||
};
|
||||
|
||||
let dirs = ProjectDirs::from("", "", "puffin");
|
||||
|
||||
let result = match cli.command {
|
||||
Commands::PipCompile(args) => {
|
||||
let dirs = ProjectDirs::from("", "", "puffin");
|
||||
let sources = args
|
||||
.src_file
|
||||
.into_iter()
|
||||
.map(RequirementsSource::from)
|
||||
.collect::<Vec<_>>();
|
||||
commands::pip_compile(
|
||||
&args.src,
|
||||
&sources,
|
||||
args.output_file.as_deref(),
|
||||
dirs.as_ref()
|
||||
.map(ProjectDirs::cache_dir)
|
||||
|
@ -136,8 +143,14 @@ async fn main() -> ExitCode {
|
|||
.await
|
||||
}
|
||||
Commands::PipSync(args) => {
|
||||
let dirs = ProjectDirs::from("", "", "puffin");
|
||||
let sources = args
|
||||
.src_file
|
||||
.into_iter()
|
||||
.map(RequirementsSource::from)
|
||||
.collect::<Vec<_>>();
|
||||
commands::pip_sync(
|
||||
&args.src,
|
||||
&sources,
|
||||
dirs.as_ref()
|
||||
.map(ProjectDirs::cache_dir)
|
||||
.filter(|_| !cli.no_cache),
|
||||
|
@ -146,6 +159,7 @@ async fn main() -> ExitCode {
|
|||
.await
|
||||
}
|
||||
Commands::PipUninstall(args) => {
|
||||
let dirs = ProjectDirs::from("", "", "puffin");
|
||||
let sources = args
|
||||
.package
|
||||
.into_iter()
|
||||
|
@ -162,9 +176,11 @@ async fn main() -> ExitCode {
|
|||
.await
|
||||
}
|
||||
Commands::Clean => {
|
||||
let dirs = ProjectDirs::from("", "", "puffin");
|
||||
commands::clean(dirs.as_ref().map(ProjectDirs::cache_dir), printer).await
|
||||
}
|
||||
Commands::Freeze => {
|
||||
let dirs = ProjectDirs::from("", "", "puffin");
|
||||
commands::freeze(
|
||||
dirs.as_ref()
|
||||
.map(ProjectDirs::cache_dir)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{bail, Result};
|
||||
use itertools::Either;
|
||||
|
||||
use pep508_rs::Requirement;
|
||||
|
@ -37,6 +37,9 @@ impl RequirementsSource {
|
|||
}
|
||||
Self::Path(path) => {
|
||||
let requirements_txt = RequirementsTxt::parse(path, std::env::current_dir()?)?;
|
||||
if !requirements_txt.constraints.is_empty() {
|
||||
bail!("Constraints in requirements files are not supported");
|
||||
}
|
||||
Ok(Either::Right(
|
||||
requirements_txt
|
||||
.requirements
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue