Don't extract archives if unchanged.

This should shave 20% (40 seconds) off our Windows cycle times, going by
the graphs. It's 15% off our Linux ones, but that 15% is only 11
seconds.

Change-Id: I077c3924c722d597f66fc6dec72932ed0c81660a
Reviewed-on: https://boringssl-review.googlesource.com/12562
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/util/bot/extract.py b/util/bot/extract.py
index 77603c0..e36ce99 100644
--- a/util/bot/extract.py
+++ b/util/bot/extract.py
@@ -15,6 +15,7 @@
 """Extracts archives."""
 
 
+import hashlib
 import optparse
 import os
 import os.path
@@ -78,6 +79,22 @@
     # Skip archives that weren't downloaded.
     return 0
 
+  with open(archive) as f:
+    sha256 = hashlib.sha256()
+    while True:
+      chunk = f.read(1024 * 1024)
+      if not chunk:
+        break
+      sha256.update(chunk)
+    digest = sha256.hexdigest()
+
+  stamp_path = os.path.join(output, ".boringssl_archive_digest")
+  if os.path.exists(stamp_path):
+    with open(stamp_path) as f:
+      if f.read().strip() == digest:
+        print "Already up-to-date."
+        return 0
+
   if archive.endswith('.zip'):
     entries = IterateZip(archive)
   elif archive.endswith('.tar.gz'):
@@ -129,9 +146,10 @@
   finally:
     entries.close()
 
-  if num_extracted % 100 == 0:
-    print "Done. Extracted %d files." % (num_extracted,)
+  with open(stamp_path, 'w') as f:
+    f.write(digest)
 
+  print "Done. Extracted %d files." % (num_extracted,)
   return 0