Add an internal flag for output overwriting

This changes the default behavior about dex files to allow overwriting.

Change-Id: Ibb6e1170ccaf71dc0ac098dee5858f59991fd79b
diff --git a/src/main/java/com/android/tools/r8/BaseOutput.java b/src/main/java/com/android/tools/r8/BaseOutput.java
index cb4d473..a1fbb8e 100644
--- a/src/main/java/com/android/tools/r8/BaseOutput.java
+++ b/src/main/java/com/android/tools/r8/BaseOutput.java
@@ -49,6 +49,7 @@
    * Write the output resources to a zip-archive or directory.
    *
    * @param output Path to existing directory or non-existing zip-archive.
+   * @param overwrite true to allow overwriting existing files with outputs.
    */
-  abstract public void write(Path output) throws IOException;
+  abstract public void write(Path output, boolean overwrite) throws IOException;
 }
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 5a8ff11..522f6f0 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -60,11 +60,12 @@
    * @return the compilation result.
    */
   public static D8Output run(D8Command command) throws IOException {
-    CompilationResult result = runForTesting(command.getInputApp(), command.getInternalOptions());
+    InternalOptions options = command.getInternalOptions();
+    CompilationResult result = runForTesting(command.getInputApp(), options);
     assert result != null;
     D8Output output = new D8Output(result.androidApp, command.getOutputMode());
     if (command.getOutputPath() != null) {
-      output.write(command.getOutputPath());
+      output.write(command.getOutputPath(), options.overwriteOutputs);
     }
     return output;
   }
@@ -80,12 +81,13 @@
    * @return the compilation result.
    */
   public static D8Output run(D8Command command, ExecutorService executor) throws IOException {
+    InternalOptions options = command.getInternalOptions();
     CompilationResult result = runForTesting(
-        command.getInputApp(), command.getInternalOptions(), executor);
+        command.getInputApp(), options, executor);
     assert result != null;
     D8Output output = new D8Output(result.androidApp, command.getOutputMode());
     if (command.getOutputPath() != null) {
-      output.write(command.getOutputPath());
+      output.write(command.getOutputPath(), options.overwriteOutputs);
     }
     return output;
   }
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 848713a..62cb5a5 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -194,6 +194,7 @@
     assert !internal.debug;
     internal.debug = getMode() == CompilationMode.DEBUG;
     internal.minApiLevel = getMinApiLevel();
+    internal.overwriteOutputs = true;
     // Assert and fixup defaults.
     assert !internal.skipMinification;
     internal.skipMinification = true;
diff --git a/src/main/java/com/android/tools/r8/D8Output.java b/src/main/java/com/android/tools/r8/D8Output.java
index 1910e9b..4ba7067 100644
--- a/src/main/java/com/android/tools/r8/D8Output.java
+++ b/src/main/java/com/android/tools/r8/D8Output.java
@@ -16,7 +16,7 @@
   }
 
   @Override
-  public void write(Path output) throws IOException {
-    getAndroidApp().write(output, getOutputMode());
+  public void write(Path output, boolean overwrite) throws IOException {
+    getAndroidApp().write(output, getOutputMode(), overwrite);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 7dd2d33..fbcd34c 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -385,14 +385,17 @@
   static void writeOutputs(R8Command command, InternalOptions options, AndroidApp outputApp)
       throws IOException {
     if (command.getOutputPath() != null) {
-      outputApp.write(command.getOutputPath(), options.outputMode);
+      outputApp.write(command.getOutputPath(), options.outputMode, options.overwriteOutputs);
     }
 
     if (options.printMapping && !options.skipMinification) {
       assert outputApp.hasProguardMap();
       try (Closer closer = Closer.create()) {
-        OutputStream mapOut =
-            openPathWithDefault(closer, options.printMappingFile, true, System.out);
+        OutputStream mapOut = openPathWithDefault(
+            closer,
+            options.printMappingFile,
+            options.overwriteOutputs,
+            System.out);
         outputApp.writeProguardMap(closer, mapOut);
       }
     }
@@ -400,7 +403,7 @@
       assert outputApp.hasProguardSeeds();
       try (Closer closer = Closer.create()) {
         OutputStream seedsOut =
-            openPathWithDefault(closer, options.seedsFile, true, System.out);
+            openPathWithDefault(closer, options.seedsFile, options.overwriteOutputs, System.out);
         outputApp.writeProguardSeeds(closer, seedsOut);
       }
     }
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 9b44546..34834f2 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -346,6 +346,7 @@
     internal.useTreeShaking = useTreeShaking();
     assert !internal.ignoreMissingClasses;
     internal.ignoreMissingClasses = ignoreMissingClasses;
+    internal.overwriteOutputs = true;
 
     // TODO(zerny): Consider which other proguard options should be given flags.
     assert internal.packagePrefix.length() == 0;
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
index c174a31..4a499ec 100644
--- a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
@@ -484,7 +484,7 @@
       }
       writeZipWithClasses(inputs, result, output);
     } else {
-      result.write(output);
+      result.write(output, true);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index d999f37..9d2379a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -91,6 +91,8 @@
 
   public String warningInvalidParameterAnnotations = null;
 
+  public boolean overwriteOutputs; // default value is set in D/R8Command
+
   public boolean printWarnings() {
     boolean printed = false;
     if (warningInvalidParameterAnnotations != null) {
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 66844af..13a4c24 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -989,7 +989,7 @@
             builder.setMinApiLevel(minSdkVersion);
           }
           D8Output output = D8.run(builder.build());
-          output.write(Paths.get(resultPath));
+          output.write(Paths.get(resultPath), true);
           break;
         }
       case R8:
diff --git a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
index 0d72a52..2cdb4d7 100644
--- a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
+++ b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
@@ -38,17 +38,17 @@
     D8Command.Builder arithmeticBuilder = D8Command.builder().addProgramFiles(ARITHMETIC_JAR);
     D8Command.Builder arrayAccessBuilder = D8Command.builder().addProgramFiles(ARRAYACCESS_JAR);
     D8Output output = D8.run(arrayAccessBuilder.build());
-    output.write(defaultApiFolder1.getRoot().toPath());
+    output.write(defaultApiFolder1.getRoot().toPath(), true);
     output = D8.run(arrayAccessBuilder.setMinApiLevel(Constants.ANDROID_O_API).build());
-    output.write(androidOApiFolder1.getRoot().toPath());
+    output.write(androidOApiFolder1.getRoot().toPath(), true);
     output = D8.run(arrayAccessBuilder.setMinApiLevel(Constants.ANDROID_N_API).build());
-    output.write(androidNApiFolder1.getRoot().toPath());
+    output.write(androidNApiFolder1.getRoot().toPath(), true);
     output = D8.run(arithmeticBuilder.build());
-    output.write(defaultApiFolder2.getRoot().toPath());
+    output.write(defaultApiFolder2.getRoot().toPath(), true);
     output = D8.run(arithmeticBuilder.setMinApiLevel(Constants.ANDROID_O_API).build());
-    output.write(androidOApiFolder2.getRoot().toPath());
+    output.write(androidOApiFolder2.getRoot().toPath(), true);
     output = D8.run(arithmeticBuilder.setMinApiLevel(Constants.ANDROID_N_API).build());
-    output.write(androidNApiFolder2.getRoot().toPath());
+    output.write(androidNApiFolder2.getRoot().toPath(), true);
   }
 
   private Path default1() {