From 5fc2499b520bacad57f2d51773eb63b2028d302a Mon Sep 17 00:00:00 2001
From: webchick <drupal@webchick.net>
Date: Wed, 9 Sep 2015 23:00:42 -0700
Subject: [PATCH] Issue #2565669 by plach: Update Twig to 1.21.2

---
 core/composer.lock                            |  10 +-
 core/vendor/composer/installed.json           | 126 +++++++++---------
 core/vendor/twig/twig/CHANGELOG               |   7 +
 core/vendor/twig/twig/doc/filters/merge.rst   |   3 +-
 core/vendor/twig/twig/doc/filters/sort.rst    |   3 +-
 core/vendor/twig/twig/doc/recipes.rst         |   2 +-
 core/vendor/twig/twig/ext/twig/php_twig.h     |   2 +-
 .../vendor/twig/twig/lib/Twig/Environment.php |   2 +-
 .../twig/twig/lib/Twig/ExpressionParser.php   |   4 +-
 .../twig/twig/lib/Twig/Extension/Core.php     |  59 ++++++--
 .../Twig/FileExtensionEscapingStrategy.php    |  17 ++-
 .../FileExtensionEscapingStrategyTest.php     |   4 +-
 .../Twig/Tests/Fixtures/filters/merge.test    |   4 +-
 .../Twig/Tests/Fixtures/filters/replace.test  |   8 +-
 .../Fixtures/filters/replace_invalid_arg.test |   8 ++
 .../Twig/Tests/Fixtures/filters/sort.test     |   4 +-
 16 files changed, 168 insertions(+), 95 deletions(-)
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test

diff --git a/core/composer.lock b/core/composer.lock
index e1e7037bf56b..40f50fb12f76 100644
--- a/core/composer.lock
+++ b/core/composer.lock
@@ -3037,16 +3037,16 @@
         },
         {
             "name": "twig/twig",
-            "version": "v1.21.1",
+            "version": "v1.21.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/twigphp/Twig.git",
-                "reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23"
+                "reference": "ddce1136beb8db29b9cd7dffa8ab518b978c9db3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/twigphp/Twig/zipball/ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
-                "reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
+                "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddce1136beb8db29b9cd7dffa8ab518b978c9db3",
+                "reference": "ddce1136beb8db29b9cd7dffa8ab518b978c9db3",
                 "shasum": ""
             },
             "require": {
@@ -3094,7 +3094,7 @@
             "keywords": [
                 "templating"
             ],
-            "time": "2015-08-26 08:58:31"
+            "time": "2015-09-09 05:28:51"
         },
         {
             "name": "zendframework/zend-diactoros",
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index 8bc1933316c5..14a7478379b7 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -1727,69 +1727,6 @@
             "psr-7"
         ]
     },
-    {
-        "name": "twig/twig",
-        "version": "v1.21.1",
-        "version_normalized": "1.21.1.0",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/twigphp/Twig.git",
-            "reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23"
-        },
-        "dist": {
-            "type": "zip",
-            "url": "https://api.github.com/repos/twigphp/Twig/zipball/ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
-            "reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
-            "shasum": ""
-        },
-        "require": {
-            "php": ">=5.2.7"
-        },
-        "require-dev": {
-            "symfony/debug": "~2.7",
-            "symfony/phpunit-bridge": "~2.7"
-        },
-        "time": "2015-08-26 08:58:31",
-        "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "1.21-dev"
-            }
-        },
-        "installation-source": "dist",
-        "autoload": {
-            "psr-0": {
-                "Twig_": "lib/"
-            }
-        },
-        "notification-url": "https://packagist.org/downloads/",
-        "license": [
-            "BSD-3-Clause"
-        ],
-        "authors": [
-            {
-                "name": "Fabien Potencier",
-                "email": "fabien@symfony.com",
-                "homepage": "http://fabien.potencier.org",
-                "role": "Lead Developer"
-            },
-            {
-                "name": "Armin Ronacher",
-                "email": "armin.ronacher@active-4.com",
-                "role": "Project Founder"
-            },
-            {
-                "name": "Twig Team",
-                "homepage": "http://twig.sensiolabs.org/contributors",
-                "role": "Contributors"
-            }
-        ],
-        "description": "Twig, the flexible, fast, and secure template language for PHP",
-        "homepage": "http://twig.sensiolabs.org",
-        "keywords": [
-            "templating"
-        ]
-    },
     {
         "name": "fabpot/goutte",
         "version": "v3.1.1",
@@ -3415,5 +3352,68 @@
         ],
         "description": "Symfony BrowserKit Component",
         "homepage": "https://symfony.com"
