/*
* Copyright 2009 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.tasks.bundling;
import groovy.lang.Closure;
import org.gradle.api.Action;
import org.gradle.api.Incubating;
import org.gradle.api.file.CopySpec;
import org.gradle.api.internal.file.copy.CopyActionExecuter;
import org.gradle.api.tasks.AbstractCopyTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.OutputFile;
import org.gradle.internal.nativeplatform.filesystem.FileSystem;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.util.GUtil;
import java.io.File;
/**
* {@code AbstractArchiveTask} is the base class for all archive tasks.
*/
public abstract class AbstractArchiveTask extends AbstractCopyTask {
private File destinationDir;
private String customName;
private String baseName;
private String appendix;
private String version;
private String extension;
private String classifier = "";
private boolean preserveFileTimestamps = true;
private boolean reproducibleFileOrder;
/**
* Returns the archive name. If the name has not been explicitly set, the pattern for the name is:
* <code>[baseName]-[appendix]-[version]-[classifier].[extension]</code>
*
* @return the archive name.
*/
@Internal("Represented as part of archivePath")
public String getArchiveName() {
if (customName != null) {
return customName;
}
String name = GUtil.elvis(getBaseName(), "") + maybe(getBaseName(), getAppendix());
name += maybe(name, getVersion());
name += maybe(name, getClassifier());
name += GUtil.isTrue(getExtension()) ? "." + getExtension() : "";
return name;
}
/**
* Sets the archive name.
*
* @param name the archive name.
*/
public void setArchiveName(String name) {
customName = name;
}
private String maybe(String prefix, String value) {
if (GUtil.isTrue(value)) {
if (GUtil.isTrue(prefix)) {
return "-".concat(value);
} else {
return value;
}
}
return "";
}
/**
* The path where the archive is constructed. The path is simply the {@code destinationDir} plus the {@code archiveName}.
*
* @return a File object with the path to the archive
*/
@OutputFile
public File getArchivePath() {
return new File(getDestinationDir(), getArchiveName());
}
/**
* Returns the directory where the archive is generated into.
*
* @return the directory
*/
@Internal("Represented as part of archivePath")
public File getDestinationDir() {
return destinationDir;
}
public void setDestinationDir(File destinationDir) {
this.destinationDir = destinationDir;
}
/**
* Returns the base name of the archive.
*
* @return the base name.
*/
@Internal("Represented as part of archiveName")
public String getBaseName() {
return baseName;
}
public void setBaseName(String baseName) {
this.baseName = baseName;
}
/**
* Returns the appendix part of the archive name, if any.
*
* @return the appendix. May be null
*/
@Internal("Represented as part of archiveName")
public String getAppendix() {
return appendix;
}
public void setAppendix(String appendix) {
this.appendix = appendix;
}
/**
* Returns the version part of the archive name, if any.
*
* @return the version. May be null.
*/
@Internal("Represented as part of archiveName")
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
/**
* Returns the extension part of the archive name.
*/
@Internal("Represented as part of archiveName")
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension;
}
/**
* Returns the classifier part of the archive name, if any.
*
* @return The classifier. May be null.
*/
@Internal("Represented as part of archiveName")
public String getClassifier() {
return classifier;
}
public void setClassifier(String classifier) {
this.classifier = classifier;
}
/**
* Specifies the destination directory *inside* the archive for the files.
* The destination is evaluated as per {@link org.gradle.api.Project#file(Object)}.
* Don't mix it up with {@link #getDestinationDir()} which specifies the output directory for the archive.
*
* @param destPath destination directory *inside* the archive for the files
* @return this
*/
public AbstractArchiveTask into(Object destPath) {
super.into(destPath);
return this;
}
/**
* Creates and configures a child {@code CopySpec} with a destination directory *inside* the archive for the files.
* The destination is evaluated as per {@link org.gradle.api.Project#file(Object)}.
* Don't mix it up with {@link #getDestinationDir()} which specifies the output directory for the archive.
*
* @param destPath destination directory *inside* the archive for the files
* @param configureClosure The closure to use to configure the child {@code CopySpec}.
* @return this
*/
public AbstractArchiveTask into(Object destPath, Closure configureClosure) {
super.into(destPath, configureClosure);
return this;
}
/**
* Creates and configures a child {@code CopySpec} with a destination directory *inside* the archive for the files.
* The destination is evaluated as per {@link org.gradle.api.Project#file(Object)}.
* Don't mix it up with {@link #getDestinationDir()} which specifies the output directory for the archive.
*
* @param destPath destination directory *inside* the archive for the files
* @param copySpec The closure to use to configure the child {@code CopySpec}.
* @return this
*/
public CopySpec into(Object destPath, Action<? super CopySpec> copySpec) {
super.into(destPath, copySpec);
return this;
}
/**
* Specifies whether file timestamps should be preserved in the archive.
* <p>
* If <tt>false</tt> this ensures that archive entries have the same time for builds between different machines, Java versions and operating systems.
* </p>
*
* @since 3.4
* @return <tt>true</tt> if file timestamps should be preserved for archive entries
*/
@Input
@Incubating
public boolean isPreserveFileTimestamps() {
return preserveFileTimestamps;
}
/**
* Specifies whether file timestamps should be preserved in the archive.
* <p>
* If <tt>false</tt> this ensures that archive entries have the same time for builds between different machines, Java versions and operating systems.
* </p>
*
* @since 3.4
* @param preserveFileTimestamps <tt>true</tt> if file timestamps should be preserved for archive entries
*/
@Incubating
public void setPreserveFileTimestamps(boolean preserveFileTimestamps) {
this.preserveFileTimestamps = preserveFileTimestamps;
}
/**
* Specifies whether to enforce a reproducible file order when reading files from directories.
* <p>
* Gradle will then walk the directories on disk which are part of this archive in a reproducible order
* independent of file systems and operating systems.
* This helps Gradle reliably produce byte-for-byte reproducible archives.
* </p>
*
* @since 3.4
* @return <tt>true</tt> if the files should read from disk in a reproducible order.
*/
@Input
@Incubating
public boolean isReproducibleFileOrder() {
return reproducibleFileOrder;
}
/**
* Specifies whether to enforce a reproducible file order when reading files from directories.
* <p>
* Gradle will then walk the directories on disk which are part of this archive in a reproducible order
* independent of file systems and operating systems.
* This helps Gradle reliably produce byte-for-byte reproducible archives.
* </p>
*
* @since 3.4
* @param reproducibleFileOrder <tt>true</tt> if the files should read from disk in a reproducible order.
*/
@Incubating
public void setReproducibleFileOrder(boolean reproducibleFileOrder) {
this.reproducibleFileOrder = reproducibleFileOrder;
}
@Override
protected CopyActionExecuter createCopyActionExecuter() {
Instantiator instantiator = getInstantiator();
FileSystem fileSystem = getFileSystem();
return new CopyActionExecuter(instantiator, fileSystem, isReproducibleFileOrder());
}
}