#!/usr/bin/python
# Copyright (c) 2009, Google Inc. All rights reserved.
# Copyright (c) 2009 Apple Inc. All rights reserved.
#
# 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 Google Inc. 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.
#
# A tool for automating dealing with bugzilla, posting patches, committing patches, etc.

import fileinput # inplace file editing for set_reviewer_in_changelog
import os
import re
import StringIO # for add_patch_to_bug file wrappers
import subprocess
import sys

from optparse import OptionParser, IndentedHelpFormatter, SUPPRESS_USAGE, make_option

# Import WebKit-specific modules.
from modules.bugzilla import Bugzilla
from modules.scm import detect_scm_system, ScriptError

def log(string):
    print >> sys.stderr, string

def error(string):
    log(string)
    exit(1)

def plural(noun):
    # This is a dumb plural() implementation which was just enough for our uses.
    if re.search('h$', noun):
        return noun + 'es'
    else:
        return noun + 's'

def pluralize(noun, count):
    if count != 1:
        noun = plural(noun)
    return "%d %s" % (count, noun)

# These could be put in some sort of changelogs.py.
def latest_changelog_entry(changelog_path):
    # e.g. 2009-06-03  Eric Seidel  <eric@webkit.org>
    changelog_date_line_regexp = re.compile('^(\d{4}-\d{2}-\d{2})' # Consume the date.
                                  + '\s+(.+)\s+' # Consume the name.
                                  + '<([^<>]+)>$') # And finally the email address.
    
    entry_lines = []
    changelog = open(changelog_path)
    try:
        log("Parsing ChangeLog: " + changelog_path)
        # The first line should be a date line.
        first_line = changelog.readline()
        if not changelog_date_line_regexp.match(first_line):
            return None
        entry_lines.append(first_line)
        
        for line in changelog:
            # If we've hit the next entry, return.
            if changelog_date_line_regexp.match(line):
                return ''.join(entry_lines)
            entry_lines.append(line)
    finally:
        changelog.close()
    # We never found a date line!
    return None

def set_reviewer_in_changelog(changelog_path, reviewer):
    # inplace=1 creates a backup file and re-directs stdout to the file
    for line in fileinput.FileInput(changelog_path, inplace=1):
        print line.replace("NOBODY (OOPS!)", reviewer),

def modified_changelogs(scm):
    changelog_paths = []
    paths = scm.changed_files()
    for path in paths:
        if os.path.basename(path) == "ChangeLog":
            changelog_paths.append(path)
    return changelog_paths

def bug_id_from_commit_message(commit_message):
    match = re.search("http\://webkit\.org/b/(?P<bug_id>\d+)", commit_message, re.MULTILINE)
    if match:
        return match.group('bug_id')
    match = re.search(Bugzilla.bug_server_regex + "show_bug\.cgi\?id=(?P<bug_id>\d+)", commit_message, re.MULTILINE)
    if match:
        return match.group('bug_id')
    return None

def commit_message_for_this_commit(scm):
    changelog_paths = modified_changelogs(scm)
    if not len(changelog_paths):
        error("Found no modified ChangeLogs, cannot create a commit message.\n"
              "All changes require a ChangeLog.  See:\n"
              "http://webkit.org/coding/contributing.html")

    changelog_messages = []
    for path in changelog_paths:
        changelog_entry = latest_changelog_entry(path)
        if not changelog_entry:
            error("Failed to parse ChangeLog: " + os.path.abspath(path))
        changelog_messages.append(changelog_entry)
    
    # FIXME: We should sort and label the ChangeLog messages like commit-log-editor does.
    return ''.join(changelog_messages)


class Command:
    def __init__(self, help_text, argument_names="", options=[]):
        self.help_text = help_text
        self.argument_names = argument_names
        self.options = options
        self.option_parser = HelpPrintingOptionParser(usage=SUPPRESS_USAGE, add_help_option=False, option_list=self.options)
    
    def name_with_arguments(self, command_name):
        usage_string = command_name
        if len(self.options) > 0:
            usage_string += " [options]"
        if self.argument_names:
            usage_string += " " + self.argument_names
        return usage_string

    def parse_args(self, args):
        return self.option_parser.parse_args(args)

    def execute(self, options, args, tool):
        raise NotImplementedError, "subclasses must implement"


class BugsInCommitQueue(Command):
    def __init__(self):
        Command.__init__(self, 'Bugs in the commit queue')

    def execute(self, options, args, tool):
        bug_ids = tool.bugs.fetch_bug_ids_from_commit_queue()
        for bug_id in bug_ids:
            print "%s" % tool.bugs.bug_url_for_bug_id(bug_id)


