# Conflicts: # extensions/yarn.lock # package.json # src-tauri/plugins/tauri-plugin-hardware/src/vendor/vulkan.rs # src-tauri/src/lib.rs # yarn.lock
255 lines
8.8 KiB
Rust
255 lines
8.8 KiB
Rust
// WARNING: These APIs will be deprecated soon due to removing FS API access from frontend.
|
|
// It's added to ensure the legacy implementation from frontend still functions before removal.
|
|
use super::helpers::resolve_path;
|
|
use super::models::FileStat;
|
|
use std::fs;
|
|
use tauri::Runtime;
|
|
|
|
#[tauri::command]
|
|
pub fn rm<R: Runtime>(app_handle: tauri::AppHandle<R>, args: Vec<String>) -> Result<(), String> {
|
|
if args.is_empty() || args[0].is_empty() {
|
|
return Err("rm error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
if path.is_file() {
|
|
fs::remove_file(&path).map_err(|e| e.to_string())?;
|
|
} else if path.is_dir() {
|
|
fs::remove_dir_all(&path).map_err(|e| e.to_string())?;
|
|
} else {
|
|
return Err("rm error: Path does not exist".to_string());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn mkdir<R: Runtime>(app_handle: tauri::AppHandle<R>, args: Vec<String>) -> Result<(), String> {
|
|
if args.is_empty() || args[0].is_empty() {
|
|
return Err("mkdir error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
fs::create_dir_all(&path).map_err(|e| e.to_string())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn mv<R: Runtime>(app_handle: tauri::AppHandle<R>, args: Vec<String>) -> Result<(), String> {
|
|
if args.len() < 2 || args[0].is_empty() || args[1].is_empty() {
|
|
return Err("mv error: Invalid argument - source and destination required".to_string());
|
|
}
|
|
|
|
let source = resolve_path(app_handle.clone(), &args[0]);
|
|
let destination = resolve_path(app_handle, &args[1]);
|
|
|
|
if !source.exists() {
|
|
return Err("mv error: Source path does not exist".to_string());
|
|
}
|
|
|
|
fs::rename(&source, &destination).map_err(|e| e.to_string())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn join_path<R: Runtime>(
|
|
app_handle: tauri::AppHandle<R>,
|
|
args: Vec<String>,
|
|
) -> Result<String, String> {
|
|
if args.is_empty() {
|
|
return Err("join_path error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
let joined_path = args[1..].iter().fold(path, |acc, part| acc.join(part));
|
|
Ok(joined_path.to_string_lossy().to_string())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn exists_sync<R: Runtime>(
|
|
app_handle: tauri::AppHandle<R>,
|
|
args: Vec<String>,
|
|
) -> Result<bool, String> {
|
|
if args.is_empty() || args[0].is_empty() {
|
|
return Err("exist_sync error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
Ok(path.exists())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn file_stat<R: Runtime>(
|
|
app_handle: tauri::AppHandle<R>,
|
|
args: String,
|
|
) -> Result<FileStat, String> {
|
|
if args.is_empty() {
|
|
return Err("file_stat error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args);
|
|
let metadata = fs::metadata(&path).map_err(|e| e.to_string())?;
|
|
let is_directory = metadata.is_dir();
|
|
let size = if is_directory { 0 } else { metadata.len() };
|
|
let file_stat = FileStat { is_directory, size };
|
|
Ok(file_stat)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn read_file_sync<R: Runtime>(
|
|
app_handle: tauri::AppHandle<R>,
|
|
args: Vec<String>,
|
|
) -> Result<String, String> {
|
|
if args.is_empty() || args[0].is_empty() {
|
|
return Err("read_file_sync error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
fs::read_to_string(&path).map_err(|e| e.to_string())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn write_file_sync<R: Runtime>(
|
|
app_handle: tauri::AppHandle<R>,
|
|
args: Vec<String>,
|
|
) -> Result<(), String> {
|
|
if args.len() < 2 || args[0].is_empty() || args[1].is_empty() {
|
|
return Err("write_file_sync error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
let content = &args[1];
|
|
fs::write(&path, content).map_err(|e| e.to_string())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn readdir_sync<R: Runtime>(
|
|
app_handle: tauri::AppHandle<R>,
|
|
args: Vec<String>,
|
|
) -> Result<Vec<String>, String> {
|
|
if args.is_empty() || args[0].is_empty() {
|
|
return Err("read_dir_sync error: Invalid argument".to_string());
|
|
}
|
|
|
|
let path = resolve_path(app_handle, &args[0]);
|
|
let entries = fs::read_dir(&path).map_err(|e| e.to_string())?;
|
|
let paths: Vec<String> = entries
|
|
.filter_map(|entry| entry.ok())
|
|
.map(|entry| entry.path().to_string_lossy().to_string())
|
|
.collect();
|
|
Ok(paths)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn write_yaml(
|
|
app: tauri::AppHandle<impl Runtime>,
|
|
data: serde_json::Value,
|
|
save_path: &str,
|
|
) -> Result<(), String> {
|
|
// TODO: have an internal function to check scope
|
|
let jan_data_folder = crate::core::app::commands::get_jan_data_folder_path(app.clone());
|
|
let save_path = jan_utils::normalize_path(&jan_data_folder.join(save_path));
|
|
if !save_path.starts_with(&jan_data_folder) {
|
|
return Err(format!(
|
|
"Error: save path {} is not under jan_data_folder {}",
|
|
save_path.to_string_lossy(),
|
|
jan_data_folder.to_string_lossy(),
|
|
));
|
|
}
|
|
let file = fs::File::create(&save_path).map_err(|e| e.to_string())?;
|
|
let mut writer = std::io::BufWriter::new(file);
|
|
serde_yaml::to_writer(&mut writer, &data).map_err(|e| e.to_string())?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn read_yaml<R: Runtime>(app: tauri::AppHandle<R>, path: &str) -> Result<serde_json::Value, String> {
|
|
let jan_data_folder = crate::core::app::commands::get_jan_data_folder_path(app.clone());
|
|
let path = jan_utils::normalize_path(&jan_data_folder.join(path));
|
|
if !path.starts_with(&jan_data_folder) {
|
|
return Err(format!(
|
|
"Error: path {} is not under jan_data_folder {}",
|
|
path.to_string_lossy(),
|
|
jan_data_folder.to_string_lossy(),
|
|
));
|
|
}
|
|
let file = fs::File::open(&path).map_err(|e| e.to_string())?;
|
|
let reader = std::io::BufReader::new(file);
|
|
let data: serde_json::Value = serde_yaml::from_reader(reader).map_err(|e| e.to_string())?;
|
|
Ok(data)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn decompress<R: Runtime>(app: tauri::AppHandle<R>, path: &str, output_dir: &str) -> Result<(), String> {
|
|
let jan_data_folder = crate::core::app::commands::get_jan_data_folder_path(app.clone());
|
|
let path_buf = jan_utils::normalize_path(&jan_data_folder.join(path));
|
|
|
|
let output_dir_buf = jan_utils::normalize_path(&jan_data_folder.join(output_dir));
|
|
if !output_dir_buf.starts_with(&jan_data_folder) {
|
|
return Err(format!(
|
|
"Error: output directory {} is not under jan_data_folder {}",
|
|
output_dir_buf.to_string_lossy(),
|
|
jan_data_folder.to_string_lossy(),
|
|
));
|
|
}
|
|
|
|
// Ensure output directory exists
|
|
fs::create_dir_all(&output_dir_buf).map_err(|e| {
|
|
format!(
|
|
"Failed to create output directory {}: {}",
|
|
output_dir_buf.to_string_lossy(),
|
|
e
|
|
)
|
|
})?;
|
|
|
|
// Use short path on Windows to handle paths with spaces
|
|
#[cfg(windows)]
|
|
let file = {
|
|
if let Some(short_path) = jan_utils::path::get_short_path(&path_buf) {
|
|
fs::File::open(&short_path).map_err(|e| e.to_string())?
|
|
} else {
|
|
fs::File::open(&path_buf).map_err(|e| e.to_string())?
|
|
}
|
|
};
|
|
|
|
#[cfg(not(windows))]
|
|
let file = fs::File::open(&path_buf).map_err(|e| e.to_string())?;
|
|
if path.ends_with(".tar.gz") {
|
|
let tar = flate2::read::GzDecoder::new(file);
|
|
let mut archive = tar::Archive::new(tar);
|
|
archive.unpack(&output_dir_buf).map_err(|e| e.to_string())?;
|
|
} else if path.ends_with(".zip") {
|
|
let mut zip = zip::ZipArchive::new(file).map_err(|e| e.to_string())?;
|
|
for i in 0..zip.len() {
|
|
let mut entry = zip.by_index(i).map_err(|e| e.to_string())?;
|
|
let outpath = output_dir_buf.join(
|
|
entry
|
|
.enclosed_name()
|
|
.ok_or_else(|| "Invalid zip entry path".to_string())?,
|
|
);
|
|
|
|
if entry.name().ends_with('/') {
|
|
std::fs::create_dir_all(&outpath).map_err(|e| e.to_string())?;
|
|
} else {
|
|
if let Some(parent) = outpath.parent() {
|
|
std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
|
|
}
|
|
let mut outfile = std::fs::File::create(&outpath).map_err(|e| e.to_string())?;
|
|
std::io::copy(&mut entry, &mut outfile).map_err(|e| e.to_string())?;
|
|
#[cfg(unix)]
|
|
{
|
|
use std::os::unix::fs::PermissionsExt;
|
|
if let Some(mode) = entry.unix_mode() {
|
|
let _ = std::fs::set_permissions(
|
|
&outpath,
|
|
std::fs::Permissions::from_mode(mode),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
return Err("Unsupported file format. Only .tar.gz and .zip are supported.".to_string());
|
|
}
|
|
|
|
Ok(())
|
|
}
|