parameters: (src, dst, overwrite_existing_file=False, pattern_paths=None, is_pattern_required=False, fail_on_error=True)
return_statement: return copied_files
docstring: Copy a tree from a source folder to a destination folder.  If the destination does not exist, then create
      a copy automatically.  If a destination does exist, then either overwrite based on the owerwrite_existing_file
      parameter or based on if the file is different (currently only file size is checked)
  
      :param src:     The source tree to copy from
      :param dst:     The target tree to copy to
      :param overwrite_existing_file:     Flag to always overwrite (otherwise follow the copy rule)
      :param is_pattern_required: Tells the function how to interpret the pattern_paths, pattern_paths are required
       paths if is_pattern_required is True, it will be the ignore paths if it is False
      :param pattern_paths:    Any particular file/pattern to ignore
      :return:  The number of files actually copied
docstring_summary: Copy a tree from a source folder to a destination folder.  If the destination does not exist, then create
      a copy automatically.  If a destination does exist, then either overwrite based on the owerwrite_existing_file
      parameter or based on if the file is different (currently only file size is checked)
docstring_tokens: Copy a tree from a source folder to a destination folder . If the destination does not exist then create a copy automatically . If a destination does exist then either overwrite based on the owerwrite_existing_file parameter or based on if the file is different ( currently only file size is checked )
function: def copy_tree2(src, dst, overwrite_existing_file=False, pattern_paths=None, is_pattern_required=False, fail_on_error=True):
      """
      Copy a tree from a source folder to a destination folder.  If the destination does not exist, then create
      a copy automatically.  If a destination does exist, then either overwrite based on the owerwrite_existing_file
      parameter or based on if the file is different (currently only file size is checked)
  
      :param src:     The source tree to copy from
      :param dst:     The target tree to copy to
      :param overwrite_existing_file:     Flag to always overwrite (otherwise follow the copy rule)
      :param is_pattern_required: Tells the function how to interpret the pattern_paths, pattern_paths are required
       paths if is_pattern_required is True, it will be the ignore paths if it is False
      :param pattern_paths:    Any particular file/pattern to ignore
      :return:  The number of files actually copied
      """
  
      if os.path.isdir(src) is False:
          Logs.warn('[WARN] Unable to copy {} to destination {} using copy_tree2. {} is not a directory.'.format(src, dst, src))
          return 0
  
      supports_symlinks = not Utils.unversioned_sys_platform().startswith('win')
  
      src = os.path.normpath(src)
      dst = os.path.normpath(dst)
  
      # get all non ignored paths/files in dir based on ignore path input
      def _get_non_ignored_paths_in_dir_recursively(src, ignore_paths):
          non_ignored_paths = []
          paths = os.listdir(src)
  
          for item in paths:
              ignore = False
              src_path = os.path.join(src, item)
  
              if any(path in src_path for path in ignore_paths):
                  continue
  
              if supports_symlinks and os.path.islink(src_path):
                  non_ignored_paths.append(src_path)
              elif os.path.isdir(src_path):
                  non_ignored_paths.extend(_get_non_ignored_paths_in_dir_recursively(src_path, ignore_paths))
              else:
                  non_ignored_paths.append(src_path)
  
          return non_ignored_paths
  
      # copy everything if pattern_path is none
      paths_to_copy = os.listdir(src)
      copied_files = 0
  
      if pattern_paths is not None:
          filtered_paths = []
          if is_pattern_required is True:
              for path in pattern_paths:
                  filtered_paths.extend(glob.glob(os.path.join(src, path)))
  
          else:
              filtered_paths = _get_non_ignored_paths_in_dir_recursively(src, pattern_paths)
  
          # sanitize the paths in filtered_paths for further consumption (we only want relative path from src)
          for idx, item in enumerate(filtered_paths):
              item = os.path.normpath(item)
              sep = src + os.path.sep
              filtered_paths[idx] = item.replace(sep, "")
  
          paths_to_copy = filtered_paths
  
      symlinks = []
      # now we copy all files specified from the paths in paths_to_copy
      for path in paths_to_copy:
          srcname = os.path.join(src, path)
          dstname = os.path.join(dst, path)
  
          if supports_symlinks and os.path.islink(srcname):
              linkto = os.readlink(srcname)
              symlinks.append([linkto, dstname])
  
          elif os.path.isdir(srcname):
              # if we encounter a srcname that is a folder, we assume that we want the entire folder
              # pattern_paths to None tells this function that we want to copy the entire folder
              copied_files += copy_tree2(srcname, dstname, overwrite_existing_file, None, fail_on_error=fail_on_error)
  
          else:
              # check to see if we should copy the file
              copy = overwrite_existing_file or should_overwrite_file(srcname, dstname)
              if copy is False:
                  continue
              file_copied = 0
  
              Logs.debug('lumberyard: Copying file {} to {}'.format(srcname, dstname))
              try:
                  # In case the file is readonly, we'll remove the existing file first
                  if os.path.exists(dstname):
                      os.chmod(dstname, stat.S_IWRITE)
  
                  # In the case where the path doesn't exist
                  elif os.path.exists(os.path.dirname(dstname)) is False:
                      try:
                          os.makedirs(os.path.dirname(dstname))
                      except:
                          pass
                      if not os.path.exists(dst):
                          raise shutil.Error("Unable to create target folder `{}`".format(dst))
  
                  try:
                      file_copied = fast_copy2(srcname, dstname)
                  except:
                      # Second try with detail hash check
                      file_copied = fast_copy2(srcname, dstname, True)
  
              except Exception as err:
                  if fail_on_error:
                      raise err
                  else:
                      Logs.warn(
                          '[WARN] Unable to copy {} to destination {}.  Check the file permissions or any process that may be locking it.'.format(
                              srcname, dstname))
              copied_files += file_copied
  
      # symlinks will be empty if a platform does not support them so no need to
      # protect against running this code
      for symlink in symlinks:
          if os.path.exists(symlink[1]):
              if os.path.islink(symlink[1]):
                  os.unlink(symlink[1]) 
              elif os.path.isdir(symlink[1]):
                  shutil.rmtree(symlink[1])
              else:
                  os.remove(symlink[1]) 
          try:
              os.symlink(symlink[0], symlink[1])
          except OSError as oops:
              Logs.warn("Unable to create symbolic link {} because {}".format(symlink[1], oops))
              copied_files = False
  
      return copied_files
