Skip to content

Commit fd7215d

Browse files
authored
fix: Remove lock file if old version format (#22711)
Remove the package-lock.json file if it is made with lockfileVersion 1 or 2 as else there are conflicts when using new npm version. Fixes #22676
1 parent c3d1c06 commit fd7215d

File tree

2 files changed

+182
-0
lines changed

2 files changed

+182
-0
lines changed

flow-server/src/main/java/com/vaadin/flow/server/frontend/TaskRunNpmInstall.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616
package com.vaadin.flow.server.frontend;
1717

18+
import java.io.BufferedReader;
1819
import java.io.File;
20+
import java.io.FileReader;
1921
import java.io.IOException;
2022
import java.io.InputStream;
2123
import java.io.UncheckedIOException;
@@ -27,6 +29,8 @@
2729
import java.util.Map;
2830
import java.util.concurrent.ExecutionException;
2931
import java.util.function.Consumer;
32+
import java.util.regex.Matcher;
33+
import java.util.regex.Pattern;
3034
import java.util.stream.Collectors;
3135

3236
import org.apache.commons.io.FileUtils;
@@ -516,6 +520,8 @@ private void createNpmRcFile() throws IOException {
516520
}
517521

518522
private void cleanUp() throws ExecutionFailedException {
523+
verifyPackageLockAndClean();
524+
519525
if (!options.getNodeModulesFolder().exists()) {
520526
return;
521527
}
@@ -543,6 +549,53 @@ private void cleanUp() throws ExecutionFailedException {
543549
}
544550
}
545551

552+
/**
553+
* Check the lockfile lockversion to see if it is compatible with the used
554+
* npm version. If the lockfile is too old delete it.
555+
*/
556+
protected void verifyPackageLockAndClean() {
557+
File packageLockFile = packageUpdater.getPackageLockFile();
558+
if (!options.isEnablePnpm() && packageLockFile.exists()) {
559+
boolean removeLockfile = false;
560+
try (BufferedReader br = new BufferedReader(
561+
new FileReader(packageLockFile))) {
562+
String line;
563+
while ((line = br.readLine()) != null) {
564+
if (line.contains("\"lockfileVersion\"")) {
565+
int lockfileVersion = getLockfileVersion(line);
566+
removeLockfile = lockfileVersion != 3;
567+
break;
568+
}
569+
}
570+
} catch (IOException e) {
571+
// NO-OP
572+
packageUpdater.log()
573+
.debug("Failed to read the package-lock.json file.", e);
574+
}
575+
if (removeLockfile) {
576+
packageUpdater.log().info(
577+
"Removing package-lock.json as it has the wrong lockfileVersion.");
578+
try {
579+
FileUtils.delete(packageLockFile);
580+
} catch (IOException e) {
581+
// NO-OP
582+
packageUpdater.log().warn(
583+
"Exception handling the package-lock.json file.",
584+
e);
585+
}
586+
}
587+
}
588+
}
589+
590+
private static int getLockfileVersion(String line) {
591+
Matcher matcher = Pattern.compile("\"lockfileVersion\"\\s*:\\s*(\\d+)")
592+
.matcher(line);
593+
if (matcher.find()) {
594+
return Integer.parseInt(matcher.group(1));
595+
}
596+
return -1;
597+
}
598+
546599
private void deleteNodeModules(File nodeModulesFolder)
547600
throws ExecutionFailedException {
548601
try {

flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunNpmInstallTest.java

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,4 +590,133 @@ void deleteDirectory(File dir) throws IOException {
590590
.map(Path::toFile).forEach(File::delete);
591591
}
592592

593+
@Test
594+
public void verifyPackageLockAndClean_lockfileVersion3_fileNotRemoved()
595+
throws IOException {
596+
File packageLockFile = new File(npmFolder, "package-lock.json");
597+
String packageLockContent = """
598+
{
599+
"name": "test-project",
600+
"version": "1.0.0",
601+
"lockfileVersion": 3,
602+
"requires": true,
603+
"packages": {}
604+
}
605+
""";
606+
FileUtils.write(packageLockFile, packageLockContent,
607+
StandardCharsets.UTF_8);
608+
609+
task.verifyPackageLockAndClean();
610+
611+
Assert.assertTrue(
612+
"package-lock.json with version 3 should not be removed",
613+
packageLockFile.exists());
614+
}
615+
616+
@Test
617+
public void verifyPackageLockAndClean_lockfileVersion2_fileRemoved()
618+
throws IOException {
619+
File packageLockFile = new File(npmFolder, "package-lock.json");
620+
String packageLockContent = """
621+
{
622+
"name": "test-project",
623+
"version": "1.0.0",
624+
"lockfileVersion": 2,
625+
"requires": true,
626+
"packages": {}
627+
}
628+
""";
629+
FileUtils.write(packageLockFile, packageLockContent,
630+
StandardCharsets.UTF_8);
631+
632+
task.verifyPackageLockAndClean();
633+
634+
Assert.assertFalse("package-lock.json with version 2 should be removed",
635+
packageLockFile.exists());
636+
}
637+
638+
@Test
639+
public void verifyPackageLockAndClean_lockfileVersion1_fileRemoved()
640+
throws IOException {
641+
File packageLockFile = new File(npmFolder, "package-lock.json");
642+
String packageLockContent = """
643+
{
644+
"name": "test-project",
645+
"version": "1.0.0",
646+
"lockfileVersion": 1,
647+
"requires": true,
648+
"dependencies": {}
649+
}
650+
""";
651+
FileUtils.write(packageLockFile, packageLockContent,
652+
StandardCharsets.UTF_8);
653+
654+
task.verifyPackageLockAndClean();
655+
656+
Assert.assertFalse("package-lock.json with version 1 should be removed",
657+
packageLockFile.exists());
658+
}
659+
660+
@Test
661+
public void verifyPackageLockAndClean_withSpaces_correctlyParsed()
662+
throws IOException {
663+
File packageLockFile = new File(npmFolder, "package-lock.json");
664+
String packageLockContent = """
665+
{
666+
"name": "test-project",
667+
"version": "1.0.0",
668+
"lockfileVersion" : 3,
669+
"requires": true,
670+
"packages": {}
671+
}
672+
""";
673+
FileUtils.write(packageLockFile, packageLockContent,
674+
StandardCharsets.UTF_8);
675+
676+
task.verifyPackageLockAndClean();
677+
678+
Assert.assertTrue(
679+
"package-lock.json with version 3 (with spaces) should not be removed",
680+
packageLockFile.exists());
681+
}
682+
683+
@Test
684+
public void verifyPackageLockAndClean_pnpmEnabled_fileNotChecked()
685+
throws IOException {
686+
options.withEnablePnpm(true);
687+
task = createTask(new ArrayList<>());
688+
689+
File packageLockFile = new File(npmFolder, "package-lock.json");
690+
String packageLockContent = """
691+
{
692+
"name": "test-project",
693+
"version": "1.0.0",
694+
"lockfileVersion": 2,
695+
"requires": true,
696+
"packages": {}
697+
}
698+
""";
699+
FileUtils.write(packageLockFile, packageLockContent,
700+
StandardCharsets.UTF_8);
701+
702+
task.verifyPackageLockAndClean();
703+
704+
Assert.assertTrue(
705+
"package-lock.json should not be checked when pnpm is enabled",
706+
packageLockFile.exists());
707+
}
708+
709+
@Test
710+
public void verifyPackageLockAndClean_noLockfile_doesNotThrow() {
711+
File packageLockFile = new File(npmFolder, "package-lock.json");
712+
Assert.assertFalse("package-lock.json should not exist",
713+
packageLockFile.exists());
714+
715+
// Should not throw any exception
716+
task.verifyPackageLockAndClean();
717+
718+
Assert.assertFalse("package-lock.json should still not exist",
719+
packageLockFile.exists());
720+
}
721+
593722
}

0 commit comments

Comments
 (0)