Skip to content

Commit 8187042

Browse files
committed
fix: allow online-npm-install if prefer-offline fails
This resolves diffplug#1750
1 parent ca4136e commit 8187042

File tree

5 files changed

+67
-10
lines changed

5 files changed

+67
-10
lines changed

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
*/
1616
package com.diffplug.spotless.npm;
1717

18+
import static com.diffplug.spotless.npm.NpmProcessFactory.OnlinePreferrence.PREFER_OFFLINE;
19+
import static com.diffplug.spotless.npm.NpmProcessFactory.OnlinePreferrence.PREFER_ONLINE;
20+
1821
import java.util.Objects;
1922

2023
import javax.annotation.Nonnull;
2124

2225
import org.slf4j.Logger;
2326
import org.slf4j.LoggerFactory;
2427

28+
import com.diffplug.spotless.ProcessRunner;
29+
2530
public class NodeApp {
2631

2732
private static final Logger logger = LoggerFactory.getLogger(NodeApp.class);
@@ -83,6 +88,28 @@ void prepareNodeAppLayout() {
8388

8489
void npmInstall() {
8590
timedLogger.withInfo("Installing npm dependencies for {} with {}.", this.nodeServerLayout, this.npmProcessFactory.describe())
86-
.run(() -> npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations).waitFor());
91+
.run(this::optimizedNpmInstall);
92+
}
93+
94+
private void optimizedNpmInstall() {
95+
try {
96+
npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, PREFER_OFFLINE).waitFor();
97+
} catch (NpmProcessException e) {
98+
if (!offlineInstallFailed(e.getResult())) {
99+
throw e; // pass through
100+
}
101+
// if the npm install fails with message "No matching version found for <package>@<version>", we try again without the offline flag
102+
npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, PREFER_ONLINE).waitFor();
103+
}
104+
}
105+
106+
private boolean offlineInstallFailed(ProcessRunner.Result result) {
107+
if (result == null) {
108+
return false; // no result, something else must have happened
109+
}
110+
if (result.exitCode() == 0) {
111+
return false; // all is well
112+
}
113+
return result.stdOutUtf8().contains("code ETARGET") && result.stdOutUtf8().contains("No matching version found for"); // offline install failed, needs online install
87114
}
88115
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public static NodeModulesCachingNpmProcessFactory create(@Nonnull File cacheDir)
5858
}
5959

6060
@Override
61-
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations) {
62-
NpmProcess actualNpmInstallProcess = StandardNpmProcessFactory.INSTANCE.createNpmInstallProcess(nodeServerLayout, formatterStepLocations);
61+
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
62+
NpmProcess actualNpmInstallProcess = StandardNpmProcessFactory.INSTANCE.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, onlinePreferrence);
6363
return new CachingNmpInstall(actualNpmInstallProcess, nodeServerLayout);
6464
}
6565

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,26 @@
1515
*/
1616
package com.diffplug.spotless.npm;
1717

18+
import javax.annotation.CheckForNull;
19+
20+
import com.diffplug.spotless.ProcessRunner;
21+
1822
public class NpmProcessException extends RuntimeException {
1923
private static final long serialVersionUID = 6424331316676759525L;
24+
private final ProcessRunner.Result result;
2025

21-
public NpmProcessException(String message) {
26+
public NpmProcessException(String message, ProcessRunner.Result result) {
2227
super(message);
28+
this.result = result;
2329
}
2430

2531
public NpmProcessException(String message, Throwable cause) {
2632
super(message, cause);
33+
this.result = null;
34+
}
35+
36+
@CheckForNull
37+
public ProcessRunner.Result getResult() {
38+
return result;
2739
}
2840
}

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,22 @@
1616
package com.diffplug.spotless.npm;
1717

1818
public interface NpmProcessFactory {
19-
NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations);
19+
20+
enum OnlinePreferrence {
21+
PREFER_OFFLINE("--prefer-offline"), PREFER_ONLINE("--prefer-online");
22+
23+
private final String option;
24+
25+
OnlinePreferrence(String option) {
26+
this.option = option;
27+
}
28+
29+
public String option() {
30+
return option;
31+
}
32+
}
33+
34+
NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence);
2035

2136
NpmLongRunningProcess createNpmServeProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations);
2237

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ private StandardNpmProcessFactory() {
3232
}
3333

3434
@Override
35-
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations) {
36-
return new NpmInstall(nodeServerLayout.nodeModulesDir(), formatterStepLocations);
35+
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
36+
return new NpmInstall(nodeServerLayout.nodeModulesDir(), formatterStepLocations, onlinePreferrence);
3737
}
3838

3939
@Override
@@ -80,8 +80,11 @@ public String doDescribe() {
8080

8181
private static class NpmInstall extends AbstractStandardNpmProcess implements NpmProcess {
8282

83-
public NpmInstall(File workingDir, NpmFormatterStepLocations formatterStepLocations) {
83+
private final OnlinePreferrence onlinePreferrence;
84+
85+
public NpmInstall(File workingDir, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
8486
super(workingDir, formatterStepLocations);
87+
this.onlinePreferrence = onlinePreferrence;
8588
}
8689

8790
@Override
@@ -91,7 +94,7 @@ protected List<String> commandLine() {
9194
"install",
9295
"--no-audit",
9396
"--no-fund",
94-
"--prefer-offline");
97+
onlinePreferrence.option());
9598
}
9699

97100
@Override
@@ -103,7 +106,7 @@ public String describe() {
103106
public ProcessRunner.Result waitFor() {
104107
try (ProcessRunner.LongRunningProcess npmProcess = doStart()) {
105108
if (npmProcess.waitFor() != 0) {
106-
throw new NpmProcessException("Running npm command '" + describe() + "' failed with exit code: " + npmProcess.exitValue() + "\n\n" + npmProcess.result());
109+
throw new NpmProcessException("Running npm command '" + describe() + "' failed with exit code: " + npmProcess.exitValue() + "\n\n" + npmProcess.result(), npmProcess.result());
107110
}
108111
return npmProcess.result();
109112
} catch (InterruptedException e) {

0 commit comments

Comments
 (0)