diff --git a/crates/repository/src/cargo.rs b/crates/repository/src/cargo.rs index 3be6d6cf20..36e15ef34c 100644 --- a/crates/repository/src/cargo.rs +++ b/crates/repository/src/cargo.rs @@ -1,19 +1,17 @@ use core::fmt; use std::{ - env::current_dir, ffi::{OsStr, OsString}, fmt::{Display, Formatter}, path::Path, }; use color_eyre::{ - eyre::{bail, Context, ContextCompat}, + eyre::{bail, Context}, Result, }; -use pathdiff::diff_paths; use tokio::process::Command; -use crate::{data_home::get_data_home, sdk::download_and_install, Repository}; +use crate::{sdk::download_and_install, Repository}; #[derive(Debug, Clone)] pub enum Environment { @@ -64,14 +62,18 @@ impl Cargo { if let Environment::Sdk { version } = &self.environment { match self.host { Host::Local => { - let data_home = get_data_home().wrap_err("failed to get data home")?; + let data_home = repository + .resolve_data_home() + .await + .wrap_err("failed to resolve data home")?; download_and_install(version, data_home) .await .wrap_err("failed to download and install SDK")?; } Host::Remote => { - let mut command = Command::new(repository.root.join("scripts/remoteWorkspace")); + let mut command = + Command::new(repository.root.join("scripts/remote_workspace")); let status = command .arg("pepsi") @@ -110,11 +112,7 @@ impl Cargo { ) -> Result { let arguments = self.arguments.join(OsStr::new(" ")); - let relative_pwd = diff_paths( - current_dir().wrap_err("failed to get current directory")?, - &repository.root, - ) - .wrap_err("failed to express current directory relative to repository root")?; + let data_home_script = repository.data_home_script()?; let command_string = match self.environment { Environment::Native => { @@ -123,26 +121,22 @@ impl Cargo { command } Environment::Sdk { version } => { - let data_home = get_data_home().wrap_err("failed to get data home")?; - let environment_file = &data_home.join(format!( - "sdk/{version}/environment-setup-corei7-64-aldebaran-linux" - )); - let sdk_environment_setup = environment_file - .to_str() - .wrap_err("failed to convert sdk environment setup path to string")?; - let mut command = OsString::from(format!(". {sdk_environment_setup} && cargo ")); + let environment_file = format!( + "$({data_home_script})/sdk/{version}/environment-setup-corei7-64-aldebaran-linux", + ); + let mut command = OsString::from(format!(". {environment_file} && cargo ")); command.push(arguments); command } Environment::Docker { image } => { - let data_home = get_data_home().wrap_err("failed to get data home")?; - let cargo_home = data_home.join("container-cargo-home/"); + let cargo_home = format!("$({data_home_script})/container-cargo-home/"); // TODO: Make image generic over SDK/native by modifying entry point; source SDK not here - let pwd = Path::new("/hulk").join(&relative_pwd); + let pwd = Path::new("/hulk").join(&repository.root_to_current_dir()?); + let root = repository.current_dir_to_root()?; let mut command = OsString::from(format!("\ mkdir -p {cargo_home} && \ docker run \ - --volume={repository_root}:/hulk:z \ + --volume={root}:/hulk:z \ --volume={cargo_home}:/naosdk/sysroots/corei7-64-aldebaran-linux/home/cargo:z \ --rm \ --interactive \ @@ -153,8 +147,7 @@ impl Cargo { echo $PATH && \ cargo \ ", - repository_root=repository.root.display(), - cargo_home=cargo_home.display(), + root=root.display(), pwd=pwd.display(), )); command.push(arguments); @@ -170,12 +163,13 @@ impl Cargo { command } Host::Remote => { - let mut command = Command::new(repository.root.join("scripts/remoteWorkspace")); + let mut command = Command::new(repository.root.join("scripts/remote_workspace")); for path in compiler_artifacts { command.arg("--return-file").arg(path.as_ref()); } - command.arg("--cd").arg(Path::new("./").join(relative_pwd)); + let current_dir = repository.root_to_current_dir()?; + command.arg("--cd").arg(Path::new("./").join(current_dir)); command } }; diff --git a/crates/repository/src/data_home.rs b/crates/repository/src/data_home.rs index e05c0fef34..1782e272d0 100644 --- a/crates/repository/src/data_home.rs +++ b/crates/repository/src/data_home.rs @@ -1,17 +1,38 @@ -use std::{env, path::PathBuf}; +use std::path::PathBuf; -use color_eyre::Result; +use color_eyre::{ + eyre::{bail, Context}, + Result, +}; +use tokio::process::Command; -/// Get the data home directory. -/// -/// This function returns the directory where hulk stores its data. The directory is determined by -/// the `HULK_DATA_HOME` environment variable. If the environment variable is not set, the -/// user-specific data directory (set by `XDG_DATA_HOME`) is used. -pub fn get_data_home() -> Result { - if let Ok(home) = env::var("HULK_DATA_HOME") { - return Ok(PathBuf::from(home)); +use crate::Repository; + +impl Repository { + /// Get the data home directory. + /// + /// This function returns the directory where hulk stores its data. The directory is determined by + /// the `HULK_DATA_HOME` environment variable. If the environment variable is not set, the + /// user-specific data directory (set by `XDG_DATA_HOME`) is used. + pub async fn resolve_data_home(&self) -> Result { + let output = Command::new(self.root.join("scripts/resolve_data_home")) + .output() + .await + .wrap_err("failed to spawn resolve_data_home script")?; + + if !output.status.success() { + bail!("failed to resolve data home"); + } + + let data_home = String::from_utf8(output.stdout).wrap_err("failed to parse data home")?; + Ok(PathBuf::from(data_home)) } - let base_directories = xdg::BaseDirectories::with_prefix("hulk")?; - Ok(base_directories.get_data_home()) + pub fn data_home_script(&self) -> Result { + let root = self.current_dir_to_root()?; + Ok(format!( + "{root}/scripts/resolve_data_home", + root = root.display(), + )) + } } diff --git a/crates/repository/src/lib.rs b/crates/repository/src/lib.rs index ca78fbc098..f676cad7d2 100644 --- a/crates/repository/src/lib.rs +++ b/crates/repository/src/lib.rs @@ -15,6 +15,7 @@ pub mod image; pub mod inspect_version; pub mod location; pub mod modify_json; +pub mod paths; pub mod player_number; pub mod recording; pub mod sdk; diff --git a/crates/repository/src/paths.rs b/crates/repository/src/paths.rs new file mode 100644 index 0000000000..c8999559e3 --- /dev/null +++ b/crates/repository/src/paths.rs @@ -0,0 +1,25 @@ +use std::{ + env::current_dir, + path::{Path, PathBuf}, +}; + +use color_eyre::eyre::{Context, ContextCompat, Result}; +use pathdiff::diff_paths; + +use crate::Repository; + +impl Repository { + pub fn root_to_current_dir(&self) -> Result { + let current_dir = current_dir().wrap_err("failed to get current directory")?; + let path = diff_paths(¤t_dir, &self.root) + .wrap_err("failed to express current directory relative to repository root")?; + Ok(Path::new("./").join(path)) + } + + pub fn current_dir_to_root(&self) -> Result { + let current_dir = current_dir().wrap_err("failed to get current directory")?; + let path = diff_paths(&self.root, ¤t_dir) + .wrap_err("failed to express repository root relative to current directory")?; + Ok(Path::new("./").join(path)) + } +} diff --git a/scripts/hardwareStatus b/scripts/hardwareStatus deleted file mode 100755 index ad28ac7727..0000000000 --- a/scripts/hardwareStatus +++ /dev/null @@ -1,316 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import argparse -import logging -import os -import sys -import re -from subprocess import Popen, PIPE -from tabulate import tabulate -from time import strftime - -logger = logging.getLogger("NaoStatus") -logger.setLevel(logging.INFO) -console_handler = logging.StreamHandler() -console_handler.setLevel(logging.INFO) -formatter = logging.Formatter('[%(levelname)s]%(name)s: %(message)s') -console_handler.setFormatter(formatter) -logger.addHandler(console_handler) - -nao_path = os.path.dirname(os.path.realpath(__file__)) + "/.." -wiki_path = nao_path + "/.wiki" -nao_numbers = set() - -# matches the trimmed cell contents of a two column table where the second cell must be a date -# example: -# | Some text | 1337-42-69 | -row_match_regex = re.compile( - r"(?:\|\s*)([^|]*?)(?:\s*\|\s*)(\d{4}-\d{2}-\d{2})(?:\s*\|)") - - -def check_wiki(): - """ - Checks if there is a local copy of the wiki, - if not clones it. If there is one it performs a git pull - """ - if os.path.isdir(wiki_path): - logger.info("Local wiki found.") - else: - logger.info("Couldn't find local wiki, cloning...") - os.chdir(nao_path) - os.system("git clone --depth 1 git@github.com:hulks/nao.wiki.git .wiki") - - # create the current team - global nao_numbers - for file_path in os.listdir(wiki_path): - if "tuhhnao" in file_path: - nao_numbers.add(re.findall( - r"tuhhnao(\d\d)_(?:head|body).md", file_path)[0]) - nao_numbers = sorted(list(nao_numbers)) - - -def get_head_or_body(nao_number, head_or_body): - """ - Reads a NaoStatus wiki entry and returns - head, body or both parts - """ - if head_or_body == "both": - with open(wiki_path + "/tuhhnao{}_head.md".format(nao_number), 'r') as file: - head_content = file.read() - head_matches = row_match_regex.findall(head_content) - if len(head_matches) == 0: - head_matches = [("Empty status", "Empty date")] - with open(wiki_path + "/tuhhnao{}_body.md".format(nao_number), 'r') as file: - body_content = file.read() - body_matches = row_match_regex.findall(body_content) - if len(body_matches) == 0: - body_matches = [("Empty status", "Empty date")] - - head_preheader = "\n".join(head_content.splitlines()[:2]) + "\n" - body_preheader = "\n".join(body_content.splitlines()[:2]) + "\n" - - return head_preheader, head_matches, body_preheader, body_matches - - else: - with open(wiki_path + "/tuhhnao{}_{}.md".format(nao_number, head_or_body), 'r') as file: - content = file.read() - matches = row_match_regex.findall(content) - if len(matches) == 0: - matches = [("Empty status", "Empty date")] - - preheader = "\n".join(content.splitlines()[:2]) + "\n" - - return preheader, matches - - -def main_add(args): - """ - Adds a line to the wiki entry for the tuhhnao{nao_number} - """ - if not args.no_sync: - rebase(args) - - if args.message is None: - logger.error("The add command needs a message. Specify it with -m") - sys.exit(1) - - # case asking for head and body - if args.head_or_body == "both": - # add the message to both head and body - head_preheader, head_lines, body_preheader, body_lines = get_head_or_body( - args.nao_number, args.head_or_body) - head_lines.append((args.message, args.date)) - body_lines.append((args.message, args.date)) - - # pretty format the table - head_content = head_preheader + \ - tabulate(head_lines, ["Status", "Date"], tablefmt="pipe") - body_content = body_preheader + \ - tabulate(body_lines, ["Status", "Date"], tablefmt="pipe") - - # write to files - with open(wiki_path + "/tuhhnao{}_head.md".format(args.nao_number), 'w') as file: - file.write(head_content) - with open(wiki_path + "/tuhhnao{}_body.md".format(args.nao_number), 'w') as file: - file.write(body_content) - - logger.info("Saved message: \"{}\" for nao {} head and body.".format( - args.message, args.nao_number)) - - else: - # add the message - preheader, lines = get_head_or_body(args.nao_number, args.head_or_body) - lines.append((args.message, args.date)) - - # pretty format the table - content = preheader + \ - tabulate(lines, ["Status", "Date"], tablefmt="pipe") - - # write to file - with open(wiki_path + "/tuhhnao{}_{}.md".format(args.nao_number, args.head_or_body), 'w') as file: - file.write(content) - - logger.info("Saved message: \"{}\" for nao {} {}.".format( - args.message, args.nao_number, args.head_or_body)) - - # commit and sync - commit("add", args) - - if not args.no_sync: - push(args) - - -def main_modify(args): - """ - Modifies last message in wiki with new message - """ - - if not args.no_sync: - rebase(args) - - if args.message is None: - logger.error("The modify command needs a message. Specify it with -m.") - sys.exit(1) - - # change the last line - preheader, lines = get_head_or_body(args.nao_number, args.head_or_body) - lines[-1] = (args.message, args.date) - - # pretty format the table - content = preheader + tabulate(lines, ["Status", "Date"], tablefmt="pipe") - - # write to file - with open(wiki_path + "/tuhhnao{}_{}.md".format(args.nao_number, args.head_or_body), 'w') as file: - file.write(content) - - logger.info("Modified last status message to: \"{}\" for nao {} {}.".format( - args.message, args.nao_number, args.head_or_body)) - - # commit and sync - commit("modify", args) - - if not args.no_sync: - push(args) - - -def main_status(args): - """ - Prints what is currently saved in tuhhnao{nao_number}'s status entry - """ - if args.nao_number == "team": - team_message_lines = [] - for nao_number in nao_numbers: - team_message_lines.append( - "+++++++++++ Nao {} +++++++++++".format(nao_number)) - _, head_lines, _, body_lines = get_head_or_body( - nao_number, args.head_or_body) - team_message_lines.append( - "Head - {}, {}".format(head_lines[-1][0], head_lines[-1][1])) - team_message_lines.append( - "Body - {}, {}".format(body_lines[-1][0], body_lines[-1][1])) - team_message_lines.append("") - print("\n".join(team_message_lines)) - - else: - if args.head_or_body == "both": - with open(wiki_path + "/tuhhnao{}_head.md".format(args.nao_number), 'r') as file: - print(file.read()) - print("") - with open(wiki_path + "/tuhhnao{}_body.md".format(args.nao_number), 'r') as file: - print(file.read()) - else: - with open(wiki_path + "/tuhhnao{}_{}.md".format(args.nao_number, args.head_or_body), 'r') as file: - print(file.read()) - - -def rebase(args): - """ - Rebases onto the master - """ - os.chdir(wiki_path) - os.system("git pull origin master --rebase") - - -def commit(command, args): - """ - Commits the current changes - """ - os.chdir(wiki_path) - os.system("git commit -am \"naoStatus.py {} nao:{}, message:{}, part:{}\"".format( - command, args.nao_number, args.message, args.head_or_body)) - - -def push(args): - """ - Pushes to master - """ - os.chdir(wiki_path) - os.system("git push origin master") - - -def sync_main(args): - """ - Syncs the wiki repository - """ - rebase(args) - push(args) - - -def main(): - arg_parser = argparse.ArgumentParser(description="Nao status management tool for the hulks github wiki", - formatter_class=argparse.RawTextHelpFormatter) - subparsers = arg_parser.add_subparsers() - - # parser arguments for add command - parser_add = subparsers.add_parser( - 'add', help='Add command appends a line to the nao\'s status entry in the wiki') - parser_add.add_argument('nao_number', type=str, - help='Number of the target nao') - parser_add.add_argument("head_or_body", default="both", choices=[ - "head", "body", "both"], type=str) - parser_add.add_argument('-m', "--message", default=None, - type=str, help="The message passed to our wiki") - parser_add.add_argument('-d', "--date", default=strftime("%Y-%m-%d"), - type=str, help="The date passed to our wiki, default is today") - parser_add.add_argument('-n', '--no-sync', action='store_true', - default=False, help="Keeps the script from syncing with the wiki") - parser_add.set_defaults(func=main_add) - - # parser arguments for modify command - parser_modify = subparsers.add_parser( - 'modify', help='Modify the last line of the nao\'s status entry in the wiki') - parser_modify.add_argument( - 'nao_number', type=str, help='Number of the target nao') - parser_modify.add_argument("head_or_body", default="both", choices=[ - "head", "body", "both"], type=str) - parser_modify.add_argument( - '-m', "--message", default=None, type=str, help="The message passed to our wiki") - parser_modify.add_argument('-d', "--date", default=strftime("%Y-%m-%d"), - type=str, help="The date passed to our wiki, default is today") - parser_modify.add_argument('-n', '--no-sync', action='store_true', - default=False, help="Keeps the script from syncing with the wiki") - parser_modify.set_defaults(func=main_modify) - - # parser arguments for status command - parser_status = subparsers.add_parser( - 'show', help='Print the nao\'s latest status entry in the wiki') - parser_status.add_argument( - 'nao_number', default="team", nargs='?', type=str, help='Number of the target nao') - parser_status.add_argument("head_or_body", default="both", nargs="?", choices=[ - "head", "body", "both"], type=str) - parser_status.set_defaults(func=main_status) - - # parser arguments for the sync command - parser_sync = subparsers.add_parser( - 'sync', help='Sync the wiki with github') - parser_sync.set_defaults(func=sync_main) - - # parse all arguments - args = arg_parser.parse_args() - - # check for iso date format - if hasattr(args, "date"): - if not re.match(r'([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))', args.date): - logger.error("Date needs to be iso formatted. E.g.: 2018-09-29") - sys.exit(1) - - # check the nao number - if hasattr(args, "nao_number"): - if not args.nao_number.isdigit() and not args.nao_number == "team": - logger.error( - "Use \"team\" or a specific nao number, not: {}".format(args.nao_number)) - sys.exit(1) - - # check the wiki - check_wiki() - - # call respective main - if len(sys.argv) > 1: - args.func(args) - else: - arg_parser.print_help() - - -if __name__ == '__main__': - # parse all given arguments, this function also decides which main to call - main() diff --git a/scripts/remoteGdb b/scripts/remote_gdb similarity index 100% rename from scripts/remoteGdb rename to scripts/remote_gdb diff --git a/scripts/remoteWorkspace b/scripts/remote_workspace similarity index 99% rename from scripts/remoteWorkspace rename to scripts/remote_workspace index de25373239..a5281de9ee 100755 --- a/scripts/remoteWorkspace +++ b/scripts/remote_workspace @@ -84,11 +84,11 @@ fi ssh \ $SSH_FLAGS \ $address \ - "sh -c \" \ + "sh -c ' \ cd \"$remotePath\" \ && cd \"$path\" \ && $@ -\"" +'" if [ ${#files[@]} -gt 0 ]; then # fetch results diff --git a/scripts/resolve_data_home b/scripts/resolve_data_home new file mode 100755 index 0000000000..66de23954c --- /dev/null +++ b/scripts/resolve_data_home @@ -0,0 +1,8 @@ +#!/bin/env bash + +HOME="${HOME:-$(echo ~)}" + +DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" +HULK_DATA_HOME="${HULK_DATA_HOME:-$DATA_HOME/hulk}" + +echo -n $(realpath "$HULK_DATA_HOME") diff --git a/tools/pepsi/src/gammaray.rs b/tools/pepsi/src/gammaray.rs index 56414ca015..cea1c198c5 100644 --- a/tools/pepsi/src/gammaray.rs +++ b/tools/pepsi/src/gammaray.rs @@ -6,7 +6,7 @@ use color_eyre::{eyre::WrapErr, Result}; use argument_parsers::NaoAddress; use nao::Nao; use opn::verify_image; -use repository::{data_home::get_data_home, image::download_image, Repository}; +use repository::{image::download_image, Repository}; use crate::progress_indicator::ProgressIndicator; @@ -31,7 +31,10 @@ pub async fn gammaray(arguments: Arguments, repository: &Repository) -> Result<( .await .wrap_err("failed to get OS version")?, }; - let data_home = get_data_home()?; + let data_home = repository + .resolve_data_home() + .await + .wrap_err("failed to resolve data home")?; let image_path = match arguments.image_path { Some(image_path) => image_path, None => download_image(&version, data_home).await?, diff --git a/tools/pepsi/src/sdk.rs b/tools/pepsi/src/sdk.rs index 6d55a1da25..935edc1050 100644 --- a/tools/pepsi/src/sdk.rs +++ b/tools/pepsi/src/sdk.rs @@ -1,7 +1,7 @@ use clap::Subcommand; use color_eyre::{eyre::Context, Result}; -use repository::{data_home::get_data_home, sdk::download_and_install, Repository}; +use repository::{sdk::download_and_install, Repository}; #[derive(Subcommand)] pub enum Arguments { @@ -14,9 +14,12 @@ pub enum Arguments { } pub async fn sdk(arguments: Arguments, repository: &Repository) -> Result<()> { + let data_home = repository + .resolve_data_home() + .await + .wrap_err("failed to get data home")?; match arguments { Arguments::Install { version } => { - let data_home = get_data_home().wrap_err("failed to get data home")?; let version = match version { Some(version) => version, None => repository @@ -31,7 +34,6 @@ pub async fn sdk(arguments: Arguments, repository: &Repository) -> Result<()> { .read_sdk_version() .await .wrap_err("failed to get HULK OS version")?; - let data_home = get_data_home().wrap_err("failed to get data home")?; let path = &data_home.join(format!("sdk/{sdk_version}/")); println!("{}", path.display()); }