aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--crates/shirabe/build.rs37
-rw-r--r--crates/shirabe/src/command/config_command.rs11
-rw-r--r--crates/shirabe/src/json/json_file.rs53
3 files changed, 30 insertions, 71 deletions
diff --git a/crates/shirabe/build.rs b/crates/shirabe/build.rs
deleted file mode 100644
index d98b07e7..00000000
--- a/crates/shirabe/build.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-use std::path::PathBuf;
-
-// Composer ships its JSON schemas in res/ and JsonFile resolves them via __DIR__.
-// We copy those schema files next to the built executable so they can be located
-// at runtime through std::env::current_exe().
-fn main() {
- let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
- let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
-
- // OUT_DIR is target/<profile>/build/<pkg>-<hash>/out; its 3rd ancestor is target/<profile>.
- let target_profile_dir = out_dir
- .ancestors()
- .nth(3)
- .expect("OUT_DIR has an unexpected layout");
-
- let composer_res = manifest_dir.join("../../composer/res");
- let files = ["composer-schema.json", "composer-lock-schema.json"];
-
- // Binaries live in target/<profile>, test/example binaries in target/<profile>/deps;
- // populate a res/ directory next to both so current_exe()/../res resolves either way.
- for dest_dir in [
- target_profile_dir.join("res"),
- target_profile_dir.join("deps").join("res"),
- ] {
- std::fs::create_dir_all(&dest_dir).unwrap();
- for file in files {
- std::fs::copy(composer_res.join(file), dest_dir.join(file)).unwrap();
- }
- }
-
- for file in files {
- println!(
- "cargo:rerun-if-changed={}",
- composer_res.join(file).display()
- );
- }
-}
diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs
index a92c2f59..9e2f4e66 100644
--- a/crates/shirabe/src/command/config_command.rs
+++ b/crates/shirabe/src/command/config_command.rs
@@ -23,9 +23,9 @@ use shirabe_external_packages::symfony::console::input::InputInterface;
use shirabe_external_packages::symfony::console::output::OutputInterface;
use shirabe_php_shim::{
InvalidArgumentException, PhpMixed, RuntimeException, array_is_list, array_merge,
- escapeshellcmd, exec, explode, file_exists, file_get_contents, implode, in_array, is_array,
- is_bool, is_dir, is_numeric, is_object, is_string, json_encode, php_regex, str_replace, strpos,
- strtolower, system, touch, var_export,
+ escapeshellcmd, exec, explode, file_exists, implode, in_array, is_array, is_bool, is_dir,
+ is_numeric, is_object, is_string, json_encode, php_regex, str_replace, strpos, strtolower,
+ system, touch, var_export,
};
use shirabe_semver::VersionParser;
@@ -431,10 +431,7 @@ impl Command for ConfigCommand {
// ensure we get {} output for properties which are objects
if value.as_array().map(|a| a.is_empty()).unwrap_or(false) {
let schema = JsonFile::parse_json(
- Some(
- &file_get_contents(JsonFile::composer_schema_path())
- .unwrap_or_default(),
- ),
+ Some(JsonFile::COMPOSER_SCHEMA_JSON),
Some("composer.schema.json"),
)?;
let type_value = schema
diff --git a/crates/shirabe/src/json/json_file.rs b/crates/shirabe/src/json/json_file.rs
index 868745ef..dbcd7a19 100644
--- a/crates/shirabe/src/json/json_file.rs
+++ b/crates/shirabe/src/json/json_file.rs
@@ -83,25 +83,17 @@ impl JsonFile {
pub const INDENT_DEFAULT: &'static str = " ";
- /// build.rs copies the Composer schema files into a res/ directory next to the
- /// executable; this resolves that path via the running executable's location.
- ///
- /// TODO(phase-f): this on-disk layout is hard to distribute. Embed the schema with
- /// include_str! and extract it to a temporary file at runtime instead.
- pub fn composer_schema_path() -> std::path::PathBuf {
- Self::schema_res_path("composer-schema.json")
- }
-
- /// See composer_schema_path.
- pub fn lock_schema_path() -> std::path::PathBuf {
- Self::schema_res_path("composer-lock-schema.json")
- }
+ /// PHP points these at Composer's res/ directory; here the schemas are embedded in the
+ /// binary and SchemaRetriever resolves these URIs back to the constants below. The res/
+ /// path segment matters: composer-lock-schema.json reaches the composer schema through the
+ /// relative reference "./composer-schema.json", which must resolve to COMPOSER_SCHEMA_PATH.
+ pub const COMPOSER_SCHEMA_PATH: &'static str = "shirabe:///res/composer-schema.json";
+ pub const LOCK_SCHEMA_PATH: &'static str = "shirabe:///res/composer-lock-schema.json";
- fn schema_res_path(filename: &str) -> std::path::PathBuf {
- let exe = std::env::current_exe().expect("failed to resolve current executable path");
- let dir = exe.parent().expect("executable has no parent directory");
- dir.join("res").join(filename)
- }
+ pub const COMPOSER_SCHEMA_JSON: &'static str =
+ include_str!("../../../../composer/res/composer-schema.json");
+ const LOCK_SCHEMA_JSON: &'static str =
+ include_str!("../../../../composer/res/composer-lock-schema.json");
/// Initializes json file reader/parser.
///
@@ -348,18 +340,17 @@ impl JsonFile {
schema_file: Option<&str>,
) -> anyhow::Result<bool> {
let mut is_composer_schema_file = false;
- let schema_file = match schema_file {
- Some(f) => f.into(),
+ let mut schema_file = match schema_file {
+ Some(f) => f.to_string(),
None => {
if schema == Self::LOCK_SCHEMA {
- Self::lock_schema_path()
+ Self::LOCK_SCHEMA_PATH.to_string()
} else {
is_composer_schema_file = true;
- Self::composer_schema_path()
+ Self::COMPOSER_SCHEMA_PATH.to_string()
}
}
};
- let mut schema_file = schema_file.to_string_lossy().into_owned();
// Prepend with file:// only when not using a special schema already (e.g. in the phar)
if strpos(&schema_file, "://").is_none() {
@@ -379,7 +370,7 @@ impl JsonFile {
};
if schema == Self::STRICT_SCHEMA && is_composer_schema_file {
- schema_data = json_decode(&file_get_contents(&schema_file).unwrap_or_default(), false)?;
+ schema_data = json_decode(Self::COMPOSER_SCHEMA_JSON, false)?;
if let PhpMixed::Object(map) = &mut schema_data {
map.insert("additionalProperties".to_string(), PhpMixed::Bool(false));
map.insert(
@@ -407,7 +398,7 @@ impl JsonFile {
let schema_value = serde_json::to_value(&schema_data)?;
let data_value = serde_json::to_value(data)?;
let validator = jsonschema::options()
- .with_retriever(FileRetriever)
+ .with_retriever(SchemaRetriever)
.build(&schema_value)
.map_err(|e| anyhow::anyhow!("{e}"))?;
@@ -594,14 +585,22 @@ impl JsonFile {
}
#[derive(Debug)]
-struct FileRetriever;
+struct SchemaRetriever;
-impl jsonschema::Retrieve for FileRetriever {
+impl jsonschema::Retrieve for SchemaRetriever {
fn retrieve(
&self,
uri: &jsonschema::Uri<String>,
) -> anyhow::Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>> {
match uri.scheme().as_str() {
+ "shirabe" => {
+ let contents = match uri.path().as_str() {
+ "/res/composer-schema.json" => JsonFile::COMPOSER_SCHEMA_JSON,
+ "/res/composer-lock-schema.json" => JsonFile::LOCK_SCHEMA_JSON,
+ path => return Err(format!("Unknown embedded resource {path}").into()),
+ };
+ Ok(serde_json::from_str(contents)?)
+ }
"file" => {
let file = std::fs::File::open(uri.path().as_str())?;
Ok(serde_json::from_reader(std::io::BufReader::new(file))?)