| #!/bin/env python |
| |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| |
| import os |
| import sys |
| import argparse |
| from datetime import datetime |
| |
| import git |
| import pysvn |
| from mercurial import ui, hg, cmdutil |
| |
| |
| def main(opts): |
| if opts.type == 'git': |
| repo = git.Repo(opts.repo_path, odbt=git.GitCmdObjectDB) |
| cid = opts.cid |
| path = opts.path.strip('/') |
| tree = repo.commit(opts.cid).tree |
| if path: |
| tree = tree[path] |
| names = [n.name for n in tree] |
| impl = impl_git_tree if opts.full_tree else impl_git_node |
| elif opts.type == 'hg': |
| repo = hg.repository(HgUI(), opts.repo_path) |
| cid = None if opts.cid == 'HEAD' else ['%s:0' % opts.cid] |
| path = opts.path.strip('/') |
| filenames = repo['tip' if opts.cid == 'HEAD' else opts.cid].manifest().keys() |
| filenames = [name for name in filenames if name.startswith(('%s/' % path).lstrip('/'))] |
| names = set() |
| for name in filenames: |
| names.add(name.split('/')[0]) |
| names = list(names) |
| impl = impl_hg_tree if opts.full_tree else impl_hg_node |
| elif opts.type == 'svn': |
| repo = pysvn.Client() |
| if opts.cid == 'HEAD': |
| cid = pysvn.Revision(pysvn.opt_revision_kind.head) |
| else: |
| cid = pysvn.Revision(pysvn.opt_revision_kind.number, opts.cid) |
| path = opts.path.strip('/') |
| names = [] |
| impl = impl_svn_tree if opts.full_tree else impl_svn_node |
| |
| sys.stdout.write('Timing %s' % ('full tree' if opts.full_tree else 'node')) |
| sys.stdout.flush() |
| total = 0.0 |
| for i in range(opts.count): |
| sys.stdout.write('.') |
| sys.stdout.flush() |
| start = datetime.now() |
| impl(repo, cid, path, names, opts.repo_path) |
| end = datetime.now() |
| total += (end - start).total_seconds() |
| print |
| print 'Total time: %s' % total |
| print 'Average time per run: %s' % (total / opts.count) |
| |
| |
| def impl_git_tree(repo, cid, path, names, *args): |
| data = {} |
| for name in names: |
| #data[name] = repo.git.rev_list(cid, '--', os.path.join(path, name), max_count=1) |
| data[name] = git.Commit.iter_items(repo, cid, os.path.join(path, name), max_count=1).next().hexsha |
| return data |
| |
| def impl_git_node(repo, cid, path, *args): |
| #return repo.git.rev_list(cid, '--', path, max_count=1) |
| return git.Commit.iter_items(repo, cid, path, max_count=1).next().hexsha |
| |
| |
| def impl_hg_tree(repo, cid, path, names, *args): |
| m = cmdutil.match(repo, pats=[path], default=path) |
| data = {} |
| for name in names: |
| rev_iter = cmdutil.walkchangerevs(repo, m, {'rev': cid}, lambda c,f: None) |
| data[name] = rev_iter.next().hex() |
| return data |
| |
| def impl_hg_node(repo, cid, path, *args): |
| m = cmdutil.match(repo, pats=[path], default=path) |
| rev_iter = cmdutil.walkchangerevs(repo, m, {'rev': cid}, lambda c,f: None) |
| return rev_iter.next().hex() |
| |
| def impl_svn_tree(repo, cid, path, names, repo_path, *args): |
| infos = repo.info2( |
| 'file://%s/%s' % (repo_path, path), |
| revision=cid, |
| depth=pysvn.depth.immediates) |
| data = {} |
| for name, info in infos[1:]: |
| data[name] = info.last_changed_rev |
| return data |
| |
| def impl_svn_node(repo, cid, path, names, repo_path, *args): |
| logs = repo.log( |
| 'file://%s/%s' % (repo_path, path), |
| revision_start=cid, |
| limit=1) |
| return logs[0].revision.number |
| |
| |
| class HgUI(ui.ui): |
| '''Hg UI subclass that suppresses reporting of untrusted hgrc files.''' |
| def __init__(self, *args, **kwargs): |
| super(HgUI, self).__init__(*args, **kwargs) |
| self._reportuntrusted = False |
| |
| def parse_opts(): |
| parser = argparse.ArgumentParser(description='Benchmark getting LCD from repo tool') |
| parser.add_argument('--type', default='git', dest='type', |
| help='Type of repository being tested.') |
| parser.add_argument('--repo-path', dest='repo_path', required=True, |
| help='Path to the repository to test against') |
| parser.add_argument('--commit', default='HEAD', dest='cid', |
| help='Commit ID or revision number to test against') |
| parser.add_argument('--path', default='', dest='path', |
| help='Path within the repository to test against') |
| parser.add_argument('--count', type=int, default=100, dest='count', |
| help='Number of times to execute') |
| parser.add_argument('--full-tree', action='store_true', default=False, dest='full_tree', |
| help='Time full tree listing instead of just the single node') |
| return parser.parse_args() |
| |
| if __name__ == '__main__': |
| main(parse_opts()) |