#!/usr/bin/env python3
#
# Copyright (c) 2017-2018 Arm Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import subprocess
import re
from functools import wraps

class Commit(object):
    _re_tag = re.compile(r"^((?:\w|-)+): (.*)$")

    def __init__(self, rev):
        self.rev = rev
        self._log = None
        self._tags = None

    def _git(self, args):
        return subprocess.check_output([ "git", ] + args).decode()

    @property
    def log(self):
        """Log message belonging to a commit returned as a list with on line
        per element.

        """
        if self._log is None:
            self._log = self._git(
                ["show", "--format=%B", "--no-patch", str(self.rev) ]
            ).rstrip("\n").split("\n")
        return self._log

    @property
    def tags(self):
        """Get all commit message tags in the current commit.

        Returns: { tag, [ value, ... ] }

        """
        if self._tags is None:
            tags = {}
            for l in self.log[1:]:
                m = Commit._re_tag.match(l)
                if m:
                    key, value = m.group(1), m.group(2)
                    try:
                        tags[key].append(value)
                    except KeyError:
                        tags[key] = [ value ]
            self._tags = tags

        return self._tags

    @property
    def change_id(self):
        """Get the Change-Id tag from the commit

        Returns: A change ID or None if no change ID has been
        specified.

        """
        try:
            cids = self.tags["Change-Id"]
        except KeyError:
            return None

        assert len(cids) == 1
        return cids[0]

    def __str__(self):
        return "%s: %s" % (self.rev[0:8], self.log[0])

def list_revs(branch, baseline=None, paths=[]):
    """Get a generator that lists git revisions that exist in 'branch'. If
    the optional parameter 'baseline' is specified, the generator
    excludes commits that exist on that branch.

    Returns: Generator of Commit objects

    """

    if baseline is not None:
        query = "%s..%s" % (branch, baseline)
    else:
        query = str(branch)

    changes = subprocess.check_output(
        [ "git", "rev-list", query, '--'] + paths
    ).decode()

    if changes == "":
        return

    for rev in changes.rstrip("\n").split("\n"):
        assert rev != ""
        yield Commit(rev)

def list_changes(upstream, feature, paths=[]):
    feature_revs = tuple(list_revs(upstream, feature, paths=paths))
    upstream_revs = tuple(list_revs(feature, upstream, paths=paths))

    feature_cids = dict([
        (c.change_id, c) for c in feature_revs if c.change_id is not None ])
    upstream_cids = dict([
        (c.change_id, c) for c in upstream_revs if c.change_id is not None ])

    incoming = [r for r in reversed(upstream_revs) \
        if r.change_id and r.change_id not in feature_cids]
    outgoing = [r for r in reversed(feature_revs) \
        if r.change_id and r.change_id not in upstream_cids]
    common = [r for r in reversed(feature_revs) \
        if r.change_id in upstream_cids]
    upstream_unknown = [r for r in reversed(upstream_revs) \
        if r.change_id is None]
    feature_unknown = [r for r in reversed(feature_revs) \
        if r.change_id is None]

    return incoming, outgoing, common, upstream_unknown, feature_unknown

def _main():
    import argparse
    parser = argparse.ArgumentParser(
        description="List incoming and outgoing changes in a feature branch")

    parser.add_argument("--upstream", "-u", type=str, default="origin/master",
                        help="Upstream branch for comparison. " \
                        "Default: %(default)s")
    parser.add_argument("--feature", "-f", type=str, default="HEAD",
                        help="Feature branch for comparison. " \
                        "Default: %(default)s")
    parser.add_argument("--show-unknown", action="store_true",
                        help="Print changes without Change-Id tags")
    parser.add_argument("--show-common", action="store_true",
                        help="Print common changes")
    parser.add_argument("--deep-search", action="store_true",
                        help="Use a deep search to find incorrectly " \
                        "rebased changes")
    parser.add_argument("paths", metavar="PATH", type=str, nargs="*",
                        help="Paths to list changes for")

    args = parser.parse_args()

    incoming, outgoing, common, upstream_unknown, feature_unknown = \
        list_changes(args.upstream, args.feature, paths=args.paths)

    if incoming:
        print("Incoming changes:")
        for rev in incoming:
            print(rev)
        print()

    if args.show_unknown and upstream_unknown:
        print("Upstream changes without change IDs:")
        for rev in upstream_unknown:
            print(rev)
        print()

    if outgoing:
        print("Outgoing changes:")
        for rev in outgoing:
            print(rev)
        print()

    if args.show_common and common:
        print("Common changes:")
        for rev in common:
            print(rev)
        print()

    if args.show_unknown and feature_unknown:
        print("Outgoing changes without change IDs:")
        for rev in feature_unknown:
            print(rev)

    if args.deep_search:
        print("Incorrectly rebased changes:")
        all_upstream_revs = list_revs(args.upstream, paths=args.paths)
        all_upstream_cids = dict([
            (c.change_id, c) for c in all_upstream_revs \
            if c.change_id is not None ])
        incorrect_outgoing = [r for r in outgoing if r.change_id in all_upstream_cids]
        for rev in incorrect_outgoing:
            print(rev)




if __name__ == "__main__":
    _main()
