Skip to content

Commit

Permalink
perf: 优化依赖关系图 ,解析package-lock.json(#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
ngd-b authored Jan 12, 2025
1 parent 3136703 commit 6feaa77
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 29 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
tags: "v*" # pushing a tag matching v*. e.g. v1.2.3
workflow_dispatch:

permissions:
contents: write

jobs:
release-build:
# runs-on: ubuntu-latest
Expand Down
15 changes: 14 additions & 1 deletion packages/pkg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,21 @@ pub fn check_file_exist<P: AsRef<Path>>(path: P) -> bool {
/// ```
pub async fn run(args: Args, package: Package) {
let mut file_path = args.dir.clone();
if !args.dir.ends_with("package.json") {
// 判断是不是一个文件夹目录
let dir = Path::new(&args.dir);

if dir.is_dir() {
file_path.push_str("/package.json");
} else {
// 是一个文件路径,但是不是package.json文件
if !args.dir.ends_with("package.json") {
let parent_dir = dir.parent().unwrap();
file_path = parent_dir
.join("package.json")
.to_str()
.unwrap()
.to_string();
}
}

let pkg_file_path = Path::new(&file_path);
Expand Down
102 changes: 74 additions & 28 deletions packages/pkg/src/package/package_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub struct Pkg {
#[serde(default)]
pub version: String,
#[serde(default)]
#[serde(rename = "lockfileVersion")]
pub lockfile_version: i32,
#[serde(default)]
pub packages: HashMap<String, PkgInfo>,
#[serde(default)]
pub dep_name: String,
Expand All @@ -26,6 +29,7 @@ impl Default for Pkg {
Self {
name: Default::default(),
version: Default::default(),
lockfile_version: Default::default(),
packages: HashMap::new(),
dep_name: Default::default(),
pkg_info: PkgInfo::default(),
Expand Down Expand Up @@ -125,48 +129,78 @@ impl Pkg {
}
/// 读取某个依赖的依赖关系图
pub fn read_pkg_graph(&mut self) -> Result<(), Box<dyn Error>> {
// 如果当前npm版本很低,则不支持查询
if self.lockfile_version < 2 {
return Err("当前npm版本不支持查询依赖关系图".into());
}
// 嵌套路径
let prefix = [self.dep_name.clone()].to_vec();
let key = format!("{}/{}", "node_modules", prefix.join("/node_modules/"));
if !self.packages.contains_key(&key) {
return Err(format!("当前路径未找到依赖:{}", self.dep_name).into());
}
// 记录依赖已被访问
// self.visited.insert(key.clone(), self.pkg_info.clone());

self.pkg_info = self.packages.get(&key).unwrap().clone();
// 当前依赖名称设置为顶层路径的依赖名
self.pkg_info.name = self.dep_name.clone();
self.pkg_info.path = key;
// 开始递归查找依赖关系图
self.pkg_info.relations = self
.read_pkg_child_graph(self.pkg_info.clone(), prefix)
let key = format!("{}@{}", self.pkg_info.name, self.pkg_info.version);
let relations = self
.read_pkg_child_graph(self.pkg_info.clone(), prefix, vec![key])
.unwrap();

// 不能递归查找依赖关系图,应该采用bfs的方式查找依赖关系图
// let mut queue = VecDeque::new();
// queue.push_back(&mut relations);
// // 记录已访问的依赖
// let mut visited = HashSet::new();
// // 记录已访问的依赖,防止循环依赖
// visited.insert(format!("{}@{}", self.pkg_info.name, self.pkg_info.version));
// while let Some(nodes) = queue.pop_front() {
// // bfs
// for node in nodes {
// let key = format!("{}@{}", node.name, node.version);
// if visited.contains(&key) {
// node.is_loop = true;
// continue;
// }
// visited.insert(key.clone());
// // 将子依赖加入队列
// queue.push_back(&mut node.relations);
// }
// }

self.pkg_info.relations = relations;
Ok(())
}

fn read_pkg_child_graph(
&mut self,
parent: PkgInfo,
prefix: Vec<String>,
visited: Vec<String>,
) -> Result<Vec<PkgInfo>, Box<dyn Error>> {
let mut relations = Vec::new();

for (child_name, _) in parent.dependencies.iter() {
let mut prefix = prefix.clone();
prefix.push(child_name.to_string());
// 递归查找依赖关系图
let mut child = self.read_pkg_graph_recursively(prefix)?;
child.is_peer = false;
relations.push(child);
}
for (child_name, _) in parent.peer_dependencies.iter() {
let mut prefix = prefix.clone();
prefix.push(child_name.to_string());
// 递归查找依赖关系图
let mut child = self.read_pkg_graph_recursively(prefix)?;
child.is_peer = true;
relations.push(child);
}
let mut process_dependencies = |dependencies: &HashMap<String, String>, is_peer: bool| {
for (child_name, _) in dependencies.iter() {
let mut prefix = prefix.clone();
prefix.push(child_name.to_string());
// 递归查找依赖关系图
let mut child = self
.read_pkg_graph_recursively(prefix, visited.clone())
.unwrap();

child.is_peer = is_peer;
relations.push(child);
}
};

process_dependencies(&parent.dependencies, false);
process_dependencies(&parent.peer_dependencies, true);

Ok(relations)
}
Expand All @@ -177,37 +211,45 @@ impl Pkg {
fn read_pkg_graph_recursively(
&mut self,
prefix: Vec<String>,
visited: Vec<String>,
) -> Result<PkgInfo, Box<dyn Error>> {
println!(
"开始递归读取依赖关系图,当前依赖:{:#?}",
prefix.last().unwrap()
&prefix.last().unwrap()
);
let mut graph = PkgInfo::default();

let mut keys = prefix.clone();

while keys.len() > 0 {
let key: String = format!("{}/{}", "node_modules", keys.join("/node_modules/"));

println!("正在查找依赖,依赖路径:{}", key);
if self.packages.contains_key(&key) {
println!("找到依赖:{}", &key);

graph = self.packages.get(&key).unwrap().clone();

graph.name = keys.last().unwrap().to_string();
graph.path = key.clone();
// 判断是否存在循环依赖
if self.visited.contains_key(&key) {
graph = self.visited.get(&key).unwrap().clone();
// if self.visited.contains_key(&key) {
// graph = self.visited.get(&key).unwrap().clone();
// // graph.is_loop = true;
// // 记录循环依赖
// println!("存在循环依赖:{}", &key);
// break;
// }
// // 缓存已访问的依赖
// self.visited.insert(key.clone(), graph.clone());
let visited_name = format!("{}@{}", graph.name, graph.version);
if visited.contains(&visited_name) {
graph.is_loop = true;

println!("存在循环依赖:{}", &key);
break;
}
// 缓存已访问的依赖
self.visited.insert(key.clone(), graph.clone());
let mut visited = visited.clone();
visited.push(visited_name);
// 递归处理依赖关系图
graph.relations = self.read_pkg_child_graph(graph.clone(), prefix)?;
graph.relations =
self.read_pkg_child_graph(graph.clone(), prefix.clone(), visited)?;

break;
}
Expand All @@ -217,6 +259,10 @@ impl Pkg {
}
keys.remove(keys.len() - 2);
}
// 没有查到
if graph.name.is_empty() {
graph.name = prefix.last().unwrap().to_string();
}
Ok(graph)
}
}

0 comments on commit 6feaa77

Please sign in to comment.