Skip to content
Open
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 .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ jobs:
perl -MText::Template -e "print 'Text::Template loaded successfully\n'"
perl -MParams::Check -e "print 'Params::Check loaded successfully\n'"
perl -MIPC::Cmd -e "print 'IPC::Cmd loaded successfully\n'"
$perl_lib_path = "C:\hostedtoolcache\windows\perl\5.38.4-thr\x64\site\lib"
$perl_lib_path = "C:\hostedtoolcache\windows\perl\5.38.5-thr\x64\site\lib"
echo "PERL5LIB=$perl_lib_path" >> $env:GITHUB_ENV

- name: Cache cargo
Expand All @@ -211,7 +211,7 @@ jobs:
OPENSSL_LIB_DIR: 'C:\vcpkg\installed\x64-windows-static-md\lib'
OPENSSL_INCLUDE_DIR: 'C:\vcpkg\installed\x64-windows-static-md\include'
OPENSSL_STATIC: "1"
PERL: 'C:\\hostedtoolcache\\windows\\perl\\5.38.4-thr\\x64\\bin\\perl.exe'
PERL: 'C:\\hostedtoolcache\\windows\\perl\\5.38.5-thr\\x64\\bin\\perl.exe'
run: |
cd src-tauri
cargo build --release --no-default-features --features cli ${{ matrix.target && format('--target {0}', matrix.target) || '' }}
Expand Down
17 changes: 14 additions & 3 deletions docs/src/cli_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ These options can be used with any command:
| `remove` | Remove a specific ESP-IDF version |
| `purge` | Purge all ESP-IDF installations |
| `import` | Import existing ESP-IDF installation using tools_set_config.json |
| `discover` | Discover available ESP-IDF versions (not implemented yet) |
| `discover` | Discover available ESP-IDF versions |
| `gui` | Run the ESP-IDF Installer GUI with arguments passed through command line |

## Command Details

Expand Down Expand Up @@ -139,10 +140,20 @@ If `PATH` is not provided, the command will inform you that no config file was s
Discover available ESP-IDF versions (not implemented yet).

```bash
eim discover
eim discover [PATH]
```

This command is planned to discover ESP-IDF installations on your system but is not yet implemented.
This command searches for previously installed ESP-IDF versions on your system. If PATH is not provided, the command will search from the root of the filesystem. For any found versions where automatic import is possible, they will be imported into EIM's management. For other found versions that cannot be automatically imported, the command will suggest the appropriate `eim install` command to allow the user to manually reinstall them.

### Fix Command

Fix the ESP-IDF installation by reinstalling the tools and dependencies

```bash
eim fix [PATH]
```

If no `PATH` is provided, the user will be presented with selection of all known IDF installation to select from.

## Examples

Expand Down
13 changes: 11 additions & 2 deletions src-tauri/src/cli/cli_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,11 @@ pub enum Commands {
version: Option<String>,
},

/// Discover available ESP-IDF versions (not implemented yet)
Discover,
/// Discover available ESP-IDF versions
Discover {
#[arg(help = "Discover available ESP-IDF versions and imports them")]
path: Option<String>,
},

