Skip to content

Commit

Permalink
many fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Moeglich committed Oct 7, 2024
1 parent c2114e8 commit 9cf2eee
Show file tree
Hide file tree
Showing 16 changed files with 352 additions and 208 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "weaveconfig"
version = "0.1.2"
version = "0.2.0"
edition = "2021"
description = "A unified configuration tool for monorepos"
readme = "README.md"
Expand Down Expand Up @@ -32,4 +32,4 @@ lto = "fat"

[profile.dev]
opt-level = 0
debug = true
debug = true
90 changes: 67 additions & 23 deletions src/apply_resolved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use std::{

use anyhow::Context;
use futures::{stream::FuturesUnordered, StreamExt};
use serde_json::Map;

use crate::{
map_path::map_path, resolve_spaces::ResolvedSpace, template_file::template_file,
get_environment_value::get_environment_value, map_path::map_path,
resolve_spaces::ResolvedSpace, template_file::template_file,
ts_binding::generate_binding::generate_binding, write_json_file::write_json_file,
};

Expand Down Expand Up @@ -42,10 +42,14 @@ async fn apply_space(space: ResolvedSpace, real_path: PathBuf) -> Result<(), any
real_path.display()
));
}
let gen_folder = gen_folder(&real_path).await?;
write_gitignore(&gen_folder).await?;
write_json_file(&space, &gen_folder).await?;
generate_binding(&space, &gen_folder).await?;
if space.generate.generate && space.variables.is_some() {
let gen_folder = gen_folder(&real_path).await?;
write_gitignore(&gen_folder).await?;
write_json_file(&space, &gen_folder).await?;
if space.generate.typescript {
generate_binding(&space, &gen_folder).await?;
}
}
write_to_copy(&space, &real_path).await?;
Ok(())
}
Expand All @@ -58,25 +62,65 @@ async fn write_gitignore(gen_folder: &PathBuf) -> Result<(), anyhow::Error> {
Ok(())
}

