예제 #1
0
 def BatchListOwners(self, project, branch, paths):
     """Returns a dictionary {path: [owners]}."""
     with git_common.ScopedPool(kind='threads') as pool:
         return dict(
             pool.imap_unordered(
                 lambda p: (p, self.ListOwnersForFile(project, branch, p)),
                 paths))
  def BatchListOwners(self, paths):
    """List all owners for a group of files.

    Returns a dictionary {path: [owners]}.
    """
    with git_common.ScopedPool(kind='threads') as pool:
      return dict(pool.imap_unordered(
          lambda p: (p, self.ListOwners(p)), paths))
예제 #3
0
def load_generation_numbers(targets):
  """Populates the caches of get_num and get_number_tree so they contain
  the results for |targets|.

  Loads cached numbers from disk, and calculates missing numbers if one or
  more of |targets| is newer than the cached calculations.

  Args:
    targets - An iterable of binary-encoded full git commit hashes.
  """
  # In case they pass us a generator, listify targets.
  targets = list(targets)

  if all(get_num(t) is not None for t in targets):
    return

  if git.tree(REF) is None:
    empty = git.mktree({})
    commit_hash = git.run(
        # Git user.name and/or user.email may not be configured, so specifying
        # them explicitly. They are not used, but requried by Git.
        '-c', 'user.name=%s' % AUTHOR_NAME,
        '-c', 'user.email=%s' % AUTHOR_EMAIL,
        'commit-tree',
        '-m', 'Initial commit from git-number',
        empty)
    git.run('update-ref', REF, commit_hash)

  with git.ScopedPool(kind=POOL_KIND) as pool:
    preload_iter = pool.imap_unordered(preload_tree, all_prefixes())

    rev_list = []

    with git.ProgressPrinter('Loading commits: %(count)d') as inc:
      # Curiously, buffering the list into memory seems to be the fastest
      # approach in python (as opposed to iterating over the lines in the
      # stdout as they're produced). GIL strikes again :/
      cmd = [
        'rev-list', '--topo-order', '--parents', '--reverse', '^' + REF,
      ] + [binascii.hexlify(target).decode() for target in targets]
      for line in git.run(*cmd).splitlines():
        tokens = [binascii.unhexlify(token) for token in line.split()]
        rev_list.append((tokens[0], tokens[1:]))
        inc()

    get_number_tree.update(preload_iter)

  with git.ProgressPrinter('Counting: %%(count)d/%d' % len(rev_list)) as inc:
    for commit_hash, pars in rev_list:
      num = max(map(get_num, pars)) + 1 if pars else 0

      prefix = commit_hash[:PREFIX_LEN]
      get_number_tree(prefix)[commit_hash] = num
      DIRTY_TREES[prefix] += 1
      get_num.set(commit_hash, num)

      inc()
예제 #4
0
def finalize(targets):
    """Saves all cache data to the git repository.

  After calculating the generation number for |targets|, call finalize() to
  save all the work to the git repository.

  This in particular saves the trees referred to by DIRTY_TREES.
  """
    if not DIRTY_TREES:
        return

    msg = 'git-number Added %s numbers' % sum(DIRTY_TREES.itervalues())

    idx = os.path.join(git.run('rev-parse', '--git-dir'), 'number.idx')
    env = os.environ.copy()
    env['GIT_INDEX_FILE'] = idx

    progress_message = 'Finalizing: (%%(count)d/%d)' % len(DIRTY_TREES)
    with git.ProgressPrinter(progress_message) as inc:
        git.run('read-tree', REF, env=env)

        prefixes_trees = ((p, get_number_tree(p)) for p in sorted(DIRTY_TREES))
        updater = subprocess2.Popen(
            ['git', 'update-index', '-z', '--index-info'],
            stdin=subprocess2.PIPE,
            env=env)

        with git.ScopedPool(kind=POOL_KIND) as leaf_pool:
            for item in leaf_pool.imap(leaf_map_fn, prefixes_trees):
                updater.stdin.write(item)
                inc()

        updater.stdin.close()
        updater.wait()
        assert updater.returncode == 0

        tree_id = git.run('write-tree', env=env)
        commit_cmd = [
            # Git user.name and/or user.email may not be configured, so specifying
            # them explicitly. They are not used, but requried by Git.
            '-c',
            'user.name=%s' % AUTHOR_NAME,
            '-c',
            'user.email=%s' % AUTHOR_EMAIL,
            'commit-tree',
            '-m',
            msg,
            '-p'
        ] + git.hash_multi(REF)
        for t in targets:
            commit_cmd.extend(['-p', binascii.hexlify(t)])
        commit_cmd.append(tree_id)
        commit_hash = git.run(*commit_cmd)
        git.run('update-ref', REF, commit_hash)
    DIRTY_TREES.clear()