1use clap::Args;
2use eyre::{eyre, Context, Result};
3use itertools::Itertools;
4use lux_lib::package::{PackageName, PackageReq};
5use lux_lib::progress::{MultiProgress, ProgressBar};
6use lux_lib::remote_package_db::RemotePackageDB;
7use lux_lib::rockspec::lua_dependency::LuaDependencyType;
8use lux_lib::workspace::Workspace;
9use lux_lib::{config::Config, operations};
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 let progress = MultiProgress::new_arc(&config);
43 progress.map(|p| p.add(ProgressBar::from("🔎 Looking for updates...".to_string())));
44
45 if args.toml {
46 let mut workspace = Workspace::current_or_err()?;
47
48 let progress = MultiProgress::new(&config);
49 let bar = progress.map(|progress| progress.new_bar());
50 let db = RemotePackageDB::from_config(&config, &bar).await?;
51 let package_names = to_package_names(args.packages.as_ref())?;
52 let mut upgrade_all = true;
53 if let Some(packages) = package_names {
54 upgrade_all = false;
55 if let Some(package) = &args.package {
56 let project = workspace.select_member_mut(package)?;
57 project
58 .upgrade(LuaDependencyType::Regular(packages.iter().collect()), &db)
59 .await?;
60 } else {
61 for project in workspace.members_mut().iter_mut() {
62 project
63 .upgrade(LuaDependencyType::Regular(packages.iter().collect()), &db)
64 .await?;
65 }
66 }
67 }
68 let build_package_names = to_package_names(args.build.as_ref())?;
69 if let Some(packages) = build_package_names {
70 upgrade_all = false;
71 if let Some(package) = &args.package {
72 let project = workspace.select_member_mut(package)?;
73 project
74 .upgrade(LuaDependencyType::Build(packages.iter().collect()), &db)
75 .await?;
76 } else {
77 for project in workspace.members_mut().iter_mut() {
78 project
79 .upgrade(LuaDependencyType::Build(packages.iter().collect()), &db)
80 .await?;
81 }
82 }
83 }
84 let test_package_names = to_package_names(args.test.as_ref())?;
85 if let Some(packages) = test_package_names {
86 upgrade_all = false;
87 if let Some(package) = &args.package {
88 let project = workspace.select_member_mut(package)?;
89 project
90 .upgrade(LuaDependencyType::Test(packages.iter().collect()), &db)
91 .await?;
92 } else {
93 for project in workspace.members_mut().iter_mut() {
94 project
95 .upgrade(LuaDependencyType::Test(packages.iter().collect()), &db)
96 .await?;
97 }
98 }
99 }
100 if upgrade_all {
101 if let Some(package) = &args.package {
102 let project = workspace.select_member_mut(package)?;
103 project.upgrade_all(&db).await?;
104 } else {
105 for project in workspace.members_mut().iter_mut() {
106 project.upgrade_all(&db).await?;
107 }
108 }
109 }
110 }
111
112 let updated_packages = operations::Update::new(&config)
113 .progress(progress)
114 .packages(args.packages)
115 .build_dependencies(args.build)
116 .test_dependencies(args.test)
117 .validate_integrity(!args.no_integrity_check)
118 .update()
119 .await
120 .wrap_err("update failed.")?;
121
122 if updated_packages.is_empty() {
123 println!("Nothing to update.");
124 return Ok(());
125 }
126
127 Ok(())
128}
129
130fn to_package_names(packages: Option<&Vec<PackageReq>>) -> Result<Option<Vec<PackageName>>> {
131 if packages.is_some_and(|pkgs| !pkgs.iter().any(|pkg| pkg.version_req().is_any())) {
132 return Err(eyre!(
133 "Cannot use version constraints to upgrade dependencies in lux.toml."
134 ));
135 }
136 Ok(packages
137 .as_ref()
138 .map(|pkgs| pkgs.iter().map(|pkg| pkg.name()).cloned().collect_vec()))
139}