You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
7.8 KiB
Python
207 lines
7.8 KiB
Python
#
|
|
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
# its licensors.
|
|
#
|
|
# For complete copyright and license terms please see the LICENSE at the root of this
|
|
# distribution (the "License"). All use of this software is governed by the License,
|
|
# or, if provided, by the license below or the license accompanying this file. Do not
|
|
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
#
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import shutil
|
|
import uuid
|
|
from urllib.parse import urlparse
|
|
|
|
|
|
download_url_base = "http://gamedev.amazon.com/lumberyard/releases/"
|
|
|
|
|
|
def set_download_url_base(url):
|
|
global download_url_base
|
|
download_url_base = url
|
|
|
|
|
|
def is_url(potential_url):
|
|
return urlparse(potential_url)[0] == 'https'
|
|
|
|
|
|
def get_package_name(package_path):
|
|
path_to_file = package_path
|
|
if is_url(package_path):
|
|
# index 2 is everything that isn't a parameter in the URL after the high level domain
|
|
# see https://docs.python.org/2/library/urlparse.html#urlparse.urlparse for more info
|
|
path_to_file = urlparse(package_path)[2]
|
|
return os.path.basename(path_to_file)
|
|
|
|
|
|
def get_ly_version_from_package(args, unpacked_location):
|
|
version = None
|
|
path_to_default_settings = os.path.join(unpacked_location, 'dev/_WAF_/default_settings.json')
|
|
verbose_print(args.verbose, 'Searching for Lumberyard version in {}'.format(path_to_default_settings))
|
|
with open(path_to_default_settings) as default_settings_file:
|
|
default_settings_data = json.load(default_settings_file)
|
|
default_settings_file.close()
|
|
for build_option in default_settings_data['Build Options']:
|
|
if 'attribute' in build_option and 'default_value' in build_option:
|
|
if build_option['attribute'] == 'version':
|
|
version = build_option['default_value']
|
|
|
|
if version is None:
|
|
verbose_print(args.verbose, 'Version not found in package')
|
|
raise Exception('Version was not available in default settings.json')
|
|
|
|
return version
|
|
|
|
|
|
def append_trailing_slash_to_url(url):
|
|
if not url.endswith(tuple(['/', '\\'])):
|
|
url += '/'
|
|
return url
|
|
|
|
|
|
def generate_target_url(base_target_url, version, build_id, suppress_version_in_path, append_build_id):
|
|
output_url = base_target_url
|
|
if append_build_id:
|
|
output_url = append_trailing_slash_to_url(output_url)
|
|
output_url += build_id
|
|
if not suppress_version_in_path:
|
|
output_url = append_trailing_slash_to_url(output_url)
|
|
output_url += '{}/installer'.format(version)
|
|
return output_url
|
|
|
|
|
|
# PRODUCT & UPGRADE/PATCH GUID CREATION
|
|
def create_id(name, seed, version, build_id):
|
|
"""
|
|
Generate the Product GUID using the name, the version, and a changelist value.
|
|
@param name - Name of the product.
|
|
@param seed - String used to create a unique GUID.
|
|
@param version - The version of the product in the form "PRODUCT.MAJOR.MINOR.PATCH".
|
|
@param build_id - An optional identifier for the build to be used in GUID generation.
|
|
@return - A GUID for this version of the product.
|
|
"""
|
|
# Temporary. Replace the download_url_base with wherever we pass in to the public host or host url.
|
|
uuid_seed = download_url_base + seed + name + version
|
|
if build_id is not None:
|
|
uuid_seed += build_id
|
|
return str(uuid.uuid3(uuid.NAMESPACE_URL, uuid_seed)).upper()
|
|
# END PRODUCT & UPGRADE/PATCH GUID CREATION
|
|
|
|
|
|
def replace_leading_numbers(source_string):
|
|
pattern = re.compile(r'^[0-9]')
|
|
return pattern.sub('N', source_string)
|
|
|
|
|
|
def strip_special_characters(source_string):
|
|
"""
|
|
Remove all non-alphanumeric characters from the given sourceString.
|
|
@return - A new string that is a copy of the original, containing only
|
|
letters and numbers.
|
|
"""
|
|
if source_string.isalnum():
|
|
return source_string
|
|
|
|
pattern = re.compile(r'[\W_]+')
|
|
return pattern.sub('', source_string)
|
|
|
|
|
|
def check_for_empty_subfolders(package_root, allowed_empty_folders):
|
|
# find empty folders
|
|
empty_folders_found = []
|
|
for root, dirs, files in os.walk(package_root):
|
|
if dirs == [] and files == []:
|
|
empty_folders_found.append(os.path.normpath(os.path.relpath(root, package_root)))
|
|
if allowed_empty_folders is not None:
|
|
whitelist_root = 'Whitelist'
|
|
whitelist_folders = []
|
|
assert (os.path.exists(allowed_empty_folders)), 'The whitelist file specified at {} does not exist.'.format(allowed_empty_folders)
|
|
with open(allowed_empty_folders, 'r') as source:
|
|
json_whitelist = json.load(source)
|
|
try:
|
|
for allowed_folder in json_whitelist[whitelist_root]:
|
|
whitelist_folders.append(os.path.normpath(allowed_folder))
|
|
except KeyError:
|
|
print('Unknown json root {}, please check the json root specified.'.format(whitelist_root))
|
|
exit(1)
|
|
assert (len(whitelist_folders) > 0), 'The whitelist in the file specified at {} is empty. Either populate the list or omit the argument.'.format(allowed_empty_folders)
|
|
for folder in empty_folders_found:
|
|
assert (folder in whitelist_folders), 'The empty folder {} could not be found in the whitelist of empty folders.'.format(folder)
|
|
|
|
|
|
def get_immediate_subdirectories(root_dir):
|
|
"""
|
|
Create a list of all directories that exist in the given directory, without
|
|
recursing through the subdirectories' children.
|
|
@param root_dir - The directory to search for subdirectories.
|
|
@return - A list of subdirectories in this directory, excluding their children.
|
|
"""
|
|
directories = []
|
|
for directory in os.listdir(root_dir):
|
|
if os.path.isdir(os.path.join(root_dir, directory)):
|
|
directories.append(directory)
|
|
|
|
return directories
|
|
|
|
|
|
def get_file_names_in_directory(directory, file_extension=None):
|
|
"""
|
|
Create a list of all files in a directory. If given a file extension, it
|
|
will list all files with that extension.
|
|
@param directory - The directory to gather files from.
|
|
@param file_extension - (Optional) The type of files to find. Must be a
|
|
string in the ".extension" format. (Default None)
|
|
@retun - A list of names of all files in this directory (that match the given
|
|
extension if provided).
|
|
"""
|
|
file_list = []
|
|
if file_extension:
|
|
for file in os.listdir(directory):
|
|
if file.endswith(file_extension):
|
|
file_list.append(os.path.basename(file))
|
|
else:
|
|
for file in os.listdir(directory):
|
|
file_list.append(os.path.basename(file))
|
|
|
|
return file_list
|
|
|
|
|
|
# VERBOSE RELATED FUNCTIONS
|
|
|
|
def verbose_print(isVerbose, message):
|
|
if isVerbose:
|
|
print(message)
|
|
|
|
|
|
def find_file_in_package(packageRoot, fileToFind, pathFilters=None):
|
|
"""
|
|
Searchs the package path for a file.
|
|
@param packageRoot: Path to the root of content.
|
|
@param fileToFind: Name of the file to find.
|
|
@param pathFilters: Path filter to apply to find.
|
|
@return: The full path to the file if found, otherwise None.
|
|
"""
|
|
for root, dirs, files in os.walk(packageRoot):
|
|
if fileToFind in files:
|
|
if pathFilters is None or any(pathFilter in root for pathFilter in pathFilters):
|
|
return os.path.join(root, fileToFind)
|
|
return None
|
|
|
|
|
|
def safe_shutil_file_copy(src, dst):
|
|
# need to remove the old version of dst if it already exists due to a bug
|
|
# in shutil.copy that causes both the src and dst files to be zeroed out
|
|
# if they are identical files.
|
|
if os.path.exists(dst):
|
|
os.remove(dst)
|
|
shutil.copy(src, dst)
|
|
|
|
|
|
def create_version_file(buildId, installerPath):
|
|
with open(os.path.join(installerPath, 'version.txt'), 'w') as versionFile:
|
|
versionFile.write(buildId)
|