class PatchesInCommitQueue(Command):
    def __init__(self):
        Command.__init__(self, 'Patches attached to bugs in the commit queue')

    def execute(self, options, args, tool):
        patches = tool.bugs.fetch_patches_from_commit_queue()
        log("Patches in commit queue:")
        for patch in patches:
            print "%s" % patch['url']


class ReviewedPatchesOnBug(Command):
    def __init__(self):
        Command.__init__(self, 'r+\'d patches on a bug', 'BUGID')

    def execute(self, options, args, tool):
        bug_id = args[0]
        patches_to_land = tool.bugs.fetch_reviewed_patches_from_bug(bug_id)
        for patch in patches_to_land:
            print "%s" % patch['url']


class ApplyPatchesFromBug(Command):
    def __init__(self):
        options = [
            make_option("--no-update", action="store_false", dest="update", default=True, help="Don't update the working directory before applying patches"),
            make_option("--force-clean", action="store_true", dest="force_clean", default=False, help="Clean working directory before applying patches (removes local changes and commits)"),
            make_option("--no-clean", action="store_false", dest="clean", default=True, help="Don't check if the working directory is clean before applying patches"),
            make_option("--local-commit", action="store_true", dest="local_commit", default=False, help="Make a local commit for each applied patch"),
        ]
        Command.__init__(self, 'Applies all patches on a bug to the local working directory without committing.', 'BUGID', options=options)

    @staticmethod
    def apply_patches(patches, scm, commit_each):
        for patch in patches:
            scm.apply_patch(patch)
            if commit_each:
                commit_message = commit_message_for_this_commit(scm)
                scm.commit_locally_with_message(commit_message or patch['name'])

    def execute(self, options, args, tool):
        bug_id = args[0]
        patches = tool.bugs.fetch_reviewed_patches_from_bug(bug_id)
        os.chdir(tool.scm().checkout_root)
        if options.clean:
            tool.scm().ensure_clean_working_directory(options.force_clean)
        if options.update:
            tool.scm().update_webkit()
        
        if options.local_commit and not tool.scm().supports_local_commits():
            error("--local-commit passed, but %s does not support local commits" % tool.scm().display_name())
        
        self.apply_patches(patches, tool.scm(), options.local_commit)

def bug_comment_from_commit_text(scm, commit_text):
    match = re.search(scm.commit_success_regexp(), commit_text, re.MULTILINE)
    svn_revision = match.group('svn_revision')
    commit_text += ("\nhttp://trac.webkit.org/changeset/%s" % svn_revision)
    return commit_text

class LandAndUpdateBug(Command):
    def __init__(self):
        options = [
            make_option("-r", "--reviewer", action="store", type="string", dest="reviewer", help="Update ChangeLogs to say Reviewed by REVIEWER."),
            make_option("--no-close", action="store_false", dest="close_bug", default=True, help="Leave bug open after landing."),
            make_option("--no-build", action="store_false", dest="build", default=True, help="Commit without building first, implies --no-test."),
            make_option("--no-test", action="store_false", dest="test", default=True, help="Commit without running run-webkit-tests."),
        ]
        Command.__init__(self, 'Lands the current working directory diff and updates the bug if provided.', '[BUGID]', options=options)

    def guess_reviewer_from_bug(self, bugs, bug_id):
        patches = bugs.fetch_reviewed_patches_from_bug(bug_id)
        if len(patches) != 1:
            log("%s on bug %s, cannot infer reviewer." % (pluralize("reviewed patch", len(patches)), bug_id))
            return None
        patch = patches[0]
        reviewer = patch['reviewer']
        log('Guessing "%s" as reviewer from attachment %s on bug %s.' % (reviewer, patch['id'], bug_id))
        return reviewer

    def update_changelogs_with_reviewer(self, reviewer, bug_id, tool):
        if not reviewer:
            if not bug_id:
                log("No bug id provided and --reviewer= not provided.  Not updating ChangeLogs with reviewer.")
                return
            reviewer = self.guess_reviewer_from_bug(tool.bugs, bug_id)

        if not reviewer:
            log("Failed to guess reviewer from bug %s and --reviewer= not provided.  Not updating ChangeLogs with reviewer." % bug_id)
            return

        changelogs = modified_changelogs(tool.scm())
        for changelog in changelogs:
            set_reviewer_in_changelog(changelog, reviewer)

    def execute(self, options, args, tool):
        bug_id = args[0] if len(args) else None
        os.chdir(tool.scm().checkout_root)

        self.update_changelogs_with_reviewer(options.reviewer, bug_id, tool)

        comment_text = LandPatchesFromBugs.build_and_commit(tool.scm(), options)
        if bug_id:
            log("Updating bug %s" % bug_id)
            if options.close_bug:
                tool.bugs.close_bug_as_fixed(bug_id, comment_text)
            else:
                # FIXME: We should a smart way to figure out if the patch is attached
                # to the bug, and if so obsolete it.
                tool.bugs.post_comment_to_bug(bug_id, comment_text)
        else:
            log(comment_text)
            log("No bug id provided.")

