docs: def RepackTemplates(self,
                        repack_configs,
                        templates,
                        output_dir,
                        config=None,
                        sign=False,
                        signed_template=False):
      """Call repacker in a subprocess."""
      pool = multiprocessing.Pool(processes=10)
      results = []
      bulk_sign_installers = False
      for repack_config in repack_configs:
        for template in templates:
          repack_args = ["grr_client_build"]
          if config:
            repack_args.extend(["--config", config])
  
          repack_args.extend([
              "--secondary_configs", repack_config, "repack", "--template",
              template, "--output_dir",
              self.GetOutputDir(output_dir, repack_config)
          ])
  
          # We only sign exes and rpms at the moment. The others will raise if we
          # try to ask for signing.
          passwd = None
  
          if sign:
            if template.endswith(".exe.zip"):
              # This is for osslsigncode only.
              if platform.system() != "Windows":
                passwd = self.GetWindowsPassphrase()
                repack_args.append("--sign")
              else:
                bulk_sign_installers = True
              if signed_template:
                repack_args.append("--signed_template")
            elif template.endswith(".rpm.zip"):
              bulk_sign_installers = True
  
          print("Calling %s" % " ".join(repack_args))
          results.append(
              pool.apply_async(SpawnProcess, (repack_args,), dict(passwd=passwd)))
  
          # Also build debug if it's windows.
          if template.endswith(".exe.zip"):
            debug_args = []
            debug_args.extend(repack_args)
            debug_args.append("--debug_build")
            print("Calling %s" % " ".join(debug_args))
            results.append(
                pool.apply_async(SpawnProcess, (debug_args,),
                                 dict(passwd=passwd)))
  
      try:
        pool.close()
        # Workaround to handle keyboard kills
        # http://stackoverflow.com/questions/1408356/keyboard-interrupts-with-pythons-multiprocessing-pool
        # get will raise if the child raises.
        for result_obj in results:
          result_obj.get(9999)
        pool.join()
      except KeyboardInterrupt:
        print("parent received control-c")
        pool.terminate()
      except ErrorDuringRepacking:
        pool.terminate()
        raise
  
      if bulk_sign_installers:
        to_sign = {}
        for root, _, files in os.walk(output_dir):
          for f in files:
            if f.endswith(".exe"):
              to_sign.setdefault("windows", []).append(os.path.join(root, f))
            elif f.endswith(".rpm"):
              to_sign.setdefault("rpm", []).append(os.path.join(root, f))
        if to_sign.get("windows"):
          signer = repacking.TemplateRepacker().GetSigner([
              "ClientBuilder Context",
              "Platform:%s" % platform.system(), "Target:Windows"
          ])
          signer.SignFiles(to_sign.get("windows"))
        if to_sign.get("rpm"):
          signer = repacking.TemplateRepacker().GetSigner([
              "ClientBuilder Context",
              "Platform:%s" % platform.system(), "Target:Linux", "Target:LinuxRpm"
          ])
          signer.AddSignatureToRPMs(to_sign.get("rpm"))