/vendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php

https://gitlab.com/yousafsyed/easternglamor · PHP · 171 lines · 89 code · 28 blank · 54 comment · 13 complexity · 203b2b8421cefcd1f76e6bb29bc14ede MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Package\Archiver;
  12. use Composer\Downloader\DownloadManager;
  13. use Composer\Package\PackageInterface;
  14. use Composer\Package\RootPackageInterface;
  15. use Composer\Util\Filesystem;
  16. use Composer\Json\JsonFile;
  17. /**
  18. * @author Matthieu Moquet <matthieu@moquet.net>
  19. * @author Till Klampaeckel <till@php.net>
  20. */
  21. class ArchiveManager
  22. {
  23. protected $downloadManager;
  24. protected $archivers = array();
  25. /**
  26. * @var bool
  27. */
  28. protected $overwriteFiles = true;
  29. /**
  30. * @param DownloadManager $downloadManager A manager used to download package sources
  31. */
  32. public function __construct(DownloadManager $downloadManager)
  33. {
  34. $this->downloadManager = $downloadManager;
  35. }
  36. /**
  37. * @param ArchiverInterface $archiver
  38. */
  39. public function addArchiver(ArchiverInterface $archiver)
  40. {
  41. $this->archivers[] = $archiver;
  42. }
  43. /**
  44. * Set whether existing archives should be overwritten
  45. *
  46. * @param bool $overwriteFiles New setting
  47. *
  48. * @return $this
  49. */
  50. public function setOverwriteFiles($overwriteFiles)
  51. {
  52. $this->overwriteFiles = $overwriteFiles;
  53. return $this;
  54. }
  55. /**
  56. * Generate a distinct filename for a particular version of a package.
  57. *
  58. * @param PackageInterface $package The package to get a name for
  59. *
  60. * @return string A filename without an extension
  61. */
  62. public function getPackageFilename(PackageInterface $package)
  63. {
  64. $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
  65. if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
  66. $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
  67. } else {
  68. $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
  69. }
  70. if ($package->getSourceReference()) {
  71. $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
  72. }
  73. $name = implode('-', array_filter($nameParts, function ($p) {
  74. return !empty($p);
  75. }));
  76. return str_replace('/', '-', $name);
  77. }
  78. /**
  79. * Create an archive of the specified package.
  80. *
  81. * @param PackageInterface $package The package to archive
  82. * @param string $format The format of the archive (zip, tar, ...)
  83. * @param string $targetDir The diretory where to build the archive
  84. * @throws \InvalidArgumentException
  85. * @throws \RuntimeException
  86. * @return string The path of the created archive
  87. */
  88. public function archive(PackageInterface $package, $format, $targetDir)
  89. {
  90. if (empty($format)) {
  91. throw new \InvalidArgumentException('Format must be specified');
  92. }
  93. // Search for the most appropriate archiver
  94. $usableArchiver = null;
  95. foreach ($this->archivers as $archiver) {
  96. if ($archiver->supports($format, $package->getSourceType())) {
  97. $usableArchiver = $archiver;
  98. break;
  99. }
  100. }
  101. // Checks the format/source type are supported before downloading the package
  102. if (null === $usableArchiver) {
  103. throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
  104. }
  105. $filesystem = new Filesystem();
  106. $packageName = $this->getPackageFilename($package);
  107. // Archive filename
  108. $filesystem->ensureDirectoryExists($targetDir);
  109. $target = realpath($targetDir).'/'.$packageName.'.'.$format;
  110. $filesystem->ensureDirectoryExists(dirname($target));
  111. if (!$this->overwriteFiles && file_exists($target)) {
  112. return $target;
  113. }
  114. if ($package instanceof RootPackageInterface) {
  115. $sourcePath = realpath('.');
  116. } else {
  117. // Directory used to download the sources
  118. $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
  119. $filesystem->ensureDirectoryExists($sourcePath);
  120. // Download sources
  121. $this->downloadManager->download($package, $sourcePath);
  122. // Check exclude from downloaded composer.json
  123. if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
  124. $jsonFile = new JsonFile($composerJsonPath);
  125. $jsonData = $jsonFile->read();
  126. if (!empty($jsonData['archive']['exclude'])) {
  127. $package->setArchiveExcludes($jsonData['archive']['exclude']);
  128. }
  129. }
  130. }
  131. // Create the archive
  132. $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
  133. $filesystem->ensureDirectoryExists(dirname($tempTarget));
  134. $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes());
  135. rename($archivePath, $target);
  136. // cleanup temporary download
  137. if (!$package instanceof RootPackageInterface) {
  138. $filesystem->removeDirectory($sourcePath);
  139. }
  140. $filesystem->remove($tempTarget);
  141. return $target;
  142. }
  143. }