Skip to content

Commit

Permalink
rework documentation and error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidma committed Nov 4, 2024
1 parent 4811598 commit f0d5321
Show file tree
Hide file tree
Showing 23 changed files with 125 additions and 139 deletions.
13 changes: 7 additions & 6 deletions crates/nao/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
net::Ipv4Addr,
path::Path,
process::Stdio,
time::Duration,
};

use color_eyre::{
Expand All @@ -16,7 +17,7 @@ use tokio::{
select,
};

pub const PING_TIMEOUT_SECONDS: u32 = 2;
const PING_TIMEOUT: Duration = Duration::from_secs(2);

const NAO_SSH_FLAGS: &[&str] = &[
"-lnao",
Expand Down Expand Up @@ -47,17 +48,17 @@ pub struct Nao {
}

impl Nao {
pub fn new(host: Ipv4Addr) -> Self {
Self { address: host }
pub fn new(address: Ipv4Addr) -> Self {
Self { address }
}

pub async fn try_new_with_ping(host: Ipv4Addr) -> Result<Self> {
Self::try_new_with_ping_and_arguments(host, PING_TIMEOUT_SECONDS).await
Self::try_new_with_ping_and_arguments(host, PING_TIMEOUT).await
}

pub async fn try_new_with_ping_and_arguments(
host: Ipv4Addr,
timeout_seconds: u32,
timeout: Duration,
) -> Result<Self> {
#[cfg(target_os = "macos")]
const TIMEOUT_FLAG: &str = "-t";
Expand All @@ -68,7 +69,7 @@ impl Nao {
.arg("-c")
.arg("1")
.arg(TIMEOUT_FLAG)
.arg(timeout_seconds.to_string())
.arg(timeout.as_secs().to_string())
.arg(host.to_string())
.output()
.await
Expand Down
2 changes: 1 addition & 1 deletion crates/repository/src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ impl<'a> CargoCommand<'a> {
repository_root=self.repository_root.to_str().wrap_err("failed to convert repository root to string")?,
cargo_home=cargo_home.to_str().wrap_err("failed to convert cargo home to string")?,
command=self.sub_command,
)
)
}
};
Ok(shell_command)
Expand Down
21 changes: 13 additions & 8 deletions crates/repository/src/communication.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use std::path::Path;

use color_eyre::Result;
use color_eyre::{eyre::Context, Result};
use serde_json::Value;

use crate::modify_json::modify_json_inplace;

/// Sets the communication address in the framework.json file.
///
/// This function takes a boolean value to enable or disable communication. It reads the
/// framework.json file, updates the communication address field, and writes the updated JSON back.
pub async fn set_communication(enable: bool, repository_root: impl AsRef<Path>) -> Result<()> {
pub async fn configure_communication(
enable: bool,
repository_root: impl AsRef<Path>,
) -> Result<()> {
let framework_json = repository_root
.as_ref()
.join("etc/parameters/framework.json");
Expand All @@ -20,11 +19,17 @@ pub async fn set_communication(enable: bool, repository_root: impl AsRef<Path>)
Value::Null
};

modify_json_inplace(framework_json, |mut hardware_json: Value| {
modify_json_inplace(&framework_json, |mut hardware_json: Value| {
hardware_json["communication_addresses"] = address;
hardware_json
})
.await?;
.await
.wrap_err_with(|| {
format!(
"failed to configure communication address in {}",
framework_json.display()
)
})?;

Ok(())
}
12 changes: 7 additions & 5 deletions crates/repository/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ pub struct Configuration {
pub sdk_version: String,
}

pub async fn get_os_version(repository_root: impl AsRef<Path>) -> Result<String> {
let hulk = find_and_parse_hulk_toml(repository_root).await?;
/// Get the OS version configured in the `hulk.toml`.
pub async fn read_os_version(repository_root: impl AsRef<Path>) -> Result<String> {
let hulk = read_hulk_toml(repository_root).await?;
Ok(hulk.os_version)
}

pub async fn get_sdk_version(repository_root: impl AsRef<Path>) -> Result<String> {
let hulk = find_and_parse_hulk_toml(repository_root).await?;
/// Get the SDK version configured in the `hulk.toml`.
pub async fn read_sdk_version(repository_root: impl AsRef<Path>) -> Result<String> {
let hulk = read_hulk_toml(repository_root).await?;
Ok(hulk.sdk_version)
}

pub async fn find_and_parse_hulk_toml(repository_root: impl AsRef<Path>) -> Result<Configuration> {
pub async fn read_hulk_toml(repository_root: impl AsRef<Path>) -> Result<Configuration> {
let hulk_toml = repository_root.as_ref().join("hulk.toml");
let hulk_toml = read_to_string(hulk_toml)
.await
Expand Down
74 changes: 18 additions & 56 deletions crates/repository/src/inspect_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,33 @@ use serde::Deserialize;
struct Cargo {
package: Package,
}

#[derive(Deserialize, Debug)]
struct Package {
version: String,
}

/// Inspects and returns the version of a Cargo package from its `Cargo.toml` file.
///
/// This function takes a path to a `Cargo.toml` file, reads the file,
/// parses the contents to extract the package version, and returns the version.
///
/// # Errors
///
/// This function will return an error if:
///
/// * The `Cargo.toml` file cannot be read.
/// * The contents of the `Cargo.toml` file cannot be parsed.
/// * The version string extracted from the `Cargo.toml` file cannot be parsed into a `Version` object.
///
/// # Example
///
/// ```no_run
/// let version = inspect_version(Path::new("path/to/Cargo.toml")).expect("failed to inspect version");
/// println!("Package version: {}", version);
/// ```
pub fn inspect_version(path: impl AsRef<Path>) -> Result<Version> {
let path = path.as_ref();
let cargo_toml_text = read_to_string(path)
.wrap_err_with(|| format!("failed to load Cargo.toml at {}", path.display()))?;
let cargo_toml: Cargo = toml::from_str(&cargo_toml_text)
.wrap_err_with(|| format!("failed to parse package version from {}", path.display()))?;
let version = Version::parse(&cargo_toml.package.version).wrap_err_with(|| {
format!(
"failed to parse package version '{}' from {}",
cargo_toml.package.version,
path.display()
)
})?;
/// Inspects and returns the version of a package from its `Cargo.toml` file.
pub fn inspect_version(toml_path: impl AsRef<Path>) -> Result<Version> {
let toml_path = toml_path.as_ref();
let cargo_toml_text = read_to_string(toml_path).wrap_err("failed to read file")?;
let cargo_toml: Cargo = toml::from_str(&cargo_toml_text).wrap_err("failed to parse content")?;
let raw_version = &cargo_toml.package.version;
let version = Version::parse(raw_version)
.wrap_err_with(|| format!("failed to parse version '{raw_version}' as SemVer"))?;
Ok(version)
}

/// Checks if there is a new version of the crate available.
///
/// This function takes the current version of a package and the path to a `Cargo.toml` file,
/// reads and parses the version from the `Cargo.toml` file, and compares it with the current version.
/// If the version in the `Cargo.toml` file is newer, it prints a message indicating that a new version
/// is available and provides the command to install the new version.
///
/// # Errors
///
/// This function will return an error if:
///
/// * The `own_version` string cannot be parsed into a `Version` object.
/// * The `Cargo.toml` file cannot be read or parsed to extract the package version.
///
/// # Example
///
/// ```no_run
/// let current_version = "1.0.0";
/// let cargo_toml_path = Path::new("path/to/Cargo.toml");
///
/// check_for_update(current_version, &cargo_toml_path).expect("failed to check for update");
/// ```
/// Checks whether the package has a newer version than the provided version.
pub fn check_for_update(own_version: &str, cargo_toml: impl AsRef<Path>) -> Result<()> {
let own_version = Version::parse(own_version)?;
let cargo_toml_version = inspect_version(&cargo_toml)?;
let own_version = Version::parse(own_version)
.wrap_err_with(|| format!("failed to parse own version '{own_version}' as SemVer"))?;
let cargo_toml_version = inspect_version(&cargo_toml).wrap_err_with(|| {
format!(
"failed to inspect version of package at {}",
cargo_toml.as_ref().display()
)
})?;
if own_version < cargo_toml_version {
let crate_path = cargo_toml.as_ref().parent().unwrap();
warn!(
Expand Down
5 changes: 5 additions & 0 deletions crates/repository/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! Tools and utilities for managing development workflows in the repository.
//!
//! This crate simplifies tasks like building for specific targets, handling SDKs, and setting up
//! configurations, making it easier to develop, configure, and deploy for NAO robots.

pub mod cargo;
pub mod communication;
pub mod configuration;
Expand Down
40 changes: 20 additions & 20 deletions crates/repository/src/location.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::{
collections::{HashMap, HashSet},
io::ErrorKind,
path::Path,
};
use std::{io::ErrorKind, path::Path};

use color_eyre::{
eyre::{bail, eyre, Context},
Expand All @@ -15,9 +11,9 @@ use tokio::{
io,
};

pub async fn get_configured_locations(
pub async fn list_configured_locations(
repository_root: impl AsRef<Path>,
) -> Result<HashMap<String, Option<String>>> {
) -> Result<Vec<(String, Option<String>)>> {
let parameters_root = &repository_root.as_ref().join("etc/parameters");
let results: Vec<_> = [
"nao_location",
Expand Down Expand Up @@ -66,8 +62,13 @@ pub async fn set_location(
repository_root: impl AsRef<Path>,
) -> Result<()> {
let parameters_root = repository_root.as_ref().join("etc/parameters");
if !try_exists(parameters_root.join(location)).await? {
let location_set = list_available_locations(&repository_root).await?;
if !try_exists(parameters_root.join(location))
.await
.wrap_err_with(|| format!("failed checking if location '{location}' exists"))?
{
let location_set = list_available_locations(&repository_root)
.await
.unwrap_or_default();
let available_locations: String = intersperse(
location_set
.into_iter()
Expand All @@ -76,29 +77,28 @@ pub async fn set_location(
)
.collect();
bail!(
"location {location} does not exist. \navailable locations are:\n{available_locations}"
"location {location} does not exist.\navailable locations are:\n{available_locations}"
);
}
let target_location = parameters_root.join(format!("{target}_location"));
let _ = remove_file(&target_location).await;
symlink(location, &target_location)
.await
.wrap_err_with(|| {
format!("failed creating symlink named {target_location:?} pointing to {location:?}, does the location exist?")
})
symlink(location, &target_location).await.wrap_err_with(|| {
format!(
"failed creating symlink named {target_location} pointing to {location}",
target_location = target_location.display()
)
})
}

pub async fn list_available_locations(
repository_root: impl AsRef<Path>,
) -> Result<HashSet<String>> {
pub async fn list_available_locations(repository_root: impl AsRef<Path>) -> Result<Vec<String>> {
let parameters_root = repository_root.as_ref().join("etc/parameters");
let mut locations = read_dir(parameters_root)
.await
.wrap_err("failed to read parameters directory")?;
let mut results = HashSet::new();
let mut results = Vec::new();
while let Ok(Some(entry)) = locations.next_entry().await {
if entry.path().is_dir() && !entry.path().is_symlink() {
results.insert(
results.push(
entry
.path()
.file_name()
Expand Down
8 changes: 3 additions & 5 deletions crates/repository/src/player_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ use parameters::{
use spl_network_messages::PlayerNumber;
use types::hardware::Ids;

/// Sets the player number in the parameters directory.
///
/// This function takes a head ID of a robot and a player number, and writes it to the parameters.
pub async fn set_player_number(
pub async fn configure_player_number(
head_id: &str,
player_number: PlayerNumber,
repository_root: impl AsRef<Path>,
Expand All @@ -35,5 +32,6 @@ pub async fn set_player_number(
head_id: head_id.to_string(),
},
)
.wrap_err("failed to serialize parameters directory")
.wrap_err("failed to serialize parameters directory")?;
Ok(())
}
12 changes: 9 additions & 3 deletions crates/repository/src/recording.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use serde_json::{to_value, Value};

use crate::modify_json::modify_json_inplace;

pub async fn set_recording_intervals(
pub async fn configure_recording_intervals(
recording_intervals: HashMap<String, usize>,
repository_root: impl AsRef<Path>,
) -> Result<()> {
Expand All @@ -15,11 +15,17 @@ pub async fn set_recording_intervals(
let serialized_intervals =
to_value(recording_intervals).wrap_err("failed to convert recording intervals to JSON")?;

modify_json_inplace(framework_json, |mut hardware_json: Value| {
modify_json_inplace(&framework_json, |mut hardware_json: Value| {
hardware_json["recording_intervals"] = serialized_intervals;
hardware_json
})
.await?;
.await
.wrap_err_with(|| {
format!(
"failed to configure recording intervals in {}",
framework_json.display()
)
})?;

Ok(())
}
4 changes: 3 additions & 1 deletion crates/repository/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ async fn download(version: &str, sdk_home: impl AsRef<Path>) -> Result<PathBuf>
format!("http://bighulk.hulks.dev/sdk/{installer_name}"),
format!("https://github.com/HULKs/meta-nao/releases/download/{version}/{installer_name}"),
];
download_with_fallback(urls, &download_path, CONNECT_TIMEOUT).await?;
download_with_fallback(urls, &download_path, CONNECT_TIMEOUT)
.await
.wrap_err("failed to download SDK")?;

set_permissions(&download_path, Permissions::from_mode(0o755))
.await
Expand Down
4 changes: 2 additions & 2 deletions crates/repository/src/team.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ pub struct Nao {
pub head_id: String,
}

pub async fn get_team_configuration(repository_root: impl AsRef<Path>) -> Result<Team> {
pub async fn read_team_configuration(repository_root: impl AsRef<Path>) -> Result<Team> {
let team_toml = repository_root.as_ref().join("etc/parameters/team.toml");

let content = read_to_string(&team_toml)
.await
.wrap_err_with(|| format!("failed to open {}", team_toml.display()))?;
.wrap_err_with(|| format!("failed to read {}", team_toml.display()))?;

let team = toml::from_str(&content).wrap_err("failed to parse team.toml")?;
Ok(team)
Expand Down
4 changes: 2 additions & 2 deletions tools/pepsi/src/aliveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use aliveness::{
AlivenessError, AlivenessState, Battery, JointsArray,
};
use argument_parsers::NaoAddress;
use repository::configuration::get_os_version;
use repository::configuration::read_os_version;

#[derive(Args)]
pub struct Arguments {
Expand Down Expand Up @@ -52,7 +52,7 @@ pub async fn aliveness(
print_verbose(&states);
} else {
let expected_os_version = match repository_root {
Ok(repository_root) => match get_os_version(repository_root).await {
Ok(repository_root) => match read_os_version(repository_root).await {
Ok(version) => Some(version),
Err(error) => {
error!("{error:#?}");
Expand Down
Loading

0 comments on commit f0d5321

Please sign in to comment.