Fixed RuntimeException when building release

TickTackk

Well-known member
Affected version
2.0
If any of the file path length >= 260 then exception will be thrown
Code:
RuntimeException: SplFileInfo::getMTime(): stat failed for <very long file path goes here> src\vendor\league\flysystem\src\Adapter\Local.php:484

Both file_exists() and is_readable() return false when checking for the file path inside the _build directory.

PHP: 7.2.6
OS: Windows
 
Last edited:
Found the fix I think

File: src\vendor\league\flysystem\src\Adapter\Local.php
Add after line: 261
PHP:
$location = str_replace("\\\\", "\\", $location);
 
There does appear to be a bug here related to the Local FS adapter for Flysystem that affects Windows and it is fixed in subsequent Flysystem releases but those are only compatible with PHP 5.5 and above.

However, there's little reason to use this adapter (aside from being a slightly nicer API) so we've just swapped it out with native functions. It works in my testing, though if you could check using the below diff to ensure this issue is resolved and verify a few of your releases are being built correctly.

This may represent a breaking change for any code extending the build process, but as I would assume such changes to only affect developers directly, that should be acceptable for a third point release.
Diff:
Index: src/XF/Service/AddOn/ReleaseBuilder.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/XF/Service/AddOn/ReleaseBuilder.php    (date 1536138284000)
+++ src/XF/Service/AddOn/ReleaseBuilder.php    (date 1536144638000)
@@ -22,7 +22,7 @@
     protected $tempFile;
 
     /**
-     * @var Filesystem
+     * @var \RecursiveIteratorIterator|\SplFileInfo[]
      */
     protected $localFs;
 
@@ -195,8 +195,10 @@
 
     protected function prepareFsAdapters()
     {
-        $local = new Local($this->buildRoot);
-        $this->localFs = new Filesystem($local);
+        $this->localFs = new \RecursiveIteratorIterator(
+            new \RecursiveDirectoryIterator($this->buildRoot, \FilesystemIterator::SKIP_DOTS),
+            \RecursiveIteratorIterator::SELF_FIRST
+        );
 
         $this->tempFile = File::getTempFile();
 
@@ -394,29 +396,31 @@
 
         // NOTE: any files skipped by generateHashes() won't appear in this loop...
 
-        foreach ($localFs->listContents('', true) AS $info)
+        foreach ($localFs AS $file)
         {
             // skip hidden dot files, e.g. .DS_Store, .gitignore etc.
-            if ($this->isExcludedFileName($info['basename']))
+            if ($this->isExcludedFileName($file->getBasename()))
             {
                 continue;
             }
 
-            if ($info['type'] == 'dir')
+            $localName = substr($file->getPathname(), strlen($this->buildRoot));
+
+            if ($file->isDir())
             {
-                $info['path'] .= '/';
-                $zipArchive->addEmptyDir($info['path']);
+                $localName .= '/';
+                $zipArchive->addEmptyDir($localName);
                 $perm = 040755 << 16; // dir: 0755
             }
             else
             {
-                $zipArchive->addFile($this->buildRoot . '/' . $info['path'], $info['path']);
+                $zipArchive->addFile($file->getPathname(), $localName);
                 $perm = 0100644 << 16; // file: 0644
             }
 
             if (method_exists($zipArchive, 'setExternalAttributesName'))
             {
-                $zipArchive->setExternalAttributesName($info['path'], \ZipArchive::OPSYS_UNIX, $perm);
+                $zipArchive->setExternalAttributesName($localName, \ZipArchive::OPSYS_UNIX, $perm);
             }
         }
 
Top Bottom