Skip to content

Commit

Permalink
lockfile shenanigans part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlan404 committed Sep 2, 2023
1 parent a26eeac commit 6df6daf
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 69 deletions.
8 changes: 6 additions & 2 deletions src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub async fn run(matches: &ArgMatches) -> Result<BuildContext> {
.unwrap_or(&default_output)
.clone();

let lockfile = Lockfile::load_from(&output_dir)?;
let lockfile = Lockfile::get_lockfile(&output_dir)?;

let force = matches.get_flag("force");

Expand All @@ -40,10 +40,14 @@ pub async fn run(matches: &ArgMatches) -> Result<BuildContext> {
let mut ctx = BuildContext {
server,
http_client,
output_dir,
new_lockfile: Lockfile {
path: output_dir.join(".mcman.lock"),
..Default::default()
},
force,
skip_stages,
lockfile,
output_dir,
..Default::default()
};

Expand Down
78 changes: 63 additions & 15 deletions src/core/addons.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,64 @@
use anyhow::{Context, Result};
use console::style;
use tokio::fs;

use crate::{model::Change, util::logger::Logger};

use super::{BuildContext, ReportBackState};

impl BuildContext {
pub async fn download_addons(&self, addon_type: &str) -> Result<()> {
let addon_count = match addon_type {
"plugins" => self.server.plugins.len(),
"mods" => self.server.mods.len(),
_ => unreachable!(),
pub async fn download_addons(
&mut self,
addon_type: &str,
) -> Result<()> {
let change_list = match addon_type {
"plugins" => &self.changes.plugins,
"mods" => &self.changes.mods,
_ => unreachable!()
};

let server_list = match addon_type {
"plugins" => &self.server.plugins,
"mods" => &self.server.mods,
_ => unreachable!()
};

let addon_count = server_list.len();

let idx_w = addon_count.to_string().len();

let removed_addons = change_list.iter()
.filter(|c| matches!(c, Change::Removed(_)))
.map(|c| c.inner())

Check warning on line 32 in src/core/addons.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/core/addons.rs:32:18 | 32 | .map(|c| c.inner()) | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `model::lockfile::Change::inner` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls = note: `#[warn(clippy::redundant_closure_for_method_calls)]` implied by `#[warn(clippy::pedantic)]`
.collect::<Vec<_>>();

if !removed_addons.is_empty() {
println!(
" {}",
style(format!("{} {addon_type} were removed from server.toml", removed_addons.len())).dim()
);

let logger = Logger::List { indent: 10, len: removed_addons.len() };

for (idx, (filename, _)) in removed_addons.iter().enumerate() {
let path = self.output_dir.join(addon_type).join(filename);
if path.exists() {
fs::remove_file(path).await?;
logger.item(idx, &format!(
"{} {}",
style("Deleted : ").bold(),
style(filename).dim()
));
} else {
logger.item(idx, &format!(
"{} {}",
style("Doesn't exist: ").bold(),
style(filename).dim()
));
}
}
}

println!(
" {}",
style(format!("{addon_count} {addon_type} present, processing...")).dim()
Expand All @@ -21,25 +67,21 @@ impl BuildContext {
std::fs::create_dir_all(self.output_dir.join(addon_type))
.context(format!("Failed to create {addon_type} directory"))?;

for (idx, addon) in match addon_type {
"plugins" => &self.server.plugins,
"mods" => &self.server.mods,
_ => unreachable!(),
}
.iter()
.enumerate()
for (idx, addon) in server_list
.iter()
.enumerate()
{
self.downloadable(addon, Some(addon_type), |state, file_name| match state {
let filename = self.downloadable(addon, Some(addon_type), |state, file_name| match state {
ReportBackState::Skipped => {
println!(
" ({:idx_w$}/{addon_count}) Skipping : {}",
" ({:idx_w$}/{addon_count}) Skipping : {}",
idx + 1,
style(&file_name).dim()
);
}
ReportBackState::Downloaded => {
println!(
" ({:idx_w$}/{addon_count}) {} : {}",
" ({:idx_w$}/{addon_count}) {}: {}",
idx + 1,
style("Downloaded").green().bold(),
style(&file_name).dim()
Expand All @@ -48,6 +90,12 @@ impl BuildContext {
ReportBackState::Downloading => {}
})
.await?;

match addon_type {
"plugins" => self.new_lockfile.plugins.push((filename, addon.clone())),
"mods" => self.new_lockfile.mods.push((filename, addon.clone())),
_ => unreachable!(),
}
}

Ok(())
Expand Down
14 changes: 13 additions & 1 deletion src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use dialoguer::theme::ColorfulTheme;
use tokio::fs::{self, File};

use crate::{
model::{Server, StartupMethod, Network, Lockfile},
model::{Server, StartupMethod, Network, Lockfile, Changes},
util::{self, logger::Logger}, Source,
};

Expand All @@ -25,7 +25,9 @@ pub struct BuildContext {
pub http_client: reqwest::Client,
pub output_dir: PathBuf,
pub lockfile: Lockfile,
pub new_lockfile: Lockfile,

pub changes: Changes,
pub force: bool,
pub skip_stages: Vec<String>,
pub start_time: Instant,
Expand All @@ -44,6 +46,8 @@ impl Default for BuildContext {
http_client: reqwest::Client::default(),
output_dir: PathBuf::new(),
lockfile: Lockfile::default(),
new_lockfile: Lockfile::default(),
changes: Changes::default(),
startup_method: StartupMethod::Jar(String::from("server.jar")),
skip_stages: vec![],
stage_index: 1,
Expand All @@ -58,6 +62,8 @@ impl BuildContext {
self.stage_index = 1;
self.start_time = Instant::now();

self.reload()?;

println!(
" {} {}...",
style("Building").bold(),
Expand Down Expand Up @@ -104,6 +110,12 @@ impl BuildContext {
Ok(())
}

pub fn reload(&mut self) -> Result<()> {
self.lockfile = Lockfile::get_lockfile(&self.output_dir)?;
self.changes = self.lockfile.get_changes(&self.server);
Ok(())
}

pub async fn run_stage(&mut self, name: &str, id: &str) -> Result<()> {
println!(" stage {}: {}", self.stage_index, style(name).blue().bold());

Expand Down
39 changes: 34 additions & 5 deletions src/hot_reload/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::collections::HashMap;
use std::{collections::HashMap, path::PathBuf, fs::File, io::Write};

use anyhow::Result;
use glob::Pattern;
use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -13,17 +15,44 @@ pub enum HotReloadAction {

#[derive(Debug, Serialize, Deserialize)]
pub struct HotReloadConfig {
#[serde(skip)]
pub path: PathBuf,

#[serde(skip_serializing_if = "Vec::is_empty")]
pub files: Vec<Entry>,
pub events: HashMap<HotReloadEvent, HotReloadAction>,
#[serde(skip_serializing_if = "HashMap::is_empty")]
pub events: HashMap<String, HotReloadAction>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum HotReloadEvent {
impl HotReloadConfig {
pub fn load_from(path: &PathBuf) -> Result<Self> {

Check warning on line 28 in src/hot_reload/config.rs

View workflow job for this annotation

GitHub Actions / clippy

associated items `load_from`, `reload`, and `save` are never used

warning: associated items `load_from`, `reload`, and `save` are never used --> src/hot_reload/config.rs:28:12 | 27 | impl HotReloadConfig { | -------------------- associated items in this implementation 28 | pub fn load_from(path: &PathBuf) -> Result<Self> { | ^^^^^^^^^ ... 35 | pub fn reload(&mut self) -> Result<()> { | ^^^^^^ ... 44 | pub fn save(&self) -> Result<()> { | ^^^^
let data = std::fs::read_to_string(path)?;
let mut h: Self = toml::from_str(&data)?;
h.path = path.to_owned();

Check warning on line 31 in src/hot_reload/config.rs

View workflow job for this annotation

GitHub Actions / clippy

implicitly cloning a `PathBuf` by calling `to_owned` on its dereferenced type

warning: implicitly cloning a `PathBuf` by calling `to_owned` on its dereferenced type --> src/hot_reload/config.rs:31:18 | 31 | h.path = path.to_owned(); | ^^^^^^^^^^^^^^^ help: consider using: `path.clone()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
Ok(h)
}

pub fn reload(&mut self) -> Result<()> {
let path = self.path.clone();
let data = std::fs::read_to_string(path)?;
let mut h: Self = toml::from_str(&data)?;

Check warning on line 38 in src/hot_reload/config.rs

View workflow job for this annotation

GitHub Actions / clippy

variable does not need to be mutable

warning: variable does not need to be mutable --> src/hot_reload/config.rs:38:13 | 38 | let mut h: Self = toml::from_str(&data)?; | ----^ | | | help: remove this `mut`
self.events = h.events;
self.files = h.files;
Ok(())
}

pub fn save(&self) -> Result<()> {
let cfg_str = toml::to_string_pretty(&self)?;
let mut f = File::create(&self.path)?;
f.write_all(cfg_str.as_bytes())?;

Ok(())
}
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Entry {
pub path: String,
#[serde(with = "super::pattern_serde")]
pub path: Pattern,
pub action: HotReloadAction,
}
10 changes: 5 additions & 5 deletions src/hot_reload/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use anyhow::{Result, Context};
use glob_match::glob_match;
use notify::{Watcher, recommended_watcher, EventKind};

Check warning on line 2 in src/hot_reload/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `Watcher`

warning: unused import: `Watcher` --> src/hot_reload/mod.rs:2:14 | 2 | use notify::{Watcher, recommended_watcher, EventKind}; | ^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

use crate::{commands::build::BuildContext, create_http_client, model::Server};
use crate::{core::BuildContext, create_http_client, model::Server};

use self::config::{HotReloadConfig, HotReloadAction};

pub mod config;
pub mod pattern_serde;

#[derive(Debug)]
pub struct DevSession {
pub ctx: BuildContext,
}

impl DevSession {
pub async fn start(config: &HotReloadConfig) -> Result<()> {
pub async fn start(config: HotReloadConfig) -> Result<()> {

Check warning on line 17 in src/hot_reload/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

associated function `start` is never used

warning: associated function `start` is never used --> src/hot_reload/mod.rs:17:18 | 16 | impl DevSession { | --------------- associated function in this implementation 17 | pub async fn start(config: HotReloadConfig) -> Result<()> { | ^^^^^
let server = Server::load().context("Failed to load server.toml")?;
let http_client = create_http_client()?;

Expand All @@ -31,12 +31,12 @@ impl DevSession {
EventKind::Create(_) | EventKind::Modify(_) => {
for path in e.paths {
let Some(file) = config.files.iter().find(|f| {
glob_match(&f.path, &path.to_string_lossy())
f.path.matches_path(&path)
}) else {
return;
};

match file.action {
match &file.action {
HotReloadAction::Reload => {

}
Expand Down
11 changes: 11 additions & 0 deletions src/hot_reload/pattern_serde.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use glob::Pattern;
use serde::{Serializer, Deserializer, Serialize, Deserialize};

pub fn serialize<S: Serializer>(pat: &Pattern, ser: S) -> Result<S::Ok, S::Error> {
pat.as_str().serialize(ser)
}

pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Pattern, D::Error> {
Ok(Pattern::new(&String::deserialize(de)?)
.map_err(serde::de::Error::custom)?)

Check failure on line 10 in src/hot_reload/pattern_serde.rs

View workflow job for this annotation

GitHub Actions / clippy

question mark operator is useless here

error: question mark operator is useless here --> src/hot_reload/pattern_serde.rs:9:5 | 9 | / Ok(Pattern::new(&String::deserialize(de)?) 10 | | .map_err(serde::de::Error::custom)?) | |________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark = note: `#[deny(clippy::needless_question_mark)]` implied by `#[deny(clippy::all)]` help: try removing question mark and `Ok()` | 9 ~ Pattern::new(&String::deserialize(de)?) 10 + .map_err(serde::de::Error::custom) |
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mod core;
mod model;
mod sources;
mod util;
//mod hot_reload;
mod hot_reload;

fn cli() -> Command {
Command::new("mcman")
Expand Down
3 changes: 2 additions & 1 deletion src/model/downloadable/import_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ impl Downloadable {
Some(_) | None => {
let items = vec!["Add as Custom URL", "Add as Jenkins", "Nevermind, cancel"];
let selection = Select::with_theme(&ColorfulTheme::default())
.with_prompt(" How would you like to import this URL?")
.with_prompt(format!(" How would you like to import this URL?\n -> {urlstr}"))
.items(&items)
.default(0)
.interact_opt()?;
Expand All @@ -413,6 +413,7 @@ impl Downloadable {

let desc: String = Input::with_theme(&ColorfulTheme::default())
.with_prompt(" Optional description/comment?")
.default(String::new())
.interact_text()?;

Ok(Self::Url {
Expand Down
Loading

0 comments on commit 6df6daf

Please sign in to comment.