Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library update #60

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"

[dependencies]
tokio = {version = "1.37.0", features=["full"]}
idf-im-lib = { git = "https://github.com/espressif/idf-im-lib.git", tag="v0.1.2" }
idf-im-lib = { git = "https://github.com/espressif/idf-im-lib.git", tag="v0.1.3" }
clap = {version = "4.5", features = ["cargo", "derive", "color"]}
crossterm = "0.27.0"
dialoguer = { git = "https://github.com/Hahihula/dialoguer.git", branch = "folder-select", features = ["folder-select"] }
Expand Down
6 changes: 0 additions & 6 deletions src/wizard/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,6 @@ pub fn create_progress_bar() -> ProgressBar {
pb
}

pub fn update_progress_bar(pb: &ProgressBar, stats: &git2::Progress) {
let current_progress =
((stats.received_objects() as f64) / (stats.total_objects() as f64) * 100.0) as u64;
pb.set_position(current_progress);
}

pub fn update_progress_bar_number(pb: &ProgressBar, value: u64) {
pb.set_position(value);
}
261 changes: 39 additions & 222 deletions src/wizard/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use dialoguer::FolderSelect;
use idf_im_lib::idf_tools::ToolsFile;
use idf_im_lib::settings::Settings;
use idf_im_lib::ProgressMessage;
use idf_im_lib::{DownloadProgress, ProgressMessage};
use indicatif::{ProgressBar, ProgressState, ProgressStyle};
use log::{debug, error, info, trace, warn};
use log::{debug, error, info, warn};
use rust_i18n::t;
use std::sync::mpsc;
use std::thread;
Expand All @@ -22,67 +22,12 @@ const DEFAULT_IDF_TOOLS_PY_LOCATION: &str = "./tools/idf_tools.py";

pub mod helpers;
use helpers::{
create_progress_bar, create_theme, generic_confirm, generic_input, update_progress_bar,
update_progress_bar_number,
create_progress_bar, create_theme, generic_confirm, generic_input, update_progress_bar_number,
};

mod prompts;
use prompts::*;

fn get_tools_export_paths(
// TODO: move to library
tools_file: ToolsFile,
selected_chip: Vec<String>,
tools_install_path: &str,
) -> Vec<String> {
let bin_dirs = find_bin_directories(Path::new(tools_install_path));
debug!("Bin directories: {:?}", bin_dirs);

let list = idf_im_lib::idf_tools::filter_tools_by_target(tools_file.tools, &selected_chip);
// debug!("Creating export paths for: {:?}", list);
let mut paths = vec![];
for tool in &list {
tool.export_paths.iter().for_each(|path| {
let mut p = PathBuf::new();
p.push(tools_install_path);
for level in path {
p.push(level);
}
paths.push(p.to_str().unwrap().to_string());
});
}
for bin_dir in bin_dirs {
let str_p = bin_dir.to_str().unwrap().to_string();
if paths.contains(&str_p) {
trace!("Skipping duplicate export path: {}", str_p);
} else {
trace!("Adding export path: {}", str_p);
paths.push(str_p);
}
}
debug!("Export paths: {:?}", paths);
paths
}

fn find_bin_directories(path: &Path) -> Vec<PathBuf> {
let mut result = Vec::new();

if let Ok(entries) = fs::read_dir(path) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
if path.file_name().and_then(|n| n.to_str()) == Some("bin") {
result.push(path.clone());
} else {
result.extend(find_bin_directories(&path));
}
}
}
}

result
}

async fn download_tools(
tools_file: ToolsFile,
selected_chip: Vec<String>,
Expand Down Expand Up @@ -132,18 +77,20 @@ async fn download_tools(
idf_im_lib::idf_tools::get_download_link_by_platform(list, &platform),
// Some("https://dl.espressif.com/github_assets"), // this switches mirror, should be parametrized
mirror,
);
)
.into_iter()
.collect::<Vec<_>>();
let mut downloaded_tools: Vec<String> = vec![];
for (tool_name, download_link) in download_links.iter() {
info!("{}: {}", t!("wizard.tool_download.progress"), tool_name);

let (progress_tx, progress_rx) = mpsc::channel();

let progress_bar = ProgressBar::new(download_link.size);
progress_bar.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})").unwrap()
.with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap())
.progress_chars("#>-"));