+    },
+    {
+        "name": "twig/twig",
+        "version": "v1.21.2",
+        "version_normalized": "1.21.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/twigphp/Twig.git",
+            "reference": "ddce1136beb8db29b9cd7dffa8ab518b978c9db3"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddce1136beb8db29b9cd7dffa8ab518b978c9db3",
+            "reference": "ddce1136beb8db29b9cd7dffa8ab518b978c9db3",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.2.7"
+        },
+        "require-dev": {
+            "symfony/debug": "~2.7",
+            "symfony/phpunit-bridge": "~2.7"
+        },
+        "time": "2015-09-09 05:28:51",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.21-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Twig_": "lib/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com",
+                "homepage": "http://fabien.potencier.org",
+                "role": "Lead Developer"
+            },
+            {
+                "name": "Armin Ronacher",
+                "email": "armin.ronacher@active-4.com",
+                "role": "Project Founder"
+            },
+            {
+                "name": "Twig Team",
+                "homepage": "http://twig.sensiolabs.org/contributors",
+                "role": "Contributors"
+            }
+        ],
+        "description": "Twig, the flexible, fast, and secure template language for PHP",
+        "homepage": "http://twig.sensiolabs.org",
+        "keywords": [
+            "templating"
+        ]
     }
 ]
diff --git a/core/vendor/twig/twig/CHANGELOG b/core/vendor/twig/twig/CHANGELOG
index 6e574d4d51d5..ee447b06612d 100644
--- a/core/vendor/twig/twig/CHANGELOG
+++ b/core/vendor/twig/twig/CHANGELOG
@@ -1,3 +1,10 @@
+* 1.21.2 (2015-09-09)
+
+ * fixed variable names for the deprecation triggering code
+ * fixed escaping strategy detection based on filename
+ * added Traversable support for replace, merge, and sort
+ * deprecated support for character by character replacement for the "replace" filter
+
 * 1.21.1 (2015-08-26)
 
  * fixed regression when using the deprecated Twig_Test_* classes
diff --git a/core/vendor/twig/twig/doc/filters/merge.rst b/core/vendor/twig/twig/doc/filters/merge.rst
index cb8b1b2230eb..88780dd6ff63 100644
--- a/core/vendor/twig/twig/doc/filters/merge.rst
+++ b/core/vendor/twig/twig/doc/filters/merge.rst
@@ -42,6 +42,7 @@ overridden.
         
 .. note::
 
-    Internally, Twig uses the PHP `array_merge`_ function.
+    Internally, Twig uses the PHP `array_merge`_ function. It supports
+    Traversable objects by transforming those to arrays.
 
 .. _`array_merge`: http://php.net/array_merge
diff --git a/core/vendor/twig/twig/doc/filters/sort.rst b/core/vendor/twig/twig/doc/filters/sort.rst
index 33311528fb2d..350207f8e02b 100644
--- a/core/vendor/twig/twig/doc/filters/sort.rst
+++ b/core/vendor/twig/twig/doc/filters/sort.rst
@@ -12,6 +12,7 @@ The ``sort`` filter sorts an array:
 .. note::
 
     Internally, Twig uses the PHP `asort`_ function to maintain index
