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 pub(crate) 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(
54 LuaDependencyType::Regular(packages.iter().collect()),
55 &db,
56 &config,
57 )
58 .await?;
59 } else {
60 for project in workspace.members_mut().iter_mut() {
61 project
62 .upgrade(
63 LuaDependencyType::Regular(packages.iter().collect()),
64 &db,
65 &config,
66 )
67 .await?;
68 }
69 }
70 }
71 let build_package_names = to_package_names(args.build.as_ref())?;
72 if let Some(packages) = build_package_names {
73 upgrade_all = false;
74 if let Some(package) = &args.package {
75 let project = workspace.select_member_mut(package)?;
76 project
77 .upgrade(
78 LuaDependencyType::Build(packages.iter().collect()),
79 &db,
80 &config,
81 )
82 .await?;
83 } else {
84 for project in workspace.members_mut().iter_mut() {
85 project
86 .upgrade(
87 LuaDependencyType::Build(packages.iter().collect()),
88 &db,
89 &config,
90 )
91 .await?;
92 }
93 }
94 }
95 let test_package_names = to_package_names(args.test.as_ref())?;
96 if let Some(packages) = test_package_names {
97 upgrade_all = false;
98 if let Some(package) = &args.package {
99 let project = workspace.select_member_mut(package)?;
100 project
101 .upgrade(
102 LuaDependencyType::Test(packages.iter().collect()),
103 &db,
104 &config,
105 )
106 .await?;
107 } else {
108 for project in workspace.members_mut().iter_mut() {
109 project
110 .upgrade(
111 LuaDependencyType::Test(packages.iter().collect()),
112 &db,
113 &config,
114 )
115 .await?;
116 }
117 }
118 }
119 if upgrade_all {
120 if let Some(package) = &args.package {
121 let project = workspace.select_member_mut(package)?;
122 project.upgrade_all(&db, &config).await?;
123 } else {
124 for project in workspace.members_mut().iter_mut() {
125 project.upgrade_all(&db, &config).await?;
126 }
127 }
128 }
129 }
130
131 let updated_packages = operations::Update::new(&config)
132 .packages(args.packages)
133 .build_dependencies(args.build)
134 .test_dependencies(args.test)
135 .validate_integrity(!args.no_integrity_check)
136 .update()
137 .await
138 .wrap_err("update failed.")?;
139
140 if updated_packages.is_empty() {
141 println!("Nothing to update.");
142 return Ok(());
143 }
144
145 Ok(())
146}
147
148fn to_package_names(packages: Option<&Vec<PackageReq>>) -> Result<Option<Vec<PackageName>>> {
149 if packages.is_some_and(|pkgs| !pkgs.iter().any(|pkg| pkg.version_req().is_any())) {
150 let names_str = if packages.is_some_and(|pkgs| pkgs.len() == 1) {
151 "package names"
152 } else {
153 "a package name"
154 };
155 return Err(miette!(
156 help = format!("specify {names_str} using the '--toml' flag"),
157 "cannot use version constraints to upgrade dependencies in lux.toml."
158 ));
159 }
160 Ok(packages
161 .as_ref()
162 .map(|pkgs| pkgs.iter().map(|pkg| pkg.name()).cloned().collect_vec()))
163}