|
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