async fn write_to_copy(space: &ResolvedSpace, real_path: &PathBuf) -> Result<(), anyhow::Error> {
for origin in &space.files_to_copy {
let dest_relative = origin.strip_prefix(&space.path).unwrap();
let dest = real_path.join(dest_relative);

let content = tokio::fs::read_to_string(origin).await?;
let content = {
let variables = space.variables.clone().unwrap_or(Map::new());
template_file(&content, &variables)
.with_context(|| format!("Failed to template file: {}", origin.display()))?
};

// create parent dirs
if let Some(parent) = dest.parent() {
if !parent.exists() {
tokio::fs::create_dir_all(parent).await?;
async fn write_to_copy(space: &ResolvedSpace, real_path: &Path) -> Result<(), anyhow::Error> {
// Prepare variables once to avoid cloning multiple times
let variables = space.variables.clone().unwrap_or_default();

for to_copy in &space.files_to_copy {
// Determine the relative destination path
let dest_relative = to_copy
.path
.strip_prefix(&space.path)
.with_context(|| format!("Failed to strip prefix for {}", to_copy.path.display()))?;

// Read the file content asynchronously
let content = tokio::fs::read_to_string(&to_copy.path)
.await
.with_context(|| format!("Failed to read file: {}", to_copy.path.display()))?;

// Compute the full destination path
let mapped_dist = real_path.join(dest_relative);

// Create parent directories if they don't exist
if let Some(parent) = mapped_dist.parent() {
tokio::fs::create_dir_all(parent)
.await
.with_context(|| format!("Failed to create directories: {}", parent.display()))?;
}

if to_copy.for_each_env {
// Iterate over each environment and write templated files
for env in &space.environments {
let env_variables = get_environment_value(&variables, env)
.with_context(|| format!("Failed to get variables for environment: {}", env))?;

let templated_content =
template_file(&content, &env_variables).with_context(|| {
format!(
"Failed to template file for environment {}: {}",
env,
to_copy.path.display()
)
})?;

let dest = mapped_dist.with_file_name(format!("{}.{}", env, to_copy.dest_filename));

tokio::fs::write(&dest, templated_content)
.await
.with_context(|| format!("Failed to write file: {}", dest.display()))?;
}
} else {
// Template the content once and write to the destination
let templated_content = template_file(&content, &variables)
.with_context(|| format!("Failed to template file: {}", to_copy.path.display()))?;

let dest = mapped_dist.with_file_name(&to_copy.dest_filename);

tokio::fs::write(&dest, templated_content)
.await
.with_context(|| format!("Failed to write file: {}", dest.display()))?;
}
tokio::fs::write(dest, content).await?;
}

Ok(())
}
4 changes: 2 additions & 2 deletions src/bin/weaveconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use weaveconfig::generate_weaveconfig;

#[derive(Parser)]
#[command(
name = "weaveconfig-cli",
version = "0.1.2",
name = "weaveconfig",
version = "0.1.3",
author = "Jeremy Moeglich <[email protected]>",
about = "A CLI to manage weaveconfig configurations"
)]
Expand Down
27 changes: 23 additions & 4 deletions src/file_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct Directory {
pub path: PathBuf,
pub parent_directory: Option<PathBuf>,
pub space: Option<SpaceNode>,
pub rest_to_copy: Vec<PathBuf>,
pub rest_to_copy: Vec<FileToCopy>,
}

#[derive(Debug, Clone, PartialEq)]
Expand All @@ -20,6 +20,13 @@ pub struct SpaceNode {
pub variables: Option<serde_json::Map<String, serde_json::Value>>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct FileToCopy {
pub path: PathBuf,
pub dest_filename: String,
pub for_each_env: bool,
}

/// Creates a graph of the weaveconfig configuration.
/// The root of the graph is typically the `weaveconfig` directory within the project root.
pub async fn traverse_directory(
Expand Down Expand Up @@ -136,7 +143,7 @@ async fn locate_directories(directory: &mut Directory) -> Result<(), anyhow::Err
enum FileType {
Space(SpaceSchema),
Variables(serde_json::Map<String, serde_json::Value>),
Rest(PathBuf),
Rest(FileToCopy),
}

async fn process_file(file_path: PathBuf) -> Result<FileType, anyhow::Error> {
Expand Down Expand Up @@ -188,13 +195,25 @@ async fn process_file(file_path: PathBuf) -> Result<FileType, anyhow::Error> {
map.insert(prefix, serde_json::Value::Object(variables));
Ok(FileType::Variables(map))
}
segments if segments.first() == Some(&"_forenv") => {
let dest_filename = segments[1..].join(".");
Ok(FileType::Rest(FileToCopy {
path: file_path,
dest_filename,
for_each_env: true,
}))
}
_ => Err(anyhow!(
"Invalid file name format: '{}'. Expected '_space.json', '_env.json', or '_<prefix>_env.json'.",
"Invalid file name format: '{}'. Expected '_space.json', '_env.json', '_<prefix>_env.json' or '_forenv.<rest>'.",
file_name
)),
}
} else {
Ok(FileType::Rest(file_path))
Ok(FileType::Rest(FileToCopy {
path: file_path.clone(),
dest_filename: file_name.to_string(),
for_each_env: false,
}))
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/get_environment_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use serde_json::{Map, Value};

use crate::template_file::value_type;

pub fn get_environment_value(
variables: &Map<String, Value>,
environment: &str,
) -> Result<Map<String, Value>, anyhow::Error> {
let environment_variables = variables.get(environment).ok_or(anyhow::anyhow!(
"Environment {} not found in variables, this is an internal error",
environment
))?;
let mut variables = variables.clone();
if let Value::Object(environment_variables) = environment_variables {
for (key, value) in environment_variables {
variables.insert(key.clone(), value.clone());
}
return Ok(variables);
}
Err(anyhow::anyhow!(
"Expected an object, got {}",
value_type(environment_variables)
))
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod ts_binding;
mod write_json_file;
mod template_file;
mod parse_jsonc;
mod get_environment_value;

pub async fn generate_weaveconfig(weaveconfig_config_root: &Path) -> Result<()> {
let directory = traverse_directory(weaveconfig_config_root).await?;
Expand Down
28 changes: 19 additions & 9 deletions src/resolve_spaces.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::{merging::merge_map_consume, space_graph::SpaceGraph};
use crate::{
file_graph::FileToCopy,
merging::merge_map_consume,
space_graph::{GenerateSpace, SpaceGraph},
};
use anyhow::{Context, Result};
use serde_json::{Map, Value};
use std::{
Expand All @@ -11,7 +15,8 @@ pub struct ResolvedSpace {
pub variables: Option<Map<String, Value>>,
pub environments: HashSet<String>,
pub path: PathBuf,
pub files_to_copy: Vec<PathBuf>,
pub files_to_copy: Vec<FileToCopy>,
pub generate: GenerateSpace,
}

pub fn resolve_spaces(space_graph: SpaceGraph) -> Result<HashMap<String, ResolvedSpace>> {
Expand Down Expand Up @@ -91,7 +96,11 @@ fn resolve_space(
for env in &space.environments {
variables
.entry(env.clone())
.or_insert(Value::Object(Map::new()));
.or_insert_with(|| Value::Object(Map::new()));
if let Some(Value::Object(obj)) = variables.get_mut(env) {
obj.entry("env".to_string())
.or_insert(Value::String(env.clone()));
}
}
}

Expand All @@ -102,6 +111,7 @@ fn resolve_space(
environments: space.environments.clone(),
path: space.path.clone(),
files_to_copy: space.files_to_copy.clone(),
generate: space.generate.clone(),
},
);

Expand Down Expand Up @@ -138,7 +148,7 @@ fn resolve_dependency(
}

if let Some(ref mut value) = to_merge {
move_key(value, from_env, to_env);
copy_key(value, from_env, to_env);
} else {
return Err(anyhow::anyhow!(
"No variables present to move from '{}' to '{}'",
Expand All @@ -150,7 +160,7 @@ fn resolve_dependency(
}
}

if let Some(to_merge) = to_merge {
if let Some(mut to_merge) = to_merge {
if let Some(ref mut value) = variables {
merge_map_consume(value, to_merge).with_context(|| {
format!(
Expand All @@ -166,9 +176,9 @@ fn resolve_dependency(
Ok(())
}

fn move_key(value: &mut Map<String, Value>, from_key: &str, to_key: &str) {
let current = value.remove(from_key);
if let Some(current) = current {
value.insert(to_key.to_string(), current);
fn copy_key(value: &mut Map<String, Value>, from_key: &str, to_key: &str) {
if let Some(current) = value.get(from_key) {
let copied = current.clone();
value.insert(to_key.to_string(), copied);
}
}
32 changes: 29 additions & 3 deletions src/space_graph.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::{collections::HashMap, path::PathBuf};

use crate::file_graph::Directory;
use crate::{
file_graph::{Directory, FileToCopy},
schemas::GenerateSchema,
};
use std::collections::HashSet;

#[derive(Debug, Clone, PartialEq)]
Expand All @@ -11,8 +14,15 @@ pub struct Space {
pub mapping: Option<HashMap<String, Vec<String>>>,
pub environments: HashSet<String>,
pub variables: Option<serde_json::Map<String, serde_json::Value>>,
pub files_to_copy: Vec<PathBuf>,
pub files_to_copy: Vec<FileToCopy>,
pub parent_space: Option<String>,
pub generate: GenerateSpace,
}

#[derive(Debug, Clone, PartialEq)]
pub struct GenerateSpace {
pub generate: bool,
pub typescript: bool,
}

pub type SpaceGraph = HashMap<String, Space>;
Expand Down Expand Up @@ -53,6 +63,22 @@ fn add_to_spaces_graph(
variables: space.variables,
files_to_copy: vec![],
parent_space: closest_parent_space,
generate: {
match space.schema.generate {
Some(GenerateSchema::Generate(generate)) => GenerateSpace {
generate: true,
typescript: generate.typescript,
},
Some(GenerateSchema::ShouldGenerate(generate)) => GenerateSpace {
generate,
typescript: true,
},
None => GenerateSpace {
generate: true,
typescript: true,
},
}
},
};
resolve_files_to_copy(&dir, &mut space.files_to_copy);
space_graph.insert(space.name.clone(), space);
Expand All @@ -63,7 +89,7 @@ fn add_to_spaces_graph(
}
}

fn resolve_files_to_copy(dir: &Directory, files: &mut Vec<PathBuf>) {
fn resolve_files_to_copy(dir: &Directory, files: &mut Vec<FileToCopy>) {
for file in &dir.rest_to_copy {
files.push(file.clone());
}
Expand Down
2 changes: 1 addition & 1 deletion src/template_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub enum VariableError {
InvalidType(String, String),
}

fn value_type(value: &Value) -> String {
pub fn value_type(value: &Value) -> String {
match value {
Value::String(_) => "string",
Value::Number(_) => "number",
Expand Down
Loading

0 comments on commit 9cf2eee

Please sign in to comment.