Skip to content

Commit 8815367

Browse files
committed
chore: make sure to calculate different hashes if serve-files change
this was a hidden update issue: if we change the serve-script content between two releases but the user keeps the package.json the same, the md5 hash used for the node-modules-dir stayed the same, resulting in us not using the latest version of the serve script but keep using the old one. That was especially harmful in the case where we changed the api of the serve-script to accept a uuid to allow multiple instances. The old script just ignored that resulting in a server-process that was never found due to wrong port-file-names written/waited for.
1 parent c93a158 commit 8815367

File tree

5 files changed

+55
-9
lines changed

5 files changed

+55
-9
lines changed

lib/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ dependencies {
7676
testCommonImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT"
7777
testCommonImplementation "org.assertj:assertj-core:$VER_ASSERTJ"
7878
testCommonImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN"
79+
testCommonImplementation projects.testlib
7980
testCommonRuntimeOnly "org.junit.platform:junit-platform-launcher"
8081

8182
// GLUE CODE (alphabetic order please)

lib/src/main/java/com/diffplug/spotless/npm/NodeServerLayout.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 DiffPlug
2+
* Copyright 2020-2025 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,16 +37,16 @@ class NodeServerLayout {
3737
private final File serveJsFile;
3838
private final File npmrcFile;
3939

40-
NodeServerLayout(File buildDir, String packageJsonContent) {
41-
this.nodeModulesDir = new File(buildDir, nodeModulesDirName(packageJsonContent));
40+
NodeServerLayout(File buildDir, String packageJsonContent, String serveJsContent) {
41+
this.nodeModulesDir = new File(buildDir, nodeModulesDirName(packageJsonContent, serveJsContent));
4242
this.packageJsonFile = new File(nodeModulesDir, "package.json");
4343
this.packageLockJsonFile = new File(nodeModulesDir, "package-lock.json");
4444
this.serveJsFile = new File(nodeModulesDir, "serve.js");
4545
this.npmrcFile = new File(nodeModulesDir, ".npmrc");
4646
}
4747

48-
private static String nodeModulesDirName(String packageJsonContent) {
49-
String md5Hash = NpmResourceHelper.md5(packageJsonContent);
48+
private static String nodeModulesDirName(String packageJsonContent, String serveJsContent) {
49+
String md5Hash = NpmResourceHelper.md5(packageJsonContent, serveJsContent);
5050
Matcher matcher = PACKAGE_JSON_NAME_PATTERN.matcher(packageJsonContent);
5151
if (!matcher.find()) {
5252
throw new IllegalArgumentException("package.json must contain a name property");

lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepStateBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public static class Runtime {
7171

7272
Runtime(NpmFormatterStepStateBase parent) {
7373
this.parent = parent;
74-
this.nodeServerLayout = new NodeServerLayout(parent.locations.buildDir(), parent.npmConfig.getPackageJsonContent());
74+
this.nodeServerLayout = new NodeServerLayout(parent.locations.buildDir(), parent.npmConfig.getPackageJsonContent(), parent.npmConfig.getServeScriptContent());
7575
this.nodeServeApp = new NodeServeApp(nodeServerLayout, parent.npmConfig, parent.locations);
7676
}
7777

lib/src/main/java/com/diffplug/spotless/npm/NpmResourceHelper.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2023 DiffPlug
2+
* Copyright 2016-2025 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
2727
import java.util.Objects;
2828
import java.util.concurrent.TimeoutException;
2929
import java.util.stream.Collectors;
30+
import java.util.stream.Stream;
3031

3132
import com.diffplug.spotless.ThrowingEx;
3233

@@ -140,9 +141,15 @@ static String md5(File file) {
140141
return md5(readUtf8StringFromFile(file));
141142
}
142143

143-
static String md5(String fileContent) {
144+
static String md5(String fileContent, String... additionalFileContents) {
145+
Objects.requireNonNull(fileContent, "fileContent must not be null");
146+
Stream<String> additionalFilecontentStream = Stream.concat(
147+
Stream.of(fileContent),
148+
Stream.of(additionalFileContents));
144149
MessageDigest md = ThrowingEx.get(() -> MessageDigest.getInstance("MD5"));
145-
md.update(fileContent.getBytes(StandardCharsets.UTF_8));
150+
String stringToHash = additionalFilecontentStream.collect(Collectors.joining("@@@"));
151+
md.update(stringToHash.getBytes(StandardCharsets.UTF_8));
152+
146153
byte[] digest = md.digest();
147154
// convert byte array digest to hex string
148155
StringBuilder sb = new StringBuilder();
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2025 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.npm;
17+
18+
import static com.diffplug.selfie.Selfie.expectSelfie;
19+
20+
import org.junit.jupiter.api.Test;
21+
22+
class NpmResourceHelperTest {
23+
24+
@Test
25+
void itCalculatesMd5ForSingleString() {
26+
String input = "Hello, World!";
27+
28+
expectSelfie(NpmResourceHelper.md5(input)).toBe("65a8e27d8879283831b664bd8b7f0ad4");
29+
}
30+
31+
@Test
32+
void itCalculatesMd5ForMultipleStrings() {
33+
String input1 = "Hello, World!";
34+
String input2 = "Hello, Spencer!";
35+
36+
expectSelfie(NpmResourceHelper.md5(input1, input2)).toBe("371ba0fbf3d73b33e71b4af8dc6afe00");
37+
}
38+
}

0 commit comments

Comments
 (0)