-    association.
+    association. It supports Traversable objects by transforming
+    those to arrays.
 
 .. _`asort`: http://php.net/asort
diff --git a/core/vendor/twig/twig/doc/recipes.rst b/core/vendor/twig/twig/doc/recipes.rst
index b863e103c7dc..450ce558f4ee 100644
--- a/core/vendor/twig/twig/doc/recipes.rst
+++ b/core/vendor/twig/twig/doc/recipes.rst
@@ -349,7 +349,7 @@ cache::
 
             // Compile cached file into bytecode cache
             if (extension_loaded('Zend OPcache') && ini_get('opcache.enable')) {
-                opcache_compile_file($file);
+                opcache_invalidate($file);
             } elseif (extension_loaded('apc') && ini_get('apc.enabled')) {
                 apc_compile_file($file);
             }
diff --git a/core/vendor/twig/twig/ext/twig/php_twig.h b/core/vendor/twig/twig/ext/twig/php_twig.h
index 0423b1d9c8fb..27be05bb7264 100644
--- a/core/vendor/twig/twig/ext/twig/php_twig.h
+++ b/core/vendor/twig/twig/ext/twig/php_twig.h
@@ -15,7 +15,7 @@
 #ifndef PHP_TWIG_H
 #define PHP_TWIG_H
 
-#define PHP_TWIG_VERSION "1.21.1"
+#define PHP_TWIG_VERSION "1.21.2"
 
 #include "php.h"
 
diff --git a/core/vendor/twig/twig/lib/Twig/Environment.php b/core/vendor/twig/twig/lib/Twig/Environment.php
index 7687d5b7958d..6813a301d78e 100644
--- a/core/vendor/twig/twig/lib/Twig/Environment.php
+++ b/core/vendor/twig/twig/lib/Twig/Environment.php
@@ -16,7 +16,7 @@
  */
 class Twig_Environment
 {
-    const VERSION = '1.21.1';
+    const VERSION = '1.21.2';
 
     protected $charset;
     protected $loader;
diff --git a/core/vendor/twig/twig/lib/Twig/ExpressionParser.php b/core/vendor/twig/twig/lib/Twig/ExpressionParser.php
index 085588c27248..322976c60ada 100644
--- a/core/vendor/twig/twig/lib/Twig/ExpressionParser.php
+++ b/core/vendor/twig/twig/lib/Twig/ExpressionParser.php
@@ -580,7 +580,7 @@ protected function getFunctionNodeClass($name, $line)
 
         if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
             $message = sprintf('Twig Function "%s" is deprecated', $function->getName());
-            if ($test->getAlternative()) {
+            if ($function->getAlternative()) {
                 $message .= sprintf('. Use "%s" instead', $function->getAlternative());
             }
             $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
@@ -610,7 +610,7 @@ protected function getFilterNodeClass($name, $line)
 
         if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
             $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
-            if ($test->getAlternative()) {
+            if ($filter->getAlternative()) {
                 $message .= sprintf('. Use "%s" instead', $filter->getAlternative());
             }
             $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Core.php b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
index cfffa8031155..4980ceb9335a 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Core.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
@@ -152,7 +152,7 @@ public function getFilters()
             new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)),
             new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
             new Twig_SimpleFilter('format', 'sprintf'),
-            new Twig_SimpleFilter('replace', 'strtr'),
+            new Twig_SimpleFilter('replace', 'twig_replace_filter'),
             new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
             new Twig_SimpleFilter('abs', 'abs'),
             new Twig_SimpleFilter('round', 'twig_round'),
@@ -549,6 +549,30 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
     return $date;
 }
 
