From 5e320843271e344dafc5288a1ac15db234cce719 Mon Sep 17 00:00:00 2001 From: billythekid Date: Sun, 1 Feb 2026 21:31:19 +0000 Subject: [PATCH 1/2] Fix iOS build to respect cleanup_exclude_files config The iOS build's removeUnnecessaryFiles() method was using a hardcoded list of directories to remove, ignoring the user-configurable 'cleanup_exclude_files' setting in config/nativephp.php. This caused issues when users had large directories that should be excluded from the bundle, resulting in the zip process timing out. This change brings the iOS build in line with the Android build, which already respects the cleanup_exclude_files config via PreparesBuild. Also handles null config values gracefully with null coalescing. --- src/Commands/BuildIosAppCommand.php | 26 +-- tests/Feature/IosBuildCleanupTest.php | 234 ++++++++++++++++++++++++++ 2 files changed, 248 insertions(+), 12 deletions(-) create mode 100644 tests/Feature/IosBuildCleanupTest.php diff --git a/src/Commands/BuildIosAppCommand.php b/src/Commands/BuildIosAppCommand.php index 1b3ba4c..97116e5 100644 --- a/src/Commands/BuildIosAppCommand.php +++ b/src/Commands/BuildIosAppCommand.php @@ -794,18 +794,20 @@ private function installGoogleServicesPlist(): void private function removeUnnecessaryFiles(): void { - - $directoriesToRemove = [ - '.git', - '.github', - 'node_modules', - 'vendor/bin', - 'tests', - 'storage/logs', - 'storage/framework', - 'vendor/laravel/pint/builds', - 'public/storage', - ]; + $directoriesToRemove = array_merge( + config('nativephp.cleanup_exclude_files') ?? [], + [ + '.git', + '.github', + 'node_modules', + 'vendor/bin', + 'tests', + 'storage/logs', + 'storage/framework', + 'vendor/laravel/pint/builds', + 'public/storage', + ] + ); foreach ($directoriesToRemove as $dir) { if (is_dir($this->appPath.$dir)) { diff --git a/tests/Feature/IosBuildCleanupTest.php b/tests/Feature/IosBuildCleanupTest.php new file mode 100644 index 0000000..d32b9fc --- /dev/null +++ b/tests/Feature/IosBuildCleanupTest.php @@ -0,0 +1,234 @@ +testProjectPath = sys_get_temp_dir().'/nativephp_ios_cleanup_test_'.uniqid(); + File::makeDirectory($this->testProjectPath, 0755, true); + + // Simulate the appPath that would be used during iOS build + $this->appPath = $this->testProjectPath.'/nativephp/ios/laravel/'; + File::makeDirectory($this->appPath, 0755, true); + + app()->setBasePath($this->testProjectPath); + } + + protected function tearDown(): void + { + File::deleteDirectory($this->testProjectPath); + parent::tearDown(); + } + + public function test_removes_default_unnecessary_directories(): void + { + // Create directories that should be removed by default + $defaultDirectories = [ + '.git', + '.github', + 'node_modules', + 'vendor/bin', + 'tests', + 'storage/logs', + 'storage/framework', + 'vendor/laravel/pint/builds', + 'public/storage', + ]; + + foreach ($defaultDirectories as $dir) { + File::makeDirectory($this->appPath.$dir, 0755, true); + File::put($this->appPath.$dir.'/test.txt', 'test'); + } + + // Run the cleanup + $this->invokeRemoveUnnecessaryFiles(); + + // Assert all default directories were removed + foreach ($defaultDirectories as $dir) { + $this->assertDirectoryDoesNotExist( + $this->appPath.$dir, + "Directory '{$dir}' should have been removed" + ); + } + } + + public function test_removes_user_configured_directories_from_cleanup_exclude_files(): void + { + // Configure custom directories to exclude via config + config(['nativephp.cleanup_exclude_files' => [ + 'capacitor-app', + 'docs', + 'custom-build-folder', + ]]); + + // Create these directories + $customDirectories = [ + 'capacitor-app', + 'docs', + 'custom-build-folder', + ]; + + foreach ($customDirectories as $dir) { + File::makeDirectory($this->appPath.$dir, 0755, true); + File::put($this->appPath.$dir.'/test.txt', 'test'); + } + + // Also create a directory that should NOT be removed + File::makeDirectory($this->appPath.'app/Models', 0755, true); + File::put($this->appPath.'app/Models/User.php', 'invokeRemoveUnnecessaryFiles(); + + // Assert user-configured directories were removed + foreach ($customDirectories as $dir) { + $this->assertDirectoryDoesNotExist( + $this->appPath.$dir, + "User-configured directory '{$dir}' should have been removed" + ); + } + + // Assert app directory was NOT removed (it's not in any exclusion list) + $this->assertDirectoryExists($this->appPath.'app'); + } + + public function test_removes_both_default_and_user_configured_directories(): void + { + // Configure custom directories + config(['nativephp.cleanup_exclude_files' => [ + 'capacitor-app', + 'legacy-folder', + ]]); + + // Create both default and custom directories + $allDirectories = [ + // Default + '.git', + 'node_modules', + 'tests', + // Custom + 'capacitor-app', + 'legacy-folder', + ]; + + foreach ($allDirectories as $dir) { + File::makeDirectory($this->appPath.$dir, 0755, true); + File::put($this->appPath.$dir.'/test.txt', 'test'); + } + + // Run the cleanup + $this->invokeRemoveUnnecessaryFiles(); + + // Assert all directories were removed + foreach ($allDirectories as $dir) { + $this->assertDirectoryDoesNotExist( + $this->appPath.$dir, + "Directory '{$dir}' should have been removed" + ); + } + } + + public function test_handles_empty_cleanup_exclude_files_config(): void + { + // Set empty config + config(['nativephp.cleanup_exclude_files' => []]); + + // Create a default directory that should still be removed + File::makeDirectory($this->appPath.'node_modules', 0755, true); + File::put($this->appPath.'node_modules/package.json', '{}'); + + // Run the cleanup + $this->invokeRemoveUnnecessaryFiles(); + + // Assert default directory was still removed + $this->assertDirectoryDoesNotExist($this->appPath.'node_modules'); + } + + public function test_handles_null_cleanup_exclude_files_config(): void + { + // Set null config (simulating missing config) + config(['nativephp.cleanup_exclude_files' => null]); + + // Create a default directory that should still be removed + File::makeDirectory($this->appPath.'.git', 0755, true); + File::put($this->appPath.'.git/config', '[core]'); + + // Run the cleanup + $this->invokeRemoveUnnecessaryFiles(); + + // Assert default directory was still removed + $this->assertDirectoryDoesNotExist($this->appPath.'.git'); + } + + public function test_handles_nested_directory_paths_in_config(): void + { + // Configure nested directory paths + config(['nativephp.cleanup_exclude_files' => [ + 'storage/framework/sessions', + 'storage/framework/cache', + ]]); + + // Create nested directories + File::makeDirectory($this->appPath.'storage/framework/sessions', 0755, true); + File::makeDirectory($this->appPath.'storage/framework/cache', 0755, true); + File::put($this->appPath.'storage/framework/sessions/session1', 'data'); + File::put($this->appPath.'storage/framework/cache/cache1', 'data'); + + // Run the cleanup + $this->invokeRemoveUnnecessaryFiles(); + + // Assert nested directories were removed + $this->assertDirectoryDoesNotExist($this->appPath.'storage/framework/sessions'); + $this->assertDirectoryDoesNotExist($this->appPath.'storage/framework/cache'); + } + + public function test_skips_non_existent_directories_without_error(): void + { + // Configure directories that don't exist + config(['nativephp.cleanup_exclude_files' => [ + 'non-existent-folder', + 'another-missing-dir', + ]]); + + // Don't create these directories + + // Run the cleanup - should not throw an error + $this->invokeRemoveUnnecessaryFiles(); + + // If we get here without exception, the test passes + $this->assertTrue(true); + } + + /** + * Helper method to invoke the private removeUnnecessaryFiles method + */ + protected function invokeRemoveUnnecessaryFiles(): void + { + $command = $this->app->make(BuildIosAppCommand::class); + + // Use reflection to set the appPath property + $reflection = new ReflectionClass($command); + + $appPathProperty = $reflection->getProperty('appPath'); + $appPathProperty->setAccessible(true); + $appPathProperty->setValue($command, $this->appPath); + + // Invoke the private method + $method = $reflection->getMethod('removeUnnecessaryFiles'); + $method->setAccessible(true); + $method->invoke($command); + } +} From 3ab630c9cc4f0ad826919eb7734801f2ba459526 Mon Sep 17 00:00:00 2001 From: billythekid Date: Mon, 2 Feb 2026 14:25:37 +0000 Subject: [PATCH 2/2] Handle both files and directories in cleanup_exclude_files config The cleanup_exclude_files config option is documented as supporting both files and folders, but the previous implementation only processed them as directories. This update properly checks each path and handles it appropriately - using File::deleteDirectory() for directories and unlink() for files. --- src/Commands/BuildIosAppCommand.php | 42 ++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Commands/BuildIosAppCommand.php b/src/Commands/BuildIosAppCommand.php index 97116e5..c1110d3 100644 --- a/src/Commands/BuildIosAppCommand.php +++ b/src/Commands/BuildIosAppCommand.php @@ -794,22 +794,34 @@ private function installGoogleServicesPlist(): void private function removeUnnecessaryFiles(): void { - $directoriesToRemove = array_merge( - config('nativephp.cleanup_exclude_files') ?? [], - [ - '.git', - '.github', - 'node_modules', - 'vendor/bin', - 'tests', - 'storage/logs', - 'storage/framework', - 'vendor/laravel/pint/builds', - 'public/storage', - ] - ); + // Get user-configured paths (can be files or directories) + $configuredPaths = config('nativephp.cleanup_exclude_files') ?? []; + + // Default directories to always remove + $defaultDirectories = [ + '.git', + '.github', + 'node_modules', + 'vendor/bin', + 'tests', + 'storage/logs', + 'storage/framework', + 'vendor/laravel/pint/builds', + 'public/storage', + ]; + + // Process user-configured paths (both files and directories) + foreach ($configuredPaths as $path) { + $fullPath = $this->appPath.$path; + if (is_dir($fullPath)) { + File::deleteDirectory($fullPath); + } elseif (is_file($fullPath)) { + unlink($fullPath); + } + } - foreach ($directoriesToRemove as $dir) { + // Process default directories + foreach ($defaultDirectories as $dir) { if (is_dir($this->appPath.$dir)) { File::deleteDirectory($this->appPath.$dir); }