update recipe_modules/zip/resources/zip.py to include hashing

Part of the work towards:
https://github.com/flutter/flutter/issues/38980

Right now this only adds the sha256 checksums to the stdout, for
example: https://logs.chromium.org/logs/flutter/led/fujino_google.com/0ddad41c189ba1e3a7ac1da6ab5a70548e075bbd18a5999fc58002b853898fd4/+/u/Zip_flutter_linux__3_/stdout

Change-Id: I2927a2eca509a2c25d06ad56d3bc42df1845bd53
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/15441
Commit-Queue: Christopher Fujino <fujino@google.com>
Reviewed-by: Casey Hillers <chillers@google.com>
diff --git a/recipe_modules/zip/resources/zip.py b/recipe_modules/zip/resources/zip.py
index d7e2d8a..5e7cc36 100644
--- a/recipe_modules/zip/resources/zip.py
+++ b/recipe_modules/zip/resources/zip.py
@@ -7,6 +7,7 @@
 """
 
 import json
+import hashlib
 import os
 import subprocess
 import sys
@@ -35,14 +36,18 @@
       # File must exist and be inside |root|.
       assert os.path.isfile(path), path
       assert path.startswith(root), path
-      items_to_zip.append(path[len(root):])
+      file_path = path[len(root):]
+      hash_file(file_path)
+      items_to_zip.append(file_path)
     elif entry['type'] == 'dir':
       # Append trailing '/'.
       path = path.rstrip(os.path.sep) + os.path.sep
       # Directory must exist and be inside |root| or be |root| itself.
       assert os.path.isdir(path), path
       assert path.startswith(root), path
-      items_to_zip.append(path[len(root):] or '.')
+      dir_path = path[len(root):] or '.'
+      walk_dir_and_do(path, lambda p: hash_file(p))
+      items_to_zip.append(dir_path)
     else:
       raise AssertionError('Invalid entry type: %s' % (tp,))
 
@@ -55,6 +60,24 @@
   return proc.returncode
 
 
+def walk_dir_and_do(directory_path, callback):
+    for cur, _, files in os.walk(directory_path):
+      for name in files:
+        callback(os.path.join(cur, name))
+
+
+def hash_file(file_path):
+    BUFFER_SIZE = 1 << 16 # 64kb
+    sha = hashlib.sha256()
+    with open(file_path, 'rb') as f:
+        data = f.read(BUFFER_SIZE)
+        while data:
+            sha.update(data)
+            data = f.read(BUFFER_SIZE)
+    digest = sha.hexdigest()
+    print('sha256 digest for %s is:\n%s\n' % (file_path, digest))
+
+
 def zip_with_python(root, output, entries):
   """Zips set of files and directories using 'zipfile' python module.
 
@@ -77,7 +100,8 @@
         return
       if archive_name is None:
         archive_name = path[len(root):]
-      print 'Adding %s' % archive_name
+      print('Adding %s' % archive_name)
+      hash_file(path)
       zip_file.write(path, archive_name)
 
     for entry in entries:
@@ -86,9 +110,7 @@
       if tp == 'file':
         add(path, entry.get('archive_name'))
       elif tp == 'dir':
-        for cur, _, files in os.walk(path):
-          for name in files:
-            add(os.path.join(cur, name), None)
+        walk_dir_and_do(path, lambda p: add(p, None))
       else:
         raise AssertionError('Invalid entry type: %s' % (tp,))
   return 0
@@ -117,7 +139,7 @@
   # Output zip path should be an absolute path.
   assert os.path.isabs(output), output
 
-  print 'Zipping %s...' % output
+  print('Zipping %s...' % output)
   exit_code = -1
   try:
     if use_python_zip(entries):
@@ -136,7 +158,7 @@
       except:  # pylint: disable=bare-except
         pass
   if not exit_code:
-    print 'Archive size: %.1f KB' % (os.stat(output).st_size / 1024.0,)
+    print('Archive size: %.1f KB' % (os.stat(output).st_size / 1024.0,))
   return exit_code