#!/usr/bin/env python2.7
#
# 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.
#
# Authors: Andreas Sandberg


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)

    @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
    )

    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 = filter(
        lambda r: r.change_id and r.change_id not in feature_cids,
        reversed(upstream_revs))
    outgoing = filter(
        lambda r: r.change_id and r.change_id not in upstream_cids,
        reversed(feature_revs))
    common = filter(
        lambda r: r.change_id in upstream_cids,
        reversed(feature_revs))
    upstream_unknown = filter(
        lambda r: r.change_id is None,
        reversed(upstream_revs))
    feature_unknown = filter(
        lambda r: r.change_id is None,
        reversed(feature_revs))

    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 = filter(
            lambda r: r.change_id in all_upstream_cids,
            outgoing)
        for rev in incorrect_outgoing:
            print rev




if __name__ == "__main__":
    _main()
