use std::fs;
use std::fs::create_dir;
use std::fs::create_dir_all;
use std::io;
use std::path::Path;
use std::path::PathBuf;
use anyhow::anyhow;
use anyhow::Context;
use labt_proc_macro::labt_lua;
use mlua::Lua;
use crate::submodules::build::is_file_newer;
use super::MluaAnyhowWrapper;
#[labt_lua]
fn mkdir(_lua: &Lua, path: String) {
let path = PathBuf::from(path);
let path = if path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(path);
root
} else {
path
};
create_dir(&path)
.context(format!("Failed to create directory {:?}", path))
.map_err(MluaAnyhowWrapper::external)?;
Ok(())
}
pub fn copy_recursively(src: &Path, dest: &Path) -> io::Result<()> {
fs::create_dir_all(dest)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let filetype = entry.file_type()?;
if filetype.is_dir() {
copy_recursively(&entry.path(), &dest.join(entry.file_name()))?;
} else {
fs::copy(entry.path(), dest.join(entry.file_name()))?;
}
}
Ok(())
}
#[labt_lua]
fn copy(_lua: &Lua, (src, dest, recursive): (String, String, Option<bool>)) {
let src_path = PathBuf::from(src);
let src_path = if src_path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(src_path);
root
} else {
src_path
};
let dest_path = PathBuf::from(dest);
let mut dest_path = if dest_path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(dest_path);
root
} else {
dest_path
};
let recursive = recursive.unwrap_or(false);
if src_path.is_dir() {
if !recursive {
Err(anyhow!("Attempt to copy directory without recursive mode"))
.map_err(MluaAnyhowWrapper::external)?;
}
copy_recursively(&src_path, &dest_path)
.context("Failed to copy folder recursively")
.map_err(MluaAnyhowWrapper::external)?;
} else {
if dest_path.is_dir() {
let name = src_path
.file_name()
.context("Unable to obtain the source file name")
.map_err(MluaAnyhowWrapper::external)?;
dest_path.push(name);
}
fs::copy(src_path, dest_path)
.context("Failed to copy file to destination")
.map_err(MluaAnyhowWrapper::external)?;
}
Ok(())
}
#[labt_lua]
fn mv(_lua: &Lua, (src, dest): (String, String)) {
let src_path = PathBuf::from(src);
let src_path = if src_path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(src_path);
root
} else {
src_path
};
let dest_path = PathBuf::from(dest);
let dest_path = if dest_path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(dest_path);
root
} else {
dest_path
};
fs::rename(src_path, dest_path)?;
Ok(())
}
#[labt_lua]
fn rm(_lua: &Lua, (path, recursive): (String, Option<bool>)) {
let path = PathBuf::from(path);
let path = if path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(path);
root
} else {
path
};
let recursive = recursive.unwrap_or(false);
if path.is_dir() {
if recursive {
fs::remove_dir_all(path)?;
} else {
fs::remove_dir(path)?;
}
} else {
fs::remove_file(path)?;
}
Ok(())
}
#[labt_lua]
fn mkdir_all(_lua: &Lua, path: String) {
let path = PathBuf::from(path);
let path = if path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(path);
root
} else {
path
};
create_dir_all(&path)
.context(format!("Failed to create directory {:?}", path))
.map_err(MluaAnyhowWrapper::external)?;
Ok(())
}
#[labt_lua]
fn exists(_lua: &Lua, path: String) {
let path = PathBuf::from(path);
let exists = path
.try_exists()
.context("Failed to test if file exists")
.map_err(MluaAnyhowWrapper::external)?;
Ok(exists)
}
#[labt_lua]
fn glob(_lua: &Lua, pattern: String) {
let path: PathBuf = PathBuf::from(&pattern);
let pattern = if path.is_relative() {
let mut root = crate::get_project_root()
.context("Failed to get project root directory")
.map_err(MluaAnyhowWrapper::external)?
.clone();
root.push(path);
if let Some(pattern) = root.to_str() {
pattern.to_string()
} else {
return Err(mlua::Error::runtime(
"Failed to convert pattern to unicode format",
));
}
} else {
pattern
};
let globals: Vec<String> = glob::glob(pattern.as_str())
.context("Failed to parse glob pattern")
.map_err(MluaAnyhowWrapper::external)?
.filter_map(|p| match p {
Ok(path) => path.to_str().map(|n| n.to_string()),
Err(_) => None,
})
.collect();
Ok(globals)
}
#[labt_lua]
fn is_newer(_lua: &Lua, (a, b): (String, String)) {
let path_a = PathBuf::from(a);
let path_b = PathBuf::from(b);
let result = is_file_newer(&path_a, &path_b)
.context("Failed to compare files a and b")
.map_err(MluaAnyhowWrapper::external)?;
Ok(result)
}
pub fn load_fs_table(lua: &mut Lua) -> anyhow::Result<()> {
let table = lua.create_table()?;
mkdir(lua, &table)?;
mkdir_all(lua, &table)?;
exists(lua, &table)?;
glob(lua, &table)?;
is_newer(lua, &table)?;
copy(lua, &table)?;
mv(lua, &table)?;
rm(lua, &table)?;
lua.globals().set("fs", table)?;
Ok(())
}