瀏覽代碼

Merge remote-tracking branch 'olvlvl/improved_package_sorting_alone'

Jordi Boggiano 11 年之前
父節點
當前提交
d26dda5c95
共有 1 個文件被更改,包括 67 次插入29 次删除
  1. 67 29
      src/Composer/Autoload/AutoloadGenerator.php

+ 67 - 29
src/Composer/Autoload/AutoloadGenerator.php

@@ -611,45 +611,83 @@ FOOTER;
 
     protected function sortPackageMap(array $packageMap)
     {
-        $positions = array();
-        $names = array();
-        $indexes = array();
-
-        foreach ($packageMap as $position => $item) {
-            $mainName = $item[0]->getName();
-            $names = array_merge(array_fill_keys($item[0]->getNames(), $mainName), $names);
-            $names[$mainName] = $mainName;
-            $indexes[$mainName] = $positions[$mainName] = $position;
-        }
+        $packages = array();
+        $paths = array();
+        $usageList = array();
 
         foreach ($packageMap as $item) {
-            $position = $positions[$item[0]->getName()];
-            foreach (array_merge($item[0]->getRequires(), $item[0]->getDevRequires()) as $link) {
+            list($package, $path) = $item;
+            $name = $package->getName();
+            $packages[$name] = $package;
+            $paths[$name] = $path;
+
+            foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
                 $target = $link->getTarget();
-                if (!isset($names[$target])) {
-                    continue;
-                }
+                $usageList[$target][] = $name;
+            }
+        }
 
-                $target = $names[$target];
-                if ($positions[$target] <= $position) {
-                    continue;
-                }
+        $computing = array();
+        $computed = array();
+        $computeImportance = function($name) use(&$computeImportance, &$computing, &$computed, $usageList) {
+            // reusing computed importance
+            if (isset($computed[$name])) {
+                return $computed[$name];
+            }
 
-                foreach ($positions as $key => $value) {
-                    if ($value >= $position) {
-                        break;
-                    }
-                    $positions[$key]--;
-                }
+            // canceling circular dependency
+            if (isset($computing[$name])) {
+                return 0;
+            }
+
+            $computing[$name] = true;
+            $weight = 0;
 
-                $positions[$target] = $position - 1;
+            if (isset($usageList[$name])) {
+                foreach ($usageList[$name] as $user) {
+                    $weight -= 1 - $computeImportance($user);
+                }
             }
-            asort($positions);
+
+            unset($computing[$name]);
+            $computed[$name] = $weight;
+
+            return $weight;
+        };
+
+        $weightList = array();
+
+        foreach ($packages as $name => $package) {
+            $weight = $computeImportance($name);
+            $weightList[$name] = $weight;
         }
 
+        $stable_sort = function(&$array) {
+            static $transform, $restore;
+
+            $i = 0;
+
+            if (!$transform) {
+                $transform = function(&$v, $k) use(&$i) {
+                    $v = array($v, ++$i, $k, $v);
+                };
+
+                $restore = function(&$v, $k) {
+                    $v = $v[3];
+                };
+            }
+
+            array_walk($array, $transform);
+            asort($array);
+            array_walk($array, $restore);
+        };
+
+        $stable_sort($weightList);
+
         $sortedPackageMap = array();
-        foreach (array_keys($positions) as $packageName) {
-            $sortedPackageMap[] = $packageMap[$indexes[$packageName]];
+
+        foreach (array_keys($weightList) as $name) {
+            $sortedPackageMap[] = array($packages[$name], $paths[$name]);
         }
 
         return $sortedPackageMap;