diff --git a/.fqntqpack b/.fqntqpack
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..360c9b9
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/v2.iml b/.idea/v2.iml
new file mode 100644
index 0000000..cf84ae4
--- /dev/null
+++ b/.idea/v2.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index b240594..813159e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -19,6 +19,15 @@ dependencies = [
"cpufeatures",
]
+[[package]]
+name = "aho-corasick"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "base64ct"
version = "1.6.0"
@@ -288,12 +297,24 @@ dependencies = [
"libc",
]
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+[[package]]
+name = "log"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
[[package]]
name = "lzma-sys"
version = "0.1.20"
@@ -305,6 +326,21 @@ dependencies = [
"pkg-config",
]
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@@ -314,6 +350,16 @@ dependencies = [
"adler",
]
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
[[package]]
name = "num_cpus"
version = "1.16.0"
@@ -324,12 +370,24 @@ dependencies = [
"libc",
]
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
[[package]]
name = "pack_sync"
version = "0.1.0"
@@ -338,6 +396,9 @@ dependencies = [
"num_cpus",
"serde",
"serde_yaml",
+ "toml",
+ "tracing",
+ "tracing-subscriber",
"walkdir",
"zip",
"zip_archive",
@@ -366,6 +427,12 @@ dependencies = [
"sha2",
]
+[[package]]
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
[[package]]
name = "pkg-config"
version = "0.3.27"
@@ -425,6 +492,50 @@ dependencies = [
"thiserror",
]
+[[package]]
+name = "regex"
+version = "1.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata 0.4.6",
+ "regex-syntax 0.8.2",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.2",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+
[[package]]
name = "ryu"
version = "1.0.15"
@@ -460,6 +571,15 @@ dependencies = [
"syn",
]
+[[package]]
+name = "serde_spanned"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "serde_yaml"
version = "0.9.25"
@@ -495,6 +615,21 @@ dependencies = [
"digest",
]
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+
[[package]]
name = "subprocess"
version = "0.2.9"
@@ -553,6 +688,16 @@ dependencies = [
"syn",
]
+[[package]]
+name = "thread_local"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
[[package]]
name = "time"
version = "0.3.27"
@@ -570,6 +715,101 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+[[package]]
+name = "toml"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
[[package]]
name = "typenum"
version = "1.16.0"
@@ -588,6 +828,12 @@ version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
[[package]]
name = "version_check"
version = "0.9.4"
@@ -707,6 +953,15 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+[[package]]
+name = "winnow"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "xattr"
version = "1.0.1"
diff --git a/Cargo.toml b/Cargo.toml
index a2ce002..9422898 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,14 @@ name = "pack_sync"
version = "0.1.0"
edition = "2021"
+[[bin]]
+name = "pack_sync_cli"
+path = "src/cli.rs"
+
+[[bin]]
+name = "pack_sync_server"
+path = "src/server.rs"
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@@ -10,6 +18,9 @@ dirs = "5.0.1"
num_cpus = "1.16.0"
serde = { version = "1.0.188", features = ["derive"] }
serde_yaml = "0.9.25"
+toml = "0.8.11"
+tracing = "0.1.40"
+tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
walkdir = "2.3.3"
zip = "0.6.6"
zip_archive = "1.2.2"
diff --git a/README.md b/README.md
index 093f616..059b5e2 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,28 @@
-# pack deployer
-- a simple utility to automatically archive and move your resourcepacks into a folder.
+# Pack Sync
+### A simple utility for resoucepack developers who like to stay organised.
-## use cases
+### Use Case:
+- You have a folder full of all your projects working on minecraft resource packs
+- You want to be able to automatically archive these files and move them to your resourcepacks folders for testing
+- You make modular packs with different themes that need to be kept organised
-this may be useful if you regularly create resourcepacks and want to organise your projects in different folders.
-the utility recursively scans directories in the project folder and organises packs into a folder
\ No newline at end of file
+### How pack sync can help
+The pack sync client is a command line utility that allows you to automatically
+archive and load all of your resourcepacks into correct folders.
+
+
+### Usage:
+
+- start by creating a config.toml file
+```toml
+repository = "."
+resourcepacks = "_resourcepacks"
+ignore_folder_prefix = "_"
+
+[versions.1-8-9]
+resourcepacks = "mc_instances/1.8.9/resourcepacks"
+
+[versions.1-20-1]
+resourcepacks = "mc_instances/1.20.4/resourcepacks"
+```
\ No newline at end of file
diff --git a/src/cli.rs b/src/cli.rs
new file mode 100644
index 0000000..92a23ff
--- /dev/null
+++ b/src/cli.rs
@@ -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,
+}
+
+impl Pack {
+ fn load(path: &PathBuf) -> io::Result {
+ 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::(&contents).map_err(|e| Error::new(ErrorKind::Other, e))?;
+
+ Ok(pack)
+ }
+
+ fn archive(&self, path: &PathBuf, config: &Config) -> Result<(), Box> {
+ 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> {
+// 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,
+ pub resourcepacks: Option,
+ pub ignore_folder_prefix: Option,
+}
+
+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
+}
+
+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 {
+ 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 {
+ Some(PathBuf::from(".").join("config.toml"))
+ }
+ #[cfg(not(debug_assertions))]
+ fn path() -> Option {
+ 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(())
+}
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index d77117f..0000000
--- a/src/main.rs
+++ /dev/null
@@ -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> {
- 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(())
-}
\ No newline at end of file
diff --git a/src/server.rs b/src/server.rs
new file mode 100644
index 0000000..e813a5e
--- /dev/null
+++ b/src/server.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("hello world");
+}
\ No newline at end of file
diff --git a/src/utils.rs b/src/utils.rs
deleted file mode 100644
index f1de0b4..0000000
--- a/src/utils.rs
+++ /dev/null
@@ -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 {
- 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 {
- 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)
-}
\ No newline at end of file