# -*- coding: utf-8 -*-
# Copyright 2010-2014, 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.

"""Copies files.

This script provides more features than 'copies' rule of GYP.
1. The destination file name can be different from the original name.
2. Changes the last update time according to a reference file.
(This is the same as `touch -r REFERENCE_FILE'.)
3. Is able to copy directories recursively.
"""

__author__ = "yukishiino"

import optparse
import os
import shutil
import stat
import sys


def _ErrorExit(message):
  """Prints the error message and exits with the code 1.

  The function never returns.

  Args:
    message: The error message to be printed to stderr.
  """
  print >>sys.stderr, message
  sys.exit(1)


def CopyFiles(src_list, dst, src_base='',
              preserve=False, recursive=False, reference=None,
              ignore_existence_check=False):
  """Copy files like 'cp' command on Unix.

  Args:
    src_list: List of files to be copied.
    dst: The destination file or directory.
    src_base: The base directory which holds |src_list|.
    preserve: Preserves last update time.  Permissions for files are always
        copied.
    recursive: Copies files recursively.
    reference: Last update time in the form of (atime, mtime) to be copied
        to files.  The reference time is prioritized over preserving.
    ignore_existence_check: Ignores existence check for src files.
  """
  if not src_list:
    return

  def _CopyFile(src_file, dst_file):
    if os.path.isdir(dst_file):
      _ErrorExit('An unexpected dir `%s\' exists' % dst_file)
    if ignore_existence_check and not os.path.exists(src_file):
      # Skip non-existent src.
      return
    shutil.copy(src_file, dst_file)
    _CopyUpdateTimeAndPermission(src_file, dst_file)

  def _CopyDir(src_dir, dst_dir, file_list=None):
    if file_list is None:
      file_list = os.listdir(src_dir)
    for filename in file_list:
      src = os.path.join(src_dir, filename)
      dst = os.path.join(dst_dir, filename)
      _Copy(src, dst)

  def _Copy(src, dst):
    if os.path.isdir(src):
      if not recursive:
        _ErrorExit('Cannot copy a directory `%s\'' % src)
      if not os.path.isdir(dst):
        os.mkdir(dst)
        _CopyDir(src, dst)
        _CopyUpdateTimeAndPermission(src, dst)
      else:
        _CopyDir(src, dst)
    else:
      _CopyFile(src, dst)

  def _CopyUpdateTimeAndPermission(src, dst):
    if preserve:
      shutil.copystat(src, dst)
    if reference:
      os.utime(dst, reference)
    # Changes the file writable so we can overwrite it later.
    os.chmod(dst, os.stat(dst).st_mode | stat.S_IWRITE)

  # Create the parent directory of dst.
  dst_parent = os.path.abspath(os.path.dirname(dst))
  if dst_parent and not os.path.exists(dst_parent):
    os.makedirs(dst_parent)

  if len(src_list) is 1:
    src = os.path.join(src_base, src_list[0])
    if os.path.isdir(dst):
      dst = os.path.join(dst, os.path.basename(os.path.abspath(src)))
    _Copy(src, dst)
  else:  # len(src_list) > 1
    if not os.path.isdir(dst):
      os.mkdir(dst)
    for src in src_list:
      src = os.path.abspath(os.path.join(src_base, src))
      (src_dir, src_file) = os.path.split(src)
      _CopyDir(src_dir, dst, [src_file])


def _GetUpdateTime(filename):
  """Returns the update time of the file.

  Args:
    filename: Path to the file.  The file can be a directory.  Symbolic links
        are followed.

  Returns:
    The update time in the form of (atime, mtime).
  """
  stat_info = os.stat(filename)
  return (stat_info.st_atime, stat_info.st_mtime)


def main():
  parser = optparse.OptionParser(
      usage='Usage: %prog [OPTION]... SOURCE... DEST')
  parser.add_option('--preserve', '-p', dest='preserve',
                    action='store_true', default=False,
                    help='Preserves last update time.')
  parser.add_option('--recursive', '-r', dest='recursive',
                    action='store_true', default=False,
                    help='Copies directories recursively.')
  parser.add_option('--reference', dest='reference',
                    help='Uses this file\'s last update time.')
  parser.add_option('--ignore_existence_check', dest='ignore_existence_check',
                    action='store_true', default=False,
                    help='Ignore existence check for src files.')
  (options, args) = parser.parse_args()

  if len(args) < 2:
    _ErrorExit('The arguments must be source(s) and destination files.')

  reference_time = (_GetUpdateTime(options.reference)
                    if options.reference else None)

  src_list = args[:-1]
  dst = args[-1]

  CopyFiles(src_list, dst,
            preserve=options.preserve, recursive=options.recursive,
            reference=reference_time,
            ignore_existence_check=options.ignore_existence_check)


if __name__ == '__main__':
  main()
