FileSnapshot#equals: consider UNKNOWN_SIZE

Add a unittest.

In commit I5485db55 ("Fix FileSnapshot's consideration of file size"),
the special casing of UNKNOWN_SIZE was forgotten.

This change, together with I493f3b57b ("Measure file timestamp
resolution used in FileSnapshot") introduced a regression that would
occasionally surface in Gerrit integration tests marked UseLocalDisk,
with the symptom that creating the Admin user in NoteDb failed with a
LOCK_FAILURE.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Change-Id: I7ffd972581f815c144f810481103c7985af5feb0
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
index 5ebdeb6..6e458fb 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
@@ -180,6 +180,17 @@ public void testFileSizeChanged() throws Exception {
 		assertTrue(save.wasSizeChanged());
 	}
 
+	@Test
+	public void fileSnapshotEquals() throws Exception {
+		// 0 sized FileSnapshot.
+		FileSnapshot fs1 = FileSnapshot.MISSING_FILE;
+		// UNKNOWN_SIZE FileSnapshot.
+		FileSnapshot fs2 = FileSnapshot.save(fs1.lastModified());
+
+		assertTrue(fs1.equals(fs2));
+		assertTrue(fs2.equals(fs1));
+	}
+
 	private File createFile(String string) throws IOException {
 		trash.mkdirs();
 		File f = File.createTempFile(string, "tdat", trash);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
index 1de3135..0019c5f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
@@ -144,7 +144,7 @@ private static Object getFileKey(BasicFileAttributes fileAttributes) {
 	 */
 	public static FileSnapshot save(long modified) {
 		final long read = System.currentTimeMillis();
-		return new FileSnapshot(read, modified, -1, Duration.ZERO,
+		return new FileSnapshot(read, modified, UNKNOWN_SIZE, Duration.ZERO,
 				MISSING_FILEKEY);
 	}
 
@@ -318,7 +318,8 @@ public void waitUntilNotRacy() throws InterruptedException {
 	 * @return true if the two snapshots share the same information.
 	 */
 	public boolean equals(FileSnapshot other) {
-		return lastModified == other.lastModified && size == other.size
+		boolean sizeEq = size == UNKNOWN_SIZE || other.size == UNKNOWN_SIZE || size == other.size;
+		return lastModified == other.lastModified && sizeEq
 				&& Objects.equals(fileKey, other.fileKey);
 	}