Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add support for npmrc #727

Merged
merged 9 commits into from
Nov 2, 2020
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
* Added support to npm-based steps for picking up `.npmrc` files ([#727](https://github.com/diffplug/spotless/pull/727))

## [2.9.0] - 2020-10-20
### Added
Expand Down
26 changes: 26 additions & 0 deletions gradle/spotless-freshmark.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@

import java.util.regex.Matcher
import java.util.regex.Pattern


def thisVm() {
String jre = System.getProperty("java.version")
if (jre.startsWith("1.8")) {
return 8
} else {
Matcher matcher = Pattern.compile("(\\d+)").matcher(jre)
if (!matcher.find()) {
throw new IllegalArgumentException("Expected " + jre + " to start with an integer")
}
int version = Integer.parseInt(matcher.group(1))
if (version <= 8) {
throw new IllegalArgumentException("Expected " + jre + " to start with an integer greater than 8")
}
return version
}
}

if (thisVm() >= 15) {
// freshmark doesn't run on JRE 15+
return
}

apply plugin: 'com.diffplug.spotless'

import com.diffplug.gradle.spotless.FreshMarkExtension
Expand Down
215 changes: 215 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/npm/FileFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/*
* Copyright 2020 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.npm;

import static java.util.Objects.requireNonNull;

import java.io.File;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

class FileFinder {

private final List<Supplier<Optional<File>>> fileCandidateFinders;

private FileFinder(Builder builder) {
this.fileCandidateFinders = Collections.unmodifiableList(new ArrayList<>(builder.candidateFinders));
}

static Builder finderForFilename(String fileName) {
return new Builder(fileName, null);
}

static Builder finderForExecutableFilename(String fileName) {
return new Builder(fileName, true);
}

Optional<File> tryFind() {
return fileCandidateFinders
.stream()
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
}

static class Builder {

private final String fileName;

private final Boolean executable;

private final List<Supplier<Optional<File>>> candidateFinders = new ArrayList<>();

Builder(String fileName, Boolean executable) {
this.fileName = requireNonNull(fileName);
this.executable = executable;
}

public Builder candidateEnvironmentPath(String environmentVar) {
candidateFinders.add(new CandidateOnSinglePathEnvironmentVar(environmentVar, fileName, FileIsExecutableFilter.executable(this.executable)));
return this;
}

public Builder candidateEnvironmentPathList(String environmentVar, Function<File, File> fileTransformer) {
candidateFinders.add(new CandidateOnPathListEnvironmentVar(environmentVar, fileName, fileTransformer, FileIsExecutableFilter.executable(this.executable)));
return this;
}

public Builder candidateSystemProperty(String systemProperty) {
candidateFinders.add(new CandidateOnSystemPropertyVar(systemProperty, FileIsExecutableFilter.executable(this.executable)));
return this;
}

public Builder candidateFileInFolder(File folder) {
candidateFinders.add(new CandidateInFolder(folder, fileName, FileIsExecutableFilter.executable(this.executable)));
return this;
}

public FileFinder build() {
return new FileFinder(this);
}
}

private static class FileIsExecutableFilter implements Predicate<File> {
@Override
public boolean test(File file) {
return file.canExecute();
}

static Predicate<File> executable() {
return new FileIsExecutableFilter();
}

static Predicate<File> executable(Boolean executable) {
if (executable == null) {
return AnyFileFilter.any();
}
if (executable) {
return executable();
}
// !executable
return executable().negate();
}
}

private static class AnyFileFilter implements Predicate<File> {

@Override
public boolean test(File file) {
return true;
}

static AnyFileFilter any() {
return new AnyFileFilter();
}
}

private static class CandidateOnSinglePathEnvironmentVar implements Supplier<Optional<File>> {
private final String environmentVar;
private final String fileName;
private final Predicate<File> additionalFilters;

public CandidateOnSinglePathEnvironmentVar(String environmentVar, String fileName, Predicate<File> additionalFilter) {
this.environmentVar = environmentVar;
this.fileName = fileName;
this.additionalFilters = additionalFilter == null ? AnyFileFilter.any() : additionalFilter;
}

@Override
public Optional<File> get() {
return Optional.ofNullable(environmentVar)
.map(File::new)
.map(file -> new File(file, fileName))
.filter(File::exists)
.filter(additionalFilters);
}
}

private static class CandidateOnPathListEnvironmentVar implements Supplier<Optional<File>> {
private final String environmentVar;
private final String fileName;
private final Function<File, File> fileTransformer;
private final Predicate<File> additionalFilter;

public CandidateOnPathListEnvironmentVar(String environmentVar, String fileName, Function<File, File> fileTransformer, Predicate<File> additionalFilter) {
this.environmentVar = environmentVar;
this.fileName = fileName;
this.fileTransformer = fileTransformer;
this.additionalFilter = additionalFilter;
}

@Override
public Optional<File> get() {
String pathList = System.getenv(environmentVar);
if (pathList != null) {
return Arrays.stream(pathList.split(System.getProperty("path.separator", ":")))
.map(File::new)
.filter(File::exists)
.map(fileTransformer)
.map(dir -> new File(dir, fileName))
.filter(File::exists)
.filter(additionalFilter)
.findFirst();
}
return Optional.empty();
}
}

private static class CandidateOnSystemPropertyVar implements Supplier<Optional<File>> {
private final String systemProperty;
private final Predicate<File> additionalFilter;

public CandidateOnSystemPropertyVar(String systemProperty, Predicate<File> additionalFilter) {
this.systemProperty = systemProperty;
this.additionalFilter = additionalFilter == null ? AnyFileFilter.any() : additionalFilter;

}

@Override
public Optional<File> get() {
return Optional.ofNullable(System.getProperty(this.systemProperty))
.map(File::new)
.filter(File::exists)
.filter(additionalFilter);
}
}

private static class CandidateInFolder implements Supplier<Optional<File>> {

private final File folder;
private final String fileName;
private final Predicate<File> additionalFilter;

public CandidateInFolder(File folder, String fileName, Predicate<File> additionalFilter) {
this.folder = folder;
this.fileName = fileName;
this.additionalFilter = additionalFilter == null ? AnyFileFilter.any() : additionalFilter;
}

@Override
public Optional<File> get() {
return Optional.of(folder)
.filter(File::exists)
.filter(File::isDirectory)
.map(folder -> new File(folder, fileName))
.filter(File::exists)
.filter(additionalFilter);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ class NodeServerLayout {
private final File nodeModulesDir;
private final File packageJsonFile;
private final File serveJsFile;
private final File npmrcFile;

NodeServerLayout(File buildDir, String stepName) {
this.nodeModulesDir = new File(buildDir, "spotless-node-modules-" + stepName);
this.packageJsonFile = new File(nodeModulesDir, "package.json");
this.serveJsFile = new File(nodeModulesDir, "serve.js");
this.npmrcFile = new File(nodeModulesDir, ".npmrc");
}

File nodeModulesDir() {
Expand All @@ -40,4 +42,8 @@ File packageJsonFile() {
File serveJsFile() {
return serveJsFile;
}

public File npmrcFile() {
return npmrcFile;
}
}
11 changes: 9 additions & 2 deletions lib/src/main/java/com/diffplug/spotless/npm/NpmConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@

class NpmConfig implements Serializable {

private static final long serialVersionUID = -7660089232952131272L;
private static final long serialVersionUID = 684264546497914877L;

private final String packageJsonContent;

private final String npmModule;

private final String serveScriptContent;

public NpmConfig(String packageJsonContent, String npmModule, String serveScriptContent) {
private final String npmrcContent;

public NpmConfig(String packageJsonContent, String npmModule, String serveScriptContent, String npmrcContent) {
this.packageJsonContent = packageJsonContent;
this.npmModule = npmModule;
this.serveScriptContent = serveScriptContent;
this.npmrcContent = npmrcContent;
}

public String getPackageJsonContent() {
Expand All @@ -47,4 +50,8 @@ public String getNpmModule() {
public String getServeScriptContent() {
return serveScriptContent;
}

public String getNpmrcContent() {
return npmrcContent;
}
}
Loading