Skip to content

Commit

Permalink
Remove DefaultEnvLayer and set_default
Browse files Browse the repository at this point in the history
More rationale given here #598 (comment).

I am also removing `set_envs` as it does little for ergonomics.
  • Loading branch information
schneems committed Jan 18, 2024
1 parent a253009 commit 0c82572
Showing 1 changed file with 35 additions and 146 deletions.
181 changes: 35 additions & 146 deletions libherokubuildpack/src/env_layer.rs
Original file line number Diff line number Diff line change
@@ -1,114 +1,18 @@
use libcnb::build::BuildContext;
use libcnb::data::layer::LayerName;
use libcnb::data::layer_content_metadata::LayerTypes;
use libcnb::generic::GenericMetadata;
use libcnb::layer::{Layer, LayerData, LayerResult, LayerResultBuilder};
use libcnb::layer_env::{LayerEnv, ModificationBehavior, Scope};
use libcnb::Buildpack;
use std::ffi::OsString;
use libcnb::layer::{Layer, LayerResult, LayerResultBuilder};
use libcnb::layer_env::LayerEnv;
use std::marker::PhantomData;
use std::path::Path;

/// Set default environment variables
/// Convenience layer for setting environment variables
///
/// If all you need to do is set default environment values, you can use
/// the `env_layer::set_default` function to set those values without having
/// to create a struct from scratch. Example:
/// If you do not need to modify files on disk or cache metadata, you can use this layer along with
/// [`BuildContext::handle_layer`] to apply results of [`LayerEnv::chainable_insert`] to build and
/// launch (runtime) environments.
///
/// ```no_run
///# use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder};
///# use libcnb::data::launch::{LaunchBuilder, ProcessBuilder};
///# use libcnb::data::process_type;
///# use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder};
///# use libcnb::generic::{GenericError, GenericMetadata, GenericPlatform};
///# use libcnb::{buildpack_main, Buildpack};
///# use libcnb::data::layer::LayerName;
///
///# pub(crate) struct HelloWorldBuildpack;
///
/// use libcnb::Env;
/// use libcnb::data::layer_name;
/// use libcnb::layer_env::Scope;
/// use libherokubuildpack::env_layer;
///
///# impl Buildpack for HelloWorldBuildpack {
///# type Platform = GenericPlatform;
///# type Metadata = GenericMetadata;
///# type Error = GenericError;
///
///# fn detect(&self, _context: DetectContext<Self>) -> libcnb::Result<DetectResult, Self::Error> {
///# todo!()
///# }
///
///# fn build(&self, context: BuildContext<Self>) -> libcnb::Result<BuildResult, Self::Error> {
/// // Don't forget to apply context.platform.env() in addition to current envs;
/// let env = Env::from_current();
///
/// let layer = env_layer::set_default(&context, layer_name!("default_env"),
/// [
/// ("JRUBY_OPTS", "-Xcompile.invokedynamic=false"),
/// ("RACK_ENV", "production"),
/// ("RAILS_ENV", "production"),
/// ("RAILS_SERVE_STATIC_FILES", "enabled"),
/// ("RAILS_LOG_TO_STDOUT", "enabled"),
/// ("MALLOC_ARENA_MAX", "2"),
/// ("DISABLE_SPRING", "1"),
/// ]
/// .into_iter(),
/// )?;
/// let env = layer.env.apply(Scope::Build, &env);
///
///# todo!()
///# }
///# }
/// ```
pub fn set_default<B, E, K, V>(
context: &BuildContext<B>,
layer_name: LayerName,
envs: E,
) -> libcnb::Result<LayerData<GenericMetadata>, <B as Buildpack>::Error>
where
B: Buildpack,
E: IntoIterator<Item = (K, V)> + Clone,
K: Into<OsString>,
V: Into<OsString>,
{
context.handle_layer(layer_name, DefaultEnvLayer::new(envs))
}

