Skip to content

Commit 6bf8152

Browse files
authored
refactor: move recipe generation into it's own crate (#1912)
1 parent 00b7b40 commit 6bf8152

File tree

12 files changed

+327
-119
lines changed

12 files changed

+327
-119
lines changed

Cargo.lock

Lines changed: 34 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
[workspace]
2-
members = ["rust-tests"]
2+
members = ["rust-tests", "crates/rattler_build_recipe_generator"]
3+
4+
[workspace.package]
5+
authors = ["rattler-build contributors <[email protected]>"]
6+
edition = "2024"
7+
license = "BSD-3-Clause"
8+
readme = "README.md"
9+
repository = "https://github.com/prefix-dev/rattler-build"
10+
11+
[workspace.dependencies]
12+
async-once-cell = "0.5.4"
13+
async-recursion = "1.1.1"
14+
clap = { version = "4.5.45", features = ["derive"] }
15+
flate2 = "1.1.2"
16+
fs-err = "3.1.1"
17+
indexmap = "2.11.4"
18+
insta = "1.41.1"
19+
itertools = "0.14.0"
20+
miette = "7.6.0"
21+
rattler_conda_types = { version = "0.40.0", default-features = false }
22+
rattler_digest = { version = "1.1.5", default-features = false, features = [
23+
"serde",
24+
] }
25+
regex = "1.11.1"
26+
reqwest = { version = "0.12.23", default-features = false, features = ["json"] }
27+
serde = { version = "1.0.219", features = ["derive"] }
28+
serde_json = "1.0.142"
29+
serde_with = "3.14.0"
30+
serde_yaml = "0.9.34"
31+
sha2 = "0.10.9"
32+
tar = "0.4.44"
33+
tempfile = "3.21.0"
34+
tokio = { version = "1.47.1", features = ["rt", "macros"] }
35+
toml = "0.9.5"
36+
tracing = "0.1.41"
37+
url = "2.5.4"
38+
zip = { version = "5.1.1", default-features = false, features = ["deflate"] }
339

