use super::Provider;
use crate::nixpacks::{
app::App,
environment::Environment,
nix::pkg::Pkg,
phase::{BuildPhase, InstallPhase, SetupPhase, StartPhase},
};
use anyhow::Result;
use regex::Regex;
const DEFAULT_JDK_PKG_NAME: &'static &str = &"jdk8";
const LEIN_CACHE_DIR: &'static &str = &"~/.m2";
pub struct ClojureProvider {}
impl Provider for ClojureProvider {
fn name(&self) -> &str {
"clojure"
}
fn detect(&self, app: &App, _env: &Environment) -> Result<bool> {
Ok(app.includes_file("project.clj"))
}
fn install(&self, _app: &App, _env: &Environment) -> Result<Option<InstallPhase>> {
let mut install_phase = InstallPhase::new("".to_string());
install_phase.add_cache_directory(LEIN_CACHE_DIR.to_string());
Ok(Some(install_phase))
}
fn setup(&self, app: &App, env: &Environment) -> Result<Option<SetupPhase>> {
Ok(Some(SetupPhase::new(vec![
Pkg::new("leiningen"),
ClojureProvider::get_nix_jdk_package(app, env)?,
])))
}
fn build(&self, app: &App, _env: &Environment) -> Result<Option<BuildPhase>> {
let has_lein_ring_plugin = app
.read_file("project.clj")?
.to_lowercase()
.contains("[lein-ring ");
let build_cmd = match has_lein_ring_plugin {
true => "lein ring uberjar",
false => "lein uberjar",
};
let move_file_cmd = "if [ -f /app/target/uberjar/*standalone.jar ]; then mv /app/target/uberjar/*standalone.jar /app/target/*standalone.jar; fi";
Ok(Some(BuildPhase::new(format!(
"{}; {}",
build_cmd, move_file_cmd
))))
}
fn start(&self, _app: &App, _env: &Environment) -> Result<Option<StartPhase>> {
let start_cmd = "java $JAVA_OPTS -jar /app/target/*standalone.jar";
Ok(Some(StartPhase::new(start_cmd.to_string())))
}
}
impl ClojureProvider {
fn get_custom_version(app: &App, env: &Environment) -> Result<String> {
let mut custom_version = env.get_config_variable("JDK_VERSION");
if custom_version.is_none() && app.includes_file(".jdk-version") {
custom_version = Some(app.read_file(".jdk-version")?);
}
match custom_version {
Some(v) => Ok(v),
None => Ok(DEFAULT_JDK_PKG_NAME.to_string()),
}
}
fn parse_custom_version(custom_version: String) -> Result<String> {
let jdk_regex = Regex::new(r"^([0-9][0-9]?|latest)$")?;
let matches = jdk_regex.captures(custom_version.as_str().trim());
if matches.is_none() {
return Ok(DEFAULT_JDK_PKG_NAME.to_string());
}
let matches = matches.unwrap();
let matched_value = matches.get(0);
let value = match matched_value {
Some(m) => m.as_str(),
None => "_",
};
Ok(value.to_string())
}
pub fn get_nix_jdk_package(app: &App, env: &Environment) -> Result<Pkg> {
let custom_version = ClojureProvider::get_custom_version(app, env)?;
let parsed_version = ClojureProvider::parse_custom_version(custom_version)?;
let pkg_name = match parsed_version.as_str() {
"latest" => "jdk",
"11" => "jdk11",
_ => DEFAULT_JDK_PKG_NAME, };
Ok(Pkg::new(pkg_name))
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::nixpacks::{app::App, environment::Environment, nix::pkg::Pkg};
use std::collections::BTreeMap;
#[test]
fn test_no_version() -> Result<()> {
assert_eq!(
ClojureProvider::get_nix_jdk_package(
&App::new("./examples/clojure")?,
&Environment::default()
)?,
Pkg::new(DEFAULT_JDK_PKG_NAME)
);
Ok(())
}
#[test]
fn test_custom_version() -> Result<()> {
assert_eq!(
ClojureProvider::get_nix_jdk_package(
&App::new("./examples/clojure-jdk11")?,
&Environment::default()
)?,
Pkg::new("jdk11")
);
Ok(())
}
#[test]
fn test_custom_latest_version() -> Result<()> {
assert_eq!(
ClojureProvider::get_nix_jdk_package(
&App::new("./examples/clojure-jdk-latest")?,
&Environment::default()
)?,
Pkg::new("jdk")
);
Ok(())
}
#[test]
fn test_latest_version_from_environment_variable() -> Result<()> {
assert_eq!(
ClojureProvider::get_nix_jdk_package(
&App::new("./examples/clojure-jdk-latest")?,
&Environment::new(BTreeMap::from([(
"NIXPACKS_JDK_VERSION".to_string(),
"latest".to_string()
)]))
)?,
Pkg::new("jdk")
);
Ok(())
}
#[test]
fn test_version_from_environment_variable() -> Result<()> {
assert_eq!(
ClojureProvider::get_nix_jdk_package(
&App::new("./examples/clojure")?,
&Environment::new(BTreeMap::from([(
"NIXPACKS_JDK_VERSION".to_string(),
"11".to_string()
)]))
)?,
Pkg::new("jdk11")
);
Ok(())
}
}