/// Set default environment variables in a layer
///
/// This struct is used by the helper function `set_default`. You can also use it directly with
/// with [`BuildContext::handle_layer`] to set default environment variables.
pub struct DefaultEnvLayer;

impl DefaultEnvLayer {
#[allow(clippy::new_ret_no_self)]
pub fn new<E, K, V, B>(env: E) -> ConfigureEnvLayer<B>
where
E: IntoIterator<Item = (K, V)> + Clone,
K: Into<OsString>,
V: Into<OsString>,
B: libcnb::Buildpack,
{
let mut layer_env = LayerEnv::new();
for (key, value) in env {
layer_env =
layer_env.chainable_insert(Scope::All, ModificationBehavior::Default, key, value);
}

ConfigureEnvLayer {
data: layer_env,
_buildpack: PhantomData,
}
}
}

/// Set environment variables
///
/// If you want to set many default environment variables you can use the
/// `env_layer::set_default` function. If you need to set different types of environment
/// variables you can use the `env_layer::set_envs` function. Example:
/// Example:
///
/// ```no_run
///# use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder};
Expand Down Expand Up @@ -136,38 +40,38 @@ impl DefaultEnvLayer {
///# }
///
///# fn build(&self, context: BuildContext<Self>) -> libcnb::Result<BuildResult, Self::Error> {
/// // Don't forget to apply context.platform.env() too;
/// let env = Env::from_current();
///
/// let env = {
/// let layer = env_layer::set_envs(
/// &context,
/// let layer = context.handle_layer(
/// layer_name!("configure_env"),
/// LayerEnv::new()
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Override,
/// "BUNDLE_GEMFILE", // Tells bundler where to find the `Gemfile`
/// context.app_dir.join("Gemfile"),
/// )
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Override,
/// "BUNDLE_CLEAN", // After successful `bundle install` bundler will automatically run `bundle clean`
/// "1",
/// )
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Override,
/// "BUNDLE_DEPLOYMENT", // Requires the `Gemfile.lock` to be in sync with the current `Gemfile`.
/// "1",
/// )
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Default,
/// "MY_ENV_VAR",
/// "Whatever I want"
/// )
/// env_layer::ConfigureEnvLayer::new(
/// LayerEnv::new()
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Override,
/// "BUNDLE_GEMFILE", // Tells bundler where to find the `Gemfile`
/// context.app_dir.join("Gemfile"),
/// )
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Override,
/// "BUNDLE_CLEAN", // After successful `bundle install` bundler will automatically run `bundle clean`
/// "1",
/// )
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Override,
/// "BUNDLE_DEPLOYMENT", // Requires the `Gemfile.lock` to be in sync with the current `Gemfile`.
/// "1",
/// )
/// .chainable_insert(
/// Scope::All,
/// ModificationBehavior::Default,
/// "MY_ENV_VAR",
/// "Whatever I want",
/// ),
/// ),
/// )?;
/// layer.env.apply(Scope::Build, &env)
/// };
Expand All @@ -176,21 +80,6 @@ impl DefaultEnvLayer {
///# }
///# }
/// ```
pub fn set_envs<B>(
context: &BuildContext<B>,
layer_name: LayerName,
envs: LayerEnv,
) -> libcnb::Result<LayerData<GenericMetadata>, <B as Buildpack>::Error>
where
B: Buildpack,
{
context.handle_layer(layer_name, ConfigureEnvLayer::new(envs))
}

/// Set custom environment variables in a layer
///
/// This struct is used by the helper function `set_envs`. You can also use it directly with
/// use directly with [`BuildContext::handle_layer`] to set specific environment variables.
pub struct ConfigureEnvLayer<B: libcnb::Buildpack> {
pub(crate) data: LayerEnv,
pub(crate) _buildpack: std::marker::PhantomData<B>,
Expand Down

0 comments on commit 0c82572

Please sign in to comment.