use crate::error::{Error, Result};
use crate::phpjson::{php_json_encode_with, EncodeOptions};
use serde_json::Value;
use std::path::Path;
pub const PLUGIN_NAME: &str = "pestphp/pest-plugin";
pub const CACHE_FILE: &str = "pest-plugins.json";
fn plugins_of(extra: Option<&Value>) -> Vec<Value> {
match extra
.and_then(|e| e.get("pest"))
.and_then(|p| p.get("plugins"))
{
Some(Value::Array(items)) => items.clone(),
Some(Value::Object(map)) => map.values().cloned().collect(),
_ => Vec::new(),
}
}
pub fn write_pest_plugins(
vendor_dir: &Path,
packages: &[Option<&Value>],
root_extra: Option<&Value>,
) -> Result<()> {
let mut plugins: Vec<Value> = Vec::new();
for extra in packages {
plugins.extend(plugins_of(*extra));
}
plugins.extend(plugins_of(root_extra));
let text = php_json_encode_with(
&Value::Array(plugins),
EncodeOptions {
pretty: true,
escape_slashes: true,
escape_unicode: true,
},
)?;
let path = vendor_dir.join(CACHE_FILE);
if std::fs::read_to_string(&path).ok().as_deref() == Some(text.as_str()) {
return Ok(());
}
std::fs::write(&path, text).map_err(Error::io(&path))?;
Ok(())
}
pub fn remove_pest_plugins(vendor_dir: &Path) -> Result<()> {
let path = vendor_dir.join(CACHE_FILE);
match std::fs::remove_file(&path) {
Ok(()) => Ok(()),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(Error::io(&path)(e)),
}
}
pub fn local_repository_order<'a>(
previous: &[&'a str],
removed_or_updated: &[&str],
installed: &[&'a str],
) -> Vec<&'a str> {
let mut out: Vec<&str> = previous
.iter()
.copied()
.filter(|n| !removed_or_updated.contains(n) && !installed.contains(n))
.collect();
out.extend(installed.iter().copied());
out
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn dump_like_the_plugin() {
let tmp = tempfile::tempdir().expect("tmp");
let a = json!({"pest": {"plugins": ["Pest\\Laravel\\Plugin"]}});
let b = json!({"other": true});
let c = json!({"pest": {"plugins": ["Pest\\Plugins\\Foo", "Pest\\Plugins\\Bar"]}});
let root = json!({"pest": {"plugins": ["App\\PestPlugin"]}});
write_pest_plugins(
tmp.path(),
&[Some(&a), Some(&b), None, Some(&c)],
Some(&root),
)
.unwrap();
let text = std::fs::read_to_string(tmp.path().join("pest-plugins.json")).unwrap();
assert_eq!(
text,
"[\n \"Pest\\\\Laravel\\\\Plugin\",\n \"Pest\\\\Plugins\\\\Foo\",\n \"Pest\\\\Plugins\\\\Bar\",\n \"App\\\\PestPlugin\"\n]"
);
write_pest_plugins(tmp.path(), &[], None).unwrap();
assert_eq!(
std::fs::read_to_string(tmp.path().join("pest-plugins.json")).unwrap(),
"[]"
);
}
#[test]
fn order_after_a_transaction() {
let order = local_repository_order(&["a/a", "b/b", "c/c"], &["b/b"], &["d/d", "b/b"]);
assert_eq!(order, vec!["a/a", "c/c", "d/d", "b/b"]);
}
}