Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 3 additions & 2 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 @@ -99,7 +100,7 @@ impl BuildFrontend {
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