Skip to content

Commit

Permalink
Initial work on a Copy command
Browse files Browse the repository at this point in the history
  • Loading branch information
jjlauer committed Oct 27, 2023
1 parent 79531f2 commit b8ef583
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 0 deletions.
15 changes: 15 additions & 0 deletions blaze-core/src/main/java/com/fizzed/blaze/Systems.java
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ static public Exec exec(File command, Object ... arguments) {
* @param globber The globber to use to find the paths to delete
* @return A new Remove action bound to current context
*/
static public Remove rm(Globber globber) {
return remove(globber);
}

@Deprecated
static public Remove remove(Globber globber) {
return new Remove(Contexts.currentContext())
.paths(globber);
Expand All @@ -345,6 +350,11 @@ static public Remove remove(Globber globber) {
* @param paths The paths to delete
* @return A new Remove action bound to current context
*/
static public Remove rm(Path... paths) {
return remove(paths);
}

@Deprecated
static public Remove remove(Path... paths) {
return new Remove(Contexts.currentContext())
.paths(paths);
Expand All @@ -367,6 +377,11 @@ static public Remove remove(Path... paths) {
* @param files The files to delete
* @return A new Remove action bound to current context
*/
static public Remove rm(File... files) {
return remove(files);
}

@Deprecated
static public Remove remove(File... files) {
return new Remove(Contexts.currentContext())
.paths(files);
Expand Down
234 changes: 234 additions & 0 deletions blaze-core/src/main/java/com/fizzed/blaze/system/Copy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* Copyright 2015 Fizzed, Inc.
*
* 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 com.fizzed.blaze.system;

import com.fizzed.blaze.Context;
import com.fizzed.blaze.core.Action;
import com.fizzed.blaze.core.BlazeException;
import com.fizzed.blaze.core.ExecMixin;
import com.fizzed.blaze.core.PathsMixin;
import com.fizzed.blaze.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.concurrent.TimeUnit;

abstract public class Copy extends Action<Copy.Result,Void> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());

static public class Result extends com.fizzed.blaze.core.Result<Copy,Void,Result> {

Result(Copy action, Void value) {
super(action, value);
}

}

private List<Path> sources;
private Path destination;
private boolean force;
private boolean recursive;

public Copy(Context context) {
super(context);
this.sources = new ArrayList<>();
this.force = false;
this.recursive = false;
}

public Copy source(String path) {
ObjectHelper.requireNonNull(path, "path cannot be null");
return source(Paths.get(path));
}

public Copy source(File path) {
ObjectHelper.requireNonNull(path, "path cannot be null");
return source(path.toPath());
}

public Copy source(Path path) {
ObjectHelper.requireNonNull(path, "path cannot be null");
this.sources.add(path);
return this;
}

public Copy destination(String path) {
ObjectHelper.requireNonNull(path, "path cannot be null");
return destination(Paths.get(path));
}

public Copy destination(File path) {
ObjectHelper.requireNonNull(path, "path cannot be null");
return destination(path.toPath());
}

public Copy destination(Path path) {
ObjectHelper.requireNonNull(path, "path cannot be null");
this.destination = path;
return this;
}

public Copy force() {
this.force = true;
return this;
}

public Copy force(boolean force) {
this.force = force;
return this;
}

public Copy recursive() {
this.recursive = true;
return this;
}

public Copy recursive(boolean recursive) {
this.recursive = recursive;
return this;
}

@Override
protected Copy.Result doRun() throws BlazeException {
if (this.sources.isEmpty()) {
throw new BlazeException("Copy requires at least 1 source path");
}

if (this.destination == null) {
throw new BlazeException("Copy requires a destination");
}

// the sources must all exist
for (Path source : this.sources) {
if (!Files.exists(source)) {
throw new BlazeException("Copy source " + source + " does not exist");
}
}

try {
// does the destination exist?
if (Files.exists(this.destination)) {
// if its a file, we could have issues
if (!Files.isDirectory(this.destination) && !this.force) {
throw new BlazeException("Copy destination " + this.destination + " already exists");
}
} else {
// destination does not exist, what to do?
if (this.sources.size() > 1) {
// the destination MUST be a directory
Files.createDirectories(this.destination);
} else {
// single to single, if the source is a directory, the target must be too
if (Files.isDirectory(this.sources.get(0))) {
Files.createDirectories(this.destination);
}
}
}

// single -> single
if (this.sources.size() == 1) {
final Path source = this.sources.get(0);

if (!Files.isDirectory(source)) {
// source is a file
if (Files.isDirectory(this.destination)) {
Path target = this.destination.resolve(source.getFileName());
log.info("Copying {} -> {}", source, target);
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
} else {
log.info("Copying {} -> {}", source, this.destination);
Files.copy(source, this.destination, StandardCopyOption.REPLACE_EXISTING);
}
} else {
// source is a directory
if (Files.isDirectory(this.destination)) {
copyDirectory(source, this.destination);
} else {
throw new BlazeException("Cannot copy source directory " + source + " a file " + this.destination);
}
}
}


} catch (IOException e) {
throw new BlazeException("Unable to copy", e);
}

return new Copy.Result(this, null);
}

/*private void copyDirectory(Path sourceDir, Path destinationDir) throws IOException {
Files.walk(sourceDir)
.forEach(sourcePath -> {
try {
Path targetPath = destinationDir.resolve(sourceDir.relativize(sourcePath));
log.info("Copying {} -> {}", sourcePath, targetPath);
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new UncheckedIOException("Unable to copy", e);
}
});
}*/

private void copyDirectory(Path sourceDir, Path destinationDir) throws IOException {
CopyFileVisitor fileVisitor = new CopyFileVisitor(sourceDir, destinationDir);
Files.walkFileTree(sourceDir, fileVisitor);

}

private class CopyFileVisitor extends SimpleFileVisitor<Path> {

private final Path source;
private final Path target;

public CopyFileVisitor(Path source, Path target) {
this.source = source;
this.target = target;
}

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path resolve = target.resolve(source.relativize(dir));
if (Files.notExists(resolve)) {
log.info("Creating directory {}", resolve);
Files.createDirectories(resolve);
}
return FileVisitResult.CONTINUE;

}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path resolve = target.resolve(source.relativize(file));
log.info("Copying {} -> {}", file, resolve);
Files.copy(file, resolve, StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.format("Unable to copy: %s: %s%n", file, exc);
return FileVisitResult.TERMINATE;
}

}

}

0 comments on commit b8ef583

Please sign in to comment.