cairo_toolchain_xtasks/
sync_version.rs1use anyhow::{Result, ensure};
4use clap::Parser;
5use semver::{Prerelease, Version};
6use toml_edit::{DocumentMut, value};
7use xshell::{Shell, cmd};
8
9#[derive(Default, Parser)]
11pub struct Args {
12 #[arg(long, default_value_t = false)]
14 pub dry_run: bool,
15
16 #[arg(long)]
18 pub build: Option<String>,
19
20 #[arg(long, default_value_t = false)]
22 pub no_pre_release: bool,
23}
24
25pub fn main(args: Args) -> Result<()> {
26 let sh = Shell::new()?;
27
28 let mut cargo_toml = sh.read_file("Cargo.toml")?.parse::<DocumentMut>()?;
29
30 let (package, table_path) = if let Some(workspace_package) = cargo_toml
31 .get_mut("workspace")
32 .and_then(|t| t.get_mut("package"))
33 .and_then(|t| t.as_table_mut())
34 {
35 (workspace_package, "workspace.package")
36 } else {
37 (cargo_toml["package"].as_table_mut().unwrap(), "package")
38 };
39
40 let mut version = expected_version()?;
41
42 if let Some(build) = args.build {
43 version.build = build.parse()?;
44 }
45 if args.no_pre_release {
46 version.pre = Prerelease::EMPTY;
47 }
48
49 package["version"] = value(version.to_string());
50
51 eprintln!("[{table_path}]\n{package}");
52
53 if !args.dry_run {
54 sh.write_file("Cargo.toml", cargo_toml.to_string())?;
55
56 cmd!(sh, "cargo fetch").run()?;
57 }
58
59 Ok(())
60}
61
62pub fn expected_version() -> Result<Version> {
65 let sh = Shell::new()?;
68 let cargo_lock = sh.read_file("Cargo.lock")?.parse::<DocumentMut>()?;
69 let packages = cargo_lock["package"].as_array_of_tables().unwrap();
70 let compiler = {
71 let pkgs = packages
72 .into_iter()
73 .filter(|pkg| pkg["name"].as_str().unwrap() == "cairo-lang-compiler")
74 .collect::<Vec<_>>();
75 ensure!(
76 pkgs.len() == 1,
77 "expected exactly one cairo-lang-compiler package in Cargo.lock, found: {}",
78 pkgs.len()
79 );
80 pkgs.into_iter().next().unwrap()
81 };
82 let compiler_version = compiler["version"].as_str().unwrap();
83 Ok(compiler_version.parse()?)
84}