/* * 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.internal.file.copy; import org.gradle.api.file.FileTreeElement; import org.gradle.api.file.FileVisitDetails; import org.gradle.api.file.FileVisitor; import org.gradle.api.file.RelativePath; import org.gradle.api.internal.file.CopyActionProcessingStreamAction; import org.gradle.api.internal.file.collections.DirectoryFileTreeFactory; import org.gradle.api.internal.file.collections.MinimalFileTree; import org.gradle.api.internal.tasks.SimpleWorkResult; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.WorkResult; import org.gradle.api.tasks.util.PatternFilterable; import org.gradle.api.tasks.util.PatternSet; import org.gradle.util.GFileUtils; import java.io.File; import java.util.HashSet; import java.util.Set; public class SyncCopyActionDecorator implements CopyAction { private final File baseDestDir; private final CopyAction delegate; private final PatternFilterable preserveSpec; private final DirectoryFileTreeFactory directoryFileTreeFactory; public SyncCopyActionDecorator(File baseDestDir, CopyAction delegate, DirectoryFileTreeFactory directoryFileTreeFactory) { this(baseDestDir, delegate, null, directoryFileTreeFactory); } public SyncCopyActionDecorator(File baseDestDir, CopyAction delegate, PatternFilterable preserveSpec, DirectoryFileTreeFactory directoryFileTreeFactory) { this.baseDestDir = baseDestDir; this.delegate = delegate; this.preserveSpec = preserveSpec; this.directoryFileTreeFactory = directoryFileTreeFactory; } public WorkResult execute(final CopyActionProcessingStream stream) { final Set<RelativePath> visited = new HashSet<RelativePath>(); WorkResult didWork = delegate.execute(new CopyActionProcessingStream() { public void process(final CopyActionProcessingStreamAction action) { stream.process(new CopyActionProcessingStreamAction() { public void processFile(FileCopyDetailsInternal details) { visited.add(details.getRelativePath()); action.processFile(details); } }); } }); SyncCopyActionDecoratorFileVisitor fileVisitor = new SyncCopyActionDecoratorFileVisitor(visited, preserveSpec); MinimalFileTree walker = directoryFileTreeFactory.create(baseDestDir).postfix(); walker.visit(fileVisitor); visited.clear(); return new SimpleWorkResult(didWork.getDidWork() || fileVisitor.didWork); } private static class SyncCopyActionDecoratorFileVisitor implements FileVisitor { private final Set<RelativePath> visited; private final Spec<FileTreeElement> preserveSpec; private final PatternSet preserveSet; private boolean didWork; private SyncCopyActionDecoratorFileVisitor(Set<RelativePath> visited, PatternFilterable preserveSpec) { this.visited = visited; PatternSet preserveSet = new PatternSet(); if (preserveSpec != null) { preserveSet.include(preserveSpec.getIncludes()); preserveSet.exclude(preserveSpec.getExcludes()); } this.preserveSet = preserveSet; this.preserveSpec = preserveSet.getAsSpec(); } public void visitDir(FileVisitDetails dirDetails) { maybeDelete(dirDetails, true); } public void visitFile(FileVisitDetails fileDetails) { maybeDelete(fileDetails, false); } private void maybeDelete(FileVisitDetails fileDetails, boolean isDir) { RelativePath path = fileDetails.getRelativePath(); if (!visited.contains(path)) { if (preserveSet.isEmpty() || !preserveSpec.isSatisfiedBy(fileDetails)) { if (isDir) { GFileUtils.deleteDirectory(fileDetails.getFile()); } else { GFileUtils.deleteQuietly(fileDetails.getFile()); } didWork = true; } } } } }