From 2d9c08e1e8cc4d33a4c488e2e229ece38f4f1e3b Mon Sep 17 00:00:00 2001 From: Hailey Somerville Date: Fri, 15 Sep 2023 13:51:13 +1000 Subject: [PATCH] add SourceTree enum in place of all direct git::Repository uses --- src/espidf.rs | 66 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/src/espidf.rs b/src/espidf.rs index f6c5f70..e22acc2 100644 --- a/src/espidf.rs +++ b/src/espidf.rs @@ -112,7 +112,7 @@ pub enum FromEnvError { #[error("`esp-idf` repository exists but required tools not in environment")] NotActivated { /// The esp-idf repository detected from the environment. - esp_idf_repo: git::Repository, + esp_idf_tree: SourceTree, /// The source error why detection failed. #[source] source: anyhow::Error, @@ -122,8 +122,8 @@ pub enum FromEnvError { /// Information about a esp-idf source and tools installation. #[derive(Debug)] pub struct EspIdf { - /// The esp-idf repository. - pub repository: git::Repository, + /// The esp-idf source tree. + pub tree: SourceTree, /// The binary paths of all tools concatenated with the system `PATH` env variable. pub exported_path: OsString, /// The path to the python executable to be used by the esp-idf. @@ -135,6 +135,19 @@ pub struct EspIdf { pub is_managed_espidf: bool, } +#[derive(Debug, Clone)] +pub enum SourceTree { + Git(git::Repository), +} + +impl SourceTree { + pub fn path(&self) -> &Path { + match self { + SourceTree::Git(repo) => repo.worktree(), + } + } +} + impl EspIdf { /// Try to detect an activated esp-idf environment. pub fn try_from_env() -> Result { @@ -142,12 +155,15 @@ impl EspIdf { let idf_path = env::var_os(IDF_PATH_VAR).ok_or_else(|| { FromEnvError::NoRepo(anyhow!("environment variable `{IDF_PATH_VAR}` not found")) })?; - let repo = git::Repository::open(idf_path).map_err(FromEnvError::NoRepo)?; + let tree = match git::Repository::open(idf_path) { + Ok(repo) => SourceTree::Git(repo), + Err(e) => { return Err(FromEnvError::NoRepo(e)); } + }; let path_var = env::var_os("PATH").unwrap_or_default(); let not_activated = |source: Error| -> FromEnvError { FromEnvError::NotActivated { - esp_idf_repo: repo.clone(), + esp_idf_tree: tree.clone(), source, } }; @@ -172,7 +188,7 @@ impl EspIdf { .map_err(not_activated)?; // make sure ${IDF_PATH}/tools/idf.py matches idf.py in $PATH - let idf_py_repo = path_buf![repo.worktree(), "tools", "idf.py"]; + let idf_py_repo = path_buf![tree.path(), "tools", "idf.py"]; match (idf_py.canonicalize(), idf_py_repo.canonicalize()) { (Ok(a), Ok(b)) if a != b => { return Err(not_activated(anyhow!( @@ -191,15 +207,15 @@ impl EspIdf { .with_context(|| anyhow!("python not found in $PATH")) .map_err(not_activated)?; let check_python_deps_py = - path_buf![repo.worktree(), "tools", "check_python_dependencies.py"]; + path_buf![tree.path(), "tools", "check_python_dependencies.py"]; cmd!(&python, &check_python_deps_py) .stdout() .with_context(|| anyhow!("failed to check python dependencies")) .map_err(not_activated)?; Ok(EspIdf { - version: EspIdfVersion::try_from(&repo), - repository: repo, + version: EspIdfVersion::try_from(&tree), + tree, exported_path: path_var, venv_python: python, is_managed_espidf: true, @@ -217,8 +233,8 @@ pub struct EspIdfVersion { impl EspIdfVersion { /// Try to extract the esp-idf version from an actual cloned repository. - pub fn try_from(repo: &git::Repository) -> Result { - let version_cmake = path_buf![repo.worktree(), "tools", "cmake", "version.cmake"]; + pub fn try_from(tree: &SourceTree) -> Result { + let version_cmake = path_buf![tree.path(), "tools", "cmake", "version.cmake"]; let base_err = || { anyhow!( @@ -302,7 +318,7 @@ pub struct Installer { custom_install_dir: Option, #[allow(clippy::type_complexity)] tools_provider: - Option) -> Result>>>, + Option) -> Result>>>, } impl Installer { @@ -319,7 +335,7 @@ impl Installer { #[must_use] pub fn with_tools(mut self, provider: F) -> Self where - F: 'static + FnOnce(&git::Repository, &Result) -> Result>, + F: 'static + FnOnce(&SourceTree, &Result) -> Result>, { self.tools_provider = Some(Box::new(provider)); self @@ -367,19 +383,19 @@ impl Installer { ) })?; - let (repository, managed_repo) = match self.esp_idf_origin { + let (tree, managed_repo) = match self.esp_idf_origin { EspIdfOrigin::Managed(managed) => ( - managed.open_or_clone( + SourceTree::Git(managed.open_or_clone( &install_dir, git::CloneOptions::new().depth(1), DEFAULT_ESP_IDF_REPOSITORY, MANAGED_ESP_IDF_REPOS_DIR_BASE, - )?, + )?), true, ), - EspIdfOrigin::Custom(repository) => (repository, false), + EspIdfOrigin::Custom(repository) => (SourceTree::Git(repository), false), }; - let version = EspIdfVersion::try_from(&repository); + let version = EspIdfVersion::try_from(&tree); let path_var_sep = if cfg!(windows) { ';' } else { ':' }; @@ -388,10 +404,10 @@ impl Installer { // TODO: also install python python::check_python_at_least(3, 6)?; - let idf_tools_py = path_buf![repository.worktree(), "tools", "idf_tools.py"]; + let idf_tools_py = path_buf![tree.path(), "tools", "idf_tools.py"]; let get_python_env_dir = || -> Result { - cmd!(PYTHON, &idf_tools_py, "--idf-path", repository.worktree(), "--quiet", "export", "--format=key-value"; + cmd!(PYTHON, &idf_tools_py, "--idf-path", tree.path(), "--quiet", "export", "--format=key-value"; ignore_exitcode=(), env=(IDF_TOOLS_PATH_VAR, &install_dir), env_remove=(IDF_PYTHON_ENV_PATH_VAR), env_remove=("MSYSTEM")) .stdout()? @@ -408,7 +424,7 @@ impl Installer { let python_env_dir: PathBuf = match get_python_env_dir() { Ok(dir) if Path::new(&dir).exists() => dir, _ => { - cmd!(PYTHON, &idf_tools_py, "--idf-path", repository.worktree(), "--non-interactive", "install-python-env"; + cmd!(PYTHON, &idf_tools_py, "--idf-path", tree.path(), "--non-interactive", "install-python-env"; env=(IDF_TOOLS_PATH_VAR, &install_dir), env_remove=("MSYSTEM"), env_remove=(IDF_PYTHON_ENV_PATH_VAR)).run()?; get_python_env_dir()? } @@ -427,7 +443,7 @@ impl Installer { // Install tools. let tools = self .tools_provider - .map(|p| p(&repository, &version)) + .map(|p| p(&tree, &version)) .unwrap_or(Ok(Vec::new()))?; let mut exported_paths = HashSet::new(); for tool in tools { @@ -439,7 +455,7 @@ impl Installer { .flatten(); // Install the tools. - cmd!(&python, &idf_tools_py, "--idf-path", repository.worktree(), @tools_json.clone(), "install"; + cmd!(&python, &idf_tools_py, "--idf-path", tree.path(), @tools_json.clone(), "install"; env=(IDF_TOOLS_PATH_VAR, &install_dir), args=(tool.tools)).run()?; // Get the paths to the tools. @@ -452,7 +468,7 @@ impl Installer { // native paths in rust. So we remove that environment variable when calling // idf_tools.py. exported_paths.extend( - cmd!(&python, &idf_tools_py, "--idf-path", repository.worktree(), @tools_json, "--quiet", "export", "--format=key-value"; + cmd!(&python, &idf_tools_py, "--idf-path", tree.path(), @tools_json, "--quiet", "export", "--format=key-value"; ignore_exitcode=(), env=(IDF_TOOLS_PATH_VAR, &install_dir), env_remove=("MSYSTEM")).stdout()? .lines() .find(|s| s.trim_start().starts_with("PATH=")) @@ -474,7 +490,7 @@ impl Installer { log::debug!("Using PATH='{}'", &paths.to_string_lossy()); Ok(EspIdf { - repository, + tree, exported_path: paths, venv_python: python, version,