mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
175 lines
5.3 KiB
Rust
175 lines
5.3 KiB
Rust
use console::Style;
|
|
use similar::{ChangeTag, TextDiff};
|
|
use std::path::{Path, PathBuf};
|
|
use std::str::FromStr;
|
|
use std::{
|
|
fs::{File, OpenOptions},
|
|
io::{Read, Write},
|
|
};
|
|
use tera::Tera;
|
|
use walkdir::WalkDir;
|
|
|
|
pub fn read_file(path: &str) -> Option<String> {
|
|
let mut file = File::open(path).unwrap_or_else(|_| panic!("Unable to open file at {}", path));
|
|
let mut content = String::new();
|
|
match file.read_to_string(&mut content) {
|
|
Ok(_) => Some(content),
|
|
Err(e) => {
|
|
log::error!("{}, with error: {:?}", path, e);
|
|
Some("".to_string())
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn save_content_to_file_with_diff_prompt(content: &str, output_file: &str) {
|
|
if Path::new(output_file).exists() {
|
|
let old_content = read_file(output_file).unwrap();
|
|
let new_content = content.to_owned();
|
|
let write_to_file = || match OpenOptions::new()
|
|
.create(true)
|
|
.write(true)
|
|
.append(false)
|
|
.truncate(true)
|
|
.open(output_file)
|
|
{
|
|
Ok(ref mut file) => {
|
|
file.write_all(new_content.as_bytes()).unwrap();
|
|
}
|
|
Err(err) => {
|
|
panic!("Failed to open log file: {}", err);
|
|
}
|
|
};
|
|
if new_content != old_content {
|
|
print_diff(old_content, new_content.clone());
|
|
write_to_file()
|
|
}
|
|
} else {
|
|
match OpenOptions::new().create(true).write(true).open(output_file) {
|
|
Ok(ref mut file) => file.write_all(content.as_bytes()).unwrap(),
|
|
Err(err) => panic!("Open or create to {} fail: {}", output_file, err),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn print_diff(old_content: String, new_content: String) {
|
|
let diff = TextDiff::from_lines(&old_content, &new_content);
|
|
for op in diff.ops() {
|
|
for change in diff.iter_changes(op) {
|
|
let (sign, style) = match change.tag() {
|
|
ChangeTag::Delete => ("-", Style::new().red()),
|
|
ChangeTag::Insert => ("+", Style::new().green()),
|
|
ChangeTag::Equal => (" ", Style::new()),
|
|
};
|
|
|
|
match change.tag() {
|
|
ChangeTag::Delete => {
|
|
print!("{}{}", style.apply_to(sign).bold(), style.apply_to(change));
|
|
}
|
|
ChangeTag::Insert => {
|
|
print!("{}{}", style.apply_to(sign).bold(), style.apply_to(change));
|
|
}
|
|
ChangeTag::Equal => {}
|
|
};
|
|
}
|
|
println!("---------------------------------------------------");
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn is_crate_dir(e: &walkdir::DirEntry) -> bool {
|
|
let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string();
|
|
cargo == *"Cargo"
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn is_proto_file(e: &walkdir::DirEntry) -> bool {
|
|
if e.path().extension().is_none() {
|
|
return false;
|
|
}
|
|
let ext = e.path().extension().unwrap().to_str().unwrap().to_string();
|
|
ext == *"proto"
|
|
}
|
|
|
|
pub fn is_hidden(entry: &walkdir::DirEntry) -> bool {
|
|
entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false)
|
|
}
|
|
|
|
pub fn create_dir_if_not_exist(dir: &Path) {
|
|
if !dir.exists() {
|
|
std::fs::create_dir_all(dir).unwrap();
|
|
}
|
|
}
|
|
|
|
pub fn path_string_with_component(path: &Path, components: Vec<&str>) -> String {
|
|
path_buf_with_component(path, components).to_str().unwrap().to_string()
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn path_buf_with_component(path: &Path, components: Vec<&str>) -> PathBuf {
|
|
let mut path_buf = path.to_path_buf();
|
|
for component in components {
|
|
path_buf.push(component);
|
|
}
|
|
path_buf
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn walk_dir<P: AsRef<Path>, F1, F2>(dir: P, filter: F2, mut path_and_name: F1)
|
|
where
|
|
F1: FnMut(String, String),
|
|
F2: Fn(&walkdir::DirEntry) -> bool,
|
|
{
|
|
for (path, name) in WalkDir::new(dir)
|
|
.into_iter()
|
|
.filter_map(|e| e.ok())
|
|
.filter(|e| filter(e))
|
|
.map(|e| {
|
|
(
|
|
e.path().to_str().unwrap().to_string(),
|
|
e.path().file_stem().unwrap().to_str().unwrap().to_string(),
|
|
)
|
|
})
|
|
{
|
|
path_and_name(path, name);
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn suffix_relative_to_path(path: &str, base: &str) -> String {
|
|
let base = Path::new(base);
|
|
let path = Path::new(path);
|
|
path.strip_prefix(base).unwrap().to_str().unwrap().to_owned()
|
|
}
|
|
|
|
pub fn get_tera(directory: &str) -> Tera {
|
|
let mut root = format!("{}/src/code_gen/", env!("CARGO_MANIFEST_DIR"));
|
|
root.push_str(directory);
|
|
|
|
let root_absolute_path = match std::fs::canonicalize(&root) {
|
|
Ok(p) => p.as_path().display().to_string(),
|
|
Err(e) => {
|
|
panic!("❌ Canonicalize file path {} failed {:?}", root, e);
|
|
}
|
|
};
|
|
|
|
let mut template_path = format!("{}/**/*.tera", root_absolute_path);
|
|
if cfg!(windows) {
|
|
// remove "\\?\" prefix on windows
|
|
template_path = format!("{}/**/*.tera", &root_absolute_path[4..]);
|
|
}
|
|
|
|
match Tera::new(template_path.as_ref()) {
|
|
Ok(t) => t,
|
|
Err(e) => {
|
|
log::error!("Parsing error(s): {}", e);
|
|
::std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn cache_dir() -> PathBuf {
|
|
let mut path_buf = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")).unwrap();
|
|
path_buf.push(".cache");
|
|
path_buf
|
|
}
|