From 674d31bfc94ebc4bdcb514f9ee7d8181b2a5debe Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 15 Oct 2010 09:05:02 -0500 Subject: [PATCH 01/49] Quick fix $HOME for win32 platform --- packager | 1 + 1 file changed, 1 insertion(+) diff --git a/packager b/packager index 61e8274..1e0ab3b 100755 --- a/packager +++ b/packager @@ -13,6 +13,7 @@ if ($a0 == '-h' || $a0 == '--help'){ } $home = exec('echo $HOME'); +if ($home == '$HOME') $home = array_get($_SERVER, 'USERPROFILE'); $packages = YAML::decode_file("$home/.packages.yml"); if (empty($packages)) $packages = array(); From eba9209114c395e308fbc9d0deb2c48cc11d1bce Mon Sep 17 00:00:00 2001 From: Ryan Florence Date: Wed, 27 Oct 2010 22:47:40 -0600 Subject: [PATCH 02/49] Can pass in components to exclude from the build (like Depender) for dynamic loading of scripts. Supported methods: - build_from_components - write_from_components --- packager.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packager.php b/packager.php index b5ecb32..ff7f8b0 100644 --- a/packager.php +++ b/packager.php @@ -190,7 +190,7 @@ public function validate($more_files = array(), $more_components = array(), $mor // # public BUILD - public function build($files = array(), $components = array(), $packages = array(), $blocks = array()){ + public function build($files = array(), $components = array(), $packages = array(), $blocks = array(), $excluded = array()){ if (!empty($components)){ $more = $this->components_to_files($components); @@ -204,6 +204,13 @@ public function build($files = array(), $components = array(), $packages = array $files = $this->complete_files($files); + if (!empty($excluded)){ + $less = array(); + foreach ($this->components_to_files($excluded) as $file) array_include($less, $file); + $exclude = $this->complete_files($less); + $files = array_diff($files, $exclude); + } + if (empty($files)) return ''; $included_sources = array(); @@ -226,8 +233,8 @@ public function build_from_files($files){ return $this->build($files); } - public function build_from_components($components){ - return $this->build(array(), $components); + public function build_from_components($components, $excluded = null){ + return $this->build(array(), $components, array(), array(), $excluded); } public function write_from_files($file_name, $files = null){ @@ -235,8 +242,8 @@ public function write_from_files($file_name, $files = null){ file_put_contents($file_name, $full); } - public function write_from_components($file_name, $components = null){ - $full = $this->build_from_components($components); + public function write_from_components($file_name, $components = null, $exclude = null){ + $full = $this->build_from_components($components, $exclude); file_put_contents($file_name, $full); } From c95c6b8f265afca4e01bc04524f00e1267d651d3 Mon Sep 17 00:00:00 2001 From: holy Date: Fri, 29 Oct 2010 12:04:22 +0900 Subject: [PATCH 03/49] An infinite loop in the solution part of the dependence is generated. What processed once excluded it. Signed-off-by: holy --- packager.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packager.php b/packager.php index b5ecb32..fdc5399 100644 --- a/packager.php +++ b/packager.php @@ -14,7 +14,8 @@ public static function warn($message){ private $packages = array(); private $manifests = array(); private $root = null; - + private $files = array(); + public function __construct($package_paths){ foreach ((array)$package_paths as $package_path) $this->parse_manifest($package_path); } @@ -253,9 +254,16 @@ public function get_all_files($of_package = null){ } public function get_file_dependancies($file){ + $deps = array(); $hash = $this->file_to_hash($file); if (empty($hash)) return array(); - return $this->complete_files($this->components_to_files($hash['requires'])); + if (!in_array($file, $this->files)) { + $this->files[] = $file; + $files = $this->components_to_files($hash['requires']); + $files = array_diff($files, $this->files); + $deps = $this->complete_files($files); + } + return $deps; } public function complete_file($file){ From 0153d902e57971df49fbc5de5f7de4085adcc226 Mon Sep 17 00:00:00 2001 From: slik Date: Mon, 29 Nov 2010 18:18:52 +0200 Subject: [PATCH 04/49] sources by pattern --- packager.php | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/packager.php b/packager.php index 23b4a11..30fcc48 100644 --- a/packager.php +++ b/packager.php @@ -3,7 +3,22 @@ require dirname(__FILE__) . "/helpers/yaml.php"; require dirname(__FILE__) . "/helpers/array.php"; -Class Packager { +function bfglob($path, $pattern = '*', $flags = 0, $depth = 0) { + $matches = array(); + $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); + + while($folder = array_shift($folders)) { + $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); + if($depth != 0) { + $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); + $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; + $folders = array_merge($folders, $moreFolders); + } + } + return $matches; +} + +class Packager { public static function warn($message){ $std_err = fopen('php://stderr', 'w'); @@ -58,37 +73,35 @@ private function parse_manifest($path){ $manifest['manifest'] = $manifest_path; $this->manifests[$package_name] = $manifest; - + + if(!is_array($manifest['sources'])){ + $manifest['sources'] = bfglob($package_path, $manifest['sources'], 0, 5); + $patternUsed = true; + } foreach ($manifest['sources'] as $i => $path){ - - $path = $package_path . $path; - + + if(!isset($patternUsed)) $path = $package_path . $path; + // this is where we "hook" for possible other replacers. $source = $this->replace_build($package_path, file_get_contents($path)); - $descriptor = array(); - // get contents of first comment preg_match('/\s*\/\*\s*(.*?)\s*\*\//s', $source, $matches); - if (!empty($matches)){ // get contents of YAML front matter preg_match('/^-{3}\s*$(.*?)^(?:-{3}|\.{3})\s*$/ms', $matches[1], $matches); - if (!empty($matches)) $descriptor = YAML::decode($matches[1]); } - // populate / convert to array requires and provides $requires = (array)(!empty($descriptor['requires']) ? $descriptor['requires'] : array()); $provides = (array)(!empty($descriptor['provides']) ? $descriptor['provides'] : array()); $file_name = !empty($descriptor['name']) ? $descriptor['name'] : basename($path, '.js'); - // "normalization" for requires. Fills up the default package name from requires, if not present. foreach ($requires as $i => $require) $requires[$i] = implode('/', $this->parse_name($package_name, $require)); - + $license = array_get($descriptor, 'license'); - + $this->packages[$package_name][$file_name] = array_merge($descriptor, array( 'package' => $package_name, 'requires' => $requires, @@ -98,8 +111,8 @@ private function parse_manifest($path){ 'package/name' => $package_name . '/' . $file_name, 'license' => empty($license) ? array_get($manifest, 'license') : $license )); - } + } public function add_package($package_path){ From d6159c585126f20be8b6fdbdea5e907b12b9b460 Mon Sep 17 00:00:00 2001 From: slik Date: Tue, 30 Nov 2010 11:33:21 +0200 Subject: [PATCH 05/49] bfglob is a private method now --- packager.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packager.php b/packager.php index 6abb0cb..d7982d9 100644 --- a/packager.php +++ b/packager.php @@ -3,21 +3,6 @@ require dirname(__FILE__) . "/helpers/yaml.php"; require dirname(__FILE__) . "/helpers/array.php"; -function bfglob($path, $pattern = '*', $flags = 0, $depth = 0) { - $matches = array(); - $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); - - while($folder = array_shift($folders)) { - $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); - if($depth != 0) { - $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); - $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; - $folders = array_merge($folders, $moreFolders); - } - } - return $matches; -} - class Packager { public static function warn($message){ @@ -75,7 +60,7 @@ private function parse_manifest($path){ $this->manifests[$package_name] = $manifest; if(!is_array($manifest['sources'])){ - $manifest['sources'] = bfglob($package_path, $manifest['sources'], 0, 5); + $manifest['sources'] = $this->bfglob($package_path, $manifest['sources'], 0, 5); $patternUsed = true; } foreach ($manifest['sources'] as $i => $path){ @@ -135,6 +120,21 @@ private function parse_name($default, $name){ if (empty($exploded[0])) return array($default, $exploded[1]); return array($exploded[0], $exploded[1]); } + + private function bfglob($path, $pattern = '*', $flags = 0, $depth = 0) { + $matches = array(); + $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); + + while($folder = array_shift($folders)) { + $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); + if($depth != 0) { + $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); + $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; + $folders = array_merge($folders, $moreFolders); + } + } + return $matches; + } // # private HASHES From bf02a16b050585b97af4e1ba9897d0d73fa2692d Mon Sep 17 00:00:00 2001 From: thomasd Date: Fri, 17 Dec 2010 16:35:43 +0100 Subject: [PATCH 06/49] Added the ability to read the description for a file from the source-entry in the manifest. --- packager.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packager.php b/packager.php index b5ecb32..5c2db90 100644 --- a/packager.php +++ b/packager.php @@ -61,6 +61,11 @@ private function parse_manifest($path){ foreach ($manifest['sources'] as $i => $path){ + // thomasd: if the source-node contains a description we cache it, but we wait if there's also a description-header in the file as this one takes precedence + if(is_array($path)){ + $source_desc = $path[1]; + $path = $path[0]; + } $path = $package_path . $path; // this is where we "hook" for possible other replacers. @@ -71,7 +76,13 @@ private function parse_manifest($path){ // get contents of first comment preg_match('/\/\*\s*^---(.*?)^\.\.\.\s*\*\//ms', $source, $matches); - if (!empty($matches)) $descriptor = YAML::decode($matches[0]); + if (!empty($matches)){ + $descriptor = YAML::decode($matches[0]); + } + // thomasd: if the file doesn't contain a proper description-header but the manifest does, we take that description + else if(isset($source_desc) && is_array($source_desc)){ + $descriptor = $source_desc; + } // populate / convert to array requires and provides $requires = (array)(!empty($descriptor['requires']) ? $descriptor['requires'] : array()); From 99b9f6b011789215a351dcdf9baa1124e8c02bec Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 3 Mar 2011 13:52:53 -0800 Subject: [PATCH 07/49] Restore ability to end YAML comment with dashes --- packager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packager.php b/packager.php index b5ecb32..bdaec79 100644 --- a/packager.php +++ b/packager.php @@ -69,7 +69,7 @@ private function parse_manifest($path){ $descriptor = array(); // get contents of first comment - preg_match('/\/\*\s*^---(.*?)^\.\.\.\s*\*\//ms', $source, $matches); + preg_match('/\/\*\s*^---(.*?)^(?:\.\.\.|---)\s*\*\//ms', $source, $matches); if (!empty($matches)) $descriptor = YAML::decode($matches[0]); From 4140a4aaba198f41ae35c599db3f2a56ff562f74 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 3 Mar 2011 13:53:47 -0800 Subject: [PATCH 08/49] Fix bug where file object was missing name property --- packager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packager.php b/packager.php index bdaec79..ad9a8f8 100644 --- a/packager.php +++ b/packager.php @@ -85,6 +85,7 @@ private function parse_manifest($path){ $license = array_get($descriptor, 'license'); $this->packages[$package_name][$file_name] = array_merge($descriptor, array( + 'name' => $file_name, 'package' => $package_name, 'requires' => $requires, 'provides' => $provides, From d6f88a62eedb57138452c452a021dde7d29fbd02 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 3 Mar 2011 13:55:54 -0800 Subject: [PATCH 09/49] Factored out some code in build into separate methods: resolve_files and remove_blocks --- packager | 13 +------------ packager.php | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/packager b/packager index 61e8274..e7d181e 100755 --- a/packager +++ b/packager @@ -165,20 +165,9 @@ switch ($command){ $pkg->validate($files, $components, $wildcards); - foreach ($components as $component){ - $file = $pkg->component_to_file($component); - if ($file) array_include($files, $file); - } - - foreach ($wildcards as $package){ - $all = $pkg->get_all_files($package); - foreach ($all as $file) array_include($files, $file); - } - - $files = $pkg->complete_files($files); + $files = $pkg->resolve_files($files, $components, $wildcards); Packager::warn("Build using: " . implode(', ', $pkg->get_packages()) . "\n"); - Packager::warn("Included Files/Components:\n"); foreach ($files as $file){ diff --git a/packager.php b/packager.php index ad9a8f8..3cce799 100644 --- a/packager.php +++ b/packager.php @@ -189,10 +189,7 @@ public function validate($more_files = array(), $more_components = array(), $mor } } - // # public BUILD - - public function build($files = array(), $components = array(), $packages = array(), $blocks = array()){ - + public function resolve_files($files = array(), $components = array(), $packages = array()){ if (!empty($components)){ $more = $this->components_to_files($components); foreach ($more as $file) array_include($files, $file); @@ -200,23 +197,31 @@ public function build($files = array(), $components = array(), $packages = array foreach ($packages as $package){ $more = $this->get_all_files($package); - foreach ($more as $file) array_include($files, $file); + foreach ($more as $file) array_include($files, $file); } - $files = $this->complete_files($files); - + return $this->complete_files($files); + } + + // # public BUILD + + public function build($files = array(), $components = array(), $packages = array(), $blocks = array()){ + + $files = $this->resolve_files($files, $components, $packages); if (empty($files)) return ''; $included_sources = array(); foreach ($files as $file) $included_sources[] = $this->get_file_source($file); - $source = implode($included_sources, "\n\n"); - + return $this->remove_blocks(implode($included_sources, "\n\n"), $blocks) . "\n"; + } + + public function remove_blocks($source, $blocks){ foreach ($blocks as $block){ $source = preg_replace_callback("%(/[/*])\s*<$block>(.*?)(?:\s*\*/)?%s", array($this, "block_replacement"), $source); } - return $source . "\n"; + return $source; } private function block_replacement($matches){ From 9b846a58d9c8200e97e6c2766bc273a4350a1ab6 Mon Sep 17 00:00:00 2001 From: Noritaka Horio Date: Sun, 27 Mar 2011 02:57:54 +0900 Subject: [PATCH 10/49] The bug that the dependence of the file cannot be correctly acquired since the first time is corrected. --- packager.php | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packager.php b/packager.php index fdc5399..e0fdf0a 100644 --- a/packager.php +++ b/packager.php @@ -26,7 +26,7 @@ private function parse_manifest($path){ if (is_dir($path)){ $package_path = $pathinfo['dirname'] . '/' . $pathinfo['basename'] . '/'; - + if (file_exists($package_path . 'package.yml')){ $manifest_path = $package_path . 'package.yml'; $manifest_format = 'yaml'; @@ -43,14 +43,14 @@ private function parse_manifest($path){ $manifest_path = $package_path . $pathinfo['basename']; $manifest_format = $pathinfo['extension']; } - + if ($manifest_format == 'json') $manifest = json_decode(file_get_contents($manifest_path), true); else if ($manifest_format == 'yaml' || $manifest_format == 'yml') $manifest = YAML::decode_file($manifest_path); - + if (empty($manifest)) throw new Exception("manifest not found in $package_path, or unable to parse manifest."); $package_name = $manifest['name']; - + if ($this->root == null) $this->root = $package_name; if (array_has($this->manifests, $package_name)) return; @@ -252,10 +252,17 @@ public function get_all_files($of_package = null){ } return $files; } - + public function get_file_dependancies($file){ + $this->files = array(); + $deps = $this->parse_file_dependancies($file); + return $deps; + } + + private function parse_file_dependancies($file){ $deps = array(); $hash = $this->file_to_hash($file); + if (empty($hash)) return array(); if (!in_array($file, $this->files)) { $this->files[] = $file; @@ -265,9 +272,9 @@ public function get_file_dependancies($file){ } return $deps; } - + public function complete_file($file){ - $files = $this->get_file_dependancies($file); + $files = $this->parse_file_dependancies($file); $hash = $this->file_to_hash($file); if (empty($hash)) return array(); array_include($files, $hash['package/name']); @@ -318,7 +325,7 @@ public function __call($method, $arguments){ return null; } - + public function get_packages(){ return array_keys($this->packages); } From ce39df8295db31be2e4f961c2f8cd54f78ada0c8 Mon Sep 17 00:00:00 2001 From: Noritaka Horio Date: Sun, 27 Mar 2011 05:00:19 +0900 Subject: [PATCH 11/49] The distinction from isset() to empty() because the error competes at the build Signed-off-by: Noritaka Horio --- packager.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packager.php b/packager.php index 4d55632..62a22d7 100644 --- a/packager.php +++ b/packager.php @@ -65,8 +65,7 @@ private function parse_manifest($path){ } foreach ($manifest['sources'] as $i => $path){ - - if(!isset($patternUsed)) $path = $package_path . $path; + if (!empty($patternUsed)) $path = $package_path . $path; // thomasd: if the source-node contains a description we cache it, but we wait if there's also a description-header in the file as this one takes precedence if(is_array($path)){ From f119a496d047aceeec99e93c7ff818f60040dd4d Mon Sep 17 00:00:00 2001 From: holy Date: Mon, 28 Mar 2011 11:08:06 +0900 Subject: [PATCH 12/49] Because the output message cannot be read by other programs, the method of outputting the message is appropriately changed. php://stderr to php://stdout --- packager | 16 ++++++++-------- packager.php | 6 ++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packager b/packager index f933221..a5c9819 100755 --- a/packager +++ b/packager @@ -37,8 +37,8 @@ switch ($command){ $packages[$name] = $path; file_put_contents("$home/.packages.yml", YAML::encode($packages)); - - Packager::warn("the package $name has been registered as $path\n"); + + Packager::info("the package $name has been registered as $path\n"); break; @@ -55,7 +55,7 @@ switch ($command){ file_put_contents("$home/.packages.yml", YAML::encode($packages)); - Packager::warn("the package $name has been unregistered\n"); + Packager::info("the package $name has been unregistered\n"); break; @@ -64,7 +64,7 @@ switch ($command){ $package_name = array_shift($argv); if (empty($package_name)){ - foreach ($packages as $name => $path) Packager::warn("$name: $path\n"); + foreach ($packages as $name => $path) Packager::info("$name: $path\n"); } else { if (!empty($packages[$package_name])){ $package_path = $packages[$package_name]; @@ -72,7 +72,7 @@ switch ($command){ $files = $pkg->get_all_files(); foreach ($files as $file){ $file_name = $pkg->get_file_name($file); - Packager::warn("- $file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); + Packager::info("- $file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); } } else { Packager::warn("The package $package_name has not been found.\n"); @@ -168,13 +168,13 @@ switch ($command){ $files = $pkg->resolve_files($files, $components, $wildcards); - Packager::warn("Build using: " . implode(', ', $pkg->get_packages()) . "\n"); - Packager::warn("Included Files/Components:\n"); + Packager::info("Build using: " . implode(', ', $pkg->get_packages()) . "\n"); + Packager::info("Included Files/Components:\n"); foreach ($files as $file){ $file_name = $pkg->get_file_name($file); $file_package = $pkg->get_file_package($file); - Packager::warn("- $file_package/$file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); + Packager::info("- $file_package/$file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); } echo $pkg->build($files, array(), array(), $blocks); diff --git a/packager.php b/packager.php index 62a22d7..aef5ad4 100644 --- a/packager.php +++ b/packager.php @@ -11,6 +11,12 @@ public static function warn($message){ fclose($std_err); } + public static function info($message){ + $std_out = fopen('php://stdout', 'w'); + fwrite($std_out, $message); + fclose($std_out); + } + private $packages = array(); private $manifests = array(); private $root = null; From 9f585fb911f88d03c002cbfbc94217307f403da4 Mon Sep 17 00:00:00 2001 From: Noritaka Horio Date: Tue, 29 Mar 2011 00:16:20 +0900 Subject: [PATCH 13/49] It is corrected that an extra output is included. Signed-off-by: Noritaka Horio --- packager | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packager b/packager index a5c9819..7722ac2 100755 --- a/packager +++ b/packager @@ -167,14 +167,14 @@ switch ($command){ $pkg->validate($files, $components, $wildcards); $files = $pkg->resolve_files($files, $components, $wildcards); - - Packager::info("Build using: " . implode(', ', $pkg->get_packages()) . "\n"); - Packager::info("Included Files/Components:\n"); + + Packager::warn("Build using: " . implode(', ', $pkg->get_packages()) . "\n"); + Packager::warn("Included Files/Components:\n"); foreach ($files as $file){ $file_name = $pkg->get_file_name($file); $file_package = $pkg->get_file_package($file); - Packager::info("- $file_package/$file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); + Packager::warn("- $file_package/$file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); } echo $pkg->build($files, array(), array(), $blocks); From ad66d9c8d900756dcd26523ff49aba7ecc9015ac Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 11:59:10 -0500 Subject: [PATCH 14/49] (broken) refactoring of packager into more modular approach. --- packager.php | 259 +++++++++++++++++++++++++++------------------------ 1 file changed, 135 insertions(+), 124 deletions(-) diff --git a/packager.php b/packager.php index aef5ad4..d138a37 100644 --- a/packager.php +++ b/packager.php @@ -3,6 +3,133 @@ require dirname(__FILE__) . "/helpers/yaml.php"; require dirname(__FILE__) . "/helpers/array.php"; +class Package +{ + const DESCRIPTOR_REGEX = '/\/\*\s*^---(.*?)^(?:\.\.\.|---)\s*\*\//ms'; + protected $sources = array(); + + public function __construct($path) + { + $this->path = $this->resolve_path($path); + $this->root_dir = dirname($this->path); + + $this->manifest = self::decode($this->path); + $this->normalize_manifest(); + + $this->name = $this->manifest['name']; + + foreach ($this->manifest['sources'] as $i => $source_path) { + $descriptor = $this->get_descriptor($source_path); + $this->sources[] = array_merge($descriptor, array( + 'package' => $this->name, + 'path' => $source_path, + 'package/name' => sprintf('%s/%s', $this->name, $descriptor['name']) + )); + } + } + + static function decode($path) + { + return preg_match('/\.json$/', $path) ? json_decode(file_get_contents($path), true) : YAML::decode_file($path); + } + + static function glob($path, $pattern = '*', $flags = 0, $depth = 0) + { + $matches = array(); + $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); + + while ($folder = array_shift($folders)){ + $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); + if ($depth != 0) { + $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); + $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; + $folders = array_merge($folders, $moreFolders); + } + } + return $matches; + } + + public function get_manifest() + { + return $this->manifest; + } + + public function get_descriptor($source_path) + { + $source = file_get_contents($source_path); + + preg_match(self::DESCRIPTOR_REGEX, $source, $matches); + if (empty($matches)) return array(); + + $descriptor = YAML::decode($matches[0]); + + if (!isset($descriptor['name'])) $descriptor['name'] = basename($source_path, '.js'); + if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); + $descriptor['source'] = $source; + $descriptor['requires'] = $requires = (array) array_get($descriptor, 'requires'); + $descriptor['provides'] = (array) array_get($descriptor, 'provides'); + + array_map($requires, array($this, 'normalize_requires')); + + return $descriptor; + } + + public function get_files() + { + $files = array(); + foreach ($this->sources as $descriptor) $files[] = $descriptor['package/name']; + return $files; + } + + public function get_name() + { + return $this->name; + } + + public function get_root_dir() + { + return $this->root_dir; + } + + public function resolve_path($path) + { + if (!is_dir($path) && file_exists($path)) return $path; + + $pathinfo = pathinfo($path); + $path = $pathinfo['dirname'] . '/' . $pathinfo['basename'] . '/'; + + if (file_exists($path . 'package.yml')) return $path . 'package.yml'; + if (file_exists($path . 'package.yaml')) return $path . 'package.yaml'; + if (file_exists($path . 'package.json')) return $path . 'package.json'; + + throw new Exception("package.(yml|yaml|json) not found in $path."); + } + + protected function normalize_manifest() + { + $manifest = $this->manifest; + if (!is_array($manifest['sources'])){ + # todo(ibolmo): 5, should be a class option + $manifest['sources'] = self::glob($this->path, $manifest['sources'], 0, 5); + foreach ($manifest['sources'] as $i => $source_path) $manifest['sources'][$i] = $this->root_dir . $source_path; + } + } + + protected function normalize_requires($require) + { + return implode('/', $this->parse_name($package_name, $require)); + } + + protected function parse_name($default, $name){ + $exploded = explode('/', $name); + $length = count($exploded); + if ($length == 1) return array($default, $exploded[0]); + if (empty($exploded[0])) return array($default, $exploded[1]); + return array($exploded[0], $exploded[1]); + } +} + + class Packager { public static function warn($message){ @@ -23,103 +150,14 @@ public static function info($message){ private $files = array(); public function __construct($package_paths){ - foreach ((array)$package_paths as $package_path) $this->parse_manifest($package_path); - } - - private function parse_manifest($path){ - $pathinfo = pathinfo($path); - - if (is_dir($path)){ - - $package_path = $pathinfo['dirname'] . '/' . $pathinfo['basename'] . '/'; - if (file_exists($package_path . 'package.yml')){ - $manifest_path = $package_path . 'package.yml'; - $manifest_format = 'yaml'; - } else if (file_exists($package_path . 'package.yaml')){ - $manifest_path = $package_path . 'package.yaml'; - $manifest_format = 'yaml'; - } else if (file_exists($package_path . 'package.json')){ - $manifest_path = $package_path . 'package.json'; - $manifest_format = 'json'; - } - - } else if (file_exists($path)){ - $package_path = $pathinfo['dirname'] . '/'; - $manifest_path = $package_path . $pathinfo['basename']; - $manifest_format = $pathinfo['extension']; - } - - if ($manifest_format == 'json') $manifest = json_decode(file_get_contents($manifest_path), true); - else if ($manifest_format == 'yaml' || $manifest_format == 'yml') $manifest = YAML::decode_file($manifest_path); - - if (empty($manifest)) throw new Exception("manifest not found in $package_path, or unable to parse manifest."); - - $package_name = $manifest['name']; - - if ($this->root == null) $this->root = $package_name; - - if (array_has($this->manifests, $package_name)) return; - - $manifest['path'] = $package_path; - $manifest['manifest'] = $manifest_path; - - $this->manifests[$package_name] = $manifest; - - if(!is_array($manifest['sources'])){ - $manifest['sources'] = $this->bfglob($package_path, $manifest['sources'], 0, 5); - $patternUsed = true; - } - foreach ($manifest['sources'] as $i => $path){ - - if (!empty($patternUsed)) $path = $package_path . $path; - - // thomasd: if the source-node contains a description we cache it, but we wait if there's also a description-header in the file as this one takes precedence - if(is_array($path)){ - $source_desc = $path[1]; - $path = $path[0]; - } - $path = $package_path . $path; - - // this is where we "hook" for possible other replacers. - $source = file_get_contents($path); - - $descriptor = array(); - - // get contents of first comment - preg_match('/\/\*\s*^---(.*?)^(?:\.\.\.|---)\s*\*\//ms', $source, $matches); - - if (!empty($matches)){ - $descriptor = YAML::decode($matches[0]); - } - // thomasd: if the file doesn't contain a proper description-header but the manifest does, we take that description - else if(isset($source_desc) && is_array($source_desc)){ - $descriptor = $source_desc; - } - - // populate / convert to array requires and provides - $requires = (array)(!empty($descriptor['requires']) ? $descriptor['requires'] : array()); - $provides = (array)(!empty($descriptor['provides']) ? $descriptor['provides'] : array()); - $file_name = !empty($descriptor['name']) ? $descriptor['name'] : basename($path, '.js'); - - // "normalization" for requires. Fills up the default package name from requires, if not present. - foreach ($requires as $i => $require) - $requires[$i] = implode('/', $this->parse_name($package_name, $require)); - - $license = array_get($descriptor, 'license'); - - $this->packages[$package_name][$file_name] = array_merge($descriptor, array( - 'name' => $file_name, - 'package' => $package_name, - 'requires' => $requires, - 'provides' => $provides, - 'source' => $source, - 'path' => $path, - 'package/name' => $package_name . '/' . $file_name, - 'license' => empty($license) ? array_get($manifest, 'license') : $license - )); - + foreach ((array) $package_paths as $package_path){ + $package = new Package($package_path); + $name = $package->get_name(); + if (!$this->root) $this->root = $name; + if (array_has($this->manifests, $name)) continue; + $this->packages[$name] = $package; + $this->manifests[$name] = $package->get_manifest(); } - } public function add_package($package_path){ @@ -131,31 +169,6 @@ public function remove_package($package_name){ unset($this->manifests[$package_name]); } - // # private UTILITIES - - private function parse_name($default, $name){ - $exploded = explode('/', $name); - $length = count($exploded); - if ($length == 1) return array($default, $exploded[0]); - if (empty($exploded[0])) return array($default, $exploded[1]); - return array($exploded[0], $exploded[1]); - } - - private function bfglob($path, $pattern = '*', $flags = 0, $depth = 0) { - $matches = array(); - $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); - - while($folder = array_shift($folders)) { - $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); - if($depth != 0) { - $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); - $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; - $folders = array_merge($folders, $moreFolders); - } - } - return $matches; - } - // # private HASHES private function component_to_hash($name){ @@ -299,9 +312,7 @@ public function write_from_components($file_name, $components = null, $exclude = public function get_all_files($of_package = null){ $files = array(); foreach ($this->packages as $name => $package){ - if ($of_package == null || $of_package == $name) foreach ($package as $file){ - $files[] = $file['package/name']; - } + if ($of_package == null || $of_package == $name) $files[] = $package->get_files(); } return $files; } From cd278ec888fb9b4b77e90d6632fbbaf736da7e56 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 13:54:34 -0500 Subject: [PATCH 15/49] An interim commit. Quick pass and doesn't seem that anything else (without breaking the interface) needs to be refactored. Going to start testing for correctness next. --- packager.php | 126 +++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 65 deletions(-) diff --git a/packager.php b/packager.php index d138a37..91a934e 100644 --- a/packager.php +++ b/packager.php @@ -8,8 +8,9 @@ class Package const DESCRIPTOR_REGEX = '/\/\*\s*^---(.*?)^(?:\.\.\.|---)\s*\*\//ms'; protected $sources = array(); - public function __construct($path) + public function __construct(Packager $manager, $path) { + $this->manager = $manager; $this->path = $this->resolve_path($path); $this->root_dir = dirname($this->path); @@ -20,7 +21,7 @@ public function __construct($path) foreach ($this->manifest['sources'] as $i => $source_path) { $descriptor = $this->get_descriptor($source_path); - $this->sources[] = array_merge($descriptor, array( + $this->sources[$descriptor['name']] = array_merge($descriptor, array( 'package' => $this->name, 'path' => $source_path, 'package/name' => sprintf('%s/%s', $this->name, $descriptor['name']) @@ -49,9 +50,13 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0) return $matches; } - public function get_manifest() + static function parse_name($default, $name) { - return $this->manifest; + $exploded = explode('/', $name); + $length = count($exploded); + if ($length == 1) return array($default, $exploded[0]); + if (empty($exploded[0])) return array($default, $exploded[1]); + return array($exploded[0], $exploded[1]); } public function get_descriptor($source_path) @@ -66,10 +71,10 @@ public function get_descriptor($source_path) if (!isset($descriptor['name'])) $descriptor['name'] = basename($source_path, '.js'); if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); $descriptor['source'] = $source; - $descriptor['requires'] = $requires = (array) array_get($descriptor, 'requires'); $descriptor['provides'] = (array) array_get($descriptor, 'provides'); - array_map($requires, array($this, 'normalize_requires')); + $requires = (array) array_get($descriptor, 'requires'); + $descriptor['requires'] = array_map($requires, array($this, 'normalize_requires')); return $descriptor; } @@ -81,11 +86,29 @@ public function get_files() return $files; } + public function get_manifest() + { + return $this->manifest; + } + public function get_name() { return $this->name; } + public function get_source_with_component($component) + { + foreach ($this->sources as $source){ + if (array_contains($component, $source['provides'])) return $source; + } + return null; + } + + public function get_source_with_file($name) + { + return array_get($this->sources, $name); + } + public function get_root_dir() { return $this->root_dir; @@ -105,6 +128,20 @@ public function resolve_path($path) throw new Exception("package.(yml|yaml|json) not found in $path."); } + # todo(ibolmo): Consider passing a callback function `onError` rather than passing Packager instance in constructor. + public function validate() + { + foreach ($this->sources as $descriptor){ + $file_requires = $descriptor['requires']; + foreach ($file_requires as $component){ + if (!$this->manager->component_exists($component)){ + # todo(ibolmo): Pass, or create, a logger in constructor rather than depend on Packager + Packager::warn("WARNING: The component $component, required in the file " . $file['package/name'] . ", has not been provided.\n"); + } + } + } + } + protected function normalize_manifest() { $manifest = $this->manifest; @@ -117,15 +154,7 @@ protected function normalize_manifest() protected function normalize_requires($require) { - return implode('/', $this->parse_name($package_name, $require)); - } - - protected function parse_name($default, $name){ - $exploded = explode('/', $name); - $length = count($exploded); - if ($length == 1) return array($default, $exploded[0]); - if (empty($exploded[0])) return array($default, $exploded[1]); - return array($exploded[0], $exploded[1]); + return implode('/', self::parse_name($package_name, $require)); } } @@ -150,18 +179,16 @@ public static function info($message){ private $files = array(); public function __construct($package_paths){ - foreach ((array) $package_paths as $package_path){ - $package = new Package($package_path); - $name = $package->get_name(); - if (!$this->root) $this->root = $name; - if (array_has($this->manifests, $name)) continue; - $this->packages[$name] = $package; - $this->manifests[$name] = $package->get_manifest(); - } + foreach ((array) $package_paths as $package_path) $this->add_package($package_path); } - public function add_package($package_path){ - $this->parse_manifest($package_path); + public function add_package($package_path){ + $package = new Package($this, $package_path); + $name = $package->get_name(); + if (!$this->root) $this->root = $name; + if (array_has($this->manifests, $name)) continue; + $this->packages[$name] = $package; + $this->manifests[$name] = $package->get_manifest(); } public function remove_package($package_name){ @@ -172,35 +199,15 @@ public function remove_package($package_name){ // # private HASHES private function component_to_hash($name){ - $pair = $this->parse_name($this->root, $name); - $package = array_get($this->packages, $pair[0]); - - if (!empty($package)){ - $component = $pair[1]; - - foreach ($package as $file => $data){ - foreach ($data['provides'] as $c){ - if ($c == $component) return $data; - } - } - } - - return null; + list($name, $component) = Package::parse_name($this->root, $name); + $package = array_get($this->packages, $name); + return !$package ? null : $package->get_source_with_component($component); } private function file_to_hash($name){ - $pair = $this->parse_name($this->root, $name); - $package = array_get($this->packages, $pair[0]); - - if (!empty($package)){ - $file_name = $pair[1]; - - foreach ($package as $file => $data){ - if ($file == $file_name) return $data; - } - } - - return null; + list($name, $file) = Package::parse_name($this->root, $name); + $package = array_get($this->packages, $name); + return !$package ? null : $package->get_source_with_file($file); } public function file_exists($name){ @@ -217,16 +224,7 @@ public function package_exists($name){ public function validate($more_files = array(), $more_components = array(), $more_packages = array()){ - foreach ($this->packages as $name => $files){ - foreach ($files as $file){ - $file_requires = $file['requires']; - foreach ($file_requires as $component){ - if (!$this->component_exists($component)){ - self::warn("WARNING: The component $component, required in the file " . $file['package/name'] . ", has not been provided.\n"); - } - } - } - } + foreach ($this->packages as $name => $package) $package->validate(); foreach ($more_files as $file){ if (!$this->file_exists($file)) self::warn("WARNING: The required file $file could not be found.\n"); @@ -411,10 +409,8 @@ public function get_file_authors($file){ private function normalize_authors($authors = null, $author = null, $default = null){ $use = empty($authors) ? $author : $authors; - if (empty($use) && !empty($default)) return $default; - if (is_array($use)) return $use; - if (empty($use)) return array(); - return array($use); + if (empty($use)) $use = $default; + return (array) $use; } } From de2dc42ea96b56a9a80edaf647cf8263de5ddbc0 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 14:51:45 -0500 Subject: [PATCH 16/49] Added phpunit test_packager.php. --- packager.php | 4 ++-- test/fixtures/Source/Array.js | 15 ++++++++++++++ test/fixtures/Source/Browser.js | 15 ++++++++++++++ test/fixtures/Source/Class.js | 15 ++++++++++++++ test/fixtures/Source/Core.js | 11 +++++++++++ test/fixtures/package.yml | 11 +++++++++++ test/test_packager.php | 35 +++++++++++++++++++++++++++++++++ 7 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/Source/Array.js create mode 100644 test/fixtures/Source/Browser.js create mode 100644 test/fixtures/Source/Class.js create mode 100644 test/fixtures/Source/Core.js create mode 100644 test/fixtures/package.yml create mode 100644 test/test_packager.php diff --git a/packager.php b/packager.php index 91a934e..7318acc 100644 --- a/packager.php +++ b/packager.php @@ -20,7 +20,7 @@ public function __construct(Packager $manager, $path) $this->name = $this->manifest['name']; foreach ($this->manifest['sources'] as $i => $source_path) { - $descriptor = $this->get_descriptor($source_path); + $descriptor = $this->get_descriptor($this->root_dir . '/' . $source_path); $this->sources[$descriptor['name']] = array_merge($descriptor, array( 'package' => $this->name, 'path' => $source_path, @@ -74,7 +74,7 @@ public function get_descriptor($source_path) $descriptor['provides'] = (array) array_get($descriptor, 'provides'); $requires = (array) array_get($descriptor, 'requires'); - $descriptor['requires'] = array_map($requires, array($this, 'normalize_requires')); + $descriptor['requires'] = array_map(array($this, 'normalize_requires'), $requires); return $descriptor; } diff --git a/test/fixtures/Source/Array.js b/test/fixtures/Source/Array.js new file mode 100644 index 0000000..4558507 --- /dev/null +++ b/test/fixtures/Source/Array.js @@ -0,0 +1,15 @@ +/* +--- + +name: Array + +description: Contains Array Prototypes like each, contains, and erase. + +license: MIT-style license. + +requires: Type + +provides: Array + +... +*/ \ No newline at end of file diff --git a/test/fixtures/Source/Browser.js b/test/fixtures/Source/Browser.js new file mode 100644 index 0000000..ce4f5b2 --- /dev/null +++ b/test/fixtures/Source/Browser.js @@ -0,0 +1,15 @@ +/* +--- + +name: Browser + +description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. + +license: MIT-style license. + +requires: [Array] + +provides: [Browser, Window, Document] + +... +*/ \ No newline at end of file diff --git a/test/fixtures/Source/Class.js b/test/fixtures/Source/Class.js new file mode 100644 index 0000000..c783eb0 --- /dev/null +++ b/test/fixtures/Source/Class.js @@ -0,0 +1,15 @@ +/* +--- + +name: Class + +description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. + +license: MIT-style license. + +requires: [Array] + +provides: Class + +... +*/ \ No newline at end of file diff --git a/test/fixtures/Source/Core.js b/test/fixtures/Source/Core.js new file mode 100644 index 0000000..f56b73f --- /dev/null +++ b/test/fixtures/Source/Core.js @@ -0,0 +1,11 @@ +/* +--- + +name: Core + +license: MIT-style license. + +provides: [Core, MooTools, Type, typeOf, instanceOf, Native] + +... +*/ diff --git a/test/fixtures/package.yml b/test/fixtures/package.yml new file mode 100644 index 0000000..1ae8b48 --- /dev/null +++ b/test/fixtures/package.yml @@ -0,0 +1,11 @@ +name: "Core" + +license: "[MIT License](http://mootools.net/license.txt)" + +authors: "[MooTools Development Team](http://mootools.net/developers)" + +sources: + - "Source/Core.js" + - "Source/Array.js" + - "Source/Browser.js" + - "Source/Class.js" \ No newline at end of file diff --git a/test/test_packager.php b/test/test_packager.php new file mode 100644 index 0000000..df926ec --- /dev/null +++ b/test/test_packager.php @@ -0,0 +1,35 @@ +get_all_files(); + $this->assertEquals(4, count($packages_files[0]), 'Should be 4 files'); + } + + /** + * @depends testConstructor + */ + public function test_get_packages($packager) + { + $packages = $packager->get_packages(); + $this->assertEquals('Core', $packages[0]); + } +} + +class PackageTest extends PHPUnit_Framework_TestCase +{ +} + From a0371788e15da404ac8bc99b8ccc5282c5d26201 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 15:33:31 -0500 Subject: [PATCH 17/49] Separated tests into two files. Fixed a bug with normalize_requires. --- packager.php | 6 +++--- test/test_package.php | 39 +++++++++++++++++++++++++++++++++++++++ test/test_packager.php | 28 +++++++++++++++++++++------- 3 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 test/test_package.php diff --git a/packager.php b/packager.php index 7318acc..01093f1 100644 --- a/packager.php +++ b/packager.php @@ -99,7 +99,7 @@ public function get_name() public function get_source_with_component($component) { foreach ($this->sources as $source){ - if (array_contains($component, $source['provides'])) return $source; + if (array_contains($source['provides'], $component)) return $source; } return null; } @@ -154,7 +154,7 @@ protected function normalize_manifest() protected function normalize_requires($require) { - return implode('/', self::parse_name($package_name, $require)); + return implode('/', self::parse_name($this->name, $require)); } } @@ -183,7 +183,7 @@ public function __construct($package_paths){ } public function add_package($package_path){ - $package = new Package($this, $package_path); + $package = ($package_path instanceof Package) ? $package_path : new Package($this, $package_path); $name = $package->get_name(); if (!$this->root) $this->root = $name; if (array_has($this->manifests, $name)) continue; diff --git a/test/test_package.php b/test/test_package.php new file mode 100644 index 0000000..4d33bfc --- /dev/null +++ b/test/test_package.php @@ -0,0 +1,39 @@ +add_package($package); + return $package; + } + + /** + * @depends test_constructor + */ + public function test_get_manifest($package) + { + $manifest = $package->get_manifest(); + $this->assertEquals(4, count($manifest)); + $this->assertEquals('Core', $manifest['name']); + } + + /** + * @depends test_constructor + */ + public function test_get_source_with_component($package) + { + $descriptor = $package->get_source_with_component('Core'); + $this->assertEquals(0, count($descriptor['requires'])); + $this->assertEquals('Core/Core', $descriptor['package/name']); + + $descriptor = $package->get_source_with_component('Array'); + $this->assertEquals(1, count($descriptor['requires'])); + $this->assertEquals('Core/Type', $descriptor['requires'][0]); + $this->assertEquals('Core/Array', $descriptor['package/name']); + } +} diff --git a/test/test_packager.php b/test/test_packager.php index df926ec..4e63643 100644 --- a/test/test_packager.php +++ b/test/test_packager.php @@ -4,14 +4,14 @@ class PackagerTest extends PHPUnit_Framework_TestCase { - public function testConstructor() + public function test_constructor() { new Packager(array()); return new Packager(dirname(__FILE__) . '/fixtures/package.yml'); } /** - * @depends testConstructor + * @depends test_constructor */ public function test_get_all_files($packager) { @@ -20,16 +20,30 @@ public function test_get_all_files($packager) } /** - * @depends testConstructor + * @depends test_constructor */ public function test_get_packages($packager) { $packages = $packager->get_packages(); $this->assertEquals('Core', $packages[0]); } -} - -class PackageTest extends PHPUnit_Framework_TestCase -{ + + /** + * @depends test_constructor + */ + public function test_resolve_files($packager) + { + $files = $packager->resolve_files(); + var_dump($files); + } + + /** + * @depends test_constructor + */ + public function test_build($packager) + { + $build = $packager->build(); + var_dump($build); + } } From c9adde3374577a8788f21ed366e853cac68ba84e Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 16:59:31 -0500 Subject: [PATCH 18/49] Passing tests (so far). --- packager.php | 3 +- test/test_package.php | 16 ++++++++++ test/test_packager.php | 66 ++++++++++++++++++++++++++---------------- 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/packager.php b/packager.php index 01093f1..fcba8b8 100644 --- a/packager.php +++ b/packager.php @@ -20,7 +20,8 @@ public function __construct(Packager $manager, $path) $this->name = $this->manifest['name']; foreach ($this->manifest['sources'] as $i => $source_path) { - $descriptor = $this->get_descriptor($this->root_dir . '/' . $source_path); + $source_path = $this->root_dir . '/' . $source_path; + $descriptor = $this->get_descriptor($source_path); $this->sources[$descriptor['name']] = array_merge($descriptor, array( 'package' => $this->name, 'path' => $source_path, diff --git a/test/test_package.php b/test/test_package.php index 4d33bfc..99e0c92 100644 --- a/test/test_package.php +++ b/test/test_package.php @@ -36,4 +36,20 @@ public function test_get_source_with_component($package) $this->assertEquals('Core/Type', $descriptor['requires'][0]); $this->assertEquals('Core/Array', $descriptor['package/name']); } + + /** + * @depends test_constructor + */ + public function test_get_source_with_file($package) + { + $descriptor = $package->get_source_with_file('Class'); + + $this->assertEquals('Class', $descriptor['name']); + + $this->assertEquals(1, count($descriptor['requires'])); + $this->assertEquals('Core/Array', $descriptor['requires'][0]); + + $this->assertEquals(1, count($descriptor['provides'])); + $this->assertEquals('Class', $descriptor['provides'][0]); + } } diff --git a/test/test_packager.php b/test/test_packager.php index 4e63643..b206cf4 100644 --- a/test/test_packager.php +++ b/test/test_packager.php @@ -4,46 +4,62 @@ class PackagerTest extends PHPUnit_Framework_TestCase { - public function test_constructor() + protected static $packager; + + public function setUp() { - new Packager(array()); - return new Packager(dirname(__FILE__) . '/fixtures/package.yml'); + self::$packager = new Packager(dirname(__FILE__) . '/fixtures/package.yml'); } - /** - * @depends test_constructor - */ - public function test_get_all_files($packager) + public function test_get_all_files() { - $packages_files = $packager->get_all_files(); + $packages_files = self::$packager->get_all_files(); $this->assertEquals(4, count($packages_files[0]), 'Should be 4 files'); } - /** - * @depends test_constructor - */ - public function test_get_packages($packager) + public function test_get_packages() { - $packages = $packager->get_packages(); + $packages = self::$packager->get_packages(); $this->assertEquals('Core', $packages[0]); } - /** - * @depends test_constructor - */ - public function test_resolve_files($packager) + public function test_complete_file() + { + $files = self::$packager->complete_file('Class'); + $this->assertEquals(3, count($files)); + $this->assertEquals('Core/Core', $files[0]); + $this->assertEquals('Core/Class', $files[2]); + } + + public function test_build() + { + $build = self::$packager->build(array('Class')); + $this->assertRegExp('/name: Core/', $build); + $this->assertRegExp('/name: Array/', $build); + $this->assertRegExp('/name: Class/', $build); + $this->assertNotRegExp('/name: Browser/', $build); + } + + public function test_resolve_files() + { + $files = self::$packager->resolve_files(array('Class')); + $this->assertEquals(3, count($files)); + $this->assertEquals('Core/Core', $files[0]); + $this->assertEquals('Core/Class', $files[2]); + } + + public function test_complete_files() { - $files = $packager->resolve_files(); - var_dump($files); + $files = self::$packager->complete_files(array('Class')); + $this->assertEquals(3, count($files)); + $this->assertEquals('Core/Core', $files[0]); + $this->assertEquals('Core/Class', $files[2]); } - /** - * @depends test_constructor - */ - public function test_build($packager) + public function test_get_file_source() { - $build = $packager->build(); - var_dump($build); + $source = file_get_contents(dirname(__FILE__).'/fixtures/Source/Class.js'); + $this->assertEquals($source, self::$packager->get_file_source('Class')); } } From b3dfc8a9965493c9f3b3bd25595e1a2de3eb37ff Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 17:24:47 -0500 Subject: [PATCH 19/49] Fixing get_all_files. Should return all the files for all packages in one array. Not a multi-dimensional array. --- packager.php | 2 +- test/test_packager.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packager.php b/packager.php index fcba8b8..c24e8aa 100644 --- a/packager.php +++ b/packager.php @@ -311,7 +311,7 @@ public function write_from_components($file_name, $components = null, $exclude = public function get_all_files($of_package = null){ $files = array(); foreach ($this->packages as $name => $package){ - if ($of_package == null || $of_package == $name) $files[] = $package->get_files(); + if ($of_package == null || $of_package == $name) $files = array_merge($files, $package->get_files()); } return $files; } diff --git a/test/test_packager.php b/test/test_packager.php index b206cf4..022dc30 100644 --- a/test/test_packager.php +++ b/test/test_packager.php @@ -14,7 +14,7 @@ public function setUp() public function test_get_all_files() { $packages_files = self::$packager->get_all_files(); - $this->assertEquals(4, count($packages_files[0]), 'Should be 4 files'); + $this->assertEquals(4, count($packages_files), 'Should be 4 files'); } public function test_get_packages() From 2fc967cc521223eb176664469d06f5a6eacabfd6 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Mon, 25 Apr 2011 18:08:34 -0500 Subject: [PATCH 20/49] Moved Package to its own file. At the moment it's in root directory, but could be changed in the future. I also organized, in alphabetical order packager.php. /me gets the shield ready. --- Package.php | 142 ++++++++++++++++ packager.php | 448 ++++++++++++++++----------------------------------- 2 files changed, 283 insertions(+), 307 deletions(-) create mode 100644 Package.php diff --git a/Package.php b/Package.php new file mode 100644 index 0000000..38dc183 --- /dev/null +++ b/Package.php @@ -0,0 +1,142 @@ +manager = $manager; + $this->path = $this->resolve_path($path); + $this->root_dir = dirname($this->path); + + $this->manifest = self::decode($this->path); + $this->normalize_manifest(); + + $this->name = $this->manifest['name']; + + foreach ($this->manifest['sources'] as $i => $source_path) { + $source_path = $this->root_dir . '/' . $source_path; + $descriptor = $this->get_descriptor($source_path); + $this->sources[$descriptor['name']] = array_merge($descriptor, array( + 'package' => $this->name, + 'path' => $source_path, + 'package/name' => sprintf('%s/%s', $this->name, $descriptor['name']) + )); + } + } + + static function decode($path){ + return preg_match('/\.json$/', $path) ? json_decode(file_get_contents($path), true) : YAML::decode_file($path); + } + + static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ + $matches = array(); + $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); + + while ($folder = array_shift($folders)){ + $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); + if ($depth != 0) { + $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); + $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; + $folders = array_merge($folders, $moreFolders); + } + } + return $matches; + } + + static function parse_name($default, $name){ + $exploded = explode('/', $name); + $length = count($exploded); + if ($length == 1) return array($default, $exploded[0]); + if (empty($exploded[0])) return array($default, $exploded[1]); + return array($exploded[0], $exploded[1]); + } + + public function get_descriptor($source_path){ + $source = file_get_contents($source_path); + + preg_match(self::DESCRIPTOR_REGEX, $source, $matches); + if (empty($matches)) return array(); + + $descriptor = YAML::decode($matches[0]); + + if (!isset($descriptor['name'])) $descriptor['name'] = basename($source_path, '.js'); + if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); + $descriptor['source'] = $source; + $descriptor['provides'] = (array) array_get($descriptor, 'provides'); + + $requires = (array) array_get($descriptor, 'requires'); + $descriptor['requires'] = array_map(array($this, 'normalize_requires'), $requires); + + return $descriptor; + } + + public function get_files(){ + $files = array(); + foreach ($this->sources as $descriptor) $files[] = $descriptor['package/name']; + return $files; + } + + public function get_manifest(){ + return $this->manifest; + } + + public function get_name(){ + return $this->name; + } + + public function get_source_with_component($component){ + foreach ($this->sources as $source){ + if (array_contains($source['provides'], $component)) return $source; + } + return null; + } + + public function get_source_with_file($name){ + return array_get($this->sources, $name); + } + + public function get_root_dir(){ + return $this->root_dir; + } + + public function resolve_path($path){ + if (!is_dir($path) && file_exists($path)) return $path; + + $pathinfo = pathinfo($path); + $path = $pathinfo['dirname'] . '/' . $pathinfo['basename'] . '/'; + + if (file_exists($path . 'package.yml')) return $path . 'package.yml'; + if (file_exists($path . 'package.yaml')) return $path . 'package.yaml'; + if (file_exists($path . 'package.json')) return $path . 'package.json'; + + throw new Exception("package.(yml|yaml|json) not found in $path."); + } + + # todo(ibolmo): Consider passing a callback function `onError` rather than passing Packager instance in constructor. + public function validate(){ + foreach ($this->sources as $descriptor){ + $file_requires = $descriptor['requires']; + foreach ($file_requires as $component){ + if (!$this->manager->component_exists($component)){ + # todo(ibolmo): Pass, or create, a logger in constructor rather than depend on Packager + Packager::warn("WARNING: The component $component, required in the file " . $file['package/name'] . ", has not been provided.\n"); + } + } + } + } + + protected function normalize_manifest(){ + $manifest = $this->manifest; + if (!is_array($manifest['sources'])){ + # todo(ibolmo): 5, should be a class option + $manifest['sources'] = self::glob($this->path, $manifest['sources'], 0, 5); + foreach ($manifest['sources'] as $i => $source_path) $manifest['sources'][$i] = $this->root_dir . $source_path; + } + } + + protected function normalize_requires($require){ + return implode('/', self::parse_name($this->name, $require)); + } +} diff --git a/packager.php b/packager.php index c24e8aa..358259b 100644 --- a/packager.php +++ b/packager.php @@ -2,242 +2,166 @@ require dirname(__FILE__) . "/helpers/yaml.php"; require dirname(__FILE__) . "/helpers/array.php"; +require dirname(__FILE__) . '/Package.php'; -class Package -{ - const DESCRIPTOR_REGEX = '/\/\*\s*^---(.*?)^(?:\.\.\.|---)\s*\*\//ms'; - protected $sources = array(); - - public function __construct(Packager $manager, $path) - { - $this->manager = $manager; - $this->path = $this->resolve_path($path); - $this->root_dir = dirname($this->path); +class Packager { - $this->manifest = self::decode($this->path); - $this->normalize_manifest(); + private $files = array(); + private $manifests = array(); + private $packages = array(); + private $root = null; - $this->name = $this->manifest['name']; - - foreach ($this->manifest['sources'] as $i => $source_path) { - $source_path = $this->root_dir . '/' . $source_path; - $descriptor = $this->get_descriptor($source_path); - $this->sources[$descriptor['name']] = array_merge($descriptor, array( - 'package' => $this->name, - 'path' => $source_path, - 'package/name' => sprintf('%s/%s', $this->name, $descriptor['name']) - )); - } + public function __construct($package_paths){ + foreach ((array) $package_paths as $package_path) $this->add_package($package_path); + } + + static function info($message){ + $std_out = fopen('php://stdout', 'w'); + fwrite($std_out, $message); + fclose($std_out); } - static function decode($path) - { - return preg_match('/\.json$/', $path) ? json_decode(file_get_contents($path), true) : YAML::decode_file($path); + static function warn($message){ + $std_err = fopen('php://stderr', 'w'); + fwrite($std_err, $message); + fclose($std_err); } - static function glob($path, $pattern = '*', $flags = 0, $depth = 0) - { - $matches = array(); - $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); - - while ($folder = array_shift($folders)){ - $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); - if ($depth != 0) { - $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); - $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; - $folders = array_merge($folders, $moreFolders); - } + public function __call($method, $arguments){ + if (strpos($method, 'get_file_') === 0){ + $file = array_get($arguments, 0); + if (empty($file)) return null; + $key = substr($method, 9); + $hash = $this->file_to_hash($file); + return array_get($hash, $key); + } + + if (strpos($method, 'get_package_') === 0){ + $key = substr($method, 12); + $package = array_get($arguments, 0); + $package = array_get($this->manifests, (empty($package)) ? $this->root : $package); + return array_get($package, $key); } - return $matches; + + return null; } - static function parse_name($default, $name) - { - $exploded = explode('/', $name); - $length = count($exploded); - if ($length == 1) return array($default, $exploded[0]); - if (empty($exploded[0])) return array($default, $exploded[1]); - return array($exploded[0], $exploded[1]); + public function add_package($package_path){ + $package = ($package_path instanceof Package) ? $package_path : new Package($this, $package_path); + $name = $package->get_name(); + if (!$this->root) $this->root = $name; + if (array_has($this->manifests, $name)) continue; + $this->packages[$name] = $package; + $this->manifests[$name] = $package->get_manifest(); } - - public function get_descriptor($source_path) - { - $source = file_get_contents($source_path); + + public function build($files = array(), $components = array(), $packages = array(), $blocks = array(), $excluded = array()){ + + $files = $this->resolve_files($files, $components, $packages, $blocks, $excluded); - preg_match(self::DESCRIPTOR_REGEX, $source, $matches); - if (empty($matches)) return array(); + if (empty($files)) return ''; - $descriptor = YAML::decode($matches[0]); - - if (!isset($descriptor['name'])) $descriptor['name'] = basename($source_path, '.js'); - if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); - $descriptor['source'] = $source; - $descriptor['provides'] = (array) array_get($descriptor, 'provides'); + $included_sources = array(); + foreach ($files as $file) $included_sources[] = $this->get_file_source($file); - $requires = (array) array_get($descriptor, 'requires'); - $descriptor['requires'] = array_map(array($this, 'normalize_requires'), $requires); + $source = implode($included_sources, "\n\n"); - return $descriptor; + return $this->remove_blocks($source, $blocks) . "\n"; } - public function get_files() - { - $files = array(); - foreach ($this->sources as $descriptor) $files[] = $descriptor['package/name']; - return $files; + public function build_from_components($components, $excluded = null){ + return $this->build(array(), $components, array(), array(), $excluded); } - public function get_manifest() - { - return $this->manifest; + public function build_from_files($files){ + return $this->build($files); } - - public function get_name() - { - return $this->name; + + public function complete_file($file){ + $files = $this->parse_file_dependancies($file); + $hash = $this->file_to_hash($file); + if (empty($hash)) return array(); + array_include($files, $hash['package/name']); + return $files; } - public function get_source_with_component($component) - { - foreach ($this->sources as $source){ - if (array_contains($source['provides'], $component)) return $source; + public function complete_files($files){ + $ordered_files = array(); + foreach ($files as $file){ + $all_files = $this->complete_file($file); + foreach ($all_files as $one_file) array_include($ordered_files, $one_file); } - return null; - } - - public function get_source_with_file($name) - { - return array_get($this->sources, $name); + return $ordered_files; } - public function get_root_dir() - { - return $this->root_dir; + public function component_to_file($component){ + return array_get($this->component_to_hash($component), 'package/name'); } - public function resolve_path($path) - { - if (!is_dir($path) && file_exists($path)) return $path; - - $pathinfo = pathinfo($path); - $path = $pathinfo['dirname'] . '/' . $pathinfo['basename'] . '/'; - - if (file_exists($path . 'package.yml')) return $path . 'package.yml'; - if (file_exists($path . 'package.yaml')) return $path . 'package.yaml'; - if (file_exists($path . 'package.json')) return $path . 'package.json'; - - throw new Exception("package.(yml|yaml|json) not found in $path."); + public function component_exists($name){ + return $this->component_to_hash($name) ? true : false; } - # todo(ibolmo): Consider passing a callback function `onError` rather than passing Packager instance in constructor. - public function validate() - { - foreach ($this->sources as $descriptor){ - $file_requires = $descriptor['requires']; - foreach ($file_requires as $component){ - if (!$this->manager->component_exists($component)){ - # todo(ibolmo): Pass, or create, a logger in constructor rather than depend on Packager - Packager::warn("WARNING: The component $component, required in the file " . $file['package/name'] . ", has not been provided.\n"); - } - } + public function components_to_files($components){ + $files = array(); + foreach ($components as $component){ + $file_name = $this->component_to_file($component); + if (!empty($file_name) && !in_array($file_name, $files)) $files[] = $file_name; } + return $files; } - protected function normalize_manifest() - { - $manifest = $this->manifest; - if (!is_array($manifest['sources'])){ - # todo(ibolmo): 5, should be a class option - $manifest['sources'] = self::glob($this->path, $manifest['sources'], 0, 5); - foreach ($manifest['sources'] as $i => $source_path) $manifest['sources'][$i] = $this->root_dir . $source_path; - } - } - - protected function normalize_requires($require) - { - return implode('/', self::parse_name($this->name, $require)); + public function file_exists($name){ + return $this->file_to_hash($name) ? true : false; } -} - -class Packager { + public function get_all_files($of_package = null){ + $files = array(); + foreach ($this->packages as $name => $package){ + if ($of_package == null || $of_package == $name) $files = array_merge($files, $package->get_files()); + } + return $files; + } - public static function warn($message){ - $std_err = fopen('php://stderr', 'w'); - fwrite($std_err, $message); - fclose($std_err); + public function get_file_authors($file){ + $hash = $this->file_to_hash($file); + if (empty($hash)) return array(); + return $this->normalize_authors(array_get($hash, 'authors'), array_get($hash, 'author'), $this->get_package_authors()); } - public static function info($message){ - $std_out = fopen('php://stdout', 'w'); - fwrite($std_out, $message); - fclose($std_out); + public function get_file_dependancies($file){ + $this->files = array(); + $deps = $this->parse_file_dependancies($file); + return $deps; } - private $packages = array(); - private $manifests = array(); - private $root = null; - private $files = array(); - - public function __construct($package_paths){ - foreach ((array) $package_paths as $package_path) $this->add_package($package_path); - } - - public function add_package($package_path){ - $package = ($package_path instanceof Package) ? $package_path : new Package($this, $package_path); - $name = $package->get_name(); - if (!$this->root) $this->root = $name; - if (array_has($this->manifests, $name)) continue; - $this->packages[$name] = $package; - $this->manifests[$name] = $package->get_manifest(); - } - - public function remove_package($package_name){ - unset($this->packages[$package_name]); - unset($this->manifests[$package_name]); - } - - // # private HASHES - - private function component_to_hash($name){ - list($name, $component) = Package::parse_name($this->root, $name); - $package = array_get($this->packages, $name); - return !$package ? null : $package->get_source_with_component($component); - } - - private function file_to_hash($name){ - list($name, $file) = Package::parse_name($this->root, $name); - $package = array_get($this->packages, $name); - return !$package ? null : $package->get_source_with_file($file); + public function get_packages(){ + return array_keys($this->packages); } - public function file_exists($name){ - return $this->file_to_hash($name) ? true : false; - } + // authors normalization - public function component_exists($name){ - return $this->component_to_hash($name) ? true : false; + public function get_package_authors($package = null){ + if (empty($package)) $package = $this->root; + $package = array_get($this->manifests, $package); + if (empty($package)) return array(); + return $this->normalize_authors(array_get($package, 'authors'), array_get($package, 'author')); } public function package_exists($name){ return array_contains($this->get_packages(), $name); } - public function validate($more_files = array(), $more_components = array(), $more_packages = array()){ - - foreach ($this->packages as $name => $package) $package->validate(); - - foreach ($more_files as $file){ - if (!$this->file_exists($file)) self::warn("WARNING: The required file $file could not be found.\n"); - } - - foreach ($more_components as $component){ - if (!$this->component_exists($component)) self::warn("WARNING: The required component $component could not be found.\n"); - } - - foreach ($more_packages as $package){ - if (!$this->package_exists($package)) self::warn("WARNING: The required package $package could not be found.\n"); + public function remove_blocks($source, $blocks){ + foreach ($blocks as $block){ + $source = preg_replace_callback("%(/[/*])\s*<$block>(.*?)(?:\s*\*/)?%s", array($this, "block_replacement"), $source); } + return $source; + } + + public function remove_package($package_name){ + unset($this->packages[$package_name]); + unset($this->manifests[$package_name]); } public function resolve_files($files = array(), $components = array(), $packages = array(), $blocks = array(), $excluded = array()){ @@ -261,39 +185,22 @@ public function resolve_files($files = array(), $components = array(), $packages } return $files; } + + public function validate($more_files = array(), $more_components = array(), $more_packages = array()){ - // # public BUILD - public function build($files = array(), $components = array(), $packages = array(), $blocks = array(), $excluded = array()){ - - $files = $this->resolve_files($files, $components, $packages, $blocks, $excluded); - - if (empty($files)) return ''; + foreach ($this->packages as $name => $package) $package->validate(); - $included_sources = array(); - foreach ($files as $file) $included_sources[] = $this->get_file_source($file); + foreach ($more_files as $file){ + if (!$this->file_exists($file)) self::warn("WARNING: The required file $file could not be found.\n"); + } - $source = implode($included_sources, "\n\n"); + foreach ($more_components as $component){ + if (!$this->component_exists($component)) self::warn("WARNING: The required component $component could not be found.\n"); + } - return $this->remove_blocks($source, $blocks) . "\n"; - } - - public function remove_blocks($source, $blocks){ - foreach ($blocks as $block){ - $source = preg_replace_callback("%(/[/*])\s*<$block>(.*?)(?:\s*\*/)?%s", array($this, "block_replacement"), $source); + foreach ($more_packages as $package){ + if (!$this->package_exists($package)) self::warn("WARNING: The required package $package could not be found.\n"); } - return $source; - } - - private function block_replacement($matches){ - return (strpos($matches[2], ($matches[1] == "//") ? "\n" : "*/") === false) ? $matches[2] : ""; - } - - public function build_from_files($files){ - return $this->build($files); - } - - public function build_from_components($components, $excluded = null){ - return $this->build(array(), $components, array(), array(), $excluded); } public function write_from_files($file_name, $files = null){ @@ -306,20 +213,26 @@ public function write_from_components($file_name, $components = null, $exclude = file_put_contents($file_name, $full); } - // # public FILES - - public function get_all_files($of_package = null){ - $files = array(); - foreach ($this->packages as $name => $package){ - if ($of_package == null || $of_package == $name) $files = array_merge($files, $package->get_files()); - } - return $files; + private function block_replacement($matches){ + return (strpos($matches[2], ($matches[1] == "//") ? "\n" : "*/") === false) ? $matches[2] : ""; } - - public function get_file_dependancies($file){ - $this->files = array(); - $deps = $this->parse_file_dependancies($file); - return $deps; + + private function component_to_hash($name){ + list($name, $component) = Package::parse_name($this->root, $name); + $package = array_get($this->packages, $name); + return !$package ? null : $package->get_source_with_component($component); + } + + private function file_to_hash($name){ + list($name, $file) = Package::parse_name($this->root, $name); + $package = array_get($this->packages, $name); + return !$package ? null : $package->get_source_with_file($file); + } + + private function normalize_authors($authors = null, $author = null, $default = null){ + $use = empty($authors) ? $author : $authors; + if (empty($use)) $use = $default; + return (array) $use; } private function parse_file_dependancies($file){ @@ -335,83 +248,4 @@ private function parse_file_dependancies($file){ } return $deps; } - - public function complete_file($file){ - $files = $this->parse_file_dependancies($file); - $hash = $this->file_to_hash($file); - if (empty($hash)) return array(); - array_include($files, $hash['package/name']); - return $files; - } - - public function complete_files($files){ - $ordered_files = array(); - foreach ($files as $file){ - $all_files = $this->complete_file($file); - foreach ($all_files as $one_file) array_include($ordered_files, $one_file); - } - return $ordered_files; - } - - // # public COMPONENTS - - public function component_to_file($component){ - return array_get($this->component_to_hash($component), 'package/name'); - } - - public function components_to_files($components){ - $files = array(); - foreach ($components as $component){ - $file_name = $this->component_to_file($component); - if (!empty($file_name) && !in_array($file_name, $files)) $files[] = $file_name; - } - return $files; - } - - // # dynamic getter for PACKAGE properties and FILE properties - - public function __call($method, $arguments){ - if (strpos($method, 'get_file_') === 0){ - $file = array_get($arguments, 0); - if (empty($file)) return null; - $key = substr($method, 9); - $hash = $this->file_to_hash($file); - return array_get($hash, $key); - } - - if (strpos($method, 'get_package_') === 0){ - $key = substr($method, 12); - $package = array_get($arguments, 0); - $package = array_get($this->manifests, (empty($package)) ? $this->root : $package); - return array_get($package, $key); - } - - return null; - } - - public function get_packages(){ - return array_keys($this->packages); - } - - // authors normalization - - public function get_package_authors($package = null){ - if (empty($package)) $package = $this->root; - $package = array_get($this->manifests, $package); - if (empty($package)) return array(); - return $this->normalize_authors(array_get($package, 'authors'), array_get($package, 'author')); - } - - public function get_file_authors($file){ - $hash = $this->file_to_hash($file); - if (empty($hash)) return array(); - return $this->normalize_authors(array_get($hash, 'authors'), array_get($hash, 'author'), $this->get_package_authors()); - } - - private function normalize_authors($authors = null, $author = null, $default = null){ - $use = empty($authors) ? $author : $authors; - if (empty($use)) $use = $default; - return (array) $use; - } - } From f0903d2ff3e3206b831e07b1e9932014ce4d8029 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 26 Apr 2011 00:51:50 -0500 Subject: [PATCH 21/49] Moved Source specific code into a new Source class. Required if I'm going to add a source dynamically into a package. --- Package.php | 47 ++++++++--------------------------------------- README.md | 39 +++++++++++++++++++++++++++++++++++++++ Source.php | 47 +++++++++++++++++++++++++++++++++++++++++++++++ packager.php | 4 ++-- 4 files changed, 96 insertions(+), 41 deletions(-) create mode 100644 Source.php diff --git a/Package.php b/Package.php index 38dc183..c3b7830 100644 --- a/Package.php +++ b/Package.php @@ -1,8 +1,9 @@ name = $this->manifest['name']; - foreach ($this->manifest['sources'] as $i => $source_path) { - $source_path = $this->root_dir . '/' . $source_path; - $descriptor = $this->get_descriptor($source_path); - $this->sources[$descriptor['name']] = array_merge($descriptor, array( - 'package' => $this->name, - 'path' => $source_path, - 'package/name' => sprintf('%s/%s', $this->name, $descriptor['name']) - )); - } + foreach ($this->manifest['sources'] as $i => $source_path) $this->add_source($source_path); } static function decode($path){ @@ -45,31 +38,11 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ return $matches; } - static function parse_name($default, $name){ - $exploded = explode('/', $name); - $length = count($exploded); - if ($length == 1) return array($default, $exploded[0]); - if (empty($exploded[0])) return array($default, $exploded[1]); - return array($exploded[0], $exploded[1]); - } - - public function get_descriptor($source_path){ - $source = file_get_contents($source_path); - - preg_match(self::DESCRIPTOR_REGEX, $source, $matches); - if (empty($matches)) return array(); - - $descriptor = YAML::decode($matches[0]); - - if (!isset($descriptor['name'])) $descriptor['name'] = basename($source_path, '.js'); - if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); - $descriptor['source'] = $source; - $descriptor['provides'] = (array) array_get($descriptor, 'provides'); - - $requires = (array) array_get($descriptor, 'requires'); - $descriptor['requires'] = array_map(array($this, 'normalize_requires'), $requires); - - return $descriptor; + public function add_source($source_path) + { + $source = ($source_path instanceof Source) ? $source_path : new Source($this, $this->root_dir . '/' . $source_path); + $descriptor = $source->get_descriptor(); + $this->sources[$descriptor['name']] = $descriptor; } public function get_files(){ @@ -135,8 +108,4 @@ protected function normalize_manifest(){ foreach ($manifest['sources'] as $i => $source_path) $manifest['sources'][$i] = $this->root_dir . $source_path; } } - - protected function normalize_requires($require){ - return implode('/', self::parse_name($this->name, $require)); - } } diff --git a/README.md b/README.md index 97f46c9..2878be1 100644 --- a/README.md +++ b/README.md @@ -158,3 +158,42 @@ You can mix components and files This is how you output to a file + +--------- + +# Notes + +Packager has many Package(s) +Package has many Source(s) +Source has many requires +Source has many provides + + +Dependency Graph + + A A Ø <-A-> B, C + / \ A <-B-> D, E + B C A <-C-> Ø + B / \ B <-D-> Ø + D E B <-E-> Ø + Ø Ø <-F-> Ø + / + C F + +A referenced by A, A.js, Package/A, A#a, A#b, A#..., A#z (where A#a-z is a component. E.g. Type and typeOf references Source A) + +A global dependency graph will be constructed. When a build requires an entity (a reference to a source) then graph is checked for source. If not found, then throw error. If found, then traverse tree up to roots (node with no requires). + +Traversal example: + + A Z A + \ / \ + B C + B / \ + D E + Ø + / + C F + +`require(D)` resolves: D, B, Z, A. Z and A have no priority. If they did, then Z or A would require the other. +`require(F)` resolves: F, and throw an Error or warning (depending on configuration) if a required module is missing. diff --git a/Source.php b/Source.php new file mode 100644 index 0000000..0320429 --- /dev/null +++ b/Source.php @@ -0,0 +1,47 @@ +package = $package; + $this->path = $source_path; + } + + static function parse_name($default, $name){ + $exploded = explode('/', $name); + $length = count($exploded); + if ($length == 1) return array($default, $exploded[0]); + if (empty($exploded[0])) return array($default, $exploded[1]); + return array($exploded[0], $exploded[1]); + } + + public function get_descriptor() + { + $source = file_get_contents($this->path); + + preg_match(self::DESCRIPTOR_REGEX, $source, $matches); + if (empty($matches)) return array(); + + $descriptor = YAML::decode($matches[0]); + + if (!isset($descriptor['name'])) $descriptor['name'] = basename($this->path, '.js'); + if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); + $descriptor['source'] = $source; + $descriptor['provides'] = (array) array_get($descriptor, 'provides'); + + $requires = (array) array_get($descriptor, 'requires'); + $descriptor['requires'] = array_map(array($this, 'normalize_requires'), $requires); + + return array_merge($descriptor, array( + 'package' => $this->package->get_name(), + 'package/name' => sprintf('%s/%s', $this->package->get_name(), $descriptor['name']) + )); + } + + protected function normalize_requires($require){ + return implode('/', self::parse_name($this->package->get_name(), $require)); + } +} diff --git a/packager.php b/packager.php index 358259b..2f920bf 100644 --- a/packager.php +++ b/packager.php @@ -218,13 +218,13 @@ private function block_replacement($matches){ } private function component_to_hash($name){ - list($name, $component) = Package::parse_name($this->root, $name); + list($name, $component) = Source::parse_name($this->root, $name); $package = array_get($this->packages, $name); return !$package ? null : $package->get_source_with_component($component); } private function file_to_hash($name){ - list($name, $file) = Package::parse_name($this->root, $name); + list($name, $file) = Source::parse_name($this->root, $name); $package = array_get($this->packages, $name); return !$package ? null : $package->get_source_with_file($file); } From 1bce00bd6ea86922e67e734e19c54529a28dfe5f Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Wed, 27 Apr 2011 00:22:25 -0500 Subject: [PATCH 22/49] Small optimization and added option for added a source to return the descriptor. --- Source.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source.php b/Source.php index 0320429..ddf3848 100644 --- a/Source.php +++ b/Source.php @@ -12,15 +12,14 @@ function __construct($package, $source_path) static function parse_name($default, $name){ $exploded = explode('/', $name); - $length = count($exploded); - if ($length == 1) return array($default, $exploded[0]); + if (count($exploded) == 1) return array($default, $exploded[0]); if (empty($exploded[0])) return array($default, $exploded[1]); return array($exploded[0], $exploded[1]); } - public function get_descriptor() + public function get_descriptor($source = '') { - $source = file_get_contents($this->path); + if (!$source) $source = file_get_contents($this->path); preg_match(self::DESCRIPTOR_REGEX, $source, $matches); if (empty($matches)) return array(); From d848d8eca9e9818a2f02768bde2c8fbcddfc6a92 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Wed, 27 Apr 2011 01:43:00 -0500 Subject: [PATCH 23/49] Stripped down and cleaned up the parsing. Packager next.. this will break everything. ;) --- Package.php | 100 ++++++++++++++++++---------------------------------- Source.php | 74 +++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 90 deletions(-) diff --git a/Package.php b/Package.php index c3b7830..8f8adfc 100644 --- a/Package.php +++ b/Package.php @@ -1,22 +1,17 @@ manager = $manager; - $this->path = $this->resolve_path($path); - $this->root_dir = dirname($this->path); - - $this->manifest = self::decode($this->path); - $this->normalize_manifest(); - - $this->name = $this->manifest['name']; - - foreach ($this->manifest['sources'] as $i => $source_path) $this->add_source($source_path); + public function __construct($package_path = '') + { + if ($package_path){ + $this->path = $this->resolve_path($package_path); + $this->root_dir = dirname($this->path); + $this->parse($package_path); + } } static function decode($path){ @@ -26,7 +21,7 @@ static function decode($path){ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ $matches = array(); $folders = array(rtrim($path, DIRECTORY_SEPARATOR)); - + while ($folder = array_shift($folders)){ $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); if ($depth != 0) { @@ -38,74 +33,47 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ return $matches; } - public function add_source($source_path) + public function add_source($source_path = '') { - $source = ($source_path instanceof Source) ? $source_path : new Source($this, $this->root_dir . '/' . $source_path); - $descriptor = $source->get_descriptor(); - $this->sources[$descriptor['name']] = $descriptor; + if (!is_a($source, 'Source')) $source = new Source($source_path); + throw new Exception('TODO'); } - public function get_files(){ - $files = array(); - foreach ($this->sources as $descriptor) $files[] = $descriptor['package/name']; - return $files; - } - - public function get_manifest(){ - return $this->manifest; - } - - public function get_name(){ - return $this->name; - } - - public function get_source_with_component($component){ - foreach ($this->sources as $source){ - if (array_contains($source['provides'], $component)) return $source; + public function parse($package_path) + { + $package = self::decode($package_path); + + foreach ($package as $key => $value){ + $method = 'parse_' . strtolower($key); + if (is_callable(array($this, $method))) $this->$method($value); } - return null; } - public function get_source_with_file($name){ - return array_get($this->sources, $name); + public function parse_name($name) + { + $this->name = $name; } - public function get_root_dir(){ - return $this->root_dir; + public function parse_sources($sources) + { + # todo(ibolmo): 5, should be a class option. + if (is_string($sources)){ + $sources = self::glob($this->path, $sources, 0, 5); + foreach ($sources as $i => $source_path) $sources[$i] = $this->root_dir . $source_path; + } + foreach ($sources as $source) $this->add_source($source); } public function resolve_path($path){ if (!is_dir($path) && file_exists($path)) return $path; - + $pathinfo = pathinfo($path); $path = $pathinfo['dirname'] . '/' . $pathinfo['basename'] . '/'; - + if (file_exists($path . 'package.yml')) return $path . 'package.yml'; if (file_exists($path . 'package.yaml')) return $path . 'package.yaml'; if (file_exists($path . 'package.json')) return $path . 'package.json'; - - throw new Exception("package.(yml|yaml|json) not found in $path."); - } - - # todo(ibolmo): Consider passing a callback function `onError` rather than passing Packager instance in constructor. - public function validate(){ - foreach ($this->sources as $descriptor){ - $file_requires = $descriptor['requires']; - foreach ($file_requires as $component){ - if (!$this->manager->component_exists($component)){ - # todo(ibolmo): Pass, or create, a logger in constructor rather than depend on Packager - Packager::warn("WARNING: The component $component, required in the file " . $file['package/name'] . ", has not been provided.\n"); - } - } - } - } - - protected function normalize_manifest(){ - $manifest = $this->manifest; - if (!is_array($manifest['sources'])){ - # todo(ibolmo): 5, should be a class option - $manifest['sources'] = self::glob($this->path, $manifest['sources'], 0, 5); - foreach ($manifest['sources'] as $i => $source_path) $manifest['sources'][$i] = $this->root_dir . $source_path; - } + + throw new Exception("package.(ya?ml|json) not found in $path."); } } diff --git a/Source.php b/Source.php index ddf3848..dc137de 100644 --- a/Source.php +++ b/Source.php @@ -1,13 +1,19 @@ package = $package; - $this->path = $source_path; + $this->package_name = $package_name; + + if ($source_path){ + $this->path = $source_path; + $this->parse($source_path); + } } static function parse_name($default, $name){ @@ -17,30 +23,50 @@ static function parse_name($default, $name){ return array($exploded[0], $exploded[1]); } - public function get_descriptor($source = '') + public function get_name() { - if (!$source) $source = file_get_contents($this->path); - - preg_match(self::DESCRIPTOR_REGEX, $source, $matches); - if (empty($matches)) return array(); - - $descriptor = YAML::decode($matches[0]); - - if (!isset($descriptor['name'])) $descriptor['name'] = basename($this->path, '.js'); - if (!isset($descriptorp['license'])) $descriptor['license'] = array_get($this->manifest, 'license'); - $descriptor['source'] = $source; - $descriptor['provides'] = (array) array_get($descriptor, 'provides'); - - $requires = (array) array_get($descriptor, 'requires'); - $descriptor['requires'] = array_map(array($this, 'normalize_requires'), $requires); + if (!$this->name) $this->name = basename($this->path, '.js'); + return $this->name; + } + + public function parse($source_path) + { + $this->source = file_get_contents($source_path); + preg_match(self::DESCRIPTOR_REGEX, $this->source, $matches); + if (empty($matches)) throw new Exception("No yaml header present in $source_path"); - return array_merge($descriptor, array( - 'package' => $this->package->get_name(), - 'package/name' => sprintf('%s/%s', $this->package->get_name(), $descriptor['name']) - )); + $header = YAML::decode($matches[0]); + foreach($header as $key => $value){ + $method = 'parse_' . strtolower($key); + if (is_callable(array($this, $method))) $this->$method($value); + } + } + + public function parse_name($name) + { + $this->name = $name; + } + + public function parse_provides($provides) + { + $provides = (array) $provides; + $this->provides($provides); } - protected function normalize_requires($require){ - return implode('/', self::parse_name($this->package->get_name(), $require)); + public function parse_requires($requires) + { + $requires = (array) $requires; + foreach ($requires as $i => $require) $require[$i] = implode('/', self::parse_name($this->package_name, $require)); + $this->requires($requires); + } + + public function provides($provides) + { + throw new Exception('TODO'); + } + + public function requires($requires) + { + throw new Exception('TODO'); } } From 1deeaed4b35829e24ac4eed66e0bc55d08d7a12f Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Wed, 27 Apr 2011 01:44:16 -0500 Subject: [PATCH 24/49] All Class files should have a capitalized filename. --- packager.php => Packager.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packager.php => Packager.php (100%) diff --git a/packager.php b/Packager.php similarity index 100% rename from packager.php rename to Packager.php From 4547ea71ce938ea6e759d3095d2f37536cb92432 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Wed, 27 Apr 2011 02:05:45 -0500 Subject: [PATCH 25/49] interim. getting late. --- Packager.php | 248 ++------------------------------------------------- 1 file changed, 9 insertions(+), 239 deletions(-) diff --git a/Packager.php b/Packager.php index 2f920bf..63759f3 100644 --- a/Packager.php +++ b/Packager.php @@ -1,251 +1,21 @@ add_package($package_path); - } - - static function info($message){ - $std_out = fopen('php://stdout', 'w'); - fwrite($std_out, $message); - fclose($std_out); - } - - static function warn($message){ - $std_err = fopen('php://stderr', 'w'); - fwrite($std_err, $message); - fclose($std_err); - } - - public function __call($method, $arguments){ - if (strpos($method, 'get_file_') === 0){ - $file = array_get($arguments, 0); - if (empty($file)) return null; - $key = substr($method, 9); - $hash = $this->file_to_hash($file); - return array_get($hash, $key); - } - - if (strpos($method, 'get_package_') === 0){ - $key = substr($method, 12); - $package = array_get($arguments, 0); - $package = array_get($this->manifests, (empty($package)) ? $this->root : $package); - return array_get($package, $key); - } - - return null; - } + static $instance; - public function add_package($package_path){ - $package = ($package_path instanceof Package) ? $package_path : new Package($this, $package_path); - $name = $package->get_name(); - if (!$this->root) $this->root = $name; - if (array_has($this->manifests, $name)) continue; - $this->packages[$name] = $package; - $this->manifests[$name] = $package->get_manifest(); - } - - public function build($files = array(), $components = array(), $packages = array(), $blocks = array(), $excluded = array()){ - - $files = $this->resolve_files($files, $components, $packages, $blocks, $excluded); - - if (empty($files)) return ''; - - $included_sources = array(); - foreach ($files as $file) $included_sources[] = $this->get_file_source($file); - - $source = implode($included_sources, "\n\n"); - - return $this->remove_blocks($source, $blocks) . "\n"; - } - - public function build_from_components($components, $excluded = null){ - return $this->build(array(), $components, array(), array(), $excluded); + static function get_instance() + { + if (!self::$instance) self::$instance = new Packager(); + return self::$instance; } - public function build_from_files($files){ - return $this->build($files); - } - - public function complete_file($file){ - $files = $this->parse_file_dependancies($file); - $hash = $this->file_to_hash($file); - if (empty($hash)) return array(); - array_include($files, $hash['package/name']); - return $files; + public function register($package) + { + if (!is_a($package, 'Package')) $package = new Package($package); + $this->packages[] = $package; } - public function complete_files($files){ - $ordered_files = array(); - foreach ($files as $file){ - $all_files = $this->complete_file($file); - foreach ($all_files as $one_file) array_include($ordered_files, $one_file); - } - return $ordered_files; - } - - public function component_to_file($component){ - return array_get($this->component_to_hash($component), 'package/name'); - } - - public function component_exists($name){ - return $this->component_to_hash($name) ? true : false; - } - - public function components_to_files($components){ - $files = array(); - foreach ($components as $component){ - $file_name = $this->component_to_file($component); - if (!empty($file_name) && !in_array($file_name, $files)) $files[] = $file_name; - } - return $files; - } - - public function file_exists($name){ - return $this->file_to_hash($name) ? true : false; - } - - public function get_all_files($of_package = null){ - $files = array(); - foreach ($this->packages as $name => $package){ - if ($of_package == null || $of_package == $name) $files = array_merge($files, $package->get_files()); - } - return $files; - } - - public function get_file_authors($file){ - $hash = $this->file_to_hash($file); - if (empty($hash)) return array(); - return $this->normalize_authors(array_get($hash, 'authors'), array_get($hash, 'author'), $this->get_package_authors()); - } - - public function get_file_dependancies($file){ - $this->files = array(); - $deps = $this->parse_file_dependancies($file); - return $deps; - } - - public function get_packages(){ - return array_keys($this->packages); - } - - // authors normalization - - public function get_package_authors($package = null){ - if (empty($package)) $package = $this->root; - $package = array_get($this->manifests, $package); - if (empty($package)) return array(); - return $this->normalize_authors(array_get($package, 'authors'), array_get($package, 'author')); - } - - public function package_exists($name){ - return array_contains($this->get_packages(), $name); - } - - public function remove_blocks($source, $blocks){ - foreach ($blocks as $block){ - $source = preg_replace_callback("%(/[/*])\s*<$block>(.*?)(?:\s*\*/)?%s", array($this, "block_replacement"), $source); - } - return $source; - } - - public function remove_package($package_name){ - unset($this->packages[$package_name]); - unset($this->manifests[$package_name]); - } - - public function resolve_files($files = array(), $components = array(), $packages = array(), $blocks = array(), $excluded = array()){ - if (!empty($components)){ - $more = $this->components_to_files($components); - foreach ($more as $file) array_include($files, $file); - } - - foreach ($packages as $package){ - $more = $this->get_all_files($package); - foreach ($more as $file) array_include($files, $file); - } - - $files = $this->complete_files($files); - - if (!empty($excluded)){ - $less = array(); - foreach ($this->components_to_files($excluded) as $file) array_include($less, $file); - $exclude = $this->complete_files($less); - $files = array_diff($files, $exclude); - } - return $files; - } - - public function validate($more_files = array(), $more_components = array(), $more_packages = array()){ - - foreach ($this->packages as $name => $package) $package->validate(); - - foreach ($more_files as $file){ - if (!$this->file_exists($file)) self::warn("WARNING: The required file $file could not be found.\n"); - } - - foreach ($more_components as $component){ - if (!$this->component_exists($component)) self::warn("WARNING: The required component $component could not be found.\n"); - } - - foreach ($more_packages as $package){ - if (!$this->package_exists($package)) self::warn("WARNING: The required package $package could not be found.\n"); - } - } - - public function write_from_files($file_name, $files = null){ - $full = $this->build_from_files($files); - file_put_contents($file_name, $full); - } - - public function write_from_components($file_name, $components = null, $exclude = null){ - $full = $this->build_from_components($components, $exclude); - file_put_contents($file_name, $full); - } - - private function block_replacement($matches){ - return (strpos($matches[2], ($matches[1] == "//") ? "\n" : "*/") === false) ? $matches[2] : ""; - } - - private function component_to_hash($name){ - list($name, $component) = Source::parse_name($this->root, $name); - $package = array_get($this->packages, $name); - return !$package ? null : $package->get_source_with_component($component); - } - - private function file_to_hash($name){ - list($name, $file) = Source::parse_name($this->root, $name); - $package = array_get($this->packages, $name); - return !$package ? null : $package->get_source_with_file($file); - } - - private function normalize_authors($authors = null, $author = null, $default = null){ - $use = empty($authors) ? $author : $authors; - if (empty($use)) $use = $default; - return (array) $use; - } - - private function parse_file_dependancies($file){ - $deps = array(); - $hash = $this->file_to_hash($file); - - if (empty($hash)) return array(); - if (!in_array($file, $this->files)) { - $this->files[] = $file; - $files = $this->components_to_files($hash['requires']); - $files = array_diff($files, $this->files); - $deps = $this->complete_files($files); - } - return $deps; - } } From dc71b9d118cb9bae62759010b8a6790924f3752d Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 28 Apr 2011 10:32:19 -0500 Subject: [PATCH 26/49] Some more work done on the Source. Now working on the graph on the Packager. As on now, Package is just a nice container of sources. Sources are a container of requires and provides, and each requires and provides is added to Packager so that it builds the graph. Next, I need to create and populate the graph, search and find components, iterate the graph for dependencies, and build a chain. --- Package.php | 6 ++++-- Packager.php | 13 ++++++++++++- Source.php | 46 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Package.php b/Package.php index 8f8adfc..ab36ef2 100644 --- a/Package.php +++ b/Package.php @@ -5,6 +5,8 @@ class Package { + protected $sources = array(); + public function __construct($package_path = '') { if ($package_path){ @@ -35,8 +37,8 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ public function add_source($source_path = '') { - if (!is_a($source, 'Source')) $source = new Source($source_path); - throw new Exception('TODO'); + if (!is_a($source_path, 'Source')) $source_path = new Source($source_path); + $this->sources[] = $source_path; } public function parse($package_path) diff --git a/Packager.php b/Packager.php index 63759f3..c321f3f 100644 --- a/Packager.php +++ b/Packager.php @@ -5,6 +5,7 @@ class Packager { static $instance; + private static $graph = array(); static function get_instance() { @@ -12,10 +13,20 @@ static function get_instance() return self::$instance; } - public function register($package) + public function add_package($package) { if (!is_a($package, 'Package')) $package = new Package($package); $this->packages[] = $package; } + public function add_component(Source $source, $component) + { + throw new Exception('TODO'); + } + + public function add_dependency(Source $source, $component) + { + throw new Exception('TODO'); + } + } diff --git a/Source.php b/Source.php index dc137de..6ccca54 100644 --- a/Source.php +++ b/Source.php @@ -1,11 +1,15 @@ package_name = $package_name; @@ -29,10 +33,18 @@ public function get_name() return $this->name; } - public function parse($source_path) + public function get_code() + { + return $this->code; + } + + public function parse($source_path = '') { - $this->source = file_get_contents($source_path); - preg_match(self::DESCRIPTOR_REGEX, $this->source, $matches); + if ($source_path) $this->code = file_get_contents($source_path); + + if (!$this->code) throw new RuntimeException('Missing the code to parse. Did you forget to supply the source_path or set_code?'); + + preg_match(self::DESCRIPTOR_REGEX, $this->code, $matches); if (empty($matches)) throw new Exception("No yaml header present in $source_path"); $header = YAML::decode($matches[0]); @@ -62,11 +74,33 @@ public function parse_requires($requires) public function provides($provides) { - throw new Exception('TODO'); + $packager = Packager::get_instance(); + foreach ($provides as $component){ + $packager->add_component($source, $component); + $this->provides[] = $component; + } + return $this; } public function requires($requires) { - throw new Exception('TODO'); + $packager = Packager::get_instance(); + foreach ($requires as $component){ + $packager->add_dependency($source, $component); + $this->requires[] = $component; + } + return $this; + } + + public function set_name($name) + { + $this->name = $name; + return $this; + } + + public function set_code($code) + { + $this->code = $code; + return $this; } } From eb4a5898d5c7ddb71ec7eaf04e9e96ceeb7da04c Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 29 Apr 2011 13:11:14 -0500 Subject: [PATCH 27/49] Added the add_component method. The graph structure is just two arrays. First for sources, and the other for source index keys. The keys are generated by generators that can be programmatically be added. See #configure method. Tip: override configure and add your own generators above or below the parent::configure call. Still missing the add_dependency and build methods. --- Packager.php | 78 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/Packager.php b/Packager.php index c321f3f..98218ff 100644 --- a/Packager.php +++ b/Packager.php @@ -5,28 +5,94 @@ class Packager { static $instance; + + protected $components = array(); + protected $generators = array(); + protected $keys = array(); + private static $graph = array(); + public function __construct($package_paths = '') + { + $this->configure(); + if ($package_paths) foreach ((array) $package_paths as $package) $this->add_package($package); + } + + public function configure() + { + $this->add_generator('component name', function(Source $source, $component){ + return $component; + }); + + $this->add_generator('source name', function(Source $source, $component){ + return $source->get_name(); + }); + + $this->add_generator('package and source name', function(Source $source, $component){ + return sprintf('%s/%s', $source->get_package_name(), $source->get_name()); + }); + } + + public function get_component_index(Source $source, $component) + { + foreach ($this->generators as $generator){ + $key = call_user_func($generator['callback'], $source, $component); + if (isset($this->keys[$key])) return $this->keys[$key]; + } + return -1; + } + static function get_instance() { if (!self::$instance) self::$instance = new Packager(); return self::$instance; } - public function add_package($package) + public function add_component(Source $source, $component) { - if (!is_a($package, 'Package')) $package = new Package($package); - $this->packages[] = $package; + $index = $this->get_component_index($source, $component); + if ($index < 0){ + $index = array_push($this->components, $component) - 1; + foreach ($this->generators as $generator){ + list($callback, $name) = $generator; + $this->set_key(call_user_func($callback, $source, $component), $index, $name); + } + } + return $index; } - public function add_component(Source $source, $component) + public function add_dependency(Source $source, $component) { throw new Exception('TODO'); } - public function add_dependency(Source $source, $component) + public function add_generator($name, $callback) { - throw new Exception('TODO'); + $this->generators[] = array('name' => $name, 'callback' => $callback); + } + + public function add_package($package) + { + if (!is_a($package, 'Package')) $package = new Package($package); + $this->packages[] = $package; + } + + protected function set_key($key, $index, $generator_name) + { + if (isset($this->keys[$key])) throw new Exception("Generator, $generator_name, attempted to override component key, $key."); + $this->keys[$key] = $index; } } + +/* + + Beginning of time :: [], {} + Add a component :: [Component_0], {key: index_0, alias: index_0, other_alias: index_0} + Add a component :: [Component_0, Component_1], {key_0: index_0, alias_0: index_0, other_alias_0: index_0, key_1: index_1, alias_1: index_1, other_alias_1: index_1} + + Beginning of time :: [], {} + Add a component :: [Component], {key: index, ...} + Add a dependency :: + +*/ From 6b157d91c79f129904fa64da982deb157a3e4bd3 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 29 Apr 2011 13:19:42 -0500 Subject: [PATCH 28/49] Small fix and removing notes --- Packager.php | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/Packager.php b/Packager.php index 98218ff..1a0cb94 100644 --- a/Packager.php +++ b/Packager.php @@ -6,7 +6,7 @@ class Packager { static $instance; - protected $components = array(); + protected $sources = array(); protected $generators = array(); protected $keys = array(); @@ -52,7 +52,8 @@ public function add_component(Source $source, $component) { $index = $this->get_component_index($source, $component); if ($index < 0){ - $index = array_push($this->components, $component) - 1; + # todo(ibolmo): this smells because $component is not really useful since right now we're adding source files together, and not components. + $index = array_push($this->sources, $source) - 1; foreach ($this->generators as $generator){ list($callback, $name) = $generator; $this->set_key(call_user_func($callback, $source, $component), $index, $name); @@ -84,15 +85,3 @@ protected function set_key($key, $index, $generator_name) } } - -/* - - Beginning of time :: [], {} - Add a component :: [Component_0], {key: index_0, alias: index_0, other_alias: index_0} - Add a component :: [Component_0, Component_1], {key_0: index_0, alias_0: index_0, other_alias_0: index_0, key_1: index_1, alias_1: index_1, other_alias_1: index_1} - - Beginning of time :: [], {} - Add a component :: [Component], {key: index, ...} - Add a dependency :: - -*/ From 8e83c2ead1082d82a2c5ae7392e6aab1f66c46b8 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 29 Apr 2011 13:21:47 -0500 Subject: [PATCH 29/49] Forgot to include the Source#get_package_name --- Source.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Source.php b/Source.php index 6ccca54..573e893 100644 --- a/Source.php +++ b/Source.php @@ -27,15 +27,20 @@ static function parse_name($default, $name){ return array($exploded[0], $exploded[1]); } + public function get_code() + { + return $this->code; + } + public function get_name() { if (!$this->name) $this->name = basename($this->path, '.js'); return $this->name; } - public function get_code() + public function get_package_name() { - return $this->code; + return $this->package_name; } public function parse($source_path = '') From ef6dcb424104892b036ffce6801881e1fcbfdbb6 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 29 Apr 2011 13:24:33 -0500 Subject: [PATCH 30/49] Another small fix. list doesn't work with indexed arrays. --- Packager.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Packager.php b/Packager.php index 1a0cb94..b1c0e0b 100644 --- a/Packager.php +++ b/Packager.php @@ -52,11 +52,11 @@ public function add_component(Source $source, $component) { $index = $this->get_component_index($source, $component); if ($index < 0){ - # todo(ibolmo): this smells because $component is not really useful since right now we're adding source files together, and not components. + # note(ibolmo): this smells because $component is not really useful since right now we're adding source files together, and not components. $index = array_push($this->sources, $source) - 1; foreach ($this->generators as $generator){ - list($callback, $name) = $generator; - $this->set_key(call_user_func($callback, $source, $component), $index, $name); + $key = call_user_func($generator['callback'], $source, $component); + $this->set_key($key, $index, $generator['name']); } } return $index; From 4228d60b7b031fe0bfc2d3efef4bd11b1d6d62f4 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sat, 30 Apr 2011 10:26:24 -0500 Subject: [PATCH 31/49] Added a component class. I may remove the class later on. --- Component.php | 15 +++++++++++++++ Packager.php | 24 +++++++++++++++++------- Source.php | 12 +++++++++--- 3 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 Component.php diff --git a/Component.php b/Component.php new file mode 100644 index 0000000..23976ed --- /dev/null +++ b/Component.php @@ -0,0 +1,15 @@ +source = $source; + } + + public function get_source($source) + { + # code... + } +} diff --git a/Packager.php b/Packager.php index b1c0e0b..a86cdb9 100644 --- a/Packager.php +++ b/Packager.php @@ -33,8 +33,10 @@ public function configure() }); } - public function get_component_index(Source $source, $component) + public function get_component_index(Component $component) { + $source = $component->get_source(); + $component = $component->get_name(); foreach ($this->generators as $generator){ $key = call_user_func($generator['callback'], $source, $component); if (isset($this->keys[$key])) return $this->keys[$key]; @@ -48,12 +50,13 @@ static function get_instance() return self::$instance; } - public function add_component(Source $source, $component) + public function add_component(Component $component) { - $index = $this->get_component_index($source, $component); + $index = $this->get_component_index($component); if ($index < 0){ - # note(ibolmo): this smells because $component is not really useful since right now we're adding source files together, and not components. - $index = array_push($this->sources, $source) - 1; + $source = $component->get_source(); + $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; + foreach ($this->generators as $generator){ $key = call_user_func($generator['callback'], $source, $component); $this->set_key($key, $index, $generator['name']); @@ -62,9 +65,16 @@ public function add_component(Source $source, $component) return $index; } + /* + Add dependency between source and component. + */ public function add_dependency(Source $source, $component) - { - throw new Exception('TODO'); + { + $name = $source->get_name(); + if (isset($this->keys[$name])) $source_index = $this->keys[$name]; + else throw new Exception("Could not find source, $name."); + + array_include($this->sources[$key]['requires'], $component); } public function add_generator($name, $callback) diff --git a/Source.php b/Source.php index 573e893..961ec63 100644 --- a/Source.php +++ b/Source.php @@ -10,7 +10,7 @@ class Source protected $provides = array(); protected $requires = array(); - function __construct($package_name, $source_path = '') + public function __construct($package_name, $source_path = '') { $this->package_name = $package_name; @@ -20,6 +20,11 @@ function __construct($package_name, $source_path = '') } } + public function __toString() + { + return $this->get_name(); + } + static function parse_name($default, $name){ $exploded = explode('/', $name); if (count($exploded) == 1) return array($default, $exploded[0]); @@ -81,7 +86,8 @@ public function provides($provides) { $packager = Packager::get_instance(); foreach ($provides as $component){ - $packager->add_component($source, $component); + $component = new Component($this, $component); + $packager->add_component($component); $this->provides[] = $component; } return $this; @@ -91,7 +97,7 @@ public function requires($requires) { $packager = Packager::get_instance(); foreach ($requires as $component){ - $packager->add_dependency($source, $component); + $component = $packager->add_dependency($this, $component); $this->requires[] = $component; } return $this; From da9578ee6ba2c57b9cacc1ebb646268c376ba32c Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sat, 30 Apr 2011 10:28:21 -0500 Subject: [PATCH 32/49] dirname(__FILE__) to __DIR__ --- Package.php | 4 ++-- Packager.php | 2 +- Source.php | 2 +- helpers/yaml.php | 2 +- test/test_package.php | 4 ++-- test/test_packager.php | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Package.php b/Package.php index ab36ef2..f2255b7 100644 --- a/Package.php +++ b/Package.php @@ -1,7 +1,7 @@ add_package($package); return $package; } diff --git a/test/test_packager.php b/test/test_packager.php index 022dc30..17daa65 100644 --- a/test/test_packager.php +++ b/test/test_packager.php @@ -1,6 +1,6 @@ assertEquals($source, self::$packager->get_file_source('Class')); } } From 7dba104f06708f8c5bfbb7174a7739ea66fdd1fa Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sun, 1 May 2011 19:42:33 -0500 Subject: [PATCH 33/49] requiring once.. fixed add_component and add_dependency --- Component.php | 15 ------------- Package.php | 29 ++++++++++++++++++++---- Packager.php | 48 ++++++++++++++++++--------------------- Source.php | 35 ++++++++++++++++++++--------- packager | 4 ++-- test/test_package.php | 52 ++++++++----------------------------------- 6 files changed, 82 insertions(+), 101 deletions(-) delete mode 100644 Component.php diff --git a/Component.php b/Component.php deleted file mode 100644 index 23976ed..0000000 --- a/Component.php +++ /dev/null @@ -1,15 +0,0 @@ -source = $source; - } - - public function get_source($source) - { - # code... - } -} diff --git a/Package.php b/Package.php index f2255b7..45de62a 100644 --- a/Package.php +++ b/Package.php @@ -1,7 +1,7 @@ get_name(); + } + static function decode($path){ return preg_match('/\.json$/', $path) ? json_decode(file_get_contents($path), true) : YAML::decode_file($path); } @@ -37,10 +42,20 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ public function add_source($source_path = '') { - if (!is_a($source_path, 'Source')) $source_path = new Source($source_path); + if (!is_a($source_path, 'Source')) $source_path = new Source($this, $source_path); $this->sources[] = $source_path; } + public function get_name() + { + return $this->name; + } + + public function get_sources() + { + return clone $this->sources; + } + public function parse($package_path) { $package = self::decode($package_path); @@ -53,7 +68,7 @@ public function parse($package_path) public function parse_name($name) { - $this->name = $name; + $this->set_name($name); } public function parse_sources($sources) @@ -66,6 +81,12 @@ public function parse_sources($sources) foreach ($sources as $source) $this->add_source($source); } + public function set_name($name) + { + $this->name = $name; + return $this; + } + public function resolve_path($path){ if (!is_dir($path) && file_exists($path)) return $path; diff --git a/Packager.php b/Packager.php index 1738bc4..1965f23 100644 --- a/Packager.php +++ b/Packager.php @@ -1,6 +1,6 @@ get_source(); - $component = $component->get_name(); - foreach ($this->generators as $generator){ - $key = call_user_func($generator['callback'], $source, $component); - if (isset($this->keys[$key])) return $this->keys[$key]; - } - return -1; + $key = $source->get_name(); + return isset($this->keys[$key]) ? $this->keys[$key] : -1; } static function get_instance() @@ -50,18 +45,16 @@ static function get_instance() return self::$instance; } - public function add_component(Component $component) + public function add_component(Source $source, $component) { - $index = $this->get_component_index($component); - if ($index < 0){ - $source = $component->get_source(); - $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; - - foreach ($this->generators as $generator){ - $key = call_user_func($generator['callback'], $source, $component); - $this->set_key($key, $index, $generator['name']); - } + $index = $this->get_source_index($source); + if ($index < 0) $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; + + foreach ($this->generators as $generator){ + $key = call_user_func($generator['callback'], $source, $component); + $this->set_key($key, $index, $generator['name']); } + return $index; } @@ -69,12 +62,10 @@ public function add_component(Component $component) Add dependency between source and component. */ public function add_dependency(Source $source, $component) - { - $name = $source->get_name(); - if (isset($this->keys[$name])) $source_index = $this->keys[$name]; - else throw new Exception("Could not find source, $name."); - - array_include($this->sources[$key]['requires'], $component); + { + $index = $this->get_source_index($source); + if ($index < 0) throw new Exception("Could not find source '$source'."); + $this->sources[$index]['requires'][] = $component; } public function add_generator($name, $callback) @@ -90,8 +81,13 @@ public function add_package($package) protected function set_key($key, $index, $generator_name) { - if (isset($this->keys[$key])) throw new Exception("Generator, $generator_name, attempted to override component key, $key."); + if (isset($this->keys[$key])) $this->warn("Generator '$generator_name' set component key '$key'."); $this->keys[$key] = $index; } + protected function warn($message) + { + # todo(ibolmo): log mixin + } + } diff --git a/Source.php b/Source.php index 6e29cba..0dce2e6 100644 --- a/Source.php +++ b/Source.php @@ -1,6 +1,7 @@ package_name = $package_name; - if ($source_path){ - $this->path = $source_path; - $this->parse($source_path); - } + if ($source_path) $this->parse($source_path); } public function __toString() @@ -25,7 +23,7 @@ public function __toString() return $this->get_name(); } - static function parse_name($default, $name){ + static function normalize_name($default, $name){ $exploded = explode('/', $name); if (count($exploded) == 1) return array($default, $exploded[0]); if (empty($exploded[0])) return array($default, $exploded[1]); @@ -48,9 +46,22 @@ public function get_package_name() return $this->package_name; } + public function get_provides() + { + return $this->provides; + } + + public function get_requires() + { + return $this->requires; + } + public function parse($source_path = '') { - if ($source_path) $this->code = file_get_contents($source_path); + if ($source_path){ + $this->path = $source_path; + $this->code = file_get_contents($source_path); + } if (!$this->code) throw new RuntimeException('Missing the code to parse. Did you forget to supply the source_path or set_code?'); @@ -58,6 +69,9 @@ public function parse($source_path = '') if (empty($matches)) throw new Exception("No yaml header present in $source_path"); $header = YAML::decode($matches[0]); + # note(ibolmo): This is a band-aid fix for the provides and requires ordering. + ksort($header); + foreach($header as $key => $value){ $method = 'parse_' . strtolower($key); if (is_callable(array($this, $method))) $this->$method($value); @@ -78,7 +92,7 @@ public function parse_provides($provides) public function parse_requires($requires) { $requires = (array) $requires; - foreach ($requires as $i => $require) $require[$i] = implode('/', self::parse_name($this->package_name, $require)); + foreach ($requires as $i => $require) $requires[$i] = implode('/', self::normalize_name($this->package_name, $require)); $this->requires($requires); } @@ -86,8 +100,7 @@ public function provides($provides) { $packager = Packager::get_instance(); foreach ($provides as $component){ - $component = new Component($this, $component); - $packager->add_component($component); + $packager->add_component($this, $component); $this->provides[] = $component; } return $this; @@ -97,7 +110,7 @@ public function requires($requires) { $packager = Packager::get_instance(); foreach ($requires as $component){ - $component = $packager->add_dependency($this, $component); + $packager->add_dependency($this, $component); $this->requires[] = $component; } return $this; diff --git a/packager b/packager index 7722ac2..cf41411 100755 --- a/packager +++ b/packager @@ -1,7 +1,7 @@ #!/usr/bin/env php add_package($package); - return $package; + $package = new Package(); + $package = new Package(__DIR__ . '/fixtures/package.yml'); } - /** - * @depends test_constructor - */ - public function test_get_manifest($package) + public function test_parse_sources() { - $manifest = $package->get_manifest(); - $this->assertEquals(4, count($manifest)); - $this->assertEquals('Core', $manifest['name']); - } - - /** - * @depends test_constructor - */ - public function test_get_source_with_component($package) - { - $descriptor = $package->get_source_with_component('Core'); - $this->assertEquals(0, count($descriptor['requires'])); - $this->assertEquals('Core/Core', $descriptor['package/name']); - - $descriptor = $package->get_source_with_component('Array'); - $this->assertEquals(1, count($descriptor['requires'])); - $this->assertEquals('Core/Type', $descriptor['requires'][0]); - $this->assertEquals('Core/Array', $descriptor['package/name']); - } - - /** - * @depends test_constructor - */ - public function test_get_source_with_file($package) - { - $descriptor = $package->get_source_with_file('Class'); - - $this->assertEquals('Class', $descriptor['name']); - - $this->assertEquals(1, count($descriptor['requires'])); - $this->assertEquals('Core/Array', $descriptor['requires'][0]); - - $this->assertEquals(1, count($descriptor['provides'])); - $this->assertEquals('Class', $descriptor['provides'][0]); + $package = new Package(); + $package->parse_sources(array( + __DIR__ . '/fixtures/Source/Core.js', + __DIR__ . '/fixtures/Source/Browser.js' + )); } } From 06526d87666d94e3d235df3bea673030804646cd Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sun, 1 May 2011 22:21:27 -0500 Subject: [PATCH 34/49] Working tests. --- Package.php | 11 ++-- Packager.php | 8 +-- Source.php | 2 - test/{test_package.php => packageTest.php} | 9 +++ test/packagerTest.php | 13 +++++ test/sourceTest.php | 25 +++++++++ test/test_packager.php | 65 ---------------------- 7 files changed, 55 insertions(+), 78 deletions(-) rename test/{test_package.php => packageTest.php} (51%) create mode 100644 test/packagerTest.php create mode 100644 test/sourceTest.php delete mode 100644 test/test_packager.php diff --git a/Package.php b/Package.php index 45de62a..729a5bd 100644 --- a/Package.php +++ b/Package.php @@ -42,7 +42,7 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ public function add_source($source_path = '') { - if (!is_a($source_path, 'Source')) $source_path = new Source($this, $source_path); + if (!is_a($source_path, 'Source')) $source_path = new Source($this->get_name(), $source_path); $this->sources[] = $source_path; } @@ -53,7 +53,7 @@ public function get_name() public function get_sources() { - return clone $this->sources; + return $this->sources; } public function parse($package_path) @@ -74,11 +74,8 @@ public function parse_name($name) public function parse_sources($sources) { # todo(ibolmo): 5, should be a class option. - if (is_string($sources)){ - $sources = self::glob($this->path, $sources, 0, 5); - foreach ($sources as $i => $source_path) $sources[$i] = $this->root_dir . $source_path; - } - foreach ($sources as $source) $this->add_source($source); + if (is_string($sources)) $sources = self::glob($this->path, $sources, 0, 5); + foreach ($sources as $source) $this->add_source($this->root_dir . '/' . $source); } public function set_name($name) diff --git a/Packager.php b/Packager.php index 1965f23..44694c2 100644 --- a/Packager.php +++ b/Packager.php @@ -50,9 +50,9 @@ public function add_component(Source $source, $component) $index = $this->get_source_index($source); if ($index < 0) $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; - foreach ($this->generators as $generator){ - $key = call_user_func($generator['callback'], $source, $component); - $this->set_key($key, $index, $generator['name']); + foreach ($this->generators as $name => $callback){ + $key = call_user_func($callback, $source, $component); + $this->set_key($key, $index, $name); } return $index; @@ -70,7 +70,7 @@ public function add_dependency(Source $source, $component) public function add_generator($name, $callback) { - $this->generators[] = array('name' => $name, 'callback' => $callback); + $this->generators[$name] = $callback; } public function add_package($package) diff --git a/Source.php b/Source.php index 0dce2e6..e1af3dd 100644 --- a/Source.php +++ b/Source.php @@ -1,7 +1,6 @@ package_name = $package_name; - if ($source_path) $this->parse($source_path); } diff --git a/test/test_package.php b/test/packageTest.php similarity index 51% rename from test/test_package.php rename to test/packageTest.php index bde6b13..826575e 100644 --- a/test/test_package.php +++ b/test/packageTest.php @@ -17,5 +17,14 @@ public function test_parse_sources() __DIR__ . '/fixtures/Source/Core.js', __DIR__ . '/fixtures/Source/Browser.js' )); + $sources = $package->get_sources(); + $this->assertEquals('Core', $sources[0]->get_name()); + $this->assertEquals('Browser', $sources[1]->get_name()); + + $package = new Package(__DIR__ . '/fixtures/package.yml'); + $sources = $package->get_sources(); + $this->assertEquals('Core', $sources[0]->get_name()); + $this->assertEquals('Class', end($sources)->get_name()); + $this->assertEquals(4, count($sources)); } } diff --git a/test/packagerTest.php b/test/packagerTest.php new file mode 100644 index 0000000..3d49e7d --- /dev/null +++ b/test/packagerTest.php @@ -0,0 +1,13 @@ +parse($source_path); + + $this->assertEquals('Class', $source->get_name()); + $this->assertEquals(file_get_contents($source_path), $source->get_code()); + $this->assertEquals(array('Class'), $source->get_provides()); + $this->assertEquals(array('Core/Array'), $source->get_requires()); + } +} diff --git a/test/test_packager.php b/test/test_packager.php deleted file mode 100644 index 17daa65..0000000 --- a/test/test_packager.php +++ /dev/null @@ -1,65 +0,0 @@ -get_all_files(); - $this->assertEquals(4, count($packages_files), 'Should be 4 files'); - } - - public function test_get_packages() - { - $packages = self::$packager->get_packages(); - $this->assertEquals('Core', $packages[0]); - } - - public function test_complete_file() - { - $files = self::$packager->complete_file('Class'); - $this->assertEquals(3, count($files)); - $this->assertEquals('Core/Core', $files[0]); - $this->assertEquals('Core/Class', $files[2]); - } - - public function test_build() - { - $build = self::$packager->build(array('Class')); - $this->assertRegExp('/name: Core/', $build); - $this->assertRegExp('/name: Array/', $build); - $this->assertRegExp('/name: Class/', $build); - $this->assertNotRegExp('/name: Browser/', $build); - } - - public function test_resolve_files() - { - $files = self::$packager->resolve_files(array('Class')); - $this->assertEquals(3, count($files)); - $this->assertEquals('Core/Core', $files[0]); - $this->assertEquals('Core/Class', $files[2]); - } - - public function test_complete_files() - { - $files = self::$packager->complete_files(array('Class')); - $this->assertEquals(3, count($files)); - $this->assertEquals('Core/Core', $files[0]); - $this->assertEquals('Core/Class', $files[2]); - } - - public function test_get_file_source() - { - $source = file_get_contents(__DIR__.'/fixtures/Source/Class.js'); - $this->assertEquals($source, self::$packager->get_file_source('Class')); - } -} - From 9b43497406dd51f95c40b61b3fba962cbf30c872 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Tue, 3 May 2011 23:32:31 -0500 Subject: [PATCH 35/49] Added more coverage and fixed ksort requirement. --- Packager.php | 14 ++++++++++---- Source.php | 2 -- test/packagerTest.php | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Packager.php b/Packager.php index 44694c2..9336fe4 100644 --- a/Packager.php +++ b/Packager.php @@ -18,6 +18,12 @@ public function __construct($package_paths = '') if ($package_paths) foreach ((array) $package_paths as $package) $this->add_package($package); } + static function get_instance() + { + if (!self::$instance) self::$instance = new Packager(); + return self::$instance; + } + public function configure() { $this->add_generator('component name', function(Source $source, $component){ @@ -39,10 +45,9 @@ public function get_source_index($source) return isset($this->keys[$key]) ? $this->keys[$key] : -1; } - static function get_instance() + public function get_sources() { - if (!self::$instance) self::$instance = new Packager(); - return self::$instance; + return $this->sources; } public function add_component(Source $source, $component) @@ -64,7 +69,8 @@ public function add_component(Source $source, $component) public function add_dependency(Source $source, $component) { $index = $this->get_source_index($source); - if ($index < 0) throw new Exception("Could not find source '$source'."); + if ($index < 0) $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; + $this->sources[$index]['requires'][] = $component; } diff --git a/Source.php b/Source.php index e1af3dd..95acc45 100644 --- a/Source.php +++ b/Source.php @@ -67,8 +67,6 @@ public function parse($source_path = '') if (empty($matches)) throw new Exception("No yaml header present in $source_path"); $header = YAML::decode($matches[0]); - # note(ibolmo): This is a band-aid fix for the provides and requires ordering. - ksort($header); foreach($header as $key => $value){ $method = 'parse_' . strtolower($key); diff --git a/test/packagerTest.php b/test/packagerTest.php index 3d49e7d..d282d4b 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -9,5 +9,26 @@ public function test_constructor() $packager = new Packager(); $packager = new Packager(__DIR__ . '/fixtures/package.yml'); } + + public function test_add_component() + { + $packager = new Packager(); + $source = new Source('test'); + + $this->assertEquals(-1, $packager->get_source_index($source)); + $index = $packager->add_component($source, 'test_add_component'); + $this->assertEquals($index, $packager->get_source_index($source)); + } + + public function test_add_dependency() + { + $packager = new Packager(); + $source = new Source('test'); + + $packager->add_dependency($source, 'Core'); + $sources = $packager->get_sources(); + $this->assertEquals($source, $sources[0]['source']) ; + $this->assertEquals('Core', $sources[0]['requires'][0]); + } } From e30bb252fb09428156d25a85cf4290ea536b0072 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 5 May 2011 15:48:23 -0500 Subject: [PATCH 36/49] Removed add_dependency since now that is maintained by source. About to test Packager::build. --- Package.php | 2 +- Packager.php | 97 ++++++++++++++++++++++++++++--------------- Source.php | 16 ++++--- test/packagerTest.php | 32 ++++++++++---- test/sourceTest.php | 25 +++++++++++ 5 files changed, 125 insertions(+), 47 deletions(-) diff --git a/Package.php b/Package.php index 729a5bd..fa074ef 100644 --- a/Package.php +++ b/Package.php @@ -12,7 +12,7 @@ public function __construct($package_path = '') if ($package_path){ $this->path = $this->resolve_path($package_path); $this->root_dir = dirname($this->path); - $this->parse($package_path); + $this->parse($this->path); } } diff --git a/Packager.php b/Packager.php index 9336fe4..a458d9c 100644 --- a/Packager.php +++ b/Packager.php @@ -24,19 +24,67 @@ static function get_instance() return self::$instance; } + public function add_component(Source $source, $component) + { + $index = $this->get_source_index($source); + if ($index < 0) $index = $this->add_source($source); + + foreach ($this->generators as $name => $callback){ + $key = call_user_func($callback, $source, $component); + $this->set_key($key, $index, $name); + } + + return $index; + } + + public function add_generator($name, $callback) + { + $this->generators[$name] = $callback; + } + + public function add_package($package) + { + if (!is_a($package, 'Package')) $package = new Package($package); + $this->packages[] = $package; + } + + public function add_source(Source $source) + { + $index = array_push($this->sources, $source) - 1; + return $this->keys[$source->get_name()] = $index; + } + + public function build(Source $source) + { + $build = array(); + + array_unshift($source->get_code()); + + foreach ($this->get_required_for_source($source) as $required){ + array_unshift($build, $required->get_code()); + } + + return implode("\n", $build); + } + public function configure() { $this->add_generator('component name', function(Source $source, $component){ return $component; }); - $this->add_generator('source name', function(Source $source, $component){ - return $source->get_name(); - }); - $this->add_generator('package and source name', function(Source $source, $component){ return sprintf('%s/%s', $source->get_package_name(), $source->get_name()); }); + + $this->add_generator('package and component name', function(Source $source, $component){ + return sprintf('%s/%s', $source->get_package_name(), $component); + }); + } + + public function get_source_by_name($name) + { + return isset($this->sources[$name]) ? $this->sources[$name] : null; } public function get_source_index($source) @@ -50,39 +98,22 @@ public function get_sources() return $this->sources; } - public function add_component(Source $source, $component) + public function get_required_for_source(Source $source, $required = null) { - $index = $this->get_source_index($source); - if ($index < 0) $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; - - foreach ($this->generators as $name => $callback){ - $key = call_user_func($callback, $source, $component); - $this->set_key($key, $index, $name); + $return = false; + if (!$required){ + $return = true; + $required = array(); } - - return $index; - } - - /* - Add dependency between source and component. - */ - public function add_dependency(Source $source, $component) - { $index = $this->get_source_index($source); - if ($index < 0) $index = array_push($this->sources, array('source' => $source, 'requires' => array())) - 1; - $this->sources[$index]['requires'][] = $component; - } - - public function add_generator($name, $callback) - { - $this->generators[$name] = $callback; - } - - public function add_package($package) - { - if (!is_a($package, 'Package')) $package = new Package($package); - $this->packages[] = $package; + foreach ($this->sources[$index]->get_requires() as $component){ + if (!isset($this->keys[$component])) throw new Exception("Could not find '$component'."); + $required[] = $source = $this->sources[$this->keys[$component]]; + if ($source->has_requires()) $this->get_required_for_source($source, &$required); + } + + if ($return) return $required; } protected function set_key($key, $index, $generator_name) diff --git a/Source.php b/Source.php index 95acc45..1373a59 100644 --- a/Source.php +++ b/Source.php @@ -28,6 +28,11 @@ static function normalize_name($default, $name){ return array($exploded[0], $exploded[1]); } + public function build() + { + return Packager::build($this); + } + public function get_code() { return $this->code; @@ -54,6 +59,11 @@ public function get_requires() return $this->requires; } + public function has_requires() + { + return !empty($this->requires); + } + public function parse($source_path = '') { if ($source_path){ @@ -104,11 +114,7 @@ public function provides($provides) public function requires($requires) { - $packager = Packager::get_instance(); - foreach ($requires as $component){ - $packager->add_dependency($this, $component); - $this->requires[] = $component; - } + $this->requires = $requires; return $this; } diff --git a/test/packagerTest.php b/test/packagerTest.php index d282d4b..d1d02c5 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -7,7 +7,11 @@ class PackagerTest extends PHPUnit_Framework_TestCase public function test_constructor() { $packager = new Packager(); - $packager = new Packager(__DIR__ . '/fixtures/package.yml'); + $packager = Packager::get_instance(); + $packager->add_package(__DIR__ . '/fixtures/package.yml'); + $sources = $packager->get_sources(); + $this->assertEquals(4, count($sources)); + $this->assertEquals('Core', $sources[0]->get_name()); } public function test_add_component() @@ -20,15 +24,27 @@ public function test_add_component() $this->assertEquals($index, $packager->get_source_index($source)); } - public function test_add_dependency() + public function test_get_required_for_source() { - $packager = new Packager(); - $source = new Source('test'); - - $packager->add_dependency($source, 'Core'); + $packager = Packager::get_instance(); + $packager->add_package(__DIR__ . '/fixtures/package.yml'); $sources = $packager->get_sources(); - $this->assertEquals($source, $sources[0]['source']) ; - $this->assertEquals('Core', $sources[0]['requires'][0]); + + $class = end($sources); + + $required = $packager->get_required_for_source($class); + + $this->assertEquals(2, count($required)); + $this->assertEquals('Array', $required[0]->get_name()); + $this->assertEquals('Core', $required[1]->get_name()); + } + + public function test_get_source_by_name() + { + $packager = Packaget::get_instance(); + $source = $packager->get_source_by_name('Class'); + + $packager->build($source); } } diff --git a/test/sourceTest.php b/test/sourceTest.php index 8007df6..b61eae5 100644 --- a/test/sourceTest.php +++ b/test/sourceTest.php @@ -22,4 +22,29 @@ public function test_parse() $this->assertEquals(array('Class'), $source->get_provides()); $this->assertEquals(array('Core/Array'), $source->get_requires()); } + + public function test_no_deps_build() + { + $source = new Source('test'); + + $code = '/* code */'; + $source->set_code($code); + + $this->assertEquals($code, $source->build()); + } + + public function test_deps_build() + { + $source = new Source('Core'); + $source->provides('Type'); + $core_code = '/* Core */'; + $source->set_code($core_code); + + $source = new Source('Array'); + $source->requires('Type'); + $array_code = '/* Array */'; + $source->set_code($array_code); + + $this->assertEquals($core_code.$array_code, $source->build()); + } } From 9fed39a59f173f2014597cf74d3f3d3650437e40 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 5 May 2011 15:53:56 -0500 Subject: [PATCH 37/49] Working Packager::build --- Packager.php | 4 ++-- test/packagerTest.php | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Packager.php b/Packager.php index a458d9c..84dcc84 100644 --- a/Packager.php +++ b/Packager.php @@ -58,7 +58,7 @@ public function build(Source $source) { $build = array(); - array_unshift($source->get_code()); + array_unshift($build, $source->get_code()); foreach ($this->get_required_for_source($source) as $required){ array_unshift($build, $required->get_code()); @@ -84,7 +84,7 @@ public function configure() public function get_source_by_name($name) { - return isset($this->sources[$name]) ? $this->sources[$name] : null; + return isset($this->keys[$name]) ? $this->sources[$this->keys[$name]] : null; } public function get_source_index($source) diff --git a/test/packagerTest.php b/test/packagerTest.php index d1d02c5..9051618 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -41,10 +41,21 @@ public function test_get_required_for_source() public function test_get_source_by_name() { - $packager = Packaget::get_instance(); + $packager = Packager::get_instance(); $source = $packager->get_source_by_name('Class'); - - $packager->build($source); + $this->assertEquals('Class', $source->get_name()); + } + + public function test_build() + { + $packager = Packager::get_instance(); + $source = $packager->get_source_by_name('Class'); + $build = array( + file_get_contents(__DIR__ . '/fixtures/Source/Core.js'), + file_get_contents(__DIR__ . '/fixtures/Source/Array.js'), + file_get_contents(__DIR__ . '/fixtures/Source/Class.js') + ); + $this->assertEquals(implode("\n", $build), $packager->build($source)); } } From 3ec1d5a383acbee6b668a1beea9a6104e913570c Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 5 May 2011 16:31:58 -0500 Subject: [PATCH 38/49] Working Source::build --- Packager.php | 11 ++++------- Source.php | 7 ++++--- test/packagerTest.php | 2 +- test/sourceTest.php | 6 +++--- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Packager.php b/Packager.php index 84dcc84..3fbd019 100644 --- a/Packager.php +++ b/Packager.php @@ -56,15 +56,11 @@ public function add_source(Source $source) public function build(Source $source) { - $build = array(); + $build = array($source->get_code()); - array_unshift($build, $source->get_code()); + foreach ($this->get_required_for_source($source) as $required) array_unshift($build, $required->get_code()); - foreach ($this->get_required_for_source($source) as $required){ - array_unshift($build, $required->get_code()); - } - - return implode("\n", $build); + return implode('', $build); } public function configure() @@ -106,6 +102,7 @@ public function get_required_for_source(Source $source, $required = null) $required = array(); } $index = $this->get_source_index($source); + if ($index < 0) $index = $this->add_source($source); foreach ($this->sources[$index]->get_requires() as $component){ if (!isset($this->keys[$component])) throw new Exception("Could not find '$component'."); diff --git a/Source.php b/Source.php index 1373a59..6a95575 100644 --- a/Source.php +++ b/Source.php @@ -30,7 +30,7 @@ static function normalize_name($default, $name){ public function build() { - return Packager::build($this); + return Packager::get_instance()->build($this); } public function get_code() @@ -41,6 +41,7 @@ public function get_code() public function get_name() { if (!$this->name) $this->name = basename($this->path, '.js'); + if (!$this->name) $this->name = $this->package_name; return $this->name; } @@ -105,7 +106,7 @@ public function parse_requires($requires) public function provides($provides) { $packager = Packager::get_instance(); - foreach ($provides as $component){ + foreach ((array) $provides as $component){ $packager->add_component($this, $component); $this->provides[] = $component; } @@ -114,7 +115,7 @@ public function provides($provides) public function requires($requires) { - $this->requires = $requires; + $this->requires = (array) $requires; return $this; } diff --git a/test/packagerTest.php b/test/packagerTest.php index 9051618..b670f07 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -55,7 +55,7 @@ public function test_build() file_get_contents(__DIR__ . '/fixtures/Source/Array.js'), file_get_contents(__DIR__ . '/fixtures/Source/Class.js') ); - $this->assertEquals(implode("\n", $build), $packager->build($source)); + $this->assertEquals(implode('', $build), $packager->build($source)); } } diff --git a/test/sourceTest.php b/test/sourceTest.php index b61eae5..80cb163 100644 --- a/test/sourceTest.php +++ b/test/sourceTest.php @@ -4,13 +4,13 @@ class SourceTest extends PHPUnit_Framework_TestCase { - public function test_constructor() + public function xtest_constructor() { $source = new Source('test'); $source = new Source('test', __DIR__ . '/fixtures/Source/Core.js'); } - public function test_parse() + public function xtest_parse() { $source_path = __DIR__ . '/fixtures/Source/Class.js'; $source = new Source('Core'); @@ -23,7 +23,7 @@ public function test_parse() $this->assertEquals(array('Core/Array'), $source->get_requires()); } - public function test_no_deps_build() + public function xtest_no_deps_build() { $source = new Source('test'); From c7f6fffd819ad70bd18b9aa516c3f5b2390f67d2 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 5 May 2011 18:59:44 -0500 Subject: [PATCH 39/49] All test pass. Added a todo for overwriting packages. --- Packager.php | 6 +----- test/sourceTest.php | 11 ++++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Packager.php b/Packager.php index 3fbd019..0888e3d 100644 --- a/Packager.php +++ b/Packager.php @@ -9,8 +9,6 @@ class Packager { protected $sources = array(); protected $generators = array(); protected $keys = array(); - - private static $graph = array(); public function __construct($package_paths = '') { @@ -101,10 +99,8 @@ public function get_required_for_source(Source $source, $required = null) $return = true; $required = array(); } - $index = $this->get_source_index($source); - if ($index < 0) $index = $this->add_source($source); - foreach ($this->sources[$index]->get_requires() as $component){ + foreach ($source->get_requires() as $component){ if (!isset($this->keys[$component])) throw new Exception("Could not find '$component'."); $required[] = $source = $this->sources[$this->keys[$component]]; if ($source->has_requires()) $this->get_required_for_source($source, &$required); diff --git a/test/sourceTest.php b/test/sourceTest.php index 80cb163..9e3fcf4 100644 --- a/test/sourceTest.php +++ b/test/sourceTest.php @@ -4,13 +4,13 @@ class SourceTest extends PHPUnit_Framework_TestCase { - public function xtest_constructor() + public function test_constructor() { $source = new Source('test'); $source = new Source('test', __DIR__ . '/fixtures/Source/Core.js'); } - public function xtest_parse() + public function test_parse() { $source_path = __DIR__ . '/fixtures/Source/Class.js'; $source = new Source('Core'); @@ -23,7 +23,7 @@ public function xtest_parse() $this->assertEquals(array('Core/Array'), $source->get_requires()); } - public function xtest_no_deps_build() + public function test_no_deps_build() { $source = new Source('test'); @@ -35,13 +35,14 @@ public function xtest_no_deps_build() public function test_deps_build() { - $source = new Source('Core'); + # todo(ibolmo): Cannot overwrite packages once they're defined. + $source = new Source('!Core'); $source->provides('Type'); $core_code = '/* Core */'; $source->set_code($core_code); $source = new Source('Array'); - $source->requires('Type'); + $source->requires('!Core/Type'); $array_code = '/* Array */'; $source->set_code($array_code); From f1402c3242a71859a88e135c32e9ebab70daf766 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 6 May 2011 09:50:44 -0500 Subject: [PATCH 40/49] Fixed redundant deps. --- Packager.php | 8 ++++++-- test/sourceTest.php | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Packager.php b/Packager.php index 0888e3d..f48dec2 100644 --- a/Packager.php +++ b/Packager.php @@ -102,8 +102,12 @@ public function get_required_for_source(Source $source, $required = null) foreach ($source->get_requires() as $component){ if (!isset($this->keys[$component])) throw new Exception("Could not find '$component'."); - $required[] = $source = $this->sources[$this->keys[$component]]; - if ($source->has_requires()) $this->get_required_for_source($source, &$required); + $require = $this->sources[$this->keys[$component]]; + if (!in_array($require, $required)) $required[] = $require; + } + foreach ($source->get_requires() as $component) { + $require = $this->sources[$this->keys[$component]]; + if ($require->has_requires()) $this->get_required_for_source($require, &$required); } if ($return) return $required; diff --git a/test/sourceTest.php b/test/sourceTest.php index 9e3fcf4..6a53506 100644 --- a/test/sourceTest.php +++ b/test/sourceTest.php @@ -48,4 +48,31 @@ public function test_deps_build() $this->assertEquals($core_code.$array_code, $source->build()); } + + public function test_redundant_deps() + { + $source = new Source('Base'); + $base_code = '/* Base */'; + $source->provides('Base'); + $source->set_code($base_code); + + $source = new Source('Child'); + $source->provides('Child'); + $source->requires('Base'); + $child_code = '/* Child */'; + $source->set_code($child_code); + + $source = new Source('Sibling'); + $source->provides('Sibling'); + $source->requires('Base'); + $sibling_code = '/* Sibling */'; + $source->set_code($sibling_code); + + $source = new Source('Container'); + $source->requires(array('Child', 'Sibling')); + $container_code = '/* Container */'; + $source->set_code($container_code); + + $this->assertEquals($base_code.$sibling_code.$child_code.$container_code, $source->build()); + } } From bc6b03a038fdb0a3ab7a1bfbb53bca43cc27e954 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 6 May 2011 10:20:41 -0500 Subject: [PATCH 41/49] Added Packager.strip_blocks. Decided that it's not the build function that should be doing the processing of the output. Perhaps build should return a 'Build' class that has a lot of utility functions like strip_blocks. --- Package.php | 11 +- Packager.php | 12 +- test/fixtures/Source/Array.js | 163 ++++++++++- test/fixtures/Source/Browser.js | 249 +++++++++++++++- test/fixtures/Source/Class.js | 102 ++++++- test/fixtures/Source/Core.js | 500 ++++++++++++++++++++++++++++++++ test/packagerTest.php | 21 +- 7 files changed, 1048 insertions(+), 10 deletions(-) diff --git a/Package.php b/Package.php index fa074ef..1be7a58 100644 --- a/Package.php +++ b/Package.php @@ -31,11 +31,12 @@ static function glob($path, $pattern = '*', $flags = 0, $depth = 0){ while ($folder = array_shift($folders)){ $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags)); - if ($depth != 0) { - $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); - $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; - $folders = array_merge($folders, $moreFolders); - } + + if (!$depth) continue; + + $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR); + $depth = ($depth < -1) ? -1: $depth + count($moreFolders) - 2; + $folders = array_merge($folders, $moreFolders); } return $matches; } diff --git a/Packager.php b/Packager.php index f48dec2..e53d743 100644 --- a/Packager.php +++ b/Packager.php @@ -22,6 +22,16 @@ static function get_instance() return self::$instance; } + static function strip_blocks($code, $blocks) + { + foreach ((array) $blocks as $block){ + $code = preg_replace_callback("%(/[/*])\s*<$block>(.*?)(?:\s*\*/)?%s", function($matches){ + return (strpos($matches[2], ($matches[1] == "//") ? "\n" : "*/") === false) ? $matches[2] : ""; + }, $code); + } + return $code; + } + public function add_component(Source $source, $component) { $index = $this->get_source_index($source); @@ -105,7 +115,7 @@ public function get_required_for_source(Source $source, $required = null) $require = $this->sources[$this->keys[$component]]; if (!in_array($require, $required)) $required[] = $require; } - foreach ($source->get_requires() as $component) { + foreach ($source->get_requires() as $component){ $require = $this->sources[$this->keys[$component]]; if ($require->has_requires()) $this->get_required_for_source($require, &$required); } diff --git a/test/fixtures/Source/Array.js b/test/fixtures/Source/Array.js index 4558507..feee361 100644 --- a/test/fixtures/Source/Array.js +++ b/test/fixtures/Source/Array.js @@ -12,4 +12,165 @@ requires: Type provides: Array ... -*/ \ No newline at end of file +*/ + +Array.implement({ + + invoke: function(methodName){ + var args = Array.slice(arguments, 1); + return this.map(function(item){ + return item[methodName].apply(item, args); + }); + }, + + every: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if ((i in this) && !fn.call(bind, this[i], i, this)) return false; + } + return true; + }, + + filter: function(fn, bind){ + var results = []; + for (var i = 0, l = this.length; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]); + } + return results; + }, + + clean: function(){ + return this.filter(function(item){ + return item != null; + }); + }, + + indexOf: function(item, from){ + var len = this.length; + for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ + if (this[i] === item) return i; + } + return -1; + }, + + map: function(fn, bind){ + var results = []; + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) results[i] = fn.call(bind, this[i], i, this); + } + return results; + }, + + some: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) return true; + } + return false; + }, + + associate: function(keys){ + var obj = {}, length = Math.min(this.length, keys.length); + for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; + return obj; + }, + + link: function(object){ + var result = {}; + for (var i = 0, l = this.length; i < l; i++){ + for (var key in object){ + if (object[key](this[i])){ + result[key] = this[i]; + delete object[key]; + break; + } + } + } + return result; + }, + + contains: function(item, from){ + return this.indexOf(item, from) != -1; + }, + + append: function(array){ + this.push.apply(this, array); + return this; + }, + + getLast: function(){ + return (this.length) ? this[this.length - 1] : null; + }, + + getRandom: function(){ + return (this.length) ? this[Number.random(0, this.length - 1)] : null; + }, + + include: function(item){ + if (!this.contains(item)) this.push(item); + return this; + }, + + combine: function(array){ + for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); + return this; + }, + + erase: function(item){ + for (var i = this.length; i--;){ + if (this[i] === item) this.splice(i, 1); + } + return this; + }, + + empty: function(){ + this.length = 0; + return this; + }, + + flatten: function(){ + var array = []; + for (var i = 0, l = this.length; i < l; i++){ + var type = typeOf(this[i]); + if (type == 'null') continue; + array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); + } + return array; + }, + + pick: function(){ + for (var i = 0, l = this.length; i < l; i++){ + if (this[i] != null) return this[i]; + } + return null; + }, + + hexToRgb: function(array){ + if (this.length != 3) return null; + var rgb = this.map(function(value){ + if (value.length == 1) value += value; + return value.toInt(16); + }); + return (array) ? rgb : 'rgb(' + rgb + ')'; + }, + + rgbToHex: function(array){ + if (this.length < 3) return null; + if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; + var hex = []; + for (var i = 0; i < 3; i++){ + var bit = (this[i] - 0).toString(16); + hex.push((bit.length == 1) ? '0' + bit : bit); + } + return (array) ? hex : '#' + hex.join(''); + } + +}); + +//<1.2compat> + +Array.alias('extend', 'append'); + +var $pick = function(){ + return Array.from(arguments).pick(); +}; + +// diff --git a/test/fixtures/Source/Browser.js b/test/fixtures/Source/Browser.js index ce4f5b2..93946be 100644 --- a/test/fixtures/Source/Browser.js +++ b/test/fixtures/Source/Browser.js @@ -12,4 +12,251 @@ requires: [Array] provides: [Browser, Window, Document] ... -*/ \ No newline at end of file +*/ + +(function(){ + +var document = this.document; +var window = document.window = this; + +var UID = 1; + +this.$uid = (window.ActiveXObject) ? function(item){ + return (item.uid || (item.uid = [UID++]))[0]; +} : function(item){ + return item.uid || (item.uid = UID++); +}; + +$uid(window); +$uid(document); + +var ua = navigator.userAgent.toLowerCase(), + platform = navigator.platform.toLowerCase(), + UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0], + mode = UA[1] == 'ie' && document.documentMode; + +var Browser = this.Browser = { + + extend: Function.prototype.extend, + + name: (UA[1] == 'version') ? UA[3] : UA[1], + + version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), + + Platform: { + name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0] + }, + + Features: { + xpath: !!(document.evaluate), + air: !!(window.runtime), + query: !!(document.querySelector), + json: !!(window.JSON) + }, + + Plugins: {} + +}; + +Browser[Browser.name] = true; +Browser[Browser.name + parseInt(Browser.version, 10)] = true; +Browser.Platform[Browser.Platform.name] = true; + +// Request + +Browser.Request = (function(){ + + var XMLHTTP = function(){ + return new XMLHttpRequest(); + }; + + var MSXML2 = function(){ + return new ActiveXObject('MSXML2.XMLHTTP'); + }; + + var MSXML = function(){ + return new ActiveXObject('Microsoft.XMLHTTP'); + }; + + return Function.attempt(function(){ + XMLHTTP(); + return XMLHTTP; + }, function(){ + MSXML2(); + return MSXML2; + }, function(){ + MSXML(); + return MSXML; + }); + +})(); + +Browser.Features.xhr = !!(Browser.Request); + +// Flash detection + +var version = (Function.attempt(function(){ + return navigator.plugins['Shockwave Flash'].description; +}, function(){ + return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); +}) || '0 r0').match(/\d+/g); + +Browser.Plugins.Flash = { + version: Number(version[0] || '0.' + version[1]) || 0, + build: Number(version[2]) || 0 +}; + +// String scripts + +Browser.exec = function(text){ + if (!text) return text; + if (window.execScript){ + window.execScript(text); + } else { + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.text = text; + document.head.appendChild(script); + document.head.removeChild(script); + } + return text; +}; + +String.implement('stripScripts', function(exec){ + var scripts = ''; + var text = this.replace(/]*>([\s\S]*?)<\/script>/gi, function(all, code){ + scripts += code + '\n'; + return ''; + }); + if (exec === true) Browser.exec(scripts); + else if (typeOf(exec) == 'function') exec(scripts, text); + return text; +}); + +// Window, Document + +Browser.extend({ + Document: this.Document, + Window: this.Window, + Element: this.Element, + Event: this.Event +}); + +this.Window = this.$constructor = new Type('Window', function(){}); + +this.$family = Function.from('window').hide(); + +Window.mirror(function(name, method){ + window[name] = method; +}); + +this.Document = document.$constructor = new Type('Document', function(){}); + +document.$family = Function.from('document').hide(); + +Document.mirror(function(name, method){ + document[name] = method; +}); + +document.html = document.documentElement; +document.head = document.getElementsByTagName('head')[0]; + +if (document.execCommand) try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e){} + +if (this.attachEvent && !this.addEventListener){ + var unloadEvent = function(){ + this.detachEvent('onunload', unloadEvent); + document.head = document.html = document.window = null; + }; + this.attachEvent('onunload', unloadEvent); +} + +// IE fails on collections and ) +var arrayFrom = Array.from; +try { + arrayFrom(document.html.childNodes); +} catch(e){ + Array.from = function(item){ + if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ + var i = item.length, array = new Array(i); + while (i--) array[i] = item[i]; + return array; + } + return arrayFrom(item); + }; + + var prototype = Array.prototype, + slice = prototype.slice; + ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ + var method = prototype[name]; + Array[name] = function(item){ + return method.apply(Array.from(item), slice.call(arguments, 1)); + }; + }); +} + +//<1.2compat> + +if (Browser.Platform.ios) Browser.Platform.ipod = true; + +Browser.Engine = {}; + +var setEngine = function(name, version){ + Browser.Engine.name = name; + Browser.Engine[name + version] = true; + Browser.Engine.version = version; +}; + +if (Browser.ie){ + Browser.Engine.trident = true; + + switch (Browser.version){ + case 6: setEngine('trident', 4); break; + case 7: setEngine('trident', 5); break; + case 8: setEngine('trident', 6); + } +} + +if (Browser.firefox){ + Browser.Engine.gecko = true; + + if (Browser.version >= 3) setEngine('gecko', 19); + else setEngine('gecko', 18); +} + +if (Browser.safari || Browser.chrome){ + Browser.Engine.webkit = true; + + switch (Browser.version){ + case 2: setEngine('webkit', 419); break; + case 3: setEngine('webkit', 420); break; + case 4: setEngine('webkit', 525); + } +} + +if (Browser.opera){ + Browser.Engine.presto = true; + + if (Browser.version >= 9.6) setEngine('presto', 960); + else if (Browser.version >= 9.5) setEngine('presto', 950); + else setEngine('presto', 925); +} + +if (Browser.name == 'unknown'){ + switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){ + case 'webkit': + case 'khtml': + Browser.Engine.webkit = true; + break; + case 'gecko': + Browser.Engine.gecko = true; + } +} + +this.$exec = Browser.exec; + +// + +}).call(this); diff --git a/test/fixtures/Source/Class.js b/test/fixtures/Source/Class.js index c783eb0..9d45155 100644 --- a/test/fixtures/Source/Class.js +++ b/test/fixtures/Source/Class.js @@ -12,4 +12,104 @@ requires: [Array] provides: Class ... -*/ \ No newline at end of file +*/ + +(function(){ + +var Class = this.Class = new Type('Class', function(params){ + if (instanceOf(params, Function)) params = {initialize: params}; + + var newClass = function(){ + reset(this); + if (newClass.$prototyping) return this; + this.$caller = null; + var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; + this.$caller = this.caller = null; + return value; + }.extend(this).implement(params); + + newClass.$constructor = Class; + newClass.prototype.$constructor = newClass; + newClass.prototype.parent = parent; + + return newClass; +}); + +var parent = function(){ + if (!this.$caller) throw new Error('The method "parent" cannot be called.'); + var name = this.$caller.$name, + parent = this.$caller.$owner.parent, + previous = (parent) ? parent.prototype[name] : null; + if (!previous) throw new Error('The method "' + name + '" has no parent.'); + return previous.apply(this, arguments); +}; + +var reset = function(object){ + for (var key in object){ + var value = object[key]; + switch (typeOf(value)){ + case 'object': + var F = function(){}; + F.prototype = value; + object[key] = reset(new F); + break; + case 'array': object[key] = value.clone(); break; + } + } + return object; +}; + +var wrap = function(self, key, method){ + if (method.$origin) method = method.$origin; + var wrapper = function(){ + if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); + var caller = this.caller, current = this.$caller; + this.caller = current; this.$caller = wrapper; + var result = method.apply(this, arguments); + this.$caller = current; this.caller = caller; + return result; + }.extend({$owner: self, $origin: method, $name: key}); + return wrapper; +}; + +var implement = function(key, value, retain){ + if (Class.Mutators.hasOwnProperty(key)){ + value = Class.Mutators[key].call(this, value); + if (value == null) return this; + } + + if (typeOf(value) == 'function'){ + if (value.$hidden) return this; + this.prototype[key] = (retain) ? value : wrap(this, key, value); + } else { + Object.merge(this.prototype, key, value); + } + + return this; +}; + +var getInstance = function(klass){ + klass.$prototyping = true; + var proto = new klass; + delete klass.$prototyping; + return proto; +}; + +Class.implement('implement', implement.overloadSetter()); + +Class.Mutators = { + + Extends: function(parent){ + this.parent = parent; + this.prototype = getInstance(parent); + }, + + Implements: function(items){ + Array.from(items).each(function(item){ + var instance = new item; + for (var key in instance) implement.call(this, key, instance[key], true); + }, this); + } +}; + +}).call(this); diff --git a/test/fixtures/Source/Core.js b/test/fixtures/Source/Core.js index f56b73f..69a11df 100644 --- a/test/fixtures/Source/Core.js +++ b/test/fixtures/Source/Core.js @@ -3,9 +3,509 @@ name: Core +description: The heart of MooTools. + license: MIT-style license. +copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/). + +authors: The MooTools production team (http://mootools.net/developers/) + +inspiration: + - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) + - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + provides: [Core, MooTools, Type, typeOf, instanceOf, Native] ... */ + +(function(){ + +this.MooTools = { + version: '1.3.2dev', + build: '%build%' +}; + +// typeOf, instanceOf + +var typeOf = this.typeOf = function(item){ + if (item == null) return 'null'; + if (item.$family) return item.$family(); + + if (item.nodeName){ + if (item.nodeType == 1) return 'element'; + if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; + } else if (typeof item.length == 'number'){ + if (item.callee) return 'arguments'; + if ('item' in item) return 'collection'; + } + + return typeof item; +}; + +var instanceOf = this.instanceOf = function(item, object){ + if (item == null) return false; + var constructor = item.$constructor || item.constructor; + while (constructor){ + if (constructor === object) return true; + constructor = constructor.parent; + } + return item instanceof object; +}; + +// Function overloading + +var Function = this.Function; + +var enumerables = true; +for (var i in {toString: 1}) enumerables = null; +if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; + +Function.prototype.overloadSetter = function(usePlural){ + var self = this; + return function(a, b){ + if (a == null) return this; + if (usePlural || typeof a != 'string'){ + for (var k in a) self.call(this, k, a[k]); + if (enumerables) for (var i = enumerables.length; i--;){ + k = enumerables[i]; + if (a.hasOwnProperty(k)) self.call(this, k, a[k]); + } + } else { + self.call(this, a, b); + } + return this; + }; +}; + +Function.prototype.overloadGetter = function(usePlural){ + var self = this; + return function(a){ + var args, result; + if (usePlural || typeof a != 'string') args = a; + else if (arguments.length > 1) args = arguments; + if (args){ + result = {}; + for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); + } else { + result = self.call(this, a); + } + return result; + }; +}; + +Function.prototype.extend = function(key, value){ + this[key] = value; +}.overloadSetter(); + +Function.prototype.implement = function(key, value){ + this.prototype[key] = value; +}.overloadSetter(); + +// From + +var slice = Array.prototype.slice; + +Function.from = function(item){ + return (typeOf(item) == 'function') ? item : function(){ + return item; + }; +}; + +Array.from = function(item){ + if (item == null) return []; + return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; +}; + +Number.from = function(item){ + var number = parseFloat(item); + return isFinite(number) ? number : null; +}; + +String.from = function(item){ + return item + ''; +}; + +// hide, protect + +Function.implement({ + + hide: function(){ + this.$hidden = true; + return this; + }, + + protect: function(){ + this.$protected = true; + return this; + } + +}); + +// Type + +var Type = this.Type = function(name, object){ + if (name){ + var lower = name.toLowerCase(); + var typeCheck = function(item){ + return (typeOf(item) == lower); + }; + + Type['is' + name] = typeCheck; + if (object != null){ + object.prototype.$family = (function(){ + return lower; + }).hide(); + //<1.2compat> + object.type = typeCheck; + // + } + } + + if (object == null) return null; + + object.extend(this); + object.$constructor = Type; + object.prototype.$constructor = object; + + return object; +}; + +var toString = Object.prototype.toString; + +Type.isEnumerable = function(item){ + return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); +}; + +var hooks = {}; + +var hooksOf = function(object){ + var type = typeOf(object.prototype); + return hooks[type] || (hooks[type] = []); +}; + +var implement = function(name, method){ + if (method && method.$hidden) return; + + var hooks = hooksOf(this); + + for (var i = 0; i < hooks.length; i++){ + var hook = hooks[i]; + if (typeOf(hook) == 'type') implement.call(hook, name, method); + else hook.call(this, name, method); + } + + var previous = this.prototype[name]; + if (previous == null || !previous.$protected) this.prototype[name] = method; + + if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ + return method.apply(item, slice.call(arguments, 1)); + }); +}; + +var extend = function(name, method){ + if (method && method.$hidden) return; + var previous = this[name]; + if (previous == null || !previous.$protected) this[name] = method; +}; + +Type.implement({ + + implement: implement.overloadSetter(), + + extend: extend.overloadSetter(), + + alias: function(name, existing){ + implement.call(this, name, this.prototype[existing]); + }.overloadSetter(), + + mirror: function(hook){ + hooksOf(this).push(hook); + return this; + } + +}); + +new Type('Type', Type); + +// Default Types + +var force = function(name, object, methods){ + var isType = (object != Object), + prototype = object.prototype; + + if (isType) object = new Type(name, object); + + for (var i = 0, l = methods.length; i < l; i++){ + var key = methods[i], + generic = object[key], + proto = prototype[key]; + + if (generic) generic.protect(); + + if (isType && proto){ + delete prototype[key]; + prototype[key] = proto.protect(); + } + } + + if (isType) object.implement(prototype); + + return force; +}; + +force('String', String, [ + 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', + 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase' +])('Array', Array, [ + 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', + 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' +])('Number', Number, [ + 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' +])('Function', Function, [ + 'apply', 'call', 'bind' +])('RegExp', RegExp, [ + 'exec', 'test' +])('Object', Object, [ + 'create', 'defineProperty', 'defineProperties', 'keys', + 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', + 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' +])('Date', Date, ['now']); + +Object.extend = extend.overloadSetter(); + +Date.extend('now', function(){ + return +(new Date); +}); + +new Type('Boolean', Boolean); + +// fixes NaN returning as Number + +Number.prototype.$family = function(){ + return isFinite(this) ? 'number' : 'null'; +}.hide(); + +// Number.random + +Number.extend('random', function(min, max){ + return Math.floor(Math.random() * (max - min + 1) + min); +}); + +// forEach, each + +var hasOwnProperty = Object.prototype.hasOwnProperty; +Object.extend('forEach', function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); + } +}); + +Object.each = Object.forEach; + +Array.implement({ + + forEach: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) fn.call(bind, this[i], i, this); + } + }, + + each: function(fn, bind){ + Array.forEach(this, fn, bind); + return this; + } + +}); + +// Array & Object cloning, Object merging and appending + +var cloneOf = function(item){ + switch (typeOf(item)){ + case 'array': return item.clone(); + case 'object': return Object.clone(item); + default: return item; + } +}; + +Array.implement('clone', function(){ + var i = this.length, clone = new Array(i); + while (i--) clone[i] = cloneOf(this[i]); + return clone; +}); + +var mergeOne = function(source, key, current){ + switch (typeOf(current)){ + case 'object': + if (typeOf(source[key]) == 'object') Object.merge(source[key], current); + else source[key] = Object.clone(current); + break; + case 'array': source[key] = current.clone(); break; + default: source[key] = current; + } + return source; +}; + +Object.extend({ + + merge: function(source, k, v){ + if (typeOf(k) == 'string') return mergeOne(source, k, v); + for (var i = 1, l = arguments.length; i < l; i++){ + var object = arguments[i]; + for (var key in object) mergeOne(source, key, object[key]); + } + return source; + }, + + clone: function(object){ + var clone = {}; + for (var key in object) clone[key] = cloneOf(object[key]); + return clone; + }, + + append: function(original){ + for (var i = 1, l = arguments.length; i < l; i++){ + var extended = arguments[i] || {}; + for (var key in extended) original[key] = extended[key]; + } + return original; + } + +}); + +// Object-less types + +['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ + new Type(name); +}); + +// Unique ID + +var UID = Date.now(); + +String.extend('uniqueID', function(){ + return (UID++).toString(36); +}); + +//<1.2compat> + +var Hash = this.Hash = new Type('Hash', function(object){ + if (typeOf(object) == 'hash') object = Object.clone(object.getClean()); + for (var key in object) this[key] = object[key]; + return this; +}); + +Hash.implement({ + + forEach: function(fn, bind){ + Object.forEach(this, fn, bind); + }, + + getClean: function(){ + var clean = {}; + for (var key in this){ + if (this.hasOwnProperty(key)) clean[key] = this[key]; + } + return clean; + }, + + getLength: function(){ + var length = 0; + for (var key in this){ + if (this.hasOwnProperty(key)) length++; + } + return length; + } + +}); + +Hash.alias('each', 'forEach'); + +Object.type = Type.isObject; + +var Native = this.Native = function(properties){ + return new Type(properties.name, properties.initialize); +}; + +Native.type = Type.type; + +Native.implement = function(objects, methods){ + for (var i = 0; i < objects.length; i++) objects[i].implement(methods); + return Native; +}; + +var arrayType = Array.type; +Array.type = function(item){ + return instanceOf(item, Array) || arrayType(item); +}; + +this.$A = function(item){ + return Array.from(item).slice(); +}; + +this.$arguments = function(i){ + return function(){ + return arguments[i]; + }; +}; + +this.$chk = function(obj){ + return !!(obj || obj === 0); +}; + +this.$clear = function(timer){ + clearTimeout(timer); + clearInterval(timer); + return null; +}; + +this.$defined = function(obj){ + return (obj != null); +}; + +this.$each = function(iterable, fn, bind){ + var type = typeOf(iterable); + ((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind); +}; + +this.$empty = function(){}; + +this.$extend = function(original, extended){ + return Object.append(original, extended); +}; + +this.$H = function(object){ + return new Hash(object); +}; + +this.$merge = function(){ + var args = Array.slice(arguments); + args.unshift({}); + return Object.merge.apply(null, args); +}; + +this.$lambda = Function.from; +this.$mixin = Object.merge; +this.$random = Number.random; +this.$splat = Array.from; +this.$time = Date.now; + +this.$type = function(object){ + var type = typeOf(object); + if (type == 'elements') return 'array'; + return (type == 'null') ? false : type; +}; + +this.$unlink = function(object){ + switch (typeOf(object)){ + case 'object': return Object.clone(object); + case 'array': return Array.clone(object); + case 'hash': return new Hash(object); + default: return object; + } +}; + +// + +}).call(this); diff --git a/test/packagerTest.php b/test/packagerTest.php index b670f07..11716db 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -55,7 +55,26 @@ public function test_build() file_get_contents(__DIR__ . '/fixtures/Source/Array.js'), file_get_contents(__DIR__ . '/fixtures/Source/Class.js') ); - $this->assertEquals(implode('', $build), $packager->build($source)); + + $actual = $packager->build($source); + $this->assertEquals(implode('', $build), $actual); + + return $actual; + } + + /** + * @depends test_build + */ + public function test_strip_blocks($code) + { + $blocks = array('1.2compat'); + + $code = Packager::strip_blocks($code, $blocks); + + foreach ($blocks as $block){ + $this->assertNotRegExp("/<$block>/", $code, "Should not find '$block' opening block."); + $this->assertNotRegExp("/<\/$block>/", $code, "Should not find '$block' closing block."); + } } } From 070e4db22887131a93d14784e9d0012f45e215ee Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sat, 7 May 2011 09:05:30 -0500 Subject: [PATCH 42/49] Warning that there is no yml, rather than requiring it. --- Source.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Source.php b/Source.php index 6a95575..3c99006 100644 --- a/Source.php +++ b/Source.php @@ -75,13 +75,16 @@ public function parse($source_path = '') if (!$this->code) throw new RuntimeException('Missing the code to parse. Did you forget to supply the source_path or set_code?'); preg_match(self::DESCRIPTOR_REGEX, $this->code, $matches); - if (empty($matches)) throw new Exception("No yaml header present in $source_path"); - - $header = YAML::decode($matches[0]); - - foreach($header as $key => $value){ - $method = 'parse_' . strtolower($key); - if (is_callable(array($this, $method))) $this->$method($value); + + if (!empty($matches){ + $header = YAML::decode($matches[0]); + + foreach ($header as $key => $value){ + $method = 'parse_' . strtolower($key); + if (is_callable(array($this, $method))) $this->$method($value); + } + } else { + $this->warn("No yaml header present in $source_path"); } } @@ -130,4 +133,9 @@ public function set_code($code) $this->code = $code; return $this; } + + public function warn($message) + { + # todo(ibolmo): log mixin + } } From 846479bfb619a1a56a35101638306ec5de4acd51 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sat, 7 May 2011 09:41:45 -0500 Subject: [PATCH 43/49] Fixing a cpass by reference deprecation, and err in previous commit (missing closing ')') --- Packager.php | 4 ++-- Source.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Packager.php b/Packager.php index e53d743..00a6670 100644 --- a/Packager.php +++ b/Packager.php @@ -102,7 +102,7 @@ public function get_sources() return $this->sources; } - public function get_required_for_source(Source $source, $required = null) + public function get_required_for_source(Source $source, &$required = null) { $return = false; if (!$required){ @@ -117,7 +117,7 @@ public function get_required_for_source(Source $source, $required = null) } foreach ($source->get_requires() as $component){ $require = $this->sources[$this->keys[$component]]; - if ($require->has_requires()) $this->get_required_for_source($require, &$required); + if ($require->has_requires()) $this->get_required_for_source($require, $required); } if ($return) return $required; diff --git a/Source.php b/Source.php index 3c99006..fba0500 100644 --- a/Source.php +++ b/Source.php @@ -76,7 +76,7 @@ public function parse($source_path = '') preg_match(self::DESCRIPTOR_REGEX, $this->code, $matches); - if (!empty($matches){ + if (!empty($matches)){ $header = YAML::decode($matches[0]); foreach ($header as $key => $value){ From ea7b953c085ce678d0d2d473f122b16c4b739c80 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sat, 7 May 2011 16:35:42 -0500 Subject: [PATCH 44/49] A couple of key changes. get_required_for_source now returns in required order (Core, for example, would be first). This is now the case, since I needed to recursively look for the most required component. I've also added the ability to pass Source instances to required method in Source. --- Packager.php | 30 +++++++++++++++++------------- Source.php | 2 ++ test/packagerTest.php | 4 ++-- test/sourceTest.php | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Packager.php b/Packager.php index 00a6670..8877825 100644 --- a/Packager.php +++ b/Packager.php @@ -1,5 +1,7 @@ get_code()); - - foreach ($this->get_required_for_source($source) as $required) array_unshift($build, $required->get_code()); - + { + $build = array_map(function($source){ + return $source->get_code(); + }, $this->get_required_for_source($source)); + $build[] = $source->get_code(); return implode('', $build); } @@ -103,22 +105,24 @@ public function get_sources() } public function get_required_for_source(Source $source, &$required = null) - { + { $return = false; if (!$required){ $return = true; $required = array(); } - foreach ($source->get_requires() as $component){ - if (!isset($this->keys[$component])) throw new Exception("Could not find '$component'."); - $require = $this->sources[$this->keys[$component]]; - if (!in_array($require, $required)) $required[] = $require; - } - foreach ($source->get_requires() as $component){ - $require = $this->sources[$this->keys[$component]]; + foreach ($source->get_requires() as $require){ + if (!($require instanceof Source)) $require = $this->sources[$this->keys[$require]]; if ($require->has_requires()) $this->get_required_for_source($require, $required); } + foreach ($source->get_requires() as $require){ + if (!($require instanceof Source)){ + if (!isset($this->keys[$require])) throw new Exception("Could not find '$require'."); + $require = $this->sources[$this->keys[$require]]; + } + if (!in_array($require, $required)) $required[] = $require; + } if ($return) return $required; } diff --git a/Source.php b/Source.php index fba0500..0a9ce82 100644 --- a/Source.php +++ b/Source.php @@ -7,6 +7,8 @@ class Source const DESCRIPTOR_REGEX = '/\/\*\s*^---(.*?)^(?:\.\.\.|---)\s*\*\//ms'; protected $code = ''; + protected $name = ''; + protected $path = ''; protected $provides = array(); protected $requires = array(); diff --git a/test/packagerTest.php b/test/packagerTest.php index 11716db..0252f8d 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -35,8 +35,8 @@ public function test_get_required_for_source() $required = $packager->get_required_for_source($class); $this->assertEquals(2, count($required)); - $this->assertEquals('Array', $required[0]->get_name()); - $this->assertEquals('Core', $required[1]->get_name()); + $this->assertEquals('Core', $required[0]->get_name()); + $this->assertEquals('Array', $required[1]->get_name()); } public function test_get_source_by_name() diff --git a/test/sourceTest.php b/test/sourceTest.php index 6a53506..57ec73e 100644 --- a/test/sourceTest.php +++ b/test/sourceTest.php @@ -73,6 +73,6 @@ public function test_redundant_deps() $container_code = '/* Container */'; $source->set_code($container_code); - $this->assertEquals($base_code.$sibling_code.$child_code.$container_code, $source->build()); + $this->assertEquals($base_code.$child_code.$sibling_code.$container_code, $source->build()); } } From cff1fce92fe7076bc3b3c6e876ac7f767f9af44e Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sun, 8 May 2011 09:28:54 -0700 Subject: [PATCH 45/49] Edited README.md via GitHub --- README.md | 206 +++++++----------------------------------------------- 1 file changed, 26 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index 2878be1..4f96e7c 100644 --- a/README.md +++ b/README.md @@ -1,199 +1,45 @@ Packager ======== -Packager is a PHP 5.2+ library to concatenate libraries split in multiple files in a single file. It automatically calculates dependancies. Packager requires a yml header syntax in every file, and a `package.yml` manifest file, as seen on the MooTools project. +Packager is a PHP 5.3+ library to concatenate libraries split in multiple files in a single file. It automatically calculates dependancies. -Packager API -============ +Packager requires a yml header syntax in every file, and a `package.yml` manifest file, as seen on the MooTools project. -Constructor ------------ +2.0 Branch +---------- +This is an experimental branch, dedicated to a more programmatic approach to packaging (building) your JavaScript files. -The constructor of this class accepts either a path to a package or a list of path to packages. `package.yml` must not be included in the path. +With the previous Packager, you were **required** to define a `package.yml`. This is no longer the case. You're still able to work with your `package.json` or `package.yml` files, but you have the ability to define dependencies at runtime and build only the dependencies for that file. -### Example - - $pkg = new Packager("/Users/kamicane/Sites/mootools-core/"); - $pkg = new Packager(array("/Users/kamicane/Sites/mootools-core/", "/Users/kamicane/Sites/mootools-more/")); +Why? +---- +I needed a more dynamic packager. On my web development, each web page varies between JavaScript uses. My home page, for example, might have a login area but the about us page does not. Why should I build a single `mootools.js` for the whole site? Even if I could keep track of what pages require what, it's not my job or the application's job to keep that in order. -Adding a manifest ------------------ +Instead, I wanted to: ``. I wanted homepage.js to have a yml header, and for Packager to build a _specific build_ for this **specific page**. The next step would be to create agent specific builds, but that's for another branch. -* `parse_manifest` » adds a manifest to this instance +API 2.0 +======= +Remember, the emphasis has been to create an actual API. The following are classes and their purpose. See the linked wiki pages, for additional method signatures and documentation. +[Packager](#) +Packager is the "registry" of components, and the manager of building the dependencies. -Working with files ------------------- +[Package](#) +A Package is a container of many sources. Due to the emphasis on Source, Package is not as useful **yet**. -### Getters +[Source](#) +A Source has many components (provides) and dependencies (requires). By defining a Source, you can add (provide) to the registry and build all dependencies for the source. - * `get_all_files` » gets an list of all files - * `get_file_dependancies` » gets an ordered list of every file that this file depends on - * `get_file_path` » gets the file path - * `get_file_source` » gets the file source - * `get_file_description` » gets the file description - * `get_file_provides` » gets a list of the file provided components +[Command Line Script](#) +This is currently broken, and low priority for me. Pull requests, greatly appreciated. -### Converters +Since I'm using Packager 2.0 as an API I no longer need a `npm|gem|pear`-like library for my development. - * `complete_file` » converts a single file to an ordered list of files - * `complete_files` » converts a list of files to an ordered list of files -### Generators +Getting Stated +============== +banana banana banana - * `build_from_files` » returns a string containing the source of the selected files and their dependancies - * `write_from_files` » writes a file with the selected files and their dependancies +For now, take a look at [sfPackagerPlugin](https://github.com/ibolmo/sfPackagerPlugin) for a programmatic usage of the 2.0 branch. In particular take a look at: [PackagerHelper](https://github.com/ibolmo/sfPackagerPlugin/blob/master/lib/helper/PackagerHelper.php) which has the "useful" interface, I had been talking about. -Working with components ------------------------ - -### Converting to files - - * `component_to_file` » gets the name of the file that provides this component - * `components_to_files` » converts a list of components to a list of files - -### Generators - - * `build_from_components` » returns a string containing the source of the selected components and their dependancies - * `write_from_components` » writes a file with the selected components and their dependancies - - -Class usage ------------ - -### Syntax - - $pkg = new Packager(`$path_to_manifest`); - -### Example - - $pkg = new Packager("/Users/kamicane/Sites/mootools-core/"); - - $pkg->write_from_components("/Users/kamicane/Sites/mootools.js", array('Type', 'Array')); - -Packager Command Line script ----------------------------- - -The Packager command line script is your one-stop solution to build any of your packages at once. Works on unices. - -### Syntax - - ./packager COMMAND +option1 argument1 argument2 +option2 argument1 argument2 - -* `COMMAND` a packager command *(required)* -* `+option` options for commands *(optional)* - -### Commands - -* `register` registers a package. Creates a .packages.yml file in your home folder. -* `unregister` unregisters a package -* `list` list registered packages -* `build` builds a single file with the supplied packages / files / components - -### Registering a Package - -#### Example - - ./packager register /Users/kamicane/mootools-core - » the package Core has been registered - - -### Listing Packages - -#### Example - - ./packager list - » Core: /Users/kamicane/mootools-core - - -### Unregistering a Package - -#### Example - - ./packager unregister Core - » the package Core has been unregistered - -### Building Packages - -#### Examples - - ./packager build Core/Type Core/Fx ART/ART.Element - -Which is the same as... - - ./packager build +components Core/Type Core/Fx ART/ART.Element - -Which builds the passed in components (and their dependancies) using your registered packages. - - ./packager build +files Core/Core Core/Fx ART/ART - -This builds the passed in files (and their dependancies) using your registered packages. - - ./packager build ART/* - -Builds every component from ART, and their dependancies, using your registered packages. - - ./packager build SomePackage/SomeComponent +packages /Users/kamicane/Sites/some-package - -Builds the selected components using your registered packages and a temporary package that resides in /Users/kamicane/Sites/some-package, without having to register it first. - - ./packager build SomePackage/SomeComponent -packages Core - -Builds the selected components using your registered packages minus the package names you pass to -packages. This lets you build your components without dependancies. - - ./packager build ART/SomeComponent +use-only ART - -Builds the selected components using only ART of your registered packages. This lets you build your components without dependancies. - - ./packager build SomePackage/SomeComponent +use-only +packages /Users/kamicane/Sites/some-package - -Builds the selected components using none of your registered packages plus the passed in package, without registering it. This lets you build your components without dependancies. - - ./packager build +components ART/ART +files ART/ART.Base - -You can mix components and files - - ./packager build Core/* > mootools.js - -This is how you output to a file - - ---------- - -# Notes - -Packager has many Package(s) -Package has many Source(s) -Source has many requires -Source has many provides - - -Dependency Graph - - A A Ø <-A-> B, C - / \ A <-B-> D, E - B C A <-C-> Ø - B / \ B <-D-> Ø - D E B <-E-> Ø - Ø Ø <-F-> Ø - / - C F - -A referenced by A, A.js, Package/A, A#a, A#b, A#..., A#z (where A#a-z is a component. E.g. Type and typeOf references Source A) - -A global dependency graph will be constructed. When a build requires an entity (a reference to a source) then graph is checked for source. If not found, then throw error. If found, then traverse tree up to roots (node with no requires). - -Traversal example: - - A Z A - \ / \ - B C - B / \ - D E - Ø - / - C F - -`require(D)` resolves: D, B, Z, A. Z and A have no priority. If they did, then Z or A would require the other. -`require(F)` resolves: F, and throw an Error or warning (depending on configuration) if a required module is missing. From 831a41fd96088e62a69f2c3715ea1a19871c25a1 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Sun, 8 May 2011 09:32:32 -0700 Subject: [PATCH 46/49] Edited README.md via GitHub --- README.md | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/README.md b/README.md index 2878be1..145b816 100644 --- a/README.md +++ b/README.md @@ -157,43 +157,3 @@ You can mix components and files ./packager build Core/* > mootools.js This is how you output to a file - - ---------- - -# Notes - -Packager has many Package(s) -Package has many Source(s) -Source has many requires -Source has many provides - - -Dependency Graph - - A A Ø <-A-> B, C - / \ A <-B-> D, E - B C A <-C-> Ø - B / \ B <-D-> Ø - D E B <-E-> Ø - Ø Ø <-F-> Ø - / - C F - -A referenced by A, A.js, Package/A, A#a, A#b, A#..., A#z (where A#a-z is a component. E.g. Type and typeOf references Source A) - -A global dependency graph will be constructed. When a build requires an entity (a reference to a source) then graph is checked for source. If not found, then throw error. If found, then traverse tree up to roots (node with no requires). - -Traversal example: - - A Z A - \ / \ - B C - B / \ - D E - Ø - / - C F - -`require(D)` resolves: D, B, Z, A. Z and A have no priority. If they did, then Z or A would require the other. -`require(F)` resolves: F, and throw an Error or warning (depending on configuration) if a required module is missing. From afe04863b9acb06a73e6fc8a74d5fab62cb4ae40 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Wed, 18 May 2011 08:08:30 -0500 Subject: [PATCH 47/49] The easy part. register, unregister, and list now uses 2.0 api. --- Package.php | 5 +++++ packager | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Package.php b/Package.php index 1be7a58..75cbbf8 100644 --- a/Package.php +++ b/Package.php @@ -52,6 +52,11 @@ public function get_name() return $this->name; } + public function get_path() + { + return $this->path; + } + public function get_sources() { return $this->sources; diff --git a/packager b/packager index cf41411..8e22028 100755 --- a/packager +++ b/packager @@ -3,6 +3,18 @@ require __DIR__ . '/packager.php'; +function info($message){ + $std_out = fopen('php://stdout', 'w'); + fwrite($std_out, $message); + fclose($std_out); +} + +function warn($message){ + $std_err = fopen('php://stderr', 'w'); + fwrite($std_err, $message); + fclose($std_err); +} + $executable = array_shift($argv); $command = array_shift($argv); $a0 = !empty($argv[0]) ? $argv[0] : null; @@ -26,19 +38,19 @@ switch ($command){ $realpath = realpath($folder); if (!$realpath){ - Packager::warn("file or directory $folder not found\n"); + warn("file or directory $folder not found\n"); exit(1); } - $pkg = new Packager($realpath); - $name = $pkg->get_package_name(); - $path = $pkg->get_package_manifest(); + $pkg = new Package($realpath); + $name = $pkg->get_name(); + $path = $pkg->get_path(); $packages[$name] = $path; file_put_contents("$home/.packages.yml", YAML::encode($packages)); - Packager::info("the package $name has been registered as $path\n"); + info("the package $name has been registered as $path\n"); break; @@ -47,7 +59,7 @@ switch ($command){ $name = array_shift($argv); if (empty($packages[$name])){ - Packager::warn("there is no package called $name\n"); + warn("there is no package called $name\n"); break; } @@ -55,7 +67,7 @@ switch ($command){ file_put_contents("$home/.packages.yml", YAML::encode($packages)); - Packager::info("the package $name has been unregistered\n"); + info("the package $name has been unregistered\n"); break; @@ -64,18 +76,18 @@ switch ($command){ $package_name = array_shift($argv); if (empty($package_name)){ - foreach ($packages as $name => $path) Packager::info("$name: $path\n"); + foreach ($packages as $name => $path) info("$name: $path\n"); } else { if (!empty($packages[$package_name])){ $package_path = $packages[$package_name]; - $pkg = new Packager($package_path); - $files = $pkg->get_all_files(); - foreach ($files as $file){ - $file_name = $pkg->get_file_name($file); - Packager::info("- $file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); + $pkg = new Package($package_path); + $sources = $pkg->get_sources(); + foreach ($sources as $source) { + $name = $source->get_name(); + info("- $name: [" . implode(", ", $source->get_provides()) . "]\n"); } } else { - Packager::warn("The package $package_name has not been found.\n"); + warn("The package $package_name has not been found.\n"); } } From 816560976f7c2f1e6ad4cc777d78b5e6f1a04255 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Thu, 19 May 2011 08:12:14 -0500 Subject: [PATCH 48/49] Added support to remove packages, sources, and components. Did a bit of refactoring for more DRY. This also includes a shift from throwing an Exception if the source is not found in the build process. This would allow for -packages or +use-only in cli (that's next). --- Packager.php | 51 +++++++++++++++++++++++++++++++++++-------- test/packagerTest.php | 33 ++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/Packager.php b/Packager.php index 8877825..bc40693 100644 --- a/Packager.php +++ b/Packager.php @@ -55,7 +55,7 @@ public function add_generator($name, $callback) public function add_package($package) { if (!is_a($package, 'Package')) $package = new Package($package); - $this->packages[] = $package; + $this->packages[$package->get_name()] = $package; } public function add_source(Source $source) @@ -88,14 +88,23 @@ public function configure() }); } + public function get_packages() + { + return $this->packages; + } + public function get_source_by_name($name) { - return isset($this->keys[$name]) ? $this->sources[$this->keys[$name]] : null; + $index = $this->get_source_index($name); + if ($index > -1) return $this->sources[$index]; + + $this->warn("Could not find source '$name'."); + return null; } - public function get_source_index($source) + public function get_source_index($key) { - $key = $source->get_name(); + if ($key instanceof Source) $key = $key->get_name(); return isset($this->keys[$key]) ? $this->keys[$key] : -1; } @@ -113,20 +122,44 @@ public function get_required_for_source(Source $source, &$required = null) } foreach ($source->get_requires() as $require){ - if (!($require instanceof Source)) $require = $this->sources[$this->keys[$require]]; + if (!($require instanceof Source)) $require = $this->get_source_by_name($require); + if (!$require) continue; if ($require->has_requires()) $this->get_required_for_source($require, $required); } foreach ($source->get_requires() as $require){ - if (!($require instanceof Source)){ - if (!isset($this->keys[$require])) throw new Exception("Could not find '$require'."); - $require = $this->sources[$this->keys[$require]]; - } + if (!($require instanceof Source)) $require = $this->get_source_by_name($require); + if (!$require) continue; if (!in_array($require, $required)) $required[] = $require; } if ($return) return $required; } + public function remove_component(Source $source, $component) + { + foreach ($this->generators as $name => $callback){ + $key = call_user_func($callback, $source, $component); + unset($this->keys[$key]); + } + } + + public function remove_package($package_name) + { + if ($package_name instanceof Package) $package_name = $package_name->get_name(); + if (!isset($this->packages[$package_name])) return false; + foreach($this->packages[$package_name]->get_sources() as $source) $this->remove_source($source); + unset($this->packages[$package_name]); + return true; + } + + public function remove_source(Source $source) + { + $name = $source->get_name(); + $index = $this->keys[$name]; + foreach ($source->get_provides() as $component) $this->remove_component($source, $component); + unset($this->keys[$name], $this->sources[$index]); + } + protected function set_key($key, $index, $generator_name) { if (isset($this->keys[$key])) $this->warn("Generator '$generator_name' set component key '$key'."); diff --git a/test/packagerTest.php b/test/packagerTest.php index 0252f8d..069ebe5 100644 --- a/test/packagerTest.php +++ b/test/packagerTest.php @@ -76,5 +76,38 @@ public function test_strip_blocks($code) $this->assertNotRegExp("/<\/$block>/", $code, "Should not find '$block' closing block."); } } + + public function test_remove_package() + { + $packager = Packager::get_instance(); + + $package = new Package(); + $package->set_name('Test Package'); + + $packager->add_package($package); + + $packages = $packager->get_packages(); + $this->assertEquals(2, count($packages)); + $this->assertEquals(end($packages), $package); + + $this->assertTrue($packager->remove_package($package)); + + $packages = $packager->get_packages(); + $this->assertEquals(1, count($packages)); + + $this->assertFalse($packager->remove_package('Random')); + } + + public function test_remove_package_and_components() + { + $packager = Packager::get_instance(); + + $this->assertTrue($packager->remove_package('Core')); + + $sources = $packager->get_sources(); + $this->assertEquals(0, count($sources)); + + $this->assertFalse(!!$packager->get_source_by_name('Core')); + } } From 5f410c607afd79368f479b9605010bdd29d20601 Mon Sep 17 00:00:00 2001 From: Olmo Maldonado Date: Fri, 20 May 2011 10:11:24 -0500 Subject: [PATCH 49/49] Working CLI but broken for wildcards. --- Source.php | 2 +- packager | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Source.php b/Source.php index 0a9ce82..80eddbc 100644 --- a/Source.php +++ b/Source.php @@ -1,6 +1,6 @@ add_package($path); - foreach ($selected['remove-packages'] as $package_name) $pkg->remove_package($package_name); - foreach ($selected['add-packages'] as $package_path) $pkg->add_package($package_path); + foreach ($selected['remove-packages'] as $package_name) $packager->remove_package($package_name); + foreach ($selected['add-packages'] as $package_path) $packager->add_package($package_path); $re = "/^([^\/]+)\/\*$/"; $wildcards = array(); @@ -176,20 +178,20 @@ switch ($command){ } } - $pkg->validate($files, $components, $wildcards); + $source = new Source('packager-cli'); + $source->requires(array_merge($files, $wildcards)); + warn("Build using: " . implode(', ', $packager->get_packages()) . "\n"); + warn("Included Files/Components:\n"); - $files = $pkg->resolve_files($files, $components, $wildcards); - - Packager::warn("Build using: " . implode(', ', $pkg->get_packages()) . "\n"); - Packager::warn("Included Files/Components:\n"); - - foreach ($files as $file){ - $file_name = $pkg->get_file_name($file); - $file_package = $pkg->get_file_package($file); - Packager::warn("- $file_package/$file_name: [" . implode(", ", $pkg->get_file_provides($file)) . "]\n"); + $required = $packager->get_required_for_source($source); + foreach ($required as $required_source){ + $file_name = $required_source->get_name(); + $file_package = $required_source->get_package_name(); + + warn("- $file_package/$file_name: [" . implode(", ", $required_source->get_provides()) . "]\n"); } - echo $pkg->build($files, array(), array(), $blocks); + echo Packager::strip_blocks($source->build(), $blocks); break;