From e8db765361dca69be6a347f52b58d40e09d09f83 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Fri, 20 Oct 2023 19:31:08 +0300 Subject: [PATCH] [Export] Use auto-increment build number in export versions. --- core/config/project_settings.cpp | 1 + doc/classes/ProjectSettings.xml | 3 +++ drivers/vulkan/vulkan_context.cpp | 2 +- editor/editor_node.cpp | 7 +++++++ editor/export/editor_export_preset.cpp | 20 +++++++++++++++---- editor/export/editor_export_preset.h | 1 + editor/export/project_export.cpp | 17 ++++++++++++++++ .../EditorExportPlatformAndroid.xml | 2 +- platform/android/export/export_plugin.cpp | 12 +++++------ platform/ios/export/export_plugin.cpp | 4 ++-- platform/macos/export/export_plugin.cpp | 4 ++-- platform/windows/export/export_plugin.cpp | 4 ++-- 12 files changed, 59 insertions(+), 18 deletions(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 93934f23205a..31260946ad76 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1299,6 +1299,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF_BASIC(PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()); GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT), ""); GLOBAL_DEF_BASIC("application/config/version", ""); + GLOBAL_DEF_BASIC("application/config/build", 1); GLOBAL_DEF_INTERNAL(PropertyInfo(Variant::STRING, "application/config/tags"), PackedStringArray()); GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res"), ""); GLOBAL_DEF("application/run/disable_stdout", false); diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 3fc9e94427ec..627ec5c2f14e 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -261,6 +261,9 @@ If [code]true[/code], the application automatically accepts quitting requests. + + The project's machine-readable build number. This value is automatically incremented on successful project export. + This user directory is used for storing persistent data ([code]user://[/code] filesystem). If a custom directory name is defined, this name will be appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]). The [member application/config/use_custom_user_dir] setting must be enabled for this to take effect. diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 7a397a170de6..e1a102dc5a90 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -1028,7 +1028,7 @@ Error VulkanContext::_create_instance() { /*sType*/ VK_STRUCTURE_TYPE_APPLICATION_INFO, /*pNext*/ nullptr, /*pApplicationName*/ cs.get_data(), - /*applicationVersion*/ 0, // It would be really nice if we store a version number in project settings, say "application/config/version" + /*applicationVersion*/ GLOBAL_GET("application/config/build").operator uint32_t(), /*pEngineName*/ VERSION_NAME, /*engineVersion*/ VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH), /*apiVersion*/ application_api_version diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b2a65063a767..8ffa291f0703 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -979,7 +979,14 @@ void EditorNode::_fs_changed() { err = missing_templates ? ERR_FILE_NOT_FOUND : ERR_UNCONFIGURED; } else { platform->clear_messages(); + uint32_t old_build_nr = ProjectSettings::get_singleton()->get_setting("application/config/build"); + ProjectSettings::get_singleton()->set_setting("application/config/build", old_build_nr + 1); /// Increase build number. err = platform->export_project(export_preset, export_defer.debug, export_path); + if (err == OK) { + ProjectSettings::get_singleton()->save(); + } else { + ProjectSettings::get_singleton()->set_setting("application/config/build", old_build_nr); // Reset build number. + } } } if (err != OK) { diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index b941170b7bc0..4be94f4f9eba 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -344,10 +344,22 @@ _FORCE_INLINE_ bool _check_digits(const String &p_str) { return true; } +String EditorExportPreset::get_build_nr(const StringName &p_preset_string) const { + String result = get(p_preset_string); + if (result.is_empty()) { + result = GLOBAL_GET("application/config/build"); + if (result.is_empty()) { + result = "1"; + } + } + return result; +} + String EditorExportPreset::get_version(const StringName &p_preset_string, bool p_windows_version) const { String result = get(p_preset_string); if (result.is_empty()) { result = GLOBAL_GET("application/config/version"); + String build_nr = GLOBAL_GET("application/config/build"); // Split and validate version number components. const PackedStringArray result_split = result.split(".", false); @@ -363,11 +375,11 @@ String EditorExportPreset::get_version(const StringName &p_preset_string, bool p if (p_windows_version) { // Modify version number to match Windows constraints (version numbers must have 4 components). if (result_split.size() == 1) { - result = result + ".0.0.0"; + result = result + ".0.0." + build_nr; } else if (result_split.size() == 2) { - result = result + ".0.0"; + result = result + ".0." + build_nr; } else if (result_split.size() == 3) { - result = result + ".0"; + result = result + "." + build_nr; } else { result = vformat("%s.%s.%s.%s", result_split[0], result_split[1], result_split[2], result_split[3]); } @@ -379,7 +391,7 @@ String EditorExportPreset::get_version(const StringName &p_preset_string, bool p WARN_PRINT(vformat("Invalid version number \"%s\". The version number can only contain numeric characters (0-9) and non-consecutive periods (.).", result)); } if (p_windows_version) { - result = "1.0.0.0"; + result = "1.0.0." + build_nr; } else { result = "1.0.0"; } diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h index 025e7603f346..9c484ce42527 100644 --- a/editor/export/editor_export_preset.h +++ b/editor/export/editor_export_preset.h @@ -160,6 +160,7 @@ class EditorExportPreset : public RefCounted { // be compatible with Windows executable metadata (which requires a // 4-component format). String get_version(const StringName &p_name, bool p_windows_version = false) const; + String get_build_nr(const StringName &p_name) const; const HashMap &get_properties() const { return properties; } const HashMap &get_values() const { return values; } diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 719c3114f4b9..099d921f09c9 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -1084,7 +1084,13 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { exporting = true; platform->clear_messages(); + + uint32_t old_build_nr = ProjectSettings::get_singleton()->get_setting("application/config/build"); + ProjectSettings::get_singleton()->set_setting("application/config/build", old_build_nr + 1); // Increase build number. Error err = platform->export_project(current, export_debug->is_pressed(), current->get_export_path(), 0); + if (err != OK) { + ProjectSettings::get_singleton()->set_setting("application/config/build", old_build_nr); // Reset build number. + } result_dialog_log->clear(); if (err != ERR_SKIP) { if (platform->fill_log_messages(result_dialog_log, err)) { @@ -1114,7 +1120,11 @@ void ProjectExportDialog::_export_all(bool p_debug) { exporting = true; + uint32_t old_build_nr = ProjectSettings::get_singleton()->get_setting("application/config/build"); + ProjectSettings::get_singleton()->set_setting("application/config/build", old_build_nr + 1); // Increase build number. + bool show_dialog = false; + bool all_exports_fail = true; result_dialog_log->clear(); for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) { Ref preset = EditorExport::get_singleton()->get_export_preset(i); @@ -1133,13 +1143,20 @@ void ProjectExportDialog::_export_all(bool p_debug) { platform->clear_messages(); Error err = platform->export_project(preset, p_debug, preset->get_export_path(), 0); + if (err == OK) { + all_exports_fail = false; // At least one export was successful, keep new build number. + } if (err == ERR_SKIP) { exporting = false; + show_dialog = false; return; } bool has_messages = platform->fill_log_messages(result_dialog_log, err); show_dialog = show_dialog || has_messages; } + if (all_exports_fail) { + ProjectSettings::get_singleton()->set_setting("application/config/build", old_build_nr); // Reset build number. + } if (show_dialog) { result_dialog->popup_centered_ratio(0.5); } diff --git a/platform/android/doc_classes/EditorExportPlatformAndroid.xml b/platform/android/doc_classes/EditorExportPlatformAndroid.xml index dae968378b89..f971104076ab 100644 --- a/platform/android/doc_classes/EditorExportPlatformAndroid.xml +++ b/platform/android/doc_classes/EditorExportPlatformAndroid.xml @@ -583,7 +583,7 @@ If [code]true[/code], allows the application to participate in the backup and restore infrastructure. - + Machine-readable application version. This must be incremented for every new release pushed to the Play Store. diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index f0ee405b41fb..42abf30db10e 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -906,7 +906,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p Vector stable_extra; String version_name = p_preset->get_version("version/name"); - int version_code = p_preset->get("version/code"); + String version_code = p_preset->get_build_nr("version/code"); String package_name = p_preset->get("package/unique_name"); const int screen_orientation = @@ -998,7 +998,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref &p } if (tname == "manifest" && attrname == "versionCode") { - encode_uint32(version_code, &p_manifest.write[iofs + 16]); + encode_uint32(version_code.to_int(), &p_manifest.write[iofs + 16]); } if (tname == "manifest" && attrname == "versionName") { @@ -1835,7 +1835,7 @@ void EditorExportPlatformAndroid::get_export_options(List *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/code", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project build number"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "com.example.$genname", false, true)); @@ -2458,9 +2458,9 @@ List EditorExportPlatformAndroid::get_binary_extensions(const Ref &p_preset, const String &p_path) { - int version_code = p_preset->get("version/code"); + String version_code = p_preset->get_build_nr("version/code"); String package_name = p_preset->get("package/unique_name"); - String apk_file_name = "main." + itos(version_code) + "." + get_package_name(package_name) + ".obb"; + String apk_file_name = "main." + version_code + "." + get_package_name(package_name) + ".obb"; String fullpath = p_path.get_base_dir().path_join(apk_file_name); return fullpath; } @@ -2916,7 +2916,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Refget("package/unique_name")); - String version_code = itos(p_preset->get("version/code")); + String version_code = p_preset->get_build_nr("version/code"); String version_name = p_preset->get_version("version/name"); String min_sdk_version = p_preset->get("gradle_build/min_sdk"); if (!min_sdk_version.is_valid_int()) { diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index c0e052865fce..e513617468ca 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -179,7 +179,7 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "", false, true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project build number"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/launch_screens_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4)); @@ -286,7 +286,7 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ } else if (lines[i].find("$short_version") != -1) { strnew += lines[i].replace("$short_version", p_preset->get_version("application/short_version")) + "\n"; } else if (lines[i].find("$version") != -1) { - strnew += lines[i].replace("$version", p_preset->get_version("application/version")) + "\n"; + strnew += lines[i].replace("$version", p_preset->get_build_nr("application/version")) + "\n"; } else if (lines[i].find("$signature") != -1) { strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n"; } else if (lines[i].find("$team_id") != -1) { diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index 24cb76b4ab7a..3196acc80c4d 100644 --- a/platform/macos/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -381,7 +381,7 @@ void EditorExportPlatformMacOS::get_export_options(List *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_category", PROPERTY_HINT_ENUM, "Business,Developer-tools,Education,Entertainment,Finance,Games,Action-games,Adventure-games,Arcade-games,Board-games,Card-games,Casino-games,Dice-games,Educational-games,Family-games,Kids-games,Music-games,Puzzle-games,Racing-games,Role-playing-games,Simulation-games,Sports-games,Strategy-games,Trivia-games,Word-games,Graphics-design,Healthcare-fitness,Lifestyle,Medical,Music,News,Photography,Productivity,Reference,Social-networking,Sports,Travel,Utilities,Video,Weather"), "Games")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project build number"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_macos_version"), "10.12")); @@ -660,7 +660,7 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref &p_pres } else if (lines[i].find("$short_version") != -1) { strnew += lines[i].replace("$short_version", p_preset->get_version("application/short_version")) + "\n"; } else if (lines[i].find("$version") != -1) { - strnew += lines[i].replace("$version", p_preset->get_version("application/version")) + "\n"; + strnew += lines[i].replace("$version", p_preset->get_build_nr("application/version")) + "\n"; } else if (lines[i].find("$signature") != -1) { strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n"; } else if (lines[i].find("$app_category") != -1) { diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 4185c36d7731..a384f82f2f59 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -372,8 +372,8 @@ void EditorExportPlatformWindows::get_export_options(List *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), "", false, true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version and build number"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version and build number"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), ""));