It's a long way, but is it also useful?
3 files added
12 files modified
| | |
| | | package de.micromata.borgbutler; |
| | | |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import de.micromata.borgbutler.config.BorgRepoConfig; |
| | | import de.micromata.borgbutler.data.Archive; |
| | | import de.micromata.borgbutler.data.Repository; |
| | |
| | | import java.io.IOException; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Scanner; |
| | | |
| | |
| | | try (Scanner scanner = new Scanner(command.getResponse())) { |
| | | while (scanner.hasNextLine()) { |
| | | String json = scanner.nextLine(); |
| | | BorgFilesystemItem item = JsonUtils.fromJson(BorgFilesystemItem.class, json); |
| | | FilesystemItem item = JsonUtils.fromJson(FilesystemItem.class, json); |
| | | item.setMtime(DateUtils.format(item.getMtime())); |
| | | content.add(item); |
| | | } |
| | | } |
| | | Collections.sort(content); // Sort by path. |
| | | return content; |
| | | } |
| | | |
| | |
| | | package de.micromata.borgbutler; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | |
| | | * @param otherItems Sorted list of items of the archive to extract differences. |
| | | * @return A list of differing items (new, removed and modified ones). |
| | | */ |
| | | public static List<BorgFilesystemItem> extractDifferences(List<BorgFilesystemItem> items, List<BorgFilesystemItem> otherItems) { |
| | | List<BorgFilesystemItem> currentList = items != null ? items : new ArrayList<>(); |
| | | List<BorgFilesystemItem> otherList = otherItems != null ? otherItems : new ArrayList<>(); |
| | | List<BorgFilesystemItem> result = new ArrayList<>(); |
| | | Iterator<BorgFilesystemItem> currentIt = currentList.iterator(); |
| | | Iterator<BorgFilesystemItem> otherIt = otherList.iterator(); |
| | | BorgFilesystemItem current = null; |
| | | BorgFilesystemItem other = null; |
| | | public static List<FilesystemItem> extractDifferences(List<FilesystemItem> items, List<FilesystemItem> otherItems) { |
| | | List<FilesystemItem> currentList = items != null ? items : new ArrayList<>(); |
| | | List<FilesystemItem> otherList = otherItems != null ? otherItems : new ArrayList<>(); |
| | | List<FilesystemItem> result = new ArrayList<>(); |
| | | Iterator<FilesystemItem> currentIt = currentList.iterator(); |
| | | Iterator<FilesystemItem> otherIt = otherList.iterator(); |
| | | FilesystemItem current = null; |
| | | FilesystemItem other = null; |
| | | while (true) { |
| | | if (current == null && currentIt.hasNext()) |
| | | current = currentIt.next(); |
| | |
| | | continue; |
| | | } |
| | | // Current entry differs: |
| | | current.setDiffStatus(BorgFilesystemItem.DiffStatus.MODIFIED); |
| | | current.setDiffStatus(FilesystemItem.DiffStatus.MODIFIED); |
| | | current.setDiffItem(other); |
| | | current.buildDifferencesString(); |
| | | result.add(current); |
| | | current = other = null; // increment both iterators. |
| | | } else if (cmp < 0) { |
| | | result.add(current.setDiffStatus(BorgFilesystemItem.DiffStatus.NEW)); |
| | | result.add(current.setDiffStatus(FilesystemItem.DiffStatus.NEW)); |
| | | current = currentIt.hasNext() ? currentIt.next() : null; |
| | | } else { |
| | | result.add(other.setDiffStatus(BorgFilesystemItem.DiffStatus.REMOVED)); |
| | | result.add(other.setDiffStatus(FilesystemItem.DiffStatus.REMOVED)); |
| | | other = otherIt.hasNext() ? otherIt.next() : null; |
| | | } |
| | | } |
| | | while (current != null) { |
| | | result.add(current.setDiffStatus(BorgFilesystemItem.DiffStatus.NEW)); |
| | | result.add(current.setDiffStatus(FilesystemItem.DiffStatus.NEW)); |
| | | current = currentIt.hasNext() ? currentIt.next() : null; |
| | | } |
| | | while (other != null) { |
| | | result.add(other.setDiffStatus(BorgFilesystemItem.DiffStatus.REMOVED)); |
| | | result.add(other.setDiffStatus(FilesystemItem.DiffStatus.REMOVED)); |
| | | other = otherIt.hasNext() ? otherIt.next() : null; |
| | | } |
| | | return result; |
| | |
| | | import de.micromata.borgbutler.data.Archive; |
| | | import de.micromata.borgbutler.data.FileSystemFilter; |
| | | import de.micromata.borgbutler.data.Repository; |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.utils.ReplaceUtils; |
| | | import lombok.Getter; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; |
| | | import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; |
| | |
| | | private int cacheArchiveContentMaxDiscSizeMB; |
| | | private long FILES_EXPIRE_TIME = 7 * 24 * 3660 * 1000; // Expires after 7 days. |
| | | |
| | | public void save(BorgRepoConfig repoConfig, Archive archive, List<BorgFilesystemItem> filesystemItems) { |
| | | public void save(BorgRepoConfig repoConfig, Archive archive, List<FilesystemItem> filesystemItems) { |
| | | if (CollectionUtils.isEmpty(filesystemItems)) { |
| | | return; |
| | | } |
| | |
| | | log.info("Saving archive content as file list: " + file.getAbsolutePath()); |
| | | try (ObjectOutputStream outputStream = new ObjectOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(file))))) { |
| | | outputStream.writeObject(filesystemItems.size()); |
| | | for (BorgFilesystemItem item : filesystemItems) { |
| | | for (FilesystemItem item : filesystemItems) { |
| | | outputStream.writeObject(item); |
| | | } |
| | | outputStream.writeObject("EOF"); |
| | |
| | | * @param archive |
| | | * @return |
| | | */ |
| | | public List<BorgFilesystemItem> load(BorgRepoConfig repoConfig, Archive archive) { |
| | | public List<FilesystemItem> load(BorgRepoConfig repoConfig, Archive archive) { |
| | | return load(repoConfig, archive, null); |
| | | } |
| | | |
| | |
| | | * @param filter If given, only file items matching this filter are returned. |
| | | * @return |
| | | */ |
| | | public List<BorgFilesystemItem> load(BorgRepoConfig repoConfig, Archive archive, FileSystemFilter filter) { |
| | | public List<FilesystemItem> load(BorgRepoConfig repoConfig, Archive archive, FileSystemFilter filter) { |
| | | File file = getFile(repoConfig, archive); |
| | | if (!file.exists()) { |
| | | return null; |
| | |
| | | * @param filter If given, only file items matching this filter are returned. |
| | | * @return |
| | | */ |
| | | public List<BorgFilesystemItem> load(File file, FileSystemFilter filter) { |
| | | public List<FilesystemItem> load(File file, FileSystemFilter filter) { |
| | | if (!file.exists()) { |
| | | log.error("File '" + file.getAbsolutePath() + "' doesn't exist. Can't get archive content files."); |
| | | return null; |
| | | } |
| | | log.info("Loading archive content as file list from: " + file.getAbsolutePath()); |
| | | List<BorgFilesystemItem> list = null; |
| | | List<FilesystemItem> list = null; |
| | | try { |
| | | // Set last modified time of file: |
| | | Files.setAttribute(file.toPath(), "lastModifiedTime", FileTime.fromMillis(System.currentTimeMillis())); |
| | |
| | | for (int i = 0; i < size; i++) { |
| | | ++fileNumber; |
| | | obj = inputStream.readObject(); |
| | | if (obj instanceof BorgFilesystemItem) { |
| | | BorgFilesystemItem item = (BorgFilesystemItem) obj; |
| | | item.setFileNumber(fileNumber); |
| | | if (obj instanceof FilesystemItem) { |
| | | FilesystemItem item = (FilesystemItem) obj; |
| | | // item.setFileNumber(fileNumber); |
| | | if (filter == null || filter.matches(item)) { |
| | | list.add(item); |
| | | if (filter != null && filter.isFinished()) break; |
| | |
| | | Collections.sort(list); // Sort by path (if archive list order wasn't correct). |
| | | log.info("Loading done."); |
| | | if (filter != null) { |
| | | return filter.reduce(list); |
| | | // return filter.reduce(list); |
| | | } |
| | | return list; |
| | | } |
| | |
| | | return archive; |
| | | } |
| | | |
| | | public List<BorgFilesystemItem> getArchiveContent(String archiveId) { |
| | | public List<FilesystemItem> getArchiveContent(String archiveId) { |
| | | return getArchiveContent(archiveId, true, null); |
| | | } |
| | | |
| | |
| | | * @param filter If not null, the result will be filtered. |
| | | * @return |
| | | */ |
| | | public List<BorgFilesystemItem> getArchiveContent(String archiveId, boolean forceLoad, FileSystemFilter filter) { |
| | | public List<FilesystemItem> getArchiveContent(String archiveId, boolean forceLoad, FileSystemFilter filter) { |
| | | Archive archive = getArchive(archiveId); |
| | | if (archive == null) { |
| | | log.error("Can't find archive with id '" + archiveId + "'. May-be it doesn't exist or the archives of the target repository aren't yet loaded."); |
| | |
| | | * @param archive |
| | | * @return |
| | | */ |
| | | public List<BorgFilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive) { |
| | | public List<FilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive) { |
| | | return getArchiveContent(repoConfig, archive, true, null); |
| | | } |
| | | |
| | |
| | | * @param filter If given, only the items matching this filter are returned.. |
| | | * @return |
| | | */ |
| | | public List<BorgFilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive, boolean forceLoad, |
| | | public List<FilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive, boolean forceLoad, |
| | | FileSystemFilter filter) { |
| | | if (archive == null || StringUtils.isBlank(archive.getName())) { |
| | | return null; |
| | | } |
| | | List<BorgFilesystemItem> items = archiveFilelistCache.load(repoConfig, archive, filter); |
| | | List<FilesystemItem> items = archiveFilelistCache.load(repoConfig, archive, filter); |
| | | if (items == null && forceLoad) { |
| | | List<BorgFilesystemItem> list = BorgCommands.listArchiveContent(repoConfig, archive); |
| | | if (CollectionUtils.isNotEmpty(list)) { |
| | | archiveFilelistCache.save(repoConfig, archive, list); |
| | | List<BorgFilesystemItem> borgList = BorgCommands.listArchiveContent(repoConfig, archive); |
| | | FilesystemItem root = Filesystem.build(borgList); |
| | | if (CollectionUtils.isNotEmpty(root.getChilds())) { |
| | | archiveFilelistCache.save(repoConfig, archive, root.getChilds()); |
| | | items = new ArrayList<>(); |
| | | int fileNumber = -1; |
| | | for (BorgFilesystemItem item : list) { |
| | | ++fileNumber; |
| | | item.setFileNumber(fileNumber); |
| | | for (FilesystemItem item : list) { |
| | | if (filter == null || filter.matches(item)) { |
| | | items.add(item); |
| | | if (filter != null && filter.isFinished()) break; |
| | | } |
| | | } |
| | | if (filter != null) { |
| | | items = filter.reduce(items); |
| | | // items = filter.reduce(items); |
| | | } |
| | | } |
| | | } |
| | |
| | | return items; |
| | | } |
| | | |
| | | public List<BorgFilesystemItem> getArchiveContent(File file) { |
| | | public List<FilesystemItem> getArchiveContent(File file) { |
| | | return archiveFilelistCache.load(file, null); |
| | | } |
| | | |
| New file |
| | |
| | | package de.micromata.borgbutler.cache; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | public class Filesystem { |
| | | |
| | | public static FilesystemItem build(List<BorgFilesystemItem> itemList) { |
| | | FilesystemItem root = new FilesystemItem(); |
| | | if (CollectionUtils.isEmpty(itemList)) { |
| | | return root; |
| | | } |
| | | Collections.sort(itemList); |
| | | for (BorgFilesystemItem item : itemList) { |
| | | Path path = Paths.get(item.getPath()); |
| | | root.add(path, 0, item); |
| | | } |
| | | return root; |
| | | } |
| | | } |
| New file |
| | |
| | | package de.micromata.borgbutler.cache; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.io.Serializable; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class FilesystemItem extends BorgFilesystemItem implements Serializable { |
| | | private transient static Logger log = LoggerFactory.getLogger(FilesystemItem.class); |
| | | private static final long serialVersionUID = 6561019300264543523L; |
| | | |
| | | @Getter |
| | | @Setter |
| | | private List<FilesystemItem> childs; |
| | | @Getter |
| | | @Setter |
| | | private String name; |
| | | |
| | | public FilesystemItem() { |
| | | |
| | | } |
| | | |
| | | public FilesystemItem(BorgFilesystemItem item) { |
| | | this.path = item.getPath(); |
| | | this.mode = item.getMode(); |
| | | this.mtime = item.getMtime(); |
| | | this.flags = item.getFlags(); |
| | | this.size = item.getSize(); |
| | | this.type = item.getType(); |
| | | this.gid = item.getGid(); |
| | | this.group = item.getGroup(); |
| | | this.healthy = item.isHealthy(); |
| | | this.linktarget = item.getLinktarget(); |
| | | this.source = item.getSource(); |
| | | this.uid = item.getUid(); |
| | | this.user = item.getUser(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * If running in diff mode, this flag specifies the type of difference. Null represents unmodified. |
| | | */ |
| | | public enum DiffStatus {NEW, REMOVED, MODIFIED} |
| | | |
| | | @Setter |
| | | @Getter |
| | | protected String displayPath; |
| | | |
| | | /** |
| | | * If created by diff tool, this flag represents the type of difference. |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private FilesystemItem.DiffStatus diffStatus; |
| | | /** |
| | | * If created by diff tool, this object holds the file item of the other archive (diff archive). |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private FilesystemItem diffItem; |
| | | /** |
| | | * If created by diff tool, this String contains all differences between current and other item for {@link FilesystemItem.DiffStatus#MODIFIED}. |
| | | * This String may used for displaying. |
| | | */ |
| | | @Getter |
| | | private String differences; |
| | | |
| | | /** |
| | | * Compares all fields and creates human readable string with differences. |
| | | */ |
| | | public void buildDifferencesString() { |
| | | if (diffItem == null) { |
| | | // Nothing to do. |
| | | return; |
| | | } |
| | | if (!StringUtils.equals(this.path, diffItem.getPath())) { |
| | | log.error("*** Internal error: Differences should only be made on same path object: current='" + path |
| | | + "', other='" + diffItem.getPath() + "'."); |
| | | return; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | appendDiff(sb, "type", this.type, diffItem.getType()); |
| | | //appendDiff(sb, "mode", this.mode, diffItem.mode); // Done by frontend (jsx) |
| | | appendDiff(sb, "user", this.user, diffItem.getUser()); |
| | | appendDiff(sb, "group", this.group, diffItem.getGroup()); |
| | | appendDiff(sb, "uid", this.uid, diffItem.getUid()); |
| | | appendDiff(sb, "gid", this.gid, diffItem.getGid()); |
| | | //appendDiff(sb, "mtime", this.mtime, diffItem.mtime); // Done by frontend (jsx) |
| | | //appendDiff(sb, "size", this.size, diffItem.size); // Done by frontend (jsx) |
| | | if (sb.length() > 0) { |
| | | diffStatus = FilesystemItem.DiffStatus.MODIFIED; |
| | | this.differences = sb.toString(); |
| | | } |
| | | } |
| | | |
| | | private void appendDiff(StringBuilder sb, String field, String current, String other) { |
| | | if (StringUtils.equals(current, other)) { |
| | | // Not modified. |
| | | return; |
| | | } |
| | | if (sb.length() > 0) { |
| | | sb.append(", "); |
| | | } |
| | | sb.append(field + ":['" + other + "'->'" + current + "']"); |
| | | } |
| | | |
| | | private void appendDiff(StringBuilder sb, String field, long current, long other) { |
| | | if (current == other) { |
| | | // Not modified. |
| | | return; |
| | | } |
| | | if (sb.length() > 0) { |
| | | sb.append(", "); |
| | | } |
| | | sb.append(field + ": ['" + current + "' -> '" + other + "']"); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return path; |
| | | } |
| | | |
| | | FilesystemItem add(Path path, int count, BorgFilesystemItem borgItem) { |
| | | if (childs == null) { |
| | | childs = new ArrayList<>(); |
| | | } |
| | | if (count + 1 == path.getNameCount()) { |
| | | FilesystemItem item = new FilesystemItem(borgItem); |
| | | item.setName(path.getFileName().toString()); |
| | | childs.add(item); |
| | | return item; |
| | | } |
| | | String name = path.getName(count).toString(); |
| | | FilesystemItem child = null; |
| | | for (FilesystemItem ch : childs) { |
| | | if (StringUtils.equals(ch.name, name)) { |
| | | child = ch; |
| | | break; |
| | | } |
| | | } |
| | | if (child == null) { |
| | | child = new FilesystemItem(); |
| | | child.setName(name); |
| | | childs.add(child); |
| | | } |
| | | return child.add(path, count + 1, borgItem); |
| | | } |
| | | |
| | | public FilesystemItem find(String pathString) { |
| | | if (StringUtils.isBlank(pathString)) { |
| | | return this; |
| | | } |
| | | Path path = Paths.get(pathString); |
| | | if (path.getNameCount() == 0) { |
| | | return this; |
| | | } |
| | | return find(path, 0); |
| | | } |
| | | |
| | | private FilesystemItem find(Path path, int count) { |
| | | if (childs == null) { |
| | | return null; |
| | | } |
| | | for (FilesystemItem child : childs) { |
| | | String name = path.getName(count).toString(); |
| | | if (StringUtils.equals(child.name, name)) { |
| | | if (path.getNameCount() == count + 1) |
| | | return child; |
| | | else |
| | | return child.find(path, count + 1); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public int getFileNumber() { |
| | | return path.hashCode(); |
| | | } |
| | | } |
| | |
| | | package de.micromata.borgbutler.data; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.apache.commons.collections4.MapUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.*; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class FileSystemFilter { |
| | | private Logger log = LoggerFactory.getLogger(FileSystemFilter.class); |
| | |
| | | private Mode mode; |
| | | @Getter |
| | | private String currentDirectory; |
| | | // For storing sub directories of the currentDirectory |
| | | private Map<String, BorgFilesystemItem> subDirectories; |
| | | @Getter |
| | | @Setter |
| | | private int maxResultSize = -1; |
| | |
| | | @Getter |
| | | private boolean finished; |
| | | |
| | | public List<FilesystemItem> buildMatchList(FilesystemItem root) { |
| | | FilesystemItem current = root; |
| | | if (StringUtils.isNotBlank(currentDirectory)) { |
| | | current = root.find(currentDirectory); |
| | | if (current == null) { |
| | | current = root; |
| | | log.warn("Directory '" + currentDirectory + "' not found. Searching in root directory."); |
| | | currentDirectory = null; |
| | | } |
| | | } |
| | | List<FilesystemItem> resultList = new ArrayList<>(); |
| | | if (CollectionUtils.isNotEmpty(current.getChilds())) { |
| | | for (FilesystemItem item : current.getChilds()) { |
| | | buildMatchList(item, resultList); |
| | | } |
| | | } |
| | | return resultList; |
| | | } |
| | | |
| | | private void buildMatchList(FilesystemItem item, List<FilesystemItem> resultList) { |
| | | String pathString = item.getPath(); |
| | | if (mode == Mode.TREE && currentDirectory != null) { |
| | | if (matchesRecursive(item)) { |
| | | resultList.add(item); |
| | | } |
| | | return; |
| | | } |
| | | if (matches(item)) { |
| | | resultList.add(item); |
| | | if (CollectionUtils.isEmpty(item.getChilds())) |
| | | return; |
| | | for (FilesystemItem child : item.getChilds()) { |
| | | buildMatchList(child, resultList); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Please ensure that you call matches exactly ones for every file item. If matches returns true, the internal |
| | | * item counter is incremented (for maxResultSize functionality). |
| | |
| | | * @param item |
| | | * @return true if the given item matches this filter. |
| | | */ |
| | | public boolean matches(BorgFilesystemItem item) { |
| | | public boolean matches(FilesystemItem item) { |
| | | item.setDisplayPath(item.getPath()); |
| | | if (fileNumber != null) { |
| | | if (item.getFileNumber() == fileNumber) { |
| | |
| | | } |
| | | return false; |
| | | } |
| | | if (mode == Mode.TREE) { |
| | | // In this run only register all direct childs of currentDirectory. |
| | | String topLevelDir = getTopLevel(item.getPath()); |
| | | if (topLevelDir == null) { |
| | | // item is not inside the current directory. |
| | | if (item.getPath() == null) { |
| | | return false; |
| | | } |
| | | if (!subDirectories.containsKey(topLevelDir)) { |
| | | subDirectories.put(topLevelDir, item); |
| | | if (mode == Mode.TREE) { |
| | | if (currentDirectory != null && item.getPath().startsWith(currentDirectory) == false) { |
| | | return false; |
| | | } |
| | | } |
| | | if (searchKeyWords == null && blackListSearchKeyWords == null) { |
| | | processFinishedFlag(); |
| | | return true; |
| | | } |
| | | if (item.getPath() == null) { |
| | | return false; |
| | | } |
| | | String path = item.getPath().toLowerCase(); |
| | | if (searchKeyWords != null) { |
| | | for (String searchKeyWord : searchKeyWords) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * After processing a list by using {@link #matches(BorgFilesystemItem)} you should call finally this method with |
| | | * your result list to reduce the files and directories for mode {@link Mode#TREE}. For the mode {@link Mode#FLAT} |
| | | * nothing is done. |
| | | * Please ensure that you call matches exactly ones for every file item. If matches returns true, the internal |
| | | * item counter is incremented (for maxResultSize functionality). |
| | | * <br> |
| | | * Reorders the list (.files will be displayed after normal files). |
| | | * If the number of positive matches is greater than {@link #maxResultSize}, the finished flag is set to true. |
| | | * |
| | | * @param list |
| | | * @return The original list for mode {@link Mode#FLAT} or the reduced list for the tree view. |
| | | * @param item |
| | | * @return true if the given item matches this filter. |
| | | */ |
| | | public List<BorgFilesystemItem> reduce(List<BorgFilesystemItem> list) { |
| | | if (mode == FileSystemFilter.Mode.TREE) { |
| | | if (MapUtils.isEmpty(subDirectories)) { |
| | | // If matches was not called before, do this now for getting all subdirectories. |
| | | subDirectories = new HashMap<>(); |
| | | for (BorgFilesystemItem item : list) { |
| | | // Needed for building subdirectories... |
| | | this.matches(item); |
| | | public boolean matchesRecursive(FilesystemItem item) { |
| | | boolean matches = matches(item); |
| | | if (matches == true) { |
| | | return true; |
| | | } |
| | | } |
| | | Set<String> set = new HashSet<>(); |
| | | List<BorgFilesystemItem> list2 = list; |
| | | list = new ArrayList<>(); |
| | | for (BorgFilesystemItem item : list2) { |
| | | String topLevel = getTopLevel(item.getPath()); |
| | | if (topLevel == null) { |
| | | continue; |
| | | } |
| | | if (set.contains(topLevel) == false) { |
| | | set.add(topLevel); |
| | | BorgFilesystemItem topItem = subDirectories.get(topLevel); |
| | | topItem.setDisplayPath(StringUtils.removeStart(topItem.getPath(), currentDirectory)); |
| | | list.add(topItem); |
| | | } |
| | | } |
| | | list2 = list; |
| | | // Re-ordering (show dot files at last) |
| | | list = new ArrayList<>(); |
| | | // First add normal files: |
| | | for (BorgFilesystemItem item : list2) { |
| | | if (!item.getDisplayPath().startsWith(".")) { |
| | | list.add(item); |
| | | } |
| | | } |
| | | // Now add dot files: |
| | | for (BorgFilesystemItem item : list2) { |
| | | if (item.getDisplayPath().startsWith(".")) { |
| | | list.add(item); |
| | | if (item.getChilds() != null) { |
| | | for (FilesystemItem child : item.getChilds()) { |
| | | if (matchesRecursive(child)) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * @param path The path of the current item. |
| | | * @return null if the item is not a child of the current directory otherwise the top level sub directory name of |
| | | * the current directory. |
| | | */ |
| | | String getTopLevel(String path) { |
| | | if (StringUtils.isEmpty(currentDirectory)) { |
| | | int pos = path.indexOf('/'); |
| | | if (pos < 0) { |
| | | return path; |
| | | } |
| | | return path.substring(0, pos); |
| | | } |
| | | if (!path.startsWith(currentDirectory)) { |
| | | // item is not a child of currentDirectory. |
| | | return null; |
| | | } |
| | | if (path.length() <= currentDirectory.length() + 1) { |
| | | // Don't show the current directory itself. |
| | | return null; |
| | | } |
| | | path = StringUtils.removeStart(path, currentDirectory); |
| | | int pos = path.indexOf('/'); |
| | | if (pos < 0) { |
| | | return path; |
| | | } |
| | | return path.substring(0, pos); |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public FileSystemFilter setMode(Mode mode) { |
| | | this.mode = mode; |
| | | if (mode == Mode.TREE) { |
| | | this.subDirectories = new HashMap<>(); // needed only for tree view. |
| | | } |
| | | return this; |
| | | } |
| | | |
| | |
| | | |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.commons.lang3.builder.EqualsBuilder; |
| | | import org.apache.commons.lang3.builder.HashCodeBuilder; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | public class BorgFilesystemItem implements Serializable, Comparable<BorgFilesystemItem> { |
| | | private transient static Logger log = LoggerFactory.getLogger(BorgFilesystemItem.class); |
| | | private static final long serialVersionUID = -5545350851640655468L; |
| | | |
| | | /** |
| | | * If running in diff mode, this flag specifies the type of difference. Null represents unmodified. |
| | | */ |
| | | public enum DiffStatus {NEW, REMOVED, MODIFIED} |
| | | |
| | | /** |
| | | * d (directory), - (file) |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private String type; |
| | | protected String type; |
| | | /** |
| | | * Unix mode, e. g. <tt>drwxr-xr-x</tt> |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private String mode; |
| | | protected String mode; |
| | | @Getter |
| | | private String user; |
| | | protected String user; |
| | | @Getter |
| | | private String group; |
| | | protected String group; |
| | | @Getter |
| | | private long uid; |
| | | protected long uid; |
| | | @Getter |
| | | private long gid; |
| | | protected long gid; |
| | | @Getter |
| | | @Setter |
| | | private String path; |
| | | @Setter |
| | | protected String path; |
| | | @Getter |
| | | private String displayPath; |
| | | protected boolean healthy; |
| | | @Getter |
| | | private boolean healthy; |
| | | protected String source; |
| | | @Getter |
| | | private String source; |
| | | protected String linktarget; |
| | | @Getter |
| | | private String linktarget; |
| | | @Getter |
| | | private String flags; |
| | | protected String flags; |
| | | @Getter |
| | | @Setter |
| | | private String mtime; |
| | | protected String mtime; |
| | | @Getter |
| | | @Setter |
| | | private long size; |
| | | /** |
| | | * Represents the number of the file in the archive (for downloading). This field is created and only known by BorgButler. |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private int fileNumber; |
| | | /** |
| | | * If created by diff tool, this flag represents the type of difference. |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private DiffStatus diffStatus; |
| | | /** |
| | | * If created by diff tool, this object holds the file item of the other archive (diff archive). |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | private BorgFilesystemItem diffItem; |
| | | /** |
| | | * If created by diff tool, this String contains all differences between current and other item for {@link DiffStatus#MODIFIED}. |
| | | * This String may used for displaying. |
| | | */ |
| | | @Getter |
| | | private String differences; |
| | | protected long size; |
| | | |
| | | @Override |
| | | public int compareTo(BorgFilesystemItem o) { |
| | |
| | | } |
| | | return path.compareToIgnoreCase(o.path); |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object obj) { |
| | | if (obj == null) { |
| | | return false; |
| | | } |
| | | if (obj == this) { |
| | | return true; |
| | | } |
| | | if (obj.getClass() != getClass()) { |
| | | return false; |
| | | } |
| | | BorgFilesystemItem rhs = (BorgFilesystemItem) obj; |
| | | return new EqualsBuilder() |
| | | .append(path, rhs.path) |
| | | .append(type, rhs.type) |
| | | .append(mode, rhs.mode) |
| | | .append(user, rhs.user) |
| | | .append(group, rhs.group) |
| | | .append(uid, rhs.uid) |
| | | .append(gid, rhs.gid) |
| | | .append(mtime, rhs.mtime) |
| | | .append(size, rhs.size) |
| | | .append(flags, rhs.flags) |
| | | .isEquals(); |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return new HashCodeBuilder() |
| | | .append(path) |
| | | .append(type) |
| | | .append(mode) |
| | | .append(user) |
| | | .append(group) |
| | | .append(uid) |
| | | .append(gid) |
| | | .append(mtime) |
| | | .append(size) |
| | | .append(flags) |
| | | .toHashCode(); |
| | | } |
| | | |
| | | /** |
| | | * Compares all fields and creates human readable string with differences. |
| | | */ |
| | | public void buildDifferencesString() { |
| | | if (diffItem == null) { |
| | | // Nothing to do. |
| | | return; |
| | | } |
| | | if (!StringUtils.equals(this.path, diffItem.path)) { |
| | | log.error("*** Internal error: Differences should only be made on same path object: current='" + path + "', other='" + diffItem.path + "'."); |
| | | return; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | appendDiff(sb, "type", this.type, diffItem.type); |
| | | //appendDiff(sb, "mode", this.mode, diffItem.mode); // Done by frontend (jsx) |
| | | appendDiff(sb, "user", this.user, diffItem.user); |
| | | appendDiff(sb, "group", this.group, diffItem.group); |
| | | appendDiff(sb, "uid", this.uid, diffItem.uid); |
| | | appendDiff(sb, "gid", this.gid, diffItem.gid); |
| | | //appendDiff(sb, "mtime", this.mtime, diffItem.mtime); // Done by frontend (jsx) |
| | | //appendDiff(sb, "size", this.size, diffItem.size); // Done by frontend (jsx) |
| | | if (sb.length() > 0) { |
| | | diffStatus = DiffStatus.MODIFIED; |
| | | this.differences = sb.toString(); |
| | | } |
| | | } |
| | | |
| | | private void appendDiff(StringBuilder sb, String field, String current, String other) { |
| | | if (StringUtils.equals(current, other)) { |
| | | // Not modified. |
| | | return; |
| | | } |
| | | if (sb.length() > 0) { |
| | | sb.append(", "); |
| | | } |
| | | sb.append(field + ":['" + other + "'->'" + current + "']"); |
| | | } |
| | | |
| | | private void appendDiff(StringBuilder sb, String field, long current, long other) { |
| | | if (current == other) { |
| | | // Not modified. |
| | | return; |
| | | } |
| | | if (sb.length() > 0) { |
| | | sb.append(", "); |
| | | } |
| | | sb.append(field + ": ['" + current + "' -> '" + other + "']"); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return path; |
| | | } |
| | | } |
| | |
| | | package de.micromata.borgbutler; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | | import java.util.ArrayList; |
| | |
| | | public class DiffToolTest { |
| | | @Test |
| | | void differencesTest() { |
| | | BorgFilesystemItem i1 = create("etc", true, "drwx------", 0, "2018-11-21"); |
| | | BorgFilesystemItem i2 = create("etc", true, "drwx------", 0, "2018-11-21"); |
| | | FilesystemItem i1 = create("etc", true, "drwx------", 0, "2018-11-21"); |
| | | FilesystemItem i2 = create("etc", true, "drwx------", 0, "2018-11-21"); |
| | | assertTrue(i1.equals(i2)); |
| | | i1.setType("-").setMode("drwxrwxrwx").setMtime("2018-11-22"); |
| | | assertFalse(i1.equals(i2)); |
| | |
| | | |
| | | @Test |
| | | void diffToolTest() { |
| | | List<BorgFilesystemItem> l1 = null; |
| | | List<BorgFilesystemItem> l2 = null; |
| | | List<BorgFilesystemItem> result; |
| | | List<FilesystemItem> l1 = null; |
| | | List<FilesystemItem> l2 = null; |
| | | List<FilesystemItem> result; |
| | | assertEquals(0, DiffTool.extractDifferences(l1, l2).size()); |
| | | l1 = create(); |
| | | result = DiffTool.extractDifferences(l1, l2); |
| | | assertEquals(7, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | result = DiffTool.extractDifferences(l2, l1); |
| | | assertEquals(7, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | |
| | | l1 = create(); |
| | | l2 = create(); |
| | |
| | | get(l1, "home/kai/.borgbutler/borgbutler-config.json").setSize(712).setMtime("2018-11-22"); // 3 |
| | | result = DiffTool.extractDifferences(l1, l2); |
| | | assertEquals(4, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus()); |
| | | |
| | | result = DiffTool.extractDifferences(l2, l1); |
| | | assertEquals(4, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.MODIFIED, result.get(3).getDiffStatus()); |
| | | |
| | | l1 = create(); |
| | | l2 = create(); |
| | |
| | | remove(l1, "home/kai/.borgbutler/borgbutler-config.json"); // 2 |
| | | result = DiffTool.extractDifferences(l1, l2); |
| | | assertEquals(3, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus()); |
| | | result = DiffTool.extractDifferences(l2, l1); |
| | | assertEquals(3, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus()); |
| | | |
| | | |
| | | l1 = create(); |
| | |
| | | remove(l2, "home/kai/.borgbutler/borgbutler-config.json"); |
| | | result = DiffTool.extractDifferences(l1, l2); |
| | | assertEquals(2, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | result = DiffTool.extractDifferences(l2, l1); |
| | | assertEquals(2, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | |
| | | l1 = create(); |
| | | l2 = create(); |
| | |
| | | remove(l2, "home/kai/.borgbutler/borgbutler-config-bak.json"); |
| | | result = DiffTool.extractDifferences(l1, l2); |
| | | assertEquals(3, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(2).getDiffStatus()); |
| | | result = DiffTool.extractDifferences(l2, l1); |
| | | assertEquals(3, result.size()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus()); |
| | | assertEquals(FilesystemItem.DiffStatus.REMOVED, result.get(2).getDiffStatus()); |
| | | } |
| | | |
| | | private BorgFilesystemItem create(String path, boolean directory, String mode, long size, String mtime) { |
| | | return new BorgFilesystemItem() |
| | | private FilesystemItem create(String path, boolean directory, String mode, long size, String mtime) { |
| | | return (FilesystemItem)new FilesystemItem() |
| | | .setPath(path) |
| | | .setType(directory ? "d" : "-") |
| | | .setMode(mode) |
| | |
| | | .setMtime(mtime); |
| | | } |
| | | |
| | | private List<BorgFilesystemItem> create() { |
| | | List<BorgFilesystemItem> list = new ArrayList<>(); |
| | | private List<FilesystemItem> create() { |
| | | List<FilesystemItem> list = new ArrayList<>(); |
| | | list.add(create("etc", true, "drwx------", 0, "2018-11-21")); |
| | | list.add(create("etc/passwd", false, "-rwx------", 100, "2018-11-21")); |
| | | list.add(create("home", true, "drwx------", 0, "2018-11-21")); |
| | |
| | | return list; |
| | | } |
| | | |
| | | private void remove(List<BorgFilesystemItem> list, String path) { |
| | | BorgFilesystemItem item = get(list, path); |
| | | private void remove(List<FilesystemItem> list, String path) { |
| | | FilesystemItem item = get(list, path); |
| | | list.remove(item); |
| | | } |
| | | |
| | | private BorgFilesystemItem get(List<BorgFilesystemItem> list, String path) { |
| | | for (BorgFilesystemItem item : list) { |
| | | private FilesystemItem get(List<FilesystemItem> list, String path) { |
| | | for (FilesystemItem item : list) { |
| | | if (item.getPath().equals(path)) { |
| | | return item; |
| | | } |
| | |
| | | |
| | | import de.micromata.borgbutler.config.BorgRepoConfig; |
| | | import de.micromata.borgbutler.data.Archive; |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | |
| | | |
| | | @Test |
| | | void readWriteTest() throws Exception { |
| | | List<BorgFilesystemItem> list = createList(1000000); |
| | | List<FilesystemItem> list = createList(1000000); |
| | | ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 100); |
| | | cache.removeAllCacheFiles(); |
| | | BorgRepoConfig repoConfig = new BorgRepoConfig(); |
| | |
| | | cache.save(repoConfig, archive, list); |
| | | log.info("Saving done."); |
| | | log.info("Loading items from out dir."); |
| | | List<BorgFilesystemItem> filesystemItems = cache.load(repoConfig, archive); |
| | | List<FilesystemItem> filesystemItems = cache.load(repoConfig, archive); |
| | | log.info("Loading " + filesystemItems.size() + " items done."); |
| | | assertEquals(list.size(), filesystemItems.size()); |
| | | for (int i = 0; i < filesystemItems.size(); i++) { |
| | |
| | | |
| | | @Test |
| | | void readWriteEmptyTest() throws Exception { |
| | | List<BorgFilesystemItem> list = new ArrayList<>(); |
| | | List<FilesystemItem> list = new ArrayList<>(); |
| | | ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 100); |
| | | cache.removeAllCacheFiles(); |
| | | BorgRepoConfig repoConfig = new BorgRepoConfig(); |
| | |
| | | Archive archive = createArchive("2018-12-09"); |
| | | assertNull(cache.load(repoConfig, archive)); |
| | | cache.save(repoConfig, archive, list); |
| | | List<BorgFilesystemItem> filesystemItems = cache.load(repoConfig, archive); |
| | | List<FilesystemItem> filesystemItems = cache.load(repoConfig, archive); |
| | | assertNull(cache.load(repoConfig, archive)); |
| | | cache.removeAllCacheFiles(); |
| | | } |
| | | |
| | | @Test |
| | | void cleanUpMaximumSizeTest() throws Exception { |
| | | List<BorgFilesystemItem> list = createList(1000000); |
| | | List<FilesystemItem> list = createList(1000000); |
| | | ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 3); |
| | | cache.removeAllCacheFiles(); |
| | | BorgRepoConfig repoConfig = new BorgRepoConfig(); |
| | |
| | | |
| | | @Test |
| | | void cleanUpExpiredTest() throws Exception { |
| | | List<BorgFilesystemItem> list = createList(1000); |
| | | List<FilesystemItem> list = createList(1000); |
| | | ArchiveFilelistCache cache = new ArchiveFilelistCache(new File("out"), 3); |
| | | cache.removeAllCacheFiles(); |
| | | BorgRepoConfig repoConfig = new BorgRepoConfig(); |
| | |
| | | cache.removeAllCacheFiles(); |
| | | } |
| | | |
| | | private List<BorgFilesystemItem> createList(int number) throws Exception { |
| | | List<BorgFilesystemItem> list = new ArrayList<>(); |
| | | private List<FilesystemItem> createList(int number) throws Exception { |
| | | List<FilesystemItem> list = new ArrayList<>(); |
| | | for (int i = 0; i < 1000000; i++) { |
| | | list.add(create(i)); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private BorgFilesystemItem create(int i) throws Exception { |
| | | BorgFilesystemItem item = new BorgFilesystemItem(); |
| | | private FilesystemItem create(int i) throws Exception { |
| | | FilesystemItem item = new FilesystemItem(); |
| | | set(item, "type", "-").set(item, "mode", "drwxr-xr-x") |
| | | .set(item, "user", "kai").set(item, "group", "user") |
| | | .set(item, "path", "/Users/kai/Test" + i + ".java").set(item, "size", 1000); |
| | |
| | | import de.micromata.borgbutler.config.ConfigurationHandler; |
| | | import de.micromata.borgbutler.data.Archive; |
| | | import de.micromata.borgbutler.data.Repository; |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.slf4j.Logger; |
| | |
| | | assertNotNull(archive2); |
| | | archive = ButlerCache.getInstance().getArchive(repoConfig.getRepo(), archive.getId()); |
| | | assertNotNull(archive2); |
| | | List<BorgFilesystemItem> content = ButlerCache.getInstance().getArchiveContent(repoConfig, archive2); |
| | | List<FilesystemItem> content = ButlerCache.getInstance().getArchiveContent(repoConfig, archive2); |
| | | log.info("Number of items (content) of archive: " + content.size()); |
| | | content = ButlerCache.getInstance().getArchiveContent(repoConfig, archive2); |
| | | log.info("Number of items (content) of archive: " + content.size()); |
| New file |
| | |
| | | package de.micromata.borgbutler.cache; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | |
| | | |
| | | public class FilesystemTest { |
| | | private static Logger log = LoggerFactory.getLogger(FilesystemTest.class); |
| | | |
| | | @Test |
| | | void filesystemTest() { |
| | | List<BorgFilesystemItem> borgList = new ArrayList<>(); |
| | | borgList.add(create("home/kai/test.xls")); |
| | | FilesystemItem root = Filesystem.build(borgList); |
| | | List<FilesystemItem> list = root.getChilds(); |
| | | assertEquals(1, list.size()); |
| | | assertEquals("home", list.get(0).getName()); |
| | | assertEquals("kai", list.get(0).getChilds().get(0).getName()); |
| | | assertEquals("test.xls", list.get(0).getChilds().get(0).getChilds().get(0).getName()); |
| | | assertEquals("home", root.find("home").getName()); |
| | | assertEquals("kai", root.find("home/kai").getName()); |
| | | } |
| | | |
| | | private BorgFilesystemItem create(String path) { |
| | | return new BorgFilesystemItem().setPath(path); |
| | | } |
| | | } |
| | |
| | | package de.micromata.borgbutler.data; |
| | | |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | | import java.util.ArrayList; |
| | |
| | | assertEquals("kai", filter.getTopLevel("home/kai")); |
| | | assertEquals("kai", filter.getTopLevel("home/kai/test.java")); |
| | | assertNull(filter.getTopLevel("etc/test")); |
| | | List<BorgFilesystemItem> list = createList(); |
| | | List<FilesystemItem> list = createList(); |
| | | filter.setCurrentDirectory("").setMode(FileSystemFilter.Mode.TREE); |
| | | for (BorgFilesystemItem item : list) { |
| | | for (FilesystemItem item : list) { |
| | | if (filter.matches(item)) { |
| | | // Do nothing. |
| | | } |
| | | } |
| | | list = filter.reduce(list); |
| | | // list = filter.reduce(list); |
| | | assertEquals(2, list.size()); |
| | | list = createList(); |
| | | filter.setCurrentDirectory("home"); |
| | | for (BorgFilesystemItem item : list) { |
| | | for (FilesystemItem item : list) { |
| | | if (filter.matches(item)) { |
| | | // Do nothing. |
| | | } |
| | | } |
| | | list = filter.reduce(list); |
| | | // list = filter.reduce(list); |
| | | assertEquals(4, list.size()); |
| | | assertEquals(".bashrc", list.get(0).getDisplayPath()); |
| | | assertEquals(".borgbutler", list.get(1).getDisplayPath()); |
| | | |
| | | } |
| | | |
| | | private BorgFilesystemItem create(String path, boolean directory) { |
| | | BorgFilesystemItem item = new BorgFilesystemItem().setPath(path); |
| | | private FilesystemItem create(String path, boolean directory) { |
| | | FilesystemItem item = new FilesystemItem(); |
| | | item.setPath(path); |
| | | if (directory) { |
| | | item.setType("d"); |
| | | } else { |
| | |
| | | return item; |
| | | } |
| | | |
| | | private List<BorgFilesystemItem> createList() { |
| | | List<BorgFilesystemItem> list = new ArrayList<>(); |
| | | private List<FilesystemItem> createList() { |
| | | List<FilesystemItem> list = new ArrayList<>(); |
| | | list.add(create("home", true)); |
| | | list.add(create("home/.bashrc", false)); |
| | | list.add(create("home/.borgbutler", true)); |
| | |
| | | |
| | | import de.micromata.borgbutler.cache.ButlerCache; |
| | | import de.micromata.borgbutler.config.ConfigurationHandler; |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import de.micromata.borgbutler.server.jetty.JettyServer; |
| | | import de.micromata.borgbutler.server.user.SingleUserManager; |
| | | import de.micromata.borgbutler.server.user.UserManager; |
| | |
| | | |
| | | private static void printArchiveContent(String fileName) { |
| | | File file = new File(fileName); |
| | | List<BorgFilesystemItem> fileList = ButlerCache.getInstance().getArchiveContent(file); |
| | | List<FilesystemItem> fileList = ButlerCache.getInstance().getArchiveContent(file); |
| | | boolean parseFormatExceptionPrinted = false; |
| | | if (fileList != null && fileList.size() > 0) { |
| | | TimeZone tz = TimeZone.getTimeZone("UTC"); |
| | |
| | | File out = new File(FilenameUtils.getBaseName(fileName) + ".txt.gz"); |
| | | log.info("Writing file list to: " + out.getAbsolutePath()); |
| | | try (PrintWriter writer = new PrintWriter(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(out))))) { |
| | | for (BorgFilesystemItem item : fileList) { |
| | | for (FilesystemItem item : fileList) { |
| | | String time = item.getMtime(); |
| | | if (time.indexOf('T') > 0) { |
| | | try { |
| | |
| | | import de.micromata.borgbutler.data.FileSystemFilter; |
| | | import de.micromata.borgbutler.data.Repository; |
| | | import de.micromata.borgbutler.json.JsonUtils; |
| | | import de.micromata.borgbutler.json.borg.BorgFilesystemItem; |
| | | import de.micromata.borgbutler.cache.FilesystemItem; |
| | | import de.micromata.borgbutler.utils.DirUtils; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | |
| | | .setMaxResultSize(maxSize) |
| | | .setMode(mode) |
| | | .setCurrentDirectory(currentDirectory); |
| | | List<BorgFilesystemItem> items = null; |
| | | List<FilesystemItem> items = null; |
| | | if (StringUtils.isBlank(diffArchiveId)) { |
| | | // Get file list (without running diff). |
| | | items = ButlerCache.getInstance().getArchiveContent(archiveId, force, |
| | |
| | | } else { |
| | | filter.setMode(FileSystemFilter.Mode.FLAT).setMaxResultSize(-1); |
| | | items = ButlerCache.getInstance().getArchiveContent(archiveId, true, filter); |
| | | List<BorgFilesystemItem> diffItems = ButlerCache.getInstance().getArchiveContent(diffArchiveId, true, |
| | | List<FilesystemItem> diffItems = ButlerCache.getInstance().getArchiveContent(diffArchiveId, true, |
| | | filter); |
| | | items = DiffTool.extractDifferences(items, diffItems); |
| | | filter.setMaxResultSize(maxSize) |
| | |
| | | public Response restore(@QueryParam("archiveId") String archiveId, @QueryParam("fileNumber") int fileNumber) { |
| | | log.info("Requesting file #" + fileNumber + " of archive '" + archiveId + "'."); |
| | | FileSystemFilter filter = new FileSystemFilter().setFileNumber(fileNumber); |
| | | List<BorgFilesystemItem> items = ButlerCache.getInstance().getArchiveContent(archiveId, false, |
| | | List<FilesystemItem> items = ButlerCache.getInstance().getArchiveContent(archiveId, false, |
| | | filter); |
| | | if (CollectionUtils.isEmpty(items)) { |
| | | log.error("Requested file #" + fileNumber + " not found in archive '" + archiveId |
| | |
| | | } |
| | | BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(archive.getRepoId()); |
| | | try { |
| | | BorgFilesystemItem item = items.get(0); |
| | | FilesystemItem item = items.get(0); |
| | | File restoreHomeDir = ConfigurationHandler.getConfiguration().getRestoreHomeDir(); |
| | | File restoreDir = BorgCommands.extractFiles(restoreHomeDir, repoConfig, archive, item.getPath()); |
| | | List<java.nio.file.Path> files = DirUtils.listFiles(restoreDir.toPath()); |