1use std::{collections::HashSet, path::PathBuf, str::FromStr};
2
3use itertools::Itertools;
4use lux_lib::{
5 config::Config, git::shorthand::RemoteGitUrlShorthand, lua_version::LuaVersion,
6 operations::Sync, package::PackageReq, tree::Tree, workspace::Workspace,
7};
8use miette::{Context, Result};
9use walkdir::WalkDir;
10
11pub fn top_level_ignored_files(project: &Workspace) -> Vec<PathBuf> {
12 let top_level_project_files = ignore::WalkBuilder::new(project.root())
13 .max_depth(Some(1))
14 .build()
15 .filter_map(Result::ok)
16 .filter_map(|entry| {
17 let file = entry.into_path();
18 if file.is_dir() || file.extension().is_some_and(|ext| ext == "lua") {
19 Some(file)
20 } else {
21 None
22 }
23 })
24 .collect::<HashSet<_>>();
25
26 let top_level_files = WalkDir::new(project.root())
27 .max_depth(1)
28 .into_iter()
29 .filter_map(Result::ok)
30 .filter_map(|entry| {
31 let file = entry.into_path();
32 if file.is_dir() || file.extension().is_some_and(|ext| ext == "lua") {
33 Some(file)
34 } else {
35 None
36 }
37 })
38 .collect::<HashSet<_>>();
39
40 top_level_files
41 .difference(&top_level_project_files)
42 .cloned()
43 .collect_vec()
44}
45
46#[derive(Debug, Clone)]
50pub enum PackageReqOrGitShorthand {
51 PackageReq(PackageReq),
52 GitShorthand(RemoteGitUrlShorthand),
53}
54
55impl FromStr for PackageReqOrGitShorthand {
56 type Err = miette::Report;
57
58 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
59 match RemoteGitUrlShorthand::parse_with_prefix(s) {
60 Ok(shorthand) => Ok(Self::GitShorthand(shorthand)),
61 Err(_) => Ok(Self::PackageReq(PackageReq::parse(s)?)),
62 }
63 }
64}
65
66pub fn current_workspace_or_user_tree(config: &Config) -> Result<Tree> {
69 let workspace = Workspace::current()?;
70 Ok(match &workspace {
71 Some(workspace) => workspace.tree(config)?,
72 None => {
73 let lua_version = LuaVersion::from(config)?.clone();
74 config.user_tree(lua_version)?
75 }
76 })
77}
78
79pub async fn sync_dependencies_if_locked(workspace: &Workspace, config: &Config) -> Result<()> {
80 Sync::new(workspace, config)
83 .sync_dependencies()
84 .await
85 .wrap_err("syncing dependencies with the project lockfile failed.")?;
86 Ok(())
87}
88
89pub async fn sync_build_dependencies_if_locked(
90 workspace: &Workspace,
91 config: &Config,
92) -> Result<()> {
93 Sync::new(workspace, config)
94 .sync_build_dependencies()
95 .await
96 .wrap_err("syncing build dependencies with the project lockfile failed.")?;
97 Ok(())
98}
99
100pub async fn sync_test_dependencies_if_locked(
101 workspace: &Workspace,
102 config: &Config,
103) -> Result<()> {
104 Sync::new(workspace, config)
105 .sync_test_dependencies()
106 .await
107 .wrap_err("syncing test dependencies with the project lockfile failed.")?;
108 Ok(())
109}
110
111pub fn exists_matching_workspace_member(package_req: &PackageReq) -> Result<bool> {
112 let workspace = Workspace::current()?;
113 Ok(workspace.is_some_and(|ws| {
114 ws.select_member(package_req.name()).is_ok_and(|project| {
115 project
116 .toml()
117 .version()
118 .is_ok_and(|version| package_req.version_req().matches(&version))
119 })
120 }))
121}