From 6dd5645b0c6a8643a46318227ebbedc901e996c0 Mon Sep 17 00:00:00 2001 From: Vhyrro Date: Sun, 30 Jun 2024 12:25:50 +0200 Subject: [PATCH 1/5] feat(lib): add `list` function to `Tree` --- Cargo.lock | 54 +++++++++++++++++ rocks-lib/Cargo.toml | 1 + rocks-lib/src/tree/list.rs | 26 +++++++++ rocks-lib/src/tree/mod.rs | 58 +++++++++++++++++++ .../rocks_lib__tree__tests__tree_list.snap | 9 +++ 5 files changed, 148 insertions(+) create mode 100644 rocks-lib/src/tree/list.rs create mode 100644 rocks-lib/src/tree/snapshots/rocks_lib__tree__tests__tree_list.snap diff --git a/Cargo.lock b/Cargo.lock index ee0c4eba..c9e263ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1205,6 +1205,9 @@ dependencies = [ "console", "lazy_static", "linked-hash-map", + "pest", + "pest_derive", + "serde", "similar", ] @@ -1753,6 +1756,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -3000,6 +3048,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unarray" version = "0.1.4" diff --git a/rocks-lib/Cargo.toml b/rocks-lib/Cargo.toml index 069e41e2..938ed3ca 100644 --- a/rocks-lib/Cargo.toml +++ b/rocks-lib/Cargo.toml @@ -29,6 +29,7 @@ tempdir = "0.3.7" vfs = "0.12.0" walkdir = "2.4.0" zip = "0.6.6" +insta = { version = "1.39.0", features = ["redactions", "yaml"] } [dev-dependencies] httptest = { version = "0.15.5" } diff --git a/rocks-lib/src/tree/list.rs b/rocks-lib/src/tree/list.rs new file mode 100644 index 00000000..418ba069 --- /dev/null +++ b/rocks-lib/src/tree/list.rs @@ -0,0 +1,26 @@ +use std::collections::HashMap; + +use itertools::Itertools; +use walkdir::WalkDir; + +use super::Tree; + +impl<'a> Tree<'a> { + pub fn list(&self) -> HashMap> { + WalkDir::new(dbg!(self.root())) + .min_depth(1) + .max_depth(1) + .into_iter() + .map(|rock_directory| { + let rock_dir = rock_directory.unwrap(); + let (name, version) = rock_dir + .file_name() + .to_str() + .unwrap() + .split_once('@') + .unwrap(); + (name.to_string(), version.to_string()) + }) + .into_group_map() + } +} diff --git a/rocks-lib/src/tree/mod.rs b/rocks-lib/src/tree/mod.rs index c8c95976..850fe321 100644 --- a/rocks-lib/src/tree/mod.rs +++ b/rocks-lib/src/tree/mod.rs @@ -3,6 +3,8 @@ use std::path::PathBuf; use crate::config::LuaVersion; use eyre::Result; +mod list; + /// A tree is a collection of files where installed rocks are located. /// /// `rocks` diverges from the traditional hierarchy employed by luarocks. @@ -22,6 +24,7 @@ pub struct Tree<'a> { } /// Change-agnostic way of referencing various paths for a rock. +#[derive(Debug, PartialEq)] pub struct RockLayout { pub etc: PathBuf, pub lib: PathBuf, @@ -63,3 +66,58 @@ impl<'a> Tree<'a> { Ok(RockLayout { etc, lib, src }) } } + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use insta::{assert_yaml_snapshot, sorted_redaction}; + + use crate::{config::LuaVersion, tree::RockLayout}; + + use super::Tree; + + #[test] + fn rock_layout() { + let tree_path = + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/test/sample-tree"); + + let tree = Tree::new(&tree_path, &LuaVersion::Lua51).unwrap(); + + let neorg = tree + .rock(&"neorg".to_string(), &"8.0.0-1".to_string()) + .unwrap(); + + assert_eq!( + neorg, + RockLayout { + etc: tree_path.join("5.1/neorg@8.0.0-1/etc"), + lib: tree_path.join("5.1/neorg@8.0.0-1/lib"), + src: tree_path.join("5.1/neorg@8.0.0-1/src"), + } + ); + + let lua_cjson = tree + .rock(&"lua-cjson".to_string(), &"2.1.0.9-1".to_string()) + .unwrap(); + + assert_eq!( + lua_cjson, + RockLayout { + etc: tree_path.join("5.1/lua-cjson@2.1.0.9-1/etc"), + lib: tree_path.join("5.1/lua-cjson@2.1.0.9-1/lib"), + src: tree_path.join("5.1/lua-cjson@2.1.0.9-1/src"), + } + ); + } + + #[test] + fn tree_list() { + let tree_path = + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/test/sample-tree"); + + let tree = Tree::new(&tree_path, &LuaVersion::Lua51).unwrap(); + + assert_yaml_snapshot!(tree.list(), { "." => sorted_redaction() }) + } +} diff --git a/rocks-lib/src/tree/snapshots/rocks_lib__tree__tests__tree_list.snap b/rocks-lib/src/tree/snapshots/rocks_lib__tree__tests__tree_list.snap new file mode 100644 index 00000000..fb20ca2b --- /dev/null +++ b/rocks-lib/src/tree/snapshots/rocks_lib__tree__tests__tree_list.snap @@ -0,0 +1,9 @@ +--- +source: rocks-lib/src/tree/mod.rs +expression: tree.list() +--- +lua-cjson: + - 2.1.0.9-1 +neorg: + - 8.8.1-1 + - 8.0.0-1 From 476f354dcb113806cf532b628c4a001d87b68d63 Mon Sep 17 00:00:00 2001 From: Vhyrro Date: Sun, 30 Jun 2024 16:14:48 +0200 Subject: [PATCH 2/5] feat: add `rocks list` command --- rocks-bin/src/list.rs | 39 ++++++++++++++++++++++++++++++++++++++ rocks-bin/src/main.rs | 4 +++- rocks-lib/src/tree/list.rs | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 rocks-bin/src/list.rs diff --git a/rocks-bin/src/list.rs b/rocks-bin/src/list.rs new file mode 100644 index 00000000..92e5b210 --- /dev/null +++ b/rocks-bin/src/list.rs @@ -0,0 +1,39 @@ +use clap::Args; +use eyre::{OptionExt as _, Result}; +use itertools::Itertools as _; +use rocks_lib::{config::Config, tree::Tree}; +use text_trees::{FormatCharacters, StringTreeNode, TreeFormatting}; + +#[derive(Args)] +pub struct List { + #[arg(long)] + outdated: bool, + #[arg(long)] + porcelain: bool, +} + +pub fn list(list_data: List, config: &Config) -> Result<()> { + let tree = Tree::new(&config.tree, config.lua_version.as_ref().ok_or_eyre("lua version not supplied!")?)?; + let available_rocks = tree.list(); + + // TODO(vhyrro): Add `outdated` support. + + if list_data.porcelain { + for (name, versions) in available_rocks { + println!("{}: {}", name, versions.join(" ")); + } + } else { + let formatting = TreeFormatting::dir_tree(FormatCharacters::box_chars()); + for (name, versions) in available_rocks.into_iter().sorted() { + let mut tree = StringTreeNode::new(name.to_owned()); + + for version in versions { + tree.push(version); + } + + println!("{}", tree.to_string_with_format(&formatting)?); + } + } + + Ok(()) +} diff --git a/rocks-bin/src/main.rs b/rocks-bin/src/main.rs index c8b0823a..7858fbde 100644 --- a/rocks-bin/src/main.rs +++ b/rocks-bin/src/main.rs @@ -8,6 +8,7 @@ mod download; mod rockspec; mod search; mod unpack; +mod list; fn parse_lua_version(s: &str) -> Result { match s { @@ -108,7 +109,7 @@ enum Commands { /// Check syntax of a rockspec. Lint, /// List currently installed rocks. - List, + List(list::List), /// Compile package in current directory using a rockspec. Make, /// Auto-write a rockspec for a new version of the rock. @@ -176,6 +177,7 @@ async fn main() { rockspec::write_rockspec(rockspec_data).await.unwrap() } Commands::Build(build_data) => build::build(build_data, &config).unwrap(), + Commands::List(list_data) => list::list(list_data, &config).unwrap(), _ => unimplemented!(), }, None => { diff --git a/rocks-lib/src/tree/list.rs b/rocks-lib/src/tree/list.rs index 418ba069..a98b1fcd 100644 --- a/rocks-lib/src/tree/list.rs +++ b/rocks-lib/src/tree/list.rs @@ -7,7 +7,7 @@ use super::Tree; impl<'a> Tree<'a> { pub fn list(&self) -> HashMap> { - WalkDir::new(dbg!(self.root())) + WalkDir::new(self.root()) .min_depth(1) .max_depth(1) .into_iter() From 2e9522e6cfc1eebfeba9a676da4b45346c921150 Mon Sep 17 00:00:00 2001 From: Vhyrro Date: Sun, 30 Jun 2024 17:43:19 +0200 Subject: [PATCH 3/5] chore: format code --- rocks-bin/src/list.rs | 10 ++++++++-- rocks-bin/src/main.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/rocks-bin/src/list.rs b/rocks-bin/src/list.rs index 92e5b210..8f09c2d6 100644 --- a/rocks-bin/src/list.rs +++ b/rocks-bin/src/list.rs @@ -13,9 +13,15 @@ pub struct List { } pub fn list(list_data: List, config: &Config) -> Result<()> { - let tree = Tree::new(&config.tree, config.lua_version.as_ref().ok_or_eyre("lua version not supplied!")?)?; + let tree = Tree::new( + &config.tree, + config + .lua_version + .as_ref() + .ok_or_eyre("lua version not supplied!")?, + )?; let available_rocks = tree.list(); - + // TODO(vhyrro): Add `outdated` support. if list_data.porcelain { diff --git a/rocks-bin/src/main.rs b/rocks-bin/src/main.rs index 7858fbde..d650c493 100644 --- a/rocks-bin/src/main.rs +++ b/rocks-bin/src/main.rs @@ -5,10 +5,10 @@ use rocks_lib::config::{Config, LuaVersion}; mod build; mod download; +mod list; mod rockspec; mod search; mod unpack; -mod list; fn parse_lua_version(s: &str) -> Result { match s { From 6074b9ffa142f3c1fe899e9982a52b10e74f4ad4 Mon Sep 17 00:00:00 2001 From: Vhyrro Date: Sun, 30 Jun 2024 19:20:17 +0200 Subject: [PATCH 4/5] refactor!: output JSON when --porcelain is provided --- Cargo.lock | 1 + rocks-bin/Cargo.toml | 1 + rocks-bin/src/list.rs | 4 +--- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c9e263ab..746a5a24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2145,6 +2145,7 @@ dependencies = [ "octocrab", "rocks-lib", "rustyline", + "serde_json", "spdx", "spinners", "termcolor", diff --git a/rocks-bin/Cargo.toml b/rocks-bin/Cargo.toml index ac56d63c..feba0394 100644 --- a/rocks-bin/Cargo.toml +++ b/rocks-bin/Cargo.toml @@ -12,6 +12,7 @@ itertools = "0.12.1" nucleo = "0.4.1" octocrab = "0.36.0" rustyline = "14.0.0" +serde_json = "1.0.118" spdx = "0.10.4" spinners = "4.1.1" termcolor = "1.4.1" diff --git a/rocks-bin/src/list.rs b/rocks-bin/src/list.rs index 8f09c2d6..72b4c801 100644 --- a/rocks-bin/src/list.rs +++ b/rocks-bin/src/list.rs @@ -25,9 +25,7 @@ pub fn list(list_data: List, config: &Config) -> Result<()> { // TODO(vhyrro): Add `outdated` support. if list_data.porcelain { - for (name, versions) in available_rocks { - println!("{}: {}", name, versions.join(" ")); - } + println!("{}", serde_json::to_string(&available_rocks)?); } else { let formatting = TreeFormatting::dir_tree(FormatCharacters::box_chars()); for (name, versions) in available_rocks.into_iter().sorted() { From 5c72b13efbf420ba3d5bfca237045b4535239a85 Mon Sep 17 00:00:00 2001 From: Vhyrro Date: Sun, 30 Jun 2024 19:58:16 +0200 Subject: [PATCH 5/5] refactor(bin): `List` -> `ListCmd` --- rocks-bin/src/list.rs | 4 ++-- rocks-bin/src/main.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rocks-bin/src/list.rs b/rocks-bin/src/list.rs index 72b4c801..9ded0c73 100644 --- a/rocks-bin/src/list.rs +++ b/rocks-bin/src/list.rs @@ -5,14 +5,14 @@ use rocks_lib::{config::Config, tree::Tree}; use text_trees::{FormatCharacters, StringTreeNode, TreeFormatting}; #[derive(Args)] -pub struct List { +pub struct ListCmd { #[arg(long)] outdated: bool, #[arg(long)] porcelain: bool, } -pub fn list(list_data: List, config: &Config) -> Result<()> { +pub fn list_installed(list_data: ListCmd, config: &Config) -> Result<()> { let tree = Tree::new( &config.tree, config diff --git a/rocks-bin/src/main.rs b/rocks-bin/src/main.rs index d650c493..b0227794 100644 --- a/rocks-bin/src/main.rs +++ b/rocks-bin/src/main.rs @@ -109,7 +109,7 @@ enum Commands { /// Check syntax of a rockspec. Lint, /// List currently installed rocks. - List(list::List), + List(list::ListCmd), /// Compile package in current directory using a rockspec. Make, /// Auto-write a rockspec for a new version of the rock. @@ -177,7 +177,7 @@ async fn main() { rockspec::write_rockspec(rockspec_data).await.unwrap() } Commands::Build(build_data) => build::build(build_data, &config).unwrap(), - Commands::List(list_data) => list::list(list_data, &config).unwrap(), + Commands::List(list_data) => list::list_installed(list_data, &config).unwrap(), _ => unimplemented!(), }, None => {