Skip to content

Commit

Permalink
Add --diff
Browse files Browse the repository at this point in the history
  • Loading branch information
alban-auzeill committed Sep 27, 2020
1 parent b9dfcfa commit 3ac8d7a
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 1 deletion.
84 changes: 84 additions & 0 deletions src/main/java/com/auzeill/file/StatContext.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package com.auzeill.file;

import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
import java.util.stream.Collectors;

import static java.nio.charset.StandardCharsets.UTF_8;

Expand All @@ -28,29 +33,35 @@ public class StatContext {
private static final String NO_SHA1 = "--no-sha1";
private static final String IGNORE = "--ignore";
private static final String SAVE = "--save";
private static final String DIFF = "--diff";

public final Path baseDirectory;
public final Path statsDirectory;
public final Path rootPath;
public final boolean computeSha1;
public final boolean save;
public final boolean diff;
public final Set<String> ignoreSet;
public final Map<String, FileAttributes> lastFileAttributesMap;
public final List<String> previousPathsToDiff;

public StatContext(Path baseDirectory, Path rootPath, boolean computeSha1) {
this.baseDirectory = baseDirectory;
this.statsDirectory = this.baseDirectory.resolve(StatContext.DEFAULT_STATS_DIRECTORY);
this.rootPath = rootPath;
this.computeSha1 = computeSha1;
this.save = false;
this.diff = false;
this.ignoreSet = new HashSet<>();
this.lastFileAttributesMap = new HashMap<>();
this.previousPathsToDiff = Collections.emptyList();
}

public StatContext(String[] args) throws IOException {
List<String> arguments = new ArrayList<>(Arrays.asList(args));
this.computeSha1 = !arguments.remove(NO_SHA1);
this.save = arguments.remove(SAVE);
this.diff = arguments.remove(DIFF);
this.ignoreSet = new HashSet<>();
int ignorePos = arguments.lastIndexOf(IGNORE);
while (ignorePos != -1 && ignorePos + 1 < arguments.size()) {
Expand Down Expand Up @@ -103,6 +114,17 @@ public StatContext(String[] args) throws IOException {
}
}
}

this.previousPathsToDiff = this.lastFileAttributesMap.keySet().stream()
.sorted(Comparator.comparing(StatContext::pathToSort))
.collect(Collectors.toCollection(LinkedList::new));
}

private static String pathToSort(String path) {
if (path.equals(".")) {
return "\uFFFF";
}
return path.replace('\\', '\uFFFF').replace('/', '\uFFFF');
}

public Path newStatSavedPath() {
Expand All @@ -115,4 +137,66 @@ public boolean include(String relativeLinuxPath) {
return !ignoreSet.contains(relativeLinuxPath);
}

public void printStats(PrintStream out, FileAttributes attributes) {
if (diff) {
Iterator<String> previousIterator = previousPathsToDiff.iterator();
boolean compared = false;
while (previousIterator.hasNext()) {
FileAttributes prevAttributes = this.lastFileAttributesMap.get(previousIterator.next());
int comp = pathToSort(prevAttributes.relativeLinuxPath).compareTo(pathToSort(attributes.relativeLinuxPath));
if (comp < 0) {
out.println("-del- " + prevAttributes.toString());
previousIterator.remove();
} else if (comp == 0) {
compared = true;
previousIterator.remove();
if (!prevAttributes.toString().equals(attributes.toString())) {
StringBuilder diffLine = new StringBuilder();
diffLine.append("~mod~ ").append(attributes.relativeLinuxPath).append("|");
if (prevAttributes.type != attributes.type) {
diffLine.append(" type ").append(prevAttributes.type).append(" -> ").append(attributes.type).append(" |");
}
if (prevAttributes.size != attributes.size) {
diffLine.append(" size ").append(prevAttributes.size).append(" -> ").append(attributes.size).append(" |");
}
if (!prevAttributes.owner.equals(attributes.owner)) {
diffLine.append(" owner ").append(prevAttributes.owner).append(" -> ").append(attributes.owner).append(" |");
}
if (!prevAttributes.group.equals(attributes.group)) {
diffLine.append(" group ").append(prevAttributes.group).append(" -> ").append(attributes.group).append(" |");
}
if (!prevAttributes.permissions.equals(attributes.permissions)) {
diffLine.append(" permissions ").append(prevAttributes.permissions).append(" -> ").append(attributes.permissions).append(" |");
}
if (!prevAttributes.modifiedTime.equals(attributes.modifiedTime)) {
diffLine.append(" modifiedTime ").append(prevAttributes.modifiedTime).append(" -> ").append(attributes.modifiedTime).append(" |");
}
if (!prevAttributes.sha1OrSymbolicLink.equals(attributes.sha1OrSymbolicLink)) {
diffLine.append(" sha1OrSymbolicLink ").append(prevAttributes.sha1OrSymbolicLink).append(" -> ").append(attributes.sha1OrSymbolicLink).append(" |");
}
out.println(diffLine.toString());
}
} else {
break;
}
}
if (!compared) {
out.println("+new+ " + attributes.toString());
}
} else {
out.println(attributes.toString());
}
}

public void exitStats(PrintStream out) {
if (diff) {
Iterator<String> previousIterator = previousPathsToDiff.iterator();
while (previousIterator.hasNext()) {
FileAttributes prevAttributes = this.lastFileAttributesMap.get(previousIterator.next());
out.println("-del- " + prevAttributes.toString());
previousIterator.remove();
}
}
}

}
3 changes: 2 additions & 1 deletion src/main/java/com/auzeill/file/Stats.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static void stats(PrintStream out, String[] args) throws IOException {
} else {
stats(out, context, context.rootPath);
}
context.exitStats(out);
}

