Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4bf2bb3

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

File tree

2 files changed

+89
-1
lines changed
Filter options

2 files changed

+89
-1
lines changed

‎src/Symfony/Component/Process/Process.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Process.php
+33-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Tests/ProcessTest.php
+56Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.