440
[package]
541
name = "rattler-build"
@@ -39,7 +75,7 @@ tui = [
3975
'throbber-widgets-tui',
4076
'tui-input',
4177
]
42-
recipe-generation = []
78+
recipe-generation = ["rattler_build_recipe_generator"]
4379
# This feature needs to add a dependency on
4480
# clap-markdown = { git = "https://github.com/ruben-arts/clap-markdown", branch = "main" }
4581
# but in order to be able to publish to crates we remove this feature
@@ -193,6 +229,10 @@ http-range-client = { git = "https://github.com/pka/http-range-client.git", defa
193229
sevenz-rust2 = "0.18.0"
194230
dialoguer = "0.12.0"
195231

232+
rattler_build_recipe_generator = { path = "crates/rattler_build_recipe_generator", optional = true, features = [
233+
"cli",
234+
] }
235+
196236
[target.'cfg(not(target_os = "windows"))'.dependencies]
197237
sha2 = { version = "0.10.9", features = ["asm"] }
198238

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[package]
2+
name = "rattler_build_recipe_generator"
3+
version = "0.1.0"
4+
authors.workspace = true
5+
edition.workspace = true
6+
license.workspace = true
7+
repository.workspace = true
8+
description = "Recipe generation for PyPI, CRAN, CPAN, and LuaRocks packages"
9+
10+
[features]
11+
default = []
12+
cli = ["dep:clap"]
13+
14+
[dependencies]
15+
clap = { workspace = true, optional = true }
16+
async-once-cell = { workspace = true }
17+
async-recursion = { workspace = true }
18+
flate2 = { workspace = true }
19+
fs-err = { workspace = true }
20+
indexmap = { workspace = true }
21+
itertools = { workspace = true }
22+
miette = { workspace = true }
23+
rattler_conda_types = { workspace = true }
24+
rattler_digest = { workspace = true }
25+
regex = { workspace = true }
26+
reqwest = { workspace = true }
27+
serde = { workspace = true }
28+
serde_json = { workspace = true }
29+
serde_with = { workspace = true }
30+
serde_yaml = { workspace = true }
31+
sha2 = { workspace = true }
32+
tar = { workspace = true }
33+
tempfile = { workspace = true }
34+
toml = { workspace = true }
35+
tracing = { workspace = true }
36+
url = { workspace = true }
37+
zip = { workspace = true }
38+
39+
[dev-dependencies]
40+
insta = { workspace = true }
41+
tokio = { workspace = true }

src/recipe_generator/cpan.rs renamed to crates/rattler_build_recipe_generator/src/cpan.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[cfg(feature = "cli")]
12
use clap::Parser;
23
use miette::{IntoDiagnostic, WrapErr};
34
use serde::Deserialize;
@@ -9,24 +10,25 @@ use std::{
910
};
1011

1112
use super::write_recipe;
12-
use crate::recipe_generator::serialize::{self, ScriptTest, Test, UrlSourceElement};
13+
use crate::serialize::{self, ScriptTest, Test, UrlSourceElement};
1314

1415
/// Options to control CPAN recipe generation.
15-
#[derive(Debug, Clone, Parser)]
16+
#[derive(Debug, Clone)]
17+
#[cfg_attr(feature = "cli", derive(Parser))]
1618
pub struct CpanOpts {
1719
/// Name of the package to generate
1820
pub package: String,
1921

2022
/// Select a version of the package to generate (defaults to latest)
21-
#[arg(long)]
23+
#[cfg_attr(feature = "cli", arg(long))]
2224
pub version: Option<String>,
2325

2426
/// Whether to write the recipe to a folder
25-
#[arg(short, long)]
27+
#[cfg_attr(feature = "cli", arg(short, long))]
2628
pub write: bool,
2729

2830
/// Whether to generate recipes for all dependencies
29-
#[arg(short, long)]
31+
#[cfg_attr(feature = "cli", arg(short, long))]
3032
pub tree: bool,
3133
}
3234

src/recipe_generator/cran.rs renamed to crates/rattler_build_recipe_generator/src/cran.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
use clap::Parser;
21
use std::{collections::HashMap, collections::HashSet, path::PathBuf};
32

3+
#[cfg(feature = "cli")]
4+
use clap::Parser;
45
use itertools::Itertools;
56
use miette::IntoDiagnostic;
67
use rattler_digest::{Sha256Hash, compute_bytes_digest};
78
use serde::{Deserialize, Serialize};
89
use sha2::Sha256;
910
use url::Url;
1011

11-
use crate::recipe_generator::{
12+
use crate::{
1213
serialize::{self, ScriptTest, Test, UrlSourceElement},
1314
write_recipe,
1415
};
@@ -62,21 +63,22 @@ pub struct Packaged {
6263
}
6364

6465
/// Options to control CRAN/R recipe generation.
65-
#[derive(Debug, Clone, Parser)]
66+
#[derive(Debug, Clone)]
67+
#[cfg_attr(feature = "cli", derive(Parser))]
6668
pub struct CranOpts {
6769
/// The R Universe to fetch the package from (defaults to `cran`)
68-
#[arg(short, long)]
69-
universe: Option<String>,
70+
#[cfg_attr(feature = "cli", arg(short, long))]
71+
pub universe: Option<String>,
7072

7173
/// Whether to create recipes for the whole dependency tree or not
72-
#[arg(short, long)]
73-
tree: bool,
74+
#[cfg_attr(feature = "cli", arg(short, long))]
75+
pub tree: bool,
7476

7577
/// Name of the package to generate
7678
pub package: String,
7779

7880
/// Whether to write the recipe to a folder
79-
#[arg(short, long)]
81+
#[cfg_attr(feature = "cli", arg(short, long))]
8082
pub write: bool,
8183
}
8284

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//! Recipe generation for Python (PyPI), R (CRAN), Perl (CPAN), and Lua (LuaRocks) packages
2+
3+
#[cfg(feature = "cli")]
4+
use clap::Parser;
5+
6+
mod cpan;
7+
mod cran;
8+
mod luarocks;
9+
mod pypi;
10+
mod serialize;
11+
12+
pub use self::cpan::{CpanOpts, generate_cpan_recipe, generate_cpan_recipe_string};
13+
pub use self::cran::{CranOpts, generate_r_recipe, generate_r_recipe_string};
14+
pub use self::luarocks::{LuarocksOpts, generate_luarocks_recipe, generate_luarocks_recipe_string};
15+
pub use self::pypi::{PyPIOpts, generate_pypi_recipe, generate_pypi_recipe_string};
16+
pub use serialize::write_recipe;
17+
18+
/// The source of the package to generate a recipe for
19+
#[cfg(feature = "cli")]
20+
#[derive(Debug, Clone, Parser)]
21+
pub enum Source {
22+
/// Generate a recipe for a Python package from PyPI
23+
Pypi(PyPIOpts),
24+
25+
/// Generate a recipe for an R package from CRAN
26+
Cran(CranOpts),
27+
28+
/// Generate a recipe for a Perl package from CPAN
29+
Cpan(CpanOpts),
30+
31+
/// Generate a recipe for a Lua package from LuaRocks
32+
Luarocks(LuarocksOpts),
33+
}
34+
35+
/// Options for generating a recipe
36+
#[cfg(feature = "cli")]
37+
#[derive(Parser)]
38+
pub struct GenerateRecipeOpts {
39+
/// Type of package to generate a recipe for
40+
#[clap(subcommand)]
41+
pub source: Source,
42+
}
43+
44+
/// Generate a recipe for a package
45+
#[cfg(feature = "cli")]
46+
pub async fn generate_recipe(args: GenerateRecipeOpts) -> miette::Result<()> {
47+
match args.source {
48+
Source::Pypi(opts) => generate_pypi_recipe(&opts).await?,
49+
Source::Cran(opts) => generate_r_recipe(&opts).await?,
50+
Source::Cpan(opts) => generate_cpan_recipe(&opts).await?,
51+
Source::Luarocks(opts) => generate_luarocks_recipe(&opts).await?,
52+
}
53+
54+
Ok(())
55+
}

src/recipe_generator/luarocks/mod.rs renamed to crates/rattler_build_recipe_generator/src/luarocks/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@
33
44
use std::{collections::BTreeMap, io::Write, path::PathBuf};
55

6+
#[cfg(feature = "cli")]
67
use clap::Parser;
78
use indexmap::IndexMap;
89
use miette::{Context, IntoDiagnostic};
910
use rattler_conda_types::PackageName;
1011
use serde::Deserialize;
1112
use tempfile::NamedTempFile;
1213

13-
use crate::recipe_generator::serialize::{
14+
use crate::serialize::{
1415
About, Build, GitSourceElement, Python, Recipe, Requirements, ScriptTest, SourceElement, Test,
1516
UrlSourceElement, write_recipe,
1617
};
1718

1819
/// Options to control LuaRocks recipe generation.
19-
#[derive(Debug, Clone, Parser)]
20+
#[derive(Debug, Clone)]
21+
#[cfg_attr(feature = "cli", derive(Parser))]
2022
pub struct LuarocksOpts {
2123
/// Luarocks package to generate recipe for.
2224
/// Can be specified as:
@@ -27,7 +29,7 @@ pub struct LuarocksOpts {
2729
pub rock: String,
2830

2931
/// Where to write the recipe to
30-
#[arg(short, long, default_value = ".")]
32+
#[cfg_attr(feature = "cli", arg(short, long, default_value = "."))]
3133
pub write_to: PathBuf,
3234
}
3335

@@ -395,7 +397,7 @@ fn rockspec_to_recipe(rockspec: &LuarocksRockspec) -> miette::Result<Recipe> {
395397

396398
let mut recipe = Recipe {
397399
context,
398-
package: crate::recipe_generator::serialize::Package {
400+
package: crate::serialize::Package {
399401
name: package_name.as_normalized().to_string(),
400402
version: "${{ version }}".to_string(),
401403
},

src/recipe_generator/pypi.rs renamed to crates/rattler_build_recipe_generator/src/pypi.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use async_once_cell::OnceCell;
2+
#[cfg(feature = "cli")]
23
use clap::Parser;
34
use miette::{IntoDiagnostic, WrapErr};
45
use serde::Deserialize;
@@ -8,9 +9,7 @@ use std::path::PathBuf;
89
use zip::ZipArchive;
910

1011
use super::write_recipe;
11-
use crate::recipe_generator::serialize::{
12-
self, PythonTest, PythonTestInner, Test, UrlSourceElement,
13-
};
12+
use crate::serialize::{self, PythonTest, PythonTestInner, Test, UrlSourceElement};
1413

1514
#[derive(Deserialize)]
1615
struct CondaPyPiNameMapping {
@@ -19,25 +18,26 @@ struct CondaPyPiNameMapping {
1918
}
2019

2120
/// Options for generating a Python (PyPI) recipe.
22-
#[derive(Debug, Clone, Parser)]
21+
#[derive(Debug, Clone)]
22+
#[cfg_attr(feature = "cli", derive(Parser))]
2323
pub struct PyPIOpts {
2424
/// Name of the package to generate
2525
pub package: String,
2626

2727
/// Select a version of the package to generate (defaults to latest)
28-
#[arg(long)]
28+
#[cfg_attr(feature = "cli", arg(long))]
2929
pub version: Option<String>,
3030

3131
/// Whether to write the recipe to a folder
32-
#[arg(short, long)]
32+
#[cfg_attr(feature = "cli", arg(short, long))]
3333
pub write: bool,
3434

3535
/// Whether to use the conda-forge PyPI name mapping
36-
#[arg(short, long, default_value = "true")]
36+
#[cfg_attr(feature = "cli", arg(short, long, default_value = "true"))]
3737
pub use_mapping: bool,
3838

3939
/// Whether to generate recipes for all dependencies
40-
#[arg(short, long)]
40+
#[cfg_attr(feature = "cli", arg(short, long))]
4141
pub tree: bool,
4242
}
4343

0 commit comments

Comments
 (0)