Przeglądaj źródła

Make use of new dist properties, refactored ZipDownloader

Jordi Boggiano 14 lat temu
rodzic
commit
49c3446ac1

+ 21 - 4
src/Composer/Command/InstallCommand.php

@@ -23,6 +23,9 @@ class InstallCommand
     {
         $this->composer = $composer;
 
+        // TODO this needs a parameter to enable installing from source (i.e. git clone, instead of downloading archives)
+        $sourceInstall = false;
+
         $config = $this->loadConfig();
 
         foreach ($config['repositories'] as $name => $spec) {
@@ -50,11 +53,25 @@ class InstallCommand
             if (!isset($package)) {
                 throw new \UnexpectedValueException('Could not find package '.$name.' in any of your repositories');
             }
-            $downloader = $composer->getDownloader($package->getSourceType());
-            $installer = $composer->getInstaller($package->getType());
-            $lock[$name] = $installer->install($package, $downloader);
-            echo '> '.$name.' installed'.PHP_EOL;
+            echo '> Installing '.$package->getName().PHP_EOL;
+            if ($sourceInstall) {
+                // TODO
+            } else {
+                if ($package->getDistType()) {
+                    $downloader = $composer->getDownloader($package->getDistType());
+                    $type = 'dist';
+                } elseif ($package->getSourceType()) {
+                    echo 'Package '.$package->getName().' has no dist url, installing from source instead.';
+                    $downloader = $composer->getDownloader($package->getSourceType());
+                    $type = 'source';
+                } else {
+                    throw new \UnexpectedValueException('Package '.$package->getName().' has no source or dist URL.');
+                }
+                $installer = $composer->getInstaller($package->getType());
+                $lock[$name] = $installer->install($package, $downloader, $type);
+            }
         }
+        echo '> Done'.PHP_EOL;
 
         $this->storeLockFile($lock);
     }

+ 3 - 3
src/Composer/Downloader/GitDownloader.php

@@ -26,7 +26,7 @@ class GitDownloader
         $this->clone = $clone;
     }
 
-    public function download(PackageInterface $package, $path)
+    public function download(PackageInterface $package, $path, $url, $checksum = null)
     {
         if (!is_dir($path)) {
             if (file_exists($path)) {
@@ -37,9 +37,9 @@ class GitDownloader
             }
         }
         if ($this->clone) {
-            system('git clone '.escapeshellarg($package->getSourceUrl()).' -b master '.escapeshellarg($path.'/'.$package->getName()));
+            system('git clone '.escapeshellarg($url).' -b master '.escapeshellarg($path.'/'.$package->getName()));
         } else {
-            system('git archive --format=tar --prefix='.escapeshellarg($package->getName()).' --remote='.escapeshellarg($package->getSourceUrl()).' master | tar -xf -');
+            system('git archive --format=tar --prefix='.escapeshellarg($package->getName()).' --remote='.escapeshellarg($url).' master | tar -xf -');
         }
     }
 }

+ 8 - 5
src/Composer/Downloader/PearDownloader.php

