puppet 3.5.1-x86-mingw32 → 3.6.0.rc1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CONTRIBUTING.md +5 -0
- data/Gemfile +17 -9
- data/README.md +1 -0
- data/conf/fileserver.conf +4 -3
- data/ext/README.environment +8 -0
- data/ext/build_defaults.yaml +1 -1
- data/ext/debian/control +2 -2
- data/ext/debian/puppet-common.dirs +4 -0
- data/ext/debian/rules +4 -0
- data/ext/emacs/puppet-mode-init.el +1 -1
- data/ext/emacs/puppet-mode.el +36 -17
- data/ext/redhat/client.init +3 -3
- data/ext/redhat/puppet.spec.erb +9 -0
- data/ext/systemd/puppet.service +3 -4
- data/ext/systemd/puppetmaster.service +1 -3
- data/install.rb +1 -1
- data/lib/puppet.rb +2 -1
- data/lib/puppet/agent.rb +1 -1
- data/lib/puppet/application.rb +17 -17
- data/lib/puppet/application/doc.rb +1 -1
- data/lib/puppet/configurer.rb +4 -1
- data/lib/puppet/configurer/downloader.rb +13 -12
- data/lib/puppet/configurer/plugin_handler.rb +3 -3
- data/lib/puppet/context.rb +6 -1
- data/lib/puppet/defaults.rb +82 -12
- data/lib/puppet/environments.rb +169 -13
- data/lib/puppet/external/nagios/grammar.ry +2 -0
- data/lib/puppet/external/nagios/parser.rb +28 -19
- data/lib/puppet/face/config.rb +19 -6
- data/lib/puppet/face/module/generate.rb +209 -7
- data/lib/puppet/face/module/install.rb +17 -16
- data/lib/puppet/face/module/list.rb +83 -82
- data/lib/puppet/face/module/search.rb +1 -1
- data/lib/puppet/face/module/upgrade.rb +10 -9
- data/lib/puppet/face/parser.rb +3 -2
- data/lib/puppet/face/plugin.rb +8 -4
- data/lib/puppet/file_bucket/dipper.rb +6 -3
- data/lib/puppet/file_bucket/file.rb +4 -2
- data/lib/puppet/file_serving/metadata.rb +1 -1
- data/lib/puppet/file_system/memory_file.rb +27 -1
- data/lib/puppet/file_system/memory_impl.rb +15 -1
- data/lib/puppet/forge.rb +148 -52
- data/lib/puppet/forge/cache.rb +5 -1
- data/lib/puppet/forge/errors.rb +10 -0
- data/lib/puppet/forge/repository.rb +61 -26
- data/lib/puppet/functions.rb +548 -0
- data/lib/puppet/functions/assert_type.rb +42 -0
- data/lib/puppet/functions/import.rb +7 -0
- data/lib/puppet/indirector/facts/facter.rb +1 -1
- data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
- data/lib/puppet/indirector/rest.rb +18 -0
- data/lib/puppet/loaders.rb +20 -0
- data/lib/puppet/module.rb +2 -2
- data/lib/puppet/module_tool.rb +40 -14
- data/lib/puppet/module_tool/applications.rb +0 -1
- data/lib/puppet/module_tool/applications/application.rb +35 -26
- data/lib/puppet/module_tool/applications/builder.rb +16 -6
- data/lib/puppet/module_tool/applications/checksummer.rb +25 -19
- data/lib/puppet/module_tool/applications/installer.rb +196 -35
- data/lib/puppet/module_tool/applications/searcher.rb +1 -0
- data/lib/puppet/module_tool/applications/uninstaller.rb +7 -1
- data/lib/puppet/module_tool/applications/unpacker.rb +57 -31
- data/lib/puppet/module_tool/applications/upgrader.rb +221 -65
- data/lib/puppet/module_tool/checksums.rb +5 -8
- data/lib/puppet/module_tool/errors/installer.rb +12 -44
- data/lib/puppet/module_tool/errors/shared.rb +84 -11
- data/lib/puppet/module_tool/errors/upgrader.rb +16 -45
- data/lib/puppet/module_tool/install_directory.rb +7 -6
- data/lib/puppet/module_tool/installed_modules.rb +92 -0
- data/lib/puppet/module_tool/local_tarball.rb +91 -0
- data/lib/puppet/module_tool/metadata.rb +119 -115
- data/lib/puppet/module_tool/modulefile.rb +9 -9
- data/lib/puppet/module_tool/shared_behaviors.rb +19 -7
- data/lib/puppet/module_tool/skeleton/templates/generator/README.md.erb +79 -0
- data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +18 -0
- data/lib/puppet/module_tool/skeleton/templates/generator/metadata.json.erb +1 -0
- data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +7 -0
- data/lib/puppet/module_tool/tar.rb +3 -7
- data/lib/puppet/module_tool/tar/gnu.rb +21 -9
- data/lib/puppet/module_tool/tar/mini.rb +2 -8
- data/lib/puppet/network/http/api/v1.rb +1 -1
- data/lib/puppet/network/http/api/v2/authorization.rb +4 -2
- data/lib/puppet/network/http/issues.rb +1 -0
- data/lib/puppet/network/http_pool.rb +15 -6
- data/lib/puppet/node/environment.rb +91 -20
- data/lib/puppet/parser/ast/pops_bridge.rb +44 -3
- data/lib/puppet/parser/collector.rb +1 -1
- data/lib/puppet/parser/compiler.rb +50 -7
- data/lib/puppet/parser/functions.rb +6 -0
- data/lib/puppet/parser/functions/generate.rb +1 -1
- data/lib/puppet/parser/resource.rb +1 -1
- data/lib/puppet/pops.rb +22 -1
- data/lib/puppet/pops/adapters.rb +8 -1
- data/lib/puppet/pops/binder/bindings_composer.rb +1 -1
- data/lib/puppet/pops/binder/bindings_factory.rb +1 -1
- data/lib/puppet/pops/binder/config/binder_config_checker.rb +1 -1
- data/lib/puppet/pops/binder/producers.rb +2 -2
- data/lib/puppet/pops/evaluator/access_operator.rb +65 -25
- data/lib/puppet/pops/evaluator/callable_signature.rb +101 -0
- data/lib/puppet/pops/evaluator/closure.rb +57 -2
- data/lib/puppet/pops/evaluator/compare_operator.rb +1 -1
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +9 -11
- data/lib/puppet/pops/evaluator/runtime3_support.rb +72 -21
- data/lib/puppet/pops/functions/dispatch.rb +71 -0
- data/lib/puppet/pops/functions/dispatcher.rb +237 -0
- data/lib/puppet/pops/functions/function.rb +77 -0
- data/lib/puppet/pops/issues.rb +12 -0
- data/lib/puppet/pops/loader/base_loader.rb +102 -0
- data/lib/puppet/pops/loader/dependency_loader.rb +60 -0
- data/lib/puppet/pops/loader/gem_support.rb +49 -0
- data/lib/puppet/pops/loader/loader.rb +180 -0
- data/lib/puppet/pops/loader/loader_paths.rb +137 -0
- data/lib/puppet/pops/loader/module_loaders.rb +242 -0
- data/lib/puppet/pops/loader/null_loader.rb +44 -0
- data/lib/puppet/pops/loader/ruby_function_instantiator.rb +34 -0
- data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +109 -0
- data/lib/puppet/pops/loader/simple_environment_loader.rb +20 -0
- data/lib/puppet/pops/loader/static_loader.rb +69 -0
- data/lib/puppet/pops/loader/uri_helper.rb +22 -0
- data/lib/puppet/pops/loaders.rb +240 -0
- data/lib/puppet/pops/model/factory.rb +13 -5
- data/lib/puppet/pops/model/model_tree_dumper.rb +12 -4
- data/lib/puppet/pops/parser/egrammar.ra +31 -18
- data/lib/puppet/pops/parser/eparser.rb +1137 -1106
- data/lib/puppet/pops/parser/lexer2.rb +17 -16
- data/lib/puppet/pops/semantic_error.rb +17 -0
- data/lib/puppet/pops/types/type_calculator.rb +150 -15
- data/lib/puppet/pops/types/type_factory.rb +69 -0
- data/lib/puppet/pops/types/type_parser.rb +9 -0
- data/lib/puppet/pops/types/types.rb +65 -4
- data/lib/puppet/pops/validation/checker4_0.rb +1 -1
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -1
- data/lib/puppet/property/list.rb +1 -1
- data/lib/puppet/provider/augeas/augeas.rb +2 -2
- data/lib/puppet/provider/cron/crontab.rb +13 -2
- data/lib/puppet/provider/package.rb +24 -0
- data/lib/puppet/provider/package/apt.rb +6 -1
- data/lib/puppet/provider/package/gem.rb +8 -2
- data/lib/puppet/provider/package/msi.rb +0 -15
- data/lib/puppet/provider/package/openbsd.rb +0 -24
- data/lib/puppet/provider/package/rpm.rb +3 -29
- data/lib/puppet/provider/package/windows.rb +0 -15
- data/lib/puppet/provider/package/yum.rb +101 -24
- data/lib/puppet/provider/package/yumhelper.py +31 -1
- data/lib/puppet/provider/package/zypper.rb +10 -28
- data/lib/puppet/provider/service/debian.rb +1 -1
- data/lib/puppet/provider/service/init.rb +3 -0
- data/lib/puppet/provider/service/openbsd.rb +318 -0
- data/lib/puppet/provider/service/redhat.rb +6 -3
- data/lib/puppet/provider/service/systemd.rb +2 -2
- data/lib/puppet/provider/yumrepo/inifile.rb +115 -42
- data/lib/puppet/resource.rb +13 -9
- data/lib/puppet/resource/catalog.rb +12 -6
- data/lib/puppet/resource/type_collection.rb +3 -3
- data/lib/puppet/settings.rb +57 -36
- data/lib/puppet/settings/config_file.rb +5 -0
- data/lib/puppet/settings/environment_conf.rb +147 -0
- data/lib/puppet/settings/ttl_setting.rb +48 -0
- data/lib/puppet/ssl/certificate_authority.rb +2 -3
- data/lib/puppet/ssl/certificate_authority/autosign_command.rb +1 -1
- data/lib/puppet/ssl/certificate_request.rb +4 -4
- data/lib/puppet/ssl/validator/default_validator.rb +2 -2
- data/lib/puppet/status.rb +1 -1
- data/lib/puppet/test/test_helper.rb +1 -0
- data/lib/puppet/type/augeas.rb +13 -1
- data/lib/puppet/type/cron.rb +32 -18
- data/lib/puppet/type/file.rb +4 -2
- data/lib/puppet/type/file/checksum.rb +15 -5
- data/lib/puppet/type/file/content.rb +3 -1
- data/lib/puppet/type/file/source.rb +5 -5
- data/lib/puppet/type/package.rb +12 -17
- data/lib/puppet/type/resources.rb +3 -1
- data/lib/puppet/type/scheduled_task.rb +4 -5
- data/lib/puppet/type/service.rb +12 -2
- data/lib/puppet/type/user.rb +106 -0
- data/lib/puppet/type/yumrepo.rb +9 -1
- data/lib/puppet/util/checksums.rb +60 -1
- data/lib/puppet/util/diff.rb +3 -1
- data/lib/puppet/util/execution.rb +20 -16
- data/lib/puppet/util/feature.rb +3 -0
- data/lib/puppet/util/logging.rb +19 -12
- data/lib/puppet/util/rubygems.rb +10 -0
- data/lib/puppet/util/watched_file.rb +1 -1
- data/lib/puppet/util/windows/security.rb +5 -3
- data/lib/puppet/vendor/load_semantic.rb +1 -0
- data/lib/puppet/vendor/require_vendored.rb +2 -0
- data/lib/puppet/vendor/semantic/Gemfile +20 -0
- data/lib/puppet/vendor/semantic/Rakefile +69 -0
- data/lib/puppet/vendor/semantic/lib/semantic.rb +7 -0
- data/lib/puppet/vendor/semantic/lib/semantic/dependency.rb +181 -0
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/graph.rb +60 -0
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/graph_node.rb +117 -0
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/module_release.rb +46 -0
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/source.rb +25 -0
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/unsatisfiable_graph.rb +31 -0
- data/lib/puppet/vendor/semantic/lib/semantic/version.rb +168 -0
- data/lib/puppet/vendor/semantic/lib/semantic/version_range.rb +424 -0
- data/lib/puppet/vendor/semantic/spec/spec_helper.rb +24 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb +141 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_spec.rb +162 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb +143 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/source_spec.rb +5 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/unsatisfiable_graph_spec.rb +44 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb +383 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb +307 -0
- data/lib/puppet/vendor/semantic/spec/unit/semantic/version_spec.rb +608 -0
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/java.tgz +0 -0
- data/spec/fixtures/stdlib.tgz +0 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/usee/lib/puppet/functions/usee/callee.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/user/lib/puppet/functions/user/caller.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/user/metadata.json +9 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/lib/puppet/functions/modulea/rb_func_a.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/lib/puppet/functions/rb_func_a.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/manifests/init.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +19 -0
- data/spec/fixtures/unit/pops/loaders/loaders/wo_metadata_module/modules/moduleb/lib/puppet/functions/moduleb/rb_func_b.rb +6 -0
- data/spec/fixtures/unit/pops/loaders/loaders/wo_metadata_module/modules/moduleb/manifests/init.pp +3 -0
- data/spec/fixtures/unit/provider/naginator/define_empty_param +6 -0
- data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services +7 -0
- data/spec/fixtures/unit/type/user/authorized_keys +5 -0
- data/spec/integration/application/apply_spec.rb +1 -2
- data/spec/integration/configurer_spec.rb +2 -2
- data/spec/integration/faces/plugin_spec.rb +62 -0
- data/spec/integration/indirector/catalog/compiler_spec.rb +1 -1
- data/spec/integration/indirector/catalog/queue_spec.rb +1 -1
- data/spec/integration/node/environment_spec.rb +2 -2
- data/spec/integration/parser/future_compiler_spec.rb +96 -142
- data/spec/integration/parser/ruby_manifest_spec.rb +0 -5
- data/spec/integration/provider/cron/crontab_spec.rb +35 -0
- data/spec/integration/type/file_spec.rb +74 -72
- data/spec/integration/util/windows/security_spec.rb +17 -0
- data/spec/lib/matchers/resource.rb +45 -13
- data/spec/lib/puppet_spec/files.rb +18 -0
- data/spec/lib/puppet_spec/module_tool/shared_functions.rb +56 -0
- data/spec/lib/puppet_spec/module_tool/stub_source.rb +133 -0
- data/spec/shared_contexts/checksums.rb +55 -0
- data/spec/unit/application/apply_spec.rb +10 -7
- data/spec/unit/application/doc_spec.rb +17 -10
- data/spec/unit/application/indirection_base_spec.rb +18 -10
- data/spec/unit/application/inspect_spec.rb +22 -20
- data/spec/unit/configurer/downloader_spec.rb +7 -6
- data/spec/unit/configurer/plugin_handler_spec.rb +5 -8
- data/spec/unit/configurer_spec.rb +1 -1
- data/spec/unit/context_spec.rb +23 -0
- data/spec/unit/environments_spec.rb +274 -16
- data/spec/unit/face/config_spec.rb +111 -11
- data/spec/unit/face/module/install_spec.rb +14 -85
- data/spec/unit/face/module/list_spec.rb +108 -62
- data/spec/unit/face/module/search_spec.rb +1 -1
- data/spec/unit/face/module/uninstall_spec.rb +21 -42
- data/spec/unit/face/parser_spec.rb +5 -2
- data/spec/unit/file_bucket/dipper_spec.rb +92 -86
- data/spec/unit/file_bucket/file_spec.rb +23 -75
- data/spec/unit/file_serving/metadata_spec.rb +74 -74
- data/spec/unit/forge/module_release_spec.rb +131 -0
- data/spec/unit/forge/repository_spec.rb +21 -20
- data/spec/unit/forge_spec.rb +99 -23
- data/spec/unit/functions/assert_type_spec.rb +59 -0
- data/spec/unit/functions4_spec.rb +671 -0
- data/spec/unit/indirector/catalog/static_compiler_spec.rb +2 -2
- data/spec/unit/indirector/facts/facter_spec.rb +9 -3
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +156 -155
- data/spec/unit/indirector/rest_spec.rb +8 -0
- data/spec/unit/interface/face_collection_spec.rb +35 -23
- data/spec/unit/module_spec.rb +20 -8
- data/spec/unit/module_tool/applications/builder_spec.rb +40 -12
- data/spec/unit/module_tool/applications/checksummer_spec.rb +86 -105
- data/spec/unit/module_tool/applications/installer_spec.rb +293 -261
- data/spec/unit/module_tool/applications/searcher_spec.rb +1 -1
- data/spec/unit/module_tool/applications/uninstaller_spec.rb +90 -154
- data/spec/unit/module_tool/applications/unpacker_spec.rb +12 -12
- data/spec/unit/module_tool/applications/upgrader_spec.rb +286 -18
- data/spec/unit/module_tool/metadata_spec.rb +223 -14
- data/spec/unit/module_tool/tar/gnu_spec.rb +12 -9
- data/spec/unit/module_tool/tar/mini_spec.rb +1 -1
- data/spec/unit/module_tool/tar_spec.rb +4 -18
- data/spec/unit/module_tool_spec.rb +123 -27
- data/spec/unit/network/formats_spec.rb +2 -2
- data/spec/unit/network/http_pool_spec.rb +21 -0
- data/spec/unit/network/rights_spec.rb +10 -8
- data/spec/unit/node/environment_spec.rb +27 -2
- data/spec/unit/parser/collector_spec.rb +1 -1
- data/spec/unit/parser/compiler_spec.rb +1 -1
- data/spec/unit/parser/functions/generate_spec.rb +4 -0
- data/spec/unit/pops/evaluator/access_ops_spec.rb +50 -11
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +25 -0
- data/spec/unit/pops/loaders/dependency_loader_spec.rb +44 -0
- data/spec/unit/pops/loaders/loader_paths_spec.rb +66 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +105 -0
- data/spec/unit/pops/loaders/module_loaders_spec.rb +119 -0
- data/spec/unit/pops/loaders/static_loader_spec.rb +46 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +145 -10
- data/spec/unit/pops/types/type_factory_spec.rb +101 -0
- data/spec/unit/pops/types/type_parser_spec.rb +22 -0
- data/spec/unit/property/list_spec.rb +9 -1
- data/spec/unit/provider/augeas/augeas_spec.rb +58 -11
- data/spec/unit/provider/cron/crontab_spec.rb +1 -0
- data/spec/unit/provider/cron/parsed_spec.rb +15 -0
- data/spec/unit/provider/naginator_spec.rb +14 -0
- data/spec/unit/provider/package/apt_spec.rb +78 -64
- data/spec/unit/provider/package/gem_spec.rb +15 -0
- data/spec/unit/provider/package/rpm_spec.rb +6 -6
- data/spec/unit/provider/package/windows_spec.rb +1 -1
- data/spec/unit/provider/package/yum_spec.rb +199 -104
- data/spec/unit/provider/package/zypper_spec.rb +41 -15
- data/spec/unit/provider/service/openbsd_spec.rb +129 -22
- data/spec/unit/provider/service/redhat_spec.rb +18 -4
- data/spec/unit/provider/service/systemd_spec.rb +5 -9
- data/spec/unit/provider/service/upstart_spec.rb +1 -1
- data/spec/unit/provider/user/directoryservice_spec.rb +10 -0
- data/spec/unit/provider/yumrepo/inifile_spec.rb +171 -15
- data/spec/unit/resource/catalog_spec.rb +20 -104
- data/spec/unit/resource/type_collection_spec.rb +10 -9
- data/spec/unit/settings/config_file_spec.rb +29 -6
- data/spec/unit/settings/environment_conf_spec.rb +51 -0
- data/spec/unit/settings_spec.rb +97 -12
- data/spec/unit/ssl/certificate_authority_spec.rb +2 -0
- data/spec/unit/type/augeas_spec.rb +1 -1
- data/spec/unit/type/cron_spec.rb +6 -7
- data/spec/unit/type/file/checksum_spec.rb +6 -0
- data/spec/unit/type/file/content_spec.rb +277 -207
- data/spec/unit/type/file_spec.rb +9 -7
- data/spec/unit/type/user_spec.rb +106 -18
- data/spec/unit/type/yumrepo_spec.rb +8 -0
- data/spec/unit/util/checksums_spec.rb +12 -5
- data/spec/unit/util/diff_spec.rb +8 -0
- data/spec/unit/util/execution_spec.rb +4 -4
- data/spec/unit/util/feature_spec.rb +2 -0
- data/spec/unit/util/logging_spec.rb +14 -4
- data/spec/unit/util/rdoc/parser_spec.rb +5 -4
- data/spec/unit/util/rubygems_spec.rb +14 -0
- data/tasks/parallel.rake +2 -2
- metadata +154 -21
- checksums.yaml +0 -7
- data/lib/puppet/module_tool/applications/generator.rb +0 -142
- data/lib/puppet/module_tool/skeleton.rb +0 -37
- data/lib/puppet/module_tool/skeleton/templates/generator/Modulefile.erb +0 -11
- data/lib/puppet/module_tool/skeleton/templates/generator/README.erb +0 -16
- data/lib/puppet/module_tool/tar/solaris.rb +0 -5
- data/spec/fixtures/unit/provider/service/systemd/list_units_services +0 -17
- data/spec/unit/module_tool/tar/solaris_spec.rb +0 -22
@@ -0,0 +1,424 @@
|
|
1
|
+
require 'semantic'
|
2
|
+
|
3
|
+
module Semantic
|
4
|
+
class VersionRange < Range
|
5
|
+
class << self
|
6
|
+
# Parses a version range string into a comparable {VersionRange} instance.
|
7
|
+
#
|
8
|
+
# Currently parsed version range string may take any of the following:
|
9
|
+
# forms:
|
10
|
+
#
|
11
|
+
# * Regular Semantic Version strings
|
12
|
+
# * ex. `"1.0.0"`, `"1.2.3-pre"`
|
13
|
+
# * Partial Semantic Version strings
|
14
|
+
# * ex. `"1.0.x"`, `"1"`, `"2.X"`
|
15
|
+
# * Inequalities
|
16
|
+
# * ex. `"> 1.0.0"`, `"<3.2.0"`, `">=4.0.0"`
|
17
|
+
# * Approximate Versions
|
18
|
+
# * ex. `"~1.0.0"`, `"~ 3.2.0"`, `"~4.0.0"`
|
19
|
+
# * Inclusive Ranges
|
20
|
+
# * ex. `"1.0.0 - 1.3.9"`
|
21
|
+
# * Range Intersections
|
22
|
+
# * ex. `">1.0.0 <=2.3.0"`
|
23
|
+
#
|
24
|
+
# @param range_str [String] the version range string to parse
|
25
|
+
# @return [VersionRange] a new {VersionRange} instance
|
26
|
+
def parse(range_str)
|
27
|
+
partial = '\d+(?:[.]\d+)?(?:[.][x]|[.]\d+(?:[-][0-9a-z.-]*)?)?'
|
28
|
+
exact = '\d+[.]\d+[.]\d+(?:[-][0-9a-z.-]*)?'
|
29
|
+
|
30
|
+
range = range_str.gsub(/([(><=~])[ ]+/, '\1')
|
31
|
+
range = range.gsub(/ - /, '#').strip
|
32
|
+
|
33
|
+
return case range
|
34
|
+
when /\A(#{partial})\Z/i
|
35
|
+
parse_loose_version_expression($1)
|
36
|
+
when /\A([><][=]?)(#{exact})\Z/i
|
37
|
+
parse_inequality_expression($1, $2)
|
38
|
+
when /\A~(#{partial})\Z/i
|
39
|
+
parse_reasonably_close_expression($1)
|
40
|
+
when /\A(#{exact})#(#{exact})\Z/i
|
41
|
+
parse_inclusive_range_expression($1, $2)
|
42
|
+
when /[ ]+/
|
43
|
+
parse_intersection_expression(range)
|
44
|
+
else
|
45
|
+
raise ArgumentError
|
46
|
+
end
|
47
|
+
|
48
|
+
rescue ArgumentError
|
49
|
+
raise ArgumentError, "Unparsable version range: #{range_str.inspect}"
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Creates a new {VersionRange} from a range intersection expression.
|
55
|
+
#
|
56
|
+
# @param expr [String] a range intersection expression
|
57
|
+
# @return [VersionRange] a version range representing `expr`
|
58
|
+
def parse_intersection_expression(expr)
|
59
|
+
expr.split(/[ ]+/).map { |x| parse(x) }.inject { |a,b| a & b }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates a new {VersionRange} from a "loose" description of a Semantic
|
63
|
+
# Version number.
|
64
|
+
#
|
65
|
+
# @see .process_loose_expr
|
66
|
+
#
|
67
|
+
# @param expr [String] a "loose" version expression
|
68
|
+
# @return [VersionRange] a version range representing `expr`
|
69
|
+
def parse_loose_version_expression(expr)
|
70
|
+
start, finish = process_loose_expr(expr)
|
71
|
+
|
72
|
+
if start.stable?
|
73
|
+
start = start.send(:first_prerelease)
|
74
|
+
end
|
75
|
+
|
76
|
+
if finish.stable?
|
77
|
+
exclude = true
|
78
|
+
finish = finish.send(:first_prerelease)
|
79
|
+
end
|
80
|
+
|
81
|
+
self.new(start, finish, exclude)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Creates an open-ended version range from an inequality expression.
|
85
|
+
#
|
86
|
+
# @overload parse_inequality_expression('<', expr)
|
87
|
+
# {include:.parse_lt_expression}
|
88
|
+
#
|
89
|
+
# @overload parse_inequality_expression('<=', expr)
|
90
|
+
# {include:.parse_lte_expression}
|
91
|
+
#
|
92
|
+
# @overload parse_inequality_expression('>', expr)
|
93
|
+
# {include:.parse_gt_expression}
|
94
|
+
#
|
95
|
+
# @overload parse_inequality_expression('>=', expr)
|
96
|
+
# {include:.parse_gte_expression}
|
97
|
+
#
|
98
|
+
# @param comp ['<', '<=', '>', '>='] an inequality operator
|
99
|
+
# @param expr [String] a "loose" version expression
|
100
|
+
# @return [VersionRange] a range covering all versions in the inequality
|
101
|
+
def parse_inequality_expression(comp, expr)
|
102
|
+
case comp
|
103
|
+
when '>'
|
104
|
+
parse_gt_expression(expr)
|
105
|
+
when '>='
|
106
|
+
parse_gte_expression(expr)
|
107
|
+
when '<'
|
108
|
+
parse_lt_expression(expr)
|
109
|
+
when '<='
|
110
|
+
parse_lte_expression(expr)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns a range covering all versions greater than the given `expr`.
|
115
|
+
#
|
116
|
+
# @param expr [String] the version to be greater than
|
117
|
+
# @return [VersionRange] a range covering all versions greater than the
|
118
|
+
# given `expr`
|
119
|
+
def parse_gt_expression(expr)
|
120
|
+
if expr =~ /^[^+]*-/
|
121
|
+
start = Version.parse("#{expr}.0")
|
122
|
+
else
|
123
|
+
start = process_loose_expr(expr).last.send(:first_prerelease)
|
124
|
+
end
|
125
|
+
|
126
|
+
self.new(start, MAX_VERSION)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns a range covering all versions greater than or equal to the given
|
130
|
+
# `expr`.
|
131
|
+
#
|
132
|
+
# @param expr [String] the version to be greater than or equal to
|
133
|
+
# @return [VersionRange] a range covering all versions greater than or
|
134
|
+
# equal to the given `expr`
|
135
|
+
def parse_gte_expression(expr)
|
136
|
+
if expr =~ /^[^+]*-/
|
137
|
+
start = Version.parse(expr)
|
138
|
+
else
|
139
|
+
start = process_loose_expr(expr).first.send(:first_prerelease)
|
140
|
+
end
|
141
|
+
|
142
|
+
self.new(start, MAX_VERSION)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns a range covering all versions less than the given `expr`.
|
146
|
+
#
|
147
|
+
# @param expr [String] the version to be less than
|
148
|
+
# @return [VersionRange] a range covering all versions less than the
|
149
|
+
# given `expr`
|
150
|
+
def parse_lt_expression(expr)
|
151
|
+
if expr =~ /^[^+]*-/
|
152
|
+
finish = Version.parse(expr)
|
153
|
+
else
|
154
|
+
finish = process_loose_expr(expr).first.send(:first_prerelease)
|
155
|
+
end
|
156
|
+
|
157
|
+
self.new(MIN_VERSION, finish, true)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns a range covering all versions less than or equal to the given
|
161
|
+
# `expr`.
|
162
|
+
#
|
163
|
+
# @param expr [String] the version to be less than or equal to
|
164
|
+
# @return [VersionRange] a range covering all versions less than or equal
|
165
|
+
# to the given `expr`
|
166
|
+
def parse_lte_expression(expr)
|
167
|
+
if expr =~ /^[^+]*-/
|
168
|
+
finish = Version.parse(expr)
|
169
|
+
self.new(MIN_VERSION, finish)
|
170
|
+
else
|
171
|
+
finish = process_loose_expr(expr).last.send(:first_prerelease)
|
172
|
+
self.new(MIN_VERSION, finish, true)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# The "reasonably close" expression is used to designate ranges that have
|
177
|
+
# a reasonable proximity to the given "loose" version number. These take
|
178
|
+
# the form:
|
179
|
+
#
|
180
|
+
# ~[Version]
|
181
|
+
#
|
182
|
+
# The general semantics of these expressions are that the given version
|
183
|
+
# forms a lower bound for the range, and the upper bound is either the
|
184
|
+
# next version number increment (at whatever precision the expression
|
185
|
+
# provides) or the next stable version (in the case of a prerelease
|
186
|
+
# version).
|
187
|
+
#
|
188
|
+
# @example "Reasonably close" major version
|
189
|
+
# "~1" # => (>=1.0.0 <2.0.0)
|
190
|
+
# @example "Reasonably close" minor version
|
191
|
+
# "~1.2" # => (>=1.2.0 <1.3.0)
|
192
|
+
# @example "Reasonably close" patch version
|
193
|
+
# "~1.2.3" # => (1.2.3)
|
194
|
+
# @example "Reasonably close" prerelease version
|
195
|
+
# "~1.2.3-alpha" # => (>=1.2.3-alpha <1.2.4)
|
196
|
+
#
|
197
|
+
# @param expr [String] a "loose" expression to build the range around
|
198
|
+
# @return [VersionRange] a "reasonably close" version range
|
199
|
+
def parse_reasonably_close_expression(expr)
|
200
|
+
parsed, succ = process_loose_expr(expr)
|
201
|
+
|
202
|
+
if parsed.stable?
|
203
|
+
parsed = parsed.send(:first_prerelease)
|
204
|
+
succ = succ.send(:first_prerelease)
|
205
|
+
self.new(parsed, succ, true)
|
206
|
+
else
|
207
|
+
self.new(parsed, succ.next(:patch).send(:first_prerelease), true)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# An "inclusive range" expression takes two version numbers (or partial
|
212
|
+
# version numbers) and creates a range that covers all versions between
|
213
|
+
# them. These take the form:
|
214
|
+
#
|
215
|
+
# [Version] - [Version]
|
216
|
+
#
|
217
|
+
# @param start [String] a "loose" expresssion for the start of the range
|
218
|
+
# @param finish [String] a "loose" expression for the end of the range
|
219
|
+
# @return [VersionRange] a {VersionRange} covering `start` to `finish`
|
220
|
+
def parse_inclusive_range_expression(start, finish)
|
221
|
+
start, _ = process_loose_expr(start)
|
222
|
+
_, finish = process_loose_expr(finish)
|
223
|
+
|
224
|
+
start = start.send(:first_prerelease) if start.stable?
|
225
|
+
if finish.stable?
|
226
|
+
exclude = true
|
227
|
+
finish = finish.send(:first_prerelease)
|
228
|
+
end
|
229
|
+
|
230
|
+
self.new(start, finish, exclude)
|
231
|
+
end
|
232
|
+
|
233
|
+
# A "loose expression" is one that takes the form of all or part of a
|
234
|
+
# valid Semantic Version number. Particularly:
|
235
|
+
#
|
236
|
+
# * [Major].[Minor].[Patch]-[Prerelease]
|
237
|
+
# * [Major].[Minor].[Patch]
|
238
|
+
# * [Major].[Minor]
|
239
|
+
# * [Major]
|
240
|
+
#
|
241
|
+
# Various placeholders are also permitted in "loose expressions"
|
242
|
+
# (typically an 'x' or an asterisk).
|
243
|
+
#
|
244
|
+
# This method parses these expressions into a minimal and maximal version
|
245
|
+
# number pair.
|
246
|
+
#
|
247
|
+
# @todo Stabilize whether the second value is inclusive or exclusive
|
248
|
+
#
|
249
|
+
# @param expr [String] a string containing a "loose" version expression
|
250
|
+
# @return [(VersionNumber, VersionNumber)] a minimal and maximal
|
251
|
+
# version pair for the given expression
|
252
|
+
def process_loose_expr(expr)
|
253
|
+
case expr
|
254
|
+
when /^(\d+)(?:[.][xX*])?$/
|
255
|
+
expr = "#{$1}.0.0"
|
256
|
+
arity = :major
|
257
|
+
when /^(\d+[.]\d+)(?:[.][xX*])?$/
|
258
|
+
expr = "#{$1}.0"
|
259
|
+
arity = :minor
|
260
|
+
when /^\d+[.]\d+[.]\d+$/
|
261
|
+
arity = :patch
|
262
|
+
end
|
263
|
+
|
264
|
+
version = next_version = Version.parse(expr)
|
265
|
+
|
266
|
+
if arity
|
267
|
+
next_version = version.next(arity)
|
268
|
+
end
|
269
|
+
|
270
|
+
[ version, next_version ]
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Computes the intersection of a pair of ranges. If the ranges have no
|
275
|
+
# useful intersection, an empty range is returned.
|
276
|
+
#
|
277
|
+
# @param other [VersionRange] the range to intersect with
|
278
|
+
# @return [VersionRange] the common subset
|
279
|
+
def intersection(other)
|
280
|
+
raise NOT_A_VERSION_RANGE unless other.kind_of?(VersionRange)
|
281
|
+
|
282
|
+
if self.begin < other.begin
|
283
|
+
return other.intersection(self)
|
284
|
+
end
|
285
|
+
|
286
|
+
unless include?(other.begin) || other.include?(self.begin)
|
287
|
+
return EMPTY_RANGE
|
288
|
+
end
|
289
|
+
|
290
|
+
endpoint = ends_before?(other) ? self : other
|
291
|
+
VersionRange.new(self.begin, endpoint.end, endpoint.exclude_end?)
|
292
|
+
end
|
293
|
+
alias :& :intersection
|
294
|
+
|
295
|
+
# Returns a string representation of this range, prefering simple common
|
296
|
+
# expressions for comprehension.
|
297
|
+
#
|
298
|
+
# @return [String] a range expression representing this VersionRange
|
299
|
+
def to_s
|
300
|
+
start, finish = self.begin, self.end
|
301
|
+
inclusive = exclude_end? ? '' : '='
|
302
|
+
|
303
|
+
case
|
304
|
+
when EMPTY_RANGE == self
|
305
|
+
"<0.0.0"
|
306
|
+
when exact_version?, patch_version?
|
307
|
+
"#{ start }"
|
308
|
+
when minor_version?
|
309
|
+
"#{ start }".sub(/.0$/, '.x')
|
310
|
+
when major_version?
|
311
|
+
"#{ start }".sub(/.0.0$/, '.x')
|
312
|
+
when open_end? && start.to_s =~ /-.*[.]0$/
|
313
|
+
">#{ start }".sub(/.0$/, '')
|
314
|
+
when open_end?
|
315
|
+
">=#{ start }"
|
316
|
+
when open_begin?
|
317
|
+
"<#{ inclusive }#{ finish }"
|
318
|
+
else
|
319
|
+
">=#{ start } <#{ inclusive }#{ finish }"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
alias :inspect :to_s
|
323
|
+
|
324
|
+
private
|
325
|
+
|
326
|
+
# The lowest precedence Version possible
|
327
|
+
MIN_VERSION = Version.new(0, 0, 0, []).freeze
|
328
|
+
|
329
|
+
# The highest precedence Version possible
|
330
|
+
MAX_VERSION = Version.new((1.0/0.0), 0, 0).freeze
|
331
|
+
|
332
|
+
# Determines whether this {VersionRange} has an earlier endpoint than the
|
333
|
+
# give `other` range.
|
334
|
+
#
|
335
|
+
# @param other [VersionRange] the range to compare against
|
336
|
+
# @return [Boolean] true if the endpoint for this range is less than or
|
337
|
+
# equal to the endpoint of the `other` range.
|
338
|
+
def ends_before?(other)
|
339
|
+
self.end < other.end || (self.end == other.end && self.exclude_end?)
|
340
|
+
end
|
341
|
+
|
342
|
+
# Describes whether this range has an upper limit.
|
343
|
+
# @return [Boolean] true if this range has no upper limit
|
344
|
+
def open_end?
|
345
|
+
self.end == MAX_VERSION
|
346
|
+
end
|
347
|
+
|
348
|
+
# Describes whether this range has a lower limit.
|
349
|
+
# @return [Boolean] true if this range has no lower limit
|
350
|
+
def open_begin?
|
351
|
+
self.begin == MIN_VERSION
|
352
|
+
end
|
353
|
+
|
354
|
+
# Describes whether this range follows the patterns for matching all
|
355
|
+
# releases with the same exact version.
|
356
|
+
# @return [Boolean] true if this range matches only a single exact version
|
357
|
+
def exact_version?
|
358
|
+
self.begin == self.end
|
359
|
+
end
|
360
|
+
|
361
|
+
# Describes whether this range follows the patterns for matching all
|
362
|
+
# releases with the same major version.
|
363
|
+
# @return [Boolean] true if this range matches only a single major version
|
364
|
+
def major_version?
|
365
|
+
start, finish = self.begin, self.end
|
366
|
+
|
367
|
+
exclude_end? &&
|
368
|
+
start.major.next == finish.major &&
|
369
|
+
same_minor? && start.minor == 0 &&
|
370
|
+
same_patch? && start.patch == 0 &&
|
371
|
+
[start.prerelease, finish.prerelease] == ['', '']
|
372
|
+
end
|
373
|
+
|
374
|
+
# Describes whether this range follows the patterns for matching all
|
375
|
+
# releases with the same minor version.
|
376
|
+
# @return [Boolean] true if this range matches only a single minor version
|
377
|
+
def minor_version?
|
378
|
+
start, finish = self.begin, self.end
|
379
|
+
|
380
|
+
exclude_end? &&
|
381
|
+
same_major? &&
|
382
|
+
start.minor.next == finish.minor &&
|
383
|
+
same_patch? && start.patch == 0 &&
|
384
|
+
[start.prerelease, finish.prerelease] == ['', '']
|
385
|
+
end
|
386
|
+
|
387
|
+
# Describes whether this range follows the patterns for matching all
|
388
|
+
# releases with the same patch version.
|
389
|
+
# @return [Boolean] true if this range matches only a single patch version
|
390
|
+
def patch_version?
|
391
|
+
start, finish = self.begin, self.end
|
392
|
+
|
393
|
+
exclude_end? &&
|
394
|
+
same_major? &&
|
395
|
+
same_minor? &&
|
396
|
+
start.patch.next == finish.patch &&
|
397
|
+
[start.prerelease, finish.prerelease] == ['', '']
|
398
|
+
end
|
399
|
+
|
400
|
+
# @return [Boolean] true if `begin` and `end` share the same major verion
|
401
|
+
def same_major?
|
402
|
+
self.begin.major == self.end.major
|
403
|
+
end
|
404
|
+
|
405
|
+
# @return [Boolean] true if `begin` and `end` share the same minor verion
|
406
|
+
def same_minor?
|
407
|
+
self.begin.minor == self.end.minor
|
408
|
+
end
|
409
|
+
|
410
|
+
# @return [Boolean] true if `begin` and `end` share the same patch verion
|
411
|
+
def same_patch?
|
412
|
+
self.begin.patch == self.end.patch
|
413
|
+
end
|
414
|
+
|
415
|
+
undef :to_a
|
416
|
+
|
417
|
+
NOT_A_VERSION_RANGE = ArgumentError.new("value must be a #{VersionRange}")
|
418
|
+
|
419
|
+
public
|
420
|
+
|
421
|
+
# A range that matches no versions
|
422
|
+
EMPTY_RANGE = VersionRange.parse('< 0.0.0').freeze
|
423
|
+
end
|
424
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
PROJECT_ROOT = File.join(File.dirname(__FILE__), '..')
|
2
|
+
|
3
|
+
if ENV['COVERAGE']
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "/spec/"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
|
21
|
+
config.before do
|
22
|
+
Semantic::Dependency.instance_variable_set(:@sources, nil)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'semantic/dependency/graph_node'
|
3
|
+
|
4
|
+
describe Semantic::Dependency::GraphNode do
|
5
|
+
let(:klass) do
|
6
|
+
Class.new do
|
7
|
+
include Semantic::Dependency::GraphNode
|
8
|
+
|
9
|
+
attr_accessor :name
|
10
|
+
|
11
|
+
def initialize(name, *satisfying)
|
12
|
+
@name = name
|
13
|
+
@satisfying = satisfying
|
14
|
+
@satisfying.each { |x| add_dependency(x.name) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# @override
|
18
|
+
def satisfies_dependency?(node)
|
19
|
+
@satisfying.include?(node)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def instance(*args)
|
25
|
+
name = args.first.name unless args.empty?
|
26
|
+
klass.new(name || 'unnamed', *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'dependencies' do
|
30
|
+
subject { instance() }
|
31
|
+
|
32
|
+
example 'are added by #add_dependency' do
|
33
|
+
subject.add_dependency('foo')
|
34
|
+
subject.add_dependency('bar')
|
35
|
+
subject.add_dependency('baz')
|
36
|
+
expect(subject.dependency_names).to match_array %w[ foo bar baz ]
|
37
|
+
end
|
38
|
+
|
39
|
+
example 'are maintained in the #dependencies Hash' do
|
40
|
+
expect(subject.dependencies).to be_empty
|
41
|
+
subject.add_dependency('foo')
|
42
|
+
expect(subject.dependencies).to have_key 'foo'
|
43
|
+
expect(subject.dependencies).to respond_to :to_a
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#<<' do
|
48
|
+
let(:foo) { double('Node', :name => 'foo') }
|
49
|
+
let(:bar1) { double('Node', :name => 'bar', :'<=>' => 0) }
|
50
|
+
let(:bar2) { double('Node', :name => 'bar', :'<=>' => 0) }
|
51
|
+
let(:bar3) { double('Node', :name => 'bar') }
|
52
|
+
let(:baz) { double('Node', :name => 'baz') }
|
53
|
+
|
54
|
+
subject { instance(foo, bar1, bar2) }
|
55
|
+
|
56
|
+
it 'appends satisfying nodes to the dependencies' do
|
57
|
+
subject << foo << bar1 << bar2
|
58
|
+
expect(Array(subject.dependencies['foo'])).to match_array [ foo ]
|
59
|
+
expect(Array(subject.dependencies['bar'])).to match_array [ bar1, bar2 ]
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'does not append nodes with unknown names' do
|
63
|
+
subject << baz
|
64
|
+
expect(Array(subject.dependencies['baz'])).to be_empty
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'does not append unsatisfying nodes' do
|
68
|
+
subject << bar3
|
69
|
+
expect(Array(subject.dependencies['bar'])).to be_empty
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#satisfied' do
|
74
|
+
let(:foo) { double('Node', :name => 'foo') }
|
75
|
+
let(:bar) { double('Node', :name => 'bar') }
|
76
|
+
|
77
|
+
subject { instance(foo, bar) }
|
78
|
+
|
79
|
+
it 'is unsatisfied when no nodes have been appended' do
|
80
|
+
expect(subject).to_not be_satisfied
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'is unsatisfied when any dependencies are missing' do
|
84
|
+
subject << foo
|
85
|
+
expect(subject).to_not be_satisfied
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'is satisfied when all dependencies are fulfilled' do
|
89
|
+
subject << foo << bar
|
90
|
+
expect(subject).to be_satisfied
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#populate_children' do
|
95
|
+
let(:foo) { double('Node', :name => 'foo') }
|
96
|
+
let(:bar1) { double('Node', :name => 'bar', :'<=>' => 0) }
|
97
|
+
let(:bar2) { double('Node', :name => 'bar', :'<=>' => 0) }
|
98
|
+
let(:baz1) { double('Node', :name => 'baz', :'<=>' => 0) }
|
99
|
+
let(:baz2) { double('Node', :name => 'baz', :'<=>' => 0) }
|
100
|
+
let(:quxx) { double('Node', :name => 'quxx') }
|
101
|
+
|
102
|
+
subject do
|
103
|
+
graph = instance(foo, bar1, bar2, baz1, baz2)
|
104
|
+
graph << foo << bar1 << bar2 << baz1 << baz2
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'saves all relevant nodes as its children' do
|
108
|
+
nodes = [ foo, bar2, baz1, quxx ]
|
109
|
+
nodes.each do |node|
|
110
|
+
allow(node).to receive(:populate_children)
|
111
|
+
end
|
112
|
+
|
113
|
+
subject.populate_children(nodes)
|
114
|
+
|
115
|
+
expected = { 'foo' => foo, 'bar' => bar2, 'baz' => baz1 }
|
116
|
+
expect(subject.children).to eql expected
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'accepts a graph solution and populates it across all nodes' do
|
120
|
+
nodes = [ foo, bar2, baz1 ]
|
121
|
+
nodes.each do |node|
|
122
|
+
expect(node).to receive(:populate_children).with(nodes)
|
123
|
+
end
|
124
|
+
|
125
|
+
subject.populate_children(nodes)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#<=>' do
|
130
|
+
it 'can be compared' do
|
131
|
+
a = instance(double('Node', :name => 'a'))
|
132
|
+
b = instance(double('Node', :name => 'b'))
|
133
|
+
|
134
|
+
expect(a).to be < b
|
135
|
+
expect(b).to be > a
|
136
|
+
expect([b, a].sort).to eql [a, b]
|
137
|
+
expect([a, b].sort).to eql [a, b]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|