started v2

This commit is contained in:
FantasyPvP
2024-03-18 10:53:38 +00:00
parent 403e6ba087
commit 9b72d23779
12 changed files with 681 additions and 185 deletions
View File
+8
View File
@@ -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
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/v2.iml" filepath="$PROJECT_DIR$/.idea/v2.iml" />
</modules>
</component>
</project>
Generated
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
Generated
+255
View File
@@ -19,6 +19,15 @@ dependencies = [
"cpufeatures", "cpufeatures",
] ]
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.6.0" version = "1.6.0"
@@ -288,12 +297,24 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.147" version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]] [[package]]
name = "lzma-sys" name = "lzma-sys"
version = "0.1.20" version = "0.1.20"
@@ -305,6 +326,21 @@ dependencies = [
"pkg-config", "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]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.1" version = "0.7.1"
@@ -314,6 +350,16 @@ dependencies = [
"adler", "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]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.16.0" version = "1.16.0"
@@ -324,12 +370,24 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "option-ext" name = "option-ext"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "pack_sync" name = "pack_sync"
version = "0.1.0" version = "0.1.0"
@@ -338,6 +396,9 @@ dependencies = [
"num_cpus", "num_cpus",
"serde", "serde",
"serde_yaml", "serde_yaml",
"toml",
"tracing",
"tracing-subscriber",
"walkdir", "walkdir",
"zip", "zip",
"zip_archive", "zip_archive",
@@ -366,6 +427,12 @@ dependencies = [
"sha2", "sha2",
] ]
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.27" version = "0.3.27"
@@ -425,6 +492,50 @@ dependencies = [
"thiserror", "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]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.15" version = "1.0.15"
@@ -460,6 +571,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.9.25" version = "0.9.25"
@@ -495,6 +615,21 @@ dependencies = [
"digest", "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]] [[package]]
name = "subprocess" name = "subprocess"
version = "0.2.9" version = "0.2.9"
@@ -553,6 +688,16 @@ dependencies = [
"syn", "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]] [[package]]
name = "time" name = "time"
version = "0.3.27" version = "0.3.27"
@@ -570,6 +715,101 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" 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]] [[package]]
name = "typenum" name = "typenum"
version = "1.16.0" version = "1.16.0"
@@ -588,6 +828,12 @@ version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"
@@ -707,6 +953,15 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "winnow"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "xattr" name = "xattr"
version = "1.0.1" version = "1.0.1"
+11
View File
@@ -3,6 +3,14 @@ name = "pack_sync"
version = "0.1.0" version = "0.1.0"
edition = "2021" 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 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
@@ -10,6 +18,9 @@ dirs = "5.0.1"
num_cpus = "1.16.0" num_cpus = "1.16.0"
serde = { version = "1.0.188", features = ["derive"] } serde = { version = "1.0.188", features = ["derive"] }
serde_yaml = "0.9.25" 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" walkdir = "2.3.3"
zip = "0.6.6" zip = "0.6.6"
zip_archive = "1.2.2" zip_archive = "1.2.2"
+25 -5
View File
@@ -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. ### How pack sync can help
the utility recursively scans directories in the project folder and organises packs into a folder 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"
```
+354
View File
@@ -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
View File
@@ -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(())
}
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("hello world");
}
-74
View File
@@ -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)
}