'''
Downloads the actual gm results most recently generated by the Skia buildbots,
and adds any new ones to SVN control.

This tool makes it much easier to check in new baselines, via the following
steps:

cd .../trunk
svn update
# make sure there are no files awaiting svn commit
python tools/download-baselines.py gm/base-macmini-lion-fixed  # or other gm/ subdir
# validate that the new images look right (maybe using compare-baselines.py)
# upload CL for review
# validate that the new images look right in the review tool
# commit CL

Launch with --help to see more options.


Copyright 2011 Google Inc.

Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
'''

# common Python modules
import fnmatch
import optparse
import os
import re
import shutil
import sys
import tempfile

# modules declared within this same directory
import svn

# Base URL of SVN repository where buildbots store actual gm image results.
SVN_BASE_URL = 'http://skia-autogen.googlecode.com/svn/gm-actual'

USAGE_STRING = 'usage: %s [options] <baseline_subdir>'
OPTION_IGNORE_LOCAL_MODS = '--ignore-local-mods'
OPTION_ADD_NEW_FILES = '--add-new-files'

def GetLatestResultsSvnUrl(baseline_subdir):
    """Return SVN URL from which we can check out the MOST RECENTLY generated
    images for this baseline type.

    @param baseline_subdir indicates which platform we want images for
    """
    # trim off 'gm/' prefix
    gm_prefix = 'gm%s' % os.sep
    if not baseline_subdir.startswith(gm_prefix):
        raise Exception('baseline_subdir "%s" should start with "%s"' % (
            baseline_subdir, gm_prefix))
    return '%s/%s' % (SVN_BASE_URL, baseline_subdir[len(gm_prefix):])

def CopyMatchingFiles(source_dir, dest_dir, filename_pattern,
                      only_copy_updates=False):
    """Copy all files from source_dir that match filename_pattern, and
    save them (with their original filenames) in dest_dir.

    @param source_dir
    @param dest_dir where to save the copied files
    @param filename_pattern only copy files that match this Unix-style filename
           pattern (e.g., '*.jpg')
    @param only_copy_updates if True, only copy files that are already
           present in dest_dir
    """
    all_filenames = os.listdir(source_dir)
    matching_filenames = fnmatch.filter(all_filenames, filename_pattern)
    for filename in matching_filenames:
        source_path = os.path.join(source_dir, filename)
        dest_path = os.path.join(dest_dir, filename)
        if only_copy_updates and not os.path.isfile(dest_path):
            continue
        shutil.copyfile(source_path, dest_path)

def Main(options, args):
    """Download most recently generated baseline images for a given platform,
    and add any new ones to SVN control.

    @param options
    @param args
    """
    num_args = len(args)
    if num_args != 1:
        RaiseUsageException()

    # Create repo_to_modify to handle the SVN repository we will add files to.
    baseline_subdir = args[0].rstrip(os.sep);
    if not os.path.isdir(baseline_subdir):
        raise Exception('could not find baseline_subdir "%s"' % baseline_subdir)
    repo_to_modify = svn.Svn(baseline_subdir)

    # If there are any locally modified files in that directory, exit
    # (so that we don't risk overwriting the user's previous work).
    new_and_modified_files = repo_to_modify.GetNewAndModifiedFiles()
    if not options.ignore_local_mods:
        if new_and_modified_files:
            raise Exception('Exiting because there are already new and/or '
                            'modified files in %s.  To continue in spite of '
                            'that, run with %s option.' % (
                                baseline_subdir, OPTION_IGNORE_LOCAL_MODS))

    # Download actual gm images into a separate repo in a temporary directory.
    tempdir = tempfile.mkdtemp()
    download_repo = svn.Svn(tempdir)
    download_repo.Checkout(GetLatestResultsSvnUrl(baseline_subdir), '.')

    # Copy any of those files we are interested in into repo_to_modify,
    # and then delete the temporary directory.
    CopyMatchingFiles(source_dir=tempdir, dest_dir=baseline_subdir,
                      filename_pattern='*.png',
                      only_copy_updates=(not options.add_new_files))
    shutil.rmtree(tempdir)
    download_repo = None

    # Add any new files to SVN control (if we are running with add_new_files).
    new_files = repo_to_modify.GetNewFiles()
    if new_files and options.add_new_files:
        repo_to_modify.AddFiles(new_files)

    # Set the mimetype property on *all* image files in baseline_subdir, even
    # the ones that were already there (in case that property wasn't properly
    # set already).
    repo_to_modify.SetPropertyByFilenamePattern(
        '*.png', svn.PROPERTY_MIMETYPE, 'image/png')
    repo_to_modify.SetPropertyByFilenamePattern(
        '*.pdf', svn.PROPERTY_MIMETYPE, 'application/pdf')

def RaiseUsageException():
    raise Exception(USAGE_STRING %  __file__)

if __name__ == '__main__':
    parser = optparse.OptionParser(USAGE_STRING % '%prog')
    parser.add_option(OPTION_IGNORE_LOCAL_MODS,
                      action='store_true', default=False,
                      help='allow tool to run even if there are already '
                      'local modifications in the baseline_subdir')
    parser.add_option(OPTION_ADD_NEW_FILES,
                      action='store_true', default=False,
                      help='in addition to downloading new versions of '
                      'existing baselines, also download baselines that are '
                      'not under SVN control yet')
    (options, args) = parser.parse_args()
    Main(options, args)
