• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ljacqu / FileDuplicateFinder / 5661257559

25 Jul 2023 08:04PM UTC coverage: 23.055% (-0.4%) from 23.453%
5661257559

push

github

ljacqu
Merge remote-tracking branch 'origin/master'

111 of 610 branches covered (18.2%)

Branch coverage included in aggregate %.

378 of 1511 relevant lines covered (25.02%)

1.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.0
/src/main/java/ch/jalu/fileduplicatefinder/folderdiff/FolderDiffRunner.java
1
package ch.jalu.fileduplicatefinder.folderdiff;
2

3
import ch.jalu.fileduplicatefinder.config.FileUtilConfiguration;
4
import ch.jalu.fileduplicatefinder.hashing.FileHasherFactory;
5
import ch.jalu.fileduplicatefinder.output.WriterReader;
6
import ch.jalu.fileduplicatefinder.utils.ConsoleProgressListener;
7
import ch.jalu.fileduplicatefinder.utils.PathUtils;
8
import com.google.common.annotations.VisibleForTesting;
9

10
import javax.annotation.Nullable;
11
import java.io.File;
12
import java.nio.file.Path;
13
import java.util.Comparator;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.stream.Collectors;
18

19
import static ch.jalu.fileduplicatefinder.config.FileUtilSettings.DIFF_FILES_PROCESSED_INTERVAL;
20
import static ch.jalu.fileduplicatefinder.config.FileUtilSettings.DIFF_FOLDER1;
21
import static ch.jalu.fileduplicatefinder.config.FileUtilSettings.DIFF_FOLDER2;
22
import static ch.jalu.fileduplicatefinder.config.FileUtilSettings.DIFF_USE_SMART_FOLDER_PREFIXES;
23
import static com.google.common.base.MoreObjects.firstNonNull;
24

