Skip to content

Commit

Permalink
feat: add local dependency support
Browse files Browse the repository at this point in the history
  • Loading branch information
halajohn committed Jan 4, 2025
1 parent 8491209 commit a78b172
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 55 deletions.
120 changes: 94 additions & 26 deletions core/src/ten_manager/src/cmd/cmd_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,27 +261,91 @@ fn update_package_manifest(
if let Some(ref mut dependencies) =
base_pkg_info.manifest.as_mut().unwrap().dependencies
{
let is_present = dependencies.iter().any(|dep| match dep {
ManifestDependency::RegistryDependency {
pkg_type, name, ..
} => {
*pkg_type
== added_dependency
.basic_info
.type_and_name
.pkg_type
.to_string()
&& *name == added_dependency.basic_info.type_and_name.name
}
ManifestDependency::LocalDependency { path } => {
added_dependency.is_local_dependency
&& path
== added_dependency
.local_dependency_path
.as_ref()
.unwrap()
let mut is_present = false;
let mut deps_to_remove = Vec::new();

for (i, dep) in dependencies.iter().enumerate() {
match dep {
ManifestDependency::RegistryDependency {
pkg_type,
name,
..
} => {
let manifest_dependency_type_and_name = PkgTypeAndName {
pkg_type: PkgType::from_str(pkg_type)?,
name: name.clone(),
};

if manifest_dependency_type_and_name
== added_dependency.basic_info.type_and_name
{
if !added_dependency.is_local_dependency {
is_present = true;
} else {
// The `manifest.json` specifies a registry
// dependency, but a local dependency is being
// added. Therefore, remove the original dependency
// item from `manifest.json`.
deps_to_remove.push(i);
}
break;
}
}
ManifestDependency::LocalDependency { path } => {
let manifest_dependency_pkg_info =
match get_pkg_info_from_path(Path::new(&path), false) {
Ok(info) => info,
Err(_) => {
panic!(
"Failed to get package info from path: {}",
path
);
}
};

if manifest_dependency_pkg_info.basic_info.type_and_name
== added_dependency.basic_info.type_and_name
{
if added_dependency.is_local_dependency {
assert!(
added_dependency
.local_dependency_path
.is_some(),
"Should not happen."
);

if path
== added_dependency
.local_dependency_path
.as_ref()
.unwrap()
{
is_present = true;
} else {
// The `manifest.json` specifies a local
// dependency, but a different local dependency
// is being added. Therefore, remove the
// original dependency item from
// `manifest.json`.
deps_to_remove.push(i);
}
} else {
// The `manifest.json` specifies a local dependency,
// but a registry dependency is being added.
// Therefore, remove the original dependency item
// from `manifest.json`.
deps_to_remove.push(i);
}
break;
}
}
}
});
}

// Remove dependencies to remove in reverse order to prevent index shift
for &i in deps_to_remove.iter().rev() {
dependencies.remove(i);
}

// If the added dependency does not exist in the `manifest.json`, add
// it.
Expand Down Expand Up @@ -565,12 +629,14 @@ pub async fn execute_cmd(
let desired_pkg_dest_name = template_ctx
.and_then(|ctx| ctx.get("package_name").and_then(|val| val.as_str()));

if let Some(package_type_str) = command_data.package_type {
if let Some(package_type_str) = command_data.package_type.as_ref() {
// Case 1: tman install <package_type> <package_name>

let desired_pkg_type_: PkgType = package_type_str.parse()?;
let (desired_pkg_src_name_, desired_pkg_src_version_) =
parse_pkg_name_version(&command_data.package_name.unwrap())?;
parse_pkg_name_version(
&command_data.package_name.as_ref().unwrap(),
)?;

desired_pkg_type = Some(desired_pkg_type_);
desired_pkg_src_name = Some(desired_pkg_src_name_.clone());
Expand All @@ -595,11 +661,11 @@ pub async fn execute_cmd(
} else {
// If it is not a standalone install, then the `cwd` must be within
// the base directory of a TEN app.
let app_pkg_ = get_pkg_info_from_path(&cwd)?;
let app_pkg_ = get_pkg_info_from_path(&cwd, true)?;
affected_pkg_name = app_pkg_.basic_info.type_and_name.name.clone();

// Push the app itself into the initial_input_pkgs.
initial_input_pkgs.push(get_pkg_info_from_path(&cwd)?);
initial_input_pkgs.push(app_pkg_.clone());

all_existing_local_pkgs =
tman_get_all_existed_pkgs_info_of_app(tman_config, &cwd)?;
Expand Down Expand Up @@ -660,7 +726,7 @@ pub async fn execute_cmd(
check_is_app_folder(&cwd)?;

// Push the app itself into the initial_input_pkgs.
initial_input_pkgs.push(get_pkg_info_from_path(&cwd)?);
initial_input_pkgs.push(get_pkg_info_from_path(&cwd, true)?);

all_existing_local_pkgs =
tman_get_all_existed_pkgs_info_of_app(tman_config, &cwd)?;
Expand All @@ -682,7 +748,7 @@ pub async fn execute_cmd(
fs::create_dir_all(path)?;
}

initial_input_pkgs.push(get_pkg_info_from_path(&cwd)?);
initial_input_pkgs.push(get_pkg_info_from_path(&cwd, true)?);

filter_compatible_pkgs_to_candidates(
tman_config,
Expand Down Expand Up @@ -794,6 +860,7 @@ pub async fn execute_cmd(
// `package-name` arg?
install_solver_results_in_standalone_mode(
tman_config,
&command_data,
&affected_pkg,
&pkg_identity_mappings,
template_ctx,
Expand Down Expand Up @@ -867,6 +934,7 @@ do you want to continue?",

install_solver_results_in_app_folder(
tman_config,
&command_data,
&remaining_solver_results,
&pkg_identity_mappings,
template_ctx,
Expand Down
2 changes: 1 addition & 1 deletion core/src/ten_manager/src/cmd/cmd_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub async fn execute_cmd(

let cwd = crate::utils::get_cwd()?;

let pkg_info = get_pkg_info_from_path(&cwd)?;
let pkg_info = get_pkg_info_from_path(&cwd, true)?;
let output_zip_file_name = get_package_zip_file_name(&pkg_info)?;

let output_zip_file_path_str =
Expand Down
2 changes: 1 addition & 1 deletion core/src/ten_manager/src/cmd/cmd_publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub async fn execute_cmd(

let cwd = crate::utils::get_cwd()?;

let pkg_info = get_pkg_info_from_path(&cwd)?;
let pkg_info = get_pkg_info_from_path(&cwd, true)?;
let output_zip_file_name = get_package_zip_file_name(&pkg_info)?;

// Generate the zip file.
Expand Down
13 changes: 8 additions & 5 deletions core/src/ten_manager/src/dep_and_candidate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,14 @@ async fn process_dependencies_to_get_candidates(
for dependency in input_dependencies {
if dependency.is_local() {
// Enforce having only one candidate: the package info parsed from
// the specified path. First, construct a `PkgInfo` to
// represent the package corresponding to the specified path.
let pkg_info: PkgInfo = get_pkg_info_from_path(Path::new(
&dependency.path.as_ref().unwrap(),
))?;
// the specified path.

// Construct a `PkgInfo` to represent the package corresponding to
// the specified path.
let pkg_info: PkgInfo = get_pkg_info_from_path(
Path::new(&dependency.path.as_ref().unwrap()),
false,
)?;

let candidate_map =
all_candidates.entry((&pkg_info).into()).or_default();
Expand Down
42 changes: 34 additions & 8 deletions core/src/ten_manager/src/install/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
pub mod installed_paths;
pub mod template;

use std::path::{Path, PathBuf};
use std::{
fs,
path::{Path, PathBuf},
};

use anyhow::Result;
use installed_paths::{
Expand All @@ -19,7 +22,9 @@ use ten_rust::pkg_info::{pkg_type::PkgType, PkgInfo};

use super::{config::TmanConfig, fs::merge_folders, registry::get_package};
use crate::{
log::tman_verbose_println, package_file::unzip::extract_and_process_zip,
cmd::cmd_install::{InstallCommand, LocalInstallMode},
log::tman_verbose_println,
package_file::unzip::extract_and_process_zip,
};

pub struct PkgIdentityMapping {
Expand All @@ -31,13 +36,12 @@ pub struct PkgIdentityMapping {

pub async fn install_pkg_info(
tman_config: &TmanConfig,
command_data: &InstallCommand,
pkg_info: &PkgInfo,
pkg_identity_mappings: &Vec<PkgIdentityMapping>,
template_ctx: Option<&serde_json::Value>,
base_dir: &Path,
) -> Result<()> {
// =-=-=

if pkg_info.is_installed {
tman_verbose_println!(
tman_config,
Expand All @@ -61,16 +65,38 @@ pub async fn install_pkg_info(
}
}

let path;
let target_path;
if let Some(found_pkg_identity_mapping) = found_pkg_identity_mapping {
path = Path::new(&base_dir)
target_path = Path::new(&base_dir)
.join(found_pkg_identity_mapping.dest_pkg_name.clone());
} else {
path = PathBuf::from(&base_dir)
target_path = PathBuf::from(&base_dir)
.join(pkg_info.basic_info.type_and_name.name.clone());
}

let output_dir = path.to_string_lossy().to_string();
let output_dir = target_path.to_string_lossy().to_string();

if pkg_info.is_local_dependency {
assert!(
pkg_info.local_dependency_path.is_some(),
"Should not happen.",
);

let src_path = pkg_info.local_dependency_path.as_ref().unwrap();

match command_data.local_install_mode {
LocalInstallMode::Copy => {
fs::copy(src_path, &output_dir)?;
}
LocalInstallMode::Link => {
#[cfg(unix)]
std::os::unix::fs::symlink(src_path, &output_dir)?;

#[cfg(windows)]
std::os::windows::fs::symlink_dir(path, &output_dir)?;
}
}
}

let mut temp_file = NamedTempFile::new()?;
get_package(tman_config, &pkg_info.url, &mut temp_file).await?;
Expand Down
2 changes: 2 additions & 0 deletions core/src/ten_manager/src/solver/solve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ fn create_input_str_for_all_possible_pkgs_info(
locked_pkgs.and_then(|locked_pkgs| locked_pkgs.get(candidates.0));

if let Some(locked_pkg) = locked_pkg {
// If the package recorded in `manifest-lock.json` is a local
// dependency, do not prioritize any candidate packages.
if !locked_pkg.is_local_dependency {
let idx = candidates_vec.iter().position(|pkg_info| {
pkg_info.version == locked_pkg.basic_info.version
Expand Down
5 changes: 5 additions & 0 deletions core/src/ten_manager/src/solver/solver_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use ten_rust::pkg_info::{
};

use crate::{
cmd::cmd_install::InstallCommand,
config::TmanConfig,
install::{install_pkg_info, PkgIdentityMapping},
};
Expand Down Expand Up @@ -110,6 +111,7 @@ pub fn filter_solver_results_by_type_and_name<'a>(

pub async fn install_solver_results_in_app_folder(
tman_config: &TmanConfig,
command_data: &InstallCommand,
solver_results: &Vec<&PkgInfo>,
pkg_identity_mappings: &Vec<PkgIdentityMapping>,
template_ctx: Option<&serde_json::Value>,
Expand Down Expand Up @@ -148,6 +150,7 @@ pub async fn install_solver_results_in_app_folder(

install_pkg_info(
tman_config,
command_data,
solver_result,
pkg_identity_mappings,
template_ctx,
Expand All @@ -163,6 +166,7 @@ pub async fn install_solver_results_in_app_folder(

pub async fn install_solver_results_in_standalone_mode(
tman_config: &TmanConfig,
command_data: &InstallCommand,
solver_results: &Vec<&PkgInfo>,
pkg_identity_mappings: &Vec<PkgIdentityMapping>,
template_ctx: Option<&serde_json::Value>,
Expand All @@ -171,6 +175,7 @@ pub async fn install_solver_results_in_standalone_mode(
for solver_result in solver_results {
install_pkg_info(
tman_config,
command_data,
solver_result,
pkg_identity_mappings,
template_ctx,
Expand Down
25 changes: 15 additions & 10 deletions core/src/ten_rust/src/pkg_info/manifest/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,29 @@ impl From<&PkgDependency> for ManifestDependency {
}

impl From<&PkgInfo> for ManifestDependency {
fn from(pkg_dependency: &PkgInfo) -> Self {
if pkg_dependency.is_local_dependency {
fn from(pkg_info: &PkgInfo) -> Self {
if pkg_info.is_local_dependency {
ManifestDependency::LocalDependency {
path: pkg_dependency
.local_dependency_path
.as_ref()
.unwrap()
.clone(),
path: {
assert!(
pkg_info.local_dependency_path.is_some(),
"Should not happen."
);

pkg_info.local_dependency_path.as_ref().unwrap().clone()
},
}
} else {
ManifestDependency::RegistryDependency {
pkg_type: pkg_dependency
pkg_type: pkg_info
.basic_info
.type_and_name
.pkg_type
.to_string(),
name: pkg_dependency.basic_info.type_and_name.name.clone(),
version: pkg_dependency.basic_info.version.to_string(),
name: pkg_info.basic_info.type_and_name.name.clone(),

// Use the package's version as the declared dependency version.
version: pkg_info.basic_info.version.to_string(),
}
}
}
Expand Down
Loading

0 comments on commit a78b172

Please sign in to comment.