Abstract from DownloadProgressEvent to generic FetchProgress 

In this way, we can easily add other fetch-like events to be reported
in a similar way as plain downloads.

--
Change-Id: I518df5ba27b6593eca98d30407b582f509a52aeb
Reviewed-on: https://cr.bazel.build/9313
PiperOrigin-RevId: 149655918
MOS_MIGRATED_REVID=149655918
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadProgressEvent.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadProgressEvent.java
index a8f0f15..86d2ef6 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadProgressEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadProgressEvent.java
@@ -21,7 +21,7 @@
  * Postable event reporting on progress made downloading an URL. It can be used to report the URL
  * being downloaded and the number of bytes read so far.
  */
-public class DownloadProgressEvent implements ExtendedEventHandler.ProgressLike {
+public class DownloadProgressEvent implements ExtendedEventHandler.FetchProgress {
   private final URL originalUrl;
   private final URL actualUrl;
   private final long bytesRead;
@@ -50,10 +50,16 @@
     return originalUrl;
   }
 
+  @Override
+  public String getResourceIdentifier() {
+    return originalUrl.toString();
+  }
+
   public URL getActualUrl() {
     return actualUrl;
   }
 
+  @Override
   public boolean isFinished() {
     return downloadFinished;
   }
@@ -61,4 +67,9 @@
   public long getBytesRead() {
     return bytesRead;
   }
+
+  @Override
+  public String getProgress() {
+    return bytesRead > 0 ? "" + bytesRead + "b" : "";
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/events/ExtendedEventHandler.java b/src/main/java/com/google/devtools/build/lib/events/ExtendedEventHandler.java
index e03eb23..a05b5f5 100644
--- a/src/main/java/com/google/devtools/build/lib/events/ExtendedEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/events/ExtendedEventHandler.java
@@ -31,4 +31,21 @@
    * failure) and hence should not be stored and replayed.
    */
   public interface ProgressLike extends Postable {}
+
+  /** Interface for progress events that report about fetching from a remote site */
+  public interface FetchProgress extends ProgressLike {
+
+    /**
+     * The resource that was originally requested and uniquely determines the fetch source. The
+     * actual fetching may use mirrors, proxies, or similar. The resource need not be an URL, but it
+     * has to uniquely identify the particular fetch among all fetch events.
+     */
+    String getResourceIdentifier();
+
+    /** Human readable description of the progress */
+    String getProgress();
+
+    /** Wether the fetch progress reported about is finished already */
+    boolean isFinished();
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
index 5cb71b8..2755c06 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
@@ -22,7 +22,6 @@
 import com.google.devtools.build.lib.actions.ActionStatusMessage;
 import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
 import com.google.devtools.build.lib.analysis.NoBuildEvent;
-import com.google.devtools.build.lib.bazel.repository.downloader.DownloadProgressEvent;
 import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
 import com.google.devtools.build.lib.buildtool.buildevent.BuildStartingEvent;
 import com.google.devtools.build.lib.buildtool.buildevent.ExecutionProgressReceiverAvailableEvent;
@@ -30,6 +29,7 @@
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.EventKind;
+import com.google.devtools.build.lib.events.ExtendedEventHandler.FetchProgress;
 import com.google.devtools.build.lib.pkgcache.LoadingPhaseCompleteEvent;
 import com.google.devtools.build.lib.skyframe.LoadingPhaseStartedEvent;
 import com.google.devtools.build.lib.util.Clock;
@@ -346,7 +346,7 @@
   }
 
   @Subscribe
-  public void downloadProgress(DownloadProgressEvent event) {
+  public void downloadProgress(FetchProgress event) {
     stateTracker.downloadProgress(event);
     refresh();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
index c6efa08..353dcd4 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
@@ -19,13 +19,13 @@
 import com.google.devtools.build.lib.actions.ActionStatusMessage;
 import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
-import com.google.devtools.build.lib.bazel.repository.downloader.DownloadProgressEvent;
 import com.google.devtools.build.lib.buildtool.ExecutionProgressReceiver;
 import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
 import com.google.devtools.build.lib.buildtool.buildevent.BuildStartingEvent;
 import com.google.devtools.build.lib.buildtool.buildevent.ExecutionProgressReceiverAvailableEvent;
 import com.google.devtools.build.lib.buildtool.buildevent.TestFilteringCompleteEvent;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.events.ExtendedEventHandler.FetchProgress;
 import com.google.devtools.build.lib.pkgcache.LoadingPhaseCompleteEvent;
 import com.google.devtools.build.lib.skyframe.LoadingPhaseStartedEvent;
 import com.google.devtools.build.lib.skyframe.PackageProgressReceiver;
@@ -79,7 +79,7 @@
   // access.
   private final Deque<String> runningDownloads;
   private final Map<String, Long> downloadNanoStartTimes;
-  private final Map<String, DownloadProgressEvent> downloads;
+  private final Map<String, FetchProgress> downloads;
 
   // For each test, the list of actions (again identified by the path of the
   // primary output) currently running for that test (identified by its label),
@@ -190,8 +190,8 @@
     buildComplete(event, "");
   }
 
-  synchronized void downloadProgress(DownloadProgressEvent event) {
-    String url = event.getOriginalUrl().toString();
+  synchronized void downloadProgress(FetchProgress event) {
+    String url = event.getResourceIdentifier();
     if (event.isFinished()) {
       // a download is finished, clean it up
       runningDownloads.remove(url);
@@ -565,12 +565,13 @@
 
     String postfix = "";
 
-    DownloadProgressEvent download = downloads.get(url);
+    FetchProgress download = downloads.get(url);
     long nanoDownloadTime = nanoTime - downloadNanoStartTimes.get(url);
     long downloadSeconds = nanoDownloadTime / NANOS_PER_SECOND;
 
-    if (download.getBytesRead() > 0) {
-      postfix = postfix + " " + download.getBytesRead() + "b";
+    String progress = download.getProgress();
+    if (progress.length() > 0) {
+      postfix = postfix + " " + progress;
     }
     if (downloadSeconds > SHOW_TIME_THRESHOLD_SECONDS) {
       postfix = postfix + " " + downloadSeconds + "s";