class LandPatchesFromBugs(Command):
    def __init__(self):
        options = [
            make_option("--force-clean", action="store_true", dest="force_clean", default=False, help="Clean working directory before applying patches (removes local changes and commits)"),
            make_option("--no-clean", action="store_false", dest="clean", default=True, help="Don't check if the working directory is clean before applying patches"),
            make_option("--no-build", action="store_false", dest="build", default=True, help="Commit without building first, implies --no-test."),
            make_option("--no-test", action="store_false", dest="test", default=True, help="Commit without running run-webkit-tests."),
        ]
        Command.__init__(self, 'Lands all patches on a bug optionally testing them first', 'BUGID', options=options)

    @staticmethod
    def run_and_throw_if_fail(script_name):
        build_webkit_process = subprocess.Popen(script_name)
        return_code = build_webkit_process.wait()
        if return_code:
            raise ScriptError("%s failed with exit code %d" % (script_name, return_code))

    @classmethod
    def run_webkit_script(cls, script_name):
        # We might need to pass scm into this function for scm.checkout_root
        cls.run_and_throw_if_fail(os.path.join("WebKitTools", "Scripts", script_name))

    @classmethod
    def build_webkit(cls):
        cls.run_webkit_script("build-webkit")

    @classmethod
    def run_webkit_tests(cls):
        cls.run_webkit_script("run-webkit-tests")

    @staticmethod
    def setup_for_landing(scm, options):
        os.chdir(scm.checkout_root)
        scm.ensure_no_local_commits(options.force_clean)
        if options.clean:
            scm.ensure_clean_working_directory(options.force_clean)

    @classmethod
    def build_and_commit(cls, scm, options):
        if options.build:
            cls.build_webkit()
            if options.test:
                cls.run_webkit_tests()
        commit_message = commit_message_for_this_commit(scm)
        commit_log = scm.commit_with_message(commit_message)
        return bug_comment_from_commit_text(scm, commit_log)

    @classmethod
    def land_patches(cls, bug_id, patches, options, tool):
        try:
            comment_text = ""
            for patch in patches:
                tool.scm().update_webkit() # Update before every patch in case the tree has changed
                tool.scm().apply_patch(patch)
                comment_text = cls.build_and_commit(tool.scm(), options)

                # If we're commiting more than one patch, update the bug as we go.
                if len(patches) > 1:
                    tool.bugs.obsolete_attachment(patch['id'], comment_text)

            if len(patches) > 1:
                comment_text = "All reviewed patches landed, closing."

            tool.bugs.close_bug_as_fixed(bug_id, comment_text)
        except ScriptError, e:
            # We should add a comment to the bug, and r- the patch on failure
            error(e)

    def execute(self, options, args, tool):
        if not len(args):
            error("bug-id(s) required")

        bugs_to_patches = {}
        patch_count = 0
        for bug_id in args:
            patches = tool.bugs.fetch_reviewed_patches_from_bug(bug_id)
            if not len(patches):
                exit("No reviewed patches found on %s" % bug_id)
            patch_count += len(patches)
            bugs_to_patches[bug_id] = patches

        log("Landing %s from %s." % (pluralize("patch", patch_count), pluralize("bug", len(args))))
        
        self.setup_for_landing(tool.scm(), options)

        for bug_id in args:
            self.land_patches(bug_id, bugs_to_patches[bug_id], options, tool)

class CommitMessageForCurrentDiff(Command):
    def __init__(self):
        Command.__init__(self, 'Prints a commit message suitable for the uncommitted changes.')

    def execute(self, options, args, tool):
        os.chdir(tool.scm().checkout_root)
        print "%s" % commit_message_for_this_commit(tool.scm())


