Open 0xqd opened 3 months ago
Check out rust build macros. That's what I use to copy things over for my builds, along with running the tailwindCSS executable to minify my CSS.
https://doc.rust-lang.org/cargo/reference/build-scripts.html
If you need a starter, I can give you some of my build script code.
Here's my build.rs
anyway: (Just ignore some of the bits about windows, I'm still trying to get it cross platform, but haven't gotten far enough yet.)
use std::env;
//use std::fs::create_dir;
use std::io::ErrorKind;
use std::path::PathBuf;
use std::process::Command;
//use std::thread::current;
//use regex::Regex;
fn main() {
//let out_dir = env::var("OUT_DIR").unwrap();
//Get the current directory
let current_dir = String::from(format!(
"{}",
env::current_dir().expect("current_dir failed!").display()
));
//use regex::Regex;
//let re = Regex::new(r"[A-Za-z]").unwrap();
//let result = re.replace_all("Hello World!", "x");
//println!("{}", result); // => "xxxxx xxxxx!"
// let icon_str = Regex::new(r##"fill=["'].*['"]"##).unwrap().replace_all(
// include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/img/heroicons/src/24/solid/chevron-right.svg")),
// "fill='white'"
// ).into_owned();
if cfg!(windows) {
println!("cargo:warning=windows-specific-directory");
//cd C:\
//mkdir dev
//cd dev
//mkdir vcpkg
//cd vcpkg
//git clone https://github.com/microsoft/vcpkg
//.\vcpkg\bootstrap-vcpkg.bat
//cd C:\dev\vcpkg\vcpkg
//.\vcpkg install openssl:x64-windows-static
//mkdir "C:\Program Files\OpenSSL-Win64\certs"
//winget install curl
//C:\Program` Files\Git\mingw64\bin\curl --remote-name "C:\Program` Files\OpenSSL-Win64\certs\cacert.pem" -o "C:\Program` Files\OpenSSL-Win64\certs\cacert.pem" https://curl.se/ca/cacert.pem
//set OPENSSL_NO_VENDOR=1
//set RUSTFLAGS=-Ctarget-feature=+crt-static
//set SSL_CERT_FILE=C:\OpenSSL-Win64\certs\cacert.pem
/*
I just had this issue and none of them worked, but here is what worked for me on Windows 11.
Install OpenSSL from http://slproweb.com/products/Win32OpenSSL.html into C:\Program Files\OpenSSL-Win64
Set all your env variables, for me I set OPENSSL_CONF to C:\Program Files\OpenSSL-Win64\bin\openssl.cfg and added C:\Program Files\OpenSSL-Win64\bin to my path.
Download the cert, assuming you have wget installed, wget https://curl.se/ca/cacert.pem -o cacert.pem into C:\Program Files\OpenSSL-Win64\certs
Next step is to set up your environment for building openssl run in powershell:
$env:OPENSSL_NO_VENDOR=1
$env:RUSTFLAGS='-Ctarget-feature=+crt-static'
$env:SSL_CERT = 'C:\OpenSSL-Win64\certs\cacert.pem'
$env:OPENSSL_DIR = 'C:\Program Files\OpenSSL-Win64'
and run cargo build
*/
} else {
println!("cargo:warning=unix-directory");
};
if cfg!(target_os = "windows") {
println!("Windows detected!");
Command::new("cmd")
.args(["/C", "echo hello"])
.output()
.expect("failed to execute process");
return;
} else {
Command::new("sh")
.arg("-c")
.arg("echo hello")
.output()
.expect("failed to execute process");
}
//let src_dir : PathBuf = [ ¤t_dir, "src" ].iter().collect();
//Setup the assets output directory
let assets_dir: PathBuf = [¤t_dir, "assets"].iter().collect();
//copy the css files
let css_dir: PathBuf = [¤t_dir, "src", "css"].iter().collect();
copy_dir(&css_dir, &assets_dir).expect("cargo:warning=Failed to copy_dir!");
//Minify the CSS with the tailwindcss tool, thus overwriting the site.css file
if cfg!(target_os = "linux") {
let tailwindcss_status = Command::new("./tailwindcss-linux-x64_v3.2.4")
.arg("-i")
.arg("src/css/site.css")
.arg("-o")
.arg("assets/css/site.css")
.arg("--minify")
.spawn()
.expect("Tailwind command failed to start!");
println!("cargo:warning=tailwindcss-linux-x64 ran with status: '{tailwindcss_status:?}'");
}
//copy the favicon over
let favicon_from_path : PathBuf = [¤t_dir, "src", "favicon.ico"].iter().collect();
let favicon_to_path : PathBuf = [¤t_dir, "assets", "favicon.ico"].iter().collect();
std::fs::copy(favicon_from_path, favicon_to_path).expect("cargo:warning=Failed to copy favicon.ico!");
//copy the images over
let img_dir: PathBuf = [¤t_dir, "src", "img"].iter().collect();
copy_dir(&img_dir, &assets_dir).expect("cargo:warning=Failed to copy_dir!");
//copy the template pages over
//let pages_dir: PathBuf = [¤t_dir, "src", "pages"].iter().collect();
//copy_dir(&pages_dir, &assets_dir).expect("cargo:warning=Failed to copy_dir!");
//copy the js files over
let js_dir: PathBuf = [¤t_dir, "src", "js"].iter().collect();
copy_dir(&js_dir, &assets_dir).expect("cargo:warning=Failed to copy_dir!");
//copy the component js files over
std::fs::create_dir_all(PathBuf::from_iter([¤t_dir, "assets", "js", "components"].iter()))
.expect("failed to create director(y/ies)!");
let components_dir: PathBuf = [¤t_dir, "src", "pages", "components"].iter().collect();
copy_files_with_extension(&components_dir,
&PathBuf::from_iter([¤t_dir, "assets", "js", "components"].iter()),
".js")
.expect("cargo:warning=Failed to copy_dir!");
//let dest_path = Path::new(&out_dir).join("hello.rs");
//let mut f = File::create(&dest_path).unwrap();
// f.write_all(b"
// pub fn message() -> &'static str {
// \"Hello, World!\"
// }
// ").unwrap();
}
/// don't call this except when in copy_dir, or recursive_copy_dir.
fn recursive_copy_dir(from: &PathBuf, to: &PathBuf) -> Result<(), std::io::Error> {
// println!("cargo:warning=recursive_copy_dir entered! from: {:?}",from.clone().display());
// println!("cargo:warning=recursive_copy_dir entered! to : {:?}",to.clone().display());
for entry in std::fs::read_dir(from)? {
let path = entry.expect("failed to read entry").path();
// let metadata = std::fs::metadata(&path)?;
// let last_modified = metadata
// .modified()?
// .elapsed()
// .expect("std::io::Error")
// .as_secs();
// if last_modified < 24 * 3600 && metadata.is_file() {
// println!(
// "cargo:warning=Last modified: {:?} seconds, is read only: {:?}, size: {:?} bytes, filename: {:?}",
// last_modified,
// metadata.permissions().readonly(),
// metadata.len(),
// path.file_name().ok_or("No filename").expect("No filename!")
// );
// }
if path.is_file() {
let from_filename = path.file_name().expect("filename not found!");
let to_filepath = [to, &PathBuf::from(from_filename)].iter().collect::<PathBuf>();
// println!("cargo:warning=path.is_file()");
// println!("cargo:warning=from{:?} to filepath{:?}",&path,&filepath);
let from_attr = std::fs::metadata(&path)?;
//Check if the file already exists
match std::fs::metadata(&to_filepath) {
Ok(to_attr) => {
//File exists in the target location
match from_attr.modified() {
Ok(from_modified) => {
match to_attr.modified() {
Ok(to_modified) => {
//Only copy files over where the modification date is different
if from_modified != to_modified {
std::fs::copy(path, &to_filepath)?;
}
},
Err(err) => {
println!("cargo:warning=Unable to determine to's modified value: {:?}. Cannot continue. Error: {:?}",&to_attr,&err);
}
}
},
Err(err) => {
println!("cargo:warning=Unable to determine from's modified value: {:?}. Cannot continue. Error: {:?}",&from_attr,&err);
},
}
},
Err(err)=> {
//File does not exist or there is an error reading the to location path
if err.kind() == ErrorKind::NotFound {
std::fs::copy(path, &to_filepath)?;
} else {
println!("cargo:warning=Unable to determine to_filepath's modified value: {:?}. Cannot continue. Error: {:?}",&from_attr,&err);
}
}
}
//std::fs::copy(path, &filepath)?;
} else if path.is_dir() {
//If the current item we are copying is a directory, we need to create it
//println!("cargo:warning=path.is_dir()");
let dirname = path.file_name().expect("filename not found!");
match dirname.to_str() {
Some(dirname_str) => {
//Don't copy over .hidden directories
if dirname_str.starts_with(".") == false {
let directory_path_to_create = [to, &PathBuf::from(dirname)].iter().collect();
//println!("cargo:warning=from {:?} to directory_path_to_create {:?}",&path,&directory_path_to_create);
std::fs::create_dir_all(&directory_path_to_create)
.expect("failed to create director(y/ies)!");
recursive_copy_dir(&path, &directory_path_to_create)?;
}
},
None => {
},
}
} else {
// Skip other content
}
//println!("cargo:warning=Counter is: {:?}", counter.clone());
}
Ok(())
}
/// Recursively copies the contents of one directory to another. This function will also copy the
/// permission bits of the original files to the destination files.
///
/// This function will **overwrite** the contents of `to`, if files have the same name.
///
/// On success, the total number of files and directories copied is returned.
///
/// ## Errors
///
/// This function will return an error in the following situations, but is not limited to just
/// these cases:
///
/// - The `from` path is not a directory
/// - The `from` path does not exist
/// - The current process does not have the permission rights to access `from` or write `to`
pub fn copy_dir(from: &PathBuf, to: &PathBuf) -> Result<(), std::io::Error> {
//let to_buf = to.as_ref().to_path_buf();
// println!("cargo:warning=copy_dir entered! from: {:?}",from.clone().display());
// println!("cargo:warning=copy_dir entered! to : {:?}",to.clone().display());
//First check if the path even exists
if !from.as_path().exists() {
//println!("cargo:warning=copy from directory doesn't exist! Exists?'{:?}' ", from.as_path().exists());
return Ok(());
}
let mut from_directory_name: Option<PathBuf> = None;
//If we are copying a directory, we need to create the directory on the target, and change the copy command
if from.as_path().is_dir() {
let directory_to_create = from
.as_path()
.file_name()
.expect("unable to get directory name!");
// println!("cargo:warning=directory_to_create {:?} to.as_path() {:?}", directory_to_create, to.as_path().file_name());
let directory_path_to_create: PathBuf =
[to.to_path_buf().as_os_str(), &directory_to_create]
.iter()
.collect();
// println!("cargo:warning=directory_path_to_create {:?}", directory_path_to_create);
//Check if directory already exists
match std::fs::metadata(&directory_path_to_create) as std::io::Result<std::fs::Metadata> {
Ok(ref _directory_metadata) => {
// println!("cargo:warning=NOT creating: {:?} MetaData: {:?}", &directory_path_to_create, &directory_metadata);
from_directory_name = Some(PathBuf::from(directory_to_create));
}
_ => {
// println!("cargo:warning=YES creating: {:?}", &directory_path_to_create);
std::fs::create_dir_all(&directory_path_to_create)
.expect("failed to create director(y/ies)!");
from_directory_name = Some(PathBuf::from(directory_to_create));
}
}
} else {
// println!("cargo:warning=from.as_path().is_dir() {:?}", &from.as_path().is_dir());
}
//If we are copying from a directory we need to use the new path
match from_directory_name {
Some(ref directory_name) => {
// println!("cargo:warning=match directory_created SOME to:{:?}",
// &[to.to_path_buf(), directory_name.clone().to_path_buf()].iter().collect::<PathBuf>()
// );
recursive_copy_dir(
from,
&[to.to_path_buf(), directory_name.to_path_buf()]
.iter()
.collect::<PathBuf>(),
)
.expect("Failed to recursive_copy_dir:Some!");
}
None => {
// println!("cargo:warning=match directory_created NONE to:{:?}",
// &[to.to_path_buf()].iter().collect::<PathBuf>()
// );
recursive_copy_dir(from, to).expect("failed to recursive_copy_dir:None!");
}
};
Ok(())
}
/// Recursively copies the contents of one directory to another. This function will also copy the
/// permission bits of the original files to the destination files.
///
/// This function will **overwrite** the contents of `to`, if files have the same name.
///
/// On success, the total number of files and directories copied is returned.
///
/// ## Errors
///
/// This function will return an error in the following situations, but is not limited to just
/// these cases:
///
/// - The `from` path is not a directory
/// - The `from` path does not exist
/// - The current process does not have the permission rights to access `from` or write `to`
pub fn copy_files_with_extension(from: &PathBuf, to: &PathBuf, file_extension_limiter: &str) -> Result<(), std::io::Error> {
//let to_buf = to.as_ref().to_path_buf();
// println!("cargo:warning=copy_dir entered! from: {:?}",from.clone().display());
// println!("cargo:warning=copy_dir entered! to : {:?}",to.clone().display());
//First check if the path even exists
if !from.as_path().exists() {
//println!("cargo:warning=copy from directory doesn't exist! Exists?'{:?}' ", from.as_path().exists());
return Ok(());
}
for entry in std::fs::read_dir(from)? {
let path = entry.expect("failed to read entry").path();
// let metadata = std::fs::metadata(&path)?;
// let last_modified = metadata
// .modified()?
// .elapsed()
// .expect("std::io::Error")
// .as_secs();
// if last_modified < 24 * 3600 && metadata.is_file() {
// println!(
// "cargo:warning=Last modified: {:?} seconds, is read only: {:?}, size: {:?} bytes, filename: {:?}",
// last_modified,
// metadata.permissions().readonly(),
// metadata.len(),
// path.file_name().ok_or("No filename").expect("No filename!")
// );
// }
if path.is_file() && path.display().to_string().ends_with(file_extension_limiter) {
let from_filename = path.file_name().expect("filename not found!");
let to_filepath = [to, &PathBuf::from(from_filename)].iter().collect::<PathBuf>();
// println!("cargo:warning=path.is_file()");
// println!("cargo:warning=from{:?} to filepath{:?}",&path,&filepath);
let from_attr = std::fs::metadata(&path)?;
//Check if the file already exists
match std::fs::metadata(&to_filepath) {
Ok(to_attr) => {
//File exists in the target location
match from_attr.modified() {
Ok(from_modified) => {
match to_attr.modified() {
Ok(to_modified) => {
//Only copy files over where the modification date is different
if from_modified != to_modified {
std::fs::copy(path, &to_filepath)?;
}
},
Err(err) => {
println!("cargo:warning=Unable to determine to's modified value: {:?}. Cannot continue. Error: {:?}",&to_attr,&err);
}
}
},
Err(err) => {
println!("cargo:warning=Unable to determine from's modified value: {:?}. Cannot continue. Error: {:?}",&from_attr,&err);
},
}
},
Err(err)=> {
//File does not exist or there is an error reading the to location path
if err.kind() == ErrorKind::NotFound {
std::fs::copy(path, &to_filepath)?;
} else {
println!("cargo:warning=Unable to determine to_filepath's modified value: {:?}. Cannot continue. Error: {:?}",&from_attr,&err);
}
}
}
//std::fs::copy(path, &filepath)?;
} else if path.is_dir() {
//If the current item we are copying is a directory, we need to create it
//println!("cargo:warning=path.is_dir()");
let dirname = path.file_name().expect("filename not found!");
match dirname.to_str() {
Some(dirname_str) => {
//Don't copy over .hidden directories
if dirname_str.starts_with(".") == false {
//let directory_path_to_create = [to, &PathBuf::from(dirname)].iter().collect();
//println!("cargo:warning=from {:?} to directory_path_to_create {:?}",&path,&directory_path_to_create);
// std::fs::create_dir_all(&directory_path_to_create)
// .expect("failed to create director(y/ies)!");
// recursive_copy_dir_files_with_extension(&path, &directory_path_to_create, file_extension_limiter)?;
}
},
None => {
},
}
} else {
// Skip other content
}
//println!("cargo:warning=Counter is: {:?}", counter.clone());
}
Ok(())
}
Thanks for sharing!
My approach is simpler, it would be something like this:
cp -R a /b; cd b/; ./sailfish-cli .
You can of sailfish-cli is a general tool just like tera-cli https://github.com/chevdor/tera-cli
Features: I need a sailfish-cli tool to transform a nested folder
a
to folderb
, will transform all files with ext.stpl tob
same folder structure with files without .stpl. I have looked into sailfish and compiler, it mostly support macro for now which is a bit hard to navigate around. The dictionaries data to do the translation can be environment variable or config file through--config, -c
If there is any hint to get it done? Thanks
Would this bash script suffice?
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Usage: $0 path_a path_b"
exit 1
fi
path_a="$1"
path_b="$2"
if [ ! -d "$path_b" ]; then
mkdir -p "$path_b"
fi
for file in "$path_a"/*; do
filename=$(basename "$file")
# Check if file has .stpl extension
if [[ "$filename" == *.stpl ]]; then
new_filename="${filename%.stpl}"
mv "$file" "$path_b/$new_filename"
else
mv "$file" "$path_b/$filename"
fi
done
This doesn't include the part of translating stpl file. The copy part with script is easy, hard part is doing translate recursively the whole directory without writing macro like what we normally do with sailfish. That's why I ask about how to use sailfish compiler directly.
Features: I need a sailfish-cli tool to transform a nested folder
a
to folderb
, will transform all files with ext.stpl tob
same folder structure with files without .stpl. I have looked into sailfish and compiler, it mostly support macro for now which is a bit hard to navigate around. The dictionaries data to do the translation can be environment variable or config file through--config, -c
If there is any hint to get it done? Thanks