diff --git a/README.md b/README.md
index b3b489c0f..83f795966 100644
--- a/README.md
+++ b/README.md
@@ -140,7 +140,7 @@ present).
Have a look at the example `POM` to see how it should be set up with Yarn:
https://github.com/eirslett/frontend-maven-plugin/blob/master/frontend-maven-plugin/src/it/yarn-integration/pom.xml
-
+For standard default node and yarn location
```xml
...
@@ -165,6 +165,16 @@ https://github.com/eirslett/frontend-maven-plugin/blob/master/frontend-maven-plu
```
+To specify a custom yarn dist tar ball location:
+```xml
+ https://repository.xyz.com/content/repositories/public/yarn/
+ 1.17.3
+ tgz
+```
+Then the program will look for a tar file at:
+```/yarn-.tgz```, which translates to
+```https://repository.xyz.com/content/repositories/public/yarn/yarn-1.17.3.tgz```
+
### Running npm
All node packaged modules will be installed in the `node_modules` folder in your [working directory](#working-directory).
diff --git a/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java b/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java
index daae17c79..4c1cb921a 100644
--- a/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java
+++ b/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java
@@ -31,6 +31,14 @@ public final class InstallNodeAndYarnMojo extends AbstractFrontendMojo {
defaultValue = YarnInstaller.DEFAULT_YARN_DOWNLOAD_ROOT)
private String yarnDownloadRoot;
+ /**
+ * Full path minus version to download Yarn binary from. No default. Ends with slash.
+ * Example: https://a-host.a-domain/blah/blah/-/ of https://a-host.a-domain/blah/blah/-/yarn-1.17.3.tgz
+ */
+ @Parameter(property = "yarnDownloadUrl", required = false,
+ defaultValue = "")
+ private String yarnDownloadUrl;
+
/**
* The version of Node.js to install. IMPORTANT! Most Node.js version names start with 'v', for example
* 'v0.10.18'
@@ -44,6 +52,12 @@ public final class InstallNodeAndYarnMojo extends AbstractFrontendMojo {
@Parameter(property = "yarnVersion", required = true)
private String yarnVersion;
+ /**
+ * The tarball extension of Yarn to install, something like tgz, tar.gz, etc.
+ */
+ @Parameter(property = "yarnExtension", required = false, defaultValue = "")
+ private String yarnExtension;
+
/**
* Server Id for download username and password
*/
@@ -81,8 +95,13 @@ public void execute(FrontendPluginFactory factory) throws InstallationException
} else {
factory.getNodeInstaller(proxyConfig).setNodeDownloadRoot(this.nodeDownloadRoot)
.setNodeVersion(this.nodeVersion).install();
- factory.getYarnInstaller(proxyConfig).setYarnDownloadRoot(this.yarnDownloadRoot)
- .setYarnVersion(this.yarnVersion).install();
+ if (this.yarnDownloadUrl != null && !this.yarnDownloadUrl.isEmpty()) {
+ factory.getYarnInstaller(proxyConfig).setYarnVersion(this.yarnVersion)
+ .install(this.yarnDownloadUrl, this.yarnExtension);
+ } else {
+ factory.getYarnInstaller(proxyConfig).setYarnDownloadRoot(this.yarnDownloadRoot)
+ .setYarnVersion(this.yarnVersion).install();
+ }
}
}
diff --git a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java
index 532439fb2..c6e4234c4 100644
--- a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java
+++ b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java
@@ -73,6 +73,21 @@ public void install() throws InstallationException {
}
}
+ public void install(String yarnDownloadUrl, String yarnExtension) throws InstallationException {
+ if (yarnVersion == null || yarnVersion.isEmpty()) {
+ throw new InstallationException("yarnVersion has to be provided.");
+ }
+ if (yarnExtension == null || yarnExtension.isEmpty()) {
+ throw new InstallationException("yarnExtension has to be provided.");
+ }
+ // use static lock object for a synchronized block
+ synchronized (LOCK) {
+ if (!yarnIsAlreadyInstalled()) {
+ installYarn(yarnDownloadUrl, yarnVersion, yarnExtension);
+ }
+ }
+ }
+
private boolean yarnIsAlreadyInstalled() {
try {
YarnExecutorConfig executorConfig = new InstallYarnExecutorConfig(config);
@@ -97,15 +112,27 @@ private boolean yarnIsAlreadyInstalled() {
}
private void installYarn() throws InstallationException {
+ String downloadUrl = yarnDownloadRoot + yarnVersion;
+ String defaultYarnExtension = "tar.gz";
+
+ try {
+ File installDirectory = getInstallDirectory();
+ ensureCorrectYarnRootDirectory(installDirectory, yarnVersion);
+ } catch (IOException e) {
+ throw new InstallationException("Could not extract the Yarn archive", e);
+ }
+
+ installYarn(downloadUrl, yarnVersion, defaultYarnExtension);
+ }
+
+ private void installYarn(String yarnDownloadUrl, String yarnVersion, String yarnExtension) throws InstallationException {
try {
logger.info("Installing Yarn version {}", yarnVersion);
- String downloadUrl = yarnDownloadRoot + yarnVersion;
- String extension = "tar.gz";
- String fileending = "/yarn-" + yarnVersion + "." + extension;
+ String fileEnding = "/yarn-" + yarnVersion + "." + yarnExtension;
- downloadUrl += fileending;
+ String downloadUrl = yarnDownloadUrl + fileEnding;
- CacheDescriptor cacheDescriptor = new CacheDescriptor("yarn", yarnVersion, extension);
+ CacheDescriptor cacheDescriptor = new CacheDescriptor("yarn", yarnVersion, yarnExtension);
File archive = config.getCacheResolver().resolve(cacheDescriptor);
@@ -141,8 +168,6 @@ private void installYarn() throws InstallationException {
throw e;
}
- ensureCorrectYarnRootDirectory(installDirectory, yarnVersion);
-
logger.info("Installed Yarn locally.");
} catch (DownloadException e) {
throw new InstallationException("Could not download Yarn", e);
@@ -160,9 +185,45 @@ private File getInstallDirectory() {
return installDirectory;
}
- private void extractFile(File archive, File destinationDirectory) throws ArchiveExtractionException {
+ private File getDistDirectory(File destinationDirectory) throws IOException {
+ File distDirectory = new File(destinationDirectory, "dist");
+ if (distDirectory.exists()) {
+ try {
+ FileUtils.deleteDirectory(distDirectory);
+ } catch (IOException e) {
+ throw new IOException("Could not clean up existing dist directory: " + distDirectory.getName());
+ }
+ }
+ logger.info("Creating directory {}", distDirectory);
+ distDirectory.mkdir();
+ return distDirectory;
+ }
+
+ private void copyToDist(File destinationDirectory) throws IOException {
+ // Copying installed /node/yarn/yarn- to /node/yarn/dist for execution path.
+ // See this: https://github.com/eirslett/frontend-maven-plugin/issues/647
+ File versionedDirectory = new File(destinationDirectory, "yarn-" +
+ (yarnVersion.startsWith("v") ? "" : "v") +
+ yarnVersion);
+ File distDirectory = getDistDirectory(destinationDirectory);
+
+ if (versionedDirectory.exists()) {
+ try {
+ logger.info("Copying {} to {}", versionedDirectory, distDirectory);
+ FileUtils.copyDirectory(versionedDirectory, distDirectory, true);
+ File distYarn = new File(distDirectory, "bin/yarn");
+ distYarn.setExecutable(true);
+ } catch (IOException e) {
+ logger.error("Failed to copy from {} to {}.", versionedDirectory, distDirectory);
+ }
+ }
+ }
+
+ private void extractFile(File archive, File destinationDirectory) throws ArchiveExtractionException, IOException {
logger.info("Unpacking {} into {}", archive, destinationDirectory);
archiveExtractor.extract(archive.getPath(), destinationDirectory.getPath());
+ copyToDist(destinationDirectory);
+
}
private void ensureCorrectYarnRootDirectory(File installDirectory, String yarnVersion) throws IOException {