chiark / gitweb /
keys.scala, etc.: Make merging public keys have a progress bar.
[tripe-android] / keys.scala
index 9108b38aca701f2bb28ecb356f2b07e494f3d616..544462e05244dce67b92ad82984f429ad4ae05d8 100644 (file)
@@ -27,7 +27,7 @@ package uk.org.distorted.tripe; package object keys {
 
 /*----- Imports -----------------------------------------------------------*/
 
-import scala.collection.mutable.HashMap;
+import scala.collection.mutable.{ArrayBuffer, HashMap};
 
 import java.io.{Closeable, File, IOException};
 import java.lang.{Long => JLong};
@@ -41,7 +41,8 @@ import sys.Errno.EEXIST;
 import sys.FileImplicits._;
 import sys.FileInfo.{DIR, REG};
 
-import progress.{Eyecandy, SimpleModel, DataModel};
+import progress.{Eyecandy, SimpleModel, DataModel, DetailedModel};
+import Implicits.truish;
 
 /*----- Useful regular expressions ----------------------------------------*/
 
@@ -275,6 +276,7 @@ def checkConfigSanity(file: File, ic: Eyecandy) {
 }
 
 private val keydatefmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+
 class PrivateKey private[keys](repo: Repository, dir: File) {
   private[this] lazy val keyring = dir/"keyring";
   private[this] lazy val meta = parseConfig(dir/"meta");
@@ -318,7 +320,7 @@ class PrivateKey private[keys](repo: Repository, dir: File) {
      * because Java doesn't have proper unsigned integers.  There's
      * `parseUnsignedInt' in Java 1.8, but that limits our Android targets.
      * And Scala has put its own `Long' object in the way of Java's so we
-     * need this circumolution.
+     * need this circumlocution.
      */
     (JLong.parseLong(info("keyid"), 16)&0xffffffff).toInt;
   }
@@ -595,16 +597,33 @@ class Repository(val root: File) extends Closeable {
     /* Confirm that the configuration in the new archive is sane. */
     checkConfigSanity(unpkdir/"tripe-keys.conf", ic);
 
-    /* Build the public keyring.  (Observe the quadratic performance.) */
-    ic.operation("collecting public keys") { or =>
+    /* Build the public keyring. */
+    ic.job(new SimpleModel("counting public keys", -1)) { jr =>
+
+      /* Delete the accumulated keyring. */
       val pubkeys = unpkdir/"keyring.pub";
       pubkeys.remove_!();
-      reposdir foreachFile { file => file.getName match {
-       case RX_PUBKEY(peer) if file.isreg_! =>
-         or.step(peer);
-         runCommand("key", "-k", pubkeys.getPath, "merge", file.getPath);
+
+      /* Figure out which files we need to hack. */
+      var kv = ArrayBuffer[File]();
+      reposdir.foreachFile { file => file.getName match {
+       case RX_PUBKEY(peer) if file.isreg_! => kv += file;
        case _ => ok;
       } }
+      kv = kv.sorted;
+      val m = new DetailedModel("collecting public keys", kv.length);
+      var i: Long = 0;
+
+      /* Work through the key files. */
+      for (k <- kv) {
+       m.detail = k.getName;
+       if (!i) jr.change(m, i);
+       else jr.step(i);
+       runCommand("key", "-k", pubkeys.getPath, "merge", k.getPath);
+       i += 1;
+      }
+
+      /* Clean up finally. */
       (unpkdir/"keyring.pub.old").remove_!();
     }