Skip to content

Commit

Permalink
feat: impl native toolchain
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <xpf6677@163.com>
  • Loading branch information
Peefy committed May 27, 2024
1 parent 0c819ee commit 357434b
Show file tree
Hide file tree
Showing 19 changed files with 1,326 additions and 37 deletions.
597 changes: 588 additions & 9 deletions kclvm/Cargo.lock

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions kclvm/api/src/service/capi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ pub(crate) fn kclvm_get_service_fn_ptr_by_name(name: &str) -> u64 {
"KclvmService.Rename" => rename as *const () as u64,
"KclvmService.RenameCode" => rename_code as *const () as u64,
"KclvmService.Test" => test as *const () as u64,
"KclvmService.UpdateDependencies" => update_dependencies as *const () as u64,
_ => panic!("unknown method name : {name}"),
}
}
Expand Down Expand Up @@ -562,3 +563,34 @@ pub(crate) fn test(
) -> *const c_char {
call!(serv, args, result_len, TestArgs, test)
}

/// Service for the dependencies updating
/// calling information.
///
/// # Parameters
///
/// `serv`: [*mut kclvm_service]
/// The pointer of &\[[KclvmServiceImpl]]
///
///
/// `args`: [*const c_char]
/// the items and compile parameters selected by the user in the KCL CLI
/// serialized as protobuf byte sequence
///
/// # Returns
///
/// result: [*const c_char]
/// Result of the call serialized as protobuf byte sequence
pub(crate) fn update_dependencies(
serv: *mut kclvm_service,
args: *const c_char,
result_len: *mut usize,
) -> *const c_char {
call!(
serv,
args,
result_len,
UpdateDependenciesArgs,
update_dependencies
)
}
8 changes: 8 additions & 0 deletions kclvm/api/src/service/jsonrpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,14 @@ fn register_kclvm_service(io: &mut IoHandler) {
};
futures::future::ready(catch!(kclvm_service_impl, args, test))
});
io.add_method("KclvmService.UpdateDependencies", |params: Params| {
let kclvm_service_impl = KclvmServiceImpl::default();
let args: UpdateDependenciesArgs = match params.parse() {
Ok(val) => val,
Err(err) => return futures::future::ready(Err(err)),
};
futures::future::ready(catch!(kclvm_service_impl, args, update_dependencies))
});
}

fn register_builtin_service(io: &mut IoHandler) {
Expand Down
50 changes: 49 additions & 1 deletion kclvm/api/src/service/service_impl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;
use std::io::Write;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::string::String;

use crate::gpyrpc::*;
Expand All @@ -9,6 +9,7 @@ use anyhow::anyhow;
use kcl_language_server::rename;
use kclvm_config::settings::build_settings_pathbuf;
use kclvm_driver::canonicalize_input_files;
use kclvm_driver::client::ModClient;
use kclvm_loader::option::list_options;
use kclvm_loader::{load_packages_with_cache, LoadPackageOptions};
use kclvm_parser::load_program;
Expand Down Expand Up @@ -1061,4 +1062,51 @@ impl KclvmServiceImpl {
}
Ok(result)
}

/// update_dependencies provides users with the ability to update kcl module dependencies.
///
/// # Examples
///
/// ```
/// use kclvm_api::service::service_impl::KclvmServiceImpl;
/// use kclvm_api::gpyrpc::*;
/// use std::path::Path;
/// use std::fs::remove_dir_all;
///
/// let serv = KclvmServiceImpl::default();
/// let result = serv.update_dependencies(&UpdateDependenciesArgs {
/// manifest_path: "./src/testdata/update_dependencies".to_string(),
/// ..Default::default()
/// }).unwrap();
/// assert_eq!(result.external_pkgs.len(), 1);
///
/// let result = serv.update_dependencies(&UpdateDependenciesArgs {
/// manifest_path: "./src/testdata/update_dependencies".to_string(),
/// vendor: true,
/// }).unwrap();
/// assert_eq!(result.external_pkgs.len(), 1);
/// let vendor_path = Path::new("./src/testdata/update_dependencies/vendor");
/// remove_dir_all(vendor_path);
/// ```
pub fn update_dependencies(
&self,
args: &UpdateDependenciesArgs,
) -> anyhow::Result<UpdateDependenciesResult> {
let mut client = ModClient::new(&args.manifest_path)?;
if args.vendor {
client.set_vendor(&Path::new(&args.manifest_path).join("vendor"));
}
client.auth()?;
let metadata = client.resolve_all_deps(true)?;
Ok(UpdateDependenciesResult {
external_pkgs: metadata
.packages
.iter()
.map(|(n, p)| ExternalPkg {
pkg_name: n.to_string(),
pkg_path: p.manifest_path.to_string_lossy().to_string(),
})
.collect(),
})
}
}
6 changes: 6 additions & 0 deletions kclvm/api/src/testdata/update_dependencies/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "update_dependencies"
version = "0.0.1"

