Skip to content

Commit

Permalink
refactor: move Luarock class into separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
vhyrro committed Jul 4, 2024
1 parent 54063c6 commit 318d588
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 66 deletions.
1 change: 1 addition & 0 deletions rocks-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod build;
pub mod config;
pub mod luarock;
pub mod manifest;
pub mod rocks;
pub mod rockspec;
Expand Down
19 changes: 19 additions & 0 deletions rocks-lib/src/luarock/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use semver::{Error, Version};

mod version;

pub use version::{parse_version, parse_version_req};

pub struct LuaRock {
pub name: String,
pub version: Version,
}

impl LuaRock {
pub fn new(name: String, version: String) -> Result<Self, Error> {
Ok(Self {
name,
version: parse_version(&version)?,
})
}
}
56 changes: 56 additions & 0 deletions rocks-lib/src/luarock/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use eyre::Result;
use html_escape::decode_html_entities;
use semver::{Error, Version, VersionReq};

/// Parses a Version from a string, automatically supplying any missing details (i.e. missing
/// minor/patch sections).
pub fn parse_version(s: &str) -> Result<Version, Error> {
Version::parse(&append_minor_patch_if_missing(s.to_string()))
}

/// Transform LuaRocks constraints into constraints that can be parsed by the semver crate.
pub fn parse_version_req(version_constraints: &str) -> Result<VersionReq, Error> {
let unescaped = decode_html_entities(version_constraints)
.to_string()
.as_str()
.to_owned();
let transformed = match unescaped {
s if s.starts_with("~>") => parse_pessimistic_version_constraint(s)?,
s => s,
};

let version_req = VersionReq::parse(&transformed)?;
Ok(version_req)
}

fn parse_pessimistic_version_constraint(version_constraint: String) -> Result<String, Error> {
// pessimistic operator
let min_version_str = &version_constraint[2..].trim();
let min_version = Version::parse(&append_minor_patch_if_missing(min_version_str.to_string()))?;

let max_version = match min_version_str.matches('.').count() {
0 => Version {
major: &min_version.major + 1,
..min_version.clone()
},
1 => Version {
minor: &min_version.minor + 1,
..min_version.clone()
},
_ => Version {
patch: &min_version.patch + 1,
..min_version.clone()
},
};

Ok(format!(">= {min_version}, < {max_version}"))
}

/// Recursively append .0 until the version string has a minor or patch version
fn append_minor_patch_if_missing(version: String) -> String {
if version.matches('.').count() < 2 {
append_minor_patch_if_missing(version + ".0")
} else {
version
}
}
73 changes: 8 additions & 65 deletions rocks-lib/src/rockspec/dependency.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, str::FromStr};

use eyre::{eyre, Result};
use html_escape::decode_html_entities;
use semver::{Version, VersionReq};
use semver::VersionReq;
use serde::{de, Deserialize, Deserializer};

use crate::luarock::{parse_version_req, LuaRock};

use super::{PartialOverride, PerPlatform, PlatformOverridable};

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -43,10 +44,11 @@ impl LuaDependency {
}

pub fn matches(&self, rock: &LuaRock) -> bool {
if self.rock_name != rock.name {
return false;
if self.rock_name == rock.name {
self.rock_version_req.matches(&rock.version)
} else {
false
}
self.rock_version_req.matches(&rock.version)
}
}

Expand Down Expand Up @@ -119,69 +121,10 @@ impl PlatformOverridable for HashMap<String, ExternalDependency> {
}
}

// TODO(mrcjkb): Move this somewhere more suitable
pub struct LuaRock {
pub name: String,
pub version: Version,
}

impl LuaRock {
pub fn new(name: String, version: String) -> Result<Self> {
Ok(Self {
name,
version: Version::parse(append_minor_patch_if_missing(version).as_str())?,
})
}
}

/// Transform LuaRocks constraints into constraints that can be parsed by the semver crate.
fn parse_version_req(version_constraints: &str) -> Result<VersionReq> {
let unescaped = decode_html_entities(version_constraints)
.to_string()
.as_str()
.to_owned();
let transformed = match unescaped {
s if s.starts_with("~>") => parse_pessimistic_version_constraint(s)?,
s => s,
};
let version_req = VersionReq::parse(&transformed)?;
Ok(version_req)
}

fn parse_pessimistic_version_constraint(version_constraint: String) -> Result<String> {
// pessimistic operator
let min_version_str = &version_constraint[2..].trim();
let min_version =
Version::parse(append_minor_patch_if_missing(min_version_str.to_string()).as_str())?;
let max_version = match min_version_str.matches('.').count() {
0 => Version {
major: &min_version.major + 1,
..min_version.clone()
},
1 => Version {
minor: &min_version.minor + 1,
..min_version.clone()
},
_ => Version {
patch: &min_version.patch + 1,
..min_version.clone()
},
};
Ok(">= ".to_string() + &min_version.to_string() + ", < " + &max_version.to_string())
}

/// Recursively append .0 until the version string has a minor or patch version
fn append_minor_patch_if_missing(version: String) -> String {
if version.matches('.').count() < 2 {
return append_minor_patch_if_missing(version + ".0");
}
version
}

#[cfg(test)]
mod tests {

use super::*;
use semver::Version;

#[tokio::test]
async fn parse_luarock() {
Expand Down
3 changes: 2 additions & 1 deletion rocks-lib/src/rockspec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ mod tests {

use std::path::PathBuf;

use crate::rockspec::{LuaRock, PlatformIdentifier};
use crate::luarock::LuaRock;
use crate::rockspec::PlatformIdentifier;

use super::*;

Expand Down

0 comments on commit 318d588

Please sign in to comment.