Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions crates/pixi_build_frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,9 @@ rattler_repodata_gateway = { workspace = true, features = ["gateway"] }
rattler_shell = { workspace = true }
rattler_solve = { workspace = true, features = ["resolvo"] }
rattler_virtual_packages = { workspace = true }
regex = { workspace = true }
reqwest-middleware = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde_with = { workspace = true }
serde_yaml = { workspace = true }
sha1 = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["process", "io-std"] }
tokio-util = { workspace = true, features = ["codec"] }
Expand Down
7 changes: 4 additions & 3 deletions crates/pixi_build_frontend/src/build_frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use rattler_conda_types::ChannelConfig;
use crate::{
protocol,
protocol_builder::{EnabledProtocols, ProtocolBuilder},
Protocol, SetupRequest, ToolContext,
protocols::JsonRPCBuildProtocol,
SetupRequest, ToolContext,
};

/// The frontend for building packages.
Expand Down Expand Up @@ -94,12 +95,12 @@ impl BuildFrontend {
}
}

/// Constructs a new [`Protocol`] for the given request. This object can be
/// Constructs a new [`JsonRPCBuildProtocol`] for the given request. This object can be
/// used to build the package.
pub async fn setup_protocol(
&self,
request: SetupRequest,
) -> Result<Protocol, BuildFrontendError> {
) -> Result<JsonRPCBuildProtocol, BuildFrontendError> {
// Determine the build protocol to use for the source directory.
let protocol = ProtocolBuilder::discover(&request.source_dir, &self.enabled_protocols)?
.with_channel_config(self.channel_config.clone())
Expand Down
5 changes: 2 additions & 3 deletions crates/pixi_build_frontend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ mod protocols;

use std::fmt::{Debug, Formatter};

pub use protocols::builders::{conda_protocol, pixi_protocol, rattler_build_protocol};
pub use protocols::builders::{pixi_protocol, rattler_build_protocol};
pub use protocols::JsonRPCBuildProtocol;

mod protocol_builder;
mod reporters;
Expand All @@ -21,8 +22,6 @@ use tokio::io::{AsyncRead, AsyncWrite};
pub use tool::{IsolatedToolSpec, SystemToolSpec, ToolContext, ToolSpec};
use url::Url;

pub use crate::protocol::Protocol;

pub use backend_override::BackendOverride;
pub use protocol_builder::EnabledProtocols;

Expand Down
112 changes: 3 additions & 109 deletions crates/pixi_build_frontend/src/protocol.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
use std::{path::PathBuf, sync::Arc};
use std::path::PathBuf;

use miette::{Diagnostic, IntoDiagnostic};
use pixi_build_types::procedures::{
conda_build::{CondaBuildParams, CondaBuildResult},
conda_metadata::{CondaMetadataParams, CondaMetadataResult},
};
use miette::Diagnostic;

use crate::{
protocols::{
builders::{conda_protocol, pixi_protocol, rattler_build_protocol},
JsonRPCBuildProtocol,
},
CondaBuildReporter, CondaMetadataReporter,
};
use crate::protocols::builders::{pixi_protocol, rattler_build_protocol};

/// Top-level error type for protocol errors.
#[derive(Debug, thiserror::Error, Diagnostic)]
Expand All @@ -21,10 +11,6 @@ pub enum FinishError {
#[diagnostic(transparent)]
Pixi(#[from] pixi_protocol::FinishError),

#[error(transparent)]
#[diagnostic(transparent)]
CondaBuild(#[from] conda_protocol::FinishError),

#[error(transparent)]
#[diagnostic(transparent)]
RattlerBuild(#[from] rattler_build_protocol::FinishError),
Expand Down Expand Up @@ -54,95 +40,3 @@ pub enum DiscoveryError {
#[diagnostic(transparent)]
RattlerBuild(#[from] rattler_build_protocol::ProtocolBuildError),
}

/// A protocol describes how to communicate with a build backend. A build
/// backend is a tool that is invoked to generate certain output.
///
/// The frontend can support multiple backends, and the protocol is used to
/// determine which backend to use for a given source directory and how to
/// communicate with it.
///
///
/// The [`Protocol`] protocol is a generic implementation that uses a
/// client-server JSON-RPC interface to communicate with another tool.
///
/// Using this JSON-RPC interface means we can evolve the backend and frontend
/// tools as long as both tools can establish a shared protocol. The JSON-RPC
/// protocol is engineered in such a way that this is possible. This allows a
/// much newer frontend to still be able to interact with a very old backend
/// which is important if you want to be able to use very old packages in the
/// far future.
///
/// The conda-build and rattler-build implementations are a hard-coded
/// implementation and do not use a client-server model. Although technically
/// they could also be implemented using the client-server model it is more
/// ergonomic to add their implementation directly into the frontend because no
/// bridge executable is needed. We can always add this later too using the
/// existing protocol.
// I think because we mostly have a single variant in use, boxing does not make
// sense here.
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Protocol {
PixiBuild(JsonRPCBuildProtocol),
// It should be more like subprocess protocol
// as we invoke the tool directly
CondaBuild(conda_protocol::Protocol),
}

impl From<JsonRPCBuildProtocol> for Protocol {
fn from(value: JsonRPCBuildProtocol) -> Self {
Self::PixiBuild(value)
}
}

impl From<conda_protocol::Protocol> for Protocol {
fn from(value: conda_protocol::Protocol) -> Self {
Self::CondaBuild(value)
}
}

impl Protocol {
/// Returns the root manifest files of the source directory. These indicate
/// the files that are used to determine the build configuration.
pub fn manifests(&self) -> Vec<String> {
match self {
Self::PixiBuild(protocol) => protocol.manifests(),
Self::CondaBuild(protocol) => protocol.manifests(),
}
}

pub async fn conda_get_metadata(
&self,
request: &CondaMetadataParams,
reporter: Arc<dyn CondaMetadataReporter>,
) -> miette::Result<CondaMetadataResult> {
match self {
Self::PixiBuild(protocol) => Ok(protocol
.conda_get_metadata(request, reporter.as_ref())
.await?),
Self::CondaBuild(protocol) => protocol.conda_get_metadata(request),
}
}

pub async fn conda_build(
&self,
request: &CondaBuildParams,
reporter: Arc<dyn CondaBuildReporter>,
) -> miette::Result<CondaBuildResult> {
match self {
Self::PixiBuild(protocol) => protocol
.conda_build(request, reporter.as_ref())
.await
.into_diagnostic(),
Self::CondaBuild(_) => unreachable!(),
}
}

pub fn identifier(&self) -> &str {
match self {
Self::PixiBuild(protocol) => protocol.backend_identifier(),
Self::CondaBuild(protocol) => protocol.backend_identifier(),
}
}
}
66 changes: 14 additions & 52 deletions crates/pixi_build_frontend/src/protocol_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use rattler_conda_types::ChannelConfig;

use crate::{
backend_override::BackendOverride,
conda_protocol, pixi_protocol,
pixi_protocol,
protocol::{DiscoveryError, FinishError},
rattler_build_protocol, BuildFrontendError, Protocol, ToolContext,
protocols::JsonRPCBuildProtocol,
rattler_build_protocol, BuildFrontendError, ToolContext,
};

/// Configuration to enable or disable certain protocols discovery.
Expand All @@ -20,8 +21,6 @@ pub struct EnabledProtocols {
pub enable_rattler_build: bool,
/// Enable the pixi protocol.
pub enable_pixi: bool,
/// Enable the conda-build protocol.
pub enable_conda_build: bool,
}

impl Default for EnabledProtocols {
Expand All @@ -30,19 +29,17 @@ impl Default for EnabledProtocols {
Self {
enable_rattler_build: true,
enable_pixi: true,
enable_conda_build: true,
}
}
}

#[derive(Debug)]
// for some reason, the clippy calculates wrong the size
// for this enum variants, so we need to disable the warning
#[allow(clippy::large_enum_variant)]
pub(crate) enum ProtocolBuilder {
/// A pixi project.
Pixi(Box<pixi_protocol::ProtocolBuilder>),

/// A directory containing a `meta.yaml` that can be interpreted by
/// conda-build.
CondaBuild(conda_protocol::ProtocolBuilder),
Pixi(pixi_protocol::ProtocolBuilder),

/// A directory containing a `recipe.yaml` that can be built with
/// rattler-build.
Expand All @@ -51,13 +48,7 @@ pub(crate) enum ProtocolBuilder {

impl From<pixi_protocol::ProtocolBuilder> for ProtocolBuilder {
fn from(value: pixi_protocol::ProtocolBuilder) -> Self {
Self::Pixi(Box::new(value))
}
}

impl From<conda_protocol::ProtocolBuilder> for ProtocolBuilder {
fn from(value: conda_protocol::ProtocolBuilder) -> Self {
Self::CondaBuild(value)
Self::Pixi(value)
}
}

Expand Down Expand Up @@ -110,27 +101,14 @@ impl ProtocolBuilder {
}
}

// Try to discover as a conda build project
if enabled_protocols.enable_conda_build {
if let Some(protocol) = conda_protocol::ProtocolBuilder::discover(source_path).unwrap()
{
return Ok(protocol.into());
}
}

// TODO: Add additional formats later
Err(DiscoveryError::UnsupportedFormat)
}

/// Sets the channel configuration used by the protocol.
pub fn with_channel_config(self, channel_config: ChannelConfig) -> Self {
match self {
Self::Pixi(protocol) => {
Self::Pixi(Box::new(protocol.with_channel_config(channel_config)))
}
Self::CondaBuild(protocol) => {
Self::CondaBuild(protocol.with_channel_config(channel_config))
}
Self::Pixi(protocol) => Self::Pixi(protocol.with_channel_config(channel_config)),
Self::RattlerBuild(protocol) => {
Self::RattlerBuild(protocol.with_channel_config(channel_config))
}
Expand All @@ -141,10 +119,7 @@ impl ProtocolBuilder {
if let Some(backend_override) = backend_override {
match self {
Self::Pixi(protocol) => {
Self::Pixi(Box::new(protocol.with_backend_override(backend_override)))
}
Self::CondaBuild(protocol) => {
Self::CondaBuild(protocol.with_backend_override(backend_override))
Self::Pixi(protocol.with_backend_override(backend_override))
}
Self::RattlerBuild(protocol) => {
Self::RattlerBuild(protocol.with_backend_override(backend_override))
Expand All @@ -158,12 +133,7 @@ impl ProtocolBuilder {
/// Sets the cache directory to use for any caching.
pub fn with_opt_cache_dir(self, cache_directory: Option<PathBuf>) -> Self {
match self {
Self::Pixi(protocol) => {
Self::Pixi(Box::new(protocol.with_opt_cache_dir(cache_directory)))
}
Self::CondaBuild(protocol) => {
Self::CondaBuild(protocol.with_opt_cache_dir(cache_directory))
}
Self::Pixi(protocol) => Self::Pixi(protocol.with_opt_cache_dir(cache_directory)),
Self::RattlerBuild(protocol) => {
Self::RattlerBuild(protocol.with_opt_cache_dir(cache_directory))
}
Expand All @@ -174,7 +144,6 @@ impl ProtocolBuilder {
pub fn name(&self) -> &str {
match self {
Self::Pixi(_) => "pixi",
Self::CondaBuild(_) => "conda-build",
Self::RattlerBuild(_) => "rattler-build",
}
}
Expand All @@ -184,23 +153,16 @@ impl ProtocolBuilder {
self,
tool_context: Arc<ToolContext>,
build_id: usize,
) -> Result<Protocol, BuildFrontendError> {
) -> Result<JsonRPCBuildProtocol, BuildFrontendError> {
match self {
Self::Pixi(protocol) => Ok(protocol
.finish(tool_context, build_id)
.await
.map_err(FinishError::Pixi)?
.into()),
Self::CondaBuild(protocol) => Ok(protocol
.finish(tool_context, build_id)
.await
.map_err(FinishError::CondaBuild)?
.into()),
.map_err(FinishError::Pixi)?),
Self::RattlerBuild(protocol) => Ok(protocol
.finish(tool_context, build_id)
.await
.map_err(FinishError::RattlerBuild)?
.into()),
.map_err(FinishError::RattlerBuild)?),
}
}
}
Loading
Loading