浏览代码

Merge branch '1.0'

Jordi Boggiano 9 年之前
父节点
当前提交
95e0347917

+ 9 - 0
CHANGELOG.md

@@ -1,3 +1,11 @@
+### [1.0.2] - 2016-04-21
+
+  * Fixed regression in 1.0.1 on systems with mbstring.func_overload enabled
+  * Fixed regression in 1.0.1 that made dev packages update to the latest reference even if not whitelisted in a partial update
+  * Fixed init command ignoring the COMPOSER env var for choosing the json file name
+  * Fixed error reporting bug when the dependency resolution fails
+  * Fixed handling of `$` sign in composer config command in some cases it could corrupt the json file
+
 ### [1.0.1] - 2016-04-18
 
   * Fixed URL updating when a package's URL changes, composer.lock now contains the right URL including correct reference
@@ -335,6 +343,7 @@
 
   * Initial release
 
+[1.0.2]: https://github.com/composer/composer/compare/1.0.2...1.0.2
 [1.0.1]: https://github.com/composer/composer/compare/1.0.0...1.0.1
 [1.0.0]: https://github.com/composer/composer/compare/1.0.0-beta2...1.0.0
 [1.0.0-beta2]: https://github.com/composer/composer/compare/1.0.0-beta1...1.0.0-beta2

+ 11 - 7
src/Composer/Json/JsonManipulator.php

@@ -74,14 +74,16 @@ class JsonManipulator
         if (isset($decoded[$type][$package])) {
             // update existing link
             $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
-            // addcslashes is used to double up backslashes since preg_replace resolves them as back references otherwise, see #1588
-            $links = preg_replace('{"'.$packageRegex.'"(\s*:\s*)'.self::$JSON_STRING.'}i', addcslashes(JsonFile::encode($package).'${1}"'.$constraint.'"', '\\'), $links);
+            $links = preg_replace_callback('{"'.$packageRegex.'"(\s*:\s*)'.self::$JSON_STRING.'}i', function ($m) use ($package, $constraint) {
+                return JsonFile::encode($package) . $m[1] . '"' . $constraint . '"';
+            }, $links);
         } else {
             if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
                 // link missing but non empty links
                 $links = preg_replace(
                     '{'.preg_quote($match[1]).'$}',
-                    addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\'),
+                    // addcslashes is used to double up backslashes/$ since preg_replace resolves them as back references otherwise, see #1588
+                    addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
                     $links
                 );
             } else {
@@ -223,7 +225,7 @@ class JsonManipulator
             // child missing but non empty children
             $children = preg_replace(
                 '#'.$match[1].'$#',
-                addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $match[1], '\\'),
+                addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $match[1], '\\$'),
                 $children
             );
         } else {
@@ -235,7 +237,9 @@ class JsonManipulator
             $children = $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $children;
         }
 
-        $this->contents = preg_replace($nodeRegex, addcslashes('${1}${2}'.$children.'${4}${5}', '\\'), $this->contents);
+        $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
+            return $m[1] . $m[2] . $children . $m[4] . $m[5];
+        }, $this->contents);
 
         return true;
     }
@@ -353,7 +357,7 @@ class JsonManipulator
         if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
             $this->contents = preg_replace(
                 '#'.$match[1].'\}$#',
-                addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\'),
+                addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
                 $this->contents
             );
 
@@ -363,7 +367,7 @@ class JsonManipulator
         // append at the end of the file
         $this->contents = preg_replace(
             '#\}$#',
-            addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\'),
+            addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
             $this->contents
         );
 

+ 2 - 1
src/Composer/Repository/Vcs/GitDriver.php

@@ -38,6 +38,7 @@ class GitDriver extends VcsDriver
     public function initialize()
     {
         if (Filesystem::isLocalPath($this->url)) {
+            $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
             $this->repoDir = $this->url;
             $cacheUrl = realpath($this->url);
         } else {
@@ -219,7 +220,7 @@ class GitDriver extends VcsDriver
      */
     public static function supports(IOInterface $io, Config $config, $url, $deep = false)
     {
-        if (preg_match('#(^git://|\.git$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
+        if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
             return true;
         }
 

+ 2 - 2
src/Composer/Util/Filesystem.php

@@ -476,13 +476,13 @@ class Filesystem
      */
     public static function isLocalPath($path)
     {
-        return (bool) preg_match('{^(file://|/|[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
+        return (bool) preg_match('{^(file://|/|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
     }
 
     public static function getPlatformPath($path)
     {
         if (Platform::isWindows()) {
-            $path = preg_replace('{^(?:file:///([a-z])/)}i', 'file://$1:/', $path);
+            $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
         }
 
         return preg_replace('{^file://}i', '', $path);

+ 38 - 0
tests/Composer/Test/Json/JsonManipulatorTest.php

@@ -2045,6 +2045,31 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase
 ', $manipulator->getContents());
     }
 
+    public function testAddMainKeyWithContentHavingDollarSignFollowedByDigit()
+    {
+        $manipulator = new JsonManipulator('{
+    "foo": "bar"
+}');
+        
+        $this->assertTrue($manipulator->addMainKey('bar', '$1baz'));
+        $this->assertEquals('{
+    "foo": "bar",
+    "bar": "$1baz"
+}
+', $manipulator->getContents());
+    }
+
+    public function testAddMainKeyWithContentHavingDollarSignFollowedByDigit2()
+    {
+        $manipulator = new JsonManipulator('{}');
+
+        $this->assertTrue($manipulator->addMainKey('foo', '$1bar'));
+        $this->assertEquals('{
+    "foo": "$1bar"
+}
+', $manipulator->getContents());
+    }
+    
     public function testUpdateMainKey()
     {
         $manipulator = new JsonManipulator('{
@@ -2105,6 +2130,19 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase
 ', $manipulator->getContents());
     }
 
+    public function testUpdateMainKeyWithContentHavingDollarSignFollowedByDigit()
+    {
+        $manipulator = new JsonManipulator('{
+    "foo": "bar"
+}');
+
+        $this->assertTrue($manipulator->addMainKey('foo', '$1bar'));
+        $this->assertEquals('{
+    "foo": "$1bar"
+}
+', $manipulator->getContents());
+    }
+    
     public function testIndentDetection()
     {
         $manipulator = new JsonManipulator('{