public static FileAttributes stats(PrintStream out, StatContext context, Path path) throws IOException {
Expand Down Expand Up @@ -61,7 +62,7 @@ public static FileAttributes stats(PrintStream out, StatContext context, Path pa
attributes.modifiedTime,
context.computeSha1 ? Sha1.digest(allSha1.toString().getBytes(UTF_8)) : "");
}
out.println(attributes.toString());
context.printStats(out, attributes);
return attributes;
} else {
return null;
Expand Down
8 changes: 8 additions & 0 deletions src/test/java/com/auzeill/file/StatContextTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void one_argument() throws IOException {
assertThat(context.baseDirectory.toString()).isEqualTo(Paths.get("src").toRealPath().toString());
assertThat(context.computeSha1).isEqualTo(true);
assertThat(context.save).isEqualTo(false);
assertThat(context.diff).isEqualTo(false);
}

@Test
Expand All @@ -37,4 +38,11 @@ void save() throws IOException {
assertThat(context.save).isEqualTo(true);
}

@Test
void diff() throws IOException {
StatContext context = new StatContext(new String[] {"--diff", "src"});
assertThat(context.baseDirectory.toString()).isEqualTo(Paths.get("src").toRealPath().toString());
assertThat(context.diff).isEqualTo(true);
}

}
37 changes: 37 additions & 0 deletions src/test/java/com/auzeill/file/StatsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,41 @@ void reuse_sha1_from_previous_save(@TempDir Path tempDir) throws IOException {
".|d|4|alban|alban|rwx------|2020-09-02T15:43:48.680382Z|158b484ae1f6f64f89da22397d25fbdafad02252" + System.lineSeparator());
}

@Test
void diff_from_previous(@TempDir Path tempDir) throws IOException {
Files.writeString(tempDir.resolve("f1"), "abcd", UTF_8);
Files.writeString(tempDir.resolve("f2"), "efgh", UTF_8);
Files.writeString(tempDir.resolve("f3"), "ijdk", UTF_8);
Files.writeString(tempDir.resolve("f5"), "efgh", UTF_8);

ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(out, true, UTF_8);
Stats.stats(stream, new String[] { "--save", tempDir.toString() });
String output = new String(out.toByteArray(), UTF_8);
assertThat(output).matches(tempDir.toString() + File.separator + ".directory-stats" + File.separator + "stat-\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}h\\d{2}m\\d{2}s\\d{3}" + System.lineSeparator());
String statPath = output.replaceFirst("[\r\n]+$", "");
String fileContent = Files.readString(Paths.get(statPath), UTF_8);
assertThat(FileAttributesTest.forceSysFields(fileContent)).isEqualTo("" +
"f1|f|4|alban|alban|rw-r--r--|2020-09-02T15:43:48.680382Z|81fe8bfe87576c3ecb22426f8e57847382917acf" + System.lineSeparator() +
"f2|f|4|alban|alban|rw-r--r--|2020-09-02T15:43:48.680382Z|2aed8aa9f826c21ef07d5ee15b48eea06e9c8a62" + System.lineSeparator() +
"f3|f|4|alban|alban|rw-r--r--|2020-09-02T15:43:48.680382Z|cca5603cae64651971a35bc1488f0d23ddabdff9" + System.lineSeparator() +
"f5|f|4|alban|alban|rw-r--r--|2020-09-02T15:43:48.680382Z|2aed8aa9f826c21ef07d5ee15b48eea06e9c8a62" + System.lineSeparator() +
".|d|16|alban|alban|rwx------|2020-09-02T15:43:48.680382Z|f81b3e16656c1bd84d7522ed2f83fa996ffd8497" + System.lineSeparator());


Files.delete(tempDir.resolve("f2"));
Files.writeString(tempDir.resolve("f3"), "changed content", UTF_8);
Files.writeString(tempDir.resolve("f4"), "new file content", UTF_8);

out = new ByteArrayOutputStream();
stream = new PrintStream(out, true, UTF_8);
Stats.stats(stream, new String[] { "--diff", tempDir.toString() });
assertThat(FileAttributesTest.forceSysFields(new String(out.toByteArray(), UTF_8)))
.isEqualTo("" +
"-del- f2|f|4|alban|alban|rw-r--r--|2020-09-02T15:43:48.680382Z|2aed8aa9f826c21ef07d5ee15b48eea06e9c8a62" + System.lineSeparator() +
"~mod~ f3| size 4 -> 15 | modifiedTime 2020-09-02T15:43:48.680382Z -> 2020-09-02T15:43:48.680382Z | sha1OrSymbolicLink cca5603cae64651971a35bc1488f0d23ddabdff9 -> 1fa817e97796161063e307eac706bb8b06cf956c |" + System.lineSeparator() +
"+new+ f4|f|16|alban|alban|rw-r--r--|2020-09-02T15:43:48.680382Z|17c494d126c27755e2134a4388178d808b139ce9" + System.lineSeparator() +
"~mod~ .| size 16 -> 39 | modifiedTime 2020-09-02T15:43:48.680382Z -> 2020-09-02T15:43:48.680382Z | sha1OrSymbolicLink f81b3e16656c1bd84d7522ed2f83fa996ffd8497 -> 2d8050016ac5619885aaac0402f8c5d88cceb077 |" + System.lineSeparator());
}

}

0 comments on commit 3ac8d7a

Please sign in to comment.