@@ -20,7 +20,7 @@ use Composer\Package\PackageInterface;
  */
 class PearDownloader
 {
-    public function download(PackageInterface $package, $path)
+    public function download(PackageInterface $package, $path, $url, $checksum = null)
     {
         $targetPath = $path . "/" . $package->getName();
         if (!is_dir($targetPath)) {
@@ -35,17 +35,20 @@ class PearDownloader
         $cwd = getcwd();
         chdir($targetPath);
 
-        $source = $package->getSourceUrl();
-        $tarName = basename($source);
+        $tarName = basename($url);
 
-        echo 'Downloading '.$source.' to '.$targetPath.'/'.$tarName.PHP_EOL;
-        copy($package->getSourceUrl(), './'.$tarName);
+        echo 'Downloading '.$url.' to '.$targetPath.'/'.$tarName.PHP_EOL;
+        copy($url, './'.$tarName);
 
         if (!file_exists($tarName)) {
             throw new \UnexpectedValueException($package->getName().' could not be saved into '.$tarName.', make sure the'
                 .' directory is writable and you have internet connectivity.');
         }
 
+        if ($checksum && hash_file('sha1', './'.$tarName) !== $checksum) {
+            throw new \UnexpectedValueException('The checksum verification failed for the '.$package->getName().' archive (downloaded from '.$url.'). Installation aborted.');
+        }
+
         echo 'Unpacking archive'.PHP_EOL;
         exec('tar -xzf "'.escapeshellarg($tarName).'"');
 

+ 40 - 9
src/Composer/Downloader/ZipDownloader.php

@@ -19,27 +19,58 @@ use Composer\Package\PackageInterface;
  */
 class ZipDownloader
 {
-    public function download(PackageInterface $package, $path)
+    public function download(PackageInterface $package, $path, $url, $checksum = null)
     {
         if (!class_exists('ZipArchive')) {
             throw new \UnexpectedValueException('You need the zip extension enabled to use the ZipDownloader');
         }
 
-        $tmpName = tempnam(sys_get_temp_dir(), '');
-        copy($package->getSourceUrl(), $tmpName);
+        $targetPath = $path . "/" . $package->getName();
+        if (!is_dir($targetPath)) {
+            if (file_exists($targetPath)) {
+                throw new \UnexpectedValueException($targetPath.' exists and is not a directory.');
+            }
+            if (!mkdir($targetPath, 0777, true)) {
+                throw new \UnexpectedValueException($targetPath.' does not exist and could not be created.');
+            }
+        }
+
+        $zipName = $targetPath.'/'.basename($url, '.zip').'.zip';
+        echo 'Downloading '.$url.' to '.$zipName.PHP_EOL;
+        copy($url, $zipName);
 
-        if (!file_exists($tmpName)) {
-            throw new \UnexpectedValueException($path.' could not be saved into '.$tmpName.', make sure the'
+        if (!file_exists($zipName)) {
+            throw new \UnexpectedValueException($path.' could not be saved into '.$zipName.', make sure the'
                 .' directory is writable and you have internet connectivity.');
         }
 
-        $zipArchive = new ZipArchive();
+        if ($checksum && hash_file('sha1', $zipName) !== $checksum) {
+            throw new \UnexpectedValueException('The checksum verification failed for the '.$package->getName().' archive (downloaded from '.$url.'). Installation aborted.');
+        }
+
+        $zipArchive = new \ZipArchive();
 
-        if (true === ($retval = $zipArchive->open($tmpName))) {
-            $zipArchive->extractTo($path.'/'.$package->getName());
+        echo 'Unpacking archive'.PHP_EOL;
+        if (true === ($retval = $zipArchive->open($zipName))) {
+            $targetPath = $path.'/'.$package->getName();
+            $zipArchive->extractTo($targetPath);
             $zipArchive->close();
+            echo 'Cleaning up'.PHP_EOL;
+            unlink($zipName);
+            if (false !== strpos($url, '//github.com/')) {
+                $contentDir = glob($targetPath.'/*');
+                if (1 === count($contentDir)) {
+                    $contentDir = $contentDir[0];
+                    foreach (array_merge(glob($contentDir.'/.*'), glob($contentDir.'/*')) as $file) {
+                        if (trim(basename($file), '.')) {
+                            rename($file, $targetPath.'/'.basename($file));
+                        }
+                    }
+                    rmdir($contentDir);
+                }
+            }
         } else {
-            throw new \UnexpectedValueException($tmpName.' is not a valid zip archive, got error code '.$retval);
+            throw new \UnexpectedValueException($zipName.' is not a valid zip archive, got error code '.$retval);
         }
     }
 }

+ 8 - 2
src/Composer/Installer/LibraryInstaller.php

@@ -26,9 +26,15 @@ class LibraryInstaller
         $this->dir = $dir;
     }
 
-    public function install(PackageInterface $package, $downloader)
+    public function install(PackageInterface $package, $downloader, $type)
     {
-        $downloader->download($package, $this->dir);
+        if ($type === 'dist') {
+            $downloader->download($package, $this->dir, $package->getDistUrl(), $package->getDistSha1Checksum());
+        } elseif ($type === 'source') {
+            $downloader->download($package, $this->dir, $package->getSourceUrl());
+        } else {
+            throw new \InvalidArgumentException('Type must be one of (dist, source), '.$type.' given.');
+        }
         return array('version' => $package->getVersion());
     }
 }

+ 4 - 0
src/Composer/Repository/ComposerRepository.php

@@ -51,6 +51,10 @@ class ComposerRepository extends ArrayRepository
             $package->setSourceType($rev['source']['type']);
             $package->setSourceUrl($rev['source']['url']);
 
+            $package->setDistType($rev['dist']['type']);
+            $package->setDistUrl($rev['dist']['url']);
+            $package->setDistSha1Checksum($rev['dist']['shasum']);
+
             if (isset($rev['license'])) {
                 $package->setLicense($rev['license']);
             }

+ 2 - 0
src/Composer/Repository/GitRepository.php

@@ -18,6 +18,8 @@ use Composer\Package\Link;
 use Composer\Package\LinkConstraint\VersionConstraint;
 
 /**
+ * FIXME This is majorly broken and incomplete, it was an experiment
+ *
  * @author Jordi Boggiano <j.boggiano@seld.be>
  */
 class GitRepository extends ArrayRepository

+ 2 - 2
src/Composer/Repository/PearRepository.php

@@ -74,8 +74,8 @@ class PearRepository extends ArrayRepository
                     $version = BasePackage::parseVersion($pearVersion);
 
                     $package = new MemoryPackage($packageName, $version['version'], $version['type']);
-                    $package->setSourceType('pear');
-                    $package->setSourceUrl($this->url.'/get/'.$packageName.'-'.$pearVersion.".tgz");
+                    $package->setDistType('pear');
+                    $package->setDistUrl($this->url.'/get/'.$packageName.'-'.$pearVersion.".tgz");
 
                     $depsLink = $releaseLink . "/deps.".$pearVersion.".txt";
                     $deps = file_get_contents($depsLink);