#!/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())
