org.gradle.api.internal.tasks.SnapshotTaskInputsBuildOperationResult Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* 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 org.gradle.api.internal.tasks;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.gradle.api.NonNullApi;
import org.gradle.caching.BuildCacheKey;
import org.gradle.internal.execution.caching.CachingInputs;
import org.gradle.internal.execution.caching.CachingState;
import org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep;
import org.gradle.internal.file.FileType;
import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint;
import org.gradle.internal.fingerprint.FileSystemLocationFingerprint;
import org.gradle.internal.hash.HashCode;
import org.gradle.internal.operations.trace.CustomOperationTraceSerialization;
import org.gradle.internal.snapshot.DirectorySnapshot;
import org.gradle.internal.snapshot.FileSystemLocationSnapshot;
import org.gradle.internal.snapshot.FileSystemSnapshotHierarchyVisitor;
import org.gradle.internal.snapshot.SnapshotVisitResult;
import org.gradle.internal.snapshot.impl.ImplementationSnapshot;
import javax.annotation.Nullable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Consumer;
/**
* This operation represents the work of analyzing the task's inputs plus the calculating the cache key.
*
*
* These two operations should be captured separately, but for historical reasons we don't yet do that.
* To reproduce this composite operation we capture across executors by starting an operation
* in {@link StartSnapshotTaskInputsBuildOperationTaskExecuter} and finished in {@link MarkSnapshottingInputsFinishedStep}.
*
*/
public class SnapshotTaskInputsBuildOperationResult implements SnapshotTaskInputsBuildOperationType.Result, CustomOperationTraceSerialization {
@VisibleForTesting
final CachingState cachingState;
public SnapshotTaskInputsBuildOperationResult(CachingState cachingState) {
this.cachingState = cachingState;
}
@Override
public Map getInputValueHashesBytes() {
return cachingState.getInputs()
.map(new java.util.function.Function>() {
@Nullable
@Override
public Map apply(CachingInputs cachingInputs) {
ImmutableSortedMap inputValueFingerprints = cachingInputs.getInputValueFingerprints();
if (inputValueFingerprints.isEmpty()) {
return null;
}
return Maps.transformValues(inputValueFingerprints, new Function() {
@Override
public byte[] apply(HashCode input) {
return input.toByteArray();
}
});
}
})
.orElse(null);
}
@NonNullApi
private static class State implements VisitState, FileSystemSnapshotHierarchyVisitor {
final InputFilePropertyVisitor visitor;
Map fingerprints;
String propertyName;
HashCode propertyHash;
String propertyNormalizationStrategyIdentifier;
String name;
String path;
HashCode hash;
int depth;
public State(InputFilePropertyVisitor visitor) {
this.visitor = visitor;
}
@Override
public String getPropertyName() {
return propertyName;
}
@Override
public byte[] getPropertyHashBytes() {
return propertyHash.toByteArray();
}
@Override
public String getPropertyNormalizationStrategyName() {
return propertyNormalizationStrategyIdentifier;
}
@Override
public String getName() {
return name;
}
@Override
public String getPath() {
return path;
}
@Override
public byte[] getHashBytes() {
return hash.toByteArray();
}
@Override
public void enterDirectory(DirectorySnapshot physicalSnapshot) {
this.path = physicalSnapshot.getAbsolutePath();
this.name = physicalSnapshot.getName();
this.hash = null;
if (depth++ == 0) {
visitor.preRoot(this);
}
visitor.preDirectory(this);
}
@Override
public SnapshotVisitResult visitEntry(FileSystemLocationSnapshot snapshot) {
if (snapshot.getType() == FileType.Directory) {
return SnapshotVisitResult.CONTINUE;
}
this.path = snapshot.getAbsolutePath();
this.name = snapshot.getName();
FileSystemLocationFingerprint fingerprint = fingerprints.get(path);
if (fingerprint == null) {
return SnapshotVisitResult.CONTINUE;
}
this.hash = fingerprint.getNormalizedContentHash();
boolean isRoot = depth == 0;
if (isRoot) {
visitor.preRoot(this);
}
visitor.file(this);
if (isRoot) {
visitor.postRoot();
}
return SnapshotVisitResult.CONTINUE;
}
@Override
public void leaveDirectory(DirectorySnapshot directorySnapshot) {
visitor.postDirectory();
if (--depth == 0) {
visitor.postRoot();
}
}
}
@Override
public void visitInputFileProperties(final InputFilePropertyVisitor visitor) {
cachingState.getInputs().ifPresent(new Consumer() {
@Override
public void accept(CachingInputs inputs) {
State state = new State(visitor);
for (Map.Entry entry : inputs.getInputFileFingerprints().entrySet()) {
CurrentFileCollectionFingerprint fingerprint = entry.getValue();
state.propertyName = entry.getKey();
state.propertyHash = fingerprint.getHash();
state.propertyNormalizationStrategyIdentifier = fingerprint.getStrategyIdentifier();
state.fingerprints = fingerprint.getFingerprints();
visitor.preProperty(state);
fingerprint.getSnapshot().accept(state);
visitor.postProperty();
}
}
});
}
@Nullable
@Override
public Set getInputPropertiesLoadedByUnknownClassLoader() {
return cachingState.getInputs()
.map(new java.util.function.Function>() {
@Nullable
@Override
public Set apply(CachingInputs inputs) {
ImmutableSortedSet invalidInputProperties = inputs.getNonCacheableInputProperties();
if (invalidInputProperties.isEmpty()) {
return null;
}
return invalidInputProperties;
}
})
.orElse(null);
}
@Override
public byte[] getClassLoaderHashBytes() {
return cachingState.getInputs()
.map(new java.util.function.Function() {
@Nullable
@Override
public byte[] apply(CachingInputs inputs) {
ImplementationSnapshot implementation = inputs.getImplementation();
if (implementation.getClassLoaderHash() == null) {
return null;
}
return implementation.getClassLoaderHash().toByteArray();
}
})
.orElse(null);
}
@Override
public List getActionClassLoaderHashesBytes() {
return cachingState.getInputs()
.map(new java.util.function.Function>() {
@Nullable
@Override
public List apply(CachingInputs inputs) {
List additionalImplementations = inputs.getAdditionalImplementations();
if (additionalImplementations.isEmpty()) {
return null;
}
return Lists.transform(additionalImplementations, new Function() {
@Override
public byte[] apply(ImplementationSnapshot input) {
return input.getClassLoaderHash() == null ? null : input.getClassLoaderHash().toByteArray();
}
});
}
})
.orElse(null);
}
@Nullable
@Override
public List getActionClassNames() {
return cachingState.getInputs()
.map(new java.util.function.Function>() {
@Nullable
@Override
public List apply(CachingInputs inputs) {
List additionalImplementations = inputs.getAdditionalImplementations();
if (additionalImplementations.isEmpty()) {
return null;
}
return Lists.transform(additionalImplementations, new Function() {
@Override
public String apply(ImplementationSnapshot input) {
return input.getTypeName();
}
});
}
})
.orElse(null);
}
@Nullable
@Override
public List getOutputPropertyNames() {
return cachingState.getInputs()
.map(new java.util.function.Function>() {
@Nullable
@Override
public List apply(CachingInputs inputs) {
ImmutableSortedSet outputPropertyNames = inputs.getOutputProperties();
if (outputPropertyNames.isEmpty()) {
return null;
}
return outputPropertyNames.asList();
}
})
.orElse(null);
}
@Override
public byte[] getHashBytes() {
return cachingState.getKey()
.map(new java.util.function.Function() {
@Override
public byte[] apply(BuildCacheKey cacheKey) {
return cacheKey.toByteArray();
}
})
.orElse(null);
}
@Override
public Object getCustomOperationTraceSerializableModel() {
Map model = new TreeMap();
final Function bytesToString = new Function() {
@Nullable
@Override
public String apply(@Nullable byte[] input) {
if (input == null) {
return null;
}
return HashCode.fromBytes(input).toString();
}
};
List actionClassLoaderHashesBytes = getActionClassLoaderHashesBytes();
if (actionClassLoaderHashesBytes != null) {
model.put("actionClassLoaderHashes", Lists.transform(getActionClassLoaderHashesBytes(), bytesToString));
} else {
model.put("actionClassLoaderHashes", null);
}
model.put("actionClassNames", getActionClassNames());
byte[] hashBytes = getHashBytes();
if (hashBytes != null) {
model.put("hash", HashCode.fromBytes(hashBytes).toString());
} else {
model.put("hash", null);
}
byte[] classLoaderHashBytes = getClassLoaderHashBytes();
if (classLoaderHashBytes != null) {
model.put("classLoaderHash", HashCode.fromBytes(classLoaderHashBytes).toString());
} else {
model.put("classLoaderHash", null);
}
model.put("inputFileProperties", fileProperties());
model.put("inputPropertiesLoadedByUnknownClassLoader", getInputPropertiesLoadedByUnknownClassLoader());
Map inputValueHashesBytes = getInputValueHashesBytes();
if (inputValueHashesBytes != null) {
model.put("inputValueHashes", Maps.transformEntries(inputValueHashesBytes, new Maps.EntryTransformer() {
@Nullable
@Override
public String transformEntry(@Nullable String key, @Nullable byte[] value) {
if (value == null) {
return null;
}
return HashCode.fromBytes(value).toString();
}
}));
} else {
model.put("inputValueHashes", null);
}
model.put("outputPropertyNames", getOutputPropertyNames());
return model;
}
protected Map fileProperties() {
final Map fileProperties = new TreeMap();
visitInputFileProperties(new InputFilePropertyVisitor() {
Property property;
Deque dirStack = new ArrayDeque();
class Property {
private final String hash;
private final String normalization;
private final List roots = new ArrayList();
public Property(String hash, String normalization) {
this.hash = hash;
this.normalization = normalization;
}
public String getHash() {
return hash;
}
public String getNormalization() {
return normalization;
}
public Collection getRoots() {
return roots;
}
}
abstract class Entry {
private final String path;
public Entry(String path) {
this.path = path;
}
public String getPath() {
return path;
}
}
class FileEntry extends Entry {
private final String hash;
FileEntry(String path, String hash) {
super(path);
this.hash = hash;
}
public String getHash() {
return hash;
}
}
class DirEntry extends Entry {
private final List children = new ArrayList();
DirEntry(String path) {
super(path);
}
public Collection getChildren() {
return children;
}
}
@Override
public void preProperty(VisitState state) {
property = new Property(HashCode.fromBytes(state.getPropertyHashBytes()).toString(), state.getPropertyNormalizationStrategyName());
fileProperties.put(state.getPropertyName(), property);
}
@Override
public void preRoot(VisitState state) {
}
@Override
public void preDirectory(VisitState state) {
boolean isRoot = dirStack.isEmpty();
DirEntry dir = new DirEntry(isRoot ? state.getPath() : state.getName());
if (isRoot) {
property.roots.add(dir);
} else {
//noinspection ConstantConditions
dirStack.peek().children.add(dir);
}
dirStack.push(dir);
}
@Override
public void file(VisitState state) {
boolean isRoot = dirStack.isEmpty();
FileEntry file = new FileEntry(isRoot ? state.getPath() : state.getName(), HashCode.fromBytes(state.getHashBytes()).toString());
if (isRoot) {
property.roots.add(file);
} else {
//noinspection ConstantConditions
dirStack.peek().children.add(file);
}
}
@Override
public void postDirectory() {
dirStack.pop();
}
@Override
public void postRoot() {
}
@Override
public void postProperty() {
}
});
return fileProperties;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy