Generate SSD staged ZIP install loop from typed Jerboa

ober

8378859f1cfb7dbb01e9824833f0e7e8bc89bd61

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 6974b8d..d79ab7b 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -2063,7 +2063,8 @@
                 shouldReplaceLocalByTimes
                 truthStoreMakePinnedTrustManager
                 zipEntryPresent
-                zipEntryIsDirectory zipEntryIsFile zipEntryDeclaresExcessiveSize)
+                zipEntryIsDirectory zipEntryIsFile zipEntryDeclaresExcessiveSize
+                countInstalledStagedZipEntries)
         (type File)
         (type Path)
         (type CertificateException)
@@ -2443,7 +2444,15 @@
                                             (entryLimit : Int)
                                             (compressedLimit : Int)) : Bool
           (or (> (zipEntrySize entry) entryLimit)
-              (> (zipEntryCompressedSize entry) compressedLimit)))))
+              (> (zipEntryCompressedSize entry) compressedLimit)))
+        (def (countInstalledStagedZipEntries
+               (entries : (List StagedZipEntry))
+               (install : (-> StagedZipEntry Bool))) : Int32
+          (for/fold ((count (int32 0)))
+                    ((i (in-range (int32 0) (list-size entries))))
+            (if (invoke install (list-ref entries i))
+                (+ count (int32 1))
+                count)))))
 
     (typed-kotlin-file "com/sfb/ssdreview/JsonGeometry.kt"
       (kotlin-imports (org json JSONArray))
@@ -11855,7 +11864,7 @@
        "            }"
        "            val current = storageStats()"
        "            require(storageCapacityWithinQuota(current.files + staged.size, current.bytes + budget.expandedBytes, MAX_STORAGE_FILES, MAX_STORAGE_BYTES)) { \"Storage quota exceeded\" }"
-       "            staged.forEach { if (installStagedZipEntry(it)) count += 1 }"
+       "            count += countInstalledStagedZipEntries(staged) { installStagedZipEntry(it) }"
        "            if (positiveCount(count)) invalidateTruthIndex()"
        "        } finally {"
        "            stage.deleteRecursively()"