|
16 | 16 |
|
17 | 17 | class PackageDiff |
18 | 18 | { |
19 | | - const LOCKFILE = 'composer.lock'; |
| 19 | + const COMPOSER = 'composer'; |
| 20 | + const EXTENSION_LOCK = '.lock'; |
| 21 | + const EXTENSION_JSON = '.json'; |
| 22 | + const GIT_SEPARATOR = ':'; |
20 | 23 |
|
21 | 24 | /** |
| 25 | + * @param string[] $directPackages |
| 26 | + * @param bool $onlyDirect |
| 27 | + * |
22 | 28 | * @return DiffEntries |
23 | 29 | */ |
24 | | - public function getDiff(RepositoryInterface $oldPackages, RepositoryInterface $targetPackages) |
| 30 | + public function getDiff(RepositoryInterface $oldPackages, RepositoryInterface $targetPackages, array $directPackages = array(), $onlyDirect = false) |
25 | 31 | { |
26 | 32 | $operations = array(); |
27 | 33 |
|
@@ -59,24 +65,37 @@ public function getDiff(RepositoryInterface $oldPackages, RepositoryInterface $t |
59 | 65 | } |
60 | 66 | } |
61 | 67 |
|
62 | | - return new DiffEntries(array_map(function (OperationInterface $operation) { |
63 | | - return new DiffEntry($operation); |
64 | | - }, $operations)); |
| 68 | + $entries = array_map(function (OperationInterface $operation) use ($directPackages) { |
| 69 | + $package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage(); |
| 70 | + |
| 71 | + return new DiffEntry($operation, in_array($package->getName(), $directPackages, true)); |
| 72 | + }, $operations); |
| 73 | + |
| 74 | + if ($onlyDirect) { |
| 75 | + $entries = array_values(array_filter($entries, function (DiffEntry $entry) { |
| 76 | + return $entry->isDirect(); |
| 77 | + })); |
| 78 | + } |
| 79 | + |
| 80 | + return new DiffEntries($entries); |
65 | 81 | } |
66 | 82 |
|
67 | 83 | /** |
68 | 84 | * @param string $from |
69 | 85 | * @param string $to |
70 | 86 | * @param bool $dev |
71 | 87 | * @param bool $withPlatform |
| 88 | + * @param bool $onlyDirect |
72 | 89 | * |
73 | 90 | * @return DiffEntries |
74 | 91 | */ |
75 | | - public function getPackageDiff($from, $to, $dev, $withPlatform) |
| 92 | + public function getPackageDiff($from, $to, $dev, $withPlatform, $onlyDirect = false) |
76 | 93 | { |
77 | 94 | return $this->getDiff( |
78 | 95 | $this->loadPackages($from, $dev, $withPlatform), |
79 | | - $this->loadPackages($to, $dev, $withPlatform) |
| 96 | + $this->loadPackages($to, $dev, $withPlatform), |
| 97 | + array_merge($this->getDirectPackages($from), $this->getDirectPackages($to)), |
| 98 | + $onlyDirect |
80 | 99 | ); |
81 | 100 | } |
82 | 101 |
|
@@ -110,33 +129,82 @@ private function loadPackages($path, $dev, $withPlatform) |
110 | 129 | /** |
111 | 130 | * @param string $path |
112 | 131 | * |
| 132 | + * @return string[] |
| 133 | + */ |
| 134 | + private function getDirectPackages($path) |
| 135 | + { |
| 136 | + $data = \json_decode($this->getFileContents($path, false), true); |
| 137 | + |
| 138 | + $packages = array(); |
| 139 | + |
| 140 | + foreach (array('require', 'require-dev') as $key) { |
| 141 | + if (isset($data[$key])) { |
| 142 | + $packages = array_merge($packages, array_keys($data[$key])); |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | + return $packages; // @phpstan-ignore return.type |
| 147 | + } |
| 148 | + |
| 149 | + /** |
| 150 | + * @param string $path |
| 151 | + * @param bool $lockFile |
| 152 | + * |
113 | 153 | * @return string |
114 | 154 | */ |
115 | | - private function getFileContents($path) |
| 155 | + private function getFileContents($path, $lockFile = true) |
116 | 156 | { |
117 | 157 | $originalPath = $path; |
118 | 158 |
|
119 | 159 | if (empty($path)) { |
120 | | - $path = self::LOCKFILE; |
| 160 | + $path = self::COMPOSER.($lockFile ? self::EXTENSION_LOCK : self::EXTENSION_JSON); |
121 | 161 | } |
122 | 162 |
|
123 | | - if (filter_var($path, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED) || file_exists($path)) { |
| 163 | + $localPath = $path; |
| 164 | + |
| 165 | + if (!$lockFile) { |
| 166 | + $localPath = $this->getJsonPath($localPath); |
| 167 | + } |
| 168 | + |
| 169 | + if (filter_var($localPath, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED) || file_exists($localPath)) { |
124 | 170 | // @phpstan-ignore return.type |
125 | | - return file_get_contents($path); |
| 171 | + return file_get_contents($localPath); |
| 172 | + } |
| 173 | + |
| 174 | + if (false === strpos($originalPath, self::GIT_SEPARATOR)) { |
| 175 | + $path .= self::GIT_SEPARATOR.self::COMPOSER.($lockFile ? self::EXTENSION_LOCK : self::EXTENSION_JSON); |
126 | 176 | } |
127 | 177 |
|
128 | | - if (false === strpos($originalPath, ':')) { |
129 | | - $path .= ':'.self::LOCKFILE; |
| 178 | + if (!$lockFile) { |
| 179 | + $path = $this->getJsonPath($path); |
130 | 180 | } |
131 | 181 |
|
132 | 182 | $output = array(); |
133 | 183 | @exec(sprintf('git show %s 2>&1', escapeshellarg($path)), $output, $exit); |
134 | 184 | $outputString = implode("\n", $output); |
135 | 185 |
|
136 | 186 | if (0 !== $exit) { |
137 | | - throw new \RuntimeException(sprintf('Could not open file %s or find it in git as %s: %s', $originalPath, $path, $outputString)); |
| 187 | + if ($lockFile) { |
| 188 | + throw new \RuntimeException(sprintf('Could not open file %s or find it in git as %s: %s', $originalPath, $path, $outputString)); |
| 189 | + } |
| 190 | + |
| 191 | + return '{}'; // Do not throw exception for composer.json as it might not exist and that's fine |
138 | 192 | } |
139 | 193 |
|
140 | 194 | return $outputString; |
141 | 195 | } |
| 196 | + |
| 197 | + /** |
| 198 | + * @param string $path |
| 199 | + * |
| 200 | + * @return string |
| 201 | + */ |
| 202 | + private function getJsonPath($path) |
| 203 | + { |
| 204 | + if (self::EXTENSION_LOCK === substr($path, -strlen(self::EXTENSION_LOCK))) { |
| 205 | + return substr($path, 0, -strlen(self::EXTENSION_LOCK)).self::EXTENSION_JSON; |
| 206 | + } |
| 207 | + |
| 208 | + return $path; |
| 209 | + } |
142 | 210 | } |
0 commit comments