Skip to content
This repository was archived by the owner on Mar 1, 2023. It is now read-only.

Commit 234cf7a

Browse files
authored
new feature for automatic (#105)
| Q | A | --------------- | --- | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | no | Related tickets | fixes #104, fixes #103, fixes #106 | License | MIT | Doc PR | -
1 parent 566bab0 commit 234cf7a

File tree

9 files changed

+135
-43
lines changed

9 files changed

+135
-43
lines changed

src/Automatic/Automatic.php

+24
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Narrowspark\Automatic;
44

55
use Closure;
6+
use Composer\Command\GlobalCommand;
67
use Composer\Composer;
78
use Composer\Config;
89
use Composer\Console\Application;
@@ -132,6 +133,13 @@ class Automatic implements PluginInterface, EventSubscriberInterface
132133
*/
133134
private $postMessages = [''];
134135

136+
/**
137+
* Check for global command.
138+
*
139+
* @var bool
140+
*/
141+
private static $isGlobalCommand = false;
142+
135143
/**
136144
* Get the Container instance.
137145
*
@@ -290,6 +298,10 @@ public function record(PackageEvent $event): void
290298
*/
291299
public function initAutoScripts(): void
292300
{
301+
if (self::$isGlobalCommand) {
302+
return;
303+
}
304+
293305
$scripts = $this->container->get(Composer::class)->getPackage()->getScripts();
294306

295307
$autoScript = '@' . ScriptEvents::AUTO_SCRIPTS;
@@ -338,6 +350,10 @@ public function initAutoScripts(): void
338350
*/
339351
public function onPostCreateProject(Event $event): void
340352
{
353+
if (self::$isGlobalCommand) {
354+
return;
355+
}
356+
341357
/** @var \Composer\Json\JsonFile $json */
342358
/** @var \Composer\Json\JsonManipulator $manipulator */
343359
[$json, $manipulator] = Util::getComposerJsonFileAndManipulator();
@@ -371,6 +387,10 @@ public function onPostCreateProject(Event $event): void
371387
*/
372388
public function runSkeletonGenerator(Event $event): void
373389
{
390+
if (self::$isGlobalCommand) {
391+
return;
392+
}
393+
374394
/** @var \Narrowspark\Automatic\Lock $lock */
375395
$lock = $this->container->get(Lock::class);
376396

@@ -1004,6 +1024,10 @@ private function extendComposer($backtrace): void
10041024
continue;
10051025
}
10061026

1027+
if ($trace['object'] instanceof GlobalCommand) {
1028+
self::$isGlobalCommand = true;
1029+
}
1030+
10071031
if (! $trace['object'] instanceof Application || ! $trace['args'][0] instanceof ArgvInput) {
10081032
continue;
10091033
}

src/Automatic/Configurator/CopyFromPackageConfigurator.php

+23-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,31 @@ public function configure(PackageContract $package): void
2626

2727
foreach ((array) $package->getConfig(ConfiguratorContract::TYPE, self::getName()) as $from => $to) {
2828
$target = self::expandTargetDir($this->options, $to);
29+
$from = $this->path->concatenate([
30+
$this->composer->getConfig()->get('vendor-dir') . \DIRECTORY_SEPARATOR,
31+
\str_replace('/', \DIRECTORY_SEPARATOR, $package->getPrettyName()) . \DIRECTORY_SEPARATOR,
32+
$from,
33+
]);
34+
35+
if (! \is_dir($from) && ! \is_file($from)) {
36+
$this->write(\sprintf(
37+
'<fg=red>Failed to find the from folder or file path for "%s" in "%s" package</>',
38+
$from,
39+
$package->getName()
40+
));
41+
42+
return;
43+
}
2944

3045
try {
31-
$this->filesystem->copy(
32-
$this->path->concatenate([$this->composer->getConfig()->get('vendor-dir') . '/' . $package->getPrettyName() . '/', $from]),
46+
$functionName = 'copy';
47+
48+
if (\is_dir($from)) {
49+
$functionName = 'mirror';
50+
}
51+
52+
$this->filesystem->{$functionName}(
53+
$from,
3354
$this->path->concatenate([$this->path->getWorkingDir(), $target])
3455
);
3556

src/Common/Path.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function relativize(string $absolutePath): string
4040
{
4141
$relativePath = \str_replace($this->workingDirectory, '.', $absolutePath);
4242

43-
return \is_dir($absolutePath) ? \rtrim($relativePath, '/') . '/' : $relativePath;
43+
return \is_dir($absolutePath) ? \rtrim($relativePath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR : $relativePath;
4444
}
4545

4646
/**
@@ -53,7 +53,7 @@ public function concatenate(array $parts): string
5353
$first = \array_shift($parts);
5454

5555
return \array_reduce($parts, function (string $initial, string $next): string {
56-
return \rtrim($initial, '/') . '/' . \ltrim($next, '/');
56+
return \rtrim($initial, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR . \ltrim($next, \DIRECTORY_SEPARATOR);
5757
}, $first);
5858
}
5959
}

src/Common/ScriptExtender/PhpScriptExtender.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
declare(strict_types=1);
33
namespace Narrowspark\Automatic\Common\ScriptExtender;
44

5+
use Composer\Util\ProcessExecutor;
56
use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException;
67
use Symfony\Component\Process\PhpExecutableFinder;
78

@@ -39,8 +40,8 @@ public function expand(string $cmd): string
3940
$arguments[] = '--php-ini=' . $ini;
4041
}
4142

42-
$phpArgs = \implode(' ', \array_map('escapeshellarg', $arguments));
43+
$phpArgs = \implode(' ', \array_map([ProcessExecutor::class, 'escape'], $arguments));
4344

44-
return \escapeshellarg((string) $php) . ($phpArgs !== '' ? ' ' . $phpArgs : '') . ' ' . $cmd;
45+
return ProcessExecutor::escape((string) $php) . ($phpArgs !== '' ? ' ' . $phpArgs : '') . ' ' . $cmd;
4546
}
4647
}

src/Security/Command/AuditCommand.php

+11-5
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,12 @@ protected function configure(): void
3636
new InputOption('composer-lock', '', InputOption::VALUE_REQUIRED, 'Path to a composer.lock'),
3737
new InputOption('format', '', InputOption::VALUE_REQUIRED, 'The output format', 'txt'),
3838
new InputOption('timeout', '', InputOption::VALUE_REQUIRED, 'The HTTP timeout in seconds'),
39+
new InputOption('disable-exit', '', InputOption::VALUE_NONE, 'Only shows which vulnerabilities was found or not (without exit code)'),
3940
])
4041
->setDescription('Checks security issues in your project dependencies')
4142
->setHelp(
4243
<<<'EOF'
43-
The <info>%command.name%</info> command looks for security issues in the
44-
project dependencies:
45-
<info>%command.full_name%</info>
44+
The <info>%command.name%</info> command looks for security issues in the project dependencies.
4645
EOF
4746
);
4847
}
@@ -78,6 +77,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7877
$output = new SymfonyStyle($input, $output);
7978
$output->writeln('=== Audit Security Report ===');
8079

80+
$errorExitCode = 1;
81+
82+
if ($input->getOption('disable-exit') !== false) {
83+
$errorExitCode = 0;
84+
}
85+
8186
try {
8287
[$vulnerabilities, $messages] = $audit->checkLock($composerFile);
8388
} catch (RuntimeException $exception) {
@@ -86,7 +91,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8691

8792
$output->writeln($formatter->formatBlock($exception->getMessage(), 'error', true));
8893

89-
return 1;
94+
return $errorExitCode;
9095
}
9196

9297
$message = 'This checker can only detect vulnerabilities that are referenced in the SensioLabs security advisories database.';
@@ -123,10 +128,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
123128
}
124129

125130
$formatter->displayResults($output, $vulnerabilities);
131+
126132
$output->writeln('<error>[!]</> ' . \sprintf('%s vulnerabilit%s found - ', $count, $count === 1 ? 'y' : 'ies') .
127133
'We recommend you to check the related security advisories and upgrade these dependencies.');
128134

129-
return 1;
135+
return $errorExitCode;
130136
}
131137

132138
$output->writeln('<fg=black;bg=green>[+]</> No known vulnerabilities found');

src/Security/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ Installation
2020
Use [Composer](https://getcomposer.org/) to install this package:
2121

2222
```sh
23-
composer require narrowspark/automatic-security-audit
23+
composer require narrowspark/automatic-security-audit --dev
2424
```
2525

2626
Usage
2727
-------------
2828

29-
The checker will be executed when you launch `composer install` or `composer update`.
29+
The checker will be executed when you launch `composer require` , `composer install` or `composer update`.
3030
If you have alerts in your composer.lock, `composer audit` will print them.
3131

3232
Contributing

tests/Automatic/Configurator/CopyFromPackageConfiguratorTest.php

+46-21
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function testCopyFileFromPackage(): void
6464

6565
$this->configurator->configure($package);
6666

67-
$filePath = \sys_get_temp_dir() . '/' . $toFileName;
67+
$filePath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . '' . $toFileName;
6868

6969
$this->assertFileExists($filePath);
7070

@@ -73,7 +73,7 @@ public function testCopyFileFromPackage(): void
7373

7474
public function testCopyDirWithFileFromPackage(): void
7575
{
76-
$toAndFromFileName = '/css/style.css';
76+
$toAndFromFileName = \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css';
7777

7878
$package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName);
7979

@@ -82,12 +82,12 @@ public function testCopyDirWithFileFromPackage(): void
8282
->with([' - Copying files'], true, IOInterface::VERBOSE);
8383
$this->ioMock->shouldReceive('writeError')
8484
->once()
85-
->with([' - Created <fg=green>"/css/style.css"</>'], true, IOInterface::VERBOSE);
85+
->with([' - Created <fg=green>"' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"</>'], true, IOInterface::VERBOSE);
8686

8787
$this->configurator->configure($package);
8888

89-
$dirPath = \sys_get_temp_dir() . '/css';
90-
$filePath = $dirPath . '/style.css';
89+
$dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css';
90+
$filePath = $dirPath . \DIRECTORY_SEPARATOR . 'style.css';
9191

9292
$this->assertDirectoryExists($dirPath);
9393
$this->assertFileExists($filePath);
@@ -96,7 +96,32 @@ public function testCopyDirWithFileFromPackage(): void
9696
\rmdir($dirPath);
9797
}
9898

99-
public function testTryCopyAFileThatIsNotFoundFromPackage(): void
99+
public function testCopyDirFromPackage(): void
100+
{
101+
$toAndFromFileName = \DIRECTORY_SEPARATOR . 'css';
102+
103+
$package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName);
104+
105+
$this->ioMock->shouldReceive('writeError')
106+
->once()
107+
->with([' - Copying files'], true, IOInterface::VERBOSE);
108+
$this->ioMock->shouldReceive('writeError')
109+
->once()
110+
->with([' - Created <fg=green>"' . \DIRECTORY_SEPARATOR . 'css"</>'], true, IOInterface::VERBOSE);
111+
112+
$this->configurator->configure($package);
113+
114+
$dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css';
115+
$filePath = $dirPath . \DIRECTORY_SEPARATOR . 'style.css';
116+
117+
$this->assertDirectoryExists($dirPath);
118+
$this->assertFileExists($filePath);
119+
120+
\unlink($filePath);
121+
\rmdir($dirPath);
122+
}
123+
124+
public function testTryCopyFileThatIsNotFoundFromPackage(): void
100125
{
101126
$toFileName = 'notfound.txt';
102127

@@ -107,11 +132,11 @@ public function testTryCopyAFileThatIsNotFoundFromPackage(): void
107132
->with([' - Copying files'], true, IOInterface::VERBOSE);
108133
$this->ioMock->shouldReceive('writeError')
109134
->once()
110-
->with([' - <fg=red>Failed to create "notfound.txt"</>; Error message: Failed to copy "' . __DIR__ . '/Stub/stub/notfound.txt" because file does not exist.'], true, IOInterface::VERBOSE);
135+
->with([' - <fg=red>Failed to find the from folder or file path for "' . __DIR__ . \DIRECTORY_SEPARATOR . 'Stub' . \DIRECTORY_SEPARATOR . 'stub' . \DIRECTORY_SEPARATOR . 'notfound.txt" in "' . $package->getName() . '" package</>'], true, IOInterface::VERBOSE);
111136

112137
$this->configurator->configure($package);
113138

114-
$filePath = \sys_get_temp_dir() . '/' . $toFileName;
139+
$filePath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . '' . $toFileName;
115140

116141
$this->assertFileNotExists($filePath);
117142
}
@@ -143,7 +168,7 @@ public function testUnconfigureAFileFromPackage(): void
143168

144169
public function testUnconfigureADirWithFileFromPackage(): void
145170
{
146-
$toAndFromFileName = '/css/style.css';
171+
$toAndFromFileName = \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css';
147172

148173
$package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName);
149174

@@ -152,7 +177,7 @@ public function testUnconfigureADirWithFileFromPackage(): void
152177
->with([' - Copying files'], true, IOInterface::VERBOSE);
153178
$this->ioMock->shouldReceive('writeError')
154179
->once()
155-
->with([' - Created <fg=green>"/css/style.css"</>'], true, IOInterface::VERBOSE);
180+
->with([' - Created <fg=green>"' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"</>'], true, IOInterface::VERBOSE);
156181

157182
$this->configurator->configure($package);
158183

@@ -161,11 +186,11 @@ public function testUnconfigureADirWithFileFromPackage(): void
161186
->with([' - Removing files'], true, IOInterface::VERBOSE);
162187
$this->ioMock->shouldReceive('writeError')
163188
->once()
164-
->with([' - Removed <fg=green>"/css/style.css"</>'], true, IOInterface::VERBOSE);
189+
->with([' - Removed <fg=green>"' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"</>'], true, IOInterface::VERBOSE);
165190

166191
$this->configurator->unconfigure($package);
167192

168-
$dirPath = \sys_get_temp_dir() . '/css';
193+
$dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css';
169194

170195
$this->assertDirectoryExists($dirPath);
171196

@@ -174,7 +199,7 @@ public function testUnconfigureADirWithFileFromPackage(): void
174199

175200
public function testUnconfigureWithAIOException(): void
176201
{
177-
$toAndFromFileName = '/css/style.css';
202+
$toAndFromFileName = \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css';
178203

179204
$package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName);
180205

@@ -183,7 +208,7 @@ public function testUnconfigureWithAIOException(): void
183208
->with([' - Copying files'], true, IOInterface::VERBOSE);
184209
$this->ioMock->shouldReceive('writeError')
185210
->once()
186-
->with([' - Created <fg=green>"/css/style.css"</>'], true, IOInterface::VERBOSE);
211+
->with([' - Created <fg=green>"' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"</>'], true, IOInterface::VERBOSE);
187212

188213
$this->configurator->configure($package);
189214

@@ -200,13 +225,13 @@ public function testUnconfigureWithAIOException(): void
200225
->with([' - Removing files'], true, IOInterface::VERBOSE);
201226
$this->ioMock->shouldReceive('writeError')
202227
->once()
203-
->with([' - <fg=red>Failed to remove "/css/style.css"</>; Error message: '], true, IOInterface::VERBOSE);
228+
->with([' - <fg=red>Failed to remove "' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"</>; Error message: '], true, IOInterface::VERBOSE);
204229

205230
$this->configurator->unconfigure($package);
206231

207-
$dirPath = \sys_get_temp_dir() . '/css';
232+
$dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css';
208233

209-
\unlink($dirPath . '/style.css');
234+
\unlink($dirPath . \DIRECTORY_SEPARATOR . 'style.css');
210235

211236
$this->assertDirectoryExists($dirPath);
212237

@@ -217,23 +242,23 @@ public function testCopyFileFromPackageWithConfig(): void
217242
{
218243
$toFileName = 'copy_of_copy.txt';
219244

220-
$package = $this->arrangePackageWithConfig('copy.txt', '%SELF_DIR%/' . $toFileName);
245+
$package = $this->arrangePackageWithConfig('copy.txt', '%SELF_DIR%' . \DIRECTORY_SEPARATOR . $toFileName);
221246

222247
$this->ioMock->shouldReceive('writeError')
223248
->once()
224249
->with([' - Copying files'], true, IOInterface::VERBOSE);
225250
$this->ioMock->shouldReceive('writeError')
226251
->once()
227-
->with([' - Created <fg=green>"test/copy_of_copy.txt"</>'], true, IOInterface::VERBOSE);
252+
->with([' - Created <fg=green>"test' . \DIRECTORY_SEPARATOR . 'copy_of_copy.txt"</>'], true, IOInterface::VERBOSE);
228253

229254
$this->configurator->configure($package);
230255

231-
$filePath = \sys_get_temp_dir() . '/test/' . $toFileName;
256+
$filePath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'test' . \DIRECTORY_SEPARATOR . $toFileName;
232257

233258
$this->assertFileExists($filePath);
234259

235260
\unlink($filePath);
236-
\rmdir(\sys_get_temp_dir() . '/test/');
261+
\rmdir(\sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'test' . \DIRECTORY_SEPARATOR);
237262
}
238263

239264
/**

0 commit comments

Comments
 (0)