Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for local dependency in extension #516

Merged
merged 4 commits into from
Jan 7, 2025
Merged
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
6 changes: 5 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,14 @@
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/out/linux/x64/ten_manager/bin/tman",
"cwd": "${workspaceFolder}/out/linux/x64/tests/ten_manager/install_all/local_dependency_link_in_extension/test_app",
"cwd": "${workspaceFolder}/out/linux/x64/tests/ten_manager/install/mock_app/mock_app",
"args": [
"--config-file=${workspaceFolder}/out/linux/x64/tests/local_registry/config.json",
"install",
"extension",
"ext_a",
"--os=linux",
"--arch=x64"
],
"preRunCommands": [
"script import pathlib;import subprocess;import lldb;rustc_sysroot = subprocess.getoutput(\"rustc --print sysroot\");rustlib_etc = pathlib.Path(rustc_sysroot) / \"lib\" / \"rustlib\" / \"etc\";lldb.debugger.HandleCommand(f'command script import \"{rustlib_etc / \"lldb_lookup.py\"}\"');lldb.debugger.HandleCommand(f'command source -s 0 \"{rustlib_etc / \"lldb_commands\"}\"')"
Expand Down
4 changes: 2 additions & 2 deletions core/src/ten_manager/src/cmd/cmd_check/cmd_check_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use clap::{Arg, ArgMatches, Command};
use console::Emoji;

use ten_rust::pkg_info::{
get_all_existed_pkgs_info_of_app, graph::Graph, localhost,
get_all_installed_pkgs_info_of_app, graph::Graph, localhost,
property::parse_property_in_folder, PkgInfo,
};

Expand Down Expand Up @@ -107,7 +107,7 @@ fn get_existed_pkgs_of_all_apps(

for app in &command.app_dir {
let app_path = path::Path::new(app);
let app_existed_pkgs = get_all_existed_pkgs_info_of_app(app_path)?;
let app_existed_pkgs = get_all_installed_pkgs_info_of_app(app_path)?;

let app_property = parse_property_in_folder(app_path)?;
let app_uri = if let Some(property) = app_property {
Expand Down
136 changes: 72 additions & 64 deletions core/src/ten_manager/src/cmd/cmd_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use console::Emoji;
use indicatif::HumanDuration;
use inquire::Confirm;

use ten_rust::pkg_info::pkg_basic_info::PkgBasicInfo;
use ten_rust::pkg_info::{
dependencies::PkgDependency,
get_pkg_info_from_path,
Expand All @@ -26,9 +27,6 @@ use ten_rust::pkg_info::{
supports::{Arch, Os, PkgSupport},
PkgInfo,
};
use ten_rust::pkg_info::{
manifest::parse_manifest_in_folder, pkg_basic_info::PkgBasicInfo,
};

use crate::{
config::TmanConfig,
Expand All @@ -42,7 +40,7 @@ use crate::{
},
log::tman_verbose_println,
manifest_lock::parse_manifest_lock_in_folder,
package_info::tman_get_all_existed_pkgs_info_of_app,
package_info::tman_get_all_installed_pkgs_info_of_app,
solver::{
introducer::extract_introducer_relations_from_raw_solver_results,
solve::{solve_all, DependencyRelationship},
Expand Down Expand Up @@ -155,6 +153,24 @@ fn get_locked_pkgs(app_dir: &Path) -> Option<HashMap<PkgTypeAndName, PkgInfo>> {
}
}

fn add_pkg_to_initial_pkg_to_find_candidates_and_all_candidates(
pkg: &PkgInfo,
initial_pkgs_to_find_candidates: &mut Vec<PkgInfo>,
all_candidates: &mut HashMap<
PkgTypeAndName,
HashMap<PkgBasicInfo, PkgInfo>,
>,
) -> Result<()> {
initial_pkgs_to_find_candidates.push(pkg.clone());

all_candidates
.entry(pkg.into())
.or_default()
.insert(pkg.into(), pkg.clone());

Ok(())
}

pub async fn execute_cmd(
tman_config: &TmanConfig,
command_data: InstallCommand,
Expand All @@ -167,35 +183,24 @@ pub async fn execute_cmd(

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

// The package affected by tman install command, which is the root declared
// in the resolver.
//
// 1. If installing a package in standalone mode, the affected package is
// the installed package itself, ex: app or extension.
//
// 2. Otherwise, the affected package is always the app, as the installing
// package must be installed in a TEN app in this case.
let mut cwd_pkg_type = PkgType::App;
let cwd_pkg_name;

// The path of `.ten/app/` if we needed.
let mut dot_ten_app_dir_path: Option<PathBuf> = None;

// If `tman install` is run within the scope of an app, then the app and
// those addons (extensions, ...) installed in the app directory are all
// considered initial_input_pkgs.
// considered initial_pkgs_to_find_candidates.
let mut initial_pkgs_to_find_candidates = vec![];
let mut all_candidates: HashMap<
PkgTypeAndName,
HashMap<PkgBasicInfo, PkgInfo>,
> = HashMap::new();

// 'all_existing_local_pkgs' contains all the packages which are already
// located in the `app` directory, including the `app` itself, and all the
// 'all_installed_pkgs' contains all the packages which are already located
// in the `app` directory, including the `app` itself, and all the
// addons located in `ten_packages/<foo>/<bar>`
//
// After the completed dependency tree is resolved,
// 'all_existing_local_pkgs' will be compared with the solver results:
// 'all_installed_pkgs' will be compared with the solver results:
//
// *) If some of these packages are not included in the dependency tree,
// then users will be prompted that these packages can be added to the
Expand All @@ -204,17 +209,33 @@ pub async fn execute_cmd(
// *) If some of these packages are not compatible with packages in
// the dependency tree, then users will be questioned whether to overwrite
// them with the new packages or quit the installation.
let mut all_existing_local_pkgs: Vec<PkgInfo> = vec![];
let mut all_installed_pkgs: Vec<PkgInfo> = vec![];
let mut all_compatible_installed_pkgs: HashMap<
PkgTypeAndName,
HashMap<PkgBasicInfo, PkgInfo>,
> = HashMap::new();

let mut dep_relationship_from_cmd_line: Option<DependencyRelationship> =
None;

let mut app_pkg: Option<PkgInfo> = None;
let mut is_install_all = false;
let mut installing_pkg_type: Option<PkgType> = None;
let mut installing_pkg_name: Option<String> = None;

let mut cwd_pkg = get_pkg_info_from_path(&cwd, true)?;

// We need to start looking for dependencies outward from the cwd package,
// and the cwd package itself is considered a candidate.
add_pkg_to_initial_pkg_to_find_candidates_and_all_candidates(
&cwd_pkg,
&mut initial_pkgs_to_find_candidates,
&mut all_candidates,
)?;

if let Some(package_type_str) = command_data.package_type.as_ref() {
// Case 1: tman install <package_type> <package_name>
//
// The `cwd` must be the base directory of a TEN app.

let installing_pkg_type_: PkgType = package_type_str.parse()?;

Expand All @@ -230,28 +251,22 @@ pub async fn execute_cmd(
installing_pkg_type = Some(installing_pkg_type_);
installing_pkg_name = Some(installing_pkg_name_.clone());

// The `cwd` must be the base directory of a TEN app.
let app_pkg_ = get_pkg_info_from_path(&cwd, true)?;
cwd_pkg_name = app_pkg_.basic_info.type_and_name.name.clone();

initial_pkgs_to_find_candidates.push(app_pkg_.clone());

all_existing_local_pkgs =
tman_get_all_existed_pkgs_info_of_app(tman_config, &cwd)?;
all_installed_pkgs =
tman_get_all_installed_pkgs_info_of_app(tman_config, &cwd)?;

filter_compatible_pkgs_to_candidates(
tman_config,
&all_existing_local_pkgs,
&mut all_candidates,
&all_installed_pkgs,
&mut all_compatible_installed_pkgs,
&command_data.support,
);

dep_relationship_from_cmd_line = Some(DependencyRelationship {
type_and_name: PkgTypeAndName {
pkg_type: app_pkg_.basic_info.type_and_name.pkg_type,
name: app_pkg_.basic_info.type_and_name.name.clone(),
pkg_type: cwd_pkg.basic_info.type_and_name.pkg_type,
name: cwd_pkg.basic_info.type_and_name.name.clone(),
},
version: app_pkg_.basic_info.version.clone(),
version: cwd_pkg.basic_info.version.clone(),
dependency: PkgDependency {
type_and_name: PkgTypeAndName {
pkg_type: installing_pkg_type_,
Expand All @@ -262,31 +277,25 @@ pub async fn execute_cmd(
base_dir: None,
},
});

app_pkg = Some(app_pkg_);
} else {
// Case 2: tman install

let manifest = parse_manifest_in_folder(&cwd)?;
cwd_pkg_type = manifest.type_and_name.pkg_type;
cwd_pkg_name = manifest.type_and_name.name.clone();
is_install_all = true;

match cwd_pkg_type {
match cwd_pkg.basic_info.type_and_name.pkg_type {
PkgType::App => {
// The TEN app itself is also a package. Extensions can declare
// dependencies on a specific version of an app, so the app also
// needs to be included in the package list for dependency tree
// calculation.
initial_pkgs_to_find_candidates
.push(get_pkg_info_from_path(&cwd, true)?);

all_existing_local_pkgs =
tman_get_all_existed_pkgs_info_of_app(tman_config, &cwd)?;
all_installed_pkgs =
tman_get_all_installed_pkgs_info_of_app(tman_config, &cwd)?;

filter_compatible_pkgs_to_candidates(
tman_config,
&all_existing_local_pkgs,
&mut all_candidates,
&all_installed_pkgs,
&mut all_compatible_installed_pkgs,
&command_data.support,
);
}
Expand All @@ -301,13 +310,10 @@ pub async fn execute_cmd(
fs::create_dir_all(path)?;
}

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

filter_compatible_pkgs_to_candidates(
tman_config,
&initial_pkgs_to_find_candidates,
&mut all_candidates,
&mut all_compatible_installed_pkgs,
&command_data.support,
);
}
Expand Down Expand Up @@ -337,6 +343,7 @@ pub async fn execute_cmd(
dep_relationship_from_cmd_line
.as_ref()
.map(|rel| &rel.dependency),
&all_compatible_installed_pkgs,
all_candidates,
locked_pkgs.as_ref(),
)
Expand All @@ -347,8 +354,8 @@ pub async fn execute_cmd(
// Find an answer (a dependency tree) that satisfies all dependencies.
let (usable_model, non_usable_models) = solve_all(
tman_config,
&cwd_pkg_type,
&cwd_pkg_name,
&cwd_pkg.basic_info.type_and_name.pkg_type,
&cwd_pkg.basic_info.type_and_name.name,
dep_relationship_from_cmd_line.as_ref(),
&all_candidates,
locked_pkgs.as_ref(),
Expand Down Expand Up @@ -385,8 +392,8 @@ pub async fn execute_cmd(
// this package already exists and does not need to be installed.
let remaining_solver_results = filter_solver_results_by_type_and_name(
&solver_results,
Some(&cwd_pkg_type),
Some(&cwd_pkg_name),
Some(&cwd_pkg.basic_info.type_and_name.pkg_type),
Some(&cwd_pkg.basic_info.type_and_name.name),
false,
)?;

Expand All @@ -395,7 +402,7 @@ pub async fn execute_cmd(
// or replaced.
let has_conflict = compare_solver_results_with_existed_pkgs(
&remaining_solver_results,
&all_existing_local_pkgs,
&all_installed_pkgs,
);

if has_conflict && !tman_config.assume_yes {
Expand Down Expand Up @@ -441,15 +448,16 @@ pub async fn execute_cmd(
}

// Write the installing package info to manifest.json.
if let Some(mut app_pkg) = app_pkg {
if installing_pkg_type.is_some() && installing_pkg_name.is_some() {
write_installing_pkg_into_manifest_file(
&mut app_pkg,
&solver_results,
&installing_pkg_type.unwrap(),
&installing_pkg_name.unwrap(),
)?;
}
if !is_install_all
&& installing_pkg_type.is_some()
&& installing_pkg_name.is_some()
{
write_installing_pkg_into_manifest_file(
&mut cwd_pkg,
&solver_results,
&installing_pkg_type.unwrap(),
&installing_pkg_name.unwrap(),
)?;
}

println!(
Expand Down
Loading
Loading