Changes OutputFileSet to overwrite on equal timestamps.

Previously OutputFileSetOnDirectory took special care to not overwrite 
a file in the output directory if it had the same timestamp as the 
current artifact being written. For a long time this had no effect
since Link.java deleted al output directory contents anyway and DevMode
was  not using OutputFileSets to perform it's writes.

But somewhat recently DevMode was changed to use 
OutputFileSetOnDirectory and it resulted in a subtle change in behavior
where generated files from 1 compile would not be overwritten by the 
samely named (but differently contented) generated file on a subsequent
compile.

As a result running a prod mode test followed by a dev mode test would 
fail as the dev mode test tried to reuse the incompatible prod mode
test Foo.nocache.js file.

Change-Id: I0916ab7933f9dfcb36b361f2e21657fac8174d67
Review-Link: https://gwt-review.googlesource.com/#/c/10311/
(cherry picked from commit c123d4887524191e960dec037641935ebff57d15)
diff --git a/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java b/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java
index 2a0d780..4f95198 100644
--- a/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java
+++ b/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java
@@ -68,14 +68,15 @@
   }
 
   /**
-   * Opens a file for write. If writing to a zip file and the file already
-   * exists, there will be no effect. If writing to a directory, the file
-   * exists, and the given timestamp is older or equal to the file's
-   * current timestamp, there will be no effect.
+   * Opens a file for write. If writing to a zip file and the file already exists,
+   * there will be no effect. If writing to a directory, the file exists, and the
+   * given timestamp is older than the current timestamp, there will be no effect.
+   *
    * @param timeStampMillis last modified time in milliseconds, or
-   * TIMESTAMP_UNAVAILABLE to force an overwrite.
+   *          TIMESTAMP_UNAVAILABLE to force an overwrite.
    * @return the output stream to write to, possibly a NullOutputStream
    */
+  // TODO: revalidate whether any timestamp based overwrite prevention is needed.
   public OutputStream openForWrite(String path, long timeStampMillis)
       throws IOException {
     pathsSeen.add(path);
diff --git a/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java b/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java
index fc9b195..d772a9a 100644
--- a/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java
+++ b/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java
@@ -47,7 +47,7 @@
       final long timeStampMillis) throws IOException {
     final File file = pathToFile(path);
     if (file.exists() && timeStampMillis != TIMESTAMP_UNAVAILABLE &&
-        file.lastModified() >= timeStampMillis) {
+        file.lastModified() > timeStampMillis) {
       return new NullOutputStream();
     }
 
diff --git a/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java b/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java
index 9aa7fbd..0c2283e 100644
--- a/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java
+++ b/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java
@@ -18,10 +18,12 @@
 import junit.framework.TestCase;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 
 /**
- * Tests for {@link OutputFileSetOnDirectory}
+ * Tests for {@link OutputFileSetOnDirectory}.
  */
 public class OutputFileSetOnDirectoryTest extends TestCase {
 
@@ -46,4 +48,37 @@
     }
   }
 
+  public void testNewFileEqualTimestampOverwrites() throws IOException {
+    File work = Utility.makeTemporaryDirectory(null, "outputfileset");
+    try {
+      OutputFileSetOnDirectory output = new OutputFileSetOnDirectory(work, "test/");
+
+      OutputStream firstStream = output.createNewOutputStream("path/to/file", 1000);
+      assertTrue(firstStream instanceof FileOutputStream);
+      firstStream.close();
+
+      OutputStream secondStream = output.createNewOutputStream("path/to/file", 1000);
+      assertTrue(secondStream instanceof FileOutputStream);
+      secondStream.close();
+    } finally {
+      Util.recursiveDelete(work, false);
+    }
+  }
+
+  public void testNewFileOlderTimestampDies() throws IOException {
+    File work = Utility.makeTemporaryDirectory(null, "outputfileset");
+    try {
+      OutputFileSetOnDirectory output = new OutputFileSetOnDirectory(work, "test/");
+
+      OutputStream firstStream = output.createNewOutputStream("path/to/file", 2000);
+      assertTrue(firstStream instanceof FileOutputStream);
+      firstStream.close();
+
+      OutputStream secondStream = output.createNewOutputStream("path/to/file", 1000);
+      assertFalse(secondStream instanceof FileOutputStream);
+      secondStream.close();
+    } finally {
+      Util.recursiveDelete(work, false);
+    }
+  }
 }