#!/usr/bin/env python

# Copyright (C) 2009, 2015 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:
#
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer. 
# 2.  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. 
#
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 gzip, optparse, os, shutil, subprocess, sys

sourceRootDirectory = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
archiveFile = os.path.join(sourceRootDirectory, "layout-test-results.zip")

def main():
    parser = optparse.OptionParser("usage: %prog [options] [action]")
    parser.add_option("--platform", dest="platform")
    parser.add_option("--debug", action="store_const", const="debug", dest="configuration")
    parser.add_option("--release", action="store_const", const="release", dest="configuration")

    options, (action, ) = parser.parse_args()
    if not options.platform:
        parser.error("Platform is required")
    if not options.configuration:
        parser.error("Configuration is required")
    if action not in ('archive'):
        parser.error("Action is required")

    layoutTestResultsDir = os.path.abspath(os.path.join(sourceRootDirectory, "layout-test-results"))
    return archive_test_results(options.configuration, options.platform, layoutTestResultsDir)

def gzip_file(root, name):
    with open(os.path.join(root, name), 'rb') as f_in, gzip.open(os.path.join(root, name + '.gz'), 'wb') as f_out:
        shutil.copyfileobj(f_in, f_out)
        os.remove(os.path.join(root, name))

def compress_spindumps(layoutTestResultsDir):
    file_patterns = ('-spindump.txt','-sample.txt')
    for root, dirs, files in os.walk(layoutTestResultsDir):
        for name in files:
            for pattern in file_patterns:        
                if pattern in name:
                    gzip_file(root, name)

def archive_test_results(configuration, platform, layoutTestResultsDir):
    assert platform in ('mac', 'win', 'gtk', 'wincairo', 'ios', 'wpe')

    try:
        os.unlink(archiveFile)
    except OSError, e:
        if e.errno != 2:
            raise

    try:
        # Ensure that layoutTestResultsDir exists since we cannot archive a directory that does not exist
        os.makedirs(layoutTestResultsDir)
    except OSError, e:
        if e.errno != 17:
            raise

    open(os.path.join(layoutTestResultsDir, '.placeholder'), 'w').close()

    if platform in ('mac', 'ios'):
        compress_spindumps(layoutTestResultsDir)
        if subprocess.call(["ditto", "-c", "-k", "--sequesterRsrc", "--zlibCompressionLevel", "2", layoutTestResultsDir, archiveFile]):
            return 1
    elif platform in ('win', 'gtk', 'wincairo', 'wpe'):
        if subprocess.call(["zip", "-r", "-2", archiveFile, "."], cwd=layoutTestResultsDir):
            return 1

    try:
        shutil.rmtree(layoutTestResultsDir)
    except OSError, e:

        # Python in Cygwin throws a mysterious exception with errno of 90
        # when removing the layout test result directory after successfully
        # deleting its contents, claiming "Directory not empty".
        # We can safely ignore this since it was the directory contents that
        # we are most interested in deleting.
        # Python in Cygwin will also sometimes throw errno 2 or 16 if a process
        # is holding a file open. There's no point in failing to create the
        # archive just because some other process is behaving badly. See
        # <http://webkit.org/b/55581> and <http://webkit.org/b/166720>.
        if e.errno != 90 and e.errno != 2 and e.errno != 16:
            raise

if __name__ == '__main__':
    sys.exit(main())
