mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
09.41.2019 f218947aa4129f54eb8325bdd3140e5dac0e0ece
DiffFileSystemFilter...
2 files renamed
2 files modified
145 ■■■■ changed files
borgbutler-core/src/main/java/de/micromata/borgbutler/data/DiffFileSystemFilter.java 19 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java 67 ●●●● patch | view | raw | blame | history
borgbutler-core/src/test/java/de/micromata/borgbutler/DiffFileSystemFilterTest.java 28 ●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java 31 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/data/DiffFileSystemFilter.java
File was renamed from borgbutler-core/src/main/java/de/micromata/borgbutler/DiffTool.java
@@ -1,4 +1,4 @@
package de.micromata.borgbutler;
package de.micromata.borgbutler.data;
import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
import org.slf4j.Logger;
@@ -11,15 +11,15 @@
/**
 * Extracts the differences between two archives of one repo.
 */
public class DiffTool {
    private static Logger log = LoggerFactory.getLogger(DiffTool.class);
public class DiffFileSystemFilter extends FileSystemFilter {
    private Logger log = LoggerFactory.getLogger(DiffFileSystemFilter.class);
    /**
     * @param items      Sorted list of items from the current archive.
     * @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) {
    public 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<>();
@@ -37,7 +37,8 @@
            }
            int cmp = current.compareTo(other);
            if (cmp == 0) { // Items represents both the same file system item.
                if (current.equals(other)) {
                if (!checkDirectoryMatchAndRegisterSubDirectories(current) ||
                        current.equals(other)) {
                    current = other = null; // increment both iterators.
                    continue;
                }
@@ -48,10 +49,14 @@
                result.add(current);
                current = other = null; // increment both iterators.
            } else if (cmp < 0) {
                result.add(current.setDiffStatus(BorgFilesystemItem.DiffStatus.NEW));
                if (checkDirectoryMatchAndRegisterSubDirectories(current)) {
                    result.add(current.setDiffStatus(BorgFilesystemItem.DiffStatus.NEW));
                }
                current = currentIt.hasNext() ? currentIt.next() : null;
            } else {
                result.add(other.setDiffStatus(BorgFilesystemItem.DiffStatus.REMOVED));
                if (checkDirectoryMatchAndRegisterSubDirectories(other)) {
                    result.add(other.setDiffStatus(BorgFilesystemItem.DiffStatus.REMOVED));
                }
                other = otherIt.hasNext() ? otherIt.next() : null;
            }
        }
borgbutler-core/src/main/java/de/micromata/borgbutler/data/FileSystemFilter.java
@@ -83,35 +83,6 @@
    }
    /**
     * This method has only effect in FLAT view. This method has to be called for every item of the list before
     * {@link #reduce(List)} may work, because this method registers sub directories of the current directory needed
     * by {@link #reduce(List)}.
     *
     * @param item
     * @return false, if the given item is not a sub item of the current directory. You may skip further checkings for this
     * item. If true, this item might be part of the result.
     */
    boolean checkDirectoryMatchAndRegisterSubDirectories(BorgFilesystemItem item) {
        if (mode != Mode.TREE) {
            return true;
        }
        if (StringUtils.isNotEmpty(currentDirectory) && !item.getPath().startsWith(currentDirectory)) {
            // item is not inside the current directory.
            return false;
        }
        // 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.
            return false;
        }
        if (!subDirectories.containsKey(topLevelDir)) {
            subDirectories.put(topLevelDir, item);
        }
        return true;
}
    /**
     * 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.
@@ -136,8 +107,12 @@
            if (set.contains(topLevel) == false) {
                set.add(topLevel);
                BorgFilesystemItem topItem = subDirectories.get(topLevel);
                topItem.setDisplayPath(StringUtils.removeStart(topItem.getPath(), currentDirectory));
                list.add(topItem);
                if (topItem == null) {
                    log.error("Internal error, can't find subDirectory: " + topLevel);
                } else {
                    topItem.setDisplayPath(StringUtils.removeStart(topItem.getPath(), currentDirectory));
                    list.add(topItem);
                }
            }
        }
        list2 = list;
@@ -194,6 +169,36 @@
    }
    /**
     * This method has only effect in FLAT view. This method has to be called for every item of the list before
     * {@link #reduce(List)} may work, because this method registers sub directories of the current directory needed
     * by {@link #reduce(List)}.
     *
     * @param item
     * @return false, if the given item is not a sub item of the current directory. You may skip further checkings for this
     * item. If true, this item might be part of the result.
     */
    protected boolean checkDirectoryMatchAndRegisterSubDirectories(BorgFilesystemItem item) {
        if (mode != Mode.TREE) {
            return true;
        }
        if (StringUtils.isNotEmpty(currentDirectory) && !item.getPath().startsWith(currentDirectory)) {
            // item is not inside the current directory.
            return false;
        }
        // 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.
            return false;
        }
        if (!subDirectories.containsKey(topLevelDir)) {
            subDirectories.put(topLevelDir, item);
        }
        return true;
    }
    /**
     * currentDirectory '': <tt>home</tt> -&gt; <tt>home</tt><br>
     * currentDirectory '': <tt>home/kai</tt> -&gt; <tt>home</tt><br>
     * currentDirectory 'home': <tt>home</tt> -&gt; <tt>null</tt><br>
borgbutler-core/src/test/java/de/micromata/borgbutler/DiffFileSystemFilterTest.java
File was renamed from borgbutler-core/src/test/java/de/micromata/borgbutler/DiffToolTest.java
@@ -1,5 +1,6 @@
package de.micromata.borgbutler;
import de.micromata.borgbutler.data.DiffFileSystemFilter;
import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
import org.junit.jupiter.api.Test;
@@ -9,7 +10,7 @@
import static org.junit.jupiter.api.Assertions.*;
public class DiffToolTest {
public class DiffFileSystemFilterTest {
    @Test
    void differencesTest() {
        BorgFilesystemItem i1 = create("etc", true, "drwx------", 0, "2018-11-21");
@@ -28,33 +29,34 @@
        List<BorgFilesystemItem> l1 = null;
        List<BorgFilesystemItem> l2 = null;
        List<BorgFilesystemItem> result;
        assertEquals(0, DiffTool.extractDifferences(l1, l2).size());
        DiffFileSystemFilter filter = new DiffFileSystemFilter();
        assertEquals(0, filter.extractDifferences(l1, l2).size());
        l1 = create();
        result = DiffTool.extractDifferences(l1, l2);
        result = filter.extractDifferences(l1, l2);
        assertEquals(7, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
        result = DiffTool.extractDifferences(l2, l1);
        result = filter.extractDifferences(l2, l1);
        assertEquals(7, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
        l1 = create();
        l2 = create();
        result = DiffTool.extractDifferences(l2, l1);
        result = filter.extractDifferences(l2, l1);
        assertEquals(0, result.size());
        remove(l2, "etc"); // 0
        remove(l2, "etc/passwd"); // 1
        remove(l1, "home/kai/.borgbutler/borgbutler-config-bak.json"); // 2
        get(l1, "home/kai/.borgbutler/borgbutler-config.json").setSize(712).setMtime("2018-11-22"); // 3
        result = DiffTool.extractDifferences(l1, l2);
        result = filter.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());
        result = DiffTool.extractDifferences(l2, l1);
        result = filter.extractDifferences(l2, l1);
        assertEquals(4, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
@@ -66,12 +68,12 @@
        remove(l2, "etc"); // 0
        remove(l2, "etc/passwd"); // 1
        remove(l1, "home/kai/.borgbutler/borgbutler-config.json"); // 2
        result = DiffTool.extractDifferences(l1, l2);
        result = filter.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());
        result = DiffTool.extractDifferences(l2, l1);
        result = filter.extractDifferences(l2, l1);
        assertEquals(3, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
@@ -82,11 +84,11 @@
        l2 = create();
        remove(l1, "home/kai/.borgbutler/borgbutler-config-bak.json");
        remove(l2, "home/kai/.borgbutler/borgbutler-config.json");
        result = DiffTool.extractDifferences(l1, l2);
        result = filter.extractDifferences(l1, l2);
        assertEquals(2, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
        result = DiffTool.extractDifferences(l2, l1);
        result = filter.extractDifferences(l2, l1);
        assertEquals(2, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.REMOVED, result.get(1).getDiffStatus());
@@ -96,12 +98,12 @@
        remove(l1, "home/kai");
        remove(l1, "home/kai/.borgbutler");
        remove(l2, "home/kai/.borgbutler/borgbutler-config-bak.json");
        result = DiffTool.extractDifferences(l1, l2);
        result = filter.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());
        result = DiffTool.extractDifferences(l2, l1);
        result = filter.extractDifferences(l2, l1);
        assertEquals(3, result.size());
        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(0).getDiffStatus());
        assertEquals(BorgFilesystemItem.DiffStatus.NEW, result.get(1).getDiffStatus());
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
@@ -1,11 +1,11 @@
package de.micromata.borgbutler.server.rest;
import de.micromata.borgbutler.BorgCommands;
import de.micromata.borgbutler.DiffTool;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.data.Archive;
import de.micromata.borgbutler.data.DiffFileSystemFilter;
import de.micromata.borgbutler.data.FileSystemFilter;
import de.micromata.borgbutler.data.Repository;
import de.micromata.borgbutler.json.JsonUtils;
@@ -77,29 +77,30 @@
                                     @QueryParam("diffArchiveId") String diffArchiveId,
                                     @QueryParam("force") boolean force,
                                     @QueryParam("prettyPrinter") boolean prettyPrinter) {
        boolean diffMode = StringUtils.isNotBlank(diffArchiveId);
        int maxSize = NumberUtils.toInt(maxResultSize, 50);
        FileSystemFilter filter = new FileSystemFilter()
                .setSearchString(searchString)
                .setMaxResultSize(maxSize)
                .setMode(mode)
        FileSystemFilter filter = diffMode ? new DiffFileSystemFilter() : new FileSystemFilter();
        filter.setSearchString(searchString)
                .setCurrentDirectory(currentDirectory);
        List<BorgFilesystemItem> items = null;
        if (StringUtils.isBlank(diffArchiveId)) {
        if (diffMode) {
            filter.setMode(FileSystemFilter.Mode.FLAT);
            items = ButlerCache.getInstance().getArchiveContent(archiveId, true, filter);
            List<BorgFilesystemItem> diffItems = ButlerCache.getInstance().getArchiveContent(diffArchiveId, true,
                    filter);
            filter.setMaxResultSize(maxSize)
                    .setMode(mode);
            items = ((DiffFileSystemFilter) filter).extractDifferences(items, diffItems);
            items = filter.reduce(items);
        } else {
            filter.setMode(mode)
                    .setMaxResultSize(maxSize);
            // Get file list (without running diff).
            items = ButlerCache.getInstance().getArchiveContent(archiveId, force,
                    filter);
            if (items == null) {
                return "[{\"mode\": \"notLoaded\"}]";
            }
        } else {
            filter.setMode(FileSystemFilter.Mode.FLAT).setMaxResultSize(-1);
            items = ButlerCache.getInstance().getArchiveContent(archiveId, true, filter);
            List<BorgFilesystemItem> diffItems = ButlerCache.getInstance().getArchiveContent(diffArchiveId, true,
                    filter);
            items = DiffTool.extractDifferences(items, diffItems);
            filter.setMaxResultSize(maxSize)
                    .setMode(mode);
            items = filter.reduce(items);
        }
        return JsonUtils.toJson(items, prettyPrinter);
    }