-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Implement ls
command
#17
base: main
Are you sure you want to change the base?
Changes from all commits
39220ff
432c423
f319325
ec45c1e
ed1c4aa
56b9854
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
use std::path::{PathBuf, MAIN_SEPARATOR}; | ||
|
||
use clap::Parser; | ||
use termtree::Tree; | ||
|
||
use pacquet_package_json::{DependencyGroup, PackageJson}; | ||
|
||
use crate::package_manager::{PackageManager, PackageManagerError}; | ||
|
||
#[derive(Parser, Debug)] | ||
pub struct ListArgs { | ||
/// Perform the command on every package subdirectories | ||
/// or on every workspace | ||
#[arg(long = "recursive", short = 'r')] | ||
pub recursive: bool, | ||
/// Log the output as JSON | ||
#[arg(long = "json")] | ||
pub json: bool, | ||
/// Show the extended information | ||
#[arg(long = "long")] | ||
pub long: bool, | ||
/// Outputs the package directories into a parseable format | ||
#[arg(long = "parseable")] | ||
pub parseable: bool, | ||
/// List the package in the global install directory instead of the | ||
/// current project | ||
#[arg(long = "global", short = 'g')] | ||
pub global: bool, | ||
/// Max display depth of the dependency tree | ||
#[arg(long = "depth")] | ||
pub depth: u32, | ||
/// Display only dependencies within dependencies or optionalDependencies | ||
#[arg(long = "prod", short = 'p')] | ||
pub prod: bool, | ||
/// Display only dependencies within devDependencies | ||
#[arg(long = "dev", short = 'd')] | ||
pub dev: bool, | ||
/// Omit packages from optionalDependencies | ||
#[arg(long = "no-optional")] | ||
pub no_opts: bool, | ||
/// Display only depndencies that are also projects within the workspace | ||
#[arg(long = "only-projects")] | ||
pub projects_only: bool, | ||
/// Display the dependencies from a given subset of dependencies | ||
#[arg(long = "filter", short = 'f')] | ||
pub filter: String, | ||
} | ||
|
||
impl ListArgs { | ||
pub fn get_scope(&self) -> DependencyGroup { | ||
if self.dev { | ||
DependencyGroup::Dev | ||
} else { | ||
DependencyGroup::Default | ||
} | ||
} | ||
|
||
pub fn get_depth(&self) -> u32 { | ||
let mut depth: u32 = 1; | ||
self.depth.clone_into(&mut depth); | ||
|
||
depth | ||
} | ||
} | ||
|
||
impl PackageManager { | ||
pub fn list( | ||
&self, | ||
package_json: &PackageJson, | ||
dependency_group: DependencyGroup, | ||
node_modules_path: &PathBuf, | ||
depth: u32, | ||
) -> Result<Tree<&str>, PackageManagerError> { | ||
match dependency_group { | ||
DependencyGroup::Default => { | ||
let mut root = Tree::new(""); | ||
let dependencies = package_json.get_dependencies(vec![DependencyGroup::Default]); | ||
|
||
for (name, version) in dependencies { | ||
// let label = format!("{} - {}", name, version); | ||
// print!("{}", label); | ||
let mut tree = helper::create_tree(name, version); | ||
|
||
if depth > 1 { | ||
let path = format!("{}{}{}", &name, MAIN_SEPARATOR, "package.json"); | ||
let pjson = PackageJson::from_path(&node_modules_path.join(path))?; | ||
let subtree = self.list( | ||
&pjson, | ||
DependencyGroup::Default, | ||
node_modules_path, | ||
depth - 1, | ||
)?; | ||
|
||
tree.push(subtree); | ||
} | ||
|
||
root.push(tree.clone()); | ||
} | ||
Comment on lines
+79
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basically, here, I'm losing the reference to the Sadly, the way I initially designed seems to not play well with the borrowed concept 🤔 Another option was to convert it to an iterator and use the utils function to map it and print it back. But wanted to keep it as last resort. Any thoughts? 🤔 |
||
|
||
Ok(root) | ||
} | ||
// DependencyGroup::Dev => Ok(root), | ||
_ => Ok(Tree::new("".clone())), | ||
} | ||
} | ||
} | ||
|
||
mod helper { | ||
use termtree::Tree; | ||
pub fn create_tree<'a>(name: &'a str, version: &str) -> Tree<&'a str> { | ||
let label = format!("{}@{}", name.clone().to_owned(), version.clone().to_owned()); | ||
Tree::new(label.to_owned().as_str()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I'm quite stuck (sorry for the silly question, still getting used to
Rust
ownership concept).I've tried several things but always stopped upon the issue of the lifetime of the strings within the loop.
cc: @anonrig