Compare commits
5 commits
7ee9ee1159
...
e783178493
| Author | SHA1 | Date | |
|---|---|---|---|
|
e783178493 |
|||
|
5a7762ac13 |
|||
|
255220b43c |
|||
|
fc2d89892c |
|||
|
8ed0b6fb12 |
3 changed files with 128 additions and 120 deletions
|
|
@ -6,65 +6,75 @@ pub trait ExportProfile {
|
||||||
fn rules(&self) -> Vec<Box<dyn Rule>>;
|
fn rules(&self) -> Vec<Box<dyn Rule>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CurseForgeProfile;
|
/// Implements [`ExportProfile`] for a unit struct with a static name and rule
|
||||||
pub struct ModrinthProfile;
|
/// list.
|
||||||
pub struct ServerPackProfile;
|
///
|
||||||
|
/// Each rule entry is an expression evaluated as
|
||||||
|
/// `Box::new(super::rules::<expr>)`, supporting both bare unit struct names and
|
||||||
|
/// constructor calls with arguments.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// export_profile! {
|
||||||
|
/// MyProfile => "my-profile" {
|
||||||
|
/// SomeRule,
|
||||||
|
/// AnotherRule::new("arg"),
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
macro_rules! export_profile {
|
||||||
|
($struct:ident => $name:literal { $($rule:expr),* $(,)? }) => {
|
||||||
|
pub struct $struct;
|
||||||
|
|
||||||
impl ExportProfile for CurseForgeProfile {
|
impl ExportProfile for $struct {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"curseforge"
|
$name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rules(&self) -> Vec<Box<dyn Rule>> {
|
fn rules(&self) -> Vec<Box<dyn Rule>> {
|
||||||
vec![
|
use super::rules::*;
|
||||||
Box::new(super::rules::CopyProjectFilesRule),
|
vec![
|
||||||
Box::new(super::rules::FilterByPlatformRule),
|
$(Box::new($rule)),*
|
||||||
Box::new(super::rules::MissingProjectsAsOverridesRule::new(
|
]
|
||||||
"curseforge",
|
}
|
||||||
)),
|
}
|
||||||
Box::new(super::rules::CopyOverridesRule),
|
};
|
||||||
Box::new(super::rules::CopyClientOverridesRule),
|
}
|
||||||
Box::new(super::rules::FilterServerOnlyRule),
|
|
||||||
Box::new(super::rules::GenerateManifestRule::curseforge()),
|
export_profile! {
|
||||||
Box::new(super::rules::FilterNonRedistributableRule),
|
CurseForgeProfile => "curseforge" {
|
||||||
Box::new(super::rules::TextReplacementRule),
|
CopyProjectFilesRule,
|
||||||
]
|
FilterByPlatformRule,
|
||||||
|
MissingProjectsAsOverridesRule::new("curseforge"),
|
||||||
|
CopyOverridesRule,
|
||||||
|
CopyClientOverridesRule,
|
||||||
|
FilterServerOnlyRule,
|
||||||
|
GenerateManifestRule::curseforge(),
|
||||||
|
FilterNonRedistributableRule,
|
||||||
|
TextReplacementRule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExportProfile for ModrinthProfile {
|
export_profile! {
|
||||||
fn name(&self) -> &'static str {
|
ModrinthProfile => "modrinth" {
|
||||||
"modrinth"
|
CopyProjectFilesRule,
|
||||||
}
|
FilterByPlatformRule,
|
||||||
|
MissingProjectsAsOverridesRule::new("modrinth"),
|
||||||
fn rules(&self) -> Vec<Box<dyn Rule>> {
|
CopyOverridesRule,
|
||||||
vec![
|
CopyClientOverridesRule,
|
||||||
Box::new(super::rules::CopyProjectFilesRule),
|
FilterServerOnlyRule,
|
||||||
Box::new(super::rules::FilterByPlatformRule),
|
GenerateManifestRule::modrinth(),
|
||||||
Box::new(super::rules::MissingProjectsAsOverridesRule::new(
|
TextReplacementRule
|
||||||
"modrinth",
|
|
||||||
)),
|
|
||||||
Box::new(super::rules::CopyOverridesRule),
|
|
||||||
Box::new(super::rules::CopyClientOverridesRule),
|
|
||||||
Box::new(super::rules::FilterServerOnlyRule),
|
|
||||||
Box::new(super::rules::GenerateManifestRule::modrinth()),
|
|
||||||
Box::new(super::rules::TextReplacementRule),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExportProfile for ServerPackProfile {
|
export_profile! {
|
||||||
fn name(&self) -> &'static str {
|
ServerPackProfile => "serverpack" {
|
||||||
"serverpack"
|
CopyProjectFilesRule,
|
||||||
}
|
CopyServerOverridesRule,
|
||||||
|
FilterClientOnlyRule,
|
||||||
fn rules(&self) -> Vec<Box<dyn Rule>> {
|
TextReplacementRule
|
||||||
vec![
|
|
||||||
Box::new(super::rules::CopyProjectFilesRule),
|
|
||||||
Box::new(super::rules::CopyServerOverridesRule),
|
|
||||||
Box::new(super::rules::FilterClientOnlyRule),
|
|
||||||
Box::new(super::rules::TextReplacementRule),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -578,6 +578,53 @@ pub struct LockFile {
|
||||||
pub lockfile_version: u32,
|
pub lockfile_version: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LockFile {
|
||||||
|
pub fn get_project(&self, pakku_id: &str) -> Option<&Project> {
|
||||||
|
self
|
||||||
|
.projects
|
||||||
|
.iter()
|
||||||
|
.find(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_loader_names(&self) -> Vec<String> {
|
||||||
|
self.loaders.keys().cloned().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_project(&mut self, pakku_id: &str) -> Option<Project> {
|
||||||
|
if let Some(pos) = self
|
||||||
|
.projects
|
||||||
|
.iter()
|
||||||
|
.position(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
||||||
|
{
|
||||||
|
Some(self.projects.remove(pos))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_project(&self, pakku_id: &str) -> Option<&Project> {
|
||||||
|
self.get_project(pakku_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_project_mut(&mut self, pakku_id: &str) -> Option<&mut Project> {
|
||||||
|
self
|
||||||
|
.projects
|
||||||
|
.iter_mut()
|
||||||
|
.find(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_project_by_platform_id(
|
||||||
|
&self,
|
||||||
|
platform: &str,
|
||||||
|
id: &str,
|
||||||
|
) -> Option<&Project> {
|
||||||
|
self
|
||||||
|
.projects
|
||||||
|
.iter()
|
||||||
|
.find(|p| p.id.get(platform).is_some_and(|pid| pid == id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LockFile {
|
impl LockFile {
|
||||||
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
|
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||||
Self::load_with_validation(path, true)
|
Self::load_with_validation(path, true)
|
||||||
|
|
@ -720,52 +767,4 @@ impl LockFile {
|
||||||
self.projects.push(project);
|
self.projects.push(project);
|
||||||
self.projects.sort_by_key(super::project::Project::get_name);
|
self.projects.sort_by_key(super::project::Project::get_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_project(&self, pakku_id: &str) -> Option<&Project> {
|
|
||||||
self
|
|
||||||
.projects
|
|
||||||
.iter()
|
|
||||||
.find(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_loader_names(&self) -> Vec<String> {
|
|
||||||
self.loaders.keys().cloned().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_project(&mut self, pakku_id: &str) -> Option<Project> {
|
|
||||||
if let Some(pos) = self
|
|
||||||
.projects
|
|
||||||
.iter()
|
|
||||||
.position(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
|
||||||
{
|
|
||||||
Some(self.projects.remove(pos))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_project(&self, pakku_id: &str) -> Option<&Project> {
|
|
||||||
self
|
|
||||||
.projects
|
|
||||||
.iter()
|
|
||||||
.find(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_project_mut(&mut self, pakku_id: &str) -> Option<&mut Project> {
|
|
||||||
self
|
|
||||||
.projects
|
|
||||||
.iter_mut()
|
|
||||||
.find(|p| p.pakku_id.as_deref() == Some(pakku_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_project_by_platform_id(
|
|
||||||
&self,
|
|
||||||
platform: &str,
|
|
||||||
id: &str,
|
|
||||||
) -> Option<&Project> {
|
|
||||||
self
|
|
||||||
.projects
|
|
||||||
.iter()
|
|
||||||
.find(|p| p.id.get(platform).is_some_and(|pid| pid == id))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,30 +72,29 @@ impl RateLimiter {
|
||||||
|
|
||||||
let interval = Duration::from_secs(60) / rate.max(1);
|
let interval = Duration::from_secs(60) / rate.max(1);
|
||||||
|
|
||||||
let mut inner = self.inner.lock().await;
|
loop {
|
||||||
let now = Instant::now();
|
let mut inner = self.inner.lock().await;
|
||||||
let platform_requests =
|
let now = Instant::now();
|
||||||
inner.requests.entry(platform.to_string()).or_default();
|
let platform_requests =
|
||||||
|
inner.requests.entry(platform.to_string()).or_default();
|
||||||
|
|
||||||
platform_requests
|
platform_requests
|
||||||
.retain(|t| now.duration_since(*t) < Duration::from_secs(60));
|
.retain(|t| now.duration_since(*t) < Duration::from_secs(60));
|
||||||
|
|
||||||
if platform_requests.len() >= burst as usize
|
if platform_requests.len() >= burst as usize
|
||||||
&& let Some(oldest) = platform_requests.first()
|
&& let Some(oldest) = platform_requests.first()
|
||||||
{
|
{
|
||||||
let wait_time = interval.saturating_sub(now.duration_since(*oldest));
|
let wait_time = interval.saturating_sub(now.duration_since(*oldest));
|
||||||
if wait_time > Duration::ZERO {
|
if wait_time > Duration::ZERO {
|
||||||
drop(inner);
|
drop(inner);
|
||||||
tokio::time::sleep(wait_time).await;
|
tokio::time::sleep(wait_time).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
platform_requests.push(Instant::now());
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inner = self.inner.lock().await;
|
|
||||||
let platform_requests =
|
|
||||||
inner.requests.entry(platform.to_string()).or_default();
|
|
||||||
platform_requests.push(Instant::now());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn wait_for(&self, platform: &str) {
|
pub async fn wait_for(&self, platform: &str) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue