def _GCProjects()

in subcmds/sync.py [0:0]


  def _GCProjects(self, projects, opt, err_event):
    pm = Progress('Garbage collecting', len(projects), delay=False, quiet=opt.quiet)
    pm.update(inc=0, msg='prescan')

    tidy_dirs = {}
    for project in projects:
      # Make sure pruning never kicks in with shared projects.
      if (not project.use_git_worktrees and
              len(project.manifest.GetProjectsWithName(project.name)) > 1):
        if not opt.quiet:
          print('\r%s: Shared project %s found, disabling pruning.' %
                (project.relpath, project.name))
        if git_require((2, 7, 0)):
          project.EnableRepositoryExtension('preciousObjects')
        else:
          # This isn't perfect, but it's the best we can do with old git.
          print('\r%s: WARNING: shared projects are unreliable when using old '
                'versions of git; please upgrade to git-2.7.0+.'
                % (project.relpath,),
                file=sys.stderr)
          project.config.SetString('gc.pruneExpire', 'never')
      project.config.SetString('gc.autoDetach', 'false')
      # Only call git gc once per objdir, but call pack-refs for the remainder.
      if project.objdir not in tidy_dirs:
        tidy_dirs[project.objdir] = (
            True,  # Run a full gc.
            project.bare_git,
        )
      elif project.gitdir not in tidy_dirs:
        tidy_dirs[project.gitdir] = (
            False,  # Do not run a full gc; just run pack-refs.
            project.bare_git,
        )

    cpu_count = os.cpu_count()
    jobs = min(self.jobs, cpu_count)

    if jobs < 2:
      for (run_gc, bare_git) in tidy_dirs.values():
        pm.update(msg=bare_git._project.name)
        if run_gc:
          bare_git.gc('--auto')
        else:
          bare_git.pack_refs()
      pm.end()
      return

    config = {'pack.threads': cpu_count // jobs if cpu_count > jobs else 1}

    threads = set()
    sem = _threading.Semaphore(jobs)

    def tidy_up(run_gc, bare_git):
      pm.start(bare_git._project.name)
      try:
        try:
          if run_gc:
            bare_git.gc('--auto', config=config)
          else:
            bare_git.pack_refs(config=config)
        except GitError:
          err_event.set()
        except Exception:
          err_event.set()
          raise
      finally:
        pm.finish(bare_git._project.name)
        sem.release()

    for (run_gc, bare_git) in tidy_dirs.values():
      if err_event.is_set() and opt.fail_fast:
        break
      sem.acquire()
      t = _threading.Thread(target=tidy_up, args=(run_gc, bare_git,))
      t.daemon = True
      threads.add(t)
      t.start()

    for t in threads:
      t.join()
    pm.end()