diff --git a/kclvm/driver/src/kpm_metadata.rs b/kclvm/driver/src/kpm_metadata.rs index 996d404fa..ed1abdc39 100644 --- a/kclvm/driver/src/kpm_metadata.rs +++ b/kclvm/driver/src/kpm_metadata.rs @@ -1,7 +1,8 @@ +use crate::{get_path_for_executable, kcl, lookup_the_nearest_file_dir}; use anyhow::{bail, Ok, Result}; use kclvm_parser::LoadProgramOptions; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, env, iter, path::PathBuf, process::Command}; +use std::{collections::HashMap, path::PathBuf, process::Command}; const MANIFEST_FILE: &str = "kcl.mod"; @@ -115,71 +116,7 @@ pub(crate) fn fetch_mod_metadata(manifest_path: PathBuf) -> Result { } } -/// [`lookup_the_nearest_file_dir`] will start from [`from`] and search for file [`the_nearest_file`] in the parent directories. -/// If found, it will return the [`Some`] of [`the_nearest_file`] file path. If not found, it will return [`None`] -pub(crate) fn lookup_the_nearest_file_dir( - from: PathBuf, - the_nearest_file: &str, -) -> Option { - let mut current_dir = from; - - loop { - let found_path = current_dir.join(the_nearest_file); - if found_path.is_file() { - return current_dir.canonicalize().ok(); - } - - match current_dir.parent() { - Some(parent) => current_dir = parent.to_path_buf(), - None => return None, - } - } -} - -/// [`kcl`] will return the path for executable kcl binary. -pub fn kcl() -> PathBuf { - get_path_for_executable("kcl") -} - /// [`kpm`] will return the path for executable kpm binary. pub fn kpm() -> PathBuf { get_path_for_executable("kpm") } - -/// [`get_path_for_executable`] will return the path for [`executable_name`]. -pub fn get_path_for_executable(executable_name: &'static str) -> PathBuf { - // The current implementation checks $PATH for an executable to use: - // `` - // example: for , this tries just , which will succeed if is on the $PATH - - if lookup_in_path(executable_name) { - return executable_name.into(); - } - - executable_name.into() -} - -/// [`lookup_in_path`] will search for an executable file [`exec`] in the environment variable ‘PATH’. -/// If found, return true, otherwise return false. -fn lookup_in_path(exec: &str) -> bool { - let paths = env::var_os("PATH").unwrap_or_default(); - env::split_paths(&paths) - .map(|path| path.join(exec)) - .find_map(probe) - .is_some() -} - -/// [`probe`] check if the given path points to a file. -/// If it does, return [`Some`] of the path. -/// If not, check if adding the current operating system's executable file extension (if any) to the path points to a file. -/// If it does, return [`Some`] of the path with the extension added. -/// If neither, return [`None`]. -fn probe(path: PathBuf) -> Option { - let with_extension = match env::consts::EXE_EXTENSION { - "" => None, - it => Some(path.with_extension(it)), - }; - iter::once(path) - .chain(with_extension) - .find(|it| it.is_file()) -} diff --git a/kclvm/driver/src/kpm_update.rs b/kclvm/driver/src/kpm_update.rs index 1892c5198..f6caf4f5e 100644 --- a/kclvm/driver/src/kpm_update.rs +++ b/kclvm/driver/src/kpm_update.rs @@ -1,5 +1,6 @@ use anyhow::{bail, Result}; -use std::{collections::HashMap, env, iter, path::PathBuf, process::Command}; +use std::{path::PathBuf, process::Command}; +use crate::{probe, lookup_the_nearest_file_dir, kcl}; const MANIFEST_FILE: &str = "kcl.mod"; @@ -30,67 +31,3 @@ pub(crate) fn update_kcl_module(manifest_path: PathBuf) -> Result<()> { None => bail!("Manifest file '{}' not found in directory hierarchy", MANIFEST_FILE), } } - -/// Get the path for the KCL executable. -fn kcl() -> PathBuf { - get_path_for_executable("kcl") -} - -/// [`get_path_for_executable`] will return the path for [`executable_name`]. -pub fn get_path_for_executable(executable_name: &'static str) -> PathBuf { - // The current implementation checks $PATH for an executable to use: - // `` - // example: for , this tries just , which will succeed if is on the $PATH - - if lookup_in_path(executable_name) { - return executable_name.into(); - } - - executable_name.into() -} - -/// [`lookup_in_path`] will search for an executable file [`exec`] in the environment variable ‘PATH’. -/// If found, return true, otherwise return false. -fn lookup_in_path(exec: &str) -> bool { - let paths = env::var_os("PATH").unwrap_or_default(); - env::split_paths(&paths) - .map(|path| path.join(exec)) - .find_map(probe) - .is_some() -} - -/// [`probe`] check if the given path points to a file. -/// If it does, return [`Some`] of the path. -/// If not, check if adding the current operating system's executable file extension (if any) to the path points to a file. -/// If it does, return [`Some`] of the path with the extension added. -/// If neither, return [`None`]. -fn probe(path: PathBuf) -> Option { - let with_extension = match env::consts::EXE_EXTENSION { - "" => None, - it => Some(path.with_extension(it)), - }; - iter::once(path) - .chain(with_extension) - .find(|it| it.is_file()) -} - -/// [`lookup_the_nearest_file_dir`] will start from [`from`] and search for file [`the_nearest_file`] in the parent directories. -/// If found, it will return the [`Some`] of [`the_nearest_file`] file path. If not found, it will return [`None`] -pub(crate) fn lookup_the_nearest_file_dir( - from: PathBuf, - the_nearest_file: &str, -) -> Option { - let mut current_dir = from; - - loop { - let found_path = current_dir.join(the_nearest_file); - if found_path.is_file() { - return current_dir.canonicalize().ok(); - } - - match current_dir.parent() { - Some(parent) => current_dir = parent.to_path_buf(), - None => return None, - } - } -} diff --git a/kclvm/driver/src/lib.rs b/kclvm/driver/src/lib.rs index a454f65d2..66539156e 100644 --- a/kclvm/driver/src/lib.rs +++ b/kclvm/driver/src/lib.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use std::{env, iter}; pub mod arguments; pub mod kpm_metadata; pub const DEFAULT_PROJECT_FILE: &str = "project.yaml"; @@ -217,6 +218,70 @@ pub fn lookup_kcl_yaml(dir: &PathBuf) -> io::Result { } } +/// Get the path for the KCL executable. +fn kcl() -> PathBuf { + get_path_for_executable("kcl") +} + +/// [`get_path_for_executable`] will return the path for [`executable_name`]. +pub fn get_path_for_executable(executable_name: &'static str) -> PathBuf { + // The current implementation checks $PATH for an executable to use: + // `` + // example: for , this tries just , which will succeed if is on the $PATH + + if lookup_in_path(executable_name) { + return executable_name.into(); + } + + executable_name.into() +} + +/// [`lookup_in_path`] will search for an executable file [`exec`] in the environment variable ‘PATH’. +/// If found, return true, otherwise return false. +fn lookup_in_path(exec: &str) -> bool { + let paths = env::var_os("PATH").unwrap_or_default(); + env::split_paths(&paths) + .map(|path| path.join(exec)) + .find_map(probe) + .is_some() +} + +/// [`probe`] check if the given path points to a file. +/// If it does, return [`Some`] of the path. +/// If not, check if adding the current operating system's executable file extension (if any) to the path points to a file. +/// If it does, return [`Some`] of the path with the extension added. +/// If neither, return [`None`]. +fn probe(path: PathBuf) -> Option { + let with_extension = match env::consts::EXE_EXTENSION { + "" => None, + it => Some(path.with_extension(it)), + }; + iter::once(path) + .chain(with_extension) + .find(|it| it.is_file()) +} + +/// [`lookup_the_nearest_file_dir`] will start from [`from`] and search for file [`the_nearest_file`] in the parent directories. +/// If found, it will return the [`Some`] of [`the_nearest_file`] file path. If not found, it will return [`None`] +pub(crate) fn lookup_the_nearest_file_dir( + from: PathBuf, + the_nearest_file: &str, +) -> Option { + let mut current_dir = from; + + loop { + let found_path = current_dir.join(the_nearest_file); + if found_path.is_file() { + return current_dir.canonicalize().ok(); + } + + match current_dir.parent() { + Some(parent) => current_dir = parent.to_path_buf(), + None => return None, + } + } +} + /// For the KCL project, some definitions may be introduced through multi-file /// compilation (kcl.yaml). This function is used to start from a single file and try /// to find a `compile unit` that contains all definitions