started project
- packs can now be automatically zipped - reads from config file but doesn't do anything with it yet
This commit is contained in:
+106
@@ -0,0 +1,106 @@
|
||||
use std::{fs, io::{self, Error, ErrorKind}, path::{Path, PathBuf}};
|
||||
use zip::write::{FileOptions, ZipWriter};
|
||||
use zip::CompressionMethod;
|
||||
use walkdir::WalkDir;
|
||||
use zip_archive::{Archiver, get_dir_list};
|
||||
use num_cpus;
|
||||
|
||||
pub mod utils;
|
||||
|
||||
const PACK_REPO: &str = "./";
|
||||
const RESOURCEPACKS: &str = "./_resourcepacks";
|
||||
|
||||
const IGNORE_FOLDERS_PREFIX: &str = "_";
|
||||
|
||||
fn main() {
|
||||
let conf = utils::load_config().unwrap();
|
||||
let pack_repo = PathBuf::from(PACK_REPO);
|
||||
clear_resourcepacks().unwrap();
|
||||
scan_directory(pack_repo).unwrap();
|
||||
}
|
||||
|
||||
fn clear_resourcepacks() -> io::Result<()> {
|
||||
println!("[removing existing packs]");
|
||||
fs::remove_dir_all(RESOURCEPACKS)?;
|
||||
fs::create_dir(RESOURCEPACKS)?;
|
||||
println!(" => cleared resourcepacks folder");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn scan_directory(path: PathBuf) -> io::Result<()> {
|
||||
let mut pack_mcmeta = path.clone();
|
||||
pack_mcmeta.push("pack.mcmeta");
|
||||
if pack_mcmeta.exists() {
|
||||
// if pack metadata exists, put the pack into a zip folder.
|
||||
get_archive(path).map_err(|_| Error::new(ErrorKind::Other, "failed to archive zip"))?;
|
||||
return Ok(())
|
||||
} else {
|
||||
// recursively scans subdirectories for other packs
|
||||
for entry in fs::read_dir(path)? {
|
||||
let entry = entry?;
|
||||
|
||||
if entry.path()
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_os_string()
|
||||
.into_string()
|
||||
.map_err(|_| Error::new(ErrorKind::Other, "failed to convert os_str to string"))?
|
||||
.starts_with("_") {
|
||||
println!("found _");
|
||||
continue;
|
||||
}
|
||||
if let Some(zip_str) = entry.path().extension() {
|
||||
if zip_str == "zip" {
|
||||
fs::copy(entry.path(), format!("{}/{}", RESOURCEPACKS, entry.path().file_name().unwrap().to_os_string().into_string().map_err(|_| Error::new(ErrorKind::Other, "failed to convert os_str to string"))?))?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(file_type) = entry.file_type() {
|
||||
if file_type.is_dir() {
|
||||
scan_directory(entry.path())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_archive(path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("CREATING ARCHIVE: {}", &path.display());
|
||||
if let Some(f) = path.file_stem() {
|
||||
let mut filename = f.to_os_string().into_string().map_err(|_| Error::new(ErrorKind::Other, "failed to convert os_str to string"))?;
|
||||
filename.push_str("_0");
|
||||
loop {
|
||||
if !Path::new(&format!("{}/{}.zip", RESOURCEPACKS, filename.to_string())).exists() { // checks if zip file already exists
|
||||
let zip_file = fs::File::create(format!("{}/{}.zip", RESOURCEPACKS, filename))?;
|
||||
let mut zip_writer = ZipWriter::new(zip_file);
|
||||
|
||||
let options = FileOptions::default()
|
||||
.compression_method(CompressionMethod::Deflated)
|
||||
.unix_permissions(0o755);
|
||||
|
||||
for entry in WalkDir::new(path.clone()).into_iter().filter_map(|e| e.ok()) {
|
||||
let fpath = entry.path();
|
||||
if fpath.is_file() {
|
||||
let mut file = fs::File::open(fpath)?;
|
||||
let relpath = fpath.strip_prefix(path.clone())?;
|
||||
let mut zip_path = PathBuf::new();
|
||||
zip_path.push(relpath);
|
||||
|
||||
zip_writer.start_file(zip_path.to_string_lossy().into_owned(), options)?;
|
||||
std::io::copy(&mut file, &mut zip_writer)?;
|
||||
}
|
||||
}
|
||||
zip_writer.finish()?;
|
||||
break;
|
||||
|
||||
} else {
|
||||
// 10 increments the last digit of the filename by 1
|
||||
// TODO: add support for more than one digit
|
||||
let i: u32 = filename.pop().unwrap().to_digit(10).unwrap();
|
||||
filename.push(char::from_digit(i+1, 10).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
use std::{fs::{self, OpenOptions}, io::{self, Error, ErrorKind, Write}, path::{Path, PathBuf}};
|
||||
use crate::IGNORE_FOLDERS_PREFIX;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pack_repo: String,
|
||||
resourcepacks: String,
|
||||
ignore_folder_prefix: String,
|
||||
}
|
||||
|
||||
fn config_path() -> Option<PathBuf> {
|
||||
dirs::config_dir()
|
||||
}
|
||||
|
||||
fn create_config_dir(path: &PathBuf) -> Result<(), Error> {
|
||||
fs::create_dir_all(path)?;
|
||||
create_config_file(&path.join("config.yml"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_config(path: &PathBuf, config: Config) -> Result<(), Error> {
|
||||
fs::File::create(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_config_file(path: &PathBuf) -> Result<(), Error> {
|
||||
fs::File::create(path)?;
|
||||
|
||||
let conf_file = Config {
|
||||
pack_repo: ".".to_string(),
|
||||
resourcepacks: "./_resourcepacks".to_string(),
|
||||
ignore_folder_prefix: "_".to_string(),
|
||||
};
|
||||
let yaml = serde_yaml::to_string(&conf_file).map_err(|_| Error::new(ErrorKind::Other, "failed to serialise"))?;
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path)?;
|
||||
|
||||
file.write_all(yaml.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_config() -> Result<Config, Error> {
|
||||
let mut conf_path = config_path().ok_or(Error::new(ErrorKind::Other, "error getting config path"))?;
|
||||
if !conf_path.exists() {
|
||||
return Err(Error::new(ErrorKind::Other, "No config directory found"));
|
||||
};
|
||||
|
||||
conf_path.push("fqntqpacks");
|
||||
if !conf_path.exists() {
|
||||
create_config_dir(&conf_path)?;
|
||||
};
|
||||
|
||||
conf_path.push("config.yml");
|
||||
if !conf_path.exists() {
|
||||
create_config_file(&conf_path)?;
|
||||
};
|
||||
|
||||
let config: Config = serde_yaml::from_reader(fs::File::open(&conf_path)?)
|
||||
.map_err(|_| Error::new(ErrorKind::Other, "failed to deserialise"))?;
|
||||
|
||||
println!(
|
||||
"-----------------------------------------------------------------
|
||||
WARNING: no previous config file detected, created config file at
|
||||
{}
|
||||
-----------------------------------------------------------------", conf_path.display());
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
Reference in New Issue
Block a user