[dependencies]
helloworld = { oci = "oci://ghcr.io/kcl-lang/helloworld", tag = "0.1.0" }
39 changes: 39 additions & 0 deletions kclvm/config/src/modfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ pub struct ModFile {
pub dependencies: Option<Dependencies>,
}

/// ModLockFile is kcl package file 'kc.mod.lock'.
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct ModLockFile {
pub dependencies: Option<LockDependencies>,
}

/// Package is the kcl package section of 'kcl.mod'.
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct Package {
Expand Down Expand Up @@ -67,6 +73,7 @@ pub struct Profile {

/// A map of package names to their respective dependency specifications.
pub type Dependencies = HashMap<String, Dependency>;
pub type LockDependencies = HashMap<String, LockDependency>;

/// Dependency represents a single dependency for a package, which may come in different forms
/// such as version, Git repository, OCI repository, or a local path.
Expand All @@ -83,6 +90,29 @@ pub enum Dependency {
Local(LocalSource),
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct LockDependency {
/* Common field */
pub name: String,
pub full_name: Option<String>,
pub version: Option<String>,
pub sum: Option<String>,

/* OCI Source */
pub reg: Option<String>,
pub repo: Option<String>,
pub oci_tag: Option<String>,

/* Git Source */
pub url: Option<String>,
pub branch: Option<String>,
pub commit: Option<String>,
pub git_tag: Option<String>,

/* Local Source */
pub path: Option<String>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct GitSource {
/// The URL of the Git repository.
Expand Down Expand Up @@ -129,6 +159,15 @@ pub fn load_mod_file<P: AsRef<Path>>(path: P) -> Result<ModFile> {
toml::from_slice(buffer.as_slice()).map_err(|e| anyhow::anyhow!(e))
}

/// Load kcl mod lock file from path
pub fn load_mod_lock_file<P: AsRef<Path>>(path: P) -> Result<ModLockFile> {
let file_path = path.as_ref().join(KCL_MOD_LOCK_FILE);
let mut file = std::fs::File::open(file_path)?;
let mut buffer: Vec<u8> = vec![];
file.read_to_end(&mut buffer)?;
toml::from_slice(buffer.as_slice()).map_err(|e| anyhow::anyhow!(e))
}

/// Get the path holding the external kcl package.
/// From the environment variable KCL_PKG_PATH.
/// If `KCL_PKG_PATH` is not present, then the user root string is returned.
Expand Down
7 changes: 7 additions & 0 deletions kclvm/driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ walkdir = "2"
serde = { version = "1.0", features = ["derive"] }
anyhow = { version = "1.0.70", features = ["backtrace"] }
glob = "0.3.1"
oci-distribution = "0.11.0"
flate2 = "1.0.30"
tar = "0.4.40"
tokio = { version = "1.37.0", features = ["full"] }
indexmap = "2.2.6"
once_cell = "1.19.0"
parking_lot = "0.12.3"
8 changes: 8 additions & 0 deletions kclvm/driver/src/client/fs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::path::Path;

#[inline]
pub(crate) fn directory_is_not_empty<P: AsRef<Path>>(path: P) -> bool {
std::fs::read_dir(path)
.map(|mut entries| entries.next().is_some())
.is_ok()
}
47 changes: 47 additions & 0 deletions kclvm/driver/src/client/git.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::path::{Path, PathBuf};
use std::process::Command;

use crate::client::fs::directory_is_not_empty;
use anyhow::{bail, Result};

pub(crate) fn clone_git_repo_to(
url: &str,
branch: &Option<String>,
tag: &Option<String>,
commit: &Option<String>,
path: &Path,
) -> Result<PathBuf> {
if directory_is_not_empty(path) {
return Ok(path.to_path_buf());
}
let mut git_clone_cmd = Command::new("git");
git_clone_cmd.args(["clone", url]);
if let Some(branch_name) = branch {
git_clone_cmd.args(["--branch", branch_name]);
}
git_clone_cmd.arg(path);

let output = git_clone_cmd.output()?;
if !output.status.success() {
bail!("Failed to clone Git repository {}", url);
}
if let Some(tag_name) = tag {
let output = Command::new("git")
.args(["checkout", tag_name])
.current_dir(path)
.output()?;
if !output.status.success() {
bail!("Failed to checkout Git tag");
}
} else if let Some(commit_hash) = commit {
let output = Command::new("git")
.args(["checkout", commit_hash])
.current_dir(path)
.output()?;
if !output.status.success() {
bail!("Failed to checkout Git commit");
}
}

Ok(path.to_path_buf())
}
Loading

0 comments on commit 357434b

Please sign in to comment.