let update_progress = |amount_downloaded: u64, _total_size: u64| {
progress_bar.set_position(amount_downloaded);
};
debug!("Download link: {}", download_link.url);
debug!("destination: {}", destination_path);

Expand All @@ -165,10 +112,30 @@ async fn download_tools(
debug!("{}", t!("wizard.tool_file.missing"));
}
}
let tn = tool_name.clone();
let pb = progress_bar.clone();
let progress_handle = {
thread::spawn(move || {
while let Ok(progress_msg) = progress_rx.recv() {
match progress_msg {
DownloadProgress::Progress(current, total) => {
let percentage = (current * 100 / total) as u64;
pb.set_position(percentage);
}
DownloadProgress::Complete => {
pb.finish();
break;
}
DownloadProgress::Error(err) => {
log::error!("Error downloading {}: {}", tn, err);
break;
}
}
}
})
};

match idf_im_lib::download_file(&download_link.url, destination_path, &update_progress)
.await
{
match idf_im_lib::download_file(&download_link.url, destination_path, progress_tx).await {
Ok(_) => {
downloaded_tools.push(filename.to_string());
progress_bar.finish();
Expand All @@ -180,6 +147,7 @@ async fn download_tools(
panic!();
}
}
progress_handle.join().unwrap();
}
downloaded_tools
}
Expand Down Expand Up @@ -420,28 +388,6 @@ async fn download_and_extract_tools(
Ok(())
}

fn setup_environment_variables(
tool_install_directory: &PathBuf,
idf_path: &PathBuf,
) -> Result<Vec<(String, String)>, String> {
let mut env_vars = vec![];

// env::set_var("IDF_TOOLS_PATH", tool_install_directory);
let instal_dir_string = tool_install_directory.to_str().unwrap().to_string();
env_vars.push(("IDF_TOOLS_PATH".to_string(), instal_dir_string));
let idf_path_string = idf_path.to_str().unwrap().to_string();
env_vars.push(("IDF_PATH".to_string(), idf_path_string));

let python_env_path_string = tool_install_directory
.join("python")
.to_str()
.unwrap()
.to_string();
env_vars.push(("IDF_PYTHON_ENV_PATH".to_string(), python_env_path_string));

Ok(env_vars)
}

