Add --no-annotate and --no-header flags (#1117)

Closes #1107.
Closes #1108.
This commit is contained in:
Charlie Marsh 2024-01-26 04:14:18 -08:00 committed by GitHub
parent 7755f986c3
commit 361a2039d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 159 additions and 41 deletions

View file

@ -224,21 +224,29 @@ pub struct DisplayResolutionGraph<'a> {
resolution: &'a ResolutionGraph,
/// Whether to include hashes in the output.
show_hashes: bool,
}
impl<'a> DisplayResolutionGraph<'a> {
/// Create a new [`DisplayResolutionGraph`] for the given graph.
pub fn new(underlying: &'a ResolutionGraph, show_hashes: bool) -> DisplayResolutionGraph<'a> {
Self {
resolution: underlying,
show_hashes,
}
}
/// Whether to include annotations in the output, to indicate which dependency or dependencies
/// requested each package.
include_annotations: bool,
}
impl<'a> From<&'a ResolutionGraph> for DisplayResolutionGraph<'a> {
fn from(resolution: &'a ResolutionGraph) -> Self {
Self::new(resolution, false)
Self::new(resolution, false, true)
}
}
impl<'a> DisplayResolutionGraph<'a> {
/// Create a new [`DisplayResolutionGraph`] for the given graph.
pub fn new(
underlying: &'a ResolutionGraph,
show_hashes: bool,
include_annotations: bool,
) -> DisplayResolutionGraph<'a> {
Self {
resolution: underlying,
show_hashes,
include_annotations,
}
}
}
@ -281,26 +289,28 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
}
writeln!(f)?;
// Display all dependencies.
let mut edges = self
.resolution
.petgraph
.edges_directed(index, Direction::Incoming)
.map(|edge| &self.resolution.petgraph[edge.source()])
.collect::<Vec<_>>();
edges.sort_unstable_by_key(|package| package.name());
if self.include_annotations {
// Display all dependencies.
let mut edges = self
.resolution
.petgraph
.edges_directed(index, Direction::Incoming)
.map(|edge| &self.resolution.petgraph[edge.source()])
.collect::<Vec<_>>();
edges.sort_unstable_by_key(|package| package.name());
match edges.len() {
0 => {}
1 => {
for dependency in edges {
writeln!(f, "{}", format!(" # via {}", dependency.name()).green())?;
match edges.len() {
0 => {}
1 => {
for dependency in edges {
writeln!(f, "{}", format!(" # via {}", dependency.name()).green())?;
}
}
}
_ => {
writeln!(f, "{}", " # via".green())?;
for dependency in edges {
writeln!(f, "{}", format!(" # {}", dependency.name()).green())?;
_ => {
writeln!(f, "{}", " # via".green())?;
for dependency in edges {
writeln!(f, "{}", format!(" # {}", dependency.name()).green())?;
}
}
}
}

View file

@ -42,7 +42,7 @@ use crate::requirements::{ExtrasSpecification, RequirementsSource, RequirementsS
const VERSION: &str = env!("CARGO_PKG_VERSION");
/// Resolve a set of requirements into a set of pinned versions.
#[allow(clippy::too_many_arguments)]
#[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)]
pub(crate) async fn pip_compile(
requirements: &[RequirementsSource],
constraints: &[RequirementsSource],
@ -53,6 +53,8 @@ pub(crate) async fn pip_compile(
prerelease_mode: PreReleaseMode,
upgrade: Upgrade,
generate_hashes: bool,
include_annotations: bool,
include_header: bool,
index_locations: IndexLocations,
setup_py: SetupPyStrategy,
no_build: bool,
@ -324,21 +326,26 @@ pub(crate) async fn pip_compile(
Box::new(AutoStream::auto(stdout()))
};
writeln!(
writer,
"{}",
format!("# This file was autogenerated by Puffin v{VERSION} via the following command:")
if include_header {
writeln!(
writer,
"{}",
format!(
"# This file was autogenerated by Puffin v{VERSION} via the following command:"
)
.green()
)?;
writeln!(
writer,
"{}",
format!("# puffin {}", env::args().skip(1).join(" ")).green()
)?;
)?;
writeln!(
writer,
"{}",
format!("# puffin {}", env::args().skip(1).join(" ")).green()
)?;
}
write!(
writer,
"{}",
DisplayResolutionGraph::new(&resolution, generate_hashes)
DisplayResolutionGraph::new(&resolution, generate_hashes, include_annotations)
)?;
Ok(ExitStatus::Success)

View file

@ -200,6 +200,14 @@ struct PipCompileArgs {
#[clap(short, long)]
output_file: Option<PathBuf>,
/// Exclude comment annotations indicating the source of each package.
#[clap(long)]
no_annotate: bool,
/// Exclude the comment header at the top of the generated output file.
#[clap(long)]
no_header: bool,
/// Refresh all cached data.
#[clap(long)]
refresh: bool,
@ -679,6 +687,8 @@ async fn inner() -> Result<ExitStatus> {
args.prerelease,
upgrade,
args.generate_hashes,
!args.no_annotate,
!args.no_header,
index_urls,
if args.legacy_setup_py {
SetupPyStrategy::Setuptools

View file

@ -3697,3 +3697,94 @@ fn missing_package_name() -> Result<()> {
Ok(())
}
/// Exclude annotations from the output.
#[test]
fn no_annotate() -> Result<()> {
let temp_dir = TempDir::new()?;
let cache_dir = TempDir::new()?;
let venv = create_venv_py312(&temp_dir, &cache_dir);
let requirements_in = temp_dir.child("requirements.in");
requirements_in.write_str("black==23.10.1")?;
insta::with_settings!({
filters => INSTA_FILTERS.to_vec()
}, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.arg("pip")
.arg("compile")
.arg("requirements.in")
.arg("--no-annotate")
.arg("--cache-dir")
.arg(cache_dir.path())
.arg("--exclude-newer")
.arg(EXCLUDE_NEWER)
.env("VIRTUAL_ENV", venv.as_os_str())
.current_dir(&temp_dir), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by Puffin v[VERSION] via the following command:
# puffin pip compile requirements.in --no-annotate --cache-dir [CACHE_DIR]
black==23.10.1
click==8.1.7
mypy-extensions==1.0.0
packaging==23.2
pathspec==0.11.2
platformdirs==4.0.0
----- stderr -----
Resolved 6 packages in [TIME]
"###);
});
Ok(())
}
/// Exclude header from the output.
#[test]
fn no_header() -> Result<()> {
let temp_dir = TempDir::new()?;
let cache_dir = TempDir::new()?;
let venv = create_venv_py312(&temp_dir, &cache_dir);
let requirements_in = temp_dir.child("requirements.in");
requirements_in.write_str("black==23.10.1")?;
insta::with_settings!({
filters => INSTA_FILTERS.to_vec()
}, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.arg("pip")
.arg("compile")
.arg("requirements.in")
.arg("--no-header")
.arg("--cache-dir")
.arg(cache_dir.path())
.arg("--exclude-newer")
.arg(EXCLUDE_NEWER)
.env("VIRTUAL_ENV", venv.as_os_str())
.current_dir(&temp_dir), @r###"
success: true
exit_code: 0
----- stdout -----
black==23.10.1
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==23.2
# via black
pathspec==0.11.2
# via black
platformdirs==4.0.0
# via black
----- stderr -----
Resolved 6 packages in [TIME]
"###);
});
Ok(())
}