Skip to content

Commit

Permalink
Merge pull request #38 from esp-rs/feature/improve-update
Browse files Browse the repository at this point in the history
Avoid using hardcoded Xtensa Rust version
  • Loading branch information
SergioGasquez authored Nov 3, 2022
2 parents cb88f7f + 5fc3c4e commit 26f971f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ directories-next = "2.0.0"
serde = { version = "1.0.146", features = ["derive"] }
miette = "5.4.1"
regex = "1.6.0"
serde_json = "1.0.87"

[target.aarch64-unknown-linux-gnu.dependencies]
openssl = { version = "0.10", features = ["vendored"] }
Expand Down
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl Config {
let dirs = ProjectDirs::from("rs", "esp", "espup").unwrap();
let file = dirs.config_dir().join("espup.toml");

let config = if let Ok(data) = read(&file) {
let config = if let Ok(data) = read(file) {
toml::from_slice(&data).into_diagnostic()?
} else {
return Err(ErrReport::msg("No config file found"));
Expand Down
41 changes: 15 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use espup::{
},
};
use log::{debug, info, warn};
use regex::Regex;
use std::{
collections::HashSet,
fs::{remove_dir_all, remove_file, File},
Expand All @@ -33,10 +32,6 @@ use std::{
const DEFAULT_EXPORT_FILE: &str = "export-esp.ps1";
#[cfg(not(windows))]
const DEFAULT_EXPORT_FILE: &str = "export-esp.sh";
/// Xtensa Rust Toolchain version regex.
const RE_TOOLCHAIN_VERSION: &str = r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)\.(?P<subpatch>0|[1-9]\d*)?$";
/// Latest Xtensa Rust Toolchain version.
const LATEST_TOOLCHAIN_VERSION: &str = "1.65.0.0";

#[derive(Parser)]
#[command(
Expand Down Expand Up @@ -103,8 +98,8 @@ pub struct InstallOpts {
#[arg(short = 't', long, default_value = "all")]
pub targets: String,
/// Xtensa Rust toolchain version.
#[arg(short = 'v', long, default_value = LATEST_TOOLCHAIN_VERSION, value_parser = parse_version)]
pub toolchain_version: String,
#[arg(short = 'v', long, value_parser = XtensaRust::parse_version)]
pub toolchain_version: Option<String>,
}

#[derive(Debug, Parser)]
Expand All @@ -116,7 +111,7 @@ pub struct UpdateOpts {
#[arg(short = 'l', long, default_value = "info", value_parser = ["debug", "info", "warn", "error"])]
pub log_level: String,
/// Xtensa Rust toolchain version.
#[arg(short = 'v', long, default_value = LATEST_TOOLCHAIN_VERSION, value_parser = parse_version)]
#[arg(short = 'v', long, value_parser = XtensaRust::parse_version)]
pub toolchain_version: Option<String>,
}

Expand All @@ -127,18 +122,6 @@ pub struct UninstallOpts {
pub log_level: String,
}

/// Parses the version of the Xtensa toolchain.
fn parse_version(arg: &str) -> Result<String> {
let re = Regex::new(RE_TOOLCHAIN_VERSION).unwrap();
if !re.is_match(arg) {
bail!(
"{} Invalid toolchain version, must be in the form of '<major>.<minor>.<patch>.<subpatch>'",
emoji::ERROR
);
}
Ok(arg.to_string())
}

/// Installs the Rust for ESP chips environment
fn install(args: InstallOpts) -> Result<()> {
initialize_logger(&args.log_level);
Expand All @@ -153,7 +136,13 @@ fn install(args: InstallOpts) -> Result<()> {
|| targets.contains(&Target::ESP32S2)
|| targets.contains(&Target::ESP32S3)
{
Some(XtensaRust::new(&args.toolchain_version, &host_triple))
let xtensa_rust: XtensaRust = if let Some(toolchain_version) = &args.toolchain_version {
XtensaRust::new(toolchain_version, &host_triple)
} else {
let latest_version = XtensaRust::get_latest_version()?;
XtensaRust::new(&latest_version, &host_triple)
};
Some(xtensa_rust)
} else {
None
};
Expand Down Expand Up @@ -308,12 +297,12 @@ fn update(args: UpdateOpts) -> Result<()> {
info!("{} Updating ESP Rust environment", emoji::DISC);
let host_triple = get_host_triple(args.default_host)?;
let mut config = Config::load().unwrap();
let xtensa_rust: XtensaRust;
if let Some(toolchain_version) = args.toolchain_version {
xtensa_rust = XtensaRust::new(&toolchain_version, &host_triple);
let xtensa_rust: XtensaRust = if let Some(toolchain_version) = args.toolchain_version {
XtensaRust::new(&toolchain_version, &host_triple)
} else {
xtensa_rust = XtensaRust::new(LATEST_TOOLCHAIN_VERSION, &host_triple);
}
let latest_version = XtensaRust::get_latest_version()?;
XtensaRust::new(&latest_version, &host_triple)
};

debug!(
"{} Arguments:
Expand Down
62 changes: 61 additions & 1 deletion src/toolchain/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ use crate::{
};
use anyhow::{bail, Result};
use embuild::cmd;
use log::{info, warn};
use log::{debug, info, warn};
use regex::Regex;
use reqwest::header;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::{env, fs::remove_dir_all, path::PathBuf, process::Stdio};

/// Xtensa Rust Toolchain repository
const DEFAULT_XTENSA_RUST_REPOSITORY: &str =
"https://github.com/esp-rs/rust-build/releases/download";
/// Xtensa Rust Toolchain API URL
const XTENSA_RUST_API_URL: &str = "https://api.github.com/repos/esp-rs/rust-build/releases/latest";
/// Xtensa Rust Toolchain version regex.
const RE_TOOLCHAIN_VERSION: &str = r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)\.(?P<subpatch>0|[1-9]\d*)?$";

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct XtensaRust {
Expand All @@ -42,6 +49,30 @@ pub struct XtensaRust {
}

impl XtensaRust {
/// Get the latest version of Xtensa Rust toolchain.
pub fn get_latest_version() -> Result<String> {
let mut headers = header::HeaderMap::new();
headers.insert("Accept", "application/vnd.github.v3+json".parse().unwrap());

let client = reqwest::blocking::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.user_agent("espup")
.build()
.unwrap();
let res = client
.get(XTENSA_RUST_API_URL)
.headers(headers)
.send()?
.text()?;
let json: serde_json::Value = serde_json::from_str(&res)?;
let mut version = json["tag_name"].to_string();

version.retain(|c| c != 'v' && c != '"');
Self::parse_version(&version)?;
debug!("{} Latest Xtensa Rust version: {}", emoji::DEBUG, version);
Ok(version)
}

/// Installs the Xtensa Rust toolchain.
pub fn install(&self) -> Result<()> {
#[cfg(unix)]
Expand Down Expand Up @@ -148,6 +179,19 @@ impl XtensaRust {
}
}

/// Parses the version of the Xtensa toolchain.
pub fn parse_version(arg: &str) -> Result<String> {
debug!("{} Parsing Xtensa Rust version: {}", emoji::DEBUG, arg);
let re = Regex::new(RE_TOOLCHAIN_VERSION).unwrap();
if !re.is_match(arg) {
bail!(
"{} Invalid toolchain version, must be in the form of '<major>.<minor>.<patch>.<subpatch>'",
emoji::ERROR
);
}
Ok(arg.to_string())
}

/// Removes the Xtensa Rust toolchain.
pub fn uninstall(&self) -> Result<()> {
info!("{} Uninstalling Xtensa Rust toolchain", emoji::WRENCH);
Expand Down Expand Up @@ -264,3 +308,19 @@ fn install_rust_nightly(version: &str) -> Result<()> {
.run()?;
Ok(())
}

#[cfg(test)]
mod tests {
use crate::toolchain::rust::XtensaRust;

#[test]
fn test_xtensa_rust_parse_version() {
assert_eq!(XtensaRust::parse_version("1.45.0.0").unwrap(), "1.45.0.0");
assert_eq!(XtensaRust::parse_version("1.45.0.1").unwrap(), "1.45.0.1");
assert_eq!(XtensaRust::parse_version("1.1.1.1").unwrap(), "1.1.1.1");
assert!(XtensaRust::parse_version("a.1.1.1").is_err());
assert!(XtensaRust::parse_version("1.1.1.1.1").is_err());
assert!(XtensaRust::parse_version("1..1.1").is_err());
assert!(XtensaRust::parse_version("1._.*.1").is_err());
}
}

0 comments on commit 26f971f

Please sign in to comment.