fn get_and_validate_idf_tools_path(
config: &mut Settings,
idf_path: &PathBuf,
Expand All @@ -460,7 +406,7 @@ fn get_and_validate_idf_tools_path(
idf_tools_path.push(&name);
config.idf_tools_path = Some(name);
} else {
idf_tools_path.push(DEFAULT_IDF_TOOLS_PY_LOCATION);
idf_tools_path.push(DEFAULT_IDF_TOOLS_PY_LOCATION); // TODO: defaults are in lib now
config.idf_tools_path = Some(DEFAULT_IDF_TOOLS_PY_LOCATION.to_string());
}

Expand All @@ -484,132 +430,6 @@ fn get_and_validate_idf_tools_path(
Ok(idf_tools_path)
}

fn run_idf_tools_py(
idf_tools_path: &str,
environment_variables: &Vec<(String, String)>,
) -> Result<String, String> {
let escaped_path = if std::env::consts::OS == "windows" {
idf_im_lib::replace_unescaped_spaces_win(&idf_tools_path)
} else {
idf_im_lib::replace_unescaped_spaces_posix(&idf_tools_path)
};
run_install_script(&escaped_path, environment_variables)?;
run_install_python_env_script(&escaped_path, environment_variables)
}

fn run_install_script(
idf_tools_path: &str,
environment_variables: &Vec<(String, String)>,
) -> Result<String, String> {
let output = idf_im_lib::python_utils::run_python_script_from_file(
idf_tools_path,
Some("install"),
None,
Some(environment_variables),
);

trace!("idf_tools.py install output:\n{:?}", output);

output
}

fn run_install_python_env_script(
idf_tools_path: &str,
environment_variables: &Vec<(String, String)>,
) -> Result<String, String> {
let output = idf_im_lib::python_utils::run_python_script_from_file(
idf_tools_path,
Some("install-python-env"),
None,
Some(environment_variables),
);

trace!("idf_tools.py install-python-env output:\n{:?}", output);

output
}

fn single_version_post_install(
version_instalation_path: &str,
idf_path: &str,
idf_version: &str,
tool_install_directory: &str,
export_paths: Vec<String>,
env_vars: Vec<(String, String)>, //probably dupliocate of idf_path and IDF_python_env_path
) {
match std::env::consts::OS {
"windows" => {
println!("{}", t!("wizard.windows.succes_message"));
// Creating desktop shortcut
if let Err(err) = idf_im_lib::create_desktop_shortcut(
version_instalation_path,
idf_path,
&idf_version,
tool_install_directory,
export_paths,
) {
error!(
"{} {:?}",
t!("wizard.after_install.desktop_shortcut.failed"),
err.to_string()
)
} else {
info!("{}", t!("wizard.after_install.desktop_shortcut.created"))
}
}
_ => {
let install_folder = PathBuf::from(version_instalation_path);
let install_path = install_folder.parent().unwrap().to_str().unwrap();
let _ = idf_im_lib::create_activation_shell_script(
// todo: handle error
install_path,
idf_path,
tool_install_directory,
&idf_version,
export_paths,
);

// let exports = env_vars
// .into_iter()
// .map(|(k, v)| format!("export {}=\"{}\"; ", k, v))
// .collect::<Vec<String>>();
// let exp_strig = format!(
// "{}export PATH=\"$PATH:{:?}\"; ",
// exports.join(""),
// export_paths.join(":")
// );
// match generic_confirm("wizard.after_install.add_to_path.prompt") {
// Ok(true) => match add_to_shell_rc(&exp_strig) {
// Ok(_) => println!("{}", t!("wizard.posix.succes_message")),
// Err(err) => panic!("{:?}", err.to_string()),
// },
// Ok(false) => println!(
// "{}:\r\n\r\n{}\r\n\r\n",
// t!("wizard.posix.succes_message"),
// exp_strig
// ),
// Err(err) => panic!("{:?}", err.to_string()),
// }
}
}
}

fn expand_tilde(path: &Path) -> PathBuf {
if path.starts_with("~") {
if let Some(home_dir) = dirs::home_dir() {
if path.to_str().unwrap() == "~" {
home_dir
} else {
home_dir.join(path.strip_prefix("~").unwrap())
}
} else {
path.to_path_buf()
}
} else {
path.to_path_buf()
}
}

pub async fn run_wizzard_run(mut config: Settings) -> Result<(), String> {
debug!("Config entering wizard: {:?}", config);

Expand Down Expand Up @@ -638,7 +458,7 @@ pub async fn run_wizzard_run(mut config: Settings) -> Result<(), String> {

for idf_version in config.idf_versions.clone().unwrap() {
let mut version_instalation_path = config.path.clone().unwrap();
version_instalation_path = expand_tilde(version_instalation_path.as_path());
version_instalation_path = idf_im_lib::expand_tilde(version_instalation_path.as_path());
version_instalation_path.push(&idf_version);
let mut idf_path = version_instalation_path.clone();
idf_path.push("esp-idf");
Expand Down Expand Up @@ -709,13 +529,13 @@ pub async fn run_wizzard_run(mut config: Settings) -> Result<(), String> {
)
.await?;

let env_vars = setup_environment_variables(&tool_install_directory, &idf_path)?;
let env_vars = idf_im_lib::setup_environment_variables(&tool_install_directory, &idf_path)?;

let idf_tools_path = get_and_validate_idf_tools_path(&mut config, &idf_path)?;

run_idf_tools_py(idf_tools_path.to_str().unwrap(), &env_vars)?;
idf_im_lib::python_utils::run_idf_tools_py(idf_tools_path.to_str().unwrap(), &env_vars)?;

let export_paths = get_tools_export_paths(
let export_paths = idf_im_lib::idf_tools::get_tools_export_paths(
tools,
config.target.clone().unwrap().clone(),
tool_install_directory.join("tools").to_str().unwrap(),
Expand All @@ -730,15 +550,12 @@ pub async fn run_wizzard_run(mut config: Settings) -> Result<(), String> {
})
.collect();

println!("### {}", idf_path.to_str().unwrap());

single_version_post_install(
idf_im_lib::single_version_post_install(
&version_instalation_path.to_str().unwrap(),
&idf_path.to_str().unwrap(),
&idf_version,
&tool_install_directory.to_str().unwrap(),
export_paths,
env_vars,
)
}
save_config_if_desired(&config)?;
Expand Down
Loading