class ObsoleteAttachmentsOnBug(Command):
    def __init__(self):
        Command.__init__(self, 'Marks all attachments on a bug as obsolete.', 'BUGID')

    def execute(self, options, args, tool):
        bug_id = args[0]
        attachments = tool.bugs.fetch_attachments_from_bug(bug_id)
        for attachment in attachments:
            if not attachment['is_obsolete']:
                tool.bugs.obsolete_attachment(attachment['id'])


class PostDiffAsPatchToBug(Command):
    def __init__(self):
        options = [
            make_option("--no-obsolete", action="store_false", dest="obsolete_patches", default=True, help="Do not obsolete old patches before posting this one."),
            make_option("--no-review", action="store_false", dest="review", default=True, help="Do not mark the patch for review."),
            make_option("-m", "--description", action="store", type="string", dest="description", help="Description string for the attachment (default: 'patch')"),
        ]
        Command.__init__(self, 'Attaches the current working directory diff to a bug as a patch file.', 'BUGID', options=options)

    @staticmethod
    def obsolete_patches_on_bug(bug_id, bugs):
        patches = bugs.fetch_patches_from_bug(bug_id)
        if len(patches):
            log("Obsoleting %s on bug %s" % (pluralize('old patch', len(patches)), bug_id))
            for patch in patches:
                bugs.obsolete_attachment(patch['id'])

    def execute(self, options, args, tool):
        bug_id = args[0]

        if options.obsolete_patches:
            self.obsolete_patches_on_bug(bug_id, tool.bugs)

        diff = tool.scm().create_patch()
        diff_file = StringIO.StringIO(diff) # add_patch_to_bug expects a file-like object

        description = options.description or "patch"
        tool.bugs.add_patch_to_bug(bug_id, diff_file, description, mark_for_review=options.review)


class PostCommitsAsPatchesToBug(Command):
    def __init__(self):
        options = [
            make_option("-b", "--bug-id", action="store", type="string", dest="bug_id", help="Specify bug id if no URL is provided in the commit log."),
            make_option("--no-comment", action="store_false", dest="comment", default=True, help="Do not use commit log message as a comment for the patch."),
            make_option("--no-obsolete", action="store_false", dest="obsolete_patches", default=True, help="Do not obsolete old patches before posting new ones."),
            make_option("--no-review", action="store_false", dest="review", default=True, help="Do not mark the patch for review."),
        ]
        Command.__init__(self, 'Attaches a range of local commits to bugs as patch files.', 'COMMITISH', options=options)

    def execute(self, options, args, tool):
        if not tool.scm().supports_local_commits():
            error(tool.scm().display_name() + " does not support local commits.")

        commit_ids = tool.scm().commit_ids_from_range_arguments(args, cherry_pick=True)

        if len(commit_ids) > 10:
            error("Are you sure you want to attach %s patches?" % (pluralize('patch', len(commit_ids))))
            # Could add a --patches-limit option.

        have_obsoleted_patches = set()
        for commit_id in commit_ids:
            commit_message = tool.scm().commit_message_for_commit(commit_id)
            commit_lines = commit_message.splitlines()

            bug_id = options.bug_id or bug_id_from_commit_message(commit_message)
            if not bug_id:
                log("Skipping %s: No bug id found in commit log or specified with --bug-id." % commit_id)
                continue

            if options.obsolete_patches and bug_id not in have_obsoleted_patches:
                PostDiffAsPatchToBug.obsolete_patches_on_bug(bug_id, tool.bugs)
                have_obsoleted_patches.update(bug_id)

            description = commit_lines[0]
            comment_text = None
            if (options.comment):
                comment_text = "\n".join(commit_lines[1:])
                comment_text += "\n---\n"
                comment_text += tool.scm().files_changed_summary_for_commit(commit_id)

            diff = tool.scm().create_patch_from_local_commit(commit_id)
            diff_file = StringIO.StringIO(diff) # add_patch_to_bug expects a file-like object
            tool.bugs.add_patch_to_bug(bug_id, diff_file, description, comment_text, mark_for_review=options.review)


class NonWrappingEpilogIndentedHelpFormatter(IndentedHelpFormatter):
    def __init__(self):
        IndentedHelpFormatter.__init__(self)

    # The standard IndentedHelpFormatter paragraph-wraps the epilog, killing our custom formatting.
    def format_epilog(self, epilog):
        if epilog:
            return "\n" + epilog + "\n"
        return ""

class HelpPrintingOptionParser(OptionParser):
    def error(self, msg):
        self.print_usage(sys.stderr)
        error_message = "%s: error: %s\n" % (self.get_prog_name(), msg)
        error_message += "\nType '" + self.get_prog_name() + " --help' to see usage.\n"
        self.exit(2, error_message)

class BugzillaTool:
    def __init__(self):
        self.cached_scm = None
        self.bugs = Bugzilla()
        self.commands = [
            { 'name' : 'bugs-to-commit', 'object' : BugsInCommitQueue() },
            { 'name' : 'patches-to-commit', 'object' : PatchesInCommitQueue() },
            { 'name' : 'reviewed-patches', 'object' : ReviewedPatchesOnBug() },
            { 'name' : 'apply-patches', 'object' : ApplyPatchesFromBug() },
            { 'name' : 'land-diff', 'object' : LandAndUpdateBug() },
            { 'name' : 'land-patches', 'object' : LandPatchesFromBugs() },
            { 'name' : 'commit-message', 'object' : CommitMessageForCurrentDiff() },
            { 'name' : 'obsolete-attachments', 'object' : ObsoleteAttachmentsOnBug() },
            { 'name' : 'post-diff', 'object' : PostDiffAsPatchToBug() },
            { 'name' : 'post-commits', 'object' : PostCommitsAsPatchesToBug() },
        ]
        
        self.global_option_parser = HelpPrintingOptionParser(usage=self.usage_line(), formatter=NonWrappingEpilogIndentedHelpFormatter(), epilog=self.commands_usage())
        self.global_option_parser.add_option("--dry-run", action="store_true", dest="dryrun", help="do not touch remote servers", default=False)
    
    def scm(self):
        # Lazily initialize SCM to not error-out before command line parsing (or when running non-scm commands).
        original_cwd = os.path.abspath('.')
        if not self.cached_scm:
            self.cached_scm = detect_scm_system(original_cwd)
        
        if not self.cached_scm:
            script_directory = os.path.abspath(sys.path[0])
            webkit_directory = os.path.abspath(os.path.join(script_directory, "../.."))
            self.cached_scm = detect_scm_system(webkit_directory)
            if self.cached_scm:
                log("The current directory (%s) is not a WebKit checkout, using %s" % (original_cwd, webkit_directory))
            else:
                error("FATAL: Failed to determine the SCM system for either %s or %s" % (original_cwd, webkit_directory))
        
        return self.cached_scm
    
    @staticmethod
    def usage_line():
        return "Usage: %prog [options] command [command-options] [command-arguments]"
    
    def commands_usage(self):
        commands_text = "Commands:\n"
        longest_name_length = 0
        command_rows = []
        for command in self.commands:
            command_object = command['object']
            command_name_and_args = command_object.name_with_arguments(command['name'])
            command_rows.append({ 'name-and-args': command_name_and_args, 'object': command_object })
            longest_name_length = max([longest_name_length, len(command_name_and_args)])
        
        # Use our own help formatter so as to indent enough.
        formatter = IndentedHelpFormatter()
        formatter.indent()
        formatter.indent()
        
        for row in command_rows:
            command_object = row['object']
            commands_text += "  " + row['name-and-args'].ljust(longest_name_length + 3) + command_object.help_text + "\n"
            commands_text += command_object.option_parser.format_option_help(formatter)
        return commands_text

    def handle_global_args(self, args):
        (options, args) = self.global_option_parser.parse_args(args)
        if len(args):
            # We'll never hit this because split_args splits at the first arg without a leading '-'
            self.global_option_parser.error("Extra arguments before command: " + args)
        
        if options.dryrun:
            self.scm().dryrun = True
            self.bugs.dryrun = True
    
    @staticmethod
    def split_args(args):
        # Assume the first argument which doesn't start with '-' is the command name.
        command_index = 0
        for arg in args:
            if arg[0] != '-':
                break
            command_index += 1
        else:
            return (args[:], None, [])

        global_args = args[:command_index]
        command = args[command_index]
        command_args = args[command_index + 1:]
        return (global_args, command, command_args)
    
    def command_by_name(self, command_name):
        for command in self.commands:
            if command_name == command['name']:
                return command
        return None
    
    def main(self):
        (global_args, command_name, args_after_command_name) = self.split_args(sys.argv[1:])
        
        # Handle --help, etc:
        self.handle_global_args(global_args)
        
        if not command_name:
            self.global_option_parser.error("No command specified")
        
        command = self.command_by_name(command_name)
        if not command:
            self.global_option_parser.error(command_name + " is not a recognized command")
        
        command_object = command['object']
        (command_options, command_args) = command_object.parse_args(args_after_command_name)
        return command_object.execute(command_options, command_args, self)


def main():
    tool = BugzillaTool()
    return tool.main()

if __name__ == "__main__":
    main()
