Skip to content

Commit

Permalink
feat: add work dir backup options (#1494)
Browse files Browse the repository at this point in the history
* feat: Add backup options

* feat: add sort for list backup items api

* refactor: rename varibles
  • Loading branch information
guqing authored Oct 12, 2021
1 parent 8c26430 commit 0dc75e2
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@

import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
Expand Down Expand Up @@ -81,8 +85,19 @@ public BackupDTO getMarkdownBackup(@RequestParam("filename") String filename) {
@PostMapping("work-dir")
@ApiOperation("Backups work directory")
@DisableOnCondition
public BackupDTO backupHalo() {
return backupService.backupWorkDirectory();
public BackupDTO backupHalo(@RequestBody List<String> options) {
return backupService.backupWorkDirectory(options);
}

@GetMapping("work-dir/options")
@ApiOperation("Gets items that can be backed up")
public List<String> listBackupItems() throws IOException {
return Files.list(Paths.get(haloProperties.getWorkDir()))
.map(Path::getFileName)
.filter(Objects::nonNull)
.map(Path::toString)
.sorted()
.collect(Collectors.toList());
}

@GetMapping("work-dir")
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/run/halo/app/service/BackupService.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ public interface BackupService {
/**
* Zips work directory.
*
* @param options file or directory items to back up
* @return backup dto.
*/
@NonNull
BackupDTO backupWorkDirectory();

BackupDTO backupWorkDirectory(List<String> options);

/**
* Lists all backups.
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/run/halo/app/service/impl/BackupServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import run.halo.app.config.properties.HaloProperties;
import run.halo.app.event.options.OptionUpdatedEvent;
import run.halo.app.event.theme.ThemeUpdatedEvent;
import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.NotFoundException;
import run.halo.app.exception.ServiceException;
import run.halo.app.handler.file.FileHandler;
Expand Down Expand Up @@ -213,7 +215,10 @@ public BasePostDetailDTO importMarkdown(MultipartFile file) throws IOException {
}

@Override
public BackupDTO backupWorkDirectory() {
public BackupDTO backupWorkDirectory(List<String> options) {
if (CollectionUtils.isEmpty(options)) {
throw new BadRequestException("The options parameter is missing, at least one.");
}
// Zip work directory to temporary file
try {
// Create zip path for halo zip
Expand All @@ -229,7 +234,17 @@ public BackupDTO backupWorkDirectory() {

// Zip halo
run.halo.app.utils.FileUtils
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath);
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath,
path -> {
for (String itemToBackup : options) {
Path backupItemPath =
Paths.get(this.haloProperties.getWorkDir()).resolve(itemToBackup);
if (path.startsWith(backupItemPath)) {
return true;
}
}
return false;
});

// Build backup dto
return buildBackupDto(BACKUP_RESOURCE_BASE_URI, haloZipPath);
Expand Down
51 changes: 49 additions & 2 deletions src/main/java/run/halo/app/utils/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,23 @@ public static void zip(@NonNull Path pathToZip, @NonNull Path pathOfArchive)
}
}

/**
* Zips folder or file with filter.
*
* @param pathToZip file path to zip must not be null
* @param pathOfArchive zip file path to archive must not be null
* @param filter folder or file filter
* @throws IOException throws when failed to access file to be zipped
*/
public static void zip(@NonNull Path pathToZip, @NonNull Path pathOfArchive,
@Nullable Predicate<Path> filter) throws IOException {
try (OutputStream outputStream = Files.newOutputStream(pathOfArchive)) {
try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
zip(pathToZip, zipOut, filter);
}
}
}

/**
* Zips folder or file.
*
Expand All @@ -198,6 +215,20 @@ public static void zip(@NonNull Path pathToZip, @NonNull ZipOutputStream zipOut)
zip(pathToZip, pathToZip.getFileName().toString(), zipOut);
}

/**
* Zips folder or file with filter.
*
* @param pathToZip file path to zip must not be null
* @param zipOut zip output stream must not be null
* @param filter directory or file filter
* @throws IOException throws when failed to access file to be zipped
*/
public static void zip(@NonNull Path pathToZip, @NonNull ZipOutputStream zipOut,
Predicate<Path> filter) throws IOException {
// Zip file
zip(pathToZip, pathToZip.getFileName().toString(), zipOut, filter);
}

/**
* Zips folder or file.
*
Expand All @@ -208,6 +239,20 @@ public static void zip(@NonNull Path pathToZip, @NonNull ZipOutputStream zipOut)
*/
private static void zip(@NonNull Path fileToZip, @NonNull String fileName,
@NonNull ZipOutputStream zipOut) throws IOException {
zip(fileToZip, fileName, zipOut, null);
}

/**
* Zips folder or file with path filter.
*
* @param fileToZip file path to zip must not be null
* @param fileName file name must not be blank
* @param zipOut zip output stream must not be null
* @param filter directory or file filter
* @throws IOException throws when failed to access file to be zipped
*/
private static void zip(@NonNull Path fileToZip, @NonNull String fileName,
@NonNull ZipOutputStream zipOut, @Nullable Predicate<Path> filter) throws IOException {
if (Files.isDirectory(fileToZip)) {
log.debug("Try to zip folder: [{}]", fileToZip);
// Append with '/' if missing
Expand All @@ -222,10 +267,12 @@ private static void zip(@NonNull Path fileToZip, @NonNull String fileName,
try (Stream<Path> subPathStream = Files.list(fileToZip)) {
// There should not use foreach for stream as internal zip method will throw
// IOException
List<Path> subFiles = subPathStream.collect(Collectors.toList());
List<Path> subFiles =
filter != null ? subPathStream.filter(filter).collect(Collectors.toList())
: subPathStream.collect(Collectors.toList());
for (Path subFileToZip : subFiles) {
// Zip children
zip(subFileToZip, folderName + subFileToZip.getFileName(), zipOut);
zip(subFileToZip, folderName + subFileToZip.getFileName(), zipOut, filter);
}
}
} else {
Expand Down

0 comments on commit 0dc75e2

Please sign in to comment.