XF 2.2 Add-on build failed

Earl

Well-known member
I have this in my composer.json
JSON:
{
  "require": {
    "giggsey/libphonenumber-for-php": "^8.12",
    "irazasyed/telegram-bot-sdk": "^2.0"
  }
}
and build.json
JSON:
{
  "additional_files": [
    "styles/default/Earl/PV"
  ],
  "exec": [
    "composer install --working-dir=_build/upload/src/addons/{addon_id}/ --no-dev --optimize-autoloader",
    "rm -v -rf _build/upload/src/addons/{addon_id}/phpunit.xml",
    "rm -v -rf _build/upload/src/addons/{addon_id}/tests"
  ]
}

Code:
php cmd.php xf-addon:build-release Earl/PV

Performing add-on export.



Exporting data for [Earl]  to /var/www/html/src/addons/Earl/PV/_data.

 27/27 [============================] 100%

Written successfully.

Attempting to validate addon.json file...

JSON file validates successfully!



In File.php line 616:

                                                                              

  [E_WARNING] rmdir(/var/www/html/src/addons/Earl/PV/_build/up

  load/src/addons/Earl/PV/vendor/giggsey/libphonenumber-for-ph

  p/src/geocoding/data/en): Directory not empty                               

                                                                              



xf-addon:build-release [--skip-hashes] [--] <id>





Process finished with exit code 1.

Any Idea why the process is failing?
 
I'm using this composer repo giggsey/libphonenumber-for-ph

Is this a permission bug?
 
I think this is a bug. After the add-on build process gets completed, the built zip file does not get contained all the necessary files in /vendor folder. some random files disappear.

This is chatgpt's response.



The issue arises because rmdir() in PHP will throw a warning if it attempts to delete a directory that is not empty. This can occur if the composer install command has added files to the vendor directory during its execution.

To resolve this, you can modify the code to ensure that all files and subdirectories are properly deleted before calling rmdir(). Here's an updated version of the function that ensures directories are emptied before attempting to delete them:

PHP:
public static function deleteDirectory($path)
{
    $path = self::canonicalizePath($path);
    if (!is_readable($path) || !is_dir($path))
    {
        throw new \InvalidArgumentException("$path is not readable or not a directory");
    }

    if (!is_writable($path))
    {
        throw new \InvalidArgumentException("$path is not writable");
    }

    $files = self::getRecursiveDirectoryIterator($path);
    foreach ($files AS $file)
    {
        if ($file->isLink())
        {
            unlink($file->getPath() . \XF::$DS . $file->getFilename());
        }
        else if ($file->isDir())
        {
            self::deleteDirectory($file->getRealPath()); // Recursively delete subdirectories
        }
        else
        {
            unlink($file->getRealPath());
        }
    }

    rmdir($path);
}

By using a recursive approach, the deleteDirectory function will ensure all nested directories and their contents are properly removed before attempting to delete the parent directory.

Additionally, ensure that any files or directories added by Composer are completely removed before attempting to delete the directory. This might involve checking for additional hidden files or directories that Composer might create.

If this does not resolve the issue, another workaround is to manually clean up the vendor directory before running the rmdir() function. This can be done by adding a script to your build process that ensures the directory is empty before the build script attempts to delete it.

Lastly, consider whether the timing of the Composer installation relative to the build process could be causing conflicts. If the composer install step can be isolated or handled in a way that doesn't interfere with the directory deletion, this might also resolve the issue.





@Kier @Chris D Please help.
 
Last edited:
PHP:
public static function deleteDirectory($path)
{
    $path = self::canonicalizePath($path);
    if (!is_readable($path) || !is_dir($path))
    {
        throw new \InvalidArgumentException("$path is not readable or not a directory");
    }

    if (!is_writable($path))
    {
        throw new \InvalidArgumentException("$path is not writable");
    }

    $files = self::getRecursiveDirectoryIterator($path);
    foreach ($files as $file)
    {
        if ($file->isLink())
        {
            unlink($file->getPath() . \XF::$DS . $file->getFilename());
        }
        else if ($file->isDir())
        {
            self::deleteDirectory($file->getRealPath()); // Recursively delete subdirectories
        }
        else
        {
            unlink($file->getRealPath());
        }
    }

    // Ensure all files are deleted before attempting to remove the directory
    $remainingFiles = array_diff(scandir($path), array('.', '..'));
    if (empty($remainingFiles)) {
        rmdir($path);
    } else {
        // Handle remaining files if necessary
        foreach ($remainingFiles as $remainingFile) {
            $filePath = $path . DIRECTORY_SEPARATOR . $remainingFile;
            if (is_dir($filePath)) {
                self::deleteDirectory($filePath);
            } else {
                unlink($filePath);
            }
        }
        rmdir($path);
    }
}

In this revised version:

  1. Recursively deletes subdirectories: The function ensures subdirectories are fully emptied before calling rmdir on them.
  2. Check for remaining files: After the initial deletion attempt, it checks for any remaining files or directories and handles them accordingly before finally deleting the directory.
This should help in ensuring that the directory is emptied completely before attempting to delete it, thus avoiding the Directory not empty warning.
 
Back
Top Bottom