use crate::TemplateContext;
use crate::functions::metadata::{ArgumentMetadata, FunctionMetadata, SyntaxVariants};
use crate::is_functions::ContextIsFunction;
use minijinja::value::Kwargs;
use minijinja::{Environment, Error, Value};
use std::sync::Arc;
const PATH_ARG: ArgumentMetadata = ArgumentMetadata {
name: "path",
arg_type: "string",
required: true,
default: None,
description: "Path to check",
};
pub struct File;
impl ContextIsFunction for File {
const FUNCTION_NAME: &'static str = "is_file";
const IS_NAME: &'static str = "file";
const METADATA: FunctionMetadata = FunctionMetadata {
name: "is_file",
category: "filesystem",
description: "Check if path exists and is a regular file",
arguments: &[PATH_ARG],
return_type: "boolean",
examples: &[
"{{ is_file(path=\"config.json\") }}",
"{% if \"config.json\" is file %}config exists{% endif %}",
],
syntax: SyntaxVariants::FUNCTION_AND_TEST,
};
fn call_as_function(context: Arc<TemplateContext>, kwargs: Kwargs) -> Result<Value, Error> {
let path: String = kwargs.get("path")?;
let resolved = context.resolve_path(&path);
Ok(Value::from(resolved.is_file()))
}
fn call_as_is(context: Arc<TemplateContext>, value: &Value) -> bool {
value
.as_str()
.map(|s| context.resolve_path(s).is_file())
.unwrap_or(false)
}
}
pub struct Dir;
impl ContextIsFunction for Dir {
const FUNCTION_NAME: &'static str = "is_dir";
const IS_NAME: &'static str = "dir";
const METADATA: FunctionMetadata = FunctionMetadata {
name: "is_dir",
category: "filesystem",
description: "Check if path exists and is a directory",
arguments: &[PATH_ARG],
return_type: "boolean",
examples: &[
"{{ is_dir(path=\"src\") }}",
"{% if \"src\" is dir %}directory exists{% endif %}",
],
syntax: SyntaxVariants::FUNCTION_AND_TEST,
};
fn call_as_function(context: Arc<TemplateContext>, kwargs: Kwargs) -> Result<Value, Error> {
let path: String = kwargs.get("path")?;
let resolved = context.resolve_path(&path);
Ok(Value::from(resolved.is_dir()))
}
fn call_as_is(context: Arc<TemplateContext>, value: &Value) -> bool {
value
.as_str()
.map(|s| context.resolve_path(s).is_dir())
.unwrap_or(false)
}
}
pub struct Symlink;
impl Symlink {
fn is_symlink(path: &std::path::Path) -> bool {
path.symlink_metadata()
.map(|m| m.file_type().is_symlink())
.unwrap_or(false)
}
}
impl ContextIsFunction for Symlink {
const FUNCTION_NAME: &'static str = "is_symlink";
const IS_NAME: &'static str = "symlink";
const METADATA: FunctionMetadata = FunctionMetadata {
name: "is_symlink",
category: "filesystem",
description: "Check if path exists and is a symbolic link",
arguments: &[PATH_ARG],
return_type: "boolean",
examples: &[
"{{ is_symlink(path=\"link\") }}",
"{% if \"link\" is symlink %}it's a symlink{% endif %}",
],
syntax: SyntaxVariants::FUNCTION_AND_TEST,
};
fn call_as_function(context: Arc<TemplateContext>, kwargs: Kwargs) -> Result<Value, Error> {
let path: String = kwargs.get("path")?;
let resolved = context.resolve_path(&path);
Ok(Value::from(Self::is_symlink(&resolved)))
}
fn call_as_is(context: Arc<TemplateContext>, value: &Value) -> bool {
value
.as_str()
.map(|s| Self::is_symlink(&context.resolve_path(s)))
.unwrap_or(false)
}
}
pub fn register_all(env: &mut Environment, context: Arc<TemplateContext>) {
File::register(env, context.clone());
Dir::register(env, context.clone());
Symlink::register(env, context);
}