Merge branch 'TIF/Runtime' into TIF/Jenkins
This commit is contained in:
@@ -11,5 +11,6 @@
|
||||
|
||||
add_subdirectory(detect_file_changes)
|
||||
add_subdirectory(commit_validation)
|
||||
add_subdirectory(o3de)
|
||||
add_subdirectory(project_manager)
|
||||
add_subdirectory(ctest)
|
||||
|
||||
Vendored
+45
-15
@@ -60,7 +60,7 @@ def palRm(path) {
|
||||
} else {
|
||||
def win_path = path.replace('/','\\')
|
||||
bat label: "Removing ${win_path}",
|
||||
script: "del ${win_path}"
|
||||
script: "del /Q ${win_path}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,12 +190,14 @@ def CheckoutBootstrapScripts(String branchName) {
|
||||
doGenerateSubmoduleConfigurations: false,
|
||||
extensions: [
|
||||
[$class: 'PruneStaleBranch'],
|
||||
[$class: 'AuthorInChangelog'],
|
||||
[$class: 'SparseCheckoutPaths', sparseCheckoutPaths: [
|
||||
[ $class: 'SparseCheckoutPath', path: 'scripts/build/Jenkins/' ],
|
||||
[ $class: 'SparseCheckoutPath', path: 'scripts/build/bootstrap/' ],
|
||||
[ $class: 'SparseCheckoutPath', path: 'scripts/build/Platform' ]
|
||||
]],
|
||||
[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true]
|
||||
// Shallow checkouts break changelog computation. Do not enable.
|
||||
[$class: 'CloneOption', noTags: false, reference: '', shallow: false]
|
||||
],
|
||||
submoduleCfg: [],
|
||||
userRemoteConfigs: scm.userRemoteConfigs
|
||||
@@ -234,6 +236,7 @@ def CheckoutRepo(boolean disableSubmodules = false) {
|
||||
branches: scm.branches,
|
||||
extensions: [
|
||||
[$class: 'PruneStaleBranch'],
|
||||
[$class: 'AuthorInChangelog'],
|
||||
[$class: 'SubmoduleOption', disableSubmodules: disableSubmodules, recursiveSubmodules: true],
|
||||
[$class: 'CheckoutOption', timeout: 60]
|
||||
],
|
||||
@@ -339,14 +342,17 @@ def TestMetrics(Map pipelineConfig, String workspace, String branchName, String
|
||||
checkout scm: [
|
||||
$class: 'GitSCM',
|
||||
branches: [[name: '*/main']],
|
||||
extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'mars']],
|
||||
extensions: [
|
||||
[$class: 'AuthorInChangelog'],
|
||||
[$class: 'RelativeTargetDirectory', relativeTargetDir: 'mars']
|
||||
],
|
||||
userRemoteConfigs: [[url: "${env.MARS_REPO}", name: 'mars', credentialsId: "${env.GITHUB_USER}"]]
|
||||
]
|
||||
withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) {
|
||||
def command = "${pipelineConfig.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py " +
|
||||
'-e jenkins.creds.user %username% -e jenkins.creds.pass %apitoken% ' +
|
||||
"-e jenkins.base_url ${env.JENKINS_URL} " +
|
||||
"${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} "
|
||||
"${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} --url ${env.BUILD_URL}"
|
||||
bat label: "Publishing ${buildJobName} Test Metrics",
|
||||
script: command
|
||||
}
|
||||
@@ -354,6 +360,16 @@ def TestMetrics(Map pipelineConfig, String workspace, String branchName, String
|
||||
}
|
||||
}
|
||||
|
||||
def ExportTestResults(Map options, String platform, String type, String workspace, Map params) {
|
||||
catchError(message: "Error exporting tests results (this won't fail the build)", buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||
def o3deroot = "${workspace}/${ENGINE_REPOSITORY_NAME}"
|
||||
dir("${o3deroot}/${params.OUTPUT_DIRECTORY}") {
|
||||
junit testResults: "Testing/**/*.xml"
|
||||
palRmDir("Testing")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def PostBuildCommonSteps(String workspace, boolean mount = true) {
|
||||
echo 'Starting post-build common steps...'
|
||||
|
||||
@@ -396,6 +412,14 @@ def CreateTestMetricsStage(Map pipelineConfig, String branchName, Map environmen
|
||||
}
|
||||
}
|
||||
|
||||
def CreateExportTestResultsStage(Map pipelineConfig, String platformName, String jobName, Map environmentVars, Map params) {
|
||||
return {
|
||||
stage("${jobName}_results") {
|
||||
ExportTestResults(pipelineConfig, platformName, jobName, environmentVars['WORKSPACE'], params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def CreateTeardownStage(Map environmentVars) {
|
||||
return {
|
||||
stage('Teardown') {
|
||||
@@ -511,11 +535,15 @@ try {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (env.MARS_REPO && platform.value.build_types[build_job_name].PARAMETERS.containsKey('TEST_METRICS') && platform.value.build_types[build_job_name].PARAMETERS.TEST_METRICS == 'True') {
|
||||
def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY
|
||||
def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION
|
||||
def params = platform.value.build_types[build_job_name].PARAMETERS
|
||||
if (env.MARS_REPO && params && params.containsKey('TEST_METRICS') && params.TEST_METRICS == 'True') {
|
||||
def output_directory = params.OUTPUT_DIRECTORY
|
||||
def configuration = params.CONFIGURATION
|
||||
CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call()
|
||||
}
|
||||
if (params && params.containsKey('TEST_RESULTS') && params.TEST_RESULTS == 'True') {
|
||||
CreateExportTestResultsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call()
|
||||
}
|
||||
CreateTeardownStage(envVars).call()
|
||||
}
|
||||
}
|
||||
@@ -549,15 +577,17 @@ finally {
|
||||
message:"${currentBuild.currentResult}:${BUILD_URL}:${env.RECREATE_VOLUME}:${env.CLEAN_OUTPUT_DIRECTORY}:${env.CLEAN_ASSETS}"
|
||||
)
|
||||
}
|
||||
step([
|
||||
$class: 'Mailer',
|
||||
notifyEveryUnstableBuild: true,
|
||||
sendToIndividuals: true,
|
||||
recipients: emailextrecipients([
|
||||
[$class: 'CulpritsRecipientProvider'],
|
||||
[$class: 'RequesterRecipientProvider']
|
||||
node('controller') {
|
||||
emailRecipients = [[$class: 'RequesterRecipientProvider']]
|
||||
if (env.WATCHED_BRANCHES.tokenize(',').contains(branchName)) {
|
||||
emailRecipients.add([$class: 'CulpritsRecipientProvider'])
|
||||
}
|
||||
step([
|
||||
$class: 'Mailer',
|
||||
notifyEveryUnstableBuild: true,
|
||||
recipients: emailextrecipients(emailRecipients)
|
||||
])
|
||||
])
|
||||
}
|
||||
} catch(Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
},
|
||||
"debug": {
|
||||
"TAGS":[
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND":"../Windows/build_ninja_windows.cmd",
|
||||
@@ -67,7 +68,8 @@
|
||||
},
|
||||
"profile_nounity": {
|
||||
"TAGS":[
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND":"../Windows/build_ninja_windows.cmd",
|
||||
@@ -83,7 +85,9 @@
|
||||
"asset_profile": {
|
||||
"TAGS":[
|
||||
"default",
|
||||
"weekly-build-metrics"
|
||||
"weekly-build-metrics",
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"COMMAND":"../Windows/build_asset_windows.cmd",
|
||||
"PARAMETERS": {
|
||||
@@ -95,24 +99,13 @@
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"ASSET_PROCESSOR_BINARY": "bin\\profile\\AssetProcessorBatch.exe",
|
||||
"ASSET_PROCESSOR_OPTIONS": "/zeroAnalysisMode --regset=\"/Amazon/AssetProcessor/Settings/Exclude Android/pattern=.*/DiffuseGlobalIllumination/.*precompiledshader\"",
|
||||
"ASSET_PROCESSOR_PLATFORMS":"es3"
|
||||
"ASSET_PROCESSOR_PLATFORMS":"android"
|
||||
}
|
||||
},
|
||||
"asset_clean_profile": {
|
||||
"TAGS":[
|
||||
"nightly"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
"CLEAN_ASSETS": "1"
|
||||
},
|
||||
"steps": [
|
||||
"clean",
|
||||
"asset_profile"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"TAGS":[
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND":"../Windows/build_ninja_windows.cmd",
|
||||
@@ -127,7 +120,8 @@
|
||||
},
|
||||
"monolithic_release": {
|
||||
"TAGS":[
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND":"../Windows/build_ninja_windows.cmd",
|
||||
@@ -142,15 +136,14 @@
|
||||
},
|
||||
"gradle": {
|
||||
"TAGS":[
|
||||
"default",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND":"gradle_windows.cmd",
|
||||
"PARAMETERS": {
|
||||
"CONFIGURATION":"profile",
|
||||
"OUTPUT_DIRECTORY":"build\\android_gradle",
|
||||
"OUTPUT_DIRECTORY":"build\\ad_grd",
|
||||
"GAME_PROJECT": "AutomatedTesting",
|
||||
"ANDROID_NDK_PLATFORM": "21",
|
||||
"ANDROID_SDK_PLATFORM": "29",
|
||||
"SIGN_APK": "false",
|
||||
"GRADLE_BUILD_CMD": "build",
|
||||
"ADDITIONAL_GENERATE_ARGS": ""
|
||||
@@ -164,8 +157,6 @@
|
||||
"CONFIGURATION":"profile",
|
||||
"OUTPUT_DIRECTORY":"build\\android_unittest",
|
||||
"GAME_PROJECT": "AutomatedTesting",
|
||||
"ANDROID_NDK_PLATFORM": "21",
|
||||
"ANDROID_SDK_PLATFORM": "29",
|
||||
"SIGN_APK": "true",
|
||||
"GRADLE_BUILD_CMD": "assemble",
|
||||
"ADDITIONAL_GENERATE_ARGS": "--unit-test"
|
||||
|
||||
@@ -17,20 +17,12 @@ IF NOT EXIST "%LY_3RDPARTY_PATH%" (
|
||||
GOTO :error
|
||||
)
|
||||
|
||||
IF NOT EXIST "%GRADLE_HOME%" (
|
||||
IF NOT EXIST "%GRADLE_BUILD_HOME%" (
|
||||
REM This is the default for developers
|
||||
SET GRADLE_HOME=C:\Gradle\gradle-5.6.4
|
||||
SET GRADLE_BUILD_HOME=C:\Gradle\gradle-7.0
|
||||
)
|
||||
IF NOT EXIST "%GRADLE_HOME%" (
|
||||
ECHO [ci_build] FAIL: GRADLE_HOME=%GRADLE_HOME%
|
||||
GOTO :error
|
||||
)
|
||||
|
||||
IF NOT EXIST "%CMAKE_HOME%" (
|
||||
SET CMAKE_HOME=%LY_3RDPARTY_PATH%/CMake/3.19.1/Windows/
|
||||
)
|
||||
IF NOT EXIST "%CMAKE_HOME%" (
|
||||
ECHO [ci_build] FAIL: CMAKE_HOME=%CMAKE_HOME%
|
||||
IF NOT EXIST "%GRADLE_BUILD_HOME%" (
|
||||
ECHO [ci_build] FAIL: GRADLE_BUILD_HOME=%GRADLE_BUILD_HOME%
|
||||
GOTO :error
|
||||
)
|
||||
|
||||
@@ -50,20 +42,9 @@ ECHO Ninja wasnt in the call path, add the value set by LY_NINJA_PATH
|
||||
SET PATH=%PATH%;%LY_NINJA_PATH%
|
||||
|
||||
:ninja_on_path
|
||||
IF NOT EXIST "%LY_ANDROID_SDK%" (
|
||||
SET LY_ANDROID_SDK=!LY_3RDPARTY_PATH!/android-sdk/platform-29
|
||||
)
|
||||
IF NOT EXIST "%LY_ANDROID_SDK%" (
|
||||
ECHO [ci_build] FAIL: LY_ANDROID_SDK=!LY_ANDROID_SDK!
|
||||
GOTO :error
|
||||
)
|
||||
|
||||
IF NOT EXIST "%LY_ANDROID_NDK%" (
|
||||
set LY_ANDROID_NDK=!LY_3RDPARTY_PATH!/android-ndk/r21d
|
||||
)
|
||||
IF NOT EXIST "%LY_ANDROID_NDK%" (
|
||||
ECHO [ci_build] LY_ANDROID_NDK=!LY_ANDROID_NDK!
|
||||
GOTO :error
|
||||
IF NOT "%ANDROID_GRADLE_PLUGIN%" == "" (
|
||||
set ANDROID_GRADLE_PLUGIN_OPTION=--gradle-plugin-version=%ANDROID_GRADLE_PLUGIN%
|
||||
)
|
||||
|
||||
IF NOT EXIST %OUTPUT_DIRECTORY% (
|
||||
@@ -154,11 +135,11 @@ IF "%GENERATE_SIGNED_APK%"=="true" (
|
||||
ECHO Using keystore file at %CI_ANDROID_KEYSTORE_FILE_ABS%
|
||||
)
|
||||
|
||||
ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %OPTIONAL_TEST_FLAG% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_BUILD_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-sdk-path=%ANDROID_HOME% %ANDROID_GRADLE_PLUGIN_OPTION% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_BUILD_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-sdk-path=%ANDROID_HOME% %ANDROID_GRADLE_PLUGIN_OPTION% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
) ELSE (
|
||||
ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% %GRADLE_OVERRIDE_OPTION% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% %ANDROID_GRADLE_PLUGIN_OPTION% --android-sdk-path=%ANDROID_HOME% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_BUILD_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% %ANDROID_GRADLE_PLUGIN_OPTION% --android-sdk-path=%ANDROID_HOME% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
|
||||
)
|
||||
|
||||
REM Validate the android project generation
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ENV": {
|
||||
"GRADLE_HOME": "C:/Gradle/gradle-5.6.4",
|
||||
"NODE_LABEL": "windows-047e5cdf",
|
||||
"GRADLE_HOME": "C:/Gradle/gradle-7.0",
|
||||
"NODE_LABEL": "windows-b3c8994f1",
|
||||
"LY_3RDPARTY_PATH": "C:/ly/3rdParty",
|
||||
"TIMEOUT": 30,
|
||||
"WORKSPACE": "D:/workspace",
|
||||
@@ -13,6 +13,9 @@
|
||||
},
|
||||
"packaging": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
},
|
||||
"nightly-clean": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,8 @@
|
||||
},
|
||||
"debug": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_linux.sh",
|
||||
@@ -43,9 +44,10 @@
|
||||
},
|
||||
"profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"daily-pipeline-metrics",
|
||||
"weekly-build-metrics"
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"daily-pipeline-metrics",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_linux.sh",
|
||||
"PARAMETERS": {
|
||||
@@ -81,7 +83,7 @@
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "all",
|
||||
"CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest"
|
||||
"CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -LE SUITE_sandbox -L FRAMEWORK_googletest"
|
||||
}
|
||||
},
|
||||
"test_profile_nounity": {
|
||||
@@ -93,12 +95,14 @@
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "all",
|
||||
"CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest"
|
||||
"CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -LE SUITE_sandbox -L FRAMEWORK_googletest"
|
||||
}
|
||||
},
|
||||
"asset_profile": {
|
||||
"TAGS": [
|
||||
"weekly-build-metrics"
|
||||
"weekly-build-metrics",
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"COMMAND": "build_asset_linux.sh",
|
||||
"PARAMETERS": {
|
||||
@@ -126,21 +130,10 @@
|
||||
"ASSET_PROCESSOR_PLATFORMS": "pc,server"
|
||||
}
|
||||
},
|
||||
"asset_clean_profile": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
"CLEAN_ASSETS": "1"
|
||||
},
|
||||
"steps": [
|
||||
"clean",
|
||||
"asset_profile"
|
||||
]
|
||||
},
|
||||
"periodic_test_profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_linux.sh",
|
||||
@@ -150,12 +143,32 @@
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "TEST_SUITE_periodic",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_periodic)\""
|
||||
"CTEST_OPTIONS": "-L (SUITE_periodic)"
|
||||
}
|
||||
},
|
||||
"sandbox_test_profile": {
|
||||
"TAGS": [
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
"ON_FAILURE_MARK": "UNSTABLE"
|
||||
},
|
||||
"COMMAND": "build_test_linux.sh",
|
||||
"PARAMETERS": {
|
||||
"CONFIGURATION": "profile",
|
||||
"OUTPUT_DIRECTORY": "build/linux",
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4 -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "all",
|
||||
"CTEST_OPTIONS": "-L (SUITE_sandbox)"
|
||||
}
|
||||
},
|
||||
"benchmark_test_profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_linux.sh",
|
||||
@@ -165,12 +178,13 @@
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "TEST_SUITE_benchmark",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_benchmark)\""
|
||||
"CTEST_OPTIONS": "-L (SUITE_benchmark)"
|
||||
}
|
||||
},
|
||||
"release": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_linux.sh",
|
||||
@@ -184,7 +198,8 @@
|
||||
},
|
||||
"monolithic_release": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_linux.sh",
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
},
|
||||
"packaging": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
},
|
||||
"nightly-clean": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
},
|
||||
"profile_pipe": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"steps": [
|
||||
"profile",
|
||||
@@ -28,7 +29,8 @@
|
||||
},
|
||||
"debug": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_mac.sh",
|
||||
@@ -56,7 +58,8 @@
|
||||
},
|
||||
"profile_nounity": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_mac.sh",
|
||||
@@ -70,7 +73,9 @@
|
||||
},
|
||||
"asset_profile": {
|
||||
"TAGS": [
|
||||
"weekly-build-metrics"
|
||||
"weekly-build-metrics",
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"COMMAND": "build_asset_mac.sh",
|
||||
"PARAMETERS": {
|
||||
@@ -81,24 +86,13 @@
|
||||
"CMAKE_TARGET": "AssetProcessorBatch",
|
||||
"ASSET_PROCESSOR_BINARY": "bin/profile/AssetProcessorBatch",
|
||||
"ASSET_PROCESSOR_OPTIONS": "/zeroAnalysisMode",
|
||||
"ASSET_PROCESSOR_PLATFORMS": "osx_gl"
|
||||
"ASSET_PROCESSOR_PLATFORMS": "mac"
|
||||
}
|
||||
},
|
||||
"asset_clean_profile": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
"CLEAN_ASSETS": "1"
|
||||
},
|
||||
"steps": [
|
||||
"clean",
|
||||
"asset_profile"
|
||||
]
|
||||
},
|
||||
"periodic_test_profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_mac.sh",
|
||||
@@ -113,7 +107,8 @@
|
||||
},
|
||||
"benchmark_test_profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_mac.sh",
|
||||
@@ -128,7 +123,8 @@
|
||||
},
|
||||
"release": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_mac.sh",
|
||||
@@ -142,7 +138,8 @@
|
||||
},
|
||||
"monolithic_release": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_mac.sh",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ENV": {
|
||||
"NODE_LABEL": "mac",
|
||||
"NODE_LABEL": "mac-catalina-7ad2e45b",
|
||||
"LY_3RDPARTY_PATH": "/Users/lybuilder/3rdParty",
|
||||
"TIMEOUT": 30,
|
||||
"WORKSPACE": "/Users/lybuilder/workspace",
|
||||
@@ -12,6 +12,9 @@
|
||||
},
|
||||
"packaging": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
},
|
||||
"nightly-clean": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@
|
||||
},
|
||||
"debug_vs2019_pipe": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"steps": [
|
||||
"debug_vs2019",
|
||||
@@ -125,7 +126,8 @@
|
||||
"CMAKE_TARGET": "TEST_SUITE_smoke TEST_SUITE_main",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_smoke|SUITE_main)\" -LE \"(REQUIRES_gpu)\" -T Test",
|
||||
"TEST_METRICS": "True"
|
||||
"TEST_METRICS": "True",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
"profile_vs2019": {
|
||||
@@ -145,7 +147,8 @@
|
||||
},
|
||||
"profile_vs2019_nounity": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_windows.cmd",
|
||||
@@ -172,15 +175,17 @@
|
||||
"CMAKE_TARGET": "TEST_SUITE_smoke TEST_SUITE_main",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_smoke|SUITE_main)\" -LE \"(REQUIRES_gpu)\" -T Test",
|
||||
"TEST_METRICS": "True"
|
||||
"TEST_METRICS": "True",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
"test_gpu_profile_vs2019": {
|
||||
"TAGS":[
|
||||
"nightly"
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"PIPELINE_ENV":{
|
||||
"NODE_LABEL":"windows-gpu"
|
||||
"NODE_LABEL":"windows-gpu"
|
||||
},
|
||||
"COMMAND": "build_test_windows.cmd",
|
||||
"PARAMETERS": {
|
||||
@@ -191,12 +196,15 @@
|
||||
"CMAKE_TARGET": "TEST_SUITE_smoke TEST_SUITE_main",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_smoke_REQUIRES_gpu|SUITE_main_REQUIRES_gpu)\" -T Test",
|
||||
"TEST_METRICS": "True"
|
||||
"TEST_METRICS": "True",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
"asset_profile_vs2019": {
|
||||
"TAGS": [
|
||||
"weekly-build-metrics"
|
||||
"weekly-build-metrics",
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"COMMAND": "build_asset_windows.cmd",
|
||||
"PARAMETERS": {
|
||||
@@ -211,21 +219,10 @@
|
||||
"ASSET_PROCESSOR_PLATFORMS": "pc,server"
|
||||
}
|
||||
},
|
||||
"asset_clean_profile_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
"CLEAN_ASSETS": "1"
|
||||
},
|
||||
"steps": [
|
||||
"clean",
|
||||
"asset_profile_vs2019"
|
||||
]
|
||||
},
|
||||
"periodic_test_profile_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_windows.cmd",
|
||||
@@ -237,12 +234,14 @@
|
||||
"CMAKE_TARGET": "TEST_SUITE_periodic",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_periodic)\" -T Test",
|
||||
"TEST_METRICS": "True"
|
||||
"TEST_METRICS": "True",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
"sandbox_test_profile_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
@@ -257,12 +256,14 @@
|
||||
"CMAKE_TARGET": "TEST_SUITE_sandbox",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_sandbox)\" -T Test",
|
||||
"TEST_METRICS": "True"
|
||||
"TEST_METRICS": "True",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
"benchmark_test_profile_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_windows.cmd",
|
||||
@@ -274,12 +275,14 @@
|
||||
"CMAKE_TARGET": "TEST_SUITE_benchmark",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_benchmark)\" -T Test",
|
||||
"TEST_METRICS": "True"
|
||||
"TEST_METRICS": "True",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
"release_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_windows.cmd",
|
||||
@@ -294,7 +297,8 @@
|
||||
},
|
||||
"monolithic_release_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_windows.cmd",
|
||||
@@ -309,13 +313,14 @@
|
||||
},
|
||||
"install_profile_vs2019": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
"nightly-incremental",
|
||||
"nightly-clean"
|
||||
],
|
||||
"COMMAND": "build_windows.cmd",
|
||||
"PARAMETERS": {
|
||||
"CONFIGURATION": "profile",
|
||||
"OUTPUT_DIRECTORY": "build\\windows_vs2019",
|
||||
"CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DCMAKE_INSTALL_PREFIX=install",
|
||||
"CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE",
|
||||
"CMAKE_LY_PROJECTS": "",
|
||||
"CMAKE_TARGET": "INSTALL",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo"
|
||||
@@ -347,7 +352,7 @@
|
||||
"PARAMETERS": {
|
||||
"CONFIGURATION": "profile",
|
||||
"OUTPUT_DIRECTORY": "build\\windows_vs2019",
|
||||
"CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DCMAKE_MODULE_PATH=!WORKSPACE!/o3de/build/windows_vs2019/install/cmake",
|
||||
"CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DCMAKE_MODULE_PATH=!WORKSPACE!/o3de/install/cmake",
|
||||
"CMAKE_LY_PROJECTS": "",
|
||||
"CMAKE_TARGET": "ALL_BUILD",
|
||||
"CMAKE_NATIVE_BUILD_ARGS": "/m /nologo"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ENV": {
|
||||
"NODE_LABEL": "windows-047e5cdf",
|
||||
"NODE_LABEL": "windows-b3c8994f1",
|
||||
"LY_3RDPARTY_PATH": "C:/ly/3rdParty",
|
||||
"TIMEOUT": 30,
|
||||
"WORKSPACE": "D:/workspace",
|
||||
@@ -12,6 +12,9 @@
|
||||
},
|
||||
"packaging": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
},
|
||||
"nightly-clean": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,8 @@
|
||||
},
|
||||
"debug": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "../Mac/build_mac.sh",
|
||||
@@ -34,7 +35,8 @@
|
||||
},
|
||||
"profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"daily-pipeline-metrics",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
@@ -50,7 +52,8 @@
|
||||
},
|
||||
"profile_nounity": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "../Mac/build_mac.sh",
|
||||
@@ -65,14 +68,15 @@
|
||||
},
|
||||
"asset_profile": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "../Mac/build_asset_mac.sh",
|
||||
"PARAMETERS": {
|
||||
"CONFIGURATION": "profile",
|
||||
"OUTPUT_DIRECTORY": "build/mac",
|
||||
"CMAKE_OPTIONS": "-G Xcode -DLY_UNITY_BUILD=TRUE",
|
||||
"CMAKE_OPTIONS": "-G Xcode -DLY_UNITY_BUILD=TRUE -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "AssetProcessorBatch",
|
||||
"ASSET_PROCESSOR_BINARY": "bin/profile/AssetProcessorBatch",
|
||||
@@ -80,21 +84,10 @@
|
||||
"ASSET_PROCESSOR_PLATFORMS": "ios"
|
||||
}
|
||||
},
|
||||
"asset_clean_profile": {
|
||||
"TAGS": [
|
||||
"nightly"
|
||||
],
|
||||
"PIPELINE_ENV": {
|
||||
"CLEAN_ASSETS": "true"
|
||||
},
|
||||
"steps": [
|
||||
"clean",
|
||||
"asset_profile"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"TAGS": [
|
||||
"nightly",
|
||||
"nightly-incremental",
|
||||
"nightly-clean",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "../Mac/build_mac.sh",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ENV": {
|
||||
"NODE_LABEL": "mac",
|
||||
"NODE_LABEL": "mac-catalina-7ad2e45b",
|
||||
"LY_3RDPARTY_PATH": "/Users/lybuilder/3rdParty",
|
||||
"TIMEOUT": 30,
|
||||
"WORKSPACE": "/Users/lybuilder/workspace",
|
||||
@@ -12,6 +12,9 @@
|
||||
},
|
||||
"packaging": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
},
|
||||
"nightly-clean": {
|
||||
"CLEAN_WORKSPACE": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ then
|
||||
./aws/install
|
||||
rm -rf ./aws
|
||||
else
|
||||
AWS_CLI_VERSION=`aws --version | awk '{print $1}' | awk -F/ '{print $2}'`
|
||||
AWS_CLI_VERSION=$(aws --version | awk '{print $1}' | awk -F/ '{print $2}')
|
||||
echo AWS CLI \(version $AWS_CLI_VERSION\) already installed
|
||||
fi
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UBUNTU_DISTRO="`lsb_release -c | awk '{print $2}'`"
|
||||
UBUNTU_DISTRO="$(lsb_release -c | awk '{print $2}')"
|
||||
if [ "$UBUNTU_DISTRO" == "bionic" ]
|
||||
then
|
||||
echo "Setup for Ubuntu 18.04 LTS ($UBUNTU_DISTRO)"
|
||||
@@ -53,7 +53,7 @@ fi
|
||||
# will install it from the bionic distro manually into focal. This is needed since Ubuntu 20.04 supports
|
||||
# python 3.8 out of the box, but we are using 3.7
|
||||
#
|
||||
LIBFFI6_COUNT=`apt list --installed 2>/dev/null | grep libffi6 | wc -l`
|
||||
LIBFFI6_COUNT=$(apt list --installed 2>/dev/null | grep libffi6 | wc -l)
|
||||
if [ "$UBUNTU_DISTRO" == "focal" ] && [ $LIBFFI6_COUNT -eq 0 ]
|
||||
then
|
||||
echo "Installing libffi for Ubuntu 20.04"
|
||||
@@ -90,7 +90,7 @@ fi
|
||||
# Add the kitware repository for cmake if necessary
|
||||
#
|
||||
|
||||
KITWARE_REPO_COUNT=`cat /etc/apt/sources.list | grep ^deb | grep https://apt.kitware.com/ubuntu/ | wc -l`
|
||||
KITWARE_REPO_COUNT=$(cat /etc/apt/sources.list | grep ^deb | grep https://apt.kitware.com/ubuntu/ | wc -l)
|
||||
|
||||
if [ $KITWARE_REPO_COUNT -eq 0 ]
|
||||
then
|
||||
@@ -121,33 +121,34 @@ PACKAGE_FILE_LIST=package-list.ubuntu-$UBUNTU_DISTRO.txt
|
||||
echo Reading package list $PACKAGE_FILE_LIST
|
||||
|
||||
# Read each line (strip out comment tags)
|
||||
for LINE in `cat $PACKAGE_FILE_LIST | sed 's/#.*$//g'`
|
||||
for PREPROC_LINE in $(cat $PACKAGE_FILE_LIST | sed 's/#.*$//g')
|
||||
do
|
||||
PACKAGE=`echo $LINE | awk -F / '{print $1}'`
|
||||
LINE=$(echo $PREPROC_LINE | tr -d '\r\n')
|
||||
PACKAGE=$(echo $LINE | awk -F / '{$1=$1;print $1}')
|
||||
if [ "$PACKAGE" != "" ] # Skip blank lines
|
||||
then
|
||||
PACKAGE_VER=`echo $LINE | awk -F / '{print $2}'`
|
||||
PACKAGE_VER=$(echo $LINE | awk -F / '{$2=$2;print $2}')
|
||||
if [ "$PACKAGE_VER" == "" ]
|
||||
then
|
||||
# Process non-versioned packages
|
||||
INSTALLED_COUNT=`apt list --installed 2>/dev/null | grep ^$PACKAGE/ | wc -l`
|
||||
INSTALLED_COUNT=$(apt list --installed 2>/dev/null | grep ^$PACKAGE/ | wc -l)
|
||||
if [ $INSTALLED_COUNT -eq 0 ]
|
||||
then
|
||||
echo Installing $PACKAGE
|
||||
apt-get install $PACKAGE -y
|
||||
else
|
||||
INSTALLED_VERSION=`apt list --installed 2>/dev/null | grep ^$PACKAGE/ | awk '{print $2}'`
|
||||
INSTALLED_VERSION=$(apt list --installed 2>/dev/null | grep ^$PACKAGE/ | awk '{print $2}')
|
||||
echo $PACKAGE already installed \(version $INSTALLED_VERSION\)
|
||||
fi
|
||||
else
|
||||
# Process versioned packages
|
||||
INSTALLED_COUNT=`apt list --installed 2>/dev/null | grep ^$PACKAGE/ | wc -l`
|
||||
INSTALLED_COUNT=$(apt list --installed 2>/dev/null | grep ^$PACKAGE/ | wc -l)
|
||||
if [ $INSTALLED_COUNT -eq 0 ]
|
||||
then
|
||||
echo Installing $PACKAGE \( $PACKAGE_VER \)
|
||||
apt-get install $PACKAGE=$PACKAGE_VER -y
|
||||
else
|
||||
INSTALLED_VERSION=`apt list --installed 2>/dev/null | grep ^$PACKAGE/ | awk '{print $2}'`
|
||||
INSTALLED_VERSION=$(apt list --installed 2>/dev/null | grep ^$PACKAGE/ | awk '{print $2}')
|
||||
if [ "$INSTALLED_VERSION" != "$PACKAGE_VER" ]
|
||||
then
|
||||
echo $PACKAGE already installed but with the wrong version. Purging the package
|
||||
|
||||
@@ -26,7 +26,7 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UBUNTU_DISTRO="`lsb_release -c | awk '{print $2}'`"
|
||||
UBUNTU_DISTRO="$(lsb_release -c | awk '{print $2}')"
|
||||
if [ "$UBUNTU_DISTRO" == "bionic" ]
|
||||
then
|
||||
echo "Setup for Ubuntu 18.04 LTS ($UBUNTU_DISTRO)"
|
||||
@@ -49,14 +49,14 @@ then
|
||||
apt-get update
|
||||
apt-get install git -y
|
||||
else
|
||||
GIT_VERSION=`git --version | awk '{print $3}'`
|
||||
GIT_VERSION=$(git --version | awk '{print $3}')
|
||||
echo Git $GIT_VERSION already Installed. Skipping Git installation
|
||||
fi
|
||||
|
||||
#
|
||||
# Setup Git-LFS if needed
|
||||
#
|
||||
GIT_LFS_PACKAGE_COUNT=`apt list --installed 2>/dev/null | grep git-lfs/ | wc -l`
|
||||
GIT_LFS_PACKAGE_COUNT=$(apt list --installed 2>/dev/null | grep git-lfs/ | wc -l)
|
||||
if [ $GIT_LFS_PACKAGE_COUNT -eq 0 ]
|
||||
then
|
||||
echo Setting up Git-LFS
|
||||
@@ -87,7 +87,7 @@ then
|
||||
dpkg -i $GCM_PACKAGE_NAME
|
||||
popd
|
||||
else
|
||||
GCM_VERSION=`git-credential-manager-core --version`
|
||||
GCM_VERSION=$(git-credential-manager-core --version)
|
||||
echo Git Credential Manager \(GCM\) version $GCM_VERSION already installed. Skipping GCM installation
|
||||
fi
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
# This script must be run as root
|
||||
if [[ $EUID -ne 0 ]]
|
||||
then
|
||||
echo "This script must be run as root (sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install python3 if necessary
|
||||
python3 --version >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Installing Python3
|
||||
apt-get install python3
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Error installing python3
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
PYTHON_VERSION=$(python3 --version)
|
||||
echo Python3 already installed \($PYTHON_VERSION\)
|
||||
fi
|
||||
|
||||
# Install python3 pip if necessary
|
||||
pip3 --version >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Installing Python3 PIP
|
||||
apt-get install -y python3-pip
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Error installing python3
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
PYTHON_VERSION=$(pip3 --version | awk '{print $2}')
|
||||
echo Python3 Pip already installed \($PYTHON_VERSION\)
|
||||
fi
|
||||
|
||||
|
||||
# Read from the package list and process each package
|
||||
PIP_REQUIREMENTS_FILE=requirements.txt
|
||||
|
||||
pip3 install -r $PIP_REQUIREMENTS_FILE
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Error installing python3
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo Python3 setup complete
|
||||
exit 0
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
# This script must be run as root
|
||||
if [[ $EUID -ne 0 ]]
|
||||
then
|
||||
echo "This script must be run as root (sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo Installing packages and tools for O3DE development
|
||||
|
||||
# Install awscli
|
||||
./install-ubuntu-awscli.sh
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Error installing AWSCLI
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Install git
|
||||
./install-ubuntu-git.sh
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Error installing Git
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install the necessary build tools
|
||||
./install-ubuntu-build-tools.sh
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo Error installing ubuntu tools
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo Packages and tools for O3DE setup complete
|
||||
exit 0
|
||||
@@ -0,0 +1,43 @@
|
||||
boto3==1.16.18 \
|
||||
--hash=sha256:51c419d890ae216b9b031be31f3182739dc3deb5b64351f286bffca2818ddb35 \
|
||||
--hash=sha256:d70d21ea137d786e84124639a62be42f92f4b09472ebfb761156057c92dc5366
|
||||
psutil==5.8.0 \
|
||||
--hash=sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64 \
|
||||
--hash=sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131 \
|
||||
--hash=sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c \
|
||||
--hash=sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6 \
|
||||
--hash=sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023 \
|
||||
--hash=sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df \
|
||||
--hash=sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394 \
|
||||
--hash=sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4 \
|
||||
--hash=sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b \
|
||||
--hash=sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2 \
|
||||
--hash=sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d \
|
||||
--hash=sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65 \
|
||||
--hash=sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d \
|
||||
--hash=sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef \
|
||||
--hash=sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7 \
|
||||
--hash=sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60 \
|
||||
--hash=sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6 \
|
||||
--hash=sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8 \
|
||||
--hash=sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b \
|
||||
--hash=sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d \
|
||||
--hash=sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac \
|
||||
--hash=sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935 \
|
||||
--hash=sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d \
|
||||
--hash=sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28 \
|
||||
--hash=sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876 \
|
||||
--hash=sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0 \
|
||||
--hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \
|
||||
--hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563
|
||||
requests==2.25.1 \
|
||||
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
|
||||
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
|
||||
traceback2==1.4.0 \
|
||||
--hash=sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030 \
|
||||
--hash=sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23
|
||||
urllib3==1.26.4 \
|
||||
--hash=sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df \
|
||||
--hash=sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937
|
||||
tempfile2==0.1.1 \
|
||||
--hash=sha256:77fdd256c16804053d3d588168b79595099ea5e874c3fb171893b0ababd10340
|
||||
@@ -28,8 +28,8 @@ Start-Process -FilePath $sdkmanager -ArgumentList $build_tools -NoNewWindow -Wai
|
||||
Write-Host "Installing Gradle and Ninja"
|
||||
Import-Module C:\ProgramData\chocolatey\helpers\chocolateyInstaller.psm1 #Grade needs a custom installer due to being hardcoded to C:\Programdata in Chocolatey
|
||||
$packageName = 'gradle'
|
||||
$version = '5.6.4'
|
||||
$checksum = 'ABC10BCEDB58806E8654210F96031DB541BCD2D6FC3161E81CB0572D6A15E821'
|
||||
$version = '7.0'
|
||||
$checksum = '81003F83B0056D20EEDF48CDDD4F52A9813163D4BA185BCF8ABD34B8EEEA4CBD'
|
||||
$url = "https://services.gradle.org/distributions/gradle-$version-all.zip"
|
||||
$installDir = "C:\Gradle"
|
||||
|
||||
@@ -38,6 +38,6 @@ Install-ChocolateyZipPackage $packageName $url $installDir -Checksum $checksum -
|
||||
$gradle_home = Join-Path $installDir "$packageName-$version"
|
||||
$gradle_bat = Join-Path $gradle_home 'bin/gradle.bat'
|
||||
|
||||
Install-ChocolateyEnvironmentVariable "GRADLE_HOME" $gradle_home 'Machine'
|
||||
Install-ChocolateyEnvironmentVariable "GRADLE_BUILD_HOME" $gradle_home 'Machine'
|
||||
|
||||
choco install -y ninja --version=1.10.0 --package-parameters="/installDir:C:\Ninja"
|
||||
@@ -53,7 +53,7 @@ def lambda_handler(event, context):
|
||||
backoff = 30
|
||||
status_list = [404] # Retry if the branch doesn't exist yet and provide time for Jenkins to discover it.
|
||||
method_list = ['POST']
|
||||
retry_config = Retry(total=retries, backoff_factor=backoff, status_forcelist=status_list, method_whitelist=method_list)
|
||||
retry_config = Retry(total=retries, backoff_factor=backoff, status_forcelist=status_list, allowed_methods=method_list)
|
||||
|
||||
session = requests.Session()
|
||||
session.mount('https://', HTTPAdapter(max_retries=retry_config))
|
||||
|
||||
@@ -37,25 +37,13 @@
|
||||
"AssetBundler/**": "#include",
|
||||
"AzTestRunner/**": "#include",
|
||||
"CrashHandler/**": "#include",
|
||||
"CryCommonTools/**": "#include",
|
||||
"CrySCompileServer/**": "#include",
|
||||
"CryXML/**": "#include",
|
||||
"DeltaCataloger/**": "#include",
|
||||
"GemRegistry/**": "#include",
|
||||
"GridHub/**": "#include",
|
||||
"HLSLCrossCompiler/**": "#include",
|
||||
"HLSLCrossCompilerMETAL/**": "#include",
|
||||
"LyIdentity/**": "#include",
|
||||
"LyMetrics/**": "#include",
|
||||
"News/**": "#include",
|
||||
"PythonBindingsExample/**": "#include",
|
||||
"RC/**": "#include",
|
||||
"RemoteConsole/**": "#include",
|
||||
"SceneAPI/**": "#include",
|
||||
"SerializeContextTools/**": "#include",
|
||||
"ShaderCacheGen/**": "#include",
|
||||
"SharedQMLResource/**": "#include",
|
||||
"Woodpecker/**": "#include",
|
||||
"CMakeLists.txt": "#include"
|
||||
},
|
||||
"CMakeLists.txt": "#include"
|
||||
@@ -93,7 +81,6 @@
|
||||
"GraphCanvas": "#include",
|
||||
"GraphModel": "#include",
|
||||
"HttpRequestor": "#include",
|
||||
"ImageProcessing": "#include",
|
||||
"ImGui": "#include",
|
||||
"InAppPurchases": "#include",
|
||||
"LandscapeCanvas": "#include",
|
||||
@@ -151,7 +138,6 @@
|
||||
"3dsmax/**": "#include",
|
||||
"7za.exe": "#include",
|
||||
"7za_legal_notice.txt": "#include",
|
||||
"CrySCompileServer/**": "#include",
|
||||
"PakShaders/**": "#include",
|
||||
"Python/**": "#include",
|
||||
"Redistributables": {
|
||||
|
||||
@@ -25,9 +25,6 @@ from glob3 import glob
|
||||
def package(options):
|
||||
package_env = PackageEnv(options.platform, options.type, options.package_env)
|
||||
|
||||
# Override values in bootstrap.cfg for PC package
|
||||
override_bootstrap_cfg(package_env)
|
||||
|
||||
if not package_env.get('SKIP_BUILD'):
|
||||
print(package_env.get('SKIP_BUILD'))
|
||||
print('SKIP_BUILD is False, running CMake build...')
|
||||
@@ -51,34 +48,6 @@ def get_python_path(package_env):
|
||||
return os.path.join(package_env.get('ENGINE_ROOT'), 'python', 'python.sh')
|
||||
|
||||
|
||||
def override_bootstrap_cfg(package_env):
|
||||
print('Override values in bootstrap.cfg')
|
||||
engine_root = package_env.get('ENGINE_ROOT')
|
||||
bootstrap_path = os.path.join(engine_root, 'bootstrap.cfg')
|
||||
replace_values = {'project_path':'{}'.format(package_env.get('BOOTSTRAP_CFG_GAME_FOLDER'))}
|
||||
try:
|
||||
with open(bootstrap_path, 'r') as bootstrap_cfg:
|
||||
content = bootstrap_cfg.read()
|
||||
except:
|
||||
error('Cannot read file {}'.format(bootstrap_path))
|
||||
content = content.split('\n')
|
||||
new_content = []
|
||||
for line in content:
|
||||
if not line.startswith('--'):
|
||||
strs = line.split('=')
|
||||
if len(strs):
|
||||
key = strs[0].strip(' ')
|
||||
if key in replace_values:
|
||||
line = '{}={}'.format(key, replace_values[key])
|
||||
new_content.append(line)
|
||||
try:
|
||||
with open(bootstrap_path, 'w') as out:
|
||||
out.write('\n'.join(new_content))
|
||||
except:
|
||||
error('Cannot write to file {}'.format(bootstrap_path))
|
||||
print('{} updated with value {}'.format(bootstrap_path, replace_values))
|
||||
|
||||
|
||||
def cmake_build(package_env):
|
||||
build_targets = package_env.get('BUILD_TARGETS')
|
||||
for build_target in build_targets:
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
#
|
||||
# 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 os
|
||||
from incremental_build_util import get_iam_role_credentials
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
import pip
|
||||
pip.main(['install', 'requests', '--ignore-installed', '-q'])
|
||||
import requests
|
||||
try:
|
||||
from requests_aws4auth import AWS4Auth
|
||||
except ImportError:
|
||||
import pip
|
||||
pip.main(['install', 'requests_aws4auth', '--ignore-installed', '-q'])
|
||||
from requests_aws4auth import AWS4Auth
|
||||
|
||||
IAM_ROLE_NAME = 'ec2-jenkins-node'
|
||||
TEAM = 'lumberyard-build'
|
||||
CHIME_ROOM_WEB_HOOK = "https://hooks.chime.aws/incomingwebhooks/2a6018c9-3bf5-4e03-851c-32ba82c7c4e2?token=YWhTVXZsWVJ8MXxaLTg5RkVZNlA5Q1NiMVdfQndGeS1TSHNnYW5VREVha3pjX1pUUEd5b1JF"
|
||||
|
||||
|
||||
def find_curr_oncalls_for_team(team):
|
||||
host = "who-is-oncall-pdx.corp.amazon.com"
|
||||
service_name = "who-is-oncall"
|
||||
aws_region = "us-west-2"
|
||||
headers = {"content-type": "application/json", "host": host}
|
||||
|
||||
credentials = get_iam_role_credentials(IAM_ROLE_NAME)
|
||||
try:
|
||||
aws_access_key_id = credentials['AccessKeyId']
|
||||
aws_secret_access_key = credentials['SecretAccessKey']
|
||||
aws_session_token = credentials['Token']
|
||||
except Exception as e:
|
||||
print(f'ERROR: Cannot get AWS credentials.\n{e}')
|
||||
return ['All']
|
||||
|
||||
auth = AWS4Auth(aws_access_key_id, aws_secret_access_key, aws_region, service_name, session_token=aws_session_token)
|
||||
r = requests.get(f"https://who-is-oncall-pdx.corp.amazon.com/teams/{team}", headers=headers, auth=auth, verify=False)
|
||||
if r.ok:
|
||||
res = r.json()
|
||||
try:
|
||||
return res['currOncalls']
|
||||
except KeyError:
|
||||
return ['All']
|
||||
return ['All']
|
||||
|
||||
|
||||
def send_alert_to_chime_room(web_hook, content):
|
||||
data = '{"Content":"' + content + '"}'
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
requests.post(web_hook, headers=headers, data=data)
|
||||
|
||||
|
||||
def create_content():
|
||||
content = ''
|
||||
oncalls = find_curr_oncalls_for_team(TEAM)
|
||||
for oncall in oncalls:
|
||||
content += f'@{oncall} '
|
||||
job_name = os.environ['JOB_NAME']
|
||||
build_url = os.environ['BUILD_URL']
|
||||
content += fr'\nJob {job_name} failed\nBuild URL: {build_url}\n'
|
||||
return content
|
||||
|
||||
|
||||
send_alert_to_chime_room(CHIME_ROOM_WEB_HOOK, create_content())
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""
|
||||
This script will be used in https://jenkins.agscollab.com/view/%7ESandbox/job/PACKAGE_COPY_S3/
|
||||
PACKAGE_COPY_S3 is a downstream job of nightly packaging job, it copies the nightly packages from Infra S3 bucket to Lionbridge S3 bucket based on the INCLUDE_FILTER passed from packaging job
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
import boto3
|
||||
from util import error, warn
|
||||
|
||||
|
||||
# Write EMAIL_TEMPLATE to a file and inject it into the email sent to Lionbridge
|
||||
EMAIL_TEMPLATE = '''Packages are uploaded to S3 bucket {}
|
||||
Package List:
|
||||
{}
|
||||
|
||||
|
||||
Changelists:
|
||||
{}
|
||||
'''
|
||||
|
||||
|
||||
def get_jenkins_env(key):
|
||||
try:
|
||||
return os.environ[key]
|
||||
except KeyError:
|
||||
print('Error: Jenkins parameters {} is not set.'.format(key))
|
||||
return None
|
||||
|
||||
|
||||
JENKINS_USERNAME = get_jenkins_env('JENKINS_USERNAME')
|
||||
JENKINS_API_TOKEN = get_jenkins_env('JENKINS_API_TOKEN')
|
||||
JENKINS_URL = get_jenkins_env('JENKINS_URL')
|
||||
WORKSPACE = get_jenkins_env('WORKSPACE')
|
||||
S3_TARGET = get_jenkins_env('S3_TARGET')
|
||||
INCLUDE_FILTER = get_jenkins_env('INCLUDE_FILTER')
|
||||
EMAIL_TEMPLATE_FILE = get_jenkins_env('EMAIL_TEMPLATE_FILE')
|
||||
if None in [JENKINS_USERNAME, JENKINS_API_TOKEN, JENKINS_URL, WORKSPACE, S3_TARGET, INCLUDE_FILTER, EMAIL_TEMPLATE_FILE]:
|
||||
error('Please make sure all Jenkins parameters are set correctly.')
|
||||
|
||||
|
||||
def parse_include_filter(include_filter):
|
||||
try:
|
||||
res = re.search('^(\w*)-*lumberyard-(\d+)\.(\d+)-(\d+)-(\w+).*\*(\d+)\.\*', include_filter)
|
||||
branch = res.group(1)
|
||||
major_version = int(res.group(2))
|
||||
minor_version = int(res.group(3))
|
||||
changelist_number = res.group(4)
|
||||
platform = res.group(5)
|
||||
build_number = res.group(6)
|
||||
return branch, major_version, minor_version, changelist_number, platform, build_number
|
||||
except (AttributeError, IndexError):
|
||||
error('Unable to parse INCLUDE_FILTER, please make sure the INCLUDE_FILTER is set correctly')
|
||||
|
||||
|
||||
# Get the changelists that trigger the build
|
||||
def get_changelists(job_name, build_number):
|
||||
changelists = []
|
||||
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
|
||||
try:
|
||||
res = requests.get('{}/job/{}/{}/api/json'.format(JENKINS_URL, job_name, build_number),
|
||||
auth=HTTPBasicAuth(JENKINS_USERNAME, JENKINS_API_TOKEN), headers=headers, verify=False)
|
||||
res = json.loads(res.content)
|
||||
changelists = res.get('changeSet').get('items')
|
||||
return changelists
|
||||
except:
|
||||
warn('Error: Failed to get changes from build {} in job {}'.format(build_number, job_name))
|
||||
return []
|
||||
|
||||
|
||||
def get_packaging_job_name(branch, major_version, minor_version, platform):
|
||||
if branch == '':
|
||||
branch = 'ML' if major_version + minor_version == 0 else 'v{}_{}'.format(major_version, minor_version)
|
||||
job_name = 'PKG_{}_{}'.format(branch, platform.capitalize())
|
||||
return job_name
|
||||
|
||||
|
||||
# Get package names by looking up S3 bucket
|
||||
def get_package_names(branch, major_version, minor_version, include_filter, build_number):
|
||||
package_names = []
|
||||
prefix = include_filter[:include_filter.find('*')]
|
||||
pattern = '.*{}.*{}..*'.format(prefix, build_number)
|
||||
if branch == '':
|
||||
bucket_name = 'ly-packages-mainline' if major_version + minor_version == 0 else 'ly-packages-release-candidate'
|
||||
folder = 'lumberyard-packages'
|
||||
else:
|
||||
bucket_name = 'ly-packages-feature-branches'
|
||||
folder = 'lumberyard-packages/{}'.format(branch)
|
||||
s3 = boto3.resource('s3')
|
||||
bucket = s3.Bucket(bucket_name)
|
||||
for obj in bucket.objects.filter(Prefix='{}/{}'.format(folder, prefix)):
|
||||
package_name = obj.key
|
||||
if re.match(pattern, package_name):
|
||||
package_names.append(package_name.replace('{}/'.format(folder), ''))
|
||||
return package_names
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
branch, major_version, minor_version, changelist_number, platform, build_number = parse_include_filter(INCLUDE_FILTER)
|
||||
packaging_job_name = get_packaging_job_name(branch, major_version, minor_version, platform)
|
||||
changelists = get_changelists(packaging_job_name, build_number)
|
||||
package_names = get_package_names(branch, major_version, minor_version, INCLUDE_FILTER, build_number)
|
||||
with open(os.path.join(WORKSPACE, EMAIL_TEMPLATE_FILE), 'w+') as output:
|
||||
if len(package_names) > 0:
|
||||
package_list_str = '\n'.join(package_names)
|
||||
changelists_str = ''
|
||||
for item in changelists:
|
||||
changelists_str += '---------------------------------------------------------------------------------------------\n'
|
||||
try:
|
||||
changelists_str += 'CL{} by {} on {}\n{}\n'.format(item['changeNumber'], item['author']['fullName'], item['changeTime'], item['msg'].encode('utf-8', 'ignore'))
|
||||
except KeyError:
|
||||
error('Internal error, check the output of Jenkins API.')
|
||||
output.write(EMAIL_TEMPLATE.format(S3_TARGET, package_list_str, changelists_str))
|
||||
|
||||
|
||||
@@ -163,11 +163,11 @@ def add_shaders_types():
|
||||
shaders.append(gl4)
|
||||
|
||||
gles3 = _ShaderType('GLES3', 'GLSL_HLSLcc')
|
||||
gles3.add_configuration('Android', 'es3')
|
||||
gles3.add_configuration('Android', 'android')
|
||||
shaders.append(gles3)
|
||||
|
||||
metal = _ShaderType('METAL', 'METAL_LLVM_DXC')
|
||||
metal.add_configuration('Mac', 'osx_gl')
|
||||
metal.add_configuration('Mac', 'mac')
|
||||
metal.add_configuration('iOS', 'ios')
|
||||
shaders.append(metal)
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
*/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/StandardPluginsConfig.h
|
||||
*/Gems/EMotionFX/Code/MCore/Source/Config.h
|
||||
*/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStateLocalUserLobby.inl
|
||||
*/Gems/ImageProcessing/Code/Tests/AtlasBuilderTest.cpp
|
||||
*/Gems/PhysX/Code/Source/System/PhysXSystem.cpp
|
||||
*/Gems/SaveData/Code/Tests/SaveDataTest.cpp
|
||||
*/Gems/WhiteBox/Code/Source/Rendering/Legacy/WhiteBoxLegacyRenderMesh.cpp
|
||||
|
||||
@@ -118,8 +118,10 @@ def _merge_xml_results(xml_results_path, prefix, merged_xml_name, parent_element
|
||||
def _aggregate_attributes(nodes):
|
||||
for node in nodes:
|
||||
for attribute in attributes_to_aggregate:
|
||||
value = node.attrib[attribute.name]
|
||||
temp_dict[attribute.name] += attribute.func(value)
|
||||
if attribute.name in node.attrib:
|
||||
temp_dict[attribute.name] += attribute.func(node.attrib[attribute.name])
|
||||
else:
|
||||
print("Failed to find key {} in {}, continuing...".format(attribute.name, node.tag))
|
||||
|
||||
base_tree = xet.parse(xml_files[0])
|
||||
base_tree_root = base_tree.getroot()
|
||||
|
||||
+5
-3
@@ -12,15 +12,15 @@ REM
|
||||
|
||||
pushd %~dp0%
|
||||
CD %~dp0..
|
||||
SET BASE_PATH=%CD%
|
||||
SET "BASE_PATH=%CD%"
|
||||
CD %~dp0
|
||||
SET PYTHON_DIRECTORY=%BASE_PATH%\python
|
||||
SET "PYTHON_DIRECTORY=%BASE_PATH%\python"
|
||||
IF EXIST "%PYTHON_DIRECTORY%" GOTO pythonPathAvailable
|
||||
GOTO pythonDirNotFound
|
||||
:pythonPathAvailable
|
||||
SET PYTHON_EXECUTABLE=%PYTHON_DIRECTORY%\python.cmd
|
||||
IF NOT EXIST "%PYTHON_EXECUTABLE%" GOTO pythonExeNotFound
|
||||
CALL "%PYTHON_EXECUTABLE%" %BASE_PATH%\scripts\o3de.py %*
|
||||
CALL "%PYTHON_EXECUTABLE%" "%BASE_PATH%\scripts\o3de.py" %*
|
||||
GOTO end
|
||||
:pythonDirNotFound
|
||||
ECHO Python directory not found: %PYTHON_DIRECTORY%
|
||||
@@ -33,4 +33,6 @@ popd
|
||||
EXIT /b 1
|
||||
:end
|
||||
popd
|
||||
EXIT /b %ERRORLEVEL%
|
||||
|
||||
|
||||
|
||||
+44
-15
@@ -10,25 +10,54 @@
|
||||
#
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Resolve the common python module
|
||||
ROOT_DEV_PATH = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
if ROOT_DEV_PATH not in sys.path:
|
||||
sys.path.append(ROOT_DEV_PATH)
|
||||
|
||||
from cmake.Tools import engine_template
|
||||
from cmake.Tools import current_project
|
||||
from cmake.Tools import add_remove_gem
|
||||
from cmake.Tools import registration
|
||||
|
||||
|
||||
def add_args(parser, subparsers) -> None:
|
||||
current_project.add_args(parser, subparsers)
|
||||
engine_template.add_args(parser, subparsers)
|
||||
add_remove_gem.add_args(parser, subparsers)
|
||||
registration.add_args(parser, subparsers)
|
||||
"""
|
||||
add_args is called to add expected parser arguments and subparsers arguments to each command such that it can be
|
||||
invoked by o3de.py
|
||||
Ex o3de.py can invoke the register downloadable commands by importing register,
|
||||
call add_args and execute: python o3de.py register --gem-path "C:/TestGem"
|
||||
:param parser: the caller instantiates a parser and passes it in here
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
|
||||
# As o3de.py shares the same name as the o3de package attempting to use a regular
|
||||
# from o3de import <module> line tries to import from the current o3de.py script and not the package
|
||||
# So the {current script directory} / 'o3de' is added to the front of the sys.path
|
||||
script_dir = pathlib.Path(__file__).parent
|
||||
o3de_package_dir = (script_dir / 'o3de').resolve()
|
||||
# add the scripts/o3de directory to the front of the sys.path
|
||||
sys.path.insert(0, str(o3de_package_dir))
|
||||
from o3de import engine_template, global_project, register, print_registration, get_registration, \
|
||||
enable_gem, disable_gem, sha256
|
||||
# Remove the temporarily added path
|
||||
sys.path = sys.path[1:]
|
||||
|
||||
# global_project
|
||||
global_project.add_args(subparsers)
|
||||
# engine templaate
|
||||
engine_template.add_args(subparsers)
|
||||
|
||||
# register
|
||||
register.add_args(subparsers)
|
||||
|
||||
# show
|
||||
print_registration.add_args(subparsers)
|
||||
|
||||
# get-registered
|
||||
get_registration.add_args(subparsers)
|
||||
|
||||
# add a gem to a project
|
||||
enable_gem.add_args(subparsers)
|
||||
|
||||
# remove a gem from a project
|
||||
disable_gem.add_args(subparsers)
|
||||
|
||||
# sha256
|
||||
sha256.add_args(subparsers)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+5
-6
@@ -15,11 +15,9 @@
|
||||
#Note this does not actually change the working directory
|
||||
SCRIPT_DIR=$(cd `dirname $0` && pwd)
|
||||
|
||||
#The engine root is always the parent of the scripts directory, so $(dirname "$SCRIPT_DIR") should get us engine root
|
||||
ENGINE_ROOT=$(dirname "$SCRIPT_DIR")
|
||||
|
||||
#The engines python is in the engineroot/python
|
||||
PYTHON_DIRECTORY="$ENGINE_ROOT/python"
|
||||
#python should be in the base path
|
||||
BASE_PATH=$(dirname "$SCRIPT_DIR")
|
||||
PYTHON_DIRECTORY="$BASE_PATH/python"
|
||||
|
||||
#If engine python exists use it, if not try the system python
|
||||
if [ ! -d "$PYTHON_DIRECTORY" ]; then
|
||||
@@ -33,4 +31,5 @@ if [ ! -f "$PYTHON_EXECUTABLE" ]; then
|
||||
fi
|
||||
|
||||
#run the o3de.py pass along the command
|
||||
$PYTHON_EXECUTABLE "$SCRIPT_DIR/o3de.py" $*
|
||||
$PYTHON_EXECUTABLE "$SCRIPT_DIR/o3de.py" $*
|
||||
exit $?
|
||||
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
add_subdirectory(tests)
|
||||
@@ -0,0 +1,41 @@
|
||||
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.
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
------------
|
||||
|
||||
o3de is a package of scripts containing functionality to register engine, projects, gems,
|
||||
templates and download repositories with the o3de manifests
|
||||
It also contains functionality for creating new projects, gems and templates as well
|
||||
as querying existing gems and templates
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
------------
|
||||
|
||||
* Python 3.7.10 (64-bit)
|
||||
|
||||
INSTALL
|
||||
-----------
|
||||
It is recommended to set up these these tools with O3DE's CMake build commands.
|
||||
Assuming CMake is already setup on your operating system, below are some sample build commands:
|
||||
cd /path/to/od3e/
|
||||
cmake -B windows_vs2019 -S . -G"Visual Studio 16" -DLY_3RDPARTY_PATH="%LY_3RDPARTY_PATH%"
|
||||
|
||||
To manually install the project in development mode using your own installed Python interpreter:
|
||||
cd /path/to/od3e/o3de
|
||||
/path/to/your/python -m pip install -e .
|
||||
|
||||
|
||||
UNINSTALLATION
|
||||
--------------
|
||||
|
||||
The preferred way to uninstall the project is:
|
||||
/path/to/your/python -m pip uninstall o3de
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
@@ -0,0 +1,193 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
Contains methods for query CMake gem target information
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
from o3de import manifest
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
enable_gem_start_marker = 'set(ENABLED_GEMS'
|
||||
enable_gem_end_marker = ')'
|
||||
|
||||
|
||||
def add_gem_dependency(cmake_file: pathlib.Path,
|
||||
gem_name: str) -> int:
|
||||
"""
|
||||
adds a gem dependency to a cmake file
|
||||
:param cmake_file: path to the cmake file
|
||||
:param gem_name: name of the gem
|
||||
:return: 0 for success or non 0 failure code
|
||||
"""
|
||||
if not cmake_file.is_file():
|
||||
logger.error(f'Failed to locate cmake file {str(cmake_file)}')
|
||||
return 1
|
||||
|
||||
# on a line by basis, see if there already is {gem_name}
|
||||
# find the first occurrence of a gem, copy its formatting and replace
|
||||
# the gem name with the new one and append it
|
||||
# if the gem is already present fail
|
||||
t_data = []
|
||||
added = False
|
||||
line_index_to_append = None
|
||||
with open(cmake_file, 'r') as s:
|
||||
line_index = 0
|
||||
for line in s:
|
||||
if line.strip().startswith(enable_gem_start_marker):
|
||||
line_index_to_append = line_index
|
||||
if f'{gem_name}' == line.strip():
|
||||
logger.warning(f'{gem_name} is already enabled in file {str(cmake_file)}.')
|
||||
return 0
|
||||
t_data.append(line)
|
||||
line_index += 1
|
||||
|
||||
|
||||
indent = 4
|
||||
if line_index_to_append:
|
||||
# Insert the gem after the 'set(ENABLED_GEMS)...` line
|
||||
t_data.insert(line_index_to_append + 1, f'{" " * indent}{gem_name}\n')
|
||||
added = True
|
||||
|
||||
# if we didn't add, then create a new set(ENABLED_GEMS) variable
|
||||
# add a new gem, if empty the correct format is 1 tab=4spaces
|
||||
if not added:
|
||||
t_data.append('\n')
|
||||
t_data.append(f'{enable_gem_start_marker}\n')
|
||||
t_data.append(f'{" " * indent}{gem_name}\n')
|
||||
t_data.append(f'{enable_gem_end_marker}\n')
|
||||
|
||||
# write the cmake
|
||||
with open(cmake_file, 'w') as s:
|
||||
s.writelines(t_data)
|
||||
|
||||
return 0
|
||||
|
||||
def remove_gem_dependency(cmake_file: pathlib.Path,
|
||||
gem_name: str) -> int:
|
||||
"""
|
||||
removes a gem dependency from a cmake file
|
||||
:param cmake_file: path to the cmake file
|
||||
:param gem_name: name of the gem
|
||||
:return: 0 for success or non 0 failure code
|
||||
"""
|
||||
if not cmake_file.is_file():
|
||||
logger.error(f'Failed to locate cmake file {cmake_file}')
|
||||
return 1
|
||||
|
||||
# on a line by basis, remove any line with {gem_name}
|
||||
t_data = []
|
||||
# Remove the gem from the enabled_gem file by skipping the gem name entry
|
||||
removed = False
|
||||
with open(cmake_file, 'r') as s:
|
||||
for line in s:
|
||||
if gem_name == line.strip():
|
||||
removed = True
|
||||
else:
|
||||
t_data.append(line)
|
||||
|
||||
if not removed:
|
||||
logger.error(f'Failed to remove {gem_name} from cmake file {cmake_file}')
|
||||
return 1
|
||||
|
||||
# write the cmake
|
||||
with open(cmake_file, 'w') as s:
|
||||
s.writelines(t_data)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def get_project_gems(project_path: pathlib.Path,
|
||||
platform: str = 'Common') -> set:
|
||||
return get_gems_from_cmake_file(get_enabled_gem_cmake_file(project_path=project_path, platform=platform))
|
||||
|
||||
|
||||
def get_enabled_gems(cmake_file: pathlib.Path) -> set:
|
||||
"""
|
||||
Gets a list of enabled gems from the cmake file
|
||||
:param cmake_file: path to the cmake file
|
||||
:return: set of gem targets found
|
||||
"""
|
||||
cmake_file = pathlib.Path(cmake_file).resolve()
|
||||
|
||||
if not cmake_file.is_file():
|
||||
logger.error(f'Failed to locate cmake file {cmake_file}')
|
||||
return set()
|
||||
|
||||
gem_target_set = set()
|
||||
with cmake_file.open('r') as s:
|
||||
in_gem_list = False
|
||||
for line in s:
|
||||
line = line.strip()
|
||||
if line.startswith(enable_gem_start_marker):
|
||||
# Set the flag to indicate that we are in the ENABLED_GEMS variable
|
||||
in_gem_list = True
|
||||
# Skip pass the 'set(ENABLED_GEMS' marker just in case their are gems declared on the same line
|
||||
line = line[len(enable_gem_start_marker):]
|
||||
if in_gem_list:
|
||||
# Since we are inside the ENABLED_GEMS variable determine if the line has the end_marker of ')'
|
||||
if line.endswith(enable_gem_end_marker):
|
||||
# Strip away the line end marker
|
||||
line = line[:-len(enable_gem_end_marker)]
|
||||
# Set the flag to indicate that we are no longer in the ENABLED_GEMS variable after this line
|
||||
in_gem_list = False
|
||||
# Split the rest of the line on whitespace just in case there are multiple gems in a line
|
||||
gem_name_list = line.split()
|
||||
gem_target_set.update(gem_name_list)
|
||||
|
||||
return gem_target_set
|
||||
|
||||
|
||||
def get_project_gem_paths(project_path: pathlib.Path,
|
||||
platform: str = 'Common') -> set:
|
||||
gem_names = get_project_gems(project_path, platform)
|
||||
gem_paths = set()
|
||||
for gem_name in gem_names:
|
||||
gem_paths.add(manifest.get_registered(gem_name=gem_name))
|
||||
return gem_paths
|
||||
|
||||
|
||||
def get_enabled_gem_cmake_file(project_name: str = None,
|
||||
project_path: str or pathlib.Path = None,
|
||||
platform: str = 'Common') -> pathlib.Path or None:
|
||||
"""
|
||||
get the standard cmake file name for a particular type of dependency
|
||||
:param gem_name: name of the gem, resolves gem_path
|
||||
:param gem_path: path of the gem
|
||||
:return: list of gem targets
|
||||
"""
|
||||
if not project_name and not project_path:
|
||||
logger.error(f'Must supply either a Project Name or Project Path.')
|
||||
return None
|
||||
|
||||
if project_name and not project_path:
|
||||
project_path = manifest.get_registered(project_name=project_name)
|
||||
|
||||
project_path = pathlib.Path(project_path).resolve()
|
||||
enable_gem_filename = "enabled_gems.cmake"
|
||||
|
||||
if platform == 'Common':
|
||||
project_code_dir = project_path / 'Gem/Code'
|
||||
if project_code_dir.is_dir():
|
||||
dependencies_file_path = project_code_dir / enable_gem_filename
|
||||
return dependencies_file_path.resolve()
|
||||
return (project_path / 'Code' / enable_gem_filename).resolve()
|
||||
else:
|
||||
project_code_dir = project_path / 'Gem/Code/Platform' / platform
|
||||
if project_code_dir.is_dir():
|
||||
dependencies_file_path = project_code_dir / enable_gem_filename
|
||||
return dependencies_file_path.resolve()
|
||||
return (project_path / 'Code/Platform' / platform / enable_gem_filename).resolve()
|
||||
@@ -0,0 +1,177 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
Contains methods for removing a gem from a project
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
from o3de import cmake, manifest
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
|
||||
def disable_gem_in_project(gem_name: str = None,
|
||||
gem_path: pathlib.Path = None,
|
||||
project_name: str = None,
|
||||
project_path: pathlib.Path = None,
|
||||
enabled_gem_file: pathlib.Path = None) -> int:
|
||||
"""
|
||||
disable a gem in a projects enabled_gems.cmake file
|
||||
:param gem_name: name of the gem to add
|
||||
:param gem_path: path to the gem to add
|
||||
:param project_name: name of the project to add the gem to
|
||||
:param project_path: path to the project to add the gem to
|
||||
:param enabled_gem_file: File to remove enabled gem from
|
||||
:return: 0 for success or non 0 failure code
|
||||
"""
|
||||
|
||||
# we need either a project name or path
|
||||
if not project_name and not project_path:
|
||||
logger.error(f'Must either specify a Project path or Project Name.')
|
||||
return 1
|
||||
|
||||
# if project name resolve it into a path
|
||||
if project_name and not project_path:
|
||||
project_path = manifest.get_registered(project_name=project_name)
|
||||
if not project_path:
|
||||
logger.error(f'Unable to locate project path from the registered manifest.json files:'
|
||||
f' {str(pathlib.Path("~/.o3de/o3de_manifest.json").expanduser())}, engine.json')
|
||||
return 1
|
||||
|
||||
project_path = pathlib.Path(project_path).resolve()
|
||||
if not project_path.is_dir():
|
||||
logger.error(f'Project path {project_path} is not a folder.')
|
||||
return 1
|
||||
|
||||
# We need either a gem name or path
|
||||
if not gem_name and not gem_path:
|
||||
logger.error(f'Must either specify a Gem path or Gem Name.')
|
||||
return 1
|
||||
|
||||
# if gem name resolve it into a path
|
||||
if gem_name and not gem_path:
|
||||
gem_path = manifest.get_registered(gem_name=gem_name)
|
||||
if not gem_path:
|
||||
logger.error(f'Unable to locate gem path from the registered manifest.json files:'
|
||||
f' {str(pathlib.Path.home() / ".o3de/manifest.json")},'
|
||||
f' {project_path / "project.json"}, engine.json')
|
||||
return 1
|
||||
gem_path = pathlib.Path(gem_path).resolve()
|
||||
# make sure this gem already exists if we're adding. We can always remove a gem.
|
||||
if not gem_path.is_dir():
|
||||
logger.error(f'Gem Path {gem_path} does not exist.')
|
||||
return 1
|
||||
|
||||
|
||||
# Read gem.json from the gem path
|
||||
gem_json_data = manifest.get_gem_json_data(gem_path=gem_path)
|
||||
if not gem_json_data:
|
||||
logger.error(f'Could not read gem.json content under {gem_path}.')
|
||||
return 1
|
||||
|
||||
# when removing we will try to do as much as possible even with failures so ret_val will be the last error code
|
||||
ret_val = 0
|
||||
|
||||
if not enabled_gem_file:
|
||||
enabled_gem_file = cmake.get_enabled_gem_cmake_file(project_path=project_path)
|
||||
|
||||
# make sure this is a project has an enabled gems file
|
||||
if not enabled_gem_file.is_file():
|
||||
logger.error(f'Enabled gem file {enabled_gem_file} is not present.')
|
||||
return 1
|
||||
# remove the gem
|
||||
error_code = cmake.remove_gem_dependency(enabled_gem_file, gem_json_data['gem_name'])
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def _run_disable_gem_in_project(args: argparse) -> int:
|
||||
if args.override_home_folder:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
return disable_gem_in_project(args.gem_name,
|
||||
args.gem_path,
|
||||
args.project_name,
|
||||
args.project_path,
|
||||
args.enabled_gem_file)
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python disable_gem.py --project-path D:/Test --gem-name Atom
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False,
|
||||
help='The path to the project.')
|
||||
group.add_argument('-pn', '--project-name', type=str, required=False,
|
||||
help='The name of the project.')
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False,
|
||||
help='The path to the gem.')
|
||||
group.add_argument('-gn', '--gem-name', type=str, required=False,
|
||||
help='The name of the gem.')
|
||||
parser.add_argument('-egf', '--enabled-gem-file', type=pathlib.Path, required=False,
|
||||
help='The cmake enabled gem file in which gem names are to be removed from.'
|
||||
'If not specified it will assume ')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
|
||||
parser.set_defaults(func=_run_disable_gem_in_project)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py disable-gem-from-cmake --project-path D:/Test --gem-name Atom
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
disable_gem_project_subparser = subparsers.add_parser('disable-gem')
|
||||
add_parser_args(disable_gem_project_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs disable_gem_project.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,240 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
Implements functionality for downloading o3de objecs either locally or from a URI
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
from o3de import manifest, repo, utils, validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
def unzip_manifest_json_data(download_zip_path: pathlib.Path, zip_file_name: str) -> dict:
|
||||
json_data = {}
|
||||
with zipfile.ZipFile(download_zip_path, 'r') as zip_data:
|
||||
with zip_data.open(zip_file_name) as manifest_json_file:
|
||||
try:
|
||||
json_data = json.load(manifest_json_file)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'UnZip exception:{str(e)}')
|
||||
|
||||
return json_data
|
||||
|
||||
def validate_downloaded_zip_sha256(download_uri_json_data: dict, download_zip_path: pathlib.Path,
|
||||
manifest_json_name) -> int:
|
||||
# if the engine.json has a sha256 check it against a sha256 of the zip
|
||||
try:
|
||||
sha256A = download_uri_json_data['sha256']
|
||||
except KeyError as e:
|
||||
logger.warn(f'SECURITY WARNING: The advertised o3de object you downloaded has no "sha256"!!! Be VERY careful!!!'
|
||||
f' We cannot verify this is the actually the advertised object!!!')
|
||||
else:
|
||||
sha256B = hashlib.sha256(download_zip_path.open('rb').read()).hexdigest()
|
||||
if sha256A != sha256B:
|
||||
logger.error(f'SECURITY VIOLATION: Downloaded zip sha256 {sha256B} does not match'
|
||||
f' the advertised "sha256":{sha256A} in the f{manifest_json_name}. Deleting unzipped files!!!')
|
||||
shutil.rmtree(dest_path)
|
||||
return 1
|
||||
|
||||
manifest_json_data = unzip_manifest_json_data(download_zip_path, manifest_json_name)
|
||||
|
||||
# remove the sha256 if present in the advertised downloadable manifest json
|
||||
# then compare it to the json in the zip, they should now be identical
|
||||
try:
|
||||
del download_uri_json_data['sha256']
|
||||
except KeyError as e:
|
||||
pass
|
||||
|
||||
sha256A = hashlib.sha256(json.dumps(download_uri_json_data, indent=4).encode('utf8')).hexdigest()
|
||||
with unzipped_manifest_json.open('r') as s:
|
||||
try:
|
||||
unzipped_manifest_json_data = json.load(s)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'Failed to read manifest json {unzipped_manifest_json}. Unable to confirm this'
|
||||
f' is the same template that was advertised.')
|
||||
return 1
|
||||
sha256B = hashlib.sha256(json.dumps(unzipped_manifest_json_data, indent=4).encode('utf8')).hexdigest()
|
||||
if sha256A != sha256B:
|
||||
logger.error(f'SECURITY VIOLATION: Downloaded manifest json does not match'
|
||||
f' the advertised manifest json. Deleting unzipped files!!!')
|
||||
shutil.rmtree(dest_path)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def get_downloadable(engine_name: str = None,
|
||||
project_name: str = None,
|
||||
gem_name: str = None,
|
||||
template_name: str = None,
|
||||
restricted_name: str = None) -> dict or None:
|
||||
json_data = manifest.load_o3de_manifest()
|
||||
try:
|
||||
o3de_object_uris = json_data['repos']
|
||||
except KeyError as key_err:
|
||||
logger.error(f'Unable to load repos from o3de manifest: {str(key_err)}')
|
||||
return None
|
||||
|
||||
manifest_json = 'repo.json'
|
||||
search_func = lambda: repo.search_repo(manifest_json, engine_name, project_name, gem_name, template_name)
|
||||
return repo.search_o3de_object(manifest_json, o3de_object_uris, search_func)
|
||||
|
||||
|
||||
def download_o3de_object(object_name: str, default_folder_name: str, dest_path: str or pathlib.Path,
|
||||
object_type: str, downloadable_kwarg_key) -> int:
|
||||
if not dest_path:
|
||||
dest_path = manifest.get_registered(default_folder=default_folder_name)
|
||||
if not dest_path:
|
||||
logger.error(f'Destination path not cannot be empty.')
|
||||
return 1
|
||||
|
||||
dest_path = pathlib.Path(dest_path).resolve()
|
||||
dest_path.mkdir(exist_ok=True)
|
||||
|
||||
download_path = manifest.get_o3de_download_folder() / default_folder_name / object_name
|
||||
download_path.mkdir(exist_ok=True)
|
||||
download_zip_path = download_path / f'{object_type}.zip'
|
||||
|
||||
downloadable_object_data = get_downloadable(**{downloadable_kwarg_key : object_name})
|
||||
if not downloadable_object_data:
|
||||
logger.error(f'Downloadable o3de object {object_name} not found.')
|
||||
return 1
|
||||
|
||||
origin = downloadable_json_data['origin']
|
||||
url = f'{origin}/object_type.zip'
|
||||
parsed_uri = urllib.parse.urlparse(url)
|
||||
|
||||
download_zip_result = utils.download_zip_file(parsed_uri, download_zip_path)
|
||||
if download_zip_result != 0:
|
||||
return download_zip_result
|
||||
|
||||
return validate_downloaded_zip_sha256(downloadable_object_data, download_zip_path)
|
||||
|
||||
|
||||
def download_engine(engine_name: str,
|
||||
dest_path: str or pathlib.Path) -> int:
|
||||
return download_o3de_object(engine_name, 'engines', dest_path, 'engine', 'engine_name')
|
||||
|
||||
|
||||
def download_project(project_name: str,
|
||||
dest_path: str or pathlib.Path) -> int:
|
||||
return download_o3de_object(project_name, 'projects', dest_path, 'project', 'project_name')
|
||||
|
||||
|
||||
def download_gem(gem_name: str,
|
||||
dest_path: str or pathlib.Path) -> int:
|
||||
return download_o3de_object(gem_name, 'gems', dest_path, 'gem', 'gem_name')
|
||||
|
||||
|
||||
def download_template(template_name: str,
|
||||
dest_path: str or pathlib.Path) -> int:
|
||||
return download_o3de_object(template_name, 'templates', dest_path, 'template', 'template_name')
|
||||
|
||||
|
||||
|
||||
def download_restricted(restricted_name: str,
|
||||
dest_path: str or pathlib.Path) -> int:
|
||||
return download_o3de_object(restricted_name, 'restricted', dest_path, 'restricted', 'restricted_name')
|
||||
|
||||
|
||||
def _run_download(args: argparse) -> int:
|
||||
if args.override_home_folder:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
if args.engine_name:
|
||||
return download_engine(args.engine_name,
|
||||
args.dest_path)
|
||||
elif args.project_name:
|
||||
return download_project(args.project_name,
|
||||
args.dest_path)
|
||||
elif args.gem_nanme:
|
||||
return download_gem(args.gem_name,
|
||||
args.dest_path)
|
||||
elif args.template_name:
|
||||
return download_template(args.template_name,
|
||||
args.dest_path)
|
||||
|
||||
return 1
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python download.py --engine-name "o3de"
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-e', '--engine-name', type=str, required=False,
|
||||
help='Downloadable engine name.')
|
||||
group.add_argument('-p', '--project-name', type=str, required=False,
|
||||
help='Downloadable project name.')
|
||||
group.add_argument('-g', '--gem-name', type=str, required=False,
|
||||
help='Downloadable gem name.')
|
||||
group.add_argument('-t', '--template-name', type=str, required=False,
|
||||
help='Downloadable template name.')
|
||||
parser.add_argument('-dp', '--dest-path', type=str, required=False,
|
||||
default=None,
|
||||
help='Optional destination folder to download into.'
|
||||
' i.e. download --project-name "AstomSamplerViewer" --dest-path "C:/projects"'
|
||||
' will result in C:/projects/AtomSampleViewer'
|
||||
' If blank will download to default object type folder')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
|
||||
parser.set_defaults(func=_run_download)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py download --engine-name "o3de"
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
download_subparser = subparsers.add_parser('download')
|
||||
add_parser_args(download_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs download.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
# Do not allow running the download.py script as a standalone script until it is reviewed by app-sec
|
||||
@@ -0,0 +1,181 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
Contains command to add a gem to a project's enabled_gem.cmake file
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
from o3de import cmake, manifest, validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
|
||||
def enable_gem_in_project(gem_name: str = None,
|
||||
gem_path: pathlib.Path = None,
|
||||
project_name: str = None,
|
||||
project_path: pathlib.Path = None,
|
||||
enabled_gem_file: pathlib.Path = None) -> int:
|
||||
"""
|
||||
enable a gem in a projects enabled_gems.cmake file
|
||||
:param gem_name: name of the gem to add
|
||||
:param gem_path: path to the gem to add
|
||||
:param project_name: name of to the project to add the gem to
|
||||
:param project_path: path to the project to add the gem to
|
||||
:param enabled_gem_file_file: if this dependency goes/is in a specific file
|
||||
:return: 0 for success or non 0 failure code
|
||||
"""
|
||||
# we need either a project name or path
|
||||
if not project_name and not project_path:
|
||||
logger.error(f'Must either specify a Project path or Project Name.')
|
||||
return 1
|
||||
|
||||
# if project name resolve it into a path
|
||||
if project_name and not project_path:
|
||||
project_path = manifest.get_registered(project_name=project_name)
|
||||
if not project_path:
|
||||
logger.error(f'Unable to locate project path from the registered manifest.json files:'
|
||||
f' {str(pathlib.Path.home() / ".o3de/manifest.json")}, engine.json')
|
||||
return 1
|
||||
|
||||
project_path = pathlib.Path(project_path).resolve()
|
||||
if not project_path.is_dir():
|
||||
logger.error(f'Project path {project_path} is not a folder.')
|
||||
return 1
|
||||
|
||||
# we need either a gem name or path
|
||||
if not gem_name and not gem_path:
|
||||
logger.error(f'Must either specify a Gem path or Gem Name.')
|
||||
return 1
|
||||
|
||||
# if gem name resolve it into a path
|
||||
if gem_name and not gem_path:
|
||||
gem_path = manifest.get_registered(gem_name=gem_name)
|
||||
if not gem_path:
|
||||
logger.error(f'Unable to locate gem path from the registered manifest.json files:'
|
||||
f' {str(pathlib.Path( "~/.o3de/o3de_manifest.json").expanduser())},'
|
||||
f' {project_path / "project.json"}, engine.json')
|
||||
return 1
|
||||
|
||||
gem_path = pathlib.Path(gem_path).resolve()
|
||||
# make sure this gem already exists if we're adding. We can always remove a gem.
|
||||
if not gem_path.is_dir():
|
||||
logger.error(f'Gem Path {gem_path} does not exist.')
|
||||
return 1
|
||||
|
||||
# Read gem.json from the gem path
|
||||
gem_json_data = manifest.get_gem_json_data(gem_path=gem_path)
|
||||
if not gem_json_data:
|
||||
logger.error(f'Could not read gem.json content under {gem_path}.')
|
||||
return 1
|
||||
|
||||
|
||||
ret_val = 0
|
||||
if enabled_gem_file:
|
||||
# make sure this is a project has an enabled gems file
|
||||
if not enabled_gem_file.is_file():
|
||||
logger.error(f'Enabled gem file {enabled_gem_file} is not present.')
|
||||
return 1
|
||||
# add the gem
|
||||
ret_val = cmake.add_gem_dependency(enabled_gem_file, gem_json_data['gem_name'])
|
||||
|
||||
else:
|
||||
# Find the path to enabled gem file.
|
||||
# It will be created if it doesn't exist
|
||||
project_enabled_gem_file = cmake.get_enabled_gem_cmake_file(project_path=project_path)
|
||||
if not project_enabled_gem_file.is_file():
|
||||
project_enabled_gem_file.touch()
|
||||
# add the gem
|
||||
ret_val = cmake.add_gem_dependency(project_enabled_gem_file, gem_json_data['gem_name'])
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def _run_enable_gem_in_project(args: argparse) -> int:
|
||||
if args.override_home_folder:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
return enable_gem_in_project(args.gem_name,
|
||||
args.gem_path,
|
||||
args.project_name,
|
||||
args.project_path,
|
||||
args.enabled_gem_file)
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python enable_gem.py --project-path "D:/TestProject" --gem-path "D:/TestGem"
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False,
|
||||
help='The path to the project.')
|
||||
group.add_argument('-pn', '--project-name', type=str, required=False,
|
||||
help='The name of the project.')
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False,
|
||||
help='The path to the gem.')
|
||||
group.add_argument('-gn', '--gem-name', type=str, required=False,
|
||||
help='The name of the gem.')
|
||||
parser.add_argument('-egf', '--enabled-gem-file', type=pathlib.Path, required=False,
|
||||
help='The cmake enabled_gem file in which the gem names are specified.'
|
||||
'If not specified it will assume enabled_gems.cmake')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
|
||||
parser.set_defaults(func=_run_enable_gem_in_project)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py add-gem-to-project --project-path "D:/TestProject" --gem-path "D:/TestGem"
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
enable_gem_project_subparser = subparsers.add_parser('enable-gem')
|
||||
add_parser_args(enable_gem_project_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs enable_gem.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+2465
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
#
|
||||
# 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 argparse
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
from o3de import manifest
|
||||
|
||||
def _run_get_registered(args: argparse) -> str or pathlib.Path:
|
||||
if args.override_home_folder:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
return manifest.get_registered(args.engine_name,
|
||||
args.project_name,
|
||||
args.gem_name,
|
||||
args.template_name,
|
||||
args.default_folder,
|
||||
args.repo_name,
|
||||
args.restricted_name)
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python get_registration.py --engine-name "o3de"
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-en', '--engine-name', type=str, required=False,
|
||||
help='Engine name.')
|
||||
group.add_argument('-pn', '--project-name', type=str, required=False,
|
||||
help='Project name.')
|
||||
group.add_argument('-gn', '--gem-name', type=str, required=False,
|
||||
help='Gem name.')
|
||||
group.add_argument('-tn', '--template-name', type=str, required=False,
|
||||
help='Template name.')
|
||||
group.add_argument('-df', '--default-folder', type=str, required=False,
|
||||
choices=['engines', 'projects', 'gems', 'templates', 'restricted'],
|
||||
help='The default folders for o3de.')
|
||||
group.add_argument('-rn', '--repo-name', type=str, required=False,
|
||||
help='Repo name.')
|
||||
group.add_argument('-rsn', '--restricted-name', type=str, required=False,
|
||||
help='Restricted name.')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
|
||||
parser.set_defaults(func=_run_get_registered)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py get-registered --engine-name "o3de"
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
get_registered_subparser = subparsers.add_parser('get-registered')
|
||||
add_parser_args(get_registered_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs get_registration.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,214 @@
|
||||
#
|
||||
# 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 argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import pathlib
|
||||
import json
|
||||
|
||||
from o3de import manifest, validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
DEFAULT_BOOTSTRAP_SETREG = pathlib.Path('~/.o3de/Registry/bootstrap.setreg').expanduser()
|
||||
PROJECT_PATH_KEY = ('Amazon', 'AzCore', 'Bootstrap', 'project_path')
|
||||
|
||||
def get_json_data(input_path: pathlib.Path):
|
||||
setreg_json_data = {}
|
||||
# If the output_path exist validate that it is a valid json file
|
||||
if input_path.is_file():
|
||||
with input_path.open('r') as f:
|
||||
try:
|
||||
setreg_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'The file: {input_path} is not a valid json file: {str(e)}')
|
||||
|
||||
return setreg_json_data
|
||||
|
||||
def set_global_project(output_path: pathlib.Path,
|
||||
project_name: str = None,
|
||||
project_path: pathlib.Path = None,
|
||||
force: bool = False) -> int:
|
||||
"""
|
||||
Adds a project path the a settings registry file in the users ~/.o3de/Registry directory
|
||||
:param output_path: path to .setreg file to store project_path value into
|
||||
:param project_name: name of the project to lookup path for
|
||||
:param project_path: path to the project to add to .setreg file
|
||||
:param force: if set, the project path will be set within the .setreg file regardless of if the path doesn't exist
|
||||
:return: 0 for success or non 0 failure code
|
||||
"""
|
||||
# we need either a project name or path
|
||||
if not project_name and not project_path:
|
||||
logger.error(f'Must either specify a Project path or Project Name.')
|
||||
return 1
|
||||
|
||||
# if project name resolve it into a path
|
||||
if project_name and not project_path:
|
||||
project_path = manifest.get_registered(project_name=project_name)
|
||||
|
||||
if not project_path:
|
||||
logger.error(
|
||||
f'The project name has been supplied. Unable to locate project path from the registered manifest.json files:'
|
||||
f' {str(pathlib.Path("~/.o3de/o3de_manifest.json").expanduser())}, engine.json\n'
|
||||
'A The --project-path parameter can be used directly to skip checking the manifest')
|
||||
return 1
|
||||
|
||||
# Only perform project path validations when force=False
|
||||
if not force:
|
||||
if not project_path.is_dir():
|
||||
logger.error(f'Project path {project_path} is not a folder.')
|
||||
return 1
|
||||
|
||||
# Validate that the supplied path points contains a valid project.json
|
||||
if not validation.valid_o3de_project_json(project_path / 'project.json'):
|
||||
logger.error(f'The supplied project path does not contain a valid project.json.\n'
|
||||
f'The Path will not be set')
|
||||
return 1
|
||||
|
||||
# If the output_path exist validate that it is a valid json file and read it's json data
|
||||
setreg_json_data = get_json_data(output_path)
|
||||
if output_path.is_file():
|
||||
with output_path.open('r') as f:
|
||||
try:
|
||||
setreg_json_data = json.load(f)
|
||||
except (json.JSONDecodeError) as e:
|
||||
logger.error(f'The output file: {output_path} is not a valid json file: {str(e)}')
|
||||
return 1
|
||||
|
||||
# Add a json dictionary that will be merged with any existing json data from the .setreg file
|
||||
merge_json_data = {}
|
||||
json_object_iter = merge_json_data
|
||||
for json_key in PROJECT_PATH_KEY[:-1]:
|
||||
# Add the parent json object for the key to update
|
||||
json_object_iter = json_object_iter.setdefault(json_key, {})
|
||||
|
||||
# Set the project path value here
|
||||
json_object_iter[PROJECT_PATH_KEY[-1]] = project_path.as_posix()
|
||||
setreg_json_data.update(merge_json_data)
|
||||
|
||||
# Create the parent directories
|
||||
if output_path.parent:
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
with output_path.open('w') as s:
|
||||
s.write(json.dumps(setreg_json_data, indent=4) + '\n')
|
||||
except OSError as e:
|
||||
logger.error(f'Failed to write project path {project_path} to file {output_path}: {str(e)}')
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def get_global_project(input_path: pathlib.Path) -> pathlib.Path or None:
|
||||
"""
|
||||
Retrieves the /Amazon/AzCore/Bootstrap/project_path key from the supplied file path
|
||||
:return: project_path or None on failure
|
||||
"""
|
||||
setreg_json_data = get_json_data(input_path)
|
||||
|
||||
try:
|
||||
# Iterate over each element of the tuple and read the json key from each successive json object
|
||||
json_object_iter = setreg_json_data
|
||||
for json_key in PROJECT_PATH_KEY:
|
||||
json_object_iter = json_object_iter[json_key]
|
||||
except KeyError as e:
|
||||
logger.error(f'Cannot read key /{"/".join(PROJECT_PATH_KEY)} from file {input_path.as_posix()}: {str(e)}')
|
||||
else:
|
||||
project_path = json_object_iter
|
||||
return pathlib.Path(project_path).resolve()
|
||||
return None
|
||||
|
||||
def _run_get_global_project(args: argparse) -> int:
|
||||
project_path = get_global_project(args.input_path)
|
||||
if project_path:
|
||||
print(project_path.as_posix())
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
def _run_set_global_project(args: argparse) -> int:
|
||||
return set_global_project(args.output_path,
|
||||
args.project_name,
|
||||
args.project_path,
|
||||
args.force)
|
||||
|
||||
|
||||
def add_parser_args(get_project_parser, set_project_parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python global_project.py --project-path "D:/TestProject"
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
|
||||
# get-current-project
|
||||
get_project_parser.add_argument('-i', '--input-path', type=pathlib.Path, required=False, default=DEFAULT_BOOTSTRAP_SETREG,
|
||||
help=f'Optional path to file to read /{"/".join(PROJECT_PATH_KEY)} key from.'
|
||||
f' If not supplied, then {DEFAULT_BOOTSTRAP_SETREG} is used instead')
|
||||
get_project_parser.set_defaults(func=_run_get_global_project)
|
||||
|
||||
# set-current-project
|
||||
group = set_project_parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False,
|
||||
help='The path to the project.')
|
||||
group.add_argument('-pn', '--project-name', type=str, required=False,
|
||||
help='The name of the project.')
|
||||
set_project_parser.add_argument('-o', '--output-path', type=pathlib.Path, required=False,
|
||||
default=DEFAULT_BOOTSTRAP_SETREG,
|
||||
help=f'Optional path to output file to write project_path key to. '
|
||||
f'If not supplied, then {DEFAULT_BOOTSTRAP_SETREG} is used instead')
|
||||
set_project_parser.add_argument('-f', '--force', action='store_true', default=False,
|
||||
help=f'Force the setting of the project path in the supplied setreg file')
|
||||
set_project_parser.set_defaults(func=_run_set_global_project)
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py set-global-project --project-path "D:/TestProject"
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
get_project_subparser = subparsers.add_parser('get-global-project')
|
||||
set_project_subparser = subparsers.add_parser('set-global-project')
|
||||
add_parser_args(get_project_subparser, set_project_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs this script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
project_subparsers = the_parser.add_subparsers(help="Commands for modifying the project path in the user's home"
|
||||
" setreg files")
|
||||
|
||||
# add args to the parser
|
||||
add_args(project_subparsers)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,675 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
Contains functions for data from json files such as the o3de_manifests.json, engine.json, project.json, etc...
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
from o3de import validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
# Directory methods
|
||||
override_home_folder = None
|
||||
|
||||
|
||||
def get_this_engine_path() -> pathlib.Path:
|
||||
return pathlib.Path(os.path.realpath(__file__)).parents[3].resolve()
|
||||
|
||||
|
||||
def get_home_folder() -> pathlib.Path:
|
||||
if override_home_folder:
|
||||
return pathlib.Path(override_home_folder).resolve()
|
||||
else:
|
||||
return pathlib.Path(os.path.expanduser("~")).resolve()
|
||||
|
||||
|
||||
def get_o3de_folder() -> pathlib.Path:
|
||||
o3de_folder = get_home_folder() / '.o3de'
|
||||
o3de_folder.mkdir(parents=True, exist_ok=True)
|
||||
return o3de_folder
|
||||
|
||||
|
||||
def get_o3de_registry_folder() -> pathlib.Path:
|
||||
registry_folder = get_o3de_folder() / 'Registry'
|
||||
registry_folder.mkdir(parents=True, exist_ok=True)
|
||||
return registry_folder
|
||||
|
||||
|
||||
def get_o3de_cache_folder() -> pathlib.Path:
|
||||
cache_folder = get_o3de_folder() / 'Cache'
|
||||
cache_folder.mkdir(parents=True, exist_ok=True)
|
||||
return cache_folder
|
||||
|
||||
|
||||
def get_o3de_download_folder() -> pathlib.Path:
|
||||
download_folder = get_o3de_folder() / 'Download'
|
||||
download_folder.mkdir(parents=True, exist_ok=True)
|
||||
return download_folder
|
||||
|
||||
|
||||
def get_o3de_engines_folder() -> pathlib.Path:
|
||||
engines_folder = get_o3de_folder() / 'Engines'
|
||||
engines_folder.mkdir(parents=True, exist_ok=True)
|
||||
return engines_folder
|
||||
|
||||
|
||||
def get_o3de_projects_folder() -> pathlib.Path:
|
||||
projects_folder = get_o3de_folder() / 'Projects'
|
||||
projects_folder.mkdir(parents=True, exist_ok=True)
|
||||
return projects_folder
|
||||
|
||||
|
||||
def get_o3de_gems_folder() -> pathlib.Path:
|
||||
gems_folder = get_o3de_folder() / 'Gems'
|
||||
gems_folder.mkdir(parents=True, exist_ok=True)
|
||||
return gems_folder
|
||||
|
||||
|
||||
def get_o3de_templates_folder() -> pathlib.Path:
|
||||
templates_folder = get_o3de_folder() / 'Templates'
|
||||
templates_folder.mkdir(parents=True, exist_ok=True)
|
||||
return templates_folder
|
||||
|
||||
|
||||
def get_o3de_restricted_folder() -> pathlib.Path:
|
||||
restricted_folder = get_o3de_folder() / 'Restricted'
|
||||
restricted_folder.mkdir(parents=True, exist_ok=True)
|
||||
return restricted_folder
|
||||
|
||||
|
||||
def get_o3de_logs_folder() -> pathlib.Path:
|
||||
logs_folder = get_o3de_folder() / 'Logs'
|
||||
logs_folder.mkdir(parents=True, exist_ok=True)
|
||||
return logs_folder
|
||||
|
||||
|
||||
# o3de manifest file methods
|
||||
def get_o3de_manifest() -> pathlib.Path:
|
||||
manifest_path = get_o3de_folder() / 'o3de_manifest.json'
|
||||
if not manifest_path.is_file():
|
||||
username = os.path.split(get_home_folder())[-1]
|
||||
|
||||
o3de_folder = get_o3de_folder()
|
||||
default_registry_folder = get_o3de_registry_folder()
|
||||
default_cache_folder = get_o3de_cache_folder()
|
||||
default_downloads_folder = get_o3de_download_folder()
|
||||
default_logs_folder = get_o3de_logs_folder()
|
||||
default_engines_folder = get_o3de_engines_folder()
|
||||
default_projects_folder = get_o3de_projects_folder()
|
||||
default_gems_folder = get_o3de_gems_folder()
|
||||
default_templates_folder = get_o3de_templates_folder()
|
||||
default_restricted_folder = get_o3de_restricted_folder()
|
||||
|
||||
default_projects_restricted_folder = default_projects_folder / 'Restricted'
|
||||
default_projects_restricted_folder.mkdir(parents=True, exist_ok=True)
|
||||
default_gems_restricted_folder = default_gems_folder / 'Restricted'
|
||||
default_gems_restricted_folder.mkdir(parents=True, exist_ok=True)
|
||||
default_templates_restricted_folder = default_templates_folder / 'Restricted'
|
||||
default_templates_restricted_folder.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
json_data = {}
|
||||
json_data.update({'o3de_manifest_name': f'{username}'})
|
||||
json_data.update({'origin': o3de_folder.as_posix()})
|
||||
json_data.update({'default_engines_folder': default_engines_folder.as_posix()})
|
||||
json_data.update({'default_projects_folder': default_projects_folder.as_posix()})
|
||||
json_data.update({'default_gems_folder': default_gems_folder.as_posix()})
|
||||
json_data.update({'default_templates_folder': default_templates_folder.as_posix()})
|
||||
json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()})
|
||||
|
||||
json_data.update({'projects': []})
|
||||
json_data.update({'external_subdirectories': []})
|
||||
json_data.update({'templates': []})
|
||||
json_data.update({'restricted': []})
|
||||
json_data.update({'repos': []})
|
||||
json_data.update({'engines': []})
|
||||
|
||||
default_restricted_folder_json = default_restricted_folder / 'restricted.json'
|
||||
if not default_restricted_folder_json.is_file():
|
||||
with default_restricted_folder_json.open('w') as s:
|
||||
restricted_json_data = {}
|
||||
restricted_json_data.update({'restricted_name': 'o3de'})
|
||||
s.write(json.dumps(restricted_json_data, indent=4) + '\n')
|
||||
json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()})
|
||||
|
||||
default_projects_restricted_folder_json = default_projects_restricted_folder / 'restricted.json'
|
||||
if not default_projects_restricted_folder_json.is_file():
|
||||
with default_projects_restricted_folder_json.open('w') as s:
|
||||
restricted_json_data = {}
|
||||
restricted_json_data.update({'restricted_name': 'projects'})
|
||||
s.write(json.dumps(restricted_json_data, indent=4) + '\n')
|
||||
|
||||
default_gems_restricted_folder_json = default_gems_restricted_folder / 'restricted.json'
|
||||
if not default_gems_restricted_folder_json.is_file():
|
||||
with default_gems_restricted_folder_json.open('w') as s:
|
||||
restricted_json_data = {}
|
||||
restricted_json_data.update({'restricted_name': 'gems'})
|
||||
s.write(json.dumps(restricted_json_data, indent=4) + '\n')
|
||||
|
||||
default_templates_restricted_folder_json = default_templates_restricted_folder / 'restricted.json'
|
||||
if not default_templates_restricted_folder_json.is_file():
|
||||
with default_templates_restricted_folder_json.open('w') as s:
|
||||
restricted_json_data = {}
|
||||
restricted_json_data.update({'restricted_name': 'templates'})
|
||||
s.write(json.dumps(restricted_json_data, indent=4) + '\n')
|
||||
|
||||
with manifest_path.open('w') as s:
|
||||
s.write(json.dumps(json_data, indent=4) + '\n')
|
||||
|
||||
return manifest_path
|
||||
|
||||
|
||||
def load_o3de_manifest(manifest_path: pathlib.Path = None) -> dict:
|
||||
"""
|
||||
Loads supplied manifest file or ~/.o3de/o3de_manifest.json if None
|
||||
|
||||
:param manifest_path: optional path to manifest file to load
|
||||
"""
|
||||
if not manifest_path:
|
||||
manifest_path = get_o3de_manifest()
|
||||
with manifest_path.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'Manifest json failed to load: {str(e)}')
|
||||
return {}
|
||||
else:
|
||||
return json_data
|
||||
|
||||
|
||||
def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> None:
|
||||
"""
|
||||
Save the json dictionary to the supplied manifest file or ~/.o3de/o3de_manifest.json if None
|
||||
|
||||
:param json_data: dictionary to save in json format at the file path
|
||||
:param manifest_path: optional path to manifest file to save
|
||||
"""
|
||||
if not manifest_path:
|
||||
manifest_path = get_o3de_manifest()
|
||||
with manifest_path.open('w') as s:
|
||||
try:
|
||||
s.write(json.dumps(json_data, indent=4) + '\n')
|
||||
except OSError as e:
|
||||
logger.error(f'Manifest json failed to save: {str(e)}')
|
||||
|
||||
|
||||
# Data query methods
|
||||
def get_this_engine() -> dict:
|
||||
json_data = load_o3de_manifest()
|
||||
engine_data = find_engine_data(json_data)
|
||||
return engine_data
|
||||
|
||||
|
||||
def get_engines() -> list:
|
||||
json_data = load_o3de_manifest()
|
||||
return json_data['engines'] if 'engines' in json_data else []
|
||||
|
||||
|
||||
def get_projects() -> list:
|
||||
json_data = load_o3de_manifest()
|
||||
return json_data['projects'] if 'projects' in json_data else []
|
||||
|
||||
|
||||
def get_gems() -> list:
|
||||
def is_gem_subdirectory(subdir):
|
||||
return (pathlib.Path(subdir) / 'gem.json').exists()
|
||||
|
||||
external_subdirs = get_external_subdirectories()
|
||||
return list(filter(is_gem_subdirectory, external_subdirs)) if external_subdirs else []
|
||||
|
||||
|
||||
def get_external_subdirectories() -> list:
|
||||
json_data = load_o3de_manifest()
|
||||
return json_data['external_subdirectories'] if 'external_subdirectories' in json_data else []
|
||||
|
||||
|
||||
def get_templates() -> list:
|
||||
json_data = load_o3de_manifest()
|
||||
return json_data['templates'] if 'templates' in json_data else []
|
||||
|
||||
|
||||
def get_restricted() -> list:
|
||||
json_data = load_o3de_manifest()
|
||||
return json_data['restricted'] if 'restricted' in json_data else []
|
||||
|
||||
|
||||
def get_repos() -> list:
|
||||
json_data = load_o3de_manifest()
|
||||
return json_data['repos'] if 'repos' in json_data else []
|
||||
|
||||
# engine.json queries
|
||||
def get_engine_projects() -> list:
|
||||
engine_path = get_this_engine_path()
|
||||
engine_object = get_engine_json_data(engine_path=engine_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(engine_path) / rel_path).as_posix(),
|
||||
engine_object['projects'])) if 'projects' in engine_object else []
|
||||
|
||||
|
||||
def get_engine_gems() -> list:
|
||||
def is_gem_subdirectory(subdir):
|
||||
return (pathlib.Path(subdir) / 'gem.json').exists()
|
||||
|
||||
external_subdirs = get_engine_external_subdirectories()
|
||||
return list(filter(is_gem_subdirectory, external_subdirs)) if external_subdirs else []
|
||||
|
||||
|
||||
def get_engine_external_subdirectories() -> list:
|
||||
engine_path = get_this_engine_path()
|
||||
engine_object = get_engine_json_data(engine_path=engine_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(engine_path) / rel_path).as_posix(),
|
||||
engine_object['external_subdirectories'])) if 'external_subdirectories' in engine_object else []
|
||||
|
||||
|
||||
def get_engine_templates() -> list:
|
||||
engine_path = get_this_engine_path()
|
||||
engine_object = get_engine_json_data(engine_path=engine_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(engine_path) / rel_path).as_posix(),
|
||||
engine_object['templates']))
|
||||
|
||||
|
||||
def get_engine_restricted() -> list:
|
||||
engine_path = get_this_engine_path()
|
||||
engine_object = get_engine_json_data(engine_path=engine_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(engine_path) / rel_path).as_posix(),
|
||||
engine_object['restricted'])) if 'restricted' in engine_object else []
|
||||
|
||||
|
||||
# project.json queries
|
||||
def get_project_gems(project_path: pathlib.Path) -> list:
|
||||
def is_gem_subdirectory(subdir):
|
||||
return (pathlib.Path(subdir) / 'gem.json').exists()
|
||||
|
||||
external_subdirs = get_project_external_subdirectories(project_path)
|
||||
return list(filter(is_gem_subdirectory, external_subdirs)) if external_subdirs else []
|
||||
|
||||
|
||||
def get_project_external_subdirectories(project_path: pathlib.Path) -> list:
|
||||
project_object = get_project_json_data(project_path=project_path)
|
||||
return list(map(lambda rel_path: (pathlib.Path(project_path) / rel_path).as_posix(),
|
||||
project_object['external_subdirectories'])) if 'external_subdirectories' in project_object else []
|
||||
|
||||
|
||||
# Combined manifest queries
|
||||
def get_all_projects() -> list:
|
||||
projects_data = set(get_projects())
|
||||
projects_data.update(get_engine_projects())
|
||||
return list(projects_data)
|
||||
|
||||
|
||||
def get_all_gems(project_path: pathlib.Path = None) -> list:
|
||||
gems_data = set(get_gems())
|
||||
gems_data.update(get_engine_gems())
|
||||
if project_path:
|
||||
gems_data.update(get_project_gems(project_path))
|
||||
return list(gems_data)
|
||||
|
||||
|
||||
def get_all_external_subdirectories(project_path: pathlib.Path = None) -> list:
|
||||
external_subdirectories_data = set(get_external_subdirectories())
|
||||
external_subdirectories_data.update(get_engine_external_subdirectories())
|
||||
if project_path:
|
||||
external_subdirectories_data.update(get_project_external_subdirectories(project_path))
|
||||
return list(templates_data)
|
||||
|
||||
|
||||
def get_all_templates() -> list:
|
||||
templates_data = set(get_templates())
|
||||
templates_data.update(get_engine_templates())
|
||||
return list(templates_data)
|
||||
|
||||
|
||||
def get_all_restricted() -> list:
|
||||
restricted_data = set(get_restricted())
|
||||
restricted_data.update(get_engine_restricted())
|
||||
return list(gems_data)
|
||||
|
||||
|
||||
# Template functions
|
||||
def get_project_templates(): # temporary until we have a better way to do this... maybe template_type element
|
||||
project_templates = []
|
||||
for template in get_all_templates():
|
||||
if 'Project' in template:
|
||||
project_templates.append(template)
|
||||
return project_templates
|
||||
|
||||
|
||||
def get_gem_templates(): # temporary until we have a better way to do this... maybe template_type element
|
||||
gem_templates = []
|
||||
for template in get_all_templates():
|
||||
if 'Gem' in template:
|
||||
gem_templates.append(template)
|
||||
return gem_templates
|
||||
|
||||
|
||||
def get_generic_templates(): # temporary until we have a better way to do this... maybe template_type element
|
||||
generic_templates = []
|
||||
for template in get_all_templates():
|
||||
if 'Project' not in template and 'Gem' not in template:
|
||||
generic_templates.append(template)
|
||||
return generic_templates
|
||||
|
||||
|
||||
def get_all_restricted() -> list:
|
||||
engine_restricted = get_engine_restricted()
|
||||
restricted_data = get_restricted()
|
||||
restricted_data.extend(engine_restricted)
|
||||
return restricted_data
|
||||
|
||||
|
||||
def find_engine_data(json_data: dict,
|
||||
engine_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not engine_path:
|
||||
engine_path = get_this_engine_path()
|
||||
engine_path = pathlib.Path(engine_path).resolve()
|
||||
|
||||
for engine_object in json_data['engines']:
|
||||
engine_object_path = pathlib.Path(engine_object['path']).resolve()
|
||||
if engine_path == engine_object_path:
|
||||
return engine_object
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_engine_json_data(engine_name: str = None,
|
||||
engine_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not engine_name and not engine_path:
|
||||
logger.error('Must specify either a Engine name or Engine Path.')
|
||||
return None
|
||||
|
||||
if engine_name and not engine_path:
|
||||
engine_path = get_registered(engine_name=engine_name)
|
||||
|
||||
if not engine_path:
|
||||
logger.error(f'Engine Path {engine_path} has not been registered.')
|
||||
return None
|
||||
|
||||
engine_path = pathlib.Path(engine_path).resolve()
|
||||
engine_json = engine_path / 'engine.json'
|
||||
if not engine_json.is_file():
|
||||
logger.error(f'Engine json {engine_json} is not present.')
|
||||
return None
|
||||
if not validation.valid_o3de_engine_json(engine_json):
|
||||
logger.error(f'Engine json {engine_json} is not valid.')
|
||||
return None
|
||||
|
||||
with engine_json.open('r') as f:
|
||||
try:
|
||||
engine_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{engine_json} failed to load: {str(e)}')
|
||||
else:
|
||||
return engine_json_data
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_project_json_data(project_name: str = None,
|
||||
project_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not project_name and not project_path:
|
||||
logger.error('Must specify either a Project name or Project Path.')
|
||||
return None
|
||||
|
||||
if project_name and not project_path:
|
||||
project_path = get_registered(project_name=project_name)
|
||||
|
||||
if not project_path:
|
||||
logger.error(f'Project Path {project_path} has not been registered.')
|
||||
return None
|
||||
|
||||
project_path = pathlib.Path(project_path).resolve()
|
||||
project_json = project_path / 'project.json'
|
||||
if not project_json.is_file():
|
||||
logger.error(f'Project json {project_json} is not present.')
|
||||
return None
|
||||
if not validation.valid_o3de_project_json(project_json):
|
||||
logger.error(f'Project json {project_json} is not valid.')
|
||||
return None
|
||||
|
||||
with project_json.open('r') as f:
|
||||
try:
|
||||
project_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{project_json} failed to load: {str(e)}')
|
||||
else:
|
||||
return project_json_data
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_gem_json_data(gem_name: str = None,
|
||||
gem_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not gem_name and not gem_path:
|
||||
logger.error('Must specify either a Gem name or Gem Path.')
|
||||
return None
|
||||
|
||||
if gem_name and not gem_path:
|
||||
gem_path = get_registered(gem_name=gem_name)
|
||||
|
||||
if not gem_path:
|
||||
logger.error(f'Gem Path {gem_path} has not been registered.')
|
||||
return None
|
||||
|
||||
gem_path = pathlib.Path(gem_path).resolve()
|
||||
gem_json = gem_path / 'gem.json'
|
||||
if not gem_json.is_file():
|
||||
logger.error(f'Gem json {gem_json} is not present.')
|
||||
return None
|
||||
if not validation.valid_o3de_gem_json(gem_json):
|
||||
logger.error(f'Gem json {gem_json} is not valid.')
|
||||
return None
|
||||
|
||||
with gem_json.open('r') as f:
|
||||
try:
|
||||
gem_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{gem_json} failed to load: {str(e)}')
|
||||
else:
|
||||
return gem_json_data
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_template_json_data(template_name: str = None,
|
||||
template_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not template_name and not template_path:
|
||||
logger.error('Must specify either a Template name or Template Path.')
|
||||
return None
|
||||
|
||||
if template_name and not template_path:
|
||||
template_path = get_registered(template_name=template_name)
|
||||
|
||||
if not template_path:
|
||||
logger.error(f'Template Path {template_path} has not been registered.')
|
||||
return None
|
||||
|
||||
template_path = pathlib.Path(template_path).resolve()
|
||||
template_json = template_path / 'template.json'
|
||||
if not template_json.is_file():
|
||||
logger.error(f'Template json {template_json} is not present.')
|
||||
return None
|
||||
if not validation.valid_o3de_template_json(template_json):
|
||||
logger.error(f'Template json {template_json} is not valid.')
|
||||
return None
|
||||
|
||||
with template_json.open('r') as f:
|
||||
try:
|
||||
template_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{template_json} failed to load: {str(e)}')
|
||||
else:
|
||||
return template_json_data
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_restricted_data(restricted_name: str = None,
|
||||
restricted_path: str or pathlib.Path = None) -> dict or None:
|
||||
if not restricted_name and not restricted_path:
|
||||
logger.error('Must specify either a Restricted name or Restricted Path.')
|
||||
return None
|
||||
|
||||
if restricted_name and not restricted_path:
|
||||
restricted_path = get_registered(restricted_name=restricted_name)
|
||||
|
||||
if not restricted_path:
|
||||
logger.error(f'Restricted Path {restricted_path} has not been registered.')
|
||||
return None
|
||||
|
||||
restricted_path = pathlib.Path(restricted_path).resolve()
|
||||
restricted_json = restricted_path / 'restricted.json'
|
||||
if not restricted_json.is_file():
|
||||
logger.error(f'Restricted json {restricted_json} is not present.')
|
||||
return None
|
||||
if not validation.valid_o3de_restricted_json(restricted_json):
|
||||
logger.error(f'Restricted json {restricted_json} is not valid.')
|
||||
return None
|
||||
|
||||
with restricted_json.open('r') as f:
|
||||
try:
|
||||
restricted_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{restricted_json} failed to load: {str(e)}')
|
||||
else:
|
||||
return restricted_json_data
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_registered(engine_name: str = None,
|
||||
project_name: str = None,
|
||||
gem_name: str = None,
|
||||
template_name: str = None,
|
||||
default_folder: str = None,
|
||||
repo_name: str = None,
|
||||
restricted_name: str = None) -> pathlib.Path or None:
|
||||
json_data = load_o3de_manifest()
|
||||
|
||||
# check global first then this engine
|
||||
if isinstance(engine_name, str):
|
||||
for engine in json_data['engines']:
|
||||
engine_path = pathlib.Path(engine['path']).resolve()
|
||||
engine_json = engine_path / 'engine.json'
|
||||
with engine_json.open('r') as f:
|
||||
try:
|
||||
engine_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{engine_json} failed to load: {str(e)}')
|
||||
else:
|
||||
this_engines_name = engine_json_data['engine_name']
|
||||
if this_engines_name == engine_name:
|
||||
return engine_path
|
||||
|
||||
elif isinstance(project_name, str):
|
||||
enging_projects = get_engine_projects()
|
||||
projects = json_data['projects'].copy()
|
||||
projects.extend(engine_object['projects'])
|
||||
for project_path in projects:
|
||||
project_path = pathlib.Path(project_path).resolve()
|
||||
project_json = project_path / 'project.json'
|
||||
with project_json.open('r') as f:
|
||||
try:
|
||||
project_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{project_json} failed to load: {str(e)}')
|
||||
else:
|
||||
this_projects_name = project_json_data['project_name']
|
||||
if this_projects_name == project_name:
|
||||
return project_path
|
||||
|
||||
elif isinstance(gem_name, str):
|
||||
gems = get_all_gems()
|
||||
for gem_path in gems:
|
||||
gem_path = pathlib.Path(gem_path).resolve()
|
||||
gem_json = gem_path / 'gem.json'
|
||||
with gem_json.open('r') as f:
|
||||
try:
|
||||
gem_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{gem_json} failed to load: {str(e)}')
|
||||
else:
|
||||
this_gems_name = gem_json_data['gem_name']
|
||||
if this_gems_name == gem_name:
|
||||
return gem_path
|
||||
|
||||
elif isinstance(template_name, str):
|
||||
engine_templates = get_engine_templates()
|
||||
templates = json_data['templates'].copy()
|
||||
templates.extend(engine_templates)
|
||||
for template_path in templates:
|
||||
template_path = pathlib.Path(template_path).resolve()
|
||||
template_json = template_path / 'template.json'
|
||||
with template_json.open('r') as f:
|
||||
try:
|
||||
template_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{template_path} failed to load: {str(e)}')
|
||||
else:
|
||||
this_templates_name = template_json_data['template_name']
|
||||
if this_templates_name == template_name:
|
||||
return template_path
|
||||
|
||||
elif isinstance(restricted_name, str):
|
||||
engine_restricted = get_engine_restricted()
|
||||
restricted = json_data['restricted'].copy()
|
||||
restricted.extend(engine_restricted)
|
||||
for restricted_path in restricted:
|
||||
restricted_path = pathlib.Path(restricted_path).resolve()
|
||||
restricted_json = restricted_path / 'restricted.json'
|
||||
with restricted_json.open('r') as f:
|
||||
try:
|
||||
restricted_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{restricted_json} failed to load: {str(e)}')
|
||||
else:
|
||||
this_restricted_name = restricted_json_data['restricted_name']
|
||||
if this_restricted_name == restricted_name:
|
||||
return restricted_path
|
||||
|
||||
elif isinstance(default_folder, str):
|
||||
if default_folder == 'engines':
|
||||
default_engines_folder = pathlib.Path(json_data['default_engines_folder']).resolve()
|
||||
return default_engines_folder
|
||||
elif default_folder == 'projects':
|
||||
default_projects_folder = pathlib.Path(json_data['default_projects_folder']).resolve()
|
||||
return default_projects_folder
|
||||
elif default_folder == 'gems':
|
||||
default_gems_folder = pathlib.Path(json_data['default_gems_folder']).resolve()
|
||||
return default_gems_folder
|
||||
elif default_folder == 'templates':
|
||||
default_templates_folder = pathlib.Path(json_data['default_templates_folder']).resolve()
|
||||
return default_templates_folder
|
||||
elif default_folder == 'restricted':
|
||||
default_restricted_folder = pathlib.Path(json_data['default_restricted_folder']).resolve()
|
||||
return default_restricted_folder
|
||||
|
||||
elif isinstance(repo_name, str):
|
||||
cache_folder = get_o3de_cache_folder()
|
||||
for repo_uri in json_data['repos']:
|
||||
repo_uri = pathlib.Path(repo_uri).resolve()
|
||||
repo_sha256 = hashlib.sha256(repo_uri.encode())
|
||||
cache_file = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
if cache_file.is_file():
|
||||
repo = pathlib.Path(cache_file).resolve()
|
||||
with repo.open('r') as f:
|
||||
try:
|
||||
repo_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{cache_file} failed to load: {str(e)}')
|
||||
else:
|
||||
this_repos_name = repo_json_data['repo_name']
|
||||
if this_repos_name == repo_name:
|
||||
return repo_uri
|
||||
return None
|
||||
@@ -0,0 +1,490 @@
|
||||
#
|
||||
# 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 argparse
|
||||
import json
|
||||
import hashlib
|
||||
import logging
|
||||
import sys
|
||||
import urllib.parse
|
||||
|
||||
from o3de import manifest, validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
def print_this_engine(verbose: int) -> None:
|
||||
engine_data = manifest.get_this_engine()
|
||||
print(json.dumps(engine_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_engines_data(engine_data)
|
||||
|
||||
|
||||
def print_engines(verbose: int) -> None:
|
||||
engines_data = manifest.get_engines()
|
||||
print(json.dumps(engines_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_engines_data(engines_data)
|
||||
|
||||
|
||||
def print_projects(verbose: int) -> None:
|
||||
projects_data = manifest.get_projects()
|
||||
print(json.dumps(projects_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_projects_data(projects_data)
|
||||
|
||||
|
||||
def print_gems(verbose: int) -> None:
|
||||
gems_data = manifest.get_gems()
|
||||
print(json.dumps(gems_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_gems_data(gems_data)
|
||||
|
||||
|
||||
def print_templates(verbose: int) -> None:
|
||||
templates_data = manifest.get_templates()
|
||||
print(json.dumps(templates_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_templates_data(templates_data)
|
||||
|
||||
|
||||
def print_restricted(verbose: int) -> None:
|
||||
restricted_data = manifest.get_restricted()
|
||||
print(json.dumps(restricted_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_restricted_data(restricted_data)
|
||||
|
||||
def print_engine_projects(verbose: int) -> None:
|
||||
engine_projects_data = manifest.get_engine_projects()
|
||||
print(json.dumps(engine_projects_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_projects_data(engine_projects_data)
|
||||
|
||||
|
||||
def print_engine_gems(verbose: int) -> None:
|
||||
engine_gems_data = manifest.get_engine_gems()
|
||||
print(json.dumps(engine_gems_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_gems_data(engine_gems_data)
|
||||
|
||||
|
||||
def print_engine_templates(verbose: int) -> None:
|
||||
engine_templates_data = manifest.get_engine_templates()
|
||||
print(json.dumps(engine_templates_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_templates_data(engine_templates_data)
|
||||
|
||||
|
||||
def print_engine_restricted(verbose: int) -> None:
|
||||
engine_restricted_data = manifest.get_engine_restricted()
|
||||
print(json.dumps(engine_restricted_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_restricted_data(engine_restricted_data)
|
||||
|
||||
|
||||
def print_engine_external_subdirectories(verbose: int) -> None:
|
||||
external_subdirs_data = manifest.get_engine_external_subdirectories()
|
||||
print(json.dumps(external_subdirs_data, indent=4))
|
||||
|
||||
|
||||
def print_all_projects(verbose: int) -> None:
|
||||
all_projects_data = manifest.get_all_projects()
|
||||
print(json.dumps(all_projects_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_projects_data(all_projects_data)
|
||||
|
||||
|
||||
def print_all_gems(verbose: int) -> None:
|
||||
all_gems_data = manifest.get_all_gems()
|
||||
print(json.dumps(all_gems_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_gems_data(all_gems_data)
|
||||
|
||||
|
||||
def print_all_templates(verbose: int) -> None:
|
||||
all_templates_data = manifest.get_all_templates()
|
||||
print(json.dumps(all_templates_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_templates_data(all_templates_data)
|
||||
|
||||
|
||||
def print_all_restricted(verbose: int) -> None:
|
||||
all_restricted_data = manifest.get_all_restricted()
|
||||
print(json.dumps(all_restricted_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_restricted_data(all_restricted_data)
|
||||
|
||||
|
||||
def print_engines_data(engines_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Engines================================================")
|
||||
for engine_object in engines_data:
|
||||
# if it's not local it should be in the cache
|
||||
engine_uri = engine_object['path']
|
||||
parsed_uri = urllib.parse.urlparse(engine_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(engine_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
engine = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
print(f'{engine_uri}/engine.json cached as:')
|
||||
else:
|
||||
engine_json = pathlib.Path(engine_uri).resolve() / 'engine.json'
|
||||
|
||||
with engine_json.open('r') as f:
|
||||
try:
|
||||
engine_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{engine_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(engine_json)
|
||||
print(json.dumps(engine_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_projects_data(projects_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Projects================================================")
|
||||
for project_uri in projects_data:
|
||||
# if it's not local it should be in the cache
|
||||
parsed_uri = urllib.parse.urlparse(project_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(project_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
project_json = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
project_json = pathlib.Path(project_uri).resolve() / 'project.json'
|
||||
|
||||
with project_json.open('r') as f:
|
||||
try:
|
||||
project_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{project_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(project_json)
|
||||
print(json.dumps(project_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_gems_data(gems_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Gems================================================")
|
||||
for gem_uri in gems_data:
|
||||
# if it's not local it should be in the cache
|
||||
parsed_uri = urllib.parse.urlparse(gem_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(gem_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
gem_json = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
gem_json = pathlib.Path(gem_uri).resolve() / 'gem.json'
|
||||
|
||||
with gem_json.open('r') as f:
|
||||
try:
|
||||
gem_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{gem_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(gem_json)
|
||||
print(json.dumps(gem_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_templates_data(templates_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Templates================================================")
|
||||
for template_uri in templates_data:
|
||||
# if it's not local it should be in the cache
|
||||
parsed_uri = urllib.parse.urlparse(template_uri)
|
||||
if parsed_uri.scheme == 'http' or \
|
||||
parsed_uri.scheme == 'https' or \
|
||||
parsed_uri.scheme == 'ftp' or \
|
||||
parsed_uri.scheme == 'ftps':
|
||||
repo_sha256 = hashlib.sha256(template_uri.encode())
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
template_json = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
else:
|
||||
template_json = pathlib.Path(template_uri).resolve() / 'template.json'
|
||||
|
||||
with template_json.open('r') as f:
|
||||
try:
|
||||
template_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{template_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(template_json)
|
||||
print(json.dumps(template_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_repos_data(repos_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Repos================================================")
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
for repo_uri in repos_data:
|
||||
repo_sha256 = hashlib.sha256(repo_uri.encode())
|
||||
cache_file = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
if validation.valid_o3de_repo_json(cache_file):
|
||||
with cache_file.open('r') as s:
|
||||
try:
|
||||
repo_json_data = json.load(s)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{cache_file} failed to load: {str(e)}')
|
||||
else:
|
||||
print(f'{repo_uri}/repo.json cached as:')
|
||||
print(cache_file)
|
||||
print(json.dumps(repo_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def print_restricted_data(restricted_data: dict) -> None:
|
||||
print('\n')
|
||||
print("Restricted================================================")
|
||||
for restricted_path in restricted_data:
|
||||
restricted_json = pathlib.Path(restricted_path).resolve() / 'restricted.json'
|
||||
with restricted_json.open('r') as f:
|
||||
try:
|
||||
restricted_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{restricted_json} failed to load: {str(e)}')
|
||||
else:
|
||||
print(restricted_json)
|
||||
print(json.dumps(restricted_json_data, indent=4))
|
||||
print('\n')
|
||||
|
||||
|
||||
def register_show_repos(verbose: int) -> None:
|
||||
repos_data = get_repos()
|
||||
print(json.dumps(repos_data, indent=4))
|
||||
if verbose > 0:
|
||||
print_repos_data(repos_data)
|
||||
|
||||
|
||||
def register_show(verbose: int) -> None:
|
||||
json_data = manifest.load_o3de_manifest()
|
||||
print(f"{manifest.get_o3de_manifest()}:")
|
||||
print(json.dumps(json_data, indent=4))
|
||||
|
||||
if verbose > 0:
|
||||
print_engines_data(manifest.get_engines())
|
||||
print_projects_data(manifest.get_all_projects())
|
||||
print_gems_data(manifest.get_gems())
|
||||
print_templates_data(manifest.get_all_templates())
|
||||
print_restricted_data(manifest.get_all_restricted())
|
||||
print_repos_data(manifest.get_repos())
|
||||
|
||||
|
||||
def _run_register_show(args: argparse) -> int:
|
||||
if args.override_home_folder:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
if args.this_engine:
|
||||
print_this_engine(args.verbose)
|
||||
return 0
|
||||
|
||||
elif args.engines:
|
||||
print_engines(args.verbose)
|
||||
return 0
|
||||
elif args.projects:
|
||||
print_projects(args.verbose)
|
||||
return 0
|
||||
elif args.gems:
|
||||
print_gems(args.verbose)
|
||||
return 0
|
||||
elif args.templates:
|
||||
print_templates(args.verbose)
|
||||
return 0
|
||||
elif args.repos:
|
||||
register_show_repos(args.verbose)
|
||||
return 0
|
||||
elif args.restricted:
|
||||
print_restricted(args.verbose)
|
||||
return 0
|
||||
|
||||
elif args.engine_projects:
|
||||
print_engine_projects(args.verbose)
|
||||
return 0
|
||||
elif args.engine_gems:
|
||||
print_engine_gems(args.verbose)
|
||||
return 0
|
||||
elif args.engine_templates:
|
||||
print_engine_templates(args.verbose)
|
||||
return 0
|
||||
elif args.engine_restricted:
|
||||
print_engine_restricted(args.verbose)
|
||||
return 0
|
||||
elif args.engine_external_subdirectories:
|
||||
print_engine_external_subdirectories(args.verbose)
|
||||
return 0
|
||||
|
||||
elif args.all_projects:
|
||||
print_all_projects(args.verbose)
|
||||
return 0
|
||||
elif args.all_gems:
|
||||
print_all_gems(args.verbose)
|
||||
return 0
|
||||
elif args.all_templates:
|
||||
print_all_templates(args.verbose)
|
||||
return 0
|
||||
elif args.all_restricted:
|
||||
print_all_restricted(args.verbose)
|
||||
return 0
|
||||
|
||||
elif args.downloadables:
|
||||
print_downloadables(args.verbose)
|
||||
return 0
|
||||
if args.downloadable_engines:
|
||||
print_downloadable_engines(args.verbose)
|
||||
return 0
|
||||
elif args.downloadable_projects:
|
||||
print_downloadable_projects(args.verbose)
|
||||
return 0
|
||||
elif args.downloadable_gems:
|
||||
print_downloadable_gems(args.verbose)
|
||||
return 0
|
||||
elif args.downloadable_templates:
|
||||
print_downloadable_templates(args.verbose)
|
||||
return 0
|
||||
else:
|
||||
register_show(args.verbose)
|
||||
return 0
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python print_registration.py --engine-projects
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
group = parser.add_mutually_exclusive_group(required=False)
|
||||
group.add_argument('-te', '--this-engine', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local engines.')
|
||||
|
||||
group.add_argument('-e', '--engines', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local engines.')
|
||||
group.add_argument('-p', '--projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local projects.')
|
||||
group.add_argument('-g', '--gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local gems.')
|
||||
group.add_argument('-t', '--templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local templates.')
|
||||
group.add_argument('-r', '--repos', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local repos. Ignores repos.')
|
||||
group.add_argument('-rs', '--restricted', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The local restricted folders.')
|
||||
|
||||
group.add_argument('-ep', '--engine-projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local projects. Ignores repos.')
|
||||
group.add_argument('-eg', '--engine-gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local gems. Ignores repos')
|
||||
group.add_argument('-et', '--engine-templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local templates. Ignores repos.')
|
||||
group.add_argument('-ers', '--engine-restricted', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The restricted folders.')
|
||||
group.add_argument('-x', '--engine-external-subdirectories', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The external subdirectories.')
|
||||
|
||||
group.add_argument('-ap', '--all-projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local projects. Ignores repos.')
|
||||
group.add_argument('-ag', '--all-gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local gems. Ignores repos')
|
||||
group.add_argument('-at', '--all-templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Just the local templates. Ignores repos.')
|
||||
group.add_argument('-ars', '--all-restricted', action='store_true', required=False,
|
||||
default=False,
|
||||
help='The restricted folders.')
|
||||
|
||||
group.add_argument('-d', '--downloadables', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos into a single list of resources.')
|
||||
group.add_argument('-de', '--downloadable-engines', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos engines into a single list of resources.')
|
||||
group.add_argument('-dp', '--downloadable-projects', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos projects into a single list of resources.')
|
||||
group.add_argument('-dg', '--downloadable-gems', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos gems into a single list of resources.')
|
||||
group.add_argument('-dt', '--downloadable-templates', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Combine all repos templates into a single list of resources.')
|
||||
|
||||
parser.add_argument('-v', '--verbose', action='count', required=False,
|
||||
default=0,
|
||||
help='How verbose do you want the output to be.')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
|
||||
parser.set_defaults(func=_run_register_show)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py register-show --engine-projects
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
register_show_subparser = subparsers.add_parser('register-show')
|
||||
add_parser_args(register_show_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs print_registration.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,864 @@
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
This file contains all the code that has to do with registering engines, projects, gems and templates
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import logging
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
from o3de import get_registration, manifest, repo, utils, validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
|
||||
def register_shipped_engine_o3de_objects(force: bool = False) -> int:
|
||||
engine_path = manifest.get_this_engine_path()
|
||||
|
||||
ret_val = 0
|
||||
|
||||
# register anything in the users default folders globally
|
||||
error_code = register_all_engines_in_folder(manifest.get_registered(default_folder='engines'), force=force)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_projects_in_folder(manifest.get_registered(default_folder='projects'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_gems_in_folder(manifest.get_registered(default_folder='gems'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_templates_in_folder(manifest.get_registered(default_folder='templates'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_restricted_in_folder(manifest.get_registered(default_folder='restricted'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_restricted_in_folder(manifest.get_registered(default_folder='projects'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_restricted_in_folder(manifest.get_registered(default_folder='gems'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
error_code = register_all_restricted_in_folder(manifest.get_registered(default_folder='templates'))
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def register_all_in_folder(folder_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None,
|
||||
exclude: list = None) -> int:
|
||||
if not folder_path:
|
||||
logger.error(f'Folder path cannot be empty.')
|
||||
return 1
|
||||
|
||||
folder_path = pathlib.Path(folder_path).resolve()
|
||||
if not folder_path.is_dir():
|
||||
logger.error(f'Folder path is not dir.')
|
||||
return 1
|
||||
|
||||
engines_set = set()
|
||||
projects_set = set()
|
||||
gems_set = set()
|
||||
templates_set = set()
|
||||
restricted_set = set()
|
||||
repo_set = set()
|
||||
|
||||
ret_val = 0
|
||||
for root, dirs, files in os.walk(folder_path):
|
||||
if root in exclude:
|
||||
continue
|
||||
|
||||
for name in files:
|
||||
if name == 'engine.json':
|
||||
engines_set.add(root)
|
||||
elif name == 'project.json':
|
||||
projects_set.add(root)
|
||||
elif name == 'gem.json':
|
||||
gems_set.add(root)
|
||||
elif name == 'template.json':
|
||||
templates_set.add(root)
|
||||
elif name == 'restricted.json':
|
||||
restricted_set.add(root)
|
||||
elif name == 'repo.json':
|
||||
repo_set.add(root)
|
||||
|
||||
for engine in sorted(engines_set, reverse=True):
|
||||
error_code = register(engine_path=engine, remove=remove)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
for project in sorted(projects_set, reverse=True):
|
||||
error_code = register(engine_path=engine_path, project_path=project, remove=remove)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
for gem in sorted(gems_set, reverse=True):
|
||||
error_code = register(engine_path=engine_path, gem_path=gem, remove=remove)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
for template in sorted(templates_set, reverse=True):
|
||||
error_code = register(engine_path=engine_path, template_path=template, remove=remove)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
for restricted in sorted(restricted_set, reverse=True):
|
||||
error_code = register(engine_path=engine_path, restricted_path=restricted, remove=remove)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
for repo in sorted(repo_set, reverse=True):
|
||||
error_code = register(engine_path=engine_path, repo_uri=repo, remove=remove)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib.Path,
|
||||
o3de_object_type: str,
|
||||
remove: bool,
|
||||
force: bool,
|
||||
**register_kwargs) -> int:
|
||||
if not o3de_object_path:
|
||||
logger.error(f'Engines path cannot be empty.')
|
||||
return 1
|
||||
|
||||
o3de_object_path = pathlib.Path(o3de_object_path).resolve()
|
||||
if not o3de_object_path.is_dir():
|
||||
logger.error(f'Engines path is not dir.')
|
||||
return 1
|
||||
|
||||
o3de_object_type_set = set()
|
||||
register_path_kwarg = f'{o3de_object_type}_path' if o3de_object_type != 'repo' else f'{o3de_object_type}_uri'
|
||||
|
||||
ret_val = 0
|
||||
for root, dirs, files in os.walk(o3de_object_path):
|
||||
if f'{o3de_object_type}.json' in files:
|
||||
o3de_object_type_set.add(root)
|
||||
# Stop iteration of any subdirectories
|
||||
# Nested o3de objects of the same type aren't supported(i.e an engine cannot be inside of a engine).
|
||||
dirs[:] = []
|
||||
|
||||
for o3de_object_type_root in sorted(o3de_object_type_set, reverse=True):
|
||||
error_code = register(**{register_path_kwarg: o3de_object_type_root},
|
||||
remove=remove, force=force, **register_kwargs)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def register_all_engines_in_folder(engines_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
force: bool = False) -> int:
|
||||
return register_all_o3de_objects_of_type_in_folder(engines_path, 'engine', remove, force)
|
||||
|
||||
|
||||
def register_all_projects_in_folder(projects_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
return register_all_o3de_objects_of_type_in_folder(projects_path, 'project', remove, False, engine_path=engine_path)
|
||||
|
||||
|
||||
def register_all_gems_in_folder(gems_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: pathlib.Path = None,
|
||||
project_path: pathlib.Path = None) -> int:
|
||||
return register_all_o3de_objects_of_type_in_folder(gems_path, 'gem', remove, False, engine_path=engine_path)
|
||||
|
||||
|
||||
def register_all_templates_in_folder(templates_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
return register_all_o3de_objects_of_type_in_folder(templates_path, 'template', remove, False, engine_path=engine_path)
|
||||
|
||||
|
||||
def register_all_restricted_in_folder(restricted_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
return register_all_o3de_objects_of_type_in_folder(restricted_path, 'restricted', remove, False, engine_path=engine_path)
|
||||
|
||||
|
||||
def register_all_repos_in_folder(repos_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
return register_all_o3de_objects_of_type_in_folder(repos_path, 'repo', remove, force, engine_path=engine_path)
|
||||
|
||||
|
||||
def remove_engine_name_to_path(json_data: dict,
|
||||
engine_path: pathlib.Path) -> int:
|
||||
"""
|
||||
Remove the engine at the specified path if it exist in the o3de manifest
|
||||
:param json_data in-memory json view of the o3de_manifest.json data
|
||||
:param engine_path path to engine to remove from the manifest data
|
||||
|
||||
returns 0 to indicate no issues has occurred with removal
|
||||
"""
|
||||
if engine_path.is_dir() and validation.valid_o3de_engine_json(engine_path):
|
||||
engine_json_data = manifest.get_engine_json_data(engine_path=engine_path)
|
||||
if 'engine_name' in engine_json_data and 'engines_path' in json_data:
|
||||
engine_name = engine_json_data['engine_name']
|
||||
try:
|
||||
del json_data['engines_path'][engine_name]
|
||||
except KeyError:
|
||||
# Attempting to remove a non-existent engine_name is fine
|
||||
pass
|
||||
return 0
|
||||
|
||||
|
||||
def add_engine_name_to_path(json_data: dict, engine_path: pathlib.Path, force: bool):
|
||||
# Add an engine path JSON object which maps the "engine_name" -> "engine_path"
|
||||
engine_json_data = manifest.get_engine_json_data(engine_path=engine_path)
|
||||
if not engine_json_data:
|
||||
logger.error(f'Unable to retrieve json data from engine.json at path {engine_path.as_posix()}')
|
||||
return 1
|
||||
engines_path_json = json_data.setdefault('engines_path', {})
|
||||
if 'engine_name' not in engine_json_data:
|
||||
logger.error(f'engine.json at path {engine_path.as_posix()} is missing "engine_name" key')
|
||||
return 1
|
||||
|
||||
engine_name = engine_json_data['engine_name']
|
||||
if not force and engine_name in engines_path_json and \
|
||||
pathlib.PurePath(engines_path_json[engine_name]) != engine_path:
|
||||
logger.error(
|
||||
f'Attempting to register existing engine "{engine_name}" with a new path of {engine_path.as_posix()}.'
|
||||
f' The current path is {pathlib.Path(engines_path_json[engine_name]).as_posix()}.'
|
||||
f' To force registration of a new engine path, specify the -f/--force option.')
|
||||
return 1
|
||||
engines_path_json[engine_name] = engine_path.as_posix()
|
||||
return 0
|
||||
|
||||
|
||||
def register_engine_path(json_data: dict,
|
||||
engine_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
force: bool = False) -> int:
|
||||
if not engine_path:
|
||||
logger.error(f'Engine path cannot be empty.')
|
||||
return 1
|
||||
engine_path = pathlib.Path(engine_path).resolve()
|
||||
|
||||
for engine_object in json_data.get('engines', {}):
|
||||
engine_object_path = pathlib.Path(engine_object['path']).resolve()
|
||||
if engine_object_path == engine_path:
|
||||
json_data['engines'].remove(engine_object)
|
||||
|
||||
if remove:
|
||||
return remove_engine_name_to_path(json_data, engine_path)
|
||||
|
||||
if not engine_path.is_dir():
|
||||
logger.error(f'Engine path {engine_path} does not exist.')
|
||||
return 1
|
||||
|
||||
engine_json = engine_path / 'engine.json'
|
||||
if not validation.valid_o3de_engine_json(engine_json):
|
||||
logger.error(f'Engine json {engine_json} is not valid.')
|
||||
return 1
|
||||
|
||||
engine_object = {}
|
||||
engine_object.update({'path': engine_path.as_posix()})
|
||||
|
||||
json_data.setdefault('engines', []).insert(0, engine_object)
|
||||
|
||||
return add_engine_name_to_path(json_data, engine_path, force)
|
||||
|
||||
|
||||
def register_o3de_object_path(json_data: dict,
|
||||
o3de_object_path: str or pathlib.Path,
|
||||
o3de_object_key: str,
|
||||
o3de_json_filename: str,
|
||||
validation_func: callable,
|
||||
remove: bool = False,
|
||||
engine_path: pathlib.Path = None,
|
||||
project_path: pathlib.Path = None) -> int:
|
||||
# save_path variable is used to save the changes to the store the path to the file to save
|
||||
# if the registration is for the project or engine
|
||||
save_path = None
|
||||
|
||||
if not o3de_object_path:
|
||||
logger.error(f'o3de object path cannot be empty.')
|
||||
return 1
|
||||
|
||||
o3de_object_path = pathlib.Path(o3de_object_path).resolve()
|
||||
|
||||
if engine_path and project_path:
|
||||
logger.error(f'Both a project path: {project_path} and engine path: {engine_path} has been supplied.'
|
||||
'A subdirectory can only be registered to either the engine path or project in one command')
|
||||
|
||||
manifest_data = None
|
||||
if engine_path:
|
||||
manifest_data = manifest.get_engine_json_data(json_data, engine_path)
|
||||
if not manifest_data:
|
||||
logger.error(f'Cannot load engine.json data at path {engine_path}')
|
||||
return 1
|
||||
|
||||
save_path = engine_path / 'engine.json'
|
||||
elif project_path:
|
||||
manifest_data = manifest.get_project_json_data(json_data, project_path)
|
||||
if not manifest_data:
|
||||
logger.error(f'Cannot load project.json data at path {project_path}')
|
||||
return 1
|
||||
|
||||
save_path = project_path / 'project.json'
|
||||
else:
|
||||
manifest_data = json_data
|
||||
|
||||
paths_to_remove = [o3de_object_path]
|
||||
if save_path:
|
||||
try:
|
||||
paths_to_remove.append(o3de_object_path.relative_to(save_path.parent))
|
||||
except ValueError:
|
||||
pass # It is OK relative path cannot be formed
|
||||
manifest_data[o3de_object_key] = list(filter(lambda p: pathlib.Path(p) not in paths_to_remove,
|
||||
manifest_data.setdefault(o3de_object_key, [])))
|
||||
|
||||
if remove:
|
||||
if save_path:
|
||||
manifest.save_o3de_manifest(manifest_data, save_path)
|
||||
return 0
|
||||
|
||||
if not o3de_object_path.is_dir():
|
||||
logger.error(f'o3de object path {o3de_object_path} does not exist.')
|
||||
return 1
|
||||
|
||||
manifest_json_path = o3de_object_path / o3de_json_filename
|
||||
if validation_func and not validation_func(manifest_json_path):
|
||||
logger.error(f'o3de json {manifest_json_path} is not valid.')
|
||||
return 1
|
||||
|
||||
# if there is a save path make it relative the directory containing o3de object json file
|
||||
if save_path:
|
||||
try:
|
||||
o3de_object_path = o3de_object_path.relative_to(save_path.parent)
|
||||
except ValueError:
|
||||
pass # It is OK relative path cannot be formed
|
||||
manifest_data[o3de_object_key].insert(0, o3de_object_path.as_posix())
|
||||
if save_path:
|
||||
manifest.save_o3de_manifest(manifest_data, save_path)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def register_external_subdirectory(json_data: dict,
|
||||
external_subdir_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: pathlib.Path = None,
|
||||
project_path: pathlib.Path = None) -> int:
|
||||
"""
|
||||
:return An integer return code indicating whether registration or removal of the external subdirectory
|
||||
completed successfully
|
||||
"""
|
||||
return register_o3de_object_path(json_data, external_subdir_path, 'external_subdirectories', '', None, remove,
|
||||
engine_path, project_path)
|
||||
|
||||
|
||||
def register_gem_path(json_data: dict,
|
||||
gem_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: pathlib.Path = None,
|
||||
project_path: pathlib.Path = None) -> int:
|
||||
return register_o3de_object_path(json_data, gem_path, 'external_subdirectories', 'gem.json',
|
||||
validation.valid_o3de_gem_json, remove, engine_path, project_path)
|
||||
|
||||
|
||||
def register_project_path(json_data: dict,
|
||||
project_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
result = register_o3de_object_path(json_data, project_path, 'projects', 'project.json',
|
||||
validation.valid_o3de_project_json, remove, engine_path, None)
|
||||
|
||||
if result != 0:
|
||||
return result
|
||||
|
||||
# registering a project has the additional step of setting the project.json 'engine' field
|
||||
this_engine_json = manifest.get_engine_json_data(engine_path=manifest.get_this_engine_path())
|
||||
if not this_engine_json:
|
||||
return 1
|
||||
project_json_data = manifest.get_project_json_data(project_path=project_path)
|
||||
if not project_json_data:
|
||||
return 1
|
||||
|
||||
update_project_json = False
|
||||
try:
|
||||
update_project_json = project_json_data['engine'] != this_engine_json['engine_name']
|
||||
except KeyError as e:
|
||||
update_project_json = True
|
||||
|
||||
if update_project_json:
|
||||
project_json_data['engine'] = this_engine_json['engine_name']
|
||||
utils.backup_file(project_json)
|
||||
if not manifest.save_o3de_manifest(project_json_data, project_path):
|
||||
return 1
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def register_template_path(json_data: dict,
|
||||
template_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
return register_o3de_object_path(json_data, template_path, 'templates', 'template.json',
|
||||
validation.valid_o3de_template_json, remove, engine_path, None)
|
||||
|
||||
|
||||
def register_restricted_path(json_data: dict,
|
||||
restricted_path: str or pathlib.Path,
|
||||
remove: bool = False,
|
||||
engine_path: str or pathlib.Path = None) -> int:
|
||||
return register_o3de_object_path(json_data, restricted_path, 'restricted', 'restricted.json',
|
||||
validation.valid_o3de_restricted_json, remove, engine_path, None)
|
||||
|
||||
|
||||
def register_repo(json_data: dict,
|
||||
repo_uri: str or pathlib.Path,
|
||||
remove: bool = False) -> int:
|
||||
if not repo_uri:
|
||||
logger.error(f'Repo URI cannot be empty.')
|
||||
return 1
|
||||
|
||||
url = f'{repo_uri}/repo.json'
|
||||
parsed_uri = urllib.parse.urlparse(url)
|
||||
|
||||
if parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']:
|
||||
while repo_uri in json_data['repos']:
|
||||
json_data['repos'].remove(repo_uri)
|
||||
else:
|
||||
repo_uri = pathlib.Path(repo_uri).resolve()
|
||||
while repo_uri.as_posix() in json_data['repos']:
|
||||
json_data['repos'].remove(repo_uri.as_posix())
|
||||
|
||||
if remove:
|
||||
logger.warn(f'Removing repo uri {repo_uri}.')
|
||||
return 0
|
||||
|
||||
repo_sha256 = hashlib.sha256(url.encode())
|
||||
cache_file = manifest.get_o3de_cache_folder() / str(repo_sha256.hexdigest() + '.json')
|
||||
|
||||
result = utils.download_file(url, cache_file)
|
||||
if result == 0:
|
||||
json_data['repos'].insert(0, repo_uri.as_posix())
|
||||
|
||||
result = repo.process_add_o3de_repo(cache_file, repo_set)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def register_default_o3de_object_folder(json_data: dict,
|
||||
default_o3de_object_folder: str or pathlib.Path,
|
||||
o3de_object_key: str) -> int:
|
||||
# make sure the path exists
|
||||
default_o3de_object_folder = pathlib.Path(default_o3de_object_folder).resolve()
|
||||
if not default_o3de_object_folder.is_dir():
|
||||
logger.error(f'Default o3de object folder {default_o3de_object_folder} does not exist.')
|
||||
return 1
|
||||
|
||||
json_data[o3de_object_key] = default_o3de_object_folder.as_posix()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def register_default_engines_folder(json_data: dict,
|
||||
default_engines_folder: str or pathlib.Path,
|
||||
remove: bool = False) -> int:
|
||||
return register_default_o3de_object_folder(json_data,
|
||||
manifest.get_o3de_engines_folder() if remove else default_engines_folder,
|
||||
'default_engines_folder', remove)
|
||||
|
||||
|
||||
def register_default_projects_folder(json_data: dict,
|
||||
default_projects_folder: str or pathlib.Path,
|
||||
remove: bool = False) -> int:
|
||||
return register_default_o3de_object_folder(json_data,
|
||||
manifest.get_o3de_projects_folder() if remove else default_projects_folder,
|
||||
'default_projects_folder', remove)
|
||||
|
||||
|
||||
def register_default_gems_folder(json_data: dict,
|
||||
default_gems_folder: str or pathlib.Path,
|
||||
remove: bool = False) -> int:
|
||||
return register_default_o3de_object_folder(json_data,
|
||||
manifest.get_o3de_gems_folder() if remove else default_gems_folder,
|
||||
'default_gems_folder', remove)
|
||||
|
||||
|
||||
def register_default_templates_folder(json_data: dict,
|
||||
default_templates_folder: str or pathlib.Path,
|
||||
remove: bool = False) -> int:
|
||||
return register_default_o3de_object_folder(json_data,
|
||||
manifest.get_o3de_templates_folder() if remove else default_templates_folder,
|
||||
'default_templates_folder', remove)
|
||||
|
||||
|
||||
def register_default_restricted_folder(json_data: dict,
|
||||
default_restricted_folder: str or pathlib.Path,
|
||||
reset_to_default: bool = False) -> int:
|
||||
return register_default_o3de_object_folder(json_data,
|
||||
manifest.get_o3de_restricted_folder() if remove else default_restricted_folder,
|
||||
'default_restricted_folder', remove)
|
||||
|
||||
|
||||
def register(engine_path: str or pathlib.Path = None,
|
||||
project_path: str or pathlib.Path = None,
|
||||
gem_path: str or pathlib.Path = None,
|
||||
external_subdir_path: str or pathlib.Path = None,
|
||||
template_path: str or pathlib.Path = None,
|
||||
restricted_path: str or pathlib.Path = None,
|
||||
repo_uri: str or pathlib.Path = None,
|
||||
default_engines_folder: str or pathlib.Path = None,
|
||||
default_projects_folder: str or pathlib.Path = None,
|
||||
default_gems_folder: str or pathlib.Path = None,
|
||||
default_templates_folder: str or pathlib.Path = None,
|
||||
default_restricted_folder: str or pathlib.Path = None,
|
||||
external_subdir_engine_path: pathlib.Path = None,
|
||||
external_subdir_project_path: pathlib.Path = None,
|
||||
remove: bool = False,
|
||||
force: bool = False
|
||||
) -> int:
|
||||
"""
|
||||
Adds/Updates entries to the ~/.o3de/o3de_manifest.json
|
||||
|
||||
:param engine_path: if engine folder is supplied the path will be added to the engine if it can, if not global
|
||||
:param project_path: project folder
|
||||
:param gem_path: gem folder
|
||||
:param external_subdir_path: external subdirectory
|
||||
:param template_path: template folder
|
||||
:param restricted_path: restricted folder
|
||||
:param repo_uri: repo uri
|
||||
:param default_engines_folder: default engines folder
|
||||
:param default_projects_folder: default projects folder
|
||||
:param default_gems_folder: default gems folder
|
||||
:param default_templates_folder: default templates folder
|
||||
:param default_restricted_folder: default restricted code folder
|
||||
:param external_subdir_engine_path: Path to the engine to use when registering an external subdirectory.
|
||||
The registration occurs in the engine.json file in this case
|
||||
:param external_subdir_engine_path: Path to the project to use when registering an external subdirectory.
|
||||
The registrations occurs in the project.json in this case
|
||||
:param remove: add/remove the entries
|
||||
:param force: force update of the engine_path for specified "engine_name" from the engine.json file
|
||||
|
||||
:return: 0 for success or non 0 failure code
|
||||
"""
|
||||
|
||||
json_data = manifest.load_o3de_manifest()
|
||||
|
||||
result = 0
|
||||
|
||||
# do anything that could require a engine context first
|
||||
if isinstance(project_path, str) or isinstance(project_path, pathlib.PurePath):
|
||||
if not project_path:
|
||||
logger.error(f'Project path cannot be empty.')
|
||||
return 1
|
||||
result = register_project_path(json_data, project_path, remove, engine_path)
|
||||
|
||||
elif isinstance(gem_path, str) or isinstance(gem_path, pathlib.PurePath):
|
||||
if not gem_path:
|
||||
logger.error(f'Gem path cannot be empty.')
|
||||
return 1
|
||||
result = register_gem_path(json_data, gem_path, remove,
|
||||
external_subdir_engine_path, external_subdir_project_path)
|
||||
elif isinstance(external_subdir_path, str) or isinstance(external_subdir_path, pathlib.PurePath):
|
||||
if not external_subdir_path:
|
||||
logger.error(f'External Subdirectory path is None.')
|
||||
return 1
|
||||
result = register_external_subdirectory(json_data, external_subdir_path, remove,
|
||||
external_subdir_engine_path, external_subdir_project_path)
|
||||
|
||||
elif isinstance(template_path, str) or isinstance(template_path, pathlib.PurePath):
|
||||
if not template_path:
|
||||
logger.error(f'Template path cannot be empty.')
|
||||
return 1
|
||||
result = register_template_path(json_data, template_path, remove, engine_path)
|
||||
|
||||
elif isinstance(restricted_path, str) or isinstance(restricted_path, pathlib.PurePath):
|
||||
if not restricted_path:
|
||||
logger.error(f'Restricted path cannot be empty.')
|
||||
return 1
|
||||
result = register_restricted_path(json_data, restricted_path, remove, engine_path)
|
||||
|
||||
elif isinstance(repo_uri, str) or isinstance(repo_uri, pathlib.PurePath):
|
||||
if not repo_uri:
|
||||
logger.error(f'Repo URI cannot be empty.')
|
||||
return 1
|
||||
result = register_repo(json_data, repo_uri, remove)
|
||||
|
||||
elif isinstance(default_engines_folder, str) or isinstance(default_engines_folder, pathlib.PurePath):
|
||||
result = register_default_engines_folder(json_data, default_engines_folder, remove)
|
||||
|
||||
elif isinstance(default_projects_folder, str) or isinstance(default_projects_folder, pathlib.PurePath):
|
||||
result = register_default_projects_folder(json_data, default_projects_folder, remove)
|
||||
|
||||
elif isinstance(default_gems_folder, str) or isinstance(default_gems_folder, pathlib.PurePath):
|
||||
result = register_default_gems_folder(json_data, default_gems_folder, remove)
|
||||
|
||||
elif isinstance(default_templates_folder, str) or isinstance(default_templates_folder, pathlib.PurePath):
|
||||
result = register_default_templates_folder(json_data, default_templates_folder, remove)
|
||||
|
||||
elif isinstance(default_restricted_folder, str) or isinstance(default_restricted_folder, pathlib.PurePath):
|
||||
result = register_default_restricted_folder(json_data, default_restricted_folder, remove)
|
||||
|
||||
# engine is done LAST
|
||||
# Now that everything that could have an engine context is done, if the engine is supplied that means this is
|
||||
# registering the engine itself
|
||||
elif isinstance(engine_path, str) or isinstance(engine_path, pathlib.PurePath):
|
||||
if not engine_path:
|
||||
logger.error(f'Engine path cannot be empty.')
|
||||
return 1
|
||||
result = register_engine_path(json_data, engine_path, remove, force)
|
||||
|
||||
if not result:
|
||||
manifest.save_o3de_manifest(json_data)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def remove_invalid_o3de_objects() -> None:
|
||||
json_data = manifest.load_o3de_manifest()
|
||||
|
||||
for engine_object in json_data['engines']:
|
||||
engine_path = engine_object['path']
|
||||
if not validation.valid_o3de_engine_json(pathlib.Path(engine_path).resolve() / 'engine.json'):
|
||||
logger.warn(f"Engine path {engine_path} is invalid.")
|
||||
register(engine_path=engine_path, remove=True)
|
||||
|
||||
for project in json_data['projects']:
|
||||
if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json'):
|
||||
logger.warn(f"Project path {project} is invalid.")
|
||||
register(project_path=project, remove=True)
|
||||
|
||||
for gem in json_data['gems']:
|
||||
if not validation.valid_o3de_gem_json(pathlib.Path(gem).resolve() / 'gem.json'):
|
||||
logger.warn(f"Gem path {gem} is invalid.")
|
||||
register(gem_path=gem, remove=True)
|
||||
|
||||
for external in json_data['external_subdirectories']:
|
||||
external = pathlib.Path(external).resolve()
|
||||
if not external.is_dir():
|
||||
logger.warn(f"External subdirectory {external} is invalid.")
|
||||
register(engine_path=engine_path, external_subdir_path=external, remove=True)
|
||||
|
||||
for template in json_data['templates']:
|
||||
if not validation.valid_o3de_template_json(pathlib.Path(template).resolve() / 'template.json'):
|
||||
logger.warn(f"Template path {template} is invalid.")
|
||||
register(template_path=template, remove=True)
|
||||
|
||||
for restricted in json_data['restricted']:
|
||||
if not validation.valid_o3de_restricted_json(pathlib.Path(restricted).resolve() / 'restricted.json'):
|
||||
logger.warn(f"Restricted path {restricted} is invalid.")
|
||||
register(restricted_path=restricted, remove=True)
|
||||
|
||||
default_engines_folder = pathlib.Path(json_data['default_engines_folder']).resolve()
|
||||
if not default_engines_folder.is_dir():
|
||||
new_default_engines_folder = manifest.get_o3de_folder() / 'Engines'
|
||||
new_default_engines_folder.mkdir(parents=True, exist_ok=True)
|
||||
logger.warn(
|
||||
f"Default engines folder {default_engines_folder} is invalid. Set default {new_default_engines_folder}")
|
||||
register(default_engines_folder=new_default_engines_folder.as_posix())
|
||||
|
||||
default_projects_folder = pathlib.Path(json_data['default_projects_folder']).resolve()
|
||||
if not default_projects_folder.is_dir():
|
||||
new_default_projects_folder = manifest.get_o3de_folder() / 'Projects'
|
||||
new_default_projects_folder.mkdir(parents=True, exist_ok=True)
|
||||
logger.warn(
|
||||
f"Default projects folder {default_projects_folder} is invalid. Set default {new_default_projects_folder}")
|
||||
register(default_projects_folder=new_default_projects_folder.as_posix())
|
||||
|
||||
default_gems_folder = pathlib.Path(json_data['default_gems_folder']).resolve()
|
||||
if not default_gems_folder.is_dir():
|
||||
new_default_gems_folder = manifest.get_o3de_folder() / 'Gems'
|
||||
new_default_gems_folder.mkdir(parents=True, exist_ok=True)
|
||||
logger.warn(f"Default gems folder {default_gems_folder} is invalid."
|
||||
f" Set default {new_default_gems_folder}")
|
||||
register(default_gems_folder=new_default_gems_folder.as_posix())
|
||||
|
||||
default_templates_folder = pathlib.Path(json_data['default_templates_folder']).resolve()
|
||||
if not default_templates_folder.is_dir():
|
||||
new_default_templates_folder = manifest.get_o3de_folder() / 'Templates'
|
||||
new_default_templates_folder.mkdir(parents=True, exist_ok=True)
|
||||
logger.warn(
|
||||
f"Default templates folder {default_templates_folder} is invalid."
|
||||
f" Set default {new_default_templates_folder}")
|
||||
register(default_templates_folder=new_default_templates_folder.as_posix())
|
||||
|
||||
default_restricted_folder = pathlib.Path(json_data['default_restricted_folder']).resolve()
|
||||
if not default_restricted_folder.is_dir():
|
||||
default_restricted_folder = manifest.get_o3de_folder() / 'Restricted'
|
||||
default_restricted_folder.mkdir(parents=True, exist_ok=True)
|
||||
logger.warn(
|
||||
f"Default restricted folder {default_restricted_folder} is invalid."
|
||||
f" Set default {default_restricted_folder}")
|
||||
register(default_restricted_folder=default_restricted_folder.as_posix())
|
||||
|
||||
|
||||
def _run_register(args: argparse) -> int:
|
||||
if args.override_home_folder:
|
||||
manifest.override_home_folder = args.override_home_folder
|
||||
|
||||
if args.update:
|
||||
remove_invalid_o3de_objects()
|
||||
return repo.refresh_repos()
|
||||
elif args.this_engine:
|
||||
ret_val = register(engine_path=manifest.get_this_engine_path(), force=args.force)
|
||||
error_code = register_shipped_engine_o3de_objects(force=args.force)
|
||||
if error_code:
|
||||
ret_val = error_code
|
||||
return ret_val
|
||||
elif args.all_engines_path:
|
||||
return register_all_engines_in_folder(args.all_engines_path, args.remove, args.force)
|
||||
elif args.all_projects_path:
|
||||
return register_all_projects_in_folder(args.all_projects_path, args.remove)
|
||||
elif args.all_gems_path:
|
||||
return register_all_gems_in_folder(args.all_gems_path, args.remove)
|
||||
elif args.all_templates_path:
|
||||
return register_all_templates_in_folder(args.all_templates_path, args.remove)
|
||||
elif args.all_restricted_path:
|
||||
return register_all_restricted_in_folder(args.all_restricted_path, args.remove)
|
||||
elif args.all_repo_uri:
|
||||
return register_all_repos_in_folder(args.all_restricted_path, args.remove)
|
||||
else:
|
||||
return register(engine_path=args.engine_path,
|
||||
project_path=args.project_path,
|
||||
gem_path=args.gem_path,
|
||||
external_subdir_path=args.external_subdirectory,
|
||||
template_path=args.template_path,
|
||||
restricted_path=args.restricted_path,
|
||||
repo_uri=args.repo_uri,
|
||||
default_engines_folder=args.default_engines_folder,
|
||||
default_projects_folder=args.default_projects_folder,
|
||||
default_gems_folder=args.default_gems_folder,
|
||||
default_templates_folder=args.default_templates_folder,
|
||||
default_restricted_folder=args.default_restricted_folder,
|
||||
external_subdir_engine_path=args.external_subdirectory_engine_path,
|
||||
external_subdir_project_path=args.external_subdirectory_project_path,
|
||||
remove=args.remove,
|
||||
force=args.force)
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python register.py --engine-path "C:/o3de"
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('--this-engine', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Registers the engine this script is running from.')
|
||||
group.add_argument('-ep', '--engine-path', type=str, required=False,
|
||||
help='Engine path to register/remove.')
|
||||
group.add_argument('-pp', '--project-path', type=str, required=False,
|
||||
help='Project path to register/remove.')
|
||||
group.add_argument('-gp', '--gem-path', type=str, required=False,
|
||||
help='Gem path to register/remove.')
|
||||
group.add_argument('-es', '--external-subdirectory', type=str, required=False,
|
||||
help='External subdirectory path to register/remove.')
|
||||
group.add_argument('-tp', '--template-path', type=str, required=False,
|
||||
help='Template path to register/remove.')
|
||||
group.add_argument('-rp', '--restricted-path', type=str, required=False,
|
||||
help='A restricted folder to register/remove.')
|
||||
group.add_argument('-ru', '--repo-uri', type=str, required=False,
|
||||
help='A repo uri to register/remove.')
|
||||
group.add_argument('-aep', '--all-engines-path', type=str, required=False,
|
||||
help='All engines under this folder to register/remove.')
|
||||
group.add_argument('-app', '--all-projects-path', type=str, required=False,
|
||||
help='All projects under this folder to register/remove.')
|
||||
group.add_argument('-agp', '--all-gems-path', type=str, required=False,
|
||||
help='All gems under this folder to register/remove.')
|
||||
group.add_argument('-atp', '--all-templates-path', type=str, required=False,
|
||||
help='All templates under this folder to register/remove.')
|
||||
group.add_argument('-arp', '--all-restricted-path', type=str, required=False,
|
||||
help='All templates under this folder to register/remove.')
|
||||
group.add_argument('-aru', '--all-repo-uri', type=str, required=False,
|
||||
help='All repos under this folder to register/remove.')
|
||||
group.add_argument('-def', '--default-engines-folder', type=str, required=False,
|
||||
help='The default engines folder to register/remove.')
|
||||
group.add_argument('-dpf', '--default-projects-folder', type=str, required=False,
|
||||
help='The default projects folder to register/remove.')
|
||||
group.add_argument('-dgf', '--default-gems-folder', type=str, required=False,
|
||||
help='The default gems folder to register/remove.')
|
||||
group.add_argument('-dtf', '--default-templates-folder', type=str, required=False,
|
||||
help='The default templates folder to register/remove.')
|
||||
group.add_argument('-drf', '--default-restricted-folder', type=str, required=False,
|
||||
help='The default restricted folder to register/remove.')
|
||||
group.add_argument('-u', '--update', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Refresh the repo cache.')
|
||||
|
||||
parser.add_argument('-ohf', '--override-home-folder', type=str, required=False,
|
||||
help='By default the home folder is the user folder, override it to this folder.')
|
||||
parser.add_argument('-r', '--remove', action='store_true', required=False,
|
||||
default=False,
|
||||
help='Remove entry.')
|
||||
parser.add_argument('-f', '--force', action='store_true', default=False,
|
||||
help='For the update of the registration field being modified.')
|
||||
|
||||
external_subdir_group = parser.add_argument_group(title='external-subdirectory',
|
||||
description='path arguments to use with the --external-subdirectory option')
|
||||
external_subdir_path_group = external_subdir_group.add_mutually_exclusive_group()
|
||||
external_subdir_path_group.add_argument('-esep', '--external-subdirectory-engine-path', type=pathlib.Path,
|
||||
help='If supplied, registers the external subdirectory with the engine.json at' \
|
||||
' the engine-path location')
|
||||
external_subdir_path_group.add_argument('-espp', '--external-subdirectory-project-path', type=pathlib.Path)
|
||||
parser.set_defaults(func=_run_register)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py register --engine-path "C:/o3de"
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
register_subparser = subparsers.add_parser('register')
|
||||
add_parser_args(register_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs register.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,160 @@
|
||||
#
|
||||
# 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 logging
|
||||
import pathlib
|
||||
import shutil
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
from o3de import manifest, utils, validation
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
|
||||
def process_add_o3de_repo(file_name: str or pathlib.Path,
|
||||
repo_set: set) -> int:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not validation.valid_o3de_repo_json(file_name):
|
||||
return 1
|
||||
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
repo_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'{file_name} failed to load: {str(e)}')
|
||||
return 1
|
||||
|
||||
for o3de_object_uris, manifest_json in [(repo_data['engines'], 'engine.json'),
|
||||
(repo_data['projects'], 'project.json'),
|
||||
(repo_data['gems'], 'gem.json'),
|
||||
(repo_data['template'], 'template.json'),
|
||||
(repo_data['restricted'], 'restricted.json')]:
|
||||
for o3de_object_uri in o3de_object_uris:
|
||||
manifest_json_uri = f'{o3de_object_uri}/{manifest_json}'
|
||||
manifest_json_sha256 = hashlib.sha256(manifest_json_uri.encode())
|
||||
cache_file = cache_folder / str(manifest_json_sha256.hexdigest() + '.json')
|
||||
if not cache_file.is_file():
|
||||
parsed_uri = urllib.parse.urlparse(manifest_json_uri)
|
||||
download_file_result = utils.download_file(parsed_uri, cache_file)
|
||||
if download_file_result != 0:
|
||||
return download_file_result
|
||||
|
||||
repo_set |= repo_data['repos']
|
||||
return 0
|
||||
|
||||
|
||||
def refresh_repos() -> int:
|
||||
json_data = manifest.load_o3de_manifest()
|
||||
|
||||
# clear the cache
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
shutil.rmtree(cache_folder)
|
||||
cache_folder = manifest.get_o3de_cache_folder() # will recreate it
|
||||
|
||||
result = 0
|
||||
|
||||
# set will stop circular references
|
||||
repo_set = set()
|
||||
|
||||
for repo_uri in json_data['repos']:
|
||||
if repo_uri not in repo_set:
|
||||
repo_set.add(repo_uri)
|
||||
|
||||
repo_uri = f'{repo_uri}/repo.json'
|
||||
repo_sha256 = hashlib.sha256(repo_uri.encode())
|
||||
cache_file = cache_folder / str(repo_sha256.hexdigest() + '.json')
|
||||
if not cache_file.is_file():
|
||||
parsed_uri = urllib.parse.urlparse(repo_uri)
|
||||
download_file_result = utils.download_file(parsed_uri, cache_file)
|
||||
if download_file_result != 0:
|
||||
return download_file_result
|
||||
|
||||
if not validation.valid_o3de_repo_json(cache_file):
|
||||
logger.error(f'Repo json {repo_uri} is not valid.')
|
||||
cache_file.unlink()
|
||||
return 1
|
||||
|
||||
last_failure = process_add_o3de_repo(cache_file, repo_set)
|
||||
if last_failure:
|
||||
result = last_failure
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def search_repo(repo_json_data: dict,
|
||||
engine_name: str = None,
|
||||
project_name: str = None,
|
||||
gem_name: str = None,
|
||||
template_name: str = None,
|
||||
restricted_name: str = None) -> dict or None:
|
||||
|
||||
if isinstance(engine_name, str) or isinstance(engine_name, pathlib.PurePath):
|
||||
o3de_object_uris = repo_json_data['engines']
|
||||
manifest_json = 'engine.json'
|
||||
json_key = 'engine_name'
|
||||
search_func = lambda: None if manifest_json_data.get(json_key, '') == engine_name else manifest_json_data
|
||||
elif isinstance(project_name, str) or isinstance(project_name, pathlib.PurePath):
|
||||
o3de_object_uris = repo_json_data['projects']
|
||||
manifest_json = 'project.json'
|
||||
json_key = 'project_name'
|
||||
search_func = lambda: None if manifest_json_data.get(json_key, '') == project_name else manifest_json_data
|
||||
elif isinstance(gem_name, str) or isinstance(gem_name, pathlib.PurePath):
|
||||
o3de_object_uris = repo_json_data['gems']
|
||||
manifest_json = 'gem.json'
|
||||
json_key = 'gem_name'
|
||||
search_func = lambda: None if manifest_json_data.get(json_key, '') == gem_name else manifest_json_data
|
||||
elif isinstance(template_name, str) or isinstance(template_name, pathlib.PurePath):
|
||||
o3de_object_uris = repo_json_data['template']
|
||||
manifest_json = 'template.json'
|
||||
json_key = 'template_name'
|
||||
search_func = lambda: None if manifest_json_data.get(json_key, '') == template_name_name else manifest_json_data
|
||||
elif isinstance(restricted_name, str) or isinstance(restricted_name, pathlib.PurePath):
|
||||
o3de_object_uris = repo_json_data['restricted']
|
||||
manifest_json = 'restricted.json'
|
||||
json_key = 'restricted_name'
|
||||
search_func = lambda: None if manifest_json_data.get(json_key, '') == restricted_name else manifest_json_data
|
||||
else:
|
||||
return None
|
||||
|
||||
o3de_object = search_o3de_object(manifest_json, o3de_object_uris, search_func)
|
||||
if o3de_object:
|
||||
return o3de_object
|
||||
|
||||
# recurse into the repos object to search for the o3de object
|
||||
o3de_object_uris = repo_json_data['repos']
|
||||
manifest_json = 'repo.json'
|
||||
search_func = lambda: search_repo(manifest_json, engine_name, project_name, gem_name, template_name)
|
||||
return search_o3de_object(manifest_json, o3de_object_uris, search_func)
|
||||
|
||||
|
||||
def search_o3de_object(manifest_json, o3de_object_uris, search_func):
|
||||
# Search for the o3de object based on the supplied object name in the current repo
|
||||
cache_folder = manifest.get_o3de_cache_folder()
|
||||
for o3de_object_uri in o3de_object_uris:
|
||||
manifest_json_uri = f'{o3de_object_uri}/{manifest_json}'
|
||||
manifest_json_sha256 = hashlib.sha256(manifest_json_uri.encode())
|
||||
cache_file = cache_folder / str(manifest_json_sha256.hexdigest() + '.json')
|
||||
if cache_file.is_file():
|
||||
with cache_file.open('r') as f:
|
||||
try:
|
||||
manifest_json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warn(f'{cache_file} failed to load: {str(e)}')
|
||||
else:
|
||||
result_json_data = search_func()
|
||||
if result_json_data:
|
||||
return result_json_data
|
||||
return None
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa
|
||||
size 41127
|
||||
@@ -0,0 +1,117 @@
|
||||
#
|
||||
# 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 argparse
|
||||
import json
|
||||
import logging
|
||||
import hashlib
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
from o3de import utils
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
|
||||
def sha256(file_path: str or pathlib.Path,
|
||||
json_path: str or pathlib.Path = None) -> int:
|
||||
if not file_path:
|
||||
logger.error(f'File path cannot be empty.')
|
||||
return 1
|
||||
file_path = pathlib.Path(file_path).resolve()
|
||||
if not file_path.is_file():
|
||||
logger.error(f'File path {file_path} does not exist.')
|
||||
return 1
|
||||
|
||||
if json_path:
|
||||
json_path = pathlib.Path(json_path).resolve()
|
||||
if not json_path.is_file():
|
||||
logger.error(f'Json path {json_path} does not exist.')
|
||||
return 1
|
||||
|
||||
sha256 = hashlib.sha256(file_path.open('rb').read()).hexdigest()
|
||||
|
||||
if json_path:
|
||||
with json_path.open('r') as s:
|
||||
try:
|
||||
json_data = json.load(s)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'Failed to read Json path {json_path}: {str(e)}')
|
||||
return 1
|
||||
json_data.update({"sha256": sha256})
|
||||
utils.backup_file(json_path)
|
||||
with json_path.open('w') as s:
|
||||
try:
|
||||
s.write(json.dumps(json_data, indent=4) + '\n')
|
||||
except OSError as e:
|
||||
logger.error(f'Failed to write Json path {json_path}: {str(e)}')
|
||||
return 1
|
||||
else:
|
||||
print(sha256)
|
||||
return 0
|
||||
|
||||
|
||||
def _run_sha256(args: argparse) -> int:
|
||||
return sha256(args.file_path,
|
||||
args.json_path)
|
||||
|
||||
|
||||
def add_parser_args(parser):
|
||||
"""
|
||||
add_parser_args is called to add arguments to each command such that it can be
|
||||
invoked locally or added by a central python file.
|
||||
Ex. Directly run from this file alone with: python sha256.py --file-path "C:/TestGem"
|
||||
:param parser: the caller passes an argparse parser like instance to this method
|
||||
"""
|
||||
parser.add_argument('-f', '--file-path', type=str, required=True,
|
||||
help='The path to the file you want to sha256.')
|
||||
parser.add_argument('-j', '--json-path', type=str, required=False,
|
||||
help='optional path to an o3de json file to add the "sha256" element to.')
|
||||
parser.set_defaults(func=_run_sha256)
|
||||
|
||||
|
||||
def add_args(subparsers) -> None:
|
||||
"""
|
||||
add_args is called to add subparsers arguments to each command such that it can be
|
||||
a central python file such as o3de.py.
|
||||
It can be run from the o3de.py script as follows
|
||||
call add_args and execute: python o3de.py sha256 --file-path "C:/TestGem"
|
||||
:param subparsers: the caller instantiates subparsers and passes it in here
|
||||
"""
|
||||
sha256_subparser = subparsers.add_parser('sha256')
|
||||
add_parser_args(sha256_subparser)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Runs sha256.py script as standalone script
|
||||
"""
|
||||
# parse the command line args
|
||||
the_parser = argparse.ArgumentParser()
|
||||
|
||||
# add subparsers
|
||||
|
||||
# add args to the parser
|
||||
add_parser_args(the_parser)
|
||||
|
||||
# parse args
|
||||
the_args = the_parser.parse_args()
|
||||
|
||||
# run
|
||||
ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1
|
||||
|
||||
# return
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+112
@@ -0,0 +1,112 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
This file contains utility functions
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import pathlib
|
||||
import shutil
|
||||
import urllib.request
|
||||
|
||||
def validate_identifier(identifier: str) -> bool:
|
||||
"""
|
||||
Determine if the identifier supplied is valid.
|
||||
:param identifier: the name which needs to to checked
|
||||
:return: bool: if the identifier is valid or not
|
||||
"""
|
||||
if not identifier:
|
||||
return False
|
||||
elif len(identifier) > 64:
|
||||
return False
|
||||
elif not identifier[0].isalpha():
|
||||
return False
|
||||
else:
|
||||
for character in identifier:
|
||||
if not (character.isalnum() or character == '_' or character == '-'):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def validate_uuid4(uuid_string: str) -> bool:
|
||||
"""
|
||||
Determine if the uuid supplied is valid.
|
||||
:param uuid_string: the uuid which needs to to checked
|
||||
:return: bool: if the uuid is valid or not
|
||||
"""
|
||||
try:
|
||||
val = uuid.UUID(uuid_string, version=4)
|
||||
except ValueError:
|
||||
return False
|
||||
return str(val) == uuid_string
|
||||
|
||||
|
||||
def backup_file(file_name: str or pathlib.Path) -> None:
|
||||
index = 0
|
||||
renamed = False
|
||||
while not renamed:
|
||||
backup_file_name = pathlib.Path(str(file_name) + '.bak' + str(index)).resolve()
|
||||
index += 1
|
||||
if not backup_file_name.is_file():
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
file_name.rename(backup_file_name)
|
||||
if backup_file_name.is_file():
|
||||
renamed = True
|
||||
|
||||
|
||||
def backup_folder(folder: str or pathlib.Path) -> None:
|
||||
index = 0
|
||||
renamed = False
|
||||
while not renamed:
|
||||
backup_folder_name = pathlib.Path(str(folder) + '.bak' + str(index)).resolve()
|
||||
index += 1
|
||||
if not backup_folder_name.is_dir():
|
||||
folder = pathlib.Path(folder).resolve()
|
||||
folder.rename(backup_folder_name)
|
||||
if backup_folder_name.is_dir():
|
||||
renamed = True
|
||||
|
||||
|
||||
def download_file(parsed_uri, download_path: pathlib.Path) -> int:
|
||||
"""
|
||||
:param parsed_uri: uniform resource identifier to zip file to download
|
||||
:param download_path: location path on disk to download file
|
||||
"""
|
||||
if download_path.is_file():
|
||||
logger.warn(f'File already downloaded to {download_path}.')
|
||||
elif parsed_uri.scheme in ['http', 'https', 'ftp', 'ftps']:
|
||||
with urllib.request.urlopen(url) as s:
|
||||
with download_path.open('wb') as f:
|
||||
shutil.copyfileobj(s, f)
|
||||
else:
|
||||
origin_file = pathlib.Path(url).resolve()
|
||||
if not origin_file.is_file():
|
||||
return 1
|
||||
shutil.copy(origin_file, download_path)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def download_zip_file(parsed_uri, download_zip_path: pathlib.Path) -> int:
|
||||
"""
|
||||
:param parsed_uri: uniform resource identifier to zip file to download
|
||||
:param download_zip_path: path to output zip file
|
||||
"""
|
||||
download_file_result = download_file(parsed_uri, download_zip_path)
|
||||
if download_file_result != 0:
|
||||
return download_file_result
|
||||
|
||||
if not zipfile.is_zipfile(download_zip_path):
|
||||
logger.error(f"File zip {download_zip_path} is invalid.")
|
||||
download_zip_path.unlink()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -0,0 +1,102 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
"""
|
||||
This file validating o3de object json files
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
|
||||
def valid_o3de_json_dict(json_data: dict, key: str) -> bool:
|
||||
return key in json_data
|
||||
|
||||
|
||||
def valid_o3de_repo_json(file_name: str or pathlib.Path) -> bool:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not file_name.is_file():
|
||||
return False
|
||||
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
test = json_data['repo_name']
|
||||
test = json_data['origin']
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def valid_o3de_engine_json(file_name: str or pathlib.Path) -> bool:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not file_name.is_file():
|
||||
return False
|
||||
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
test = json_data['engine_name']
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def valid_o3de_project_json(file_name: str or pathlib.Path) -> bool:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not file_name.is_file():
|
||||
return False
|
||||
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
test = json_data['project_name']
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def valid_o3de_gem_json(file_name: str or pathlib.Path) -> bool:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not file_name.is_file():
|
||||
return False
|
||||
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
test = json_data['gem_name']
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def valid_o3de_template_json(file_name: str or pathlib.Path) -> bool:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not file_name.is_file():
|
||||
return False
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
test = json_data['template_name']
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def valid_o3de_restricted_json(file_name: str or pathlib.Path) -> bool:
|
||||
file_name = pathlib.Path(file_name).resolve()
|
||||
if not file_name.is_file():
|
||||
return False
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
json_data = json.load(f)
|
||||
test = json_data['restricted_name']
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
return False
|
||||
return True
|
||||
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
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 os
|
||||
import platform
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.develop import develop
|
||||
from setuptools.command.build_py import build_py
|
||||
|
||||
PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
PYTHON_64 = platform.architecture()[0] == '64bit'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not PYTHON_64:
|
||||
raise RuntimeError("32-bit Python is not a supported platform.")
|
||||
|
||||
with open(os.path.join(PACKAGE_ROOT, 'README.txt')) as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name="o3de",
|
||||
version="1.0.0",
|
||||
description='O3DE editor Python bindings test tools',
|
||||
long_description=long_description,
|
||||
packages=find_packages(where='o3de', exclude=['tests']),
|
||||
install_requires=[
|
||||
],
|
||||
tests_require=[
|
||||
],
|
||||
entry_points={
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
if(NOT PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Add a test to test out the o3de package `o3de.py register` command
|
||||
ly_add_pytest(
|
||||
NAME o3de_register
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_register.py
|
||||
TEST_SUITE smoke
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME o3de_cmake
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_cmake.py
|
||||
TEST_SUITE smoke
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME o3de_global_project
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/unit_test_global_project.py
|
||||
TEST_SUITE smoke
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
@@ -0,0 +1,69 @@
|
||||
#
|
||||
# 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 io
|
||||
import json
|
||||
import logging
|
||||
import pytest
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from o3de import cmake
|
||||
|
||||
|
||||
class TestGetEnabledGems:
|
||||
@pytest.mark.parametrize(
|
||||
"enable_gems_cmake_data, expected_set", [
|
||||
pytest.param("""
|
||||
# Comment
|
||||
set(ENABLED_GEMS foo bar baz)
|
||||
""", set(['foo', 'bar', 'baz'])),
|
||||
pytest.param("""
|
||||
# Comment
|
||||
set(ENABLED_GEMS
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
)
|
||||
""", set(['foo', 'bar', 'baz'])),
|
||||
pytest.param("""
|
||||
# Comment
|
||||
set(ENABLED_GEMS
|
||||
foo
|
||||
bar
|
||||
baz)
|
||||
""", set(['foo', 'bar', 'baz'])),
|
||||
pytest.param("""
|
||||
# Comment
|
||||
set(ENABLED_GEMS
|
||||
foo bar
|
||||
baz)
|
||||
""", set(['foo', 'bar', 'baz'])),
|
||||
pytest.param("""
|
||||
# Comment
|
||||
set(RANDOM_VARIABLE TestGame, TestProject Test Engine)
|
||||
set(ENABLED_GEMS HelloWorld IceCream
|
||||
foo
|
||||
baz bar
|
||||
baz baz baz baz baz morebaz lessbaz
|
||||
)
|
||||
Random Text
|
||||
""", set(['HelloWorld', 'IceCream', 'foo', 'bar', 'baz', 'morebaz', 'lessbaz'])),
|
||||
]
|
||||
)
|
||||
def test_get_enabled_gems(self, enable_gems_cmake_data, expected_set):
|
||||
enabled_gems_set = set()
|
||||
with patch('pathlib.Path.resolve', return_value=pathlib.Path('enabled_gems.cmake')) as pathlib_is_resolve_mock,\
|
||||
patch('pathlib.Path.is_file', return_value=True) as pathlib_is_file_mock,\
|
||||
patch('pathlib.Path.open', return_value=io.StringIO(enable_gems_cmake_data)) as pathlib_open_mock:
|
||||
enabled_gems_set = cmake.get_enabled_gems(pathlib.Path('enabled_gems.cmake'))
|
||||
|
||||
assert enabled_gems_set == expected_set
|
||||
+748
@@ -0,0 +1,748 @@
|
||||
#
|
||||
# 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 os
|
||||
import pytest
|
||||
from . import engine_template
|
||||
|
||||
TEST_TEMPLATED_CONTENT_WITH_LICENSE = """\
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace ${Name}
|
||||
{
|
||||
class ${Name}Requests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using ${Name}RequestsBus = AZ::EBus<${Name}Requests>;
|
||||
|
||||
} // namespace ${Name}
|
||||
|
||||
"""
|
||||
|
||||
TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE = """\
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace ${Name}
|
||||
{
|
||||
class ${Name}Requests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using ${Name}RequestsBus = AZ::EBus<${Name}Requests>;
|
||||
|
||||
} // namespace ${Name}
|
||||
|
||||
"""
|
||||
|
||||
TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITHOUT_LICENSE = """\
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace TestTemplate
|
||||
{
|
||||
class TestTemplateRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using TestTemplateRequestsBus = AZ::EBus<TestTemplateRequests>;
|
||||
|
||||
} // namespace TestTemplate
|
||||
|
||||
"""
|
||||
|
||||
TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITH_LICENSE = """\
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace TestTemplate
|
||||
{
|
||||
class TestTemplateRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using TestTemplateRequestsBus = AZ::EBus<TestTemplateRequests>;
|
||||
|
||||
} // namespace TestTemplate
|
||||
|
||||
"""
|
||||
|
||||
TEST_CONCRETE_TESTPROJECT_TEMPLATE_CONTENT_WITHOUT_LICENSE = """\
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace TestProject
|
||||
{
|
||||
class TestProjectRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using TestProjectRequestsBus = AZ::EBus<TestProjectRequests>;
|
||||
|
||||
} // namespace TestProject
|
||||
|
||||
"""
|
||||
|
||||
TEST_CONCRETE_TESTPROJECT_TEMPLATE_CONTENT_WITH_LICENSE = """\
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace TestProject
|
||||
{
|
||||
class TestProjectRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using TestProjectRequestsBus = AZ::EBus<TestProjectRequests>;
|
||||
|
||||
} // namespace TestProject
|
||||
|
||||
"""
|
||||
|
||||
TEST_CONCRETE_TESTGEM_TEMPLATE_CONTENT_WITHOUT_LICENSE = """\
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace TestGem
|
||||
{
|
||||
class TestGemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using TestGemRequestsBus = AZ::EBus<TestGemRequests>;
|
||||
|
||||
} // namespace TestGem
|
||||
|
||||
"""
|
||||
|
||||
TEST_CONCRETE_TESTGEM_TEMPLATE_CONTENT_WITH_LICENSE = """\
|
||||
// {BEGIN_LICENSE}
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// {END_LICENSE}
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace TestGem
|
||||
{
|
||||
class TestGemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Put your public methods here
|
||||
};
|
||||
|
||||
using TestGemRequestsBus = AZ::EBus<TestGemRequests>;
|
||||
|
||||
} // namespace TestGem
|
||||
|
||||
"""
|
||||
|
||||
TEST_DEFAULTTEMPLATE_JSON_CONTENTS = """\
|
||||
{
|
||||
"inputPath": "Templates/Default/Template",
|
||||
"copyFiles": [
|
||||
{
|
||||
"inFile": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"outFile": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"outDir": "Code"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include/Platform"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include/${Name}"
|
||||
}
|
||||
]
|
||||
}\
|
||||
"""
|
||||
|
||||
TEST_DEFAULTTEMPLATE_RESTRICTED_JSON_CONTENTS = """\
|
||||
{
|
||||
"inputPath": "restricted/Salem/Templates/Default/Template",
|
||||
"copyFiles": [
|
||||
{
|
||||
"inFile": "Code/Include/Platform/Salem/${Name}Bus.h",
|
||||
"outFile": "Code/Include/Platform/Salem/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"outDir": "Code/Include/Platform/Salem"
|
||||
}
|
||||
]
|
||||
}\
|
||||
"""
|
||||
|
||||
TEST_DEFAULTPROJECT_TEMPLATE_JSON_CONTENTS = """\
|
||||
{
|
||||
"inputPath": "Templates/DefaultProject/Template",
|
||||
"copyFiles": [
|
||||
{
|
||||
"inFile": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"outFile": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"outDir": "Code"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include/Platform"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include/${Name}"
|
||||
}
|
||||
]
|
||||
}\
|
||||
"""
|
||||
|
||||
TEST_DEFAULTPROJECT_TEMPLATE_RESTRICTED_JSON_CONTENTS = """\
|
||||
{
|
||||
"inputPath": "restricted/Salem/Templates/DefaultProject/Template",
|
||||
"copyFiles": [
|
||||
{
|
||||
"inFile": "Code/Include/Platform/Salem/${Name}Bus.h",
|
||||
"outFile": "Code/Include/Platform/Salem/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"outDir": "Code/Include/Platform/Salem"
|
||||
}
|
||||
]
|
||||
}\
|
||||
"""
|
||||
|
||||
TEST_DEFAULTGEM_TEMPLATE_JSON_CONTENTS = """\
|
||||
{
|
||||
"inputPath": "Templates/DefaultGem/Template",
|
||||
"copyFiles": [
|
||||
{
|
||||
"inFile": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"outFile": "Code/Include/${Name}/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"outDir": "Code"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include/Platform"
|
||||
},
|
||||
{
|
||||
"outDir": "Code/Include/${Name}"
|
||||
}
|
||||
]
|
||||
}\
|
||||
"""
|
||||
|
||||
TEST_DEFAULTGEM_TEMPLATE_RESTRICTED_JSON_CONTENTS = """\
|
||||
{
|
||||
"inputPath": "restricted/Salem/Templates/DefaultGem/Template",
|
||||
"copyFiles": [
|
||||
{
|
||||
"inFile": "Code/Include/Platform/Salem/${Name}Bus.h",
|
||||
"outFile": "Code/Include/Platform/Salem/${Name}Bus.h",
|
||||
"isTemplated": true,
|
||||
"isOptional": false
|
||||
}
|
||||
],
|
||||
"createDirectories": [
|
||||
{
|
||||
"outDir": "Code/Include/Platform/Salem"
|
||||
}
|
||||
]
|
||||
}\
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"concrete_contents,"
|
||||
" templated_contents_with_license, templated_contents_without_license,"
|
||||
" keep_license_text, expect_failure,"
|
||||
" template_json_contents, restricted_template_json_contents", [
|
||||
pytest.param(TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITH_LICENSE,
|
||||
TEST_TEMPLATED_CONTENT_WITH_LICENSE, TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE,
|
||||
True, False,
|
||||
TEST_DEFAULTTEMPLATE_JSON_CONTENTS, TEST_DEFAULTTEMPLATE_RESTRICTED_JSON_CONTENTS),
|
||||
pytest.param(TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITH_LICENSE,
|
||||
TEST_TEMPLATED_CONTENT_WITH_LICENSE, TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE,
|
||||
False, False,
|
||||
TEST_DEFAULTTEMPLATE_JSON_CONTENTS, TEST_DEFAULTTEMPLATE_RESTRICTED_JSON_CONTENTS)
|
||||
]
|
||||
)
|
||||
def test_create_template(tmpdir,
|
||||
concrete_contents,
|
||||
templated_contents_with_license, templated_contents_without_license,
|
||||
keep_license_text, expect_failure,
|
||||
template_json_contents, restricted_template_json_contents):
|
||||
dev_root = str(tmpdir.join('dev').realpath()).replace('\\', '/')
|
||||
os.makedirs(dev_root, exist_ok=True)
|
||||
|
||||
dev_gem_code_include_testgem = f'{dev_root}/TestTemplate/Code/Include/TestTemplate'
|
||||
os.makedirs(dev_gem_code_include_testgem, exist_ok=True)
|
||||
|
||||
gem_bus_file = f'{dev_gem_code_include_testgem}/TestTemplateBus.h'
|
||||
if os.path.isfile(gem_bus_file):
|
||||
os.unlink(gem_bus_file)
|
||||
with open(gem_bus_file, 'w') as s:
|
||||
s.write(concrete_contents)
|
||||
|
||||
dev_gem_code_include_platform_salem = f'{dev_root}/TestTemplate/Code/Include/Platform/Salem'
|
||||
os.makedirs(dev_gem_code_include_platform_salem, exist_ok=True)
|
||||
|
||||
restricted_gem_bus_file = f'{dev_gem_code_include_platform_salem}/TestTemplateBus.h'
|
||||
if os.path.isfile(restricted_gem_bus_file):
|
||||
os.unlink(restricted_gem_bus_file)
|
||||
with open(restricted_gem_bus_file, 'w') as s:
|
||||
s.write(concrete_contents)
|
||||
|
||||
template_folder = f'{dev_root}/Templates'
|
||||
os.makedirs(template_folder, exist_ok=True)
|
||||
|
||||
restricted_folder = f'{dev_root}/restricted'
|
||||
os.makedirs(restricted_folder, exist_ok=True)
|
||||
|
||||
result = engine_template.create_template(dev_root, 'TestTemplate', 'Default', keep_license_text=keep_license_text)
|
||||
|
||||
if expect_failure:
|
||||
assert result != 0
|
||||
else:
|
||||
assert result == 0
|
||||
new_template_folder = f'{template_folder}/Default'
|
||||
assert os.path.isdir(new_template_folder)
|
||||
new_template_json = f'{new_template_folder}/template.json'
|
||||
assert os.path.isfile(new_template_json)
|
||||
with open(new_template_json, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == template_json_contents
|
||||
|
||||
new_default_name_bus_file = f'{new_template_folder}/Template/Code/Include/' + '${Name}/${Name}Bus.h'
|
||||
assert os.path.isfile(new_default_name_bus_file)
|
||||
with open(new_default_name_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
if keep_license_text:
|
||||
assert s_data == templated_contents_with_license
|
||||
else:
|
||||
assert s_data == templated_contents_without_license
|
||||
|
||||
restricted_template_folder = f'{dev_root}/restricted/Salem/Templates'
|
||||
|
||||
new_restricted_template_folder = f'{restricted_template_folder}/Default'
|
||||
assert os.path.isdir(new_restricted_template_folder)
|
||||
new_restricted_template_json = f'{new_restricted_template_folder}/template.json'
|
||||
assert os.path.isfile(new_restricted_template_json)
|
||||
with open(new_restricted_template_json, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == restricted_template_json_contents
|
||||
|
||||
new_restricted_default_name_bus_file = f'{restricted_template_folder}' \
|
||||
f'/Default/Template/Code/Include/Platform/Salem/' + '${Name}Bus.h'
|
||||
assert os.path.isfile(new_restricted_default_name_bus_file)
|
||||
with open(new_restricted_default_name_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
if keep_license_text:
|
||||
assert s_data == templated_contents_with_license
|
||||
else:
|
||||
assert s_data == templated_contents_without_license
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"concrete_contents, templated_contents,"
|
||||
" keep_license_text, expect_failure,"
|
||||
" template_json_contents, restricted_template_json_contents", [
|
||||
pytest.param(TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITH_LICENSE, TEST_TEMPLATED_CONTENT_WITH_LICENSE,
|
||||
True, False,
|
||||
TEST_DEFAULTTEMPLATE_JSON_CONTENTS, TEST_DEFAULTTEMPLATE_RESTRICTED_JSON_CONTENTS),
|
||||
pytest.param(TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITHOUT_LICENSE, TEST_TEMPLATED_CONTENT_WITH_LICENSE,
|
||||
False, False,
|
||||
TEST_DEFAULTTEMPLATE_JSON_CONTENTS, TEST_DEFAULTTEMPLATE_RESTRICTED_JSON_CONTENTS)
|
||||
]
|
||||
)
|
||||
def test_create_from_template(tmpdir,
|
||||
concrete_contents, templated_contents,
|
||||
keep_license_text, expect_failure,
|
||||
template_json_contents, restricted_template_json_contents):
|
||||
dev_root = str(tmpdir.join('dev').realpath()).replace('\\', '/')
|
||||
os.makedirs(dev_root, exist_ok=True)
|
||||
|
||||
template_default_folder = f'{dev_root}/Templates/Default'
|
||||
os.makedirs(template_default_folder, exist_ok=True)
|
||||
|
||||
template_json = f'{template_default_folder}/template.json'
|
||||
if os.path.isfile(template_json):
|
||||
os.unlink(template_json)
|
||||
with open(template_json, 'w') as s:
|
||||
s.write(template_json_contents)
|
||||
|
||||
default_name_bus_dir = f'{template_default_folder}/Template/Code/Include/' + '${Name}'
|
||||
os.makedirs(default_name_bus_dir, exist_ok=True)
|
||||
|
||||
default_name_bus_file = f'{default_name_bus_dir}/' + '${Name}Bus.h'
|
||||
if os.path.isfile(default_name_bus_file):
|
||||
os.unlink(default_name_bus_file)
|
||||
with open(default_name_bus_file, 'w') as s:
|
||||
s.write(templated_contents)
|
||||
|
||||
restricted_template_default_folder = f'{dev_root}/restricted/Salem/Templates/Default'
|
||||
os.makedirs(restricted_template_default_folder, exist_ok=True)
|
||||
|
||||
restricted_template_json = f'{restricted_template_default_folder}/template.json'
|
||||
if os.path.isfile(restricted_template_json):
|
||||
os.unlink(restricted_template_json)
|
||||
with open(restricted_template_json, 'w') as s:
|
||||
s.write(restricted_template_json_contents)
|
||||
|
||||
restricted_default_name_bus_dir = f'{restricted_template_default_folder}/Template/Code/Include/Platform/Salem'
|
||||
os.makedirs(restricted_default_name_bus_dir, exist_ok=True)
|
||||
|
||||
restricted_default_name_bus_file = f'{restricted_default_name_bus_dir}/' + '${Name}Bus.h'
|
||||
if os.path.isfile(restricted_default_name_bus_file):
|
||||
os.unlink(restricted_default_name_bus_file)
|
||||
with open(restricted_default_name_bus_file, 'w') as s:
|
||||
s.write(templated_contents)
|
||||
|
||||
result = engine_template.create_from_template(dev_root, 'TestTemplate', 'Default',
|
||||
keep_license_text=keep_license_text)
|
||||
if expect_failure:
|
||||
assert result != 0
|
||||
else:
|
||||
assert result == 0
|
||||
|
||||
test_folder = f'{dev_root}/TestTemplate'
|
||||
assert os.path.isdir(test_folder)
|
||||
|
||||
test_bus_file = f'{test_folder}/Code/Include/TestTemplate/TestTemplateBus.h'
|
||||
assert os.path.isfile(test_bus_file)
|
||||
with open(test_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == concrete_contents
|
||||
|
||||
restricted_test_bus_folder = f'{dev_root}/restricted/Salem/TestTemplate/Code/Include/Platform/Salem'
|
||||
assert os.path.isdir(restricted_test_bus_folder)
|
||||
|
||||
restricted_default_name_bus_file = f'{restricted_test_bus_folder}/TestTemplateBus.h'
|
||||
assert os.path.isfile(restricted_default_name_bus_file)
|
||||
with open(restricted_default_name_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == concrete_contents
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"concrete_contents, templated_contents,"
|
||||
" keep_license_text, expect_failure,"
|
||||
" template_json_contents, restricted_template_json_contents", [
|
||||
pytest.param(TEST_CONCRETE_TESTPROJECT_TEMPLATE_CONTENT_WITH_LICENSE, TEST_TEMPLATED_CONTENT_WITH_LICENSE,
|
||||
True, False,
|
||||
TEST_DEFAULTPROJECT_TEMPLATE_JSON_CONTENTS, TEST_DEFAULTPROJECT_TEMPLATE_RESTRICTED_JSON_CONTENTS),
|
||||
pytest.param(TEST_CONCRETE_TESTPROJECT_TEMPLATE_CONTENT_WITHOUT_LICENSE, TEST_TEMPLATED_CONTENT_WITH_LICENSE,
|
||||
False, False,
|
||||
TEST_DEFAULTPROJECT_TEMPLATE_JSON_CONTENTS, TEST_DEFAULTPROJECT_TEMPLATE_RESTRICTED_JSON_CONTENTS)
|
||||
]
|
||||
)
|
||||
def test_create_project(tmpdir,
|
||||
concrete_contents, templated_contents,
|
||||
keep_license_text, expect_failure,
|
||||
template_json_contents, restricted_template_json_contents):
|
||||
dev_root = str(tmpdir.join('dev').realpath()).replace('\\', '/')
|
||||
os.makedirs(dev_root, exist_ok=True)
|
||||
|
||||
template_default_folder = f'{dev_root}/Templates/DefaultProject'
|
||||
os.makedirs(template_default_folder, exist_ok=True)
|
||||
|
||||
template_json = f'{template_default_folder}/template.json'
|
||||
if os.path.isfile(template_json):
|
||||
os.unlink(template_json)
|
||||
with open(template_json, 'w') as s:
|
||||
s.write(template_json_contents)
|
||||
|
||||
default_name_bus_dir = f'{template_default_folder}/Template/Code/Include/' + '${Name}'
|
||||
os.makedirs(default_name_bus_dir, exist_ok=True)
|
||||
|
||||
default_name_bus_file = f'{default_name_bus_dir}/' + '${Name}Bus.h'
|
||||
if os.path.isfile(default_name_bus_file):
|
||||
os.unlink(default_name_bus_file)
|
||||
with open(default_name_bus_file, 'w') as s:
|
||||
s.write(templated_contents)
|
||||
|
||||
restricted_template_default_folder = f'{dev_root}/restricted/Salem/Templates/DefaultProject'
|
||||
os.makedirs(restricted_template_default_folder, exist_ok=True)
|
||||
|
||||
restricted_template_json = f'{restricted_template_default_folder}/template.json'
|
||||
if os.path.isfile(restricted_template_json):
|
||||
os.unlink(restricted_template_json)
|
||||
with open(restricted_template_json, 'w') as s:
|
||||
s.write(restricted_template_json_contents)
|
||||
|
||||
restricted_default_name_bus_dir = f'{restricted_template_default_folder}/Template/Code/Include/Platform/Salem'
|
||||
os.makedirs(restricted_default_name_bus_dir, exist_ok=True)
|
||||
|
||||
restricted_default_name_bus_file = f'{restricted_default_name_bus_dir}/' + '${Name}Bus.h'
|
||||
if os.path.isfile(restricted_default_name_bus_file):
|
||||
os.unlink(restricted_default_name_bus_file)
|
||||
with open(restricted_default_name_bus_file, 'w') as s:
|
||||
s.write(templated_contents)
|
||||
|
||||
result = engine_template.create_project(dev_root, 'TestProject', keep_license_text=keep_license_text)
|
||||
|
||||
if expect_failure:
|
||||
assert result != 0
|
||||
else:
|
||||
assert result == 0
|
||||
|
||||
test_project_folder = f'{dev_root}/TestProject'
|
||||
assert os.path.isdir(test_project_folder)
|
||||
|
||||
test_project_bus_file = f'{test_project_folder}/Code/Include/TestProject/TestProjectBus.h'
|
||||
assert os.path.isfile(test_project_bus_file)
|
||||
with open(test_project_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == concrete_contents
|
||||
|
||||
restricted_test_project_bus_folder = f'{dev_root}/restricted/Salem/TestProject/Code/Include/Platform/Salem'
|
||||
assert os.path.isdir(restricted_test_project_bus_folder)
|
||||
|
||||
restricted_default_name_bus_file = f'{restricted_test_project_bus_folder}/TestProjectBus.h'
|
||||
assert os.path.isfile(restricted_default_name_bus_file)
|
||||
with open(restricted_default_name_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == concrete_contents
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"concrete_contents, templated_contents,"
|
||||
" keep_license_text, expect_failure,"
|
||||
" template_json_contents, restricted_template_json_contents", [
|
||||
pytest.param(TEST_CONCRETE_TESTGEM_TEMPLATE_CONTENT_WITH_LICENSE, TEST_TEMPLATED_CONTENT_WITH_LICENSE,
|
||||
True, False,
|
||||
TEST_DEFAULTGEM_TEMPLATE_JSON_CONTENTS, TEST_DEFAULTGEM_TEMPLATE_RESTRICTED_JSON_CONTENTS),
|
||||
pytest.param(TEST_CONCRETE_TESTGEM_TEMPLATE_CONTENT_WITHOUT_LICENSE, TEST_TEMPLATED_CONTENT_WITH_LICENSE,
|
||||
False, False,
|
||||
TEST_DEFAULTGEM_TEMPLATE_JSON_CONTENTS, TEST_DEFAULTGEM_TEMPLATE_RESTRICTED_JSON_CONTENTS)
|
||||
]
|
||||
)
|
||||
def test_create_gem(tmpdir,
|
||||
concrete_contents, templated_contents,
|
||||
keep_license_text, expect_failure,
|
||||
template_json_contents, restricted_template_json_contents):
|
||||
dev_root = str(tmpdir.join('dev').realpath()).replace('\\', '/')
|
||||
os.makedirs(dev_root, exist_ok=True)
|
||||
|
||||
template_default_folder = f'{dev_root}/Templates/DefaultGem'
|
||||
os.makedirs(template_default_folder, exist_ok=True)
|
||||
|
||||
template_json = f'{template_default_folder}/template.json'
|
||||
if os.path.isfile(template_json):
|
||||
os.unlink(template_json)
|
||||
with open(template_json, 'w') as s:
|
||||
s.write(template_json_contents)
|
||||
|
||||
default_name_bus_dir = f'{template_default_folder}/Template/Code/Include/' + '${Name}'
|
||||
os.makedirs(default_name_bus_dir, exist_ok=True)
|
||||
|
||||
default_name_bus_file = f'{default_name_bus_dir}/' + '${Name}Bus.h'
|
||||
if os.path.isfile(default_name_bus_file):
|
||||
os.unlink(default_name_bus_file)
|
||||
with open(default_name_bus_file, 'w') as s:
|
||||
s.write(templated_contents)
|
||||
|
||||
restricted_template_default_folder = f'{dev_root}/restricted/Salem/Templates/DefaultGem'
|
||||
os.makedirs(restricted_template_default_folder, exist_ok=True)
|
||||
|
||||
restricted_template_json = f'{restricted_template_default_folder}/template.json'
|
||||
if os.path.isfile(restricted_template_json):
|
||||
os.unlink(restricted_template_json)
|
||||
with open(restricted_template_json, 'w') as s:
|
||||
s.write(restricted_template_json_contents)
|
||||
|
||||
restricted_default_name_bus_dir = f'{restricted_template_default_folder}/Template/Code/Include/Platform/Salem'
|
||||
os.makedirs(restricted_default_name_bus_dir, exist_ok=True)
|
||||
|
||||
restricted_default_name_bus_file = f'{restricted_default_name_bus_dir}/' + '${Name}Bus.h'
|
||||
if os.path.isfile(restricted_default_name_bus_file):
|
||||
os.unlink(restricted_default_name_bus_file)
|
||||
with open(restricted_default_name_bus_file, 'w') as s:
|
||||
s.write(templated_contents)
|
||||
|
||||
result = engine_template.create_gem(dev_root, 'TestGem', keep_license_text=keep_license_text)
|
||||
|
||||
if expect_failure:
|
||||
assert result != 0
|
||||
else:
|
||||
assert result == 0
|
||||
|
||||
test_gem_folder = f'{dev_root}/Gems/TestGem'
|
||||
assert os.path.isdir(test_gem_folder)
|
||||
|
||||
test_gem_bus_file = f'{test_gem_folder}/Code/Include/TestGem/TestGemBus.h'
|
||||
assert os.path.isfile(test_gem_bus_file)
|
||||
with open(test_gem_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == concrete_contents
|
||||
|
||||
restricted_test_gem_bus_folder = f'{dev_root}/restricted/Salem/Gems/TestGem/Code/Include/Platform/Salem'
|
||||
assert os.path.isdir(restricted_test_gem_bus_folder)
|
||||
|
||||
restricted_default_name_bus_file = f'{restricted_test_gem_bus_folder}/TestGemBus.h'
|
||||
assert os.path.isfile(restricted_default_name_bus_file)
|
||||
with open(restricted_default_name_bus_file, 'r') as s:
|
||||
s_data = s.read()
|
||||
assert s_data == concrete_contents
|
||||
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# 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 io
|
||||
import json
|
||||
import logging
|
||||
import pytest
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from o3de import global_project
|
||||
|
||||
|
||||
logger = logging.getLogger()
|
||||
logging.basicConfig()
|
||||
|
||||
DEFAULT_BOOTSTRAP_SETREG = pathlib.Path('~/.o3de/Registry/bootstrap.setreg').expanduser()
|
||||
PROJECT_PATH_KEY = ('Amazon', 'AzCore', 'Bootstrap', 'project_path')
|
||||
|
||||
class TestSetGlobalProject:
|
||||
@pytest.mark.parametrize(
|
||||
"output_path, project_path, force, expected_result", [
|
||||
pytest.param(pathlib.Path('~/.o3de/Registry/bootstrap.setreg'), pathlib.Path('A:/'), False, False),
|
||||
pytest.param(pathlib.Path('~/.o3de/Registry/bootstrap.setreg'), pathlib.Path('A:/'), True, True)
|
||||
]
|
||||
)
|
||||
def test_set_global_project_non_existent_project_path(self, output_path, project_path, force, expected_result):
|
||||
with patch('pathlib.Path.open', return_value=io.StringIO()) as pathlib_open_mock:
|
||||
result = global_project.set_global_project(output_path, project_path=project_path, force=force) == 0
|
||||
|
||||
|
||||
assert result == expected_result
|
||||
@@ -0,0 +1,117 @@
|
||||
#
|
||||
# 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 argparse
|
||||
import json
|
||||
import logging
|
||||
import pytest
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from o3de import register
|
||||
|
||||
string_manifest_data = '{}'
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"engine_path, engine_name, force, expected_result", [
|
||||
pytest.param(pathlib.PurePath('D:/o3de/o3de'), "o3de", False, 0),
|
||||
# Same engine_name and path should result in valid registration
|
||||
pytest.param(pathlib.PurePath('D:/o3de/o3de'), "o3de", False, 0),
|
||||
# Same engine_name and but different path should fail
|
||||
pytest.param(pathlib.PurePath('D:/o3de/engine-path'), "o3de", False, 1),
|
||||
# New engine_name should result in valid registration
|
||||
pytest.param(pathlib.PurePath('D:/o3de/engine-path'), "o3de-other", False, 0),
|
||||
# Same engine_name and but different path with --force should result in valid registration
|
||||
pytest.param(pathlib.PurePath('F:/Open3DEngine'), "o3de", True, 0),
|
||||
]
|
||||
)
|
||||
def test_register_engine_path(engine_path, engine_name, force, expected_result):
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
# Register the registration script subparsers with the current argument parser
|
||||
register.add_parser_args(parser)
|
||||
arg_list = ['--engine-path', str(engine_path)]
|
||||
if force:
|
||||
arg_list += ['--force']
|
||||
args = parser.parse_args(arg_list)
|
||||
|
||||
def load_manifest_from_string() -> dict:
|
||||
try:
|
||||
manifest_json = json.loads(string_manifest_data)
|
||||
except json.JSONDecodeError as err:
|
||||
logging.error("Error decoding Json from Manifest file")
|
||||
else:
|
||||
return manifest_json
|
||||
def save_manifest_to_string(manifest_json: dict) -> None:
|
||||
global string_manifest_data
|
||||
string_manifest_data = json.dumps(manifest_json)
|
||||
|
||||
engine_json_data = {'engine_name': engine_name}
|
||||
with patch('o3de.manifest.load_o3de_manifest', side_effect=load_manifest_from_string) as load_manifest_mock, \
|
||||
patch('o3de.manifest.save_o3de_manifest', side_effect=save_manifest_to_string) as save_manifest_mock, \
|
||||
patch('o3de.manifest.get_engine_json_data', return_value=engine_json_data) as engine_paths_mock, \
|
||||
patch('o3de.validation.valid_o3de_engine_json', return_value=True) as valid_engine_mock, \
|
||||
patch('pathlib.Path.is_dir', return_value=True) as pathlib_is_dir_mock:
|
||||
result = register._run_register(args)
|
||||
assert result == expected_result
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def init_manifest_data(request):
|
||||
class ManifestData:
|
||||
def __init__(self):
|
||||
self.json_string = json.dumps({'default_engines_folder': '',
|
||||
'default_projects_folder': '', 'default_gems_folder': '',
|
||||
'default_templates_folder': '', 'default_restricted_folder': ''})
|
||||
|
||||
request.cls.manifest_data = ManifestData()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('init_manifest_data')
|
||||
class TestRegisterThisEngine:
|
||||
@pytest.mark.parametrize(
|
||||
"engine_path, engine_name, force, expected_result", [
|
||||
pytest.param(pathlib.PurePath('D:/o3de/o3de'), "o3de", False, 0),
|
||||
pytest.param(pathlib.PurePath('F:/Open3DEngine'), "o3de", False, 1),
|
||||
pytest.param(pathlib.PurePath('F:/Open3DEngine'), "o3de", True, 0)
|
||||
]
|
||||
)
|
||||
def test_register_this_engine(self, engine_path, engine_name, force, expected_result):
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
# Register the registration script subparsers with the current argument parser
|
||||
register.add_parser_args(parser)
|
||||
arg_list = ['--this-engine']
|
||||
if force:
|
||||
arg_list += ['--force']
|
||||
args = parser.parse_args(arg_list)
|
||||
|
||||
def load_manifest_from_string() -> dict:
|
||||
try:
|
||||
manifest_json = json.loads(self.manifest_data.json_string)
|
||||
except json.JSONDecodeError as err:
|
||||
logging.error("Error decoding Json from Manifest file")
|
||||
else:
|
||||
return manifest_json
|
||||
def save_manifest_to_string(manifest_json: dict) -> None:
|
||||
self.manifest_data.json_string = json.dumps(manifest_json)
|
||||
|
||||
engine_json_data = {'engine_name': engine_name}
|
||||
|
||||
with patch('o3de.manifest.load_o3de_manifest', side_effect=load_manifest_from_string) as load_manifest_mock, \
|
||||
patch('o3de.manifest.save_o3de_manifest', side_effect=save_manifest_to_string) as save_manifest_mock, \
|
||||
patch('o3de.manifest.get_engine_json_data', return_value=engine_json_data) as engine_paths_mock, \
|
||||
patch('o3de.manifest.get_this_engine_path', return_value=engine_path) as engine_paths_mock, \
|
||||
patch('o3de.validation.valid_o3de_engine_json', return_value=True) as valid_engine_mock, \
|
||||
patch('pathlib.Path.is_dir', return_value=True) as pathlib_is_dir_mock:
|
||||
result = register._run_register(args)
|
||||
assert result == expected_result
|
||||
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# 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 pytest
|
||||
|
||||
from . import utils
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, expected_result", [
|
||||
pytest.param('Game1', True),
|
||||
pytest.param('0Game1', False),
|
||||
pytest.param('the/Game1', False),
|
||||
pytest.param('', False),
|
||||
pytest.param('-test', False),
|
||||
pytest.param('test-', True),
|
||||
]
|
||||
)
|
||||
def test_validate_identifier(value, expected_result):
|
||||
result = utils.validate_identifier(value)
|
||||
assert result == expected_result
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, expected_result", [
|
||||
pytest.param('{018427ae-cd08-4ff1-ad3b-9b95256c17ca}', False),
|
||||
pytest.param('', False),
|
||||
pytest.param('{018427aecd084ff1ad3b9b95256c17ca}', False),
|
||||
pytest.param('018427ae-cd08-4ff1-ad3b-9b95256c17ca', True),
|
||||
pytest.param('018427aecd084ff1ad3b9b95256c17ca', False),
|
||||
pytest.param('018427aecd084ff1ad3b9', False),
|
||||
]
|
||||
)
|
||||
def test_validate_uuid4(value, expected_result):
|
||||
result = utils.validate_uuid4(value)
|
||||
assert result == expected_result
|
||||
+532
-386
File diff suppressed because it is too large
Load Diff
@@ -9,54 +9,67 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
|
||||
import pytest
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import logging
|
||||
import pathlib
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
# Code lives one folder above
|
||||
projects_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(projects_path)
|
||||
project_manager_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(project_manager_path)
|
||||
|
||||
from pyside import add_pyside_environment, is_configuration_valid
|
||||
from ly_test_tools import WINDOWS
|
||||
|
||||
project_marker_file = "project.json"
|
||||
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..', '..')))
|
||||
executable_path = ''
|
||||
from cmake.Tools import registration
|
||||
from cmake.Tools import engine_template
|
||||
|
||||
|
||||
class ProjectHelper:
|
||||
def __init__(self):
|
||||
self._temp_directory = tempfile.TemporaryDirectory()
|
||||
self.temp_project_root = self._temp_directory.name
|
||||
self.temp_file_dir = os.path.join(self.temp_project_root, "o3de")
|
||||
self._temp_directory = pathlib.Path(tempfile.TemporaryDirectory().name).resolve()
|
||||
self._temp_directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
self.home_path = self._temp_directory
|
||||
registration.override_home_folder = self.home_path
|
||||
self.engine_path = registration.get_this_engine_path()
|
||||
if registration.register(engine_path=self.engine_path):
|
||||
assert True, f"Failed to register the engine."
|
||||
|
||||
if registration.register_shipped_engine_o3de_objects():
|
||||
assert True, f"Failed to register shipped engine objects."
|
||||
|
||||
self.projects_folder = registration.get_o3de_projects_folder()
|
||||
if not self.projects_folder.is_dir():
|
||||
assert True
|
||||
|
||||
self.application = None
|
||||
self.dialog = None
|
||||
|
||||
if not os.path.exists(self.temp_file_dir):
|
||||
os.makedirs(self.temp_file_dir)
|
||||
|
||||
def create_empty_projects(self):
|
||||
self.project_1_dir = os.path.join(self.temp_project_root, "Project1")
|
||||
if not os.path.exists(self.project_1_dir):
|
||||
os.makedirs(self.project_1_dir)
|
||||
with open(os.path.join(self.project_1_dir,project_marker_file), 'w') as marker_file:
|
||||
marker_file.write("{}")
|
||||
self.project_2_dir = os.path.join(self.temp_project_root, "Project2")
|
||||
if not os.path.exists(self.project_2_dir):
|
||||
os.makedirs(self.project_2_dir)
|
||||
with open(os.path.join(self.project_2_dir, project_marker_file), 'w') as marker_file:
|
||||
marker_file.write("{}")
|
||||
self.project_3_dir = os.path.join(self.temp_project_root, "Project3")
|
||||
if not os.path.exists(self.project_3_dir):
|
||||
os.makedirs(self.project_3_dir)
|
||||
with open(os.path.join(self.project_3_dir, project_marker_file), 'w') as marker_file:
|
||||
marker_file.write("{}")
|
||||
self.invalid_project_dir = os.path.join(self.temp_project_root, "InvalidProject")
|
||||
self.project_1_dir = self.projects_folder / "Project1"
|
||||
if engine_template.create_project(project_manager_path=self.project_1_dir):
|
||||
assert True, f"Failed to create Project1."
|
||||
|
||||
self.project_2_dir = self.projects_folder / "Project2"
|
||||
if engine_template.create_project(project_manager_path=self.project_2_dir):
|
||||
assert True, f"Failed to create Project2."
|
||||
|
||||
self.project_3_dir = self.projects_folder / "Project3"
|
||||
if engine_template.create_project(project_manager_path=self.project_3_dir):
|
||||
assert True, f"Failed to create Project3."
|
||||
|
||||
self.invalid_project_dir = self.projects_folder / "InvalidProject"
|
||||
self.invalid_project_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def setup_dialog_test(self, workspace):
|
||||
add_pyside_environment(workspace.paths.build_directory())
|
||||
@@ -66,6 +79,7 @@ class ProjectHelper:
|
||||
# need to use the profile version of PySide which works with the profile QT libs which aren't in the debug
|
||||
# folder we've built.
|
||||
return None
|
||||
|
||||
from PySide2.QtWidgets import QApplication, QMessageBox
|
||||
|
||||
if QApplication.instance():
|
||||
@@ -74,13 +88,13 @@ class ProjectHelper:
|
||||
self.application = QApplication(sys.argv)
|
||||
assert self.application
|
||||
|
||||
from projects import ProjectDialog
|
||||
from projects import ProjectManagerDialog
|
||||
|
||||
try:
|
||||
self.dialog = ProjectDialog(settings_folder=self.temp_file_dir)
|
||||
self.dialog = ProjectManagerDialog(settings_folder=self.home_path)
|
||||
return self.dialog
|
||||
except Exception as e:
|
||||
logger.error(f'Failed to create ProjectDialog with error {e}')
|
||||
logger.error(f'Failed to create ProjectManagerDialog with error {e}')
|
||||
return None
|
||||
|
||||
def create_project_from_template(self, project_name) -> bool:
|
||||
@@ -90,21 +104,24 @@ class ProjectHelper:
|
||||
:return: True for Success, False for failure
|
||||
"""
|
||||
from PySide2.QtWidgets import QWidget, QFileDialog
|
||||
from projects import ProjectDialog
|
||||
from projects import ProjectManagerDialog
|
||||
|
||||
QWidget.exec = MagicMock()
|
||||
self.dialog.create_project_handler()
|
||||
QWidget.exec.assert_called_once()
|
||||
|
||||
assert len(self.dialog.project_templates), 'Failed to find any project templates'
|
||||
ProjectDialog.get_selected_project_template = MagicMock(return_value=self.dialog.project_templates[0])
|
||||
ProjectManagerDialog.get_selected_project_template = MagicMock(return_value=self.dialog.project_templates[0])
|
||||
|
||||
QFileDialog.exec = MagicMock()
|
||||
create_project_dir = os.path.join(self.temp_project_root, project_name)
|
||||
QFileDialog.selectedFiles = MagicMock(return_value=[create_project_dir])
|
||||
create_project_path = self.projects_folder / project_name
|
||||
QFileDialog.selectedFiles = MagicMock(return_value=[create_project_path])
|
||||
self.dialog.create_project_accepted_handler()
|
||||
assert os.path.isdir(create_project_dir), f"Expected project folder not found at {create_project_dir}"
|
||||
assert QWidget.exec.call_count == 2, "Message box confirming project creation failed to show"
|
||||
if create_project_path.is_dir():
|
||||
assert True, f"Expected project creation folder not found at {create_project_path}"
|
||||
|
||||
if QWidget.exec.call_count == 2:
|
||||
assert True, "Message box confirming project creation failed to show"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -113,7 +130,7 @@ def project_helper():
|
||||
|
||||
|
||||
@pytest.mark.skipif(not WINDOWS, reason="PySide2 only works on windows currently")
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
def test_logger_handler(workspace, project_helper):
|
||||
my_dialog = project_helper.setup_dialog_test(workspace)
|
||||
if not my_dialog:
|
||||
@@ -126,7 +143,7 @@ def test_logger_handler(workspace, project_helper):
|
||||
|
||||
|
||||
@pytest.mark.skipif(not WINDOWS, reason="PySide2 only works on windows currently")
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
def test_mru_list(workspace, project_helper):
|
||||
my_dialog = project_helper.setup_dialog_test(workspace)
|
||||
if not my_dialog:
|
||||
@@ -140,16 +157,16 @@ def test_mru_list(workspace, project_helper):
|
||||
assert len(mru_list) == 0, f'MRU list unexpectedly had entries: {mru_list}'
|
||||
|
||||
QMessageBox.warning = MagicMock()
|
||||
my_dialog.add_new_project('TestProjectInvalid')
|
||||
my_dialog.add_project(project_helper.invalid_project_dir)
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 0, f'MRU list unexpectedly added an invalid project : {mru_list}'
|
||||
QMessageBox.warning.assert_called_once()
|
||||
|
||||
my_dialog.add_new_project(project_helper.project_1_dir)
|
||||
my_dialog.add_project(project_helper.project_1_dir)
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 1, f'MRU list failed to add project at {project_helper.project_1_dir}'
|
||||
|
||||
my_dialog.add_new_project(project_helper.project_1_dir)
|
||||
my_dialog.add_project(project_helper.project_1_dir)
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 1, f'MRU list added project at {project_helper.project_1_dir} a second time : {mru_list}'
|
||||
|
||||
@@ -157,7 +174,7 @@ def test_mru_list(workspace, project_helper):
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 1, f'MRU list added project at {project_helper.project_1_dir} a second time : {mru_list}'
|
||||
|
||||
my_dialog.add_new_project(project_helper.project_2_dir)
|
||||
my_dialog.add_project(project_helper.project_2_dir)
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 2, f'MRU list failed to add project at {project_helper.project_2_dir}'
|
||||
|
||||
@@ -170,13 +187,13 @@ def test_mru_list(workspace, project_helper):
|
||||
assert mru_list[0] == project_helper.project_1_dir, f"{project_helper.project_1_dir} wasn't first item"
|
||||
assert mru_list[1] == project_helper.project_2_dir, f"{project_helper.project_2_dir} wasn't second item"
|
||||
|
||||
my_dialog.add_new_project(project_helper.invalid_project_dir)
|
||||
my_dialog.add_project(project_helper.invalid_project_dir)
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 2, f'MRU list added invalid item {mru_list}'
|
||||
assert mru_list[0] == project_helper.project_1_dir, f"{project_helper.project_1_dir} wasn't first item"
|
||||
assert mru_list[1] == project_helper.project_2_dir, f"{project_helper.project_2_dir} wasn't second item"
|
||||
|
||||
my_dialog.add_new_project(project_helper.project_3_dir)
|
||||
my_dialog.add_project(project_helper.project_3_dir)
|
||||
mru_list = my_dialog.get_mru_list()
|
||||
assert len(mru_list) == 3, f'MRU list failed to add {project_helper.project_3_dir} : {mru_list}'
|
||||
assert mru_list[0] == project_helper.project_3_dir, f"{project_helper.project_3_dir} wasn't first item"
|
||||
@@ -185,7 +202,7 @@ def test_mru_list(workspace, project_helper):
|
||||
|
||||
|
||||
@pytest.mark.skipif(not WINDOWS, reason="PySide2 only works on windows currently")
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
def test_create_project(workspace, project_helper):
|
||||
my_dialog = project_helper.setup_dialog_test(workspace)
|
||||
if not my_dialog:
|
||||
@@ -195,7 +212,7 @@ def test_create_project(workspace, project_helper):
|
||||
|
||||
|
||||
@pytest.mark.skipif(not WINDOWS, reason="PySide2 only works on windows currently")
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
@pytest.mark.parametrize('project', ['']) # Workspace wants a project, but this test is not project dependent
|
||||
def test_add_remove_gems(workspace, project_helper):
|
||||
my_dialog = project_helper.setup_dialog_test(workspace)
|
||||
if not my_dialog:
|
||||
@@ -203,32 +220,36 @@ def test_add_remove_gems(workspace, project_helper):
|
||||
|
||||
my_project_name = "TestAddRemoveGems"
|
||||
|
||||
project_helper.create_project_from_template(my_project_name)
|
||||
my_project_path = os.path.join(project_helper.temp_project_root, my_project_name)
|
||||
project_helper.create_project_from_template(project_manager_path=my_project_name)
|
||||
my_project_path = project_helper.projects_folder / my_project_name
|
||||
|
||||
from PySide2.QtWidgets import QWidget, QFileDialog
|
||||
from projects import ProjectDialog
|
||||
from projects import ProjectManagerDialog
|
||||
|
||||
assert my_dialog.path_for_selection() == my_project_path, "Gems project not selected"
|
||||
assert my_dialog.get_selected_project_path() == my_project_path, "TestAddRemoveGems project not selected"
|
||||
QWidget.exec = MagicMock()
|
||||
my_dialog.manage_gems_handler()
|
||||
assert my_dialog.manage_gems_dialog, "No gem management dialog created"
|
||||
assert my_dialog.manage_gem_targets_dialog, "No gem management dialog created"
|
||||
QWidget.exec.assert_called_once()
|
||||
|
||||
assert len(my_dialog.gems_list), 'Failed to find any gems'
|
||||
my_test_gem = my_dialog.gems_list[0]
|
||||
my_test_gem_name = my_test_gem.get("Name")
|
||||
my_test_gem_path = my_test_gem.get("Path")
|
||||
my_test_gem_selection = (my_test_gem_name, my_test_gem_path)
|
||||
ProjectDialog.get_selected_add_gems = MagicMock(return_value=[my_test_gem_selection])
|
||||
if not len(my_dialog.all_gems_list):
|
||||
assert True, 'Failed to find any gems'
|
||||
|
||||
my_test_gem_path = my_dialog.all_gems_list[0]
|
||||
gem_data = registration.get_gem_data(my_test_gem_path)
|
||||
my_test_gem_selection = (my_test_gem_name, my_test_gem_path)
|
||||
ProjectManagerDialog.get_selected_add_gems = MagicMock(return_value=[my_test_gem_selection])
|
||||
|
||||
assert my_test_gem_name, "No Name set in test gem"
|
||||
assert my_test_gem_name not in my_dialog.project_gem_list, f'Gem {my_test_gem_name} already in project gem list'
|
||||
|
||||
my_dialog.add_gems_handler()
|
||||
assert my_test_gem_name in my_dialog.project_gem_list, f'Gem {my_test_gem_name} failed to add to gem list'
|
||||
ProjectDialog.get_selected_project_gems = MagicMock(return_value=[my_test_gem_name])
|
||||
|
||||
ProjectManagerDialog.get_selected_project_gems = MagicMock(return_value=[my_test_gem_name])
|
||||
my_dialog.remove_gems_handler()
|
||||
assert my_test_gem_name not in my_dialog.project_gem_list, f'Gem {my_test_gem_name} still in project gem list'
|
||||
'''
|
||||
|
||||
|
||||
def test_project_place_holder():
|
||||
pass
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>createFromTemplateDialog</class>
|
||||
<widget class="QDialog" name="createFromTemplateDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>467</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create From Template</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="okCancel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>250</y>
|
||||
<width>400</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QListView" name="genericTemplates">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>449</width>
|
||||
<height>221</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Available Templates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>createFromTemplateDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>createFromTemplateDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>createGemDialog</class>
|
||||
<widget class="QDialog" name="createGemDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>467</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create Gem</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="okCancel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>250</y>
|
||||
<width>400</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QListView" name="gemTemplates">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>449</width>
|
||||
<height>221</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Available Templates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>createGemDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>createGemDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>226</width>
|
||||
<width>467</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -18,7 +18,7 @@
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>250</y>
|
||||
<width>171</width>
|
||||
<width>400</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -34,7 +34,7 @@
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>211</width>
|
||||
<width>449</width>
|
||||
<height>221</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -47,7 +47,7 @@
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>101</width>
|
||||
<width>300</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
+29
-29
@@ -1,24 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>addGemsDialog</class>
|
||||
<widget class="QDialog" name="addGemsDialog">
|
||||
<class>manageGemTargetsDialog</class>
|
||||
<widget class="QDialog" name="manageGemTargetsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>635</width>
|
||||
<height>327</height>
|
||||
<width>702</width>
|
||||
<height>297</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manage Gems</string>
|
||||
<string>Manage Gem Targets</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="close">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>460</x>
|
||||
<y>290</y>
|
||||
<width>171</width>
|
||||
<x>310</x>
|
||||
<y>260</y>
|
||||
<width>71</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -29,10 +29,10 @@
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QListView" name="addGemsList">
|
||||
<widget class="QListView" name="availableGemTargetsList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>380</x>
|
||||
<x>440</x>
|
||||
<y>50</y>
|
||||
<width>250</width>
|
||||
<height>221</height>
|
||||
@@ -48,7 +48,7 @@
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QListView" name="projectGems">
|
||||
<widget class="QListView" name="enabledGemTargetsList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
@@ -64,14 +64,14 @@
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>380</x>
|
||||
<x>440</x>
|
||||
<y>30</y>
|
||||
<width>91</width>
|
||||
<width>251</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Available Gems</string>
|
||||
<string>Available Gem Targets</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
@@ -79,38 +79,38 @@
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>71</width>
|
||||
<width>251</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enabled Gems</string>
|
||||
<string>Enabled Gem Targets</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="removeGemsButton">
|
||||
<widget class="QPushButton" name="removeGemTargetsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>267</x>
|
||||
<x>264</x>
|
||||
<y>130</y>
|
||||
<width>105</width>
|
||||
<width>171</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Gems >></string>
|
||||
<string>Remove Gem Targets >></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="addGemsButton">
|
||||
<widget class="QPushButton" name="addGemTargetsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>267</x>
|
||||
<x>264</x>
|
||||
<y>100</y>
|
||||
<width>105</width>
|
||||
<width>171</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><< Add Gems</string>
|
||||
<string><< Add Gem Targets</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
@@ -118,12 +118,12 @@
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>5</y>
|
||||
<width>241</width>
|
||||
<height>16</height>
|
||||
<width>400</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Adding new Gems may require rebuilding</string>
|
||||
<string>Adding new Gem Targets may require rebuilding</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
@@ -132,7 +132,7 @@
|
||||
<connection>
|
||||
<sender>close</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>addGemsDialog</receiver>
|
||||
<receiver>manageGemTargetsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@@ -148,7 +148,7 @@
|
||||
<connection>
|
||||
<sender>close</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>addGemsDialog</receiver>
|
||||
<receiver>manageGemTargetsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@@ -0,0 +1,407 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>712</width>
|
||||
<height>395</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>O3DE</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Select and manage your projects for O3DE</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="okCancel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>540</x>
|
||||
<y>360</y>
|
||||
<width>161</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="projectListBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>691</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Current project to launch or manage gems for.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>47</width>
|
||||
<height>13</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="logDisplay">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>270</x>
|
||||
<y>220</y>
|
||||
<width>431</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="createGroupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>70</y>
|
||||
<width>241</width>
|
||||
<height>151</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Create</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="createFromTemplateButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>110</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Create a new O3DE object from a pre configured template.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create From Template</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="createProjectButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Create a new O3DE object from a pre configured template.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="createGemButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>11</x>
|
||||
<y>50</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Create a new O3DE object from a pre configured template.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Gem</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="createTemplateButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>11</x>
|
||||
<y>80</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Create a new O3DE object from a pre configured template.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Template</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="addRemoveGroupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>70</y>
|
||||
<width>451</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Registration</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="addTemplateButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>80</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Template</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="addProjectButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="addGemButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Gem</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="addRestrictedButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>110</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Restricted</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="removeRestrictedButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>230</x>
|
||||
<y>110</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Restricted</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="removeProjectButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>230</x>
|
||||
<y>20</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="removeGemButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>230</x>
|
||||
<y>50</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Gem</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="removeTemplateButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>230</x>
|
||||
<y>80</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Template</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="manageProjectGroupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>230</y>
|
||||
<width>241</width>
|
||||
<height>121</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Manage Project</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="manageServerGemTargetsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>80</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Add or remove gems from your selected project. Gems add and remove additional assets and features to projects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manage Server Gem Targets</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="manageToolGemTargetsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Add or remove gems from your selected project. Gems add and remove additional assets and features to projects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manage Tool Gem Targets</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="manageRuntimeGemTargetsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>221</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Add or remove gems from your selected project. Gems add and remove additional assets and features to projects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manage Runtime Gem Targets</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,167 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>464</width>
|
||||
<height>136</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>O3DE</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Select and manage your projects for O3DE</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="okCancel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>290</x>
|
||||
<y>100</y>
|
||||
<width>171</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="projectListBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>451</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Current project to launch or manage gems for.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="createProjectButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>70</y>
|
||||
<width>91</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Create a new O3DE project from a pre configured template.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create New</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>47</width>
|
||||
<height>13</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="browseProjectsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>70</y>
|
||||
<width>91</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Browse for an existing O3DE project.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="manageGemsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>350</x>
|
||||
<y>70</y>
|
||||
<width>91</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Add or remove gems from your selected project. Gems add and remove additional assets and features to projects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Manage Gems</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="logDisplay">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>110</y>
|
||||
<width>275</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>okCancel</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -243,7 +243,7 @@ class Validator(object):
|
||||
validations += 1
|
||||
counter += 1
|
||||
|
||||
# Trim out whitelisted subdirectories in the current directory if allowed
|
||||
# Trim out allowlisted subdirectories in the current directory if allowed
|
||||
for name in bypassed_directories:
|
||||
if name in dirnames:
|
||||
dirnames.remove(name)
|
||||
|
||||
Reference in New Issue
Block a user