From 797c7668c16127fad019a61c5892b09cb24f7e6c Mon Sep 17 00:00:00 2001 From: Andrew Hlynskyi Date: Wed, 23 Jun 2021 01:59:06 +0300 Subject: [PATCH 1/4] feat(cli): Independant language binding files generation --- cli/src/generate/binding_files.rs | 141 +++++++++++++++--------------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/cli/src/generate/binding_files.rs b/cli/src/generate/binding_files.rs index 3ea9b356..7bc03dc6 100644 --- a/cli/src/generate/binding_files.rs +++ b/cli/src/generate/binding_files.rs @@ -1,6 +1,6 @@ use super::write_file; use anyhow::{Context, Result}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::{fs, str}; const BINDING_CC_TEMPLATE: &'static str = include_str!("./templates/binding.cc"); @@ -22,39 +22,33 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( // Generate rust bindings if needed. let rust_binding_dir = bindings_dir.join("rust"); - if !rust_binding_dir.exists() { - create_dir(&rust_binding_dir)?; - generate_file( - &rust_binding_dir.join("lib.rs"), - LIB_RS_TEMPLATE, - language_name, - )?; - generate_file( - &rust_binding_dir.join("build.rs"), - BUILD_RS_TEMPLATE, - language_name, - )?; - let cargo_toml_path = repo_path.join("Cargo.toml"); - if !cargo_toml_path.exists() { - generate_file(&cargo_toml_path, CARGO_TOML_TEMPLATE, dashed_language_name)?; - } - } + create_path(&rust_binding_dir, |path| create_dir(path))?; + + create_path(&rust_binding_dir.join("lib.rs").to_owned(), |path| { + generate_file(path, LIB_RS_TEMPLATE, language_name) + })?; + + create_path(&rust_binding_dir.join("build.rs").to_owned(), |path| { + generate_file(path, BUILD_RS_TEMPLATE, language_name) + })?; + + create_path(&repo_path.join("Cargo.toml").to_owned(), |path| { + generate_file(path, CARGO_TOML_TEMPLATE, dashed_language_name) + })?; // Generate node bindings let node_binding_dir = bindings_dir.join("node"); - if !node_binding_dir.exists() { - create_dir(&node_binding_dir)?; - generate_file( - &node_binding_dir.join("index.js"), - INDEX_JS_TEMPLATE, - language_name, - )?; - generate_file( - &node_binding_dir.join("binding.cc"), - BINDING_CC_TEMPLATE, - language_name, - )?; + let node_binding_dir_created = create_path(&node_binding_dir, |path| create_dir(path))?; + create_path(&node_binding_dir.join("index.js").to_owned(), |path| { + generate_file(path, INDEX_JS_TEMPLATE, language_name) + })?; + + create_path(&node_binding_dir.join("binding.cc").to_owned(), |path| { + generate_file(path, BINDING_CC_TEMPLATE, language_name) + })?; + + if node_binding_dir_created { // Create binding.gyp, or update it with new binding path. let binding_gyp_path = repo_path.join("binding.gyp"); if binding_gyp_path.exists() { @@ -67,50 +61,48 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( } else { generate_file(&binding_gyp_path, BINDING_GYP_TEMPLATE, language_name)?; } + } - // Create package.json, or update it with new binding path. - let package_json_path = repo_path.join("package.json"); - if package_json_path.exists() { - let package_json_str = fs::read_to_string(&package_json_path) - .with_context(|| "Failed to read package.json")?; - let mut package_json = - serde_json::from_str::>( - &package_json_str, - ) + // Create package.json, or update it with new binding path. + let package_json_path = repo_path.join("package.json"); + if package_json_path.exists() { + let package_json_str = fs::read_to_string(&package_json_path) + .with_context(|| "Failed to read package.json")?; + let mut package_json = + serde_json::from_str::>(&package_json_str) .with_context(|| "Failed to parse package.json")?; - let package_json_main = package_json.get("main"); - let package_json_needs_update = package_json_main.map_or(true, |v| { - let main_string = v.as_str(); - main_string == Some("index.js") || main_string == Some("./index.js") - }); - if package_json_needs_update { - eprintln!("Updating package.json with new binding path"); + let package_json_main = package_json.get("main"); + let package_json_needs_update = package_json_main.map_or(true, |v| { + let main_string = v.as_str(); + main_string == Some("index.js") || main_string == Some("./index.js") + }); + if package_json_needs_update { + eprintln!("Updating package.json with new binding path"); - package_json.insert( - "main".to_string(), - serde_json::Value::String("bindings/node".to_string()), - ); - let mut package_json_str = serde_json::to_string_pretty(&package_json)?; - package_json_str.push('\n'); - write_file(&package_json_path, package_json_str)?; - } - } else { - generate_file( - &package_json_path, - PACKAGE_JSON_TEMPLATE, - dashed_language_name, - )?; + package_json.insert( + "main".to_string(), + serde_json::Value::String("bindings/node".to_string()), + ); + let mut package_json_str = serde_json::to_string_pretty(&package_json)?; + package_json_str.push('\n'); + write_file(&package_json_path, package_json_str)?; } + } else { + generate_file( + &package_json_path, + PACKAGE_JSON_TEMPLATE, + dashed_language_name, + )?; + } - // Remove files from old node binding paths. - let old_index_js_path = repo_path.join("index.js"); - let old_binding_cc_path = repo_path.join("src").join("binding.cc"); - if old_index_js_path.exists() { - fs::remove_file(old_index_js_path).ok(); - } - if old_binding_cc_path.exists() { - fs::remove_file(old_binding_cc_path).ok(); - } + // Remove files from old node binding paths. + let old_index_js_path = repo_path.join("index.js"); + let old_binding_cc_path = repo_path.join("src").join("binding.cc"); + if old_index_js_path.exists() { + fs::remove_file(old_index_js_path).ok(); + } + if old_binding_cc_path.exists() { + fs::remove_file(old_binding_cc_path).ok(); } Ok(()) @@ -129,3 +121,14 @@ fn create_dir(path: &Path) -> Result<()> { fs::create_dir_all(&path) .with_context(|| format!("Failed to create {:?}", path.to_string_lossy())) } + +fn create_path(path: &PathBuf, action: F) -> Result +where + F: Fn(&PathBuf) -> Result<()>, +{ + if !path.exists() { + action(path)?; + return Ok(true); + } + Ok(false) +} From 86b813745758bccf62207c77de75b27641359316 Mon Sep 17 00:00:00 2001 From: Andrew Hlynskyi Date: Wed, 23 Jun 2021 02:17:00 +0300 Subject: [PATCH 2/4] Add create_path_else fn to handle creation or modification --- cli/src/generate/binding_files.rs | 94 ++++++++++++++++++------------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/cli/src/generate/binding_files.rs b/cli/src/generate/binding_files.rs index 7bc03dc6..7b965cf5 100644 --- a/cli/src/generate/binding_files.rs +++ b/cli/src/generate/binding_files.rs @@ -38,7 +38,7 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( // Generate node bindings let node_binding_dir = bindings_dir.join("node"); - let node_binding_dir_created = create_path(&node_binding_dir, |path| create_dir(path))?; + create_path(&node_binding_dir, |path| create_dir(path))?; create_path(&node_binding_dir.join("index.js").to_owned(), |path| { generate_file(path, INDEX_JS_TEMPLATE, language_name) @@ -48,52 +48,52 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( generate_file(path, BINDING_CC_TEMPLATE, language_name) })?; - if node_binding_dir_created { - // Create binding.gyp, or update it with new binding path. - let binding_gyp_path = repo_path.join("binding.gyp"); - if binding_gyp_path.exists() { + // Create binding.gyp, or update it with new binding path. + let binding_gyp_path = repo_path.join("binding.gyp"); + create_path_else( + &binding_gyp_path, + |path| generate_file(path, BINDING_GYP_TEMPLATE, language_name), + |path| { eprintln!("Updating binding.gyp with new binding path"); - - let binding_gyp = fs::read_to_string(&binding_gyp_path) - .with_context(|| "Failed to read binding.gyp")?; + let binding_gyp = + fs::read_to_string(path).with_context(|| "Failed to read binding.gyp")?; let binding_gyp = binding_gyp.replace("src/binding.cc", "bindings/node/binding.cc"); - write_file(&binding_gyp_path, binding_gyp)?; - } else { - generate_file(&binding_gyp_path, BINDING_GYP_TEMPLATE, language_name)?; - } - } + write_file(path, binding_gyp) + }, + )?; // Create package.json, or update it with new binding path. let package_json_path = repo_path.join("package.json"); - if package_json_path.exists() { - let package_json_str = fs::read_to_string(&package_json_path) - .with_context(|| "Failed to read package.json")?; - let mut package_json = - serde_json::from_str::>(&package_json_str) + create_path_else( + &package_json_path, + |path| generate_file(path, PACKAGE_JSON_TEMPLATE, dashed_language_name), + |path| { + let package_json_str = + fs::read_to_string(path).with_context(|| "Failed to read package.json")?; + let mut package_json = + serde_json::from_str::>( + &package_json_str, + ) .with_context(|| "Failed to parse package.json")?; - let package_json_main = package_json.get("main"); - let package_json_needs_update = package_json_main.map_or(true, |v| { - let main_string = v.as_str(); - main_string == Some("index.js") || main_string == Some("./index.js") - }); - if package_json_needs_update { - eprintln!("Updating package.json with new binding path"); + let package_json_main = package_json.get("main"); + let package_json_needs_update = package_json_main.map_or(true, |v| { + let main_string = v.as_str(); + main_string == Some("index.js") || main_string == Some("./index.js") + }); + if package_json_needs_update { + eprintln!("Updating package.json with new binding path"); - package_json.insert( - "main".to_string(), - serde_json::Value::String("bindings/node".to_string()), - ); - let mut package_json_str = serde_json::to_string_pretty(&package_json)?; - package_json_str.push('\n'); - write_file(&package_json_path, package_json_str)?; - } - } else { - generate_file( - &package_json_path, - PACKAGE_JSON_TEMPLATE, - dashed_language_name, - )?; - } + package_json.insert( + "main".to_string(), + serde_json::Value::String("bindings/node".to_string()), + ); + let mut package_json_str = serde_json::to_string_pretty(&package_json)?; + package_json_str.push('\n'); + write_file(path, package_json_str)?; + } + Ok(()) + }, + )?; // Remove files from old node binding paths. let old_index_js_path = repo_path.join("index.js"); @@ -132,3 +132,17 @@ where } Ok(false) } + +fn create_path_else(path: &PathBuf, action: T, else_action: F) -> Result +where + T: Fn(&PathBuf) -> Result<()>, + F: Fn(&PathBuf) -> Result<()>, +{ + if !path.exists() { + action(path)?; + return Ok(true); + } else { + else_action(path)?; + } + Ok(false) +} From 22d63338a26b654cc5d42b62f560191bcc6e97e1 Mon Sep 17 00:00:00 2001 From: Andrew Hlynskyi Date: Wed, 23 Jun 2021 02:20:28 +0300 Subject: [PATCH 3/4] Use double quoted patterns for more precise pattern matching in the binding.gyp files --- cli/src/generate/binding_files.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/generate/binding_files.rs b/cli/src/generate/binding_files.rs index 7b965cf5..c03a40e3 100644 --- a/cli/src/generate/binding_files.rs +++ b/cli/src/generate/binding_files.rs @@ -57,7 +57,7 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( eprintln!("Updating binding.gyp with new binding path"); let binding_gyp = fs::read_to_string(path).with_context(|| "Failed to read binding.gyp")?; - let binding_gyp = binding_gyp.replace("src/binding.cc", "bindings/node/binding.cc"); + let binding_gyp = binding_gyp.replace("\"src/binding.cc\"", "\"bindings/node/binding.cc\""); write_file(path, binding_gyp) }, )?; From d3527109a89a58999c8931ffc16f5d5331c94864 Mon Sep 17 00:00:00 2001 From: Andrew Hlynskyi Date: Wed, 23 Jun 2021 02:22:31 +0300 Subject: [PATCH 4/4] Updating of binding.gyp should depend on its content instead of bindings/node folder --- cli/src/generate/binding_files.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cli/src/generate/binding_files.rs b/cli/src/generate/binding_files.rs index c03a40e3..9f7980db 100644 --- a/cli/src/generate/binding_files.rs +++ b/cli/src/generate/binding_files.rs @@ -54,11 +54,15 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( &binding_gyp_path, |path| generate_file(path, BINDING_GYP_TEMPLATE, language_name), |path| { - eprintln!("Updating binding.gyp with new binding path"); let binding_gyp = fs::read_to_string(path).with_context(|| "Failed to read binding.gyp")?; - let binding_gyp = binding_gyp.replace("\"src/binding.cc\"", "\"bindings/node/binding.cc\""); - write_file(path, binding_gyp) + let old_path = "\"src/binding.cc\""; + if binding_gyp.contains(old_path) { + eprintln!("Updating binding.gyp with new binding path"); + let binding_gyp = binding_gyp.replace(old_path, "\"bindings/node/binding.cc\""); + write_file(path, binding_gyp)?; + } + Ok(()) }, )?; @@ -82,7 +86,6 @@ pub fn generate_binding_files(repo_path: &Path, language_name: &str) -> Result<( }); if package_json_needs_update { eprintln!("Updating package.json with new binding path"); - package_json.insert( "main".to_string(), serde_json::Value::String("bindings/node".to_string()),