1use clap::Args;
2use itertools::Itertools;
3use lux_lib::package::{PackageName, PackageReq};
4
5use lux_lib::remote_package_db::RemotePackageDB;
6use lux_lib::rockspec::lua_dependency::LuaDependencyType;
7use lux_lib::workspace::Workspace;
8use lux_lib::{config::Config, operations};
9use miette::{miette, Context, Result};
10
11#[derive(Args)]
12pub struct Update {
13 #[arg(long)]
15 no_integrity_check: bool,
16
17 #[arg(long)]
19 toml: bool,
20
21 packages: Option<Vec<PackageReq>>,
24
25 #[arg(short, long, alias = "dev", visible_short_aliases = ['d', 'b'])]
29 build: Option<Vec<PackageReq>>,
30
31 #[arg(short, long)]
34 test: Option<Vec<PackageReq>>,
35
36 #[arg(short, long, visible_short_alias = 'p')]
38 package: Option<PackageName>,
39}
40
41pub async fn update(args: Update, config: Config) -> Result<()> {
42 if args.toml {
43 let mut workspace = Workspace::current_or_err()?;
44
45 let db = RemotePackageDB::from_config(&config).await?;
46 let package_names = to_package_names(args.packages.as_ref())?;
47 let mut upgrade_all = true;
48 if let Some(packages) = package_names {
49 upgrade_all = false;
50 if let Some(package) = &args.package {
51 let project = workspace.select_member_mut(package)?;
52 project
53 .upgrade(LuaDependencyType::Regular(packages.iter().collect()), &db)
54 .await?;
55 } else {
56 for project in workspace.members_mut().iter_mut() {
57 project
58 .upgrade(LuaDependencyType::Regular(packages.iter().collect()), &db)
59 .await?;
60 }
61 }
62 }
63 let build_package_names = to_package_names(args.build.as_ref())?;
64 if let Some(packages) = build_package_names {
65 upgrade_all = false;
66 if let Some(package) = &args.package {
67 let project = workspace.select_member_mut(package)?;
68 project
69 .upgrade(LuaDependencyType::Build(packages.iter().collect()), &db)
70 .await?;
71 } else {
72 for project in workspace.members_mut().iter_mut() {
73 project
74 .upgrade(LuaDependencyType::Build(packages.iter().collect()), &db)
75 .await?;
76 }
77 }
78 }
79 let test_package_names = to_package_names(args.test.as_ref())?;
80 if let Some(packages) = test_package_names {
81 upgrade_all = false;
82 if let Some(package) = &args.package {
83 let project = workspace.select_member_mut(package)?;
84 project
85 .upgrade(LuaDependencyType::Test(packages.iter().collect()), &db)
86 .await?;
87 } else {
88 for project in workspace.members_mut().iter_mut() {
89 project
90 .upgrade(LuaDependencyType::Test(packages.iter().collect()), &db)
91 .await?;
92 }
93 }
94 }
95 if upgrade_all {
96 if let Some(package) = &args.package {
97 let project = workspace.select_member_mut(package)?;
98 project.upgrade_all(&db).await?;
99 } else {
100 for project in workspace.members_mut().iter_mut() {
101 project.upgrade_all(&db).await?;
102 }
103 }
104 }
105 }
106
107 let updated_packages = operations::Update::new(&config)
108 .packages(args.packages)
109 .build_dependencies(args.build)
110 .test_dependencies(args.test)
111 .validate_integrity(!args.no_integrity_check)
112 .update()
113 .await
114 .wrap_err("update failed.")?;
115
116 if updated_packages.is_empty() {
117 println!("Nothing to update.");
118 return Ok(());
119 }
120
121 Ok(())
122}
123
124fn to_package_names(packages: Option<&Vec<PackageReq>>) -> Result<Option<Vec<PackageName>>> {
125 if packages.is_some_and(|pkgs| !pkgs.iter().any(|pkg| pkg.version_req().is_any())) {
126 return Err(miette!(
127 "Cannot use version constraints to upgrade dependencies in lux.toml."
128 ));
129 }
130 Ok(packages
131 .as_ref()
132 .map(|pkgs| pkgs.iter().map(|pkg| pkg.name()).cloned().collect_vec()))
133}