+/**
+ * Replaces strings within a string.
+ *
+ * @param string            $str  String to replace in
+ * @param array|Traversable $from Replace values
+ * @param string|null       $to   Replace to, deprecated (@see http://php.net/manual/en/function.strtr.php)
+ *
+ * @return string
+ */
+function twig_replace_filter($str, $from, $to = null)
+{
+    if ($from instanceof Traversable) {
+        $from = iterator_to_array($from);
+    } elseif (is_string($from) && is_string($to)) {
+        @trigger_error('Using "replace" with character by character replacement is deprecated and will be removed in Twig 2.0', E_USER_DEPRECATED);
+
+        return strtr($str, $from, $to);
+    } elseif (!is_array($from)) {
+        throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".',is_object($from) ? get_class($from) : gettype($from)));
+    }
+
+    return strtr($str, $from);
+}
+
 /**
  * Rounds a number.
  *
@@ -682,15 +706,23 @@ function _twig_markup2string(&$value)
  *  {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
  * </pre>
  *
- * @param array $arr1 An array
- * @param array $arr2 An array
+ * @param array|Traversable $arr1 An array
+ * @param array|Traversable $arr2 An array
  *
  * @return array The merged array
  */
 function twig_array_merge($arr1, $arr2)
 {
-    if (!is_array($arr1) || !is_array($arr2)) {
-        throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or hashes; %s and %s given.', gettype($arr1), gettype($arr2)));
+    if ($arr1 instanceof Traversable) {
+        $arr1 = iterator_to_array($arr1);
+    } elseif (!is_array($arr1)) {
+        throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', gettype($arr1)));
+    }
+
+    if ($arr2 instanceof Traversable) {
+        $arr2 = iterator_to_array($arr2);
+    } elseif (!is_array($arr2)) {
+        throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', gettype($arr2)));
     }
 
     return array_merge($arr1, $arr2);
@@ -874,7 +906,7 @@ function _twig_default_filter($value, $default = '')
  */
 function twig_get_array_keys_filter($array)
 {
-    if (is_object($array) && $array instanceof Traversable) {
+    if ($array instanceof Traversable) {
         return array_keys(iterator_to_array($array));
     }
 
@@ -896,7 +928,7 @@ function twig_get_array_keys_filter($array)
  */
 function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
 {
-    if (is_object($item) && $item instanceof Traversable) {
+    if ($item instanceof Traversable) {
         return array_reverse(iterator_to_array($item), $preserveKeys);
     }
 
@@ -928,12 +960,18 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
 /**
  * Sorts an array.
  *
- * @param array $array
+ * @param array|Traversable $array
  *
  * @return array
  */
 function twig_sort_filter($array)
 {
+    if ($array instanceof Traversable) {
+        $array = iterator_to_array($array);
+    } elseif (!is_array($array)) {
+        throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', gettype($array)));
+    }
+
     asort($array);
 
     return $array;
@@ -1304,9 +1342,8 @@ function twig_title_string_filter(Twig_Environment $env, $string)
      */
     function twig_capitalize_string_filter(Twig_Environment $env, $string)
     {
-        if (null !== ($charset = $env->getCharset())) {
-            return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
-                         mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
+        if (null !== $charset = $env->getCharset()) {
+            return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
         }
 
         return ucfirst(strtolower($string));
diff --git a/core/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php b/core/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
index b1ace7dcf327..9bda0b4f6810 100644
--- a/core/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
+++ b/core/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
@@ -27,15 +27,21 @@ class Twig_FileExtensionEscapingStrategy
      *
      * @param string $filename The template file name
      *
-     * @return string The escaping strategy name to use
+     * @return string|false The escaping strategy name to use or false to disable
      */
     public static function guess($filename)
     {
-        if (!preg_match('{\.(js|css|txt)(?:\.[^/\\\\]+)?$}', $filename, $match)) {
-            return 'html';
+        if (in_array(substr($filename, -1), array('/', '\\'))) {
+            return 'html'; // return html for directories
         }
 
-        switch ($match[1]) {
+        if ('.twig' === substr($filename, -5)) {
+            $filename = substr($filename, 0, -5);
+        }
+
+        $extension = pathinfo($filename, PATHINFO_EXTENSION);
+
+        switch ($extension) {
             case 'js':
                 return 'js';
 
@@ -44,6 +50,9 @@ public static function guess($filename)
 
             case 'txt':
                 return false;
+
+            default:
+                return 'html';
         }
     }
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php b/core/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php
index d2f55eb6f3b1..b310a5be3533 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php
@@ -16,7 +16,7 @@ class Twig_Tests_FileExtensionEscapingStrategyTest extends PHPUnit_Framework_Tes
      */
     public function testGuess($strategy, $filename)
     {
-        $this->assertEquals($strategy, Twig_FileExtensionEscapingStrategy::guess($filename));
+        $this->assertSame($strategy, Twig_FileExtensionEscapingStrategy::guess($filename));
     }
 
     public function getGuessData()
@@ -34,6 +34,8 @@ public function getGuessData()
             array('css', 'foo.css'),
             array('css', 'foo.css.twig'),
             array('css', 'foo.twig.css'),
+            array('css', 'foo.js.css'),
+            array('css', 'foo.js.css.twig'),
 
             // js
             array('js', 'foo.js'),
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test
index 2bd3d4c0459e..81371a41b94f 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test
@@ -6,11 +6,13 @@
 {{ {'bar': 'foo'}|merge(items)|join }}
 {{ {'bar': 'foo'}|merge(items)|keys|join }}
 {{ numerics|merge([4, 5, 6])|join }}
+{{ traversable.a|merge(traversable.b)|join }}
 --DATA--
-return array('items' => array('foo' => 'bar'), 'numerics' => array(1, 2, 3))
+return array('items' => array('foo' => 'bar'), 'numerics' => array(1, 2, 3), 'traversable' => array('a' => new ArrayObject(array(0 => 1, 1 => 2, 2 => 3)), 'b' => new ArrayObject(array('a' => 'b'))))
 --EXPECT--
 barfoo
 foobar
 foobar
 barfoo
 123456
+123b
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test
index 4021660beddc..06be7e270aef 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test
@@ -1,8 +1,12 @@
 --TEST--
 "replace" filter
 --TEMPLATE--
-{{ "I like %this% and %that%."|replace({'%this%': "foo", '%that%': "bar"}) }}
+{{ "I liké %this% and %that%."|replace({'%this%': "foo", '%that%': "bar"}) }}
+{{ 'I like single replace operation only %that%'|replace({'%that%' : '%that%1'}) }}
+{{ 'I like %this% and %that%.'|replace(traversable) }}
 --DATA--
-return array()
+return array('traversable' => new ArrayObject(array('%this%' => 'foo', '%that%' => 'bar')))
 --EXPECT--
+I liké foo and bar.
+I like single replace operation only %that%1
 I like foo and bar.
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test
new file mode 100644
index 000000000000..08ecfd4907ac
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test
@@ -0,0 +1,8 @@
+--TEST--
+Exception for invalid argument type in replace call
+--TEMPLATE--
+{{ 'test %foo%'|replace(stdClass) }}
+--DATA--
+return array('stdClass' => new \stdClass())
+--EXCEPTION--
+Twig_Error_Runtime: The "replace" filter expects an array or "Traversable" as replace values, got "stdClass" in "index.twig" at line 2.
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test
index 21d575f18cc9..c67c18ea90a3 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test
@@ -3,8 +3,10 @@
 --TEMPLATE--
 {{ array1|sort|join }}
 {{ array2|sort|join }}
+{{ traversable|sort|join }}
 --DATA--
-return array('array1' => array(4, 1), 'array2' => array('foo', 'bar'))
+return array('array1' => array(4, 1), 'array2' => array('foo', 'bar'), 'traversable' => new ArrayObject(array(0 => 3, 1 => 2, 2 => 1)))
 --EXPECT--
 14
 barfoo
+123
-- 
GitLab