|
1 | 1 | package com.github.eirslett.maven.plugins.frontend.lib;
|
2 | 2 |
|
3 | 3 | import com.fasterxml.jackson.databind.ObjectMapper;
|
4 |
| -import java.io.EOFException; |
5 |
| -import java.io.File; |
6 |
| -import java.io.IOException; |
7 |
| -import java.nio.file.Files; |
8 |
| -import java.util.Arrays; |
9 |
| -import java.util.HashMap; |
10 | 4 | import org.apache.commons.io.FileUtils;
|
11 | 5 | import org.slf4j.Logger;
|
12 | 6 | import org.slf4j.LoggerFactory;
|
13 | 7 |
|
| 8 | +import java.io.*; |
| 9 | +import java.nio.file.Files; |
| 10 | +import java.nio.file.Path; |
| 11 | +import java.util.HashMap; |
| 12 | + |
14 | 13 | public class PnpmInstaller {
|
15 | 14 |
|
16 | 15 | private static final String VERSION = "version";
|
@@ -69,7 +68,12 @@ public void install() throws InstallationException {
|
69 | 68 | if (!pnpmIsAlreadyInstalled()) {
|
70 | 69 | installPnpm();
|
71 | 70 | }
|
72 |
| - copyPnpmScripts(); |
| 71 | + |
| 72 | + if (this.config.getPlatform().isWindows()) { |
| 73 | + linkExecutableWindows(); |
| 74 | + } else { |
| 75 | + linkExecutable(); |
| 76 | + } |
73 | 77 | }
|
74 | 78 | }
|
75 | 79 |
|
@@ -169,42 +173,72 @@ private void installPnpm() throws InstallationException {
|
169 | 173 | }
|
170 | 174 | }
|
171 | 175 |
|
172 |
| - private void copyPnpmScripts() throws InstallationException{ |
173 |
| - File installDirectory = getNodeInstallDirectory(); |
174 |
| - |
175 |
| - File nodeModulesDirectory = new File(installDirectory, "node_modules"); |
176 |
| - File pnpmDirectory = new File(nodeModulesDirectory, "pnpm"); |
177 |
| - // create a copy of the pnpm scripts next to the node executable |
178 |
| - for (String script : Arrays.asList("pnpm", "pnpm.cmd")) { |
179 |
| - File scriptFile = new File(pnpmDirectory, "bin" + File.separator + script); |
180 |
| - if (scriptFile.exists()) { |
181 |
| - File copy = new File(installDirectory, script); |
182 |
| - if (!copy.exists()) { |
183 |
| - try |
184 |
| - { |
185 |
| - FileUtils.copyFile(scriptFile, copy); |
186 |
| - } |
187 |
| - catch (IOException e) |
188 |
| - { |
189 |
| - throw new InstallationException("Could not copy pnpm", e); |
190 |
| - } |
191 |
| - copy.setExecutable(true); |
192 |
| - } |
193 |
| - } |
| 176 | + private void linkExecutable() throws InstallationException{ |
| 177 | + File nodeInstallDirectory = getNodeInstallDirectory(); |
| 178 | + File pnpmExecutable = new File(nodeInstallDirectory, "pnpm"); |
| 179 | + |
| 180 | + if (pnpmExecutable.exists()) { |
| 181 | + this.logger.info("Existing pnpm executable found, skipping linking."); |
| 182 | + return; |
194 | 183 | }
|
195 |
| - // On non-windows platforms, if no predefined executables exist, symlink the .cjs executable |
196 |
| - File pnpmExecutable = new File(installDirectory, "pnpm"); |
197 |
| - if (!pnpmExecutable.exists() && !this.config.getPlatform().isWindows()) { |
198 |
| - |
199 |
| - File pnpmJsExecutable = new File(pnpmDirectory, "bin" + File.separator + "pnpm.cjs"); |
200 |
| - if (pnpmJsExecutable.exists()) { |
201 |
| - this.logger.info("No pnpm executable found, creating symlink to {}", pnpmJsExecutable.toPath()); |
202 |
| - try { |
203 |
| - Files.createSymbolicLink(pnpmExecutable.toPath(), pnpmJsExecutable.toPath()); |
204 |
| - } catch (IOException e) { |
205 |
| - throw new InstallationException("Could not copy pnpm", e); |
206 |
| - } |
207 |
| - } |
| 184 | + |
| 185 | + NodeExecutorConfig executorConfig = new InstallNodeExecutorConfig(this.config); |
| 186 | + File pnpmJsExecutable = executorConfig.getPnpmCjsPath(); |
| 187 | + |
| 188 | + if (!pnpmJsExecutable.exists()) { |
| 189 | + throw new InstallationException("Could not link to pnpm executable, no pnpm installation found."); |
| 190 | + } |
| 191 | + |
| 192 | + this.logger.info("No pnpm executable found, creating symbolic link to {}.", pnpmJsExecutable.toPath()); |
| 193 | + |
| 194 | + try { |
| 195 | + Files.createSymbolicLink(pnpmExecutable.toPath(), pnpmJsExecutable.toPath()); |
| 196 | + } catch (IOException e) { |
| 197 | + throw new InstallationException("Could not create symbolic link for pnpm executable.", e); |
| 198 | + } |
| 199 | + } |
| 200 | + |
| 201 | + private void linkExecutableWindows() throws InstallationException{ |
| 202 | + File nodeInstallDirectory = getNodeInstallDirectory(); |
| 203 | + File pnpmExecutable = new File(nodeInstallDirectory, "pnpm.cmd"); |
| 204 | + |
| 205 | + if (pnpmExecutable.exists()) { |
| 206 | + this.logger.info("Existing pnpm executable found, skipping linking."); |
| 207 | + return; |
| 208 | + } |
| 209 | + |
| 210 | + NodeExecutorConfig executorConfig = new InstallNodeExecutorConfig(this.config); |
| 211 | + File pnpmJsExecutable = executorConfig.getPnpmCjsPath(); |
| 212 | + |
| 213 | + if (!pnpmJsExecutable.exists()) { |
| 214 | + throw new InstallationException("Could not link to pnpm executable, no pnpm installation found."); |
| 215 | + } |
| 216 | + |
| 217 | + this.logger.info("No pnpm executable found, creating proxy script to {}.", pnpmJsExecutable.toPath()); |
| 218 | + |
| 219 | + Path nodePath = executorConfig.getNodePath().toPath(); |
| 220 | + Path relativeNodePath = nodeInstallDirectory.toPath().relativize(nodePath); |
| 221 | + Path relativePnpmPath = nodeInstallDirectory.toPath().relativize(pnpmJsExecutable.toPath()); |
| 222 | + |
| 223 | + // Create a script that will proxy any commands passed into it to the pnpm executable. |
| 224 | + String scriptContents = new StringBuilder() |
| 225 | + .append(":: Created by frontend-maven-plugin, please don't edit manually.\r\n") |
| 226 | + .append("@ECHO OFF\r\n") |
| 227 | + .append("\r\n") |
| 228 | + .append("SETLOCAL\r\n") |
| 229 | + .append("\r\n") |
| 230 | + .append(String.format("SET \"NODE_EXE=%%~dp0\\%s\"\r\n", relativeNodePath)) |
| 231 | + .append(String.format("SET \"PNPM_CLI_JS=%%~dp0\\%s\"\r\n", relativePnpmPath)) |
| 232 | + .append("\r\n") |
| 233 | + .append("\"%NODE_EXE%\" \"%PNPM_CLI_JS%\" %*") |
| 234 | + .toString(); |
| 235 | + |
| 236 | + try { |
| 237 | + BufferedWriter writer = new BufferedWriter(new FileWriter(pnpmExecutable)); |
| 238 | + writer.write(scriptContents); |
| 239 | + writer.close(); |
| 240 | + } catch (IOException e) { |
| 241 | + throw new InstallationException("Could not create proxy script for pnpm executable.", e); |
208 | 242 | }
|
209 | 243 | }
|
210 | 244 |
|
|
0 commit comments