docs: def export_repos(self, envs=[]):
          """Dump JuicerRepo() objects for all repos in all environments.
  
          Note that this has undefined results should a repo exist with
          different configurations in different environments.
          """
          all_envs = envs
          juicer.utils.Log.log_notice("Only exporting repos in environment(s): %s", ", ".join(all_envs))
          all_pulp_repo_names = self.list_repos(envs=all_envs)
          all_pulp_repo_names_uniqued = set()
          num_repos = 0
  
          # Track name of all processed repos. Update when we've found
          # all environments a PulpRepo lives in.
          repos_processed = []
  
          for env, repos in all_pulp_repo_names.iteritems():
              juicer.utils.Log.log_debug("Uniqued environment: %s with %s repos", env, int(len(repos)))
              all_pulp_repo_names_uniqued.update(set(repos))
  
          num_repos += len(all_pulp_repo_names_uniqued)
  
          widgets = [
              "Exporting: ",
              progressbar.Percentage(),
              " ",
              "(",
              progressbar.SimpleProgress(),
              ") ",
              progressbar.ETA()
          ]
          progress_bar = JuiceBar(num_repos, widgets)
  
          # Hacky way to get around not easily being able to pass
          # multiple arguments to a function in a multiprocessing pool
          lookup_objects = []
  
          for repo in all_pulp_repo_names_uniqued:
              lookup_args = juicer.admin.ThreaddedQuery.LookupObject()
              setattr(lookup_args, 'progress_bar', progress_bar)
              setattr(lookup_args, 'all_pulp_repo_names', all_pulp_repo_names)
              setattr(lookup_args, 'all_envs', all_envs)
              setattr(lookup_args, 'ja', self)
              setattr(lookup_args, 'pulp_repo', repo)
              setattr(lookup_args, 'repos_processed', repos_processed)
              lookup_objects.append(lookup_args)
  
          # TODO: Add the serial/concurrent logic here
  
          try:
              # Make our thread pool
              p = ThreadPool()
              # Get an AsyncResult object
              r = p.map_async(juicer.admin.ThreaddedQuery.concurrent_pulp_lookup, lookup_objects)
              # TODO: We should probably use p.apply_async here to avoid the crappy lookup_objects hack
  
              while not r.ready():
                  r.wait(1)
          except KeyboardInterrupt:
              juicer.utils.Log.log_error("User pressed ^C during repo export")
              juicer.utils.Log.log_error("Terminating %s worker threads and then exiting", len(p._pool))
              # Prevents any more tasks from being submitted to the
              # pool. Once all the tasks have been completed the worker
              # threads will exit.
              #p.close()
              p.terminate()
              p.join()
  
          # XXX: End serial/concurrent logic
  
          progress_bar.finish()
          juicer_repos = [pr.to_juicer_repo() for pr in repos_processed]
          return sorted(juicer_repos, key=lambda d: d['name'].lower())