Skip to content

Commit 8dc0548

Browse files
authored
feat(scheduler): extract deps versions from yarn.lock (TabbyML#1711)
Closes TabbyML#876
1 parent 8203dd9 commit 8dc0548

5 files changed

Lines changed: 400 additions & 35 deletions

File tree

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/tabby-scheduler/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ tokio-cron-scheduler = { workspace = true }
3232
tokio = { workspace = true, features = ["process"] }
3333
package-lock-json-parser = "0.4.0"
3434
npm-package-json = "0.1.3"
35+
yarn-lock-parser = "0.7.0"
3536

3637
[dev-dependencies]
3738
temp_testdir = "0.2"

crates/tabby-scheduler/src/dataset/deps/javascript.rs

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -48,52 +48,86 @@ pub fn process_package_lock_json(path: &Path) -> Result<Vec<Package>> {
4848
}
4949
}
5050

51+
pub fn process_yarn_lock(path: &Path) -> Result<Vec<Package>> {
52+
let yarn_lock_file = path.join("yarn.lock");
53+
let yarn_lock_contents = read_to_string(yarn_lock_file)?;
54+
let lockfile_packages = yarn_lock_parser::parse_str(&yarn_lock_contents)?;
55+
let package_json_deps = process_package_json(path)?;
56+
57+
let mut deps = HashSet::new();
58+
59+
for package_dep in package_json_deps {
60+
let version = lockfile_packages
61+
.binary_search_by(|p| p.name.cmp(&package_dep.name))
62+
.map_or(package_dep.version, |dep| {
63+
Some(lockfile_packages[dep].version.to_string())
64+
});
65+
66+
deps.insert(Package {
67+
version,
68+
..package_dep
69+
});
70+
}
71+
72+
Ok(deps.into_iter().collect())
73+
}
74+
5175
#[cfg(test)]
5276
mod tests {
5377
use std::{env, path::PathBuf};
5478

5579
use super::*;
5680

81+
thread_local! {
82+
static EXPECTED_DEPS: Vec<Package> = Vec::from([
83+
Package {
84+
language: String::from("javascript"),
85+
name: String::from("fsevents"),
86+
version: Some(String::from("2.2.2")),
87+
},
88+
Package {
89+
language: String::from("javascript"),
90+
name: String::from("react"),
91+
version: Some(String::from("18.2.0")),
92+
},
93+
Package {
94+
language: String::from("javascript"),
95+
name: String::from("vite"),
96+
version: Some(String::from("5.1.4")),
97+
},
98+
Package {
99+
language: String::from("javascript"),
100+
name: String::from("zustand"),
101+
version: Some(String::from("4.5.1")),
102+
},
103+
]);
104+
}
105+
57106
#[test]
58107
fn it_parses_top_level_deps_from_package_lock() -> Result<()> {
59-
let mut expected_deps = Vec::from([
60-
Package {
61-
language: String::from("javascript"),
62-
name: String::from("fsevents"),
63-
version: Some(String::from("2.2.2")),
64-
},
65-
Package {
66-
language: String::from("javascript"),
67-
name: String::from("react"),
68-
version: Some(String::from("18.2.0")),
69-
},
70-
Package {
71-
language: String::from("javascript"),
72-
name: String::from("vite"),
73-
version: Some(String::from("5.1.4")),
74-
},
75-
Package {
76-
language: String::from("javascript"),
77-
name: String::from("zustand"),
78-
version: Some(String::from("4.5.1")),
79-
},
80-
]);
81-
let project_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
82-
let test_fixtures_path = project_path.join("testdata");
83-
let mut deps = process_package_lock_json(test_fixtures_path.as_path())?;
84-
85-
deps.sort();
86-
expected_deps.sort();
87-
88-
assert_eq!(deps, expected_deps);
89-
Ok(())
108+
EXPECTED_DEPS.with(|expected_deps| {
109+
let project_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
110+
let test_fixtures_path = project_path.join("testdata");
111+
let mut deps = process_package_lock_json(test_fixtures_path.as_path())?;
112+
113+
deps.sort();
114+
115+
assert_eq!(expected_deps, &deps);
116+
Ok(())
117+
})
90118
}
91119

92120
#[test]
93-
fn it_does_not_panic() {
94-
let temp_dir = env::temp_dir();
95-
let res = process_package_lock_json(temp_dir.as_path());
121+
fn it_parses_top_level_deps_from_yarn_lock() -> Result<()> {
122+
EXPECTED_DEPS.with(|expected_deps| {
123+
let project_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
124+
let test_fixtures_path = project_path.join("testdata");
125+
let mut deps = process_yarn_lock(test_fixtures_path.as_path())?;
96126

97-
assert!(res.is_err());
127+
deps.sort();
128+
129+
assert_eq!(expected_deps, &deps);
130+
Ok(())
131+
})
98132
}
99133
}

crates/tabby-scheduler/src/dataset/deps/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ pub fn collect(path: &Path, file: &mut DependencyFile) {
1919
file.direct.append(&mut deps);
2020
}
2121

22+
if let Ok(mut deps) = javascript::process_yarn_lock(path) {
23+
file.direct.append(&mut deps);
24+
}
25+
2226
// Remove duplicates across sources.
2327
let deps = file.direct.clone().into_iter().collect::<HashSet<_>>();
2428
file.direct = deps.into_iter().collect();

0 commit comments

Comments
 (0)