Page MenuHomePhabricator

D13651.id32999.diff
No OneTemporary

D13651.id32999.diff

diff --git a/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php
--- a/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php
+++ b/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php
@@ -180,22 +180,48 @@
* @return string String with variables replaced safely into it.
*/
protected function mergeVariables($function, $pattern, array $variables) {
- $regexp = '/\\$\\{(?P<name>[a-zA-Z\\.]+)\\}/';
+ $regexp = '/\\$\\{(?P<opt>\\??)(?P<name>[a-zA-Z\\.]+)\\}/';
$matches = null;
preg_match_all($regexp, $pattern, $matches);
$argv = array();
- foreach ($matches['name'] as $name) {
+ $remove_at = array();
+ $remove_at_count = 0;
+ foreach ($matches['name'] as $idx => $name) {
+ $is_optional = $matches['opt'][$idx] === '?';
+ if ($is_optional && idx($variables, $name, '') === '') {
+ // Skip this variable entirely (don't even put quotes around
+ // the empty argument).
+ $remove_at[] = $remove_at_count++;
+ continue;
+ }
if (!array_key_exists($name, $variables)) {
throw new Exception(pht("No such variable '%s'!", $name));
}
$argv[] = $variables[$name];
+ $remove_at_count++;
}
$pattern = str_replace('%', '%%', $pattern);
$pattern = preg_replace($regexp, '%s', $pattern);
+ // Remove %s for optional arguments which have been omitted.
+ $total_replacements = substr_count($pattern, '%s');
+ $current_offset = 0;
+ for ($i = 0; $i < $total_replacements && count($remove_at) > 0; $i++) {
+ $current_offset = strpos($pattern, '%s', $current_offset);
+ $head = head($remove_at);
+ if ($head === $i) {
+ $pattern =
+ substr($pattern, 0, $current_offset).
+ substr($pattern, $current_offset + 2);
+ array_shift($remove_at);
+ } else {
+ $current_offset += 2;
+ }
+ }
+
return call_user_func($function, $pattern, $argv);
}
diff --git a/src/applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php b/src/applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php
--- a/src/applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php
+++ b/src/applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php
@@ -8,4 +8,201 @@
$this->assertTrue(true);
}
+ public function testVariableMergeForRequiredVariables() {
+ $variables = array(
+ 'mandatory' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${mandatory}b c${withvalue}d',
+ $variables);
+
+ $this->assertEqual("echo a''b c'val'd", (string)$result);
+ }
+
+ public function testVariableMergeForMixedVariables1() {
+ $variables = array(
+ 'mandatory' => '',
+ 'optional' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${mandatory}b c${withvalue}d e${?optional}f',
+ $variables);
+
+ $this->assertEqual("echo a''b c'val'd ef", (string)$result);
+ }
+
+ public function testVariableMergeForMixedVariables2() {
+ $variables = array(
+ 'mandatory' => '',
+ 'optional' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${mandatory}b e${?optional}f c${withvalue}d',
+ $variables);
+
+ $this->assertEqual("echo a''b ef c'val'd", (string)$result);
+ }
+
+ public function testVariableMergeForMixedVariables3() {
+ $variables = array(
+ 'mandatory' => '',
+ 'optional' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo e${?optional}f a${mandatory}b c${withvalue}d',
+ $variables);
+
+ $this->assertEqual("echo ef a''b c'val'd", (string)$result);
+ }
+
+ public function testVariableMergeForMixedVariables4() {
+ $variables = array(
+ 'mandatory' => '',
+ 'optional' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${?optional}b c${mandatory}d e${?optional}f '.
+ 'g${withvalue}h i${?optional}j',
+ $variables);
+
+ $this->assertEqual("echo ab c''d ef g'val'h ij", (string)$result);
+ }
+
+ public function testVariableMergeForMissingVariables1() {
+ $variables = array(
+ 'mandatory' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${mandatory}b c${withvalue}d e${?optional}f',
+ $variables);
+
+ $this->assertEqual("echo a''b c'val'd ef", (string)$result);
+ }
+
+ public function testVariableMergeForMissingVariables2() {
+ $variables = array(
+ 'mandatory' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${mandatory}b e${?optional}f c${withvalue}d',
+ $variables);
+
+ $this->assertEqual("echo a''b ef c'val'd", (string)$result);
+ }
+
+ public function testVariableMergeForMissingVariables3() {
+ $variables = array(
+ 'mandatory' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo e${?optional}f a${mandatory}b c${withvalue}d',
+ $variables);
+
+ $this->assertEqual("echo ef a''b c'val'd", (string)$result);
+ }
+
+ public function testVariableMergeForMissingVariables4() {
+ $variables = array(
+ 'mandatory' => '',
+ 'withvalue' => 'val',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${?optional}b c${mandatory}d '.
+ 'e${?optional}f g${withvalue}h i${?optional}j',
+ $variables);
+
+ $this->assertEqual("echo ab c''d ef g'val'h ij", (string)$result);
+ }
+
+ public function testVariableMergeReplication1() {
+ $variables = array(
+ 'mandatory' => '',
+ );
+
+ $method = new ReflectionMethod(
+ 'HarbormasterBuildStepImplementation',
+ 'mergeVariables');
+ $method->setAccessible(true);
+ $result = $method->invoke(
+ new HarbormasterCommandBuildStepImplementation(),
+ 'vcsprintf',
+ 'echo a${?optional}b c${mandatory}d e${?optional}f '.
+ 'g${mandatory}h i${mandatory}j k${?optional}l m${?optional}n',
+ $variables);
+
+ $this->assertEqual("echo ab c''d ef g''h i''j kl mn", (string)$result);
+ }
+
+
}

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 29, 1:01 AM (1 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7725816
Default Alt Text
D13651.id32999.diff (8 KB)

Event Timeline