vivacity_core/
pest_plugin.rs1use crate::error::{Error, Result};
20use crate::phpjson::{php_json_encode_with, EncodeOptions};
21use serde_json::Value;
22use std::path::Path;
23
24pub const PLUGIN_NAME: &str = "pestphp/pest-plugin";
25pub const CACHE_FILE: &str = "pest-plugins.json";
26
27fn plugins_of(extra: Option<&Value>) -> Vec<Value> {
30 match extra
31 .and_then(|e| e.get("pest"))
32 .and_then(|p| p.get("plugins"))
33 {
34 Some(Value::Array(items)) => items.clone(),
35 Some(Value::Object(map)) => map.values().cloned().collect(),
36 _ => Vec::new(),
37 }
38}
39
40pub fn write_pest_plugins(
43 vendor_dir: &Path,
44 packages: &[Option<&Value>],
45 root_extra: Option<&Value>,
46) -> Result<()> {
47 let mut plugins: Vec<Value> = Vec::new();
48 for extra in packages {
49 plugins.extend(plugins_of(*extra));
50 }
51 plugins.extend(plugins_of(root_extra));
52 let text = php_json_encode_with(
55 &Value::Array(plugins),
56 EncodeOptions {
57 pretty: true,
58 escape_slashes: true,
59 escape_unicode: true,
60 },
61 )?;
62 let path = vendor_dir.join(CACHE_FILE);
63 if std::fs::read_to_string(&path).ok().as_deref() == Some(text.as_str()) {
64 return Ok(());
65 }
66 std::fs::write(&path, text).map_err(Error::io(&path))?;
67 Ok(())
68}
69
70pub fn remove_pest_plugins(vendor_dir: &Path) -> Result<()> {
72 let path = vendor_dir.join(CACHE_FILE);
73 match std::fs::remove_file(&path) {
74 Ok(()) => Ok(()),
75 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
76 Err(e) => Err(Error::io(&path)(e)),
77 }
78}
79
80pub fn local_repository_order<'a>(
85 previous: &[&'a str],
86 removed_or_updated: &[&str],
87 installed: &[&'a str],
88) -> Vec<&'a str> {
89 let mut out: Vec<&str> = previous
90 .iter()
91 .copied()
92 .filter(|n| !removed_or_updated.contains(n) && !installed.contains(n))
93 .collect();
94 out.extend(installed.iter().copied());
95 out
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use serde_json::json;
102
103 #[test]
104 fn dump_like_the_plugin() {
105 let tmp = tempfile::tempdir().expect("tmp");
106 let a = json!({"pest": {"plugins": ["Pest\\Laravel\\Plugin"]}});
107 let b = json!({"other": true});
108 let c = json!({"pest": {"plugins": ["Pest\\Plugins\\Foo", "Pest\\Plugins\\Bar"]}});
109 let root = json!({"pest": {"plugins": ["App\\PestPlugin"]}});
110 write_pest_plugins(
111 tmp.path(),
112 &[Some(&a), Some(&b), None, Some(&c)],
113 Some(&root),
114 )
115 .unwrap();
116 let text = std::fs::read_to_string(tmp.path().join("pest-plugins.json")).unwrap();
117 assert_eq!(
118 text,
119 "[\n \"Pest\\\\Laravel\\\\Plugin\",\n \"Pest\\\\Plugins\\\\Foo\",\n \"Pest\\\\Plugins\\\\Bar\",\n \"App\\\\PestPlugin\"\n]"
120 );
121 write_pest_plugins(tmp.path(), &[], None).unwrap();
122 assert_eq!(
123 std::fs::read_to_string(tmp.path().join("pest-plugins.json")).unwrap(),
124 "[]"
125 );
126 }
127
128 #[test]
129 fn order_after_a_transaction() {
130 let order = local_repository_order(&["a/a", "b/b", "c/c"], &["b/b"], &["d/d", "b/b"]);
131 assert_eq!(order, vec!["a/a", "c/c", "d/d", "b/b"]);
132 }
133}