/// Remove specific ESP-IDF version
Remove {
Expand Down Expand Up @@ -96,6 +99,12 @@ pub enum Commands {
/// Run the ESP-IDF Installer GUI with arguments passed through command line
#[cfg(feature = "gui")]
Gui(InstallArgs),

/// Fix the ESP-IDF installation by reinstalling the tools and dependencies
Fix {
#[arg(help = "Fix IDF on a specific path")]
path: Option<String>,
},
}

#[derive(Parser, Debug, Clone, Default)]
Expand Down
226 changes: 217 additions & 9 deletions src-tauri/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::path::Path;
use std::path::PathBuf;

use anyhow::Context;
Expand All @@ -9,7 +10,12 @@ use config::ConfigError;
use helpers::generic_input;
use helpers::generic_select;
use idf_im_lib::get_log_directory;
use idf_im_lib::idf_config::IdfConfig;
use idf_im_lib::settings::Settings;
use idf_im_lib::utils::is_valid_idf_directory;
use idf_im_lib::utils::find_by_name_and_extension;
use idf_im_lib::utils::parse_esp_idf_json;
use idf_im_lib::utils::EspIdfConfig;
use idf_im_lib::version_manager::remove_single_idf_version;
use idf_im_lib::version_manager::select_idf_version;
use log::debug;
Expand Down Expand Up @@ -315,13 +321,128 @@ pub async fn run_cli(cli: Cli) -> anyhow::Result<()> {
}
}
}
Commands::Discover => {
// TODO:Implement version discovery
unimplemented!("Version discovery not implemented yet");
println!("Discovering available versions... (This can take couple of minutes)");
let idf_dirs = idf_im_lib::version_manager::find_esp_idf_folders("/");
Commands::Discover {path } => {
info!("Discovering available versions... (This can take couple of minutes)");
let path = path.unwrap_or_else(|| {
let default_path = match std::env::consts::OS {
"windows" => {
"C:\\".to_string()
}
_ => {
"/".to_string()
}
};


debug!("No path provided, using default: {}", default_path);
default_path
});
// first parse existing esp_idf.json (using parse_esp_idf_json) || previous VSCode installations
info!("Searching for esp_idf.json files...");
let search_patch = Path::new(&path);
let esp_idf_json_path = find_by_name_and_extension(
search_patch,
"esp_idf",
"json",
);
if esp_idf_json_path.is_empty() {
info!("No esp_idf.json found");
} else {
info!("Found {} esp_idf.json files:", esp_idf_json_path.len());
}
for path in esp_idf_json_path {
info!("- {} ", &path);
match std::env::consts::OS {
"windows" => {
// On Windows, we need to fix every installation from VSCode
info!("Parsing esp_idf.json at: {}", path);
let idf_json_path = Path::new(&path);
let json_str = std::fs::read_to_string(idf_json_path).unwrap();
let config: EspIdfConfig = match serde_json::from_str(&json_str) {
Ok(config) => config,
Err(e) => {
error!("Failed to parse config file: {}", e);
continue;
}
};
for (_key, value) in config.idf_installed {
let idf_path = value.path;
fix_command(Some(idf_path)).await?;
}
}
_ => {
match parse_esp_idf_json(&path) {
Ok(_) => {
info!("Parsed config: {:?}", path);
}
Err(err) => {
info!("Failed to parse esp_idf.json: {}", err);
}
}
}
}
}
// second try to find tool_set_config.json (using parse_tool_set_config) || previous Eclipse installations
info!("Searching for tool_set_config.json files...");
let tool_set_config_path = find_by_name_and_extension(
search_patch,
"tool_set_config",
"json",
);
if tool_set_config_path.is_empty() {
info!("No tool_set_config.json found");
} else {
info!("Found {} tool_set_config.json files:", tool_set_config_path.len());
}
for path in tool_set_config_path {
info!("- {} ", &path);
match idf_im_lib::utils::parse_tool_set_config(&path) {
Ok(_) => {
info!("Parsed config: {:?}", path);
}
Err(err) => {
info!("Failed to parse tool_set_config.json: {}", err);
}
}
}
// third try to find IDF directories (using find_esp_idf_folders) || previous instalation from cli
info!("Searching for any other IDF directories...");
let idf_dirs = idf_im_lib::version_manager::find_esp_idf_folders(&path);
if idf_dirs.is_empty() {
info!("No IDF directories found");
} else {
info!("Found {} IDF directories:", idf_dirs.len());
}
let config = match idf_im_lib::version_manager::get_esp_ide_config() {
Ok(config) => {
if config.idf_installed.is_empty() {
debug!(
"No versions found. Every discovered version can be imported."
);
}
config
}
Err(_err) => {
debug!("No ide config found. New will be created.");
IdfConfig::default()
}
};
let mut paths_to_add = vec![];
for dir in idf_dirs {
println!("Found IDF directory: {}", dir);
info!("- {} ", &dir);
if config.clone().is_path_in_config(dir.clone()) {
info!("Already present!");
} else {
info!("Can be added...");
paths_to_add.push(dir);
}
}
if paths_to_add.is_empty() {
info!("No new IDF directories found to add.");
return Ok(());
} else {
info!("Found {} new IDF directories available to add:", paths_to_add.len());
info!("You can add them using `eim install` command with the `--path` option.");
}
Ok(())
}
Expand Down Expand Up @@ -353,7 +474,7 @@ pub async fn run_cli(cli: Cli) -> anyhow::Result<()> {
println!("Available versions:");
let options = versions.iter().map(|v| v.name.clone()).collect();
match generic_select("Which version do you want to remove?", &options) {
Ok(selected) => match remove_single_idf_version(&selected) {
Ok(selected) => match remove_single_idf_version(&selected, false) {
Ok(_) => {
info!("Removed version: {}", selected);
Ok(())
Expand All @@ -367,7 +488,7 @@ pub async fn run_cli(cli: Cli) -> anyhow::Result<()> {
Err(err) => Err(anyhow::anyhow!(err)),
}
} else {
match remove_single_idf_version(&version.clone().unwrap()) {
match remove_single_idf_version(&version.clone().unwrap(), false) {
Ok(_) => {
println!("Removed version: {}", version.clone().unwrap());
Ok(())
Expand All @@ -388,7 +509,7 @@ pub async fn run_cli(cli: Cli) -> anyhow::Result<()> {
let mut failed = false;
for version in versions {
info!("Removing version: {}", version.name);
match remove_single_idf_version(&version.name) {
match remove_single_idf_version(&version.name, false) {
Ok(_) => {
info!("Removed version: {}", version.name);
}
Expand Down Expand Up @@ -432,6 +553,9 @@ pub async fn run_cli(cli: Cli) -> anyhow::Result<()> {
Err(err) => Err(anyhow::anyhow!(err)),
}
}
Commands::Fix { path } => {
fix_command(path).await
}
#[cfg(feature = "gui")]
Commands::Gui(_install_args) => {
#[cfg(not(feature = "gui"))]
Expand All @@ -441,3 +565,87 @@ pub async fn run_cli(cli: Cli) -> anyhow::Result<()> {
}
}
}

async fn fix_command(path:Option<String>) -> anyhow::Result<()> {
let path_to_fix = if path.is_some() {
// If a path is provided, fix the IDF installation at that path
let path = path.unwrap();
if is_valid_idf_directory(&path) {
PathBuf::from(path)
} else {
error!("Invalid IDF directory: {}", path);
return Err(anyhow::anyhow!("Invalid IDF directory: {}", path));
}
} else {
match idf_im_lib::version_manager::list_installed_versions() {
Ok(versions) => {
if versions.is_empty() {
warn!("No versions installed");
return Ok(());
} else {
let options = versions.iter().map(|v| v.path.clone()).collect();
let version_path = match helpers::generic_select(
"Which version do you want to fix?",
&options,
) {
Ok(selected) => selected,
Err(err) => {
error!("Error: {}", err);
return Err(anyhow::anyhow!(err));
}
};
PathBuf::from(version_path)
}
}
Err(err) => {
debug!("Error: {}", err);
return Err(anyhow::anyhow!("No versions found. Use eim install to install a new ESP-IDF version."));
}
}
};
info!("Fixing IDF installation at path: {}", path_to_fix.display());
// The fix logic is just instalation with use of existing repository
let mut version_name = None;
match idf_im_lib::version_manager::list_installed_versions() {
Ok(versions) => {
for v in versions {
if v.path == path_to_fix.to_str().unwrap() {
info!("Found existing IDF version: {}", v.name);
// Remove the existing activation script and eim_idf.json entry
match remove_single_idf_version(&v.name, true) {
Ok(_) => {
info!("Removed existing IDF version from eim_idf.json: {}", v.name);
version_name = Some(v.name.clone());
}
Err(err) => {
error!("Failed to remove existing IDF version {}: {}", v.name, err);
}
}
}
}
}
Err(_) => {
info!("Failed to list installed versions. Using default naming.");
}
}

let mut settings = Settings::default();
settings.path = Some(path_to_fix.clone());
settings.non_interactive = Some(true);
settings.version_name = version_name;
settings.install_all_prerequisites = Some(true);
settings.config_file_save_path = None; // Do not save config file in fix mode
let result = wizard::run_wizzard_run(settings).await;
match result {
Ok(r) => {
info!("Fix result: {:?}", r);
info!("Successfully fixed IDF installation at {}", path_to_fix.display());
}
Err(err) => {
error!("Failed to fix IDF installation: {}", err);
return Err(anyhow::anyhow!(err));
}
}
info!("Now you can start using IDF tools");
Ok(())
}
31 changes: 0 additions & 31 deletions src-tauri/src/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,37 +169,6 @@ impl ToolSetup {
}
}

// async fn install_single_version(
// app_handle: AppHandle,
// settings: &Settings,
// version: String,
// ) -> Result<(), Box<dyn std::error::Error>> {
// info!("Installing IDF version: {}", version);

// let version_path = prepare_installation_directories(app_handle.clone(), settings, &version)?;
// let idf_path = version_path.clone().join("esp-idf");
// download_idf(&app_handle, settings, &version, &idf_path).await?;
// let export_vars = setup_tools(&app_handle, settings, &idf_path, &version).await?;
// let tools_install_path = version_path.clone().join(
// settings
// .tool_install_folder_name
// .clone()
// .unwrap_or_default(),
// );
// let idf_python_env_path = tools_install_path.clone().join("python").join(&version).join("venv");
// let activation_script_path = settings.esp_idf_json_path.clone().unwrap_or_default();
// idf_im_lib::single_version_post_install(
// &activation_script_path,
// idf_path.to_str().unwrap(),
// &version,
// tools_install_path.to_str().unwrap(),
// export_vars,
// Some(idf_python_env_path.to_str().unwrap()),
// );

// Ok(())
// }

// Helper function to check if a process is running on Windows
#[cfg(target_os = "windows")]
fn is_process_running(pid: u32) -> bool {
Expand Down
Loading
Loading