25
public class FolderDiffRunner {
26

27
    public static final String ID = "diff";
28

29
    private final FileUtilConfiguration configuration;
30
    private final FileHasherFactory fileHasherFactory;
31
    private final WriterReader logger;
32

33
    public FolderDiffRunner(FileUtilConfiguration configuration, FileHasherFactory fileHasherFactory,
34
                            WriterReader logger) {
2✔
35
        this.configuration = configuration;
3✔
36
        this.fileHasherFactory = fileHasherFactory;
3✔
37
        this.logger = logger;
3✔
38
    }
1✔
39

40
    public void run() {
41
        Path folder1 = configuration.getValueOrPrompt(DIFF_FOLDER1);
×
42
        Path folder2 = configuration.getValueOrPrompt(DIFF_FOLDER2);
×
43

44
        int notificationInterval = configuration.getValue(DIFF_FILES_PROCESSED_INTERVAL);
×
45
        List<FileDifference> differences = new FolderDiffAnalyzer(folder1, folder2, configuration, fileHasherFactory)
×
46
            .collectDifferences(new ProgressUpdater(notificationInterval));
×
47

48
        System.out.println();
×
49
        System.out.println();
×
50
        outputDifferences(folder1, folder2, differences);
×
51
    }
×
52

53
    private void outputDifferences(Path folder1, Path folder2, List<FileDifference> differences) {
54
        outputTotal(differences);
×
55

56
        String folder1Prefix;
57
        String folder2Prefix;
58
        if (configuration.getValue(DIFF_USE_SMART_FOLDER_PREFIXES)) {
×
59
            String[] prefixes = getPrefixesForFolders(folder1, folder2);
×
60
            folder1Prefix = prefixes[0];
×
61
            folder2Prefix = prefixes[1];
×
62
        } else {
×
63
            folder1Prefix = "folder1" + File.separator;
×
64
            folder2Prefix = "folder2" + File.separator;
×
65
        }
66

67
        differences.stream()
×
68
            .sorted(Comparator.comparing(FileDifference::getSortCodeForDiffType))
×
69
            .forEach(diff -> {
×
70
                if (diff.getFolder1Element() == null) {
×
71
                    logger.printLn("+ " + folder2Prefix + diff.getFolder2Element());
×
72
                } else if (diff.getFolder2Element() == null) {
×
73
                    logger.printLn("- " + folder1Prefix + diff.getFolder1Element());
×
74
                } else {
75
                    String actionPrefix = diff.wasModified() ? "*" : ">";
×
76
                    logger.printLn(actionPrefix + " " + folder1Prefix + diff.getFolder1Element().getName()
×
77
                        + " -> " + folder2Prefix + diff.getFolder2Element().getName());
×
78
                }
79
            });
×
80
    }
×
81

82
    /**
83
     * Outputs a total row with a summary of the differences that were found.
84
     *
85
     * @param differences the differences to analyze
86
     */
87
    private void outputTotal(List<FileDifference> differences) {
88
        Map<String, Integer> countByType = new HashMap<>();
×
89
        int total = 0;
×
90
        for (FileDifference diff : differences) {
×
91
            String symbol;
92
            if (diff.getFolder1Element() == null) {
×
93
                symbol = "+";
×
94
            } else if (diff.getFolder2Element() == null) {
×
95
                symbol = "-";
×
96
            } else if (diff.wasModified()) {
×
97
                symbol = "*";
×
98
            } else {
99
                symbol = ">";
×
100
            }
101
            countByType.merge(symbol, 1, Integer::sum);
×
102
            ++total;
×
103
        }
×
104

105
        if (total == 0) {
×
106
            logger.printLn("Did not find any differences! Both folders match perfectly.");
×
107
        } else {
108
            List<String> descriptions = List.of(
×
109
                countByType.get("+") + " additions (+)",
×
110
                countByType.get("-") + " removals (-)",
×
111
                countByType.get("*") + " modifications (*)",
×
112
                countByType.get(">") + " renamings (>)");
×
113

114
            logger.printLn("Found " + total + " changes: " +
×
115
                descriptions.stream().filter(count -> !count.startsWith("null")).collect(Collectors.joining(", ")));
×
116
        }
117
    }
×
118

119
    /**
120
     * Returns an array with two elements that should be used as textual representation of the two folders that
121
     * were chosen. This method attempts to find the most relevant path elements of the folders that differ from each
122
     * other. If nothing can be found, "folder1" and "folder2" are returned.
123
     *
124
     * @param folder1 the folder that was diffed
125
     * @param folder2 second folder the first folder was diffed with
126
     * @return array with two elements for the two folders
127
     */
128
    @VisibleForTesting
129
    String[] getPrefixesForFolders(Path folder1, Path folder2) {
130
        String separator = File.separator;
2✔
131
        String folder1Name = folder1.getFileName().toString();
4✔
132
        String folder2Name = folder2.getFileName().toString();
4✔
133
        if (!folder1Name.equals(folder2Name)) {
4!
134
            return new String[]{ folder1Name + separator, folder2Name + separator };
×
135
        }
136

137
        String folder1Parent = getParentName(folder1);
4✔
138
        String folder2Parent = getParentName(folder2);
4✔
139
        if (folder1Parent != null && folder2Parent != null && !folder1Parent.equals(folder2Parent)) {
8!
140
            return new String[]{ folder1Parent + "…" + separator, folder2Parent + "…" + separator };
15✔
141
        }
142

143
        String folder1Root = PathUtils.toStringNullSafe(folder1.getRoot());
4✔
144
        String folder2Root = PathUtils.toStringNullSafe(folder2.getRoot());
4✔
145
        if (folder1Root != null && folder2Root != null
6!
146
                && !folder1Root.startsWith(".") && !folder1Root.equals(folder2Root)) {
6!
147
            return new String[]{ folder1Root + "…" + separator, folder2Root + "…" + separator };
×
148
        }
149
        return new String[]{ "folder1" + separator, "folder2" + separator };
13✔
150
    }
151

152
    @Nullable
153
    private String getParentName(Path path) {
154
        Path parent = path.getParent();
3✔
155
        if (parent != null) {
2!
156
            Path parentFileName = parent.getFileName(); // null for Windows drives, e.g. for Paths.get("C:/")
3✔
157
            return firstNonNull(parentFileName, parent).toString();
6✔
158
        }
159
        return null;
×
160
    }
161

162
    /**
163
     * Logs the progress of the folder diff to the console.
164
     */
165
    private final class ProgressUpdater implements FolderDiffProgressCallback {
166

167
        private final ConsoleProgressListener scanProgressListener;
168
        private final ConsoleProgressListener analysisProgressListener;
169

170
        ProgressUpdater(int notificationInterval) {
×
171
            this.scanProgressListener = new ConsoleProgressListener(notificationInterval);
×
172
            this.analysisProgressListener = new ConsoleProgressListener(notificationInterval);
×
173
        }
×
174

175
        @Override
176
        public void startScan() {
177
            logger.print("Scanning files:  ");
×
178
        }
×
179

180
        @Override
181
        public void notifyScanProgress() {
182
            scanProgressListener.notifyItemProcessed();
×
183
        }
×
184

185
        @Override
186
        public void startAnalysis() {
187
            logger.printLn("");
×
188
            logger.print("Comparing files: ");
×
189
        }
×
190

191
        @Override
192
        public void notifyAnalysisProgress() {
193
            analysisProgressListener.notifyItemProcessed();
×
194
        }
×
195
    }
196
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc