Skip to content

Commit 1f303e0

Browse files
committed
Merge pull request #89790 from bruvzg/ios_safe_delete
[iOS Export] Check directory content before deleting old export leftovers.
2 parents 77caf02 + b304367 commit 1f303e0

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

platform/ios/doc_classes/EditorExportPlatformIOS.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
<member name="application/code_sign_identity_release" type="String" setter="" getter="">
3030
The "Full Name", "Common Name" or SHA-1 hash of the signing identity used for release export.
3131
</member>
32+
<member name="application/delete_old_export_files_unconditionally" type="bool" setter="" getter="">
33+
If [code]true[/code], existing "project name" and "project name.xcodeproj" in the export destination directory will be unconditionally deleted during export.
34+
</member>
3235
<member name="application/export_method_debug" type="int" setter="" getter="">
3336
Application distribution target (debug export).
3437
</member>

platform/ios/export/export_plugin.cpp

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
287287
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
288288

289289
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/export_project_only"), false));
290+
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/delete_old_export_files_unconditionally"), false));
290291

291292
Vector<PluginConfigIOS> found_plugins = get_plugins();
292293
for (int i = 0; i < found_plugins.size(); i++) {
@@ -1856,19 +1857,72 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
18561857
}
18571858

18581859
{
1860+
bool delete_old = p_preset->get("application/delete_old_export_files_unconditionally");
18591861
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
18601862
if (da.is_valid()) {
18611863
String current_dir = da->get_current_dir();
18621864

1863-
// remove leftovers from last export so they don't interfere
1864-
// in case some files are no longer needed
1865+
// Remove leftovers from last export so they don't interfere in case some files are no longer needed.
18651866
if (da->change_dir(binary_dir + ".xcodeproj") == OK) {
1866-
da->erase_contents_recursive();
1867+
// Check directory content before deleting.
1868+
int expected_files = 0;
1869+
int total_files = 0;
1870+
if (!delete_old) {
1871+
da->list_dir_begin();
1872+
for (String n = da->get_next(); !n.is_empty(); n = da->get_next()) {
1873+
if (!n.begins_with(".")) { // Ignore ".", ".." and hidden files.
1874+
if (da->current_is_dir()) {
1875+
if (n == "xcshareddata" || n == "project.xcworkspace") {
1876+
expected_files++;
1877+
}
1878+
} else {
1879+
if (n == "project.pbxproj") {
1880+
expected_files++;
1881+
}
1882+
}
1883+
total_files++;
1884+
}
1885+
}
1886+
da->list_dir_end();
1887+
}
1888+
if ((total_files == 0) || (expected_files >= Math::floor(total_files * 0.8))) {
1889+
da->erase_contents_recursive();
1890+
} else {
1891+
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Unexpected files found in the export destination directory \"%s.xcodeproj\", delete it manually or select another destination."), binary_dir));
1892+
return ERR_CANT_CREATE;
1893+
}
18671894
}
1895+
da->change_dir(current_dir);
1896+
18681897
if (da->change_dir(binary_dir) == OK) {
1869-
da->erase_contents_recursive();
1898+
// Check directory content before deleting.
1899+
int expected_files = 0;
1900+
int total_files = 0;
1901+
if (!delete_old) {
1902+
da->list_dir_begin();
1903+
for (String n = da->get_next(); !n.is_empty(); n = da->get_next()) {
1904+
if (!n.begins_with(".")) { // Ignore ".", ".." and hidden files.
1905+
if (da->current_is_dir()) {
1906+
if (n == "dylibs" || n == "Images.xcassets" || n.ends_with(".lproj") || n == "godot-publish-dotnet" || n.ends_with(".xcframework") || n.ends_with(".framework")) {
1907+
expected_files++;
1908+
}
1909+
} else {
1910+
if (n == binary_name + "-Info.plist" || n == binary_name + ".entitlements" || n == "Launch Screen.storyboard" || n == "export_options.plist" || n.begins_with("dummy.") || n.ends_with(".gdip")) {
1911+
expected_files++;
1912+
}
1913+
}
1914+
total_files++;
1915+
}
1916+
}
1917+
da->list_dir_end();
1918+
}
1919+
if ((total_files == 0) || (expected_files >= Math::floor(total_files * 0.8))) {
1920+
da->erase_contents_recursive();
1921+
} else {
1922+
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Unexpected files found in the export destination directory \"%s\", delete it manually or select another destination."), binary_dir));
1923+
return ERR_CANT_CREATE;
1924+
}
18701925
}
1871-
18721926
da->change_dir(current_dir);
18731927

18741928
if (!da->dir_exists(binary_dir)) {

0 commit comments

Comments
 (0)