Ultimately, there should be a core gradle task which can copy in parallel. Until this time, it’s possibly easier to write a limited ParallelCopy
task from scratch rather extending the Copy
task.
Eg:
class ParallelCopy extends DefaultTask {
private final WorkerExecutor workerExecutor
@Inject
ParallelCopy(WorkerExecutor workerExecutor) { this.workerExecutor = workerExecutor; }
@InputFiles
private List<FileCollection> froms = []
@OutputDirectory
private File into
public void from(Object from) {
this.froms << project.files(from)
}
public void into(Object into) {
this.into = project.file(into)
}
@TaskAction
public void parallelCopy() {
for (FileCollection fc : froms) {
if (fc instanceof FileTree) {
((FileTree) fc).visit { FileVisitDetails fvd ->
if (!fvd.directory) {
File destination = new File(into, fvd.path)
submitWorker(fvd.file, destination)
}
}
} else {
for (File file : fc.files) {
File destination = new File(into, file.name)
submitWorker(file, destination)
}
}
}
}
private void submitWorker(File source, File destination) {
workerExecutor.submit(ParallelCopyWorker.class, new Action<WorkerConfiguration>() {
@Override
public void execute(WorkerConfiguration config) {
config.setIsolationMode(IsolationMode.NONE);
config.params(source, destination);
}
});
}
public static class ParalellCopyWorker implements Runnable {
private final File source;
private final File destination;
@Inject
public ParalellCopyWorker(File source, File destination) {
this.source = source;
this.destination = destination;
}
public void run() {
destination.parentFile.mkdirs()
destination.bytes = source.bytes // TODO use buffer/stream instead
}
}
}
Usage
task copy1(type:ParallelCopy) {
from fileTree('somePath').matching {
include '**/*.txt'
}
from 'another/path'
into 'some/destination'
}