started v2
This commit is contained in:
+354
@@ -0,0 +1,354 @@
|
||||
|
||||
|
||||
use num_cpus;
|
||||
use std::{
|
||||
fs::{self, OpenOptions},
|
||||
io::{self, Error, ErrorKind, Write},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::slice::SliceIndex;
|
||||
use tracing::{event, info, span, Level, warn, error};
|
||||
use tracing_subscriber::{
|
||||
filter::{EnvFilter, LevelFilter},
|
||||
fmt::{self, fmt},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use toml;
|
||||
|
||||
use walkdir::WalkDir;
|
||||
use zip::write::{FileOptions, ZipWriter};
|
||||
use zip::CompressionMethod;
|
||||
use zip_archive::{get_dir_list, Archiver};
|
||||
|
||||
|
||||
fn main() {
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
fmt::layer()
|
||||
.pretty()
|
||||
.with_target(false)
|
||||
.with_thread_ids(false)
|
||||
.with_thread_names(false)
|
||||
.with_file(false)
|
||||
.with_line_number(false),
|
||||
)
|
||||
.with(
|
||||
EnvFilter::builder()
|
||||
.with_default_directive(LevelFilter::DEBUG.into())
|
||||
.from_env_lossy(),
|
||||
)
|
||||
.init();
|
||||
|
||||
let config = Config::load().expect("failed to load config");
|
||||
let pack_repo = PathBuf::from(&config.repository);
|
||||
match clear_resourcepacks(&config) {
|
||||
Ok(_) => {},
|
||||
Err(e) => return,
|
||||
};
|
||||
search_dir(&pack_repo, &config).unwrap();
|
||||
}
|
||||
|
||||
fn clear_resourcepacks(conf: &Config) -> io::Result<()> {
|
||||
let span = span!(Level::INFO, "clear_packs");
|
||||
let _guard = span.enter();
|
||||
|
||||
info!("Clearing existing resourcepacks folder");
|
||||
match fs::remove_dir_all(&conf.resourcepacks) {
|
||||
Ok(_) => {}
|
||||
Err(e) => warn!("No existing packs folder detected. Creating new folder."),
|
||||
};
|
||||
match fs::create_dir(&conf.resourcepacks) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
error!("{}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
info!("Successfully reset resourcepacks folder");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn search_dir(path: &PathBuf, config: &Config) -> io::Result<()> {
|
||||
let span = span!(Level::INFO, "Searching for packs");
|
||||
let _guard = span.enter();
|
||||
|
||||
// info!("Searching for packs in {}", path.display());
|
||||
// check if file is a valid pack
|
||||
|
||||
if path.clone().join("pack.toml").exists() {
|
||||
println!("Found pack {}", path.display());
|
||||
Pack::load(&path).unwrap().archive(&path, config).unwrap();
|
||||
return Ok(());
|
||||
} else {
|
||||
println!("1c| {}", path.display());
|
||||
|
||||
for entry in WalkDir::new(path.clone())
|
||||
.into_iter()
|
||||
.filter_map(|e| e.ok())
|
||||
.filter(|e| e.file_type().is_dir() && e.file_name() != path)
|
||||
.filter(|e| !e.file_name().to_str().unwrap().to_string().contains("/_"))
|
||||
{
|
||||
println!("PATH {}", entry.path().join(entry.file_name()).to_str().unwrap());
|
||||
// search_dir(&entry.path().join(entry.file_name()).to_path_buf(), config).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct Pack {
|
||||
release: bool,
|
||||
name: String,
|
||||
version: String,
|
||||
description: String,
|
||||
packs: HashMap<String, PackComponent>,
|
||||
}
|
||||
|
||||
impl Pack {
|
||||
fn load(path: &PathBuf) -> io::Result<Pack> {
|
||||
let span = span!(Level::INFO, "Loading Pack Config file");
|
||||
let _guard = span.enter();
|
||||
|
||||
let contents = fs::read_to_string(path.join("pack.toml"))?;
|
||||
let pack = toml::from_str::<Pack>(&contents).map_err(|e| Error::new(ErrorKind::Other, e))?;
|
||||
|
||||
Ok(pack)
|
||||
}
|
||||
|
||||
fn archive(&self, path: &PathBuf, config: &Config) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let span = span!(Level::INFO, "Archiving Pack");
|
||||
let _guard = span.enter();
|
||||
|
||||
let resourcepacks = if config.versions.contains_key(&self.version) {
|
||||
match config.versions.get(&self.version).unwrap().resourcepacks.clone() {
|
||||
Some(folder) => folder,
|
||||
None => config.resourcepacks.clone()
|
||||
}
|
||||
} else {
|
||||
config.resourcepacks.clone()
|
||||
};
|
||||
let zip_file = fs::File::create(format!("{}/{}.zip", resourcepacks, self.name))?;
|
||||
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 file_path = entry.path();
|
||||
if file_path.is_file() {
|
||||
let mut file = fs::File::open(file_path)?;
|
||||
let relpath = file_path.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()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
struct PackComponent {
|
||||
prefix: String,
|
||||
release: bool,
|
||||
}
|
||||
|
||||
//
|
||||
// fn scan_directory(path: PathBuf, config: &Config) -> 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, config).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!(
|
||||
// "{}/{}",
|
||||
// config.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(), &config)?;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
//
|
||||
// fn get_archive(path: PathBuf, config: &Config) -> 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", config.resourcepacks, filename.to_string())).exists() {
|
||||
// // checks if zip file already exists
|
||||
// let zip_file = fs::File::create(format!("{}/{}.zip", config.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 file_path = entry.path();
|
||||
// if file_path.is_file() {
|
||||
// let mut file = fs::File::open(file_path)?;
|
||||
// let relpath = file_path.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(())
|
||||
// }
|
||||
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VersionConfig {
|
||||
pub pack_repo: Option<String>,
|
||||
pub resourcepacks: Option<String>,
|
||||
pub ignore_folder_prefix: Option<String>,
|
||||
}
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
pub repository: String,
|
||||
pub resourcepacks: String,
|
||||
pub ignore_folder_prefix: String,
|
||||
pub versions: HashMap<String, VersionConfig>
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn default() -> Config {
|
||||
Config {
|
||||
repository: ".".to_string(),
|
||||
resourcepacks: "_resourcepacks".to_string(),
|
||||
ignore_folder_prefix: "_".to_string(),
|
||||
versions: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load() -> Result<Config, Error> {
|
||||
let span = span!(Level::INFO, "Loading Configuration File");
|
||||
let _guard = span.enter();
|
||||
|
||||
let mut conf_path = Config::path().ok_or(Error::new(ErrorKind::Other, "error getting config path"))?;
|
||||
|
||||
if conf_path.exists() {
|
||||
let config: Config = toml::from_str(fs::read_to_string(&conf_path)?.as_str())
|
||||
.map_err(|_| Error::new(ErrorKind::Other, "failed to deserialise"))?;
|
||||
info!(
|
||||
"Loaded Config File: \n\trepo: {}\n\tpacks folder: {}\n\tignore with prefix: {}",
|
||||
config.repository, config.resourcepacks, config.ignore_folder_prefix
|
||||
);
|
||||
Ok(config)
|
||||
} else {
|
||||
warn!(
|
||||
"No config file detected. Creating config file with default values at:\n\t{}",
|
||||
conf_path.display()
|
||||
);
|
||||
create_config_file(&conf_path)?;
|
||||
Ok(Config::default())
|
||||
}
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
fn path() -> Option<PathBuf> {
|
||||
Some(PathBuf::from(".").join("config.toml"))
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn path() -> Option<PathBuf> {
|
||||
dirs::config_dir()?.join("pack_sync").join("config.toml")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn create_config_file(path: &PathBuf) -> Result<(), Error> {
|
||||
println!("{}", path.display());
|
||||
|
||||
fs::create_dir_all(path.parent().unwrap())?;
|
||||
fs::File::create(path)?;
|
||||
|
||||
let yaml = serde_yaml::to_string(&Config::default())
|
||||
.map_err(|_| Error::new(ErrorKind::Other, "failed to serialise"))?;
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path)?
|
||||
.write_all(yaml.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
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,3 @@
|
||||
fn main() {
|
||||
println!("hello world");
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
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