Skip to content

Commit 1d9b669

Browse files
committed
Adds a test
1 parent 3bf395b commit 1d9b669

File tree

4 files changed

+100
-4
lines changed

4 files changed

+100
-4
lines changed

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"Bash(yarn test:integration:*)",
1717
"Bash(cargo check:*)",
1818
"Bash(git stash:*)",
19-
"Bash(RUST_BACKTRACE=1 ~/Repositories/zpm/target/release/yarn-bin:*)"
19+
"Bash(RUST_BACKTRACE=1 ~/Repositories/zpm/target/release/yarn-bin:*)",
20+
"Bash(/Users/mael.nison/Repositories/zpm/target/release/yarn-bin install *)"
2021
],
2122
"deny": [],
2223
"ask": []

.github/actions/run-e2e-sandbox/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ RUN apt-get update \
1313
npm \
1414
python3 \
1515
python-is-python3 \
16-
&& rm -rf /var/lib/apt/lists/*
16+
&& rm -rf /var/lib/apt/lists/* \
17+
&& npm install -g pnpm
1718

1819
COPY entrypoint.sh /entrypoint.sh
1920
RUN chmod +x /entrypoint.sh

packages/zpm/src/lockfile.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,14 +475,22 @@ pub fn from_pnpm_node_modules(project_cwd: &Path) -> Result<Lockfile, Error> {
475475
continue;
476476
};
477477

478-
let Ok(package_path) = Path::try_from(package_path_str.as_str()) else {
478+
let Ok(raw_path) = Path::try_from(package_path_str.as_str()) else {
479479
continue;
480480
};
481481

482+
let package_path = if raw_path.is_relative() {
483+
project_cwd.with_join_str("node_modules").with_join(&raw_path)
484+
} else {
485+
raw_path
486+
};
487+
482488
#[derive(Debug, Deserialize)]
483489
struct Manifest {
484490
#[serde(default)]
485491
dependencies: BTreeMap<String, String>,
492+
#[serde(default, rename = "optionalDependencies")]
493+
optional_dependencies: BTreeMap<String, String>,
486494
}
487495

488496
let manifest: Option<Manifest>
@@ -496,7 +504,11 @@ pub fn from_pnpm_node_modules(project_cwd: &Path) -> Result<Lockfile, Error> {
496504
continue;
497505
};
498506

499-
for (name, range) in manifest.dependencies {
507+
let all_dependencies
508+
= manifest.dependencies.into_iter().map(|(n, r)| (n, r, false))
509+
.chain(manifest.optional_dependencies.into_iter().map(|(n, r)| (n, r, true)));
510+
511+
for (name, range, is_optional) in all_dependencies {
500512
let Ok(ident) = Ident::from_file_string(&name) else {
501513
continue;
502514
};
@@ -510,6 +522,25 @@ pub fn from_pnpm_node_modules(project_cwd: &Path) -> Result<Lockfile, Error> {
510522
continue;
511523
};
512524

525+
if is_optional {
526+
let installed = resolved_entry.path.as_ref().and_then(|p| {
527+
let p
528+
= Path::try_from(p.as_str()).ok()?;
529+
530+
let p = if p.is_relative() {
531+
project_cwd.with_join_str("node_modules").with_join(&p)
532+
} else {
533+
p
534+
};
535+
536+
Some(p.with_join_str("package.json").fs_exists())
537+
});
538+
539+
if !installed.unwrap_or(false) {
540+
continue;
541+
}
542+
}
543+
513544
let Some(version) = &resolved_entry.version else {
514545
continue;
515546
};

tests/e2e/pnpm-migration.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env bash
2+
3+
mkdir -p packages/pkg-a
4+
5+
cat > package.json <<'JSON'
6+
{
7+
"name": "e2e-pnpm-migration",
8+
"private": true,
9+
"workspaces": [
10+
"packages/*"
11+
]
12+
}
13+
JSON
14+
15+
cat > pnpm-workspace.yaml <<'YAML'
16+
packages:
17+
- "packages/*"
18+
YAML
19+
20+
cat > packages/pkg-a/package.json <<'JSON'
21+
{
22+
"name": "pkg-a",
23+
"version": "1.0.0",
24+
"private": true,
25+
"dependencies": {
26+
"jest": "*"
27+
}
28+
}
29+
JSON
30+
31+
pnpm install
32+
33+
# Capture the versions pnpm resolved (normalized to name@version)
34+
pnpm ls -r --json --depth=Infinity \
35+
| jq -r '.. | objects | select(.version? and .from?) | "\(.from)@\(.version)"' \
36+
| sort -u > "${TEMP_DIR}/pnpm-versions.txt"
37+
38+
rm -f pnpm-lock.yaml
39+
40+
yarn install
41+
42+
# Capture the versions yarn resolved (normalized to name@version)
43+
yarn info -AR --json \
44+
| jq -r '.value' \
45+
| grep '@npm:' \
46+
| sed -E 's/@npm:(.+@)?/\t/' \
47+
| awk -F'\t' '{print $1"@"$2}' \
48+
| sort -u > "${TEMP_DIR}/yarn-versions.txt"
49+
50+
# Every version from pnpm must appear in yarn's resolution.
51+
# Platform-specific packages (like fsevents) may be absent; that's expected.
52+
MISMATCHES=0
53+
while IFS= read -r line; do
54+
if ! grep -qxF "${line}" "${TEMP_DIR}/yarn-versions.txt"; then
55+
echo "MISMATCH: pnpm had ${line} but yarn does not" >&2
56+
MISMATCHES=$((MISMATCHES + 1))
57+
fi
58+
done < "${TEMP_DIR}/pnpm-versions.txt"
59+
60+
if [[ "${MISMATCHES}" -gt 5 ]]; then
61+
echo "Too many version mismatches (${MISMATCHES}); migration did not preserve versions" >&2
62+
exit 1
63+
fi

0 commit comments

Comments
 (0)