8000 [Process] Allow writing portable "prepared" command lines · symfony/symfony@4bf2bb3 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 4bf2bb3

Browse files
author
Amrouche Hamza
committed
[Process] Allow writing portable "prepared" command lines
1 parent a522e04 commit 4bf2bb3

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

src/Symfony/Component/Process/Process.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,10 @@ public function start(callable $callback = null, array $env = array())
278278

279279
$options = array('suppress_errors' => true);
280280

281-
if ('\\' === DIRECTORY_SEPARATOR) {
281+
$windows = '\\' === DIRECTORY_SEPARATOR;
282+
$commandline = $this->replacePlaceholder($commandline, $windows, $env);
283+
284+
if ($windows) {
282285
$options['bypass_shell'] = true;
283286
$commandline = $this->prepareWindowsCommandLine($commandline, $envBackup);
284287
} elseif (!$this->useFileHandles && $this->isSigchildEnabled()) {
@@ -1562,4 +1565,33 @@ private function escapeArgument($argument)
15621565

15631566
return '"'.str_replace(array('"', '^', '%', '!', "\n"), array('""', '"^^"', '"^%"', '"^!"', '!LF!'), $argument).'"';
15641567
}
1568+
1569+
private function replacePlaceholder($commandLine, $windows, $env)
1570+
{
1571+
$toReplace = $windows ? array('!', '!') : array('$', '');
1572+
if (!preg_match_all('/\{([a-zA-Z0-9]+?)\}/', $commandLine, $matches)) {
1573+
return $commandLine;
1574+
}
1575+
1576+
$patterns = $replacements = array();
1577+
$isInEnv = false;
1578+
foreach ($matches as $match) {
1579+
$patterns[] = sprintf('/{%s}/', $match[0]);
1580+
$replacements[] = sprintf('%s%s%s', $toReplace[0], $match[0], $toReplace[1]);
1581+
if (isset($env[$match[0]])) {
1582+
$isInEnv = true;
1583+
unset($env[$match[0]]);
1584+
}
1585+
}
1586+
1587+
if (!$isInEnv) {
1588+
throw new InvalidArgumentException(sprintf('There are no passed env for the command line "%s", replacement cannot be done.', $commandLine));
1589+
}
1590+
1591+
if (!empty($env)) {
1592+
throw new InvalidArgumentException(sprintf('Placeholder%s "%s" %s exist.', count($env) > 1 ? 's' : '', implode(',', array_keys($env)), count($env) > 1 ? 'doesn\'t' : 'don\'t'));
1593+
}
1594+
1595+
return preg_replace($patterns, $replacements, $commandLine);
1596+
}
15651597
}

src/Symfony/Component/Process/Tests/ProcessTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,62 @@ public function provideEscapeArgument()
14701470
yield array('éÉèÈàÀöä');
14711471
}
14721472

1473+
public function testPreparedCommand()
1474+
{
1475+
$p = new Process('echo {abc}');
1476+
$p->run(null, array('abc' => 'ABC'));
1477+
1478+
$expected = <<<EOTXT
1479+
ABC\n
1480+
EOTXT;
1481+
$this->assertSame($expected, $p->getOutput());
1482+
}
1483+
1484+
/**
1485+
* @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
1486+
* @expectedExceptionMessage Placeholder "bcd" don't exist
1487+
*/
1488+
public function testPreparedCommandWithTooMuchEnv()
1489+
{
1490+
$p = new Process('echo {abc}');
1491+
$p->run(null, array('abc' => 'ABC', 'bcd' => 'ABC'));
1492+
1493+
$expected = <<<EOTXT
1494+
ABC\n
1495+
EOTXT;
1496+
$this->assertSame($expected, $p->getOutput());
1497+
}
1498+
1499+
/**
1500+
* @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
1501+
* @expectedExceptionMessage Placeholders "bcd,zaza" doesn't exist
1502+
*/
1503+
public function testPreparedCommandWithTwoMoreEnvs()
1504+
{
1505+
$p = new Process('echo {abc}');
1506+
$p->run(null, array('abc' => 'ABC', 'bcd' => 'ABC', 'zaza' => 'ABC'));
1507+
1508+
$expected = <<<EOTXT
1509+
ABC\n
1510+
EOTXT;
1511+
$this->assertSame($expected, $p->getOutput());
1512+
}
1513+
1514+
/**
1515+
* @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
1516+
* @expectedExceptionMessage There are no passed env for the command line "echo {abc}", replacement cannot be done.
1517+
*/
1518+
public function testPreparedCommandWithoutProvidedParam()
1519+
{
1520+
$p = new Process('echo {abc}');
1521+
$p->run(null, array('bcd' => 'ABC'));
1522+
1523+
$expected = <<<EOTXT
1524+
ABC
1525+
EOTXT;
1526+
$this->assertSame($expected, $p->getOutput());
1527+
}
1528+
14731529
public function testEnvArgument()
14741530
{
14751531
$env = array('FOO' => 'Foo', 'BAR' => 'Bar');

0 commit comments

Comments
 (0)
0