#!/usr/bin/env python
# Copyright (c) 2010 Google 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.
#
# This is a very simple script designed to crawl the build directory
# for visual studio express build logs and print them to stdout.

from __future__ import with_statement

import codecs
import os
import re

from webkitpy.common.checkout import scm
from webkitpy.common.system.executive import Executive
from webkitpy.thirdparty import BeautifulSoup


class PrintVisualStudioExpressLogs(object):
    def __init__(self):
        self._executive = Executive()

    def _find_buildlogs(self, build_directory):
        build_log_paths = []
        for dirpath, dirnames, filenames in os.walk(build_directory):
            for file_name in filenames:
                if file_name == "BuildLog.htm":
                    file_path = os.path.join(dirpath, file_name)
                    build_log_paths.append(file_path)
        return build_log_paths

    def _build_order(self):
        """Returns a list of project names in the order in which they are built."""
        script_path = os.path.join(self._scripts_directory(), "print-msvc-project-dependencies")
        sln_path = os.path.join(scm.find_checkout_root(), "WebKit", "win", "WebKit.vcproj", "WebKit.sln")
        lines = self._executive.run_command([script_path, sln_path]).splitlines()
        order = [line.strip() for line in lines if line.find("Folder") == -1]
        order.reverse()
        return order

    def _sort_buildlogs(self, log_paths):
        build_order = self._build_order()
        def sort_key(log_path):
            project_name = os.path.basename(os.path.dirname(os.path.dirname(log_path)))
            try:
                index = build_order.index(project_name)
            except ValueError:
                # If the project isn't in the list, sort it after all items that
                # are in the list.
                index = len(build_order)
            # Sort first by build order, then by project name
            return (index, project_name)
        return sorted(log_paths, key=sort_key)

    def _obj_directory(self):
        build_directory_script_path = os.path.join(self._scripts_directory(), "webkit-build-directory")
        # FIXME: ports/webkit.py should provide the build directory in a nice API.
        # NOTE: The windows VSE build does not seem to use different directories
        # for Debug and Release.
        build_directory = self._executive.run_command([build_directory_script_path, "--top-level"]).rstrip()
        return os.path.join(build_directory, "obj")

    def _scripts_directory(self):
        return os.path.dirname(__file__)

    def _relevant_text(self, log):
        soup = BeautifulSoup.BeautifulSoup(log)
        # The Output Window table is where the useful output starts in the build log.
        output_window_table = soup.find(text=re.compile("Output Window")).findParent("table")
        result = []
        for table in [output_window_table] + output_window_table.findNextSiblings("table"):
            result.extend([text.replace("&nbsp;", "") for text in table.findAll(text=True)])
            result.append("\n")
        return "".join(result)

    def main(self):
        build_log_paths = self._sort_buildlogs(self._find_buildlogs(self._obj_directory()))

        print "Found %s Visual Studio Express Build Logs:\n%s" % (len(build_log_paths), "\n".join(build_log_paths))

        for build_log_path in build_log_paths:
            print "%s:\n" % build_log_path
            with codecs.open(build_log_path, "r", "utf-16") as build_log:
                print self._relevant_text(build_log)


if __name__ == '__main__':
    PrintVisualStudioExpressLogs().main()
