Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/release'
Browse files Browse the repository at this point in the history
* origin/release: (30 commits)
  Fix javadoc search interfering with anchor links
  Revert "Fix Javadoc anchors with new JDK 9 search bar"
  Allow `@Incremental` on fields
  Use sha-256 hashing to validate distribution dependencies
  Update release features for 5.4
  More improvements for incremental task documentation
  Further specify variants.files.name
  Correct version reference to use 1.0
  Remove repositories mirror and flags to avoid confusion
  Use HTTPS mirror in `JavaProcessStackTracesMonitorSpec`
  Dissallow `@Incremental` on fields
  Revert nullability changes to RelativePath
  Add output for up-to-date incremental build example
  Clean up user manual section on incremental tasks
  Ivy publishing resolved versions
  Update publishing of resolved version doc
  Move SHA1 hashing to `TestFile` and polish the test
  Revert "Use the `StackWalker` API in order to avoid creation of an exception"
  Use the `StackWalker` API in order to avoid creation of an exception
  Only check each repository once
  ...
  • Loading branch information
big-guy committed Apr 10, 2019
2 parents bcddb6a + efacce4 commit 589c8a0
Show file tree
Hide file tree
Showing 31 changed files with 1,561 additions and 738 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ plugins {
`java-base`
gradlebuild.`build-types`
gradlebuild.`ci-reporting`
gradlebuild.security
// TODO Apply this plugin in the BuildScanConfigurationPlugin once binary plugins can apply plugins via the new plugin DSL
// We have to apply it here at the moment, so that when the build scan plugin is auto-applied via --scan can detect that
// the plugin has been already applied. For that the plugin has to be applied with the new plugin DSL syntax.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright 2019 the original author or authors.
*
* 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 gradlebuild

import java.net.URI
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock

val lock = ReentrantLock()
val allowedSchemes = setOf("https")
val alreadyChecked = mutableSetOf<ArtifactRepository>()
val insecureRepos = mutableSetOf<InsecureRepository>()
val repoToSource = mutableMapOf<ArtifactRepository, String>()

allprojects {
repositories.whenObjectAdded {
Exception().stackTrace.forEachIndexed { idx, it ->
if (idx > 1 && !repoToSource.containsKey(this) && it.isBuildScript()) {
repoToSource.put(this, "${it.fileName}:${it.lineNumber} in ${it.className}")
}
}
}
val project = this
configurations.all {
incoming.beforeResolve {
repositories.checkRepositories(project)
}
}
afterEvaluate {
extensions.findByType(PublishingExtension::class.java)?.run {
repositories.checkRepositories(project)
}
}
}

gradle.buildFinished {
if (!insecureRepos.isEmpty()) {
val byProject = insecureRepos
.groupBy(InsecureRepository::projectPath)
.mapKeys {
"In project '${it.key}' :"
}.mapValues {
it.value.map { repo ->
val location = if (repo.location != null) {
"declared at ${repo.location}"
} else {
"(unknown location)"
}
" - Repository ${repo.repositoryName} : ${repo.url} $location"
}.joinToString("\n")
}
val detail = byProject.map {
val (key, value) = it
" * $key\n$value"
}.joinToString("\n")

throw GradleException("This build used insecure repositories:\n${detail}\n\nMake sure to use HTTPS")
}
}

fun RepositoryHandler.checkRepositories(project: Project) = forEach {
lock.withLock {
if (alreadyChecked.add(it)) {
if (it is MavenArtifactRepository) {
checkURLs(project, it, setOf(it.url))
checkURLs(project, it, it.artifactUrls)
} else if (it is IvyArtifactRepository) {
checkURLs(project, it, setOf(it.url))
}
}
}
}

fun checkURLs(project: Project, repository: ArtifactRepository, uris: Collection<URI>) = uris.forEach {
if (it.scheme.toLowerCase() !in allowedSchemes) {
insecureRepos.add(InsecureRepository(project.path, repository.name, it, repoToSource.get(repository)))
}
}

data class InsecureRepository(val projectPath: String, val repositoryName: String, val url: URI, val location: String?)

fun StackTraceElement.isBuildScript() = fileName != null && (fileName.endsWith(".gradle") || fileName.endsWith(".gradle.kts"))
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ public File getFile(File baseDir) {
return new File(baseDir, getPathString());
}

@Nullable
public String getLastName() {
if (segments.length > 0) {
return segments[segments.length - 1];
Expand Down Expand Up @@ -185,7 +184,6 @@ public String toString() {
*
* @return The parent of this path, or null if this is the root path.
*/
@Nullable
public RelativePath getParent() {
switch (segments.length) {
case 0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,20 @@ class IncrementalInputsIntegrationTest extends AbstractIncrementalTasksIntegrati
buildFile << """
class MyTask extends DefaultTask {
File inputOne
File inputTwo
@Incremental
@InputDirectory
File inputOne
File getInputOne() {
inputOne
}
@Incremental
@InputDirectory
File inputTwo
File getInputTwo() {
inputTwo
}
@OutputDirectory
File outputDirectory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@NonNullApi
Expand Down Expand Up @@ -84,6 +85,7 @@ void assertNoProblems() {
if (problems.size() == 1) {
message = String.format("A problem was found with the configuration of %s.", task);
} else {
Collections.sort(problems);
message = String.format("Some problems were found with the configuration of %s.", task);
}
throw new TaskValidationException(message, CollectionUtils.collect(problems, new Transformer<InvalidUserDataException, String>() {
Expand Down Expand Up @@ -111,5 +113,10 @@ public void visitErrorStrict(String message) {
}
problems.add(message);
}

@Override
public void visitErrorStrict(@Nullable String ownerPath, String propertyName, String message) {
visitErrorStrict(message);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.gradle.api.tasks.TaskValidationException;
import org.gradle.internal.file.ReservedFileSystemLocationRegistry;

import java.util.Collections;
import java.util.List;

/**
Expand Down Expand Up @@ -62,6 +63,7 @@ public TaskExecuterResult execute(TaskInternal task, TaskStateInternal state, Ta
}

private static void report(Task task, List<String> messages, TaskStateInternal state) {
Collections.sort(messages);
List<InvalidUserDataException> causes = Lists.newArrayListWithCapacity(messages.size());
for (String message : messages) {
causes.add(new InvalidUserDataException(message));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,31 @@ public DefaultParameterValidationContext(Collection<String> messages) {
this.messages = messages;
}

@Override
public void visitError(@Nullable String ownerPath, String propertyName, String message) {
private static String decorateMessage(@Nullable String ownerPath, String propertyName, String message) {
String decoratedMessage;
if (ownerPath == null) {
visitError("Property '" + propertyName + "' " + message + ".");
decoratedMessage = "Property '" + propertyName + "' " + message + ".";
} else {
visitError("Property '" + ownerPath + '.' + propertyName + "' " + message + ".");
decoratedMessage = "Property '" + ownerPath + '.' + propertyName + "' " + message + ".";
}
return decoratedMessage;
}

@Override
public void visitError(@Nullable String ownerPath, String propertyName, String message) {
visitError(decorateMessage(ownerPath, propertyName, message));
}

@Override
public void visitError(String message) {
messages.add(message);
}

@Override
public void visitErrorStrict(@Nullable String ownerPath, String propertyName, String message) {
visitErrorStrict(decorateMessage(ownerPath, propertyName, message));
}

@Override
public void visitErrorStrict(String message) {
visitError(message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.gradle.api.internal.tasks.properties;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -53,7 +54,6 @@
import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

public class DefaultTypeMetadataStore implements TypeMetadataStore {
Expand Down Expand Up @@ -84,12 +84,12 @@ public Class<? extends Annotation> apply(PropertyAnnotationHandler handler) {
});
this.typeAnnotationHandlers = typeAnnotationHandlers;
Multimap<Class<? extends Annotation>, Class<? extends Annotation>> annotationOverrides = collectAnnotationOverrides(annotationHandlers);
Set<Class<? extends Annotation>> relevantAnnotationTypes = collectRelevantAnnotationTypes(((Map<Class<? extends Annotation>, PropertyAnnotationHandler>) Maps.uniqueIndex(annotationHandlers, new Function<PropertyAnnotationHandler, Class<? extends Annotation>>() {
Set<Class<? extends Annotation>> relevantAnnotationTypes = collectRelevantAnnotationTypes(Collections2.transform(annotationHandlers, new Function<PropertyAnnotationHandler, Class<? extends Annotation>>() {
@Override
public Class<? extends Annotation> apply(PropertyAnnotationHandler handler) {
return handler.getAnnotationType();
}
})).keySet());
}));
String displayName = calculateDisplayName(annotationHandlers);
this.propertyExtractor = new PropertyExtractor(displayName, this.annotationHandlers.keySet(), relevantAnnotationTypes, annotationOverrides, otherKnownAnnotations, IGNORED_SUPER_CLASSES, IGNORED_METHODS);
this.cache = cacheFactory.newClassCache();
Expand All @@ -116,7 +116,7 @@ private static Multimap<Class<? extends Annotation>, Class<? extends Annotation>
return builder.build();
}

private static Set<Class<? extends Annotation>> collectRelevantAnnotationTypes(Set<Class<? extends Annotation>> propertyTypeAnnotations) {
private static Set<Class<? extends Annotation>> collectRelevantAnnotationTypes(Collection<Class<? extends Annotation>> propertyTypeAnnotations) {
return ImmutableSet.<Class<? extends Annotation>>builder()
.addAll(propertyTypeAnnotations)
.add(Optional.class)
Expand Down Expand Up @@ -178,6 +178,16 @@ public void collect(@Nullable String ownerPropertyPath, ParameterValidationConte
});
}

@Override
public void visitErrorStrict(@Nullable final String ownerPath, final String propertyName, final String message) {
builder.add(new ValidationProblem() {
@Override
public void collect(@Nullable String ownerPropertyPath, ParameterValidationContext validationContext) {
validationContext.visitErrorStrict(ownerPath, propertyName, message);
}
});
}

@Override
public void visitErrorStrict(final String message) {
builder.add(new ValidationProblem() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,22 +260,31 @@ public CollectingParameterValidationContext(Class<?> topLevelBean, ProblemCollec
this.problems = problems;
}

@Override
public void visitError(@Nullable String ownerPath, String propertyName, String message) {
private String decorateMessage(String propertyName, String message) {
String decoratedMessage;
if (Task.class.isAssignableFrom(topLevelBean)) {
decoratedMessage = String.format("Task type '%s': property '%s' %s.", topLevelBean.getName(), getQualifiedPropertyName(propertyName), message);
} else {
decoratedMessage = String.format("Type '%s': property '%s' %s.", topLevelBean.getName(), getQualifiedPropertyName(propertyName), message);
}
visitError(decoratedMessage);
return decoratedMessage;
}

@Override
public void visitError(@Nullable String ownerPath, String propertyName, String message) {
visitError(decorateMessage(propertyName, message));
}

@Override
public void visitError(String message) {
problems.error(message, false);
}

@Override
public void visitErrorStrict(@Nullable String ownerPath, String propertyName, String message) {
visitErrorStrict(decorateMessage(propertyName, message));
}

@Override
public void visitErrorStrict(String message) {
problems.error(message, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.gradle.api.tasks.Optional;
import org.gradle.internal.reflect.ParameterValidationContext;
import org.gradle.internal.reflect.PropertyMetadata;
import org.gradle.work.Incremental;

import java.io.File;
import java.lang.annotation.Annotation;
Expand Down Expand Up @@ -53,7 +54,11 @@ public void validatePropertyMetadata(PropertyMetadata propertyMetadata, Paramete
if (File.class.isAssignableFrom(valueType)
|| java.nio.file.Path.class.isAssignableFrom(valueType)
|| FileCollection.class.isAssignableFrom(valueType)) {
visitor.visitError(null, propertyMetadata.getPropertyName(), "has @Input annotation used on property of type " + valueType.getName());
visitor.visitError(null, propertyMetadata.getPropertyName(),
String.format("has @Input annotation used on property of type %s", valueType.getName()));
}
if (propertyMetadata.isAnnotationPresent(Incremental.class)) {
visitor.visitErrorStrict(null, propertyMetadata.getPropertyName(), "has @Incremental annotation used on an @Input property");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency
@PathSensitive(PathSensitivity.ABSOLUTE)
@InputFiles
ConfigurableFileCollection getAbsolutePathSensitivity()

@Incremental
@Input
String getIncrementalNonFileInput()
void setIncrementalNonFileInput(String value)
}

void transform(TransformOutputs outputs) {
Expand All @@ -215,17 +220,21 @@ class ArtifactTransformValuesInjectionIntegrationTest extends AbstractDependency
failure.assertThatDescription(matchesRegexp('Cannot isolate parameters MakeGreen\\$Parameters\\$Inject@.* of artifact transform MakeGreen'))
failure.assertHasCause('Some problems were found with the configuration of the artifact transform parameter MakeGreen.Parameters.')
assertPropertyValidationErrors(
absolutePathSensitivity: 'is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms',
extension: 'is not annotated with an input annotation',
outputDir: 'is annotated with unsupported annotation @OutputDirectory',
missingInput: 'does not have a value specified',
fileInput: [
'does not have a value specified',
'has @Input annotation used on property of type java.io.File',
'does not have a value specified'
],
absolutePathSensitivity: 'is declared to be sensitive to absolute paths. This is not allowed for cacheable transforms',
incrementalNonFileInput: [
'does not have a value specified',
'has @Incremental annotation used on an @Input property',
],
missingInput: 'does not have a value specified',
noPathSensitivity: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity',
noPathSensitivityDir: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity',
noPathSensitivityFile: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity'
noPathSensitivityFile: 'is declared without path sensitivity. Properties of cacheable transforms must declare their path sensitivity',
outputDir: 'is annotated with unsupported annotation @OutputDirectory',
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public ArtifactTransformRegistration create(ImmutableAttributes from, ImmutableA
if (!validationMessages.isEmpty()) {
throw new DefaultMultiCauseException(
String.format(validationMessages.size() == 1 ? "A problem was found with the configuration of %s." : "Some problems were found with the configuration of %s.", ModelType.of(implementation).getDisplayName()),
validationMessages.stream().map(InvalidUserDataException::new).collect(Collectors.toList()));
validationMessages.stream().sorted().map(InvalidUserDataException::new).collect(Collectors.toList()));
}
Transformer transformer = new DefaultTransformer(
implementation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public void visitInputFileProperty(String propertyName, boolean optional, boolea
if (!validationMessages.isEmpty()) {
throw new DefaultMultiCauseException(
String.format(validationMessages.size() == 1 ? "A problem was found with the configuration of the artifact transform parameter %s." : "Some problems were found with the configuration of the artifact transform parameter %s.", getParameterObjectDisplayName(parameterObject)),
validationMessages.stream().map(InvalidUserDataException::new).collect(Collectors.toList())
validationMessages.stream().sorted().map(InvalidUserDataException::new).collect(Collectors.toList())
);
}

Expand Down
Loading

0 comments on commit 589c8a0

Please sign in to comment.