This commit is contained in:
parent
6d44b60182
commit
1fe7ef0f2d
9 changed files with 82 additions and 24 deletions
|
@ -1,2 +1,3 @@
|
|||
# 0.1.2
|
||||
- optimize curseforge relation meta querying
|
||||
- add debug logging
|
||||
|
|
|
@ -17,10 +17,12 @@ crossterm = "0.21.0"
|
|||
futures = "0.3.16"
|
||||
indicatif = "0.16.2"
|
||||
json5 = "0.3.0"
|
||||
log = "0.4.14"
|
||||
percent-encoding = "2.1.0"
|
||||
reqwest = { version = "0.11.4", features = ["stream"] }
|
||||
serde = { version = "1.0.129", features = ["derive"] }
|
||||
serde_json = "1.0.67"
|
||||
simplelog = "0.10.0"
|
||||
structopt = "0.3.22"
|
||||
tera = "1.12.1"
|
||||
thiserror = "1.0.28"
|
||||
|
|
|
@ -24,6 +24,7 @@ use addonscript::manifest::{
|
|||
use anyhow::{bail, Context};
|
||||
use async_trait::async_trait;
|
||||
use indicatif::ProgressBar;
|
||||
use log::{debug, info};
|
||||
use reqwest::Client;
|
||||
use std::{collections::HashMap, io::Write, path::Path, sync::Arc};
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
@ -110,6 +111,7 @@ pub async fn run((config, mut manifest): (Config, Manifest), all: bool) -> anyho
|
|||
|
||||
match installer {
|
||||
Installer::Dir(dir) => {
|
||||
info!("copying dir installer file {}", path.to_string_lossy());
|
||||
tokio::fs::copy(config.locations.src.join(path), twitch_dir.join(dir))
|
||||
.await?;
|
||||
},
|
||||
|
@ -246,6 +248,7 @@ fn sort_file(
|
|||
link_rels: &mut Vec<(Installer, Link)>,
|
||||
cf_rels: &mut Vec<(u32, u32)>,
|
||||
) -> anyhow::Result<()> {
|
||||
debug!("Sorting file {:?}", &file);
|
||||
match file {
|
||||
File::Link {
|
||||
installer, link, ..
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::{config::Config, util::CliStyle};
|
|||
pub async fn run(config: Config) -> anyhow::Result<()> {
|
||||
// These operations are so incredibly performance-critical that we absolutely
|
||||
// must execute them in parallel!
|
||||
let (res1, res2) = tokio::join!(
|
||||
// we ignore the results on purpose, so nothing fails when the dirs dont exist.
|
||||
let (_, _) = tokio::join!(
|
||||
async {
|
||||
println!(
|
||||
"{}",
|
||||
|
@ -17,8 +18,5 @@ pub async fn run(config: Config) -> anyhow::Result<()> {
|
|||
}
|
||||
);
|
||||
|
||||
res1?;
|
||||
res2?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use addonscript::manifest::{
|
|||
RepositoryType,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use log::{debug, info};
|
||||
use reqwest::Client;
|
||||
use serde::Serialize;
|
||||
use std::{collections::HashMap, path::PathBuf, sync::Arc};
|
||||
|
@ -27,6 +28,7 @@ pub async fn run(
|
|||
.context("Manifest has no versions!")?;
|
||||
let repos = util::repo_map(manifest.repositories);
|
||||
|
||||
info!("instatiating tera engine");
|
||||
let mut tera = Tera::default();
|
||||
tera.add_raw_template("modlist", TEMPLATE)?;
|
||||
|
||||
|
@ -47,6 +49,11 @@ pub async fn run(
|
|||
if !cf_rels.is_empty() {
|
||||
println!("{}", "Querying CF metas.".info());
|
||||
|
||||
info!(
|
||||
"Requesting addon info for {} curseforge mods",
|
||||
cf_rels.len()
|
||||
);
|
||||
|
||||
let res = http
|
||||
.post("https://addons-ecs.forgesvc.net/api/v2/addon")
|
||||
.body(
|
||||
|
@ -64,6 +71,7 @@ pub async fn run(
|
|||
let cf_metas = serde_json::from_slice::<Vec<AddonInfoResponse>>(&res)
|
||||
.context("Failed deserializing CF relation response")?;
|
||||
|
||||
info!("Converting CF metas to AS metas");
|
||||
let cf_metas = cf_metas.into_iter().map(|m| Meta {
|
||||
name: m.name,
|
||||
contributors: m
|
||||
|
@ -108,6 +116,7 @@ pub async fn run(
|
|||
}
|
||||
|
||||
fn get_meta(rel: Relation, repos: &HashMap<String, Repository>) -> anyhow::Result<MetaInfo> {
|
||||
debug!("getting meta for {:?}", &rel);
|
||||
if let Some(meta) = rel.meta {
|
||||
return Ok(MetaInfo::Meta(meta));
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use addonscript::{
|
|||
};
|
||||
use anyhow::{bail, Context};
|
||||
use crossterm::style::Stylize;
|
||||
use log::info;
|
||||
use twitch::manifest::Manifest as TwManifest;
|
||||
use url::Url;
|
||||
|
||||
|
@ -38,6 +39,7 @@ pub async fn run(config: Config, infile: PathBuf) -> anyhow::Result<()> {
|
|||
)
|
||||
.context("Failed to parse twitch manifest")?;
|
||||
|
||||
info!("converting twitch mods to AS relations");
|
||||
let mut relations = data
|
||||
.files
|
||||
.into_iter()
|
||||
|
@ -56,6 +58,7 @@ pub async fn run(config: Config, infile: PathBuf) -> anyhow::Result<()> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
if let Some(ml) = data.minecraft.mod_loaders.pop() {
|
||||
info!("fount modloader {:?}", &ml);
|
||||
let mut splits = ml.id.split('-');
|
||||
if !matches!(splits.next(), Some("forge")) {
|
||||
bail!("Twitch manifest contains invalid or unknown modloader!");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use async_trait::async_trait;
|
||||
use crossterm::style::Stylize;
|
||||
use futures::{stream, StreamExt};
|
||||
use log::info;
|
||||
use reqwest::{Client, StatusCode};
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
@ -58,6 +59,8 @@ impl<C: Callback> Downloader<C> {
|
|||
url: Url,
|
||||
target: PathBuf,
|
||||
) -> Result<DownloadInfo, DownloadError> {
|
||||
info!("Downloading {}", &url);
|
||||
|
||||
if let Some(parent) = target.parent() {
|
||||
tokio::fs::create_dir_all(parent).await?;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use anyhow::Context;
|
||||
use log::{info, LevelFilter};
|
||||
use simplelog::{ColorChoice, TermLogger, TerminalMode};
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
|
@ -9,6 +12,9 @@ mod util;
|
|||
|
||||
#[derive(StructOpt)]
|
||||
struct Opt {
|
||||
#[structopt(short, long, parse(from_occurrences), help = "enable verbose logging")]
|
||||
verbose: u8,
|
||||
|
||||
#[structopt(subcommand)]
|
||||
cmd: Command,
|
||||
}
|
||||
|
@ -69,32 +75,54 @@ enum Command {
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let Opt { cmd } = Opt::from_args();
|
||||
let Opt { cmd, verbose } = Opt::from_args();
|
||||
|
||||
let log_level = match verbose {
|
||||
0 => LevelFilter::Off,
|
||||
1 => LevelFilter::Info,
|
||||
2 => LevelFilter::Debug,
|
||||
_ => LevelFilter::Trace,
|
||||
};
|
||||
|
||||
TermLogger::init(
|
||||
log_level,
|
||||
simplelog::ConfigBuilder::new()
|
||||
.set_time_to_local(true)
|
||||
.set_target_level(LevelFilter::Error)
|
||||
.build(),
|
||||
TerminalMode::Stderr,
|
||||
ColorChoice::Auto,
|
||||
)
|
||||
.context("Failed to init logger")?;
|
||||
|
||||
/// runs a given command, if the first arg is config or manifest, the
|
||||
/// manifest or config file is passed to the comand respectively.
|
||||
macro_rules! run_cmd {
|
||||
(config: $cmd:ident $($args:expr),* $(,)?) => {
|
||||
run_cmd!($cmd util::parse_config().await?, $($args),*)
|
||||
};
|
||||
|
||||
(manifest: $cmd:ident $($args:expr),* $(,)?) => {
|
||||
run_cmd!($cmd util::parse_config_and_manifest().await?, $($args),*)
|
||||
};
|
||||
|
||||
($cmd:ident $($args:expr),* $(,)?) => {{
|
||||
info!("Running command {}", stringify!($cmd));
|
||||
commands::$cmd::run($($args),*).await?;
|
||||
}}
|
||||
}
|
||||
|
||||
match cmd {
|
||||
Command::Init {
|
||||
modpack_name,
|
||||
name,
|
||||
mcversion,
|
||||
} => commands::init::run(modpack_name, name, mcversion).await?,
|
||||
|
||||
Command::DownloadMods { dir, all } => {
|
||||
commands::downloadmods::run(util::parse_config_and_manifest().await?, dir, all).await?
|
||||
},
|
||||
|
||||
Command::BuildTwitch { all } => {
|
||||
commands::buildtwitch::run(util::parse_config_and_manifest().await?, all).await?
|
||||
},
|
||||
|
||||
Command::Clean => commands::clean::run(util::parse_config().await?).await?,
|
||||
|
||||
Command::CreateModList { outfile } => {
|
||||
commands::createmodlist::run(util::parse_config_and_manifest().await?, outfile).await?
|
||||
},
|
||||
|
||||
Command::Import { infile } => {
|
||||
commands::import::run(util::parse_config().await?, infile).await?
|
||||
},
|
||||
} => run_cmd!(init modpack_name, name, mcversion),
|
||||
Command::DownloadMods { dir, all } => run_cmd!(manifest: downloadmods dir, all),
|
||||
Command::BuildTwitch { all } => run_cmd!(manifest: buildtwitch all),
|
||||
Command::Clean => run_cmd!(config: clean),
|
||||
Command::CreateModList { outfile } => run_cmd!(manifest: createmodlist outfile),
|
||||
Command::Import { infile } => run_cmd!(config: import infile),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -2,6 +2,7 @@ use addonscript::manifest::{link::Link, Manifest, Repository};
|
|||
use anyhow::Context;
|
||||
use crossterm::style::{Attribute, Attributes, Color, ContentStyle, Stylize};
|
||||
use indicatif::ProgressStyle;
|
||||
use log::info;
|
||||
use percent_encoding::percent_decode;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
|
@ -17,6 +18,7 @@ use crate::config::Config;
|
|||
|
||||
/// reads and parses the config from the current working directory
|
||||
pub async fn parse_config() -> anyhow::Result<Config> {
|
||||
info!("reading config");
|
||||
let conf = tokio::fs::read("modpacktoolsconfig.toml")
|
||||
.await
|
||||
.context("Failed to read config")?;
|
||||
|
@ -36,6 +38,8 @@ pub async fn parse_config_and_manifest() -> anyhow::Result<(Config, Manifest)> {
|
|||
src.join("modpack.json")
|
||||
};
|
||||
|
||||
info!("reading manifest");
|
||||
|
||||
let data = tokio::fs::read(path)
|
||||
.await
|
||||
.context("Failed to read manifest")?;
|
||||
|
@ -109,6 +113,7 @@ pub fn progress_style() -> ProgressStyle {
|
|||
|
||||
/// creates the modpacktools temporary directory (set in the config)
|
||||
pub async fn make_tmp_dir(config: &Config) -> anyhow::Result<()> {
|
||||
info!("creating temporary directory");
|
||||
tokio::fs::create_dir_all(&config.locations.temp_dir)
|
||||
.await
|
||||
.context("Failed to create temporary directory")?;
|
||||
|
@ -181,6 +186,12 @@ pub fn link_file_name(link: &Link) -> Result<String, LinkFileNameError> {
|
|||
|
||||
/// Copies a directory inclding all files
|
||||
pub async fn copy_dir(from: PathBuf, to: PathBuf) -> io::Result<()> {
|
||||
info!(
|
||||
"Copying directory {} to {}",
|
||||
from.to_string_lossy(),
|
||||
to.to_string_lossy()
|
||||
);
|
||||
|
||||
for file in WalkDir::new(&from) {
|
||||
let file = file?;
|
||||
|
||||
|
|
Loading…
Reference in a new issue