function_tokens: def copy_tree2 ( src , dst , overwrite_existing_file = False , pattern_paths = None , is_pattern_required = False , fail_on_error = True ) : if os . path . isdir ( src ) is False : Logs . warn ( '[WARN] Unable to copy {} to destination {} using copy_tree2. {} is not a directory.' . format ( src , dst , src ) ) return 0 supports_symlinks = not Utils . unversioned_sys_platform ( ) . startswith ( 'win' ) src = os . path . normpath ( src ) dst = os . path . normpath ( dst ) # get all non ignored paths/files in dir based on ignore path input def _get_non_ignored_paths_in_dir_recursively ( src , ignore_paths ) : non_ignored_paths = [ ] paths = os . listdir ( src ) for item in paths : ignore = False src_path = os . path . join ( src , item ) if any ( path in src_path for path in ignore_paths ) : continue if supports_symlinks and os . path . islink ( src_path ) : non_ignored_paths . append ( src_path ) elif os . path . isdir ( src_path ) : non_ignored_paths . extend ( _get_non_ignored_paths_in_dir_recursively ( src_path , ignore_paths ) ) else : non_ignored_paths . append ( src_path ) return non_ignored_paths # copy everything if pattern_path is none paths_to_copy = os . listdir ( src ) copied_files = 0 if pattern_paths is not None : filtered_paths = [ ] if is_pattern_required is True : for path in pattern_paths : filtered_paths . extend ( glob . glob ( os . path . join ( src , path ) ) ) else : filtered_paths = _get_non_ignored_paths_in_dir_recursively ( src , pattern_paths ) # sanitize the paths in filtered_paths for further consumption (we only want relative path from src) for idx , item in enumerate ( filtered_paths ) : item = os . path . normpath ( item ) sep = src + os . path . sep filtered_paths [ idx ] = item . replace ( sep , "" ) paths_to_copy = filtered_paths symlinks = [ ] # now we copy all files specified from the paths in paths_to_copy for path in paths_to_copy : srcname = os . path . join ( src , path ) dstname = os . path . join ( dst , path ) if supports_symlinks and os . path . islink ( srcname ) : linkto = os . readlink ( srcname ) symlinks . append ( [ linkto , dstname ] ) elif os . path . isdir ( srcname ) : # if we encounter a srcname that is a folder, we assume that we want the entire folder # pattern_paths to None tells this function that we want to copy the entire folder copied_files += copy_tree2 ( srcname , dstname , overwrite_existing_file , None , fail_on_error = fail_on_error ) else : # check to see if we should copy the file copy = overwrite_existing_file or should_overwrite_file ( srcname , dstname ) if copy is False : continue file_copied = 0 Logs . debug ( 'lumberyard: Copying file {} to {}' . format ( srcname , dstname ) ) try : # In case the file is readonly, we'll remove the existing file first if os . path . exists ( dstname ) : os . chmod ( dstname , stat . S_IWRITE ) # In the case where the path doesn't exist elif os . path . exists ( os . path . dirname ( dstname ) ) is False : try : os . makedirs ( os . path . dirname ( dstname ) ) except : pass if not os . path . exists ( dst ) : raise shutil . Error ( "Unable to create target folder `{}`" . format ( dst ) ) try : file_copied = fast_copy2 ( srcname , dstname ) except : # Second try with detail hash check file_copied = fast_copy2 ( srcname , dstname , True ) except Exception as err : if fail_on_error : raise err else : Logs . warn ( '[WARN] Unable to copy {} to destination {}.  Check the file permissions or any process that may be locking it.' . format ( srcname , dstname ) ) copied_files += file_copied # symlinks will be empty if a platform does not support them so no need to # protect against running this code for symlink in symlinks : if os . path . exists ( symlink [ 1 ] ) : if os . path . islink ( symlink [ 1 ] ) : os . unlink ( symlink [ 1 ] ) elif os . path . isdir ( symlink [ 1 ] ) : shutil . rmtree ( symlink [ 1 ] ) else : os . remove ( symlink [ 1 ] ) try : os . symlink ( symlink [ 0 ] , symlink [ 1 ] ) except OSError as oops : Logs . warn ( "Unable to create symbolic link {} because {}" . format ( symlink [ 1 ] , oops ) ) copied_files = False return copied_files