Skip to content

Commit

Permalink
fix(build/builtin): properly autodetect modules
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb committed Dec 10, 2024
1 parent 503a2c9 commit e832971
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 34 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rocks-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ thiserror = "2.0.0"
gpgme = "0.11.0"
futures = "0.3.31"
async-recursion = "1.1.1"
predicates = "3.1.2"

[dev-dependencies]
httptest = { version = "0.16.1" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return true
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rockspec_format = "3.0"
package = "foo"
version = "1.0.0-1"
source = {
url = 'https://github.com/nvim-neorocks/luarocks-stub',
}
28 changes: 19 additions & 9 deletions rocks-lib/src/build/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use std::{
collections::HashMap,
path::{Path, PathBuf},
str::FromStr,
};
use walkdir::WalkDir;

use crate::{
build::utils,
config::Config,
lua_installation::LuaInstallation,
progress::{
Progress::{self},
ProgressBar,
},
rockspec::{utils, Build, BuiltinBuildSpec, LuaModule, ModuleSpec},
rockspec::{Build, BuiltinBuildSpec, LuaModule, ModuleSpec},
tree::RockLayout,
};
use walkdir::WalkDir;

use super::BuildError;

Expand All @@ -30,10 +32,11 @@ impl Build for BuiltinBuildSpec {
progress: &Progress<ProgressBar>,
) -> Result<(), Self::Err> {
// Detect all Lua modules
let modules = autodetect_modules(build_dir)
.into_iter()
.chain(self.modules)
.collect::<HashMap<_, _>>();
let modules = if self.modules.is_empty() {
autodetect_modules(build_dir)
} else {
self.modules
};

progress.map(|p| p.set_position(modules.len() as u64));

Expand Down Expand Up @@ -123,8 +126,9 @@ fn autodetect_modules(build_dir: &Path) -> HashMap<LuaModule, ModuleSpec> {
})
})
.map(|file| {
let diff: PathBuf = pathdiff::diff_paths(build_dir.join(file.into_path()), build_dir)
.expect("failed to autodetect modules");
let diff: PathBuf =
pathdiff::diff_paths(build_dir.join(file.clone().into_path()), build_dir)
.expect("failed to autodetect modules");

// NOTE(vhyrro): You may ask why we convert all paths to Lua module paths
// just to convert them back later in the `run()` stage.
Expand All @@ -133,7 +137,13 @@ fn autodetect_modules(build_dir: &Path) -> HashMap<LuaModule, ModuleSpec> {
// data in this form allows us to respect any overrides made by the user (which follow
// the `module.name` format, not our internal one).
let pathbuf = diff.components().skip(1).collect::<PathBuf>();
let lua_module = LuaModule::from_pathbuf(pathbuf);
let mut lua_module = LuaModule::from_pathbuf(pathbuf);

// NOTE(mrcjkb): `LuaModule` does not parse as "<module>.init" from files named "init.lua"
// To make sure we don't change the file structure when installing, we append it here.
if file.file_name().to_string_lossy().as_bytes() == b"init.lua" {
lua_module = lua_module.join(&LuaModule::from_str("init").unwrap())
}

(lua_module, ModuleSpec::SourcePath(diff))
})
Expand Down
71 changes: 70 additions & 1 deletion rocks-lib/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use crate::{
operations::{self, FetchSrcRockError},
package::RemotePackage,
progress::{Progress, ProgressBar},
rockspec::{utils, Build as _, BuildBackendSpec, LuaVersionError, Rockspec},
rockspec::{Build as _, BuildBackendSpec, LuaVersionError, Rockspec},
tree::{RockLayout, Tree},
};
pub(crate) mod utils; // Make build utilities available as a submodule
use indicatif::style::TemplateError;
use make::MakeError;
use rust_mlua::RustError;
Expand Down Expand Up @@ -232,3 +233,71 @@ pub async fn build(
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use predicates::prelude::*;
use std::path::PathBuf;

use assert_fs::{
assert::PathAssert,
prelude::{PathChild as _, PathCopy},
};

use crate::{
config::{ConfigBuilder, LuaVersion},
lua_installation::LuaInstallation,
progress::MultiProgress,
tree::RockLayout,
};

#[tokio::test]
async fn test_builtin_build() {
let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("resources/test/sample-project-no-build-spec");
let build_dir = assert_fs::TempDir::new().unwrap();
build_dir.copy_from(&project_root, &["**"]).unwrap();
let dest_dir = assert_fs::TempDir::new().unwrap();
let config = ConfigBuilder::new().build().unwrap();
let rock_layout = RockLayout {
rock_path: dest_dir.to_path_buf(),
etc: dest_dir.join("etc"),
lib: dest_dir.join("lib"),
src: dest_dir.join("src"),
bin: dest_dir.join("bin"),
conf: dest_dir.join("conf"),
doc: dest_dir.join("doc"),
};
let lua = LuaInstallation::new(config.lua_version().unwrap_or(&LuaVersion::Lua51), &config);
let rockspec_content = String::from_utf8(
std::fs::read("resources/test/sample-project-no-build-spec/project.rockspec").unwrap(),
)
.unwrap();
let rockspec = Rockspec::new(&rockspec_content).unwrap();
let progress = Progress::Progress(MultiProgress::new());
run_build(
&rockspec,
&rock_layout,
&lua,
&config,
&build_dir,
&progress.map(|p| p.new_bar()),
)
.await
.unwrap();
let foo_dir = dest_dir.child("src").child("foo");
foo_dir.assert(predicate::path::is_dir());
let foo_init = foo_dir.child("init.lua");
foo_init.assert(predicate::path::is_file());
foo_init.assert(predicate::str::contains("return true"));
let foo_bar_dir = foo_dir.child("bar");
foo_bar_dir.assert(predicate::path::is_dir());
let foo_bar_init = foo_bar_dir.child("init.lua");
foo_bar_init.assert(predicate::path::is_file());
foo_bar_init.assert(predicate::str::contains("return true"));
let foo_bar_baz = foo_bar_dir.child("baz.lua");
foo_bar_baz.assert(predicate::path::is_file());
foo_bar_baz.assert(predicate::str::contains("return true"));
}
}
15 changes: 7 additions & 8 deletions rocks-lib/src/build/rust_mlua.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
use itertools::Itertools;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::{fs, io};
use thiserror::Error;

use super::utils::lua_lib_extension;
use crate::config::LuaVersionUnset;
use crate::progress::{Progress, ProgressBar};
use crate::rockspec::utils::lua_lib_extension;
use crate::{
config::{Config, LuaVersion},
lua_installation::LuaInstallation,
rockspec::{Build, RustMluaBuildSpec},
tree::RockLayout,
};
use itertools::Itertools;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::{fs, io};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum RustError {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use crate::{
build::BuildError,
lua_installation::LuaInstallation,
rockspec::{LuaModule, ModulePaths},
};
use itertools::Itertools;
use std::{
io,
Expand All @@ -6,13 +11,9 @@ use std::{
};
use target_lexicon::Triple;

use crate::{build::BuildError, lua_installation::LuaInstallation};

use super::{LuaModule, ModulePaths};

/// Copies a lua source file to a specific destination. The destination is described by a
/// `module.path` syntax (equivalent to the syntax provided to Lua's `require()` function).
pub fn copy_lua_to_module_path(
pub(crate) fn copy_lua_to_module_path(
source: &PathBuf,
target_module: &LuaModule,
target_dir: &Path,
Expand Down Expand Up @@ -40,7 +41,7 @@ fn validate_output(output: Output) -> Result<(), BuildError> {
/// Compiles a set of C files into a single dynamic library and places them under `{target_dir}/{target_file}`.
/// # Panics
/// Panics if no parent or no filename can be determined for the target path.
pub fn compile_c_files(
pub(crate) fn compile_c_files(
files: &Vec<PathBuf>,
target_module: &LuaModule,
target_dir: &Path,
Expand Down Expand Up @@ -93,7 +94,7 @@ pub fn compile_c_files(
}

/// the extension for Lua libraries.
pub fn lua_lib_extension() -> &'static str {
pub(crate) fn lua_lib_extension() -> &'static str {
if cfg!(target_os = "windows") {
"dll"
} else {
Expand All @@ -104,7 +105,7 @@ pub fn lua_lib_extension() -> &'static str {
/// Compiles a set of C files (with extra metadata) to a given destination.
/// # Panics
/// Panics if no filename for the target path can be determined.
pub fn compile_c_modules(
pub(crate) fn compile_c_modules(
data: &ModulePaths,
source_dir: &Path,
target_module: &LuaModule,
Expand Down
2 changes: 1 addition & 1 deletion rocks-lib/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use itertools::Itertools;
use serde::Serialize;
use std::{env, fmt::Display, io, path::PathBuf, str::FromStr};

use crate::{rockspec::utils::lua_lib_extension, tree::Tree};
use crate::{build::utils::lua_lib_extension, tree::Tree};

const LUA_PATH_SEPARATOR: &str = ";";

Expand Down
31 changes: 25 additions & 6 deletions rocks-lib/src/rockspec/build/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use serde::{de, Deserialize, Deserializer};
use std::{collections::HashMap, convert::Infallible, fmt::Display, path::PathBuf, str::FromStr};
use thiserror::Error;

use crate::rockspec::{
deserialize_vec_from_lua, FromPlatformOverridable, PartialOverride, PerPlatform,
PlatformOverridable,
use crate::{
build::utils::lua_lib_extension,
rockspec::{
deserialize_vec_from_lua, FromPlatformOverridable, PartialOverride, PerPlatform,
PlatformOverridable,
},
};

use super::utils::lua_lib_extension;

#[derive(Debug, PartialEq, Deserialize, Default, Clone)]
pub struct BuiltinBuildSpec {
/// Keys are module names in the format normally used by the `require()` function
Expand Down Expand Up @@ -39,11 +40,17 @@ impl LuaModule {
.unwrap_or("".into());
let module = path
.to_string_lossy()
.trim_end_matches(extension.as_str())
.trim_end_matches(format!("init.{}", extension).as_str())
.trim_end_matches(format!(".{}", extension).as_str())
.trim_end_matches(std::path::MAIN_SEPARATOR_STR)
.replace(std::path::MAIN_SEPARATOR_STR, ".");
LuaModule(module)
}

pub fn join(&self, other: &LuaModule) -> LuaModule {
LuaModule(format!("{}.{}", self.0, other.0))
}

pub fn as_str(&self) -> &str {
self.0.as_str()
}
Expand Down Expand Up @@ -291,6 +298,18 @@ mod tests {

use super::*;

#[tokio::test]
pub async fn parse_lua_module_from_path() {
let lua_module = LuaModule::from_pathbuf("foo/init.lua".into());
assert_eq!(&lua_module.0, "foo");
let lua_module = LuaModule::from_pathbuf("foo/bar.lua".into());
assert_eq!(&lua_module.0, "foo.bar");
let lua_module = LuaModule::from_pathbuf("foo/bar/init.lua".into());
assert_eq!(&lua_module.0, "foo.bar");
let lua_module = LuaModule::from_pathbuf("foo/bar/baz.lua".into());
assert_eq!(&lua_module.0, "foo.bar.baz");
}

#[tokio::test]
pub async fn modules_spec_from_lua() {
let lua_content = "
Expand Down
1 change: 0 additions & 1 deletion rocks-lib/src/rockspec/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ mod cmake;
mod make;
mod rust_mlua;

pub mod utils; // Make build utilities available as a submodule
pub use builtin::{BuiltinBuildSpec, LuaModule, ModulePaths, ModuleSpec};
pub use cmake::*;
pub use make::*;
Expand Down

0 comments on commit e832971

Please sign in to comment.