[macruby-changes] [2550] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Sep 14 09:45:55 PDT 2009


Revision: 2550
          http://trac.macosforge.org/projects/ruby/changeset/2550
Author:   eloy.de.enige at gmail.com
Date:     2009-09-14 09:45:55 -0700 (Mon, 14 Sep 2009)
Log Message:
-----------
Imported exports of: test-unit, minitest, rubygems, and bacon.

Added Paths:
-----------
    MacRuby/trunk/test/
    MacRuby/trunk/test/libs/
    MacRuby/trunk/test/libs/bacon/
    MacRuby/trunk/test/libs/bacon/.gitignore
    MacRuby/trunk/test/libs/bacon/COPYING
    MacRuby/trunk/test/libs/bacon/README
    MacRuby/trunk/test/libs/bacon/Rakefile
    MacRuby/trunk/test/libs/bacon/bin/
    MacRuby/trunk/test/libs/bacon/bin/bacon
    MacRuby/trunk/test/libs/bacon/lib/
    MacRuby/trunk/test/libs/bacon/lib/autotest/
    MacRuby/trunk/test/libs/bacon/lib/autotest/bacon.rb
    MacRuby/trunk/test/libs/bacon/lib/autotest/bacon_rspec.rb
    MacRuby/trunk/test/libs/bacon/lib/autotest/discover.rb
    MacRuby/trunk/test/libs/bacon/lib/bacon.rb
    MacRuby/trunk/test/libs/bacon/test/
    MacRuby/trunk/test/libs/bacon/test/spec_bacon.rb
    MacRuby/trunk/test/libs/bacon/test/spec_nontrue.rb
    MacRuby/trunk/test/libs/bacon/test/spec_should.rb
    MacRuby/trunk/test/libs/minitest/
    MacRuby/trunk/test/libs/minitest/.autotest
    MacRuby/trunk/test/libs/minitest/History.txt
    MacRuby/trunk/test/libs/minitest/Manifest.txt
    MacRuby/trunk/test/libs/minitest/README.txt
    MacRuby/trunk/test/libs/minitest/Rakefile
    MacRuby/trunk/test/libs/minitest/design_rationale.rb
    MacRuby/trunk/test/libs/minitest/lib/
    MacRuby/trunk/test/libs/minitest/lib/minitest/
    MacRuby/trunk/test/libs/minitest/lib/minitest/autorun.rb
    MacRuby/trunk/test/libs/minitest/lib/minitest/mock.rb
    MacRuby/trunk/test/libs/minitest/lib/minitest/spec.rb
    MacRuby/trunk/test/libs/minitest/lib/minitest/unit.rb
    MacRuby/trunk/test/libs/minitest/test/
    MacRuby/trunk/test/libs/minitest/test/test_mini_mock.rb
    MacRuby/trunk/test/libs/minitest/test/test_mini_spec.rb
    MacRuby/trunk/test/libs/minitest/test/test_mini_test.rb
    MacRuby/trunk/test/libs/rubygems/
    MacRuby/trunk/test/libs/rubygems/.autotest
    MacRuby/trunk/test/libs/rubygems/.document
    MacRuby/trunk/test/libs/rubygems/ChangeLog
    MacRuby/trunk/test/libs/rubygems/GPL.txt
    MacRuby/trunk/test/libs/rubygems/History.txt
    MacRuby/trunk/test/libs/rubygems/LICENSE.txt
    MacRuby/trunk/test/libs/rubygems/Manifest.txt
    MacRuby/trunk/test/libs/rubygems/README
    MacRuby/trunk/test/libs/rubygems/Rakefile
    MacRuby/trunk/test/libs/rubygems/bin/
    MacRuby/trunk/test/libs/rubygems/bin/gem
    MacRuby/trunk/test/libs/rubygems/bin/update_rubygems
    MacRuby/trunk/test/libs/rubygems/cruise_config.rb
    MacRuby/trunk/test/libs/rubygems/lib/
    MacRuby/trunk/test/libs/rubygems/lib/gauntlet_rubygems.rb
    MacRuby/trunk/test/libs/rubygems/lib/rbconfig/
    MacRuby/trunk/test/libs/rubygems/lib/rbconfig/datadir.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/builder.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/command_manager.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/build_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cert_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/check_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cleanup_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/contents_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/dependency_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/environment_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/fetch_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/generate_index_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/help_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/install_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/list_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/lock_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/mirror_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/outdated_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/pristine_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/query_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/rdoc_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/search_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/server_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/setup_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/sources_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/specification_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/stale_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/uninstall_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/unpack_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/update_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/which_command.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/config_file.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/custom_require.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/defaults.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_installer.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_list.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/doc_manager.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/exceptions.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/builder.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/configure_builder.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/ext_conf_builder.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/rake_builder.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/format.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_openssl.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_path_searcher.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_runner.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/indexer.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/install_update_options.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/installer.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/local_remote_options.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/old_format.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/f_sync_dir.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_header.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_input.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_output.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader/
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader/entry.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_writer.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/package_task.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/platform.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/remote_fetcher.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/require_paths_builder.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/requirement.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/security.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/server.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_index.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache_entry.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/spec_fetcher.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/specification.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/test_utilities.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/text.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/timer.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/uninstaller.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/user_interaction.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/validator.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/version.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems/version_option.rb
    MacRuby/trunk/test/libs/rubygems/lib/rubygems.rb
    MacRuby/trunk/test/libs/rubygems/lib/ubygems.rb
    MacRuby/trunk/test/libs/rubygems/pkgs/
    MacRuby/trunk/test/libs/rubygems/pkgs/sources/
    MacRuby/trunk/test/libs/rubygems/pkgs/sources/lib/
    MacRuby/trunk/test/libs/rubygems/pkgs/sources/lib/sources.rb
    MacRuby/trunk/test/libs/rubygems/pkgs/sources/sources.gemspec
    MacRuby/trunk/test/libs/rubygems/setup.rb
    MacRuby/trunk/test/libs/rubygems/test/
    MacRuby/trunk/test/libs/rubygems/test/bogussources.rb
    MacRuby/trunk/test/libs/rubygems/test/data/
    MacRuby/trunk/test/libs/rubygems/test/data/gem-private_key.pem
    MacRuby/trunk/test/libs/rubygems/test/data/gem-public_cert.pem
    MacRuby/trunk/test/libs/rubygems/test/fake_certlib/
    MacRuby/trunk/test/libs/rubygems/test/fake_certlib/openssl.rb
    MacRuby/trunk/test/libs/rubygems/test/foo/
    MacRuby/trunk/test/libs/rubygems/test/foo/discover.rb
    MacRuby/trunk/test/libs/rubygems/test/functional.rb
    MacRuby/trunk/test/libs/rubygems/test/gem_installer_test_case.rb
    MacRuby/trunk/test/libs/rubygems/test/gem_package_tar_test_case.rb
    MacRuby/trunk/test/libs/rubygems/test/gemutilities.rb
    MacRuby/trunk/test/libs/rubygems/test/insure_session.rb
    MacRuby/trunk/test/libs/rubygems/test/mockgemui.rb
    MacRuby/trunk/test/libs/rubygems/test/private_key.pem
    MacRuby/trunk/test/libs/rubygems/test/public_cert.pem
    MacRuby/trunk/test/libs/rubygems/test/rubygems_plugin.rb
    MacRuby/trunk/test/libs/rubygems/test/simple_gem.rb
    MacRuby/trunk/test/libs/rubygems/test/test_config.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_builder.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_command_manager.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_build_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_cert_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_check_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_contents_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_dependency_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_environment_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_fetch_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_generate_index_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_install_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_list_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_lock_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_mirror_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_outdated_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_pristine_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_query_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_server_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_sources_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_specification_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_stale_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_uninstall_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_unpack_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_update_command.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_config_file.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_installer.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_list.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_doc_manager.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_configure_builder.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_ext_conf_builder.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_rake_builder.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_format.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_path_searcher.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_runner.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_indexer.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_install_update_options.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_installer.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_local_remote_options.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_header.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_input.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_output.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader_entry.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_writer.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_package_task.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_platform.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_remote_fetcher.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_requirement.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_server.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_source_index.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_spec_fetcher.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_specification.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_stream_ui.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_uninstaller.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_validator.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_version.rb
    MacRuby/trunk/test/libs/rubygems/test/test_gem_version_option.rb
    MacRuby/trunk/test/libs/rubygems/test/test_kernel.rb
    MacRuby/trunk/test/libs/rubygems/util/
    MacRuby/trunk/test/libs/rubygems/util/CL2notes
    MacRuby/trunk/test/libs/rubygems/util/gem_prelude.rb.template
    MacRuby/trunk/test/libs/test-unit/
    MacRuby/trunk/test/libs/test-unit/History.txt
    MacRuby/trunk/test/libs/test-unit/Manifest.txt
    MacRuby/trunk/test/libs/test-unit/README.txt
    MacRuby/trunk/test/libs/test-unit/Rakefile
    MacRuby/trunk/test/libs/test-unit/TODO
    MacRuby/trunk/test/libs/test-unit/bin/
    MacRuby/trunk/test/libs/test-unit/bin/testrb
    MacRuby/trunk/test/libs/test-unit/html/
    MacRuby/trunk/test/libs/test-unit/html/classic.html
    MacRuby/trunk/test/libs/test-unit/html/index.html
    MacRuby/trunk/test/libs/test-unit/html/index.html.ja
    MacRuby/trunk/test/libs/test-unit/html/test-unit-classic.png
    MacRuby/trunk/test/libs/test-unit/lib/
    MacRuby/trunk/test/libs/test-unit/lib/test/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertionfailederror.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertions.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/attribute.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/autorunner.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/descendant.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/dir.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/load.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/objectspace.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/color-scheme.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/color.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/diff.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/error.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/exceptionhandler.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/failure.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/fixture.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/notification.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/omission.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/pending.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/priority.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/console.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/emacs.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/tap.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/testcase.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/testresult.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/testsuite.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/outputlevel.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/testrunner.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/emacs/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/emacs/testrunner.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/tap/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/tap/testrunner.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunner.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnermediator.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnerutilities.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/backtracefilter.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/method-owner-finder.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/observable.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/procwrapper.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit/version.rb
    MacRuby/trunk/test/libs/test-unit/lib/test/unit.rb
    MacRuby/trunk/test/libs/test-unit/sample/
    MacRuby/trunk/test/libs/test-unit/sample/adder.rb
    MacRuby/trunk/test/libs/test-unit/sample/subtracter.rb
    MacRuby/trunk/test/libs/test-unit/sample/tc_adder.rb
    MacRuby/trunk/test/libs/test-unit/sample/tc_subtracter.rb
    MacRuby/trunk/test/libs/test-unit/sample/test_user.rb
    MacRuby/trunk/test/libs/test-unit/sample/ts_examples.rb
    MacRuby/trunk/test/libs/test-unit/test/
    MacRuby/trunk/test/libs/test-unit/test/collector/
    MacRuby/trunk/test/libs/test-unit/test/collector/test-descendant.rb
    MacRuby/trunk/test/libs/test-unit/test/collector/test-load.rb
    MacRuby/trunk/test/libs/test-unit/test/collector/test_dir.rb
    MacRuby/trunk/test/libs/test-unit/test/collector/test_objectspace.rb
    MacRuby/trunk/test/libs/test-unit/test/run-test.rb
    MacRuby/trunk/test/libs/test-unit/test/test-attribute.rb
    MacRuby/trunk/test/libs/test-unit/test/test-color-scheme.rb
    MacRuby/trunk/test/libs/test-unit/test/test-color.rb
    MacRuby/trunk/test/libs/test-unit/test/test-diff.rb
    MacRuby/trunk/test/libs/test-unit/test/test-emacs-runner.rb
    MacRuby/trunk/test/libs/test-unit/test/test-fixture.rb
    MacRuby/trunk/test/libs/test-unit/test/test-notification.rb
    MacRuby/trunk/test/libs/test-unit/test/test-omission.rb
    MacRuby/trunk/test/libs/test-unit/test/test-pending.rb
    MacRuby/trunk/test/libs/test-unit/test/test-priority.rb
    MacRuby/trunk/test/libs/test-unit/test/test-testcase.rb
    MacRuby/trunk/test/libs/test-unit/test/test_assertions.rb
    MacRuby/trunk/test/libs/test-unit/test/test_error.rb
    MacRuby/trunk/test/libs/test-unit/test/test_failure.rb
    MacRuby/trunk/test/libs/test-unit/test/test_testresult.rb
    MacRuby/trunk/test/libs/test-unit/test/test_testsuite.rb
    MacRuby/trunk/test/libs/test-unit/test/testunit-test-util.rb
    MacRuby/trunk/test/libs/test-unit/test/ui/
    MacRuby/trunk/test/libs/test-unit/test/ui/test_testrunmediator.rb
    MacRuby/trunk/test/libs/test-unit/test/util/
    MacRuby/trunk/test/libs/test-unit/test/util/test-method-owner-finder.rb
    MacRuby/trunk/test/libs/test-unit/test/util/test_backtracefilter.rb
    MacRuby/trunk/test/libs/test-unit/test/util/test_observable.rb
    MacRuby/trunk/test/libs/test-unit/test/util/test_procwrapper.rb

Added: MacRuby/trunk/test/libs/bacon/.gitignore
===================================================================
--- MacRuby/trunk/test/libs/bacon/.gitignore	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/.gitignore	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,8 @@
+*~
+ChangeLog
+TODO
+RDOX
+ann-*
+*.tar.gz
+doc
+pkg

Added: MacRuby/trunk/test/libs/bacon/COPYING
===================================================================
--- MacRuby/trunk/test/libs/bacon/COPYING	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/COPYING	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,18 @@
+Copyright (c) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Added: MacRuby/trunk/test/libs/bacon/README
===================================================================
--- MacRuby/trunk/test/libs/bacon/README	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/README	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,290 @@
+= Bacon -- small RSpec clone.
+
+   "Truth will sooner come out from error than from confusion."
+                                               ---Francis Bacon
+
+Bacon is a small RSpec clone weighing less than 350 LoC but
+nevertheless providing all essential features.
+
+
+== Whirl-wind tour
+
+    require 'bacon'
+    
+    describe 'A new array' do
+      before do
+        @ary = Array.new
+      end
+      
+      it 'should be empty' do
+        @ary.should.be.empty
+        @ary.should.not.include 1
+      end
+    
+      it 'should have zero size' do
+        @ary.size.should.equal 0
+        @ary.size.should.be.close 0.1, 0.5
+      end
+    
+      it 'should raise on trying fetch any index' do
+        lambda { @ary.fetch 0 }.
+          should.raise(IndexError).
+          message.should.match(/out of array/)
+    
+        # Alternatively:
+        should.raise(IndexError) { @ary.fetch 0 }
+      end
+    
+      it 'should have an object identity' do
+        @ary.should.not.be.same_as Array.new
+      end
+    
+      # Custom assertions are trivial to do, they are lambdas returning a
+      # boolean vale:
+      palindrome = lambda { |obj| obj == obj.reverse }
+      it 'should be a palindrome' do
+        @ary.should.be.a palindrome
+      end
+    
+      it 'should have super powers' do
+        should.flunk "no super powers found"
+      end
+    end
+
+Now run it:
+
+    $ bacon whirlwind.rb
+    A new array
+    - should be empty
+    - should have zero size
+    - should raise on trying fetch any index
+    - should have an object identity
+    - should be a palindrome
+    - should have super powers [FAILED]
+    
+    Bacon::Error: no super powers found
+    	./whirlwind.rb:39: A new array - should have super powers
+    	./whirlwind.rb:38
+    	./whirlwind.rb:3
+    
+    6 specifications (9 requirements), 1 failures, 0 errors
+
+If you want shorter output, use the Test::Unit format:
+
+    $ bacon -q whirlwind.rb
+    .....F
+    Bacon::Error: no super powers found
+    	./whirlwind.rb:39: A new array - should have super powers
+    	./whirlwind.rb:38
+    	./whirlwind.rb:3
+    
+    6 tests, 9 assertions, 1 failures, 0 errors
+
+It also supports TAP:
+
+    $ bacon -p whirlwind.rb
+    ok 1        - should be empty
+    ok 2        - should have zero size
+    ok 3        - should raise on trying fetch any index
+    ok 4        - should have an object identity
+    ok 5        - should be a palindrome
+    not ok 6    - should have super powers: FAILED
+    # Bacon::Error: no super powers found
+    # 	./whirlwind.rb:39: A new array - should have super powers
+    # 	./whirlwind.rb:38
+    # 	./whirlwind.rb:3
+    1..6
+    # 6 tests, 9 assertions, 1 failures, 0 errors
+
+    $ bacon -p whirlwind.rb | taptap -q
+    Tests took 0.00 seconds.
+    FAILED tests 6
+       6) should have super powers: FAILED
+
+    Failed 1/6 tests, 83.33% okay.
+
+(taptap is available from http://chneukirchen.org/repos/taptap/)
+
+As of Bacon 1.1, it also supports Knock:
+
+    $ bacon -k whirlwind.rb
+    ok - should be empty
+    ok - should have zero size
+    ok - should raise on trying fetch any index
+    ok - should have an object identity
+    ok - should be a palindrome
+    not ok - should have super powers: FAILED
+    # Bacon::Error: no super powers found
+    # 	./whirlwind.rb:39: A new array - should have super powers
+    # 	./whirlwind.rb:38
+    # 	./whirlwind.rb:3
+
+    $ bacon -k whirlwind.rb | kn-sum
+    6 tests, 1 failed (83.3333% succeeded)
+
+(knock is available from http://github.com/chneukirchen/knock/)
+
+
+== Implemented assertions
+
+* should.<predicate> and should.be.<predicate>
+* should.equal
+* should.match
+* should.be.identical_to / should.be.same_as
+* should.raise(*exceptions) { }
+* should.change { }
+* should.throw(symbol) { }
+* should.satisfy { |object| }
+
+
+== Added core predicates
+
+* Object#true?
+* Object#false?
+* Proc#change?
+* Proc#raise?
+* Proc#throw?
+* Numeric#close?
+
+
+== before/after
+
+before and after need to be defined before the first specification in
+a context and are run before and after each specification.
+
+As of Bacon 1.1, before and after do nest in nested contexts.
+
+
+== Shared contexts
+
+You can define shared contexts in Bacon like this:
+
+    shared "an empty container" do
+      it "should have size zero" do
+      end
+
+      it "should be empty" do
+      end
+    end
+
+    context "A new array" do
+      behaves_like "an empty container"
+    end
+
+These contexts are not executed on their own, but can be included with
+behaves_like in other contexts.  You can use shared contexts to
+structure suites with many recurring specifications.
+
+
+== Matchers
+
+Custom matchers are simply lambdas returning a boolean value, for
+example:
+
+  def shorter_than(max_size)
+    lambda { |obj| obj.size < max_size }
+  end
+
+  [1,2,3].should.be shorter_than(5)
+
+You can use modules and extend to group matchers for use in multiple
+contexts.
+
+
+== bacon standalone runner
+
+  -s, --specdox            do AgileDox-like output (default)
+  -q, --quiet              do Test::Unit-like non-verbose output
+  -p, --tap                do TAP (Test Anything Protocol) output
+  -k, --knock              do Knock output
+  -o, --output FORMAT      do FORMAT (SpecDox/TestUnit/Tap) output
+  -Q, --no-backtrace       don't print backtraces  
+  -a, --automatic          gather tests from ./test/, include ./lib/
+  -n, --name NAME          runs tests matching regexp NAME
+  -t, --testcase TESTCASE  runs tests in TestCases matching regexp TESTCASE
+
+If you don't want to use the standalone runner, run
+Bacon.summary_on_exit to install an exit handler showing the summary.
+
+
+== Object#should
+
+You can use Object#should outside of contexts, where the result of
+assertion will be returned as a boolean.  This is nice for
+demonstrations, quick checks and doctest tests.
+
+    >> require 'bacon'
+    >> (1 + 1).should.equal 2
+    => true
+    >> (6*9).should.equal 42
+    => false
+
+
+== Bacon with autotest
+
+Since version 1.0, there is autotest support.  You need to tag your
+test directories (test/ or spec/) by creating an .bacon file there.
+Autotest then will find it.  bin/bacon needs to be in PATH or RUBYPATH.
+
+
+== Converting specs
+
+spec-converter is a simple tool to convert test-unit or dust style
+tests to test/spec specs.
+
+It can be found at http://opensource.thinkrelevance.com/wiki/spec_converter.
+
+
+== Thanks to
+
+* Michael Fellinger, for fixing Bacon for 1.9 and various improvements.
+* Gabriele Renzi, for implementing Context#should.
+* James Tucker, for the autotest support.
+* Yossef Mendelssohn, for nested contexts.
+* everyone contributing bug fixes.
+
+
+== History
+
+* January 7, 2008: First public release 0.9.
+
+* July 6th, 2008: Second public release 1.0.
+  * Add Context#should as a shortcut for Context#it('should ' + _).
+  * describe now supports multiple arguments for better organization.
+  * Empty specifications are now erroneous.
+  * after-blocks run in the case of exceptions too.
+  * Autotest support.
+  * Bug fixes.
+
+* November 30th, 2008: Third public release 1.1.
+  * Nested before/after.
+  * Add -Q/--no-backtraces to not show details about failed specifications.
+  * Add Knock output.
+  * Bug fixes.
+
+
+== Contact
+
+Please mail bugs, suggestions and patches to
+<mailto:chneukirchen at gmail.com>.
+
+Git repository (patches rebased on HEAD are most welcome):
+http://github.com/chneukirchen/bacon
+git://github.com/chneukirchen/bacon.git
+
+
+== Copying
+
+Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
+
+Bacon is freely distributable under the terms of an MIT-style license.
+See COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+
+== Links
+
+Behavior-Driven Development:: <http://behaviour-driven.org/>
+RSpec:: <http://rspec.rubyforge.org/>
+test/spec:: <http://test-spec.rubyforge.org/>
+
+Christian Neukirchen:: <http://chneukirchen.org/>

Added: MacRuby/trunk/test/libs/bacon/Rakefile
===================================================================
--- MacRuby/trunk/test/libs/bacon/Rakefile	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/Rakefile	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,138 @@
+# Rakefile for Bacon.  -*-ruby-*-
+require 'rake/rdoctask'
+require 'rake/testtask'
+
+
+desc "Run all the tests"
+task :default => [:test]
+
+desc "Do predistribution stuff"
+task :predist => [:chmod, :changelog, :rdoc]
+
+
+desc "Make an archive as .tar.gz"
+task :dist => [:test, :predist] do
+  sh "git archive --format=tar --prefix=#{release}/ HEAD^{tree} >#{release}.tar"
+  sh "pax -waf #{release}.tar -s ':^:#{release}/:' RDOX ChangeLog doc"
+  sh "gzip -f -9 #{release}.tar"
+end
+
+# Helper to retrieve the "revision number" of the git tree.
+def git_tree_version
+  if File.directory?(".git")
+    @tree_version ||= `git describe`.strip.sub('-', '.')
+    @tree_version << ".0"  unless @tree_version.count('.') == 2
+  else
+    $: << "lib"
+    require 'bacon'
+    @tree_version = Bacon::VERSION
+  end
+  @tree_version
+end
+
+def gem_version
+  git_tree_version.gsub(/-.*/, '')
+end
+
+def release
+  "bacon-#{git_tree_version}"
+end
+
+def manifest
+  `git ls-files`.split("\n") - [".gitignore"]
+end
+
+
+desc "Make binaries executable"
+task :chmod do
+  Dir["bin/*"].each { |binary| File.chmod(0775, binary) }
+end
+
+desc "Generate a ChangeLog"
+task :changelog do
+  File.open("ChangeLog", "w") { |out|
+    `git log -z`.split("\0").map { |chunk|
+      author = chunk[/Author: (.*)/, 1].strip
+      date = chunk[/Date: (.*)/, 1].strip
+      desc, detail = $'.strip.split("\n", 2)
+      detail ||= ""
+      detail = detail.gsub(/.*darcs-hash:.*/, '')
+      detail.rstrip!
+      out.puts "#{date}  #{author}"
+      out.puts "  * #{desc.strip}"
+      out.puts detail  unless detail.empty?
+      out.puts
+    }
+  }
+end
+
+
+desc "Generate RDox"
+task "RDOX" do
+  sh "bin/bacon -Ilib --automatic --specdox >RDOX"
+end
+
+desc "Run all the tests"
+task :test do
+  ruby "bin/bacon -Ilib --automatic --quiet"
+end
+
+
+begin
+  $" << "sources"  if defined? FromSrc
+  require 'rubygems'
+
+  require 'rake'
+  require 'rake/clean'
+  require 'rake/packagetask'
+  require 'rake/gempackagetask'
+  require 'fileutils'
+rescue LoadError
+  # Too bad.
+else
+  spec = Gem::Specification.new do |s|
+    s.name            = "bacon"
+    s.version         = gem_version
+    s.platform        = Gem::Platform::RUBY
+    s.summary         = "a small RSpec clone"
+
+    s.description = <<-EOF
+Bacon is a small RSpec clone weighing less than 350 LoC but
+nevertheless providing all essential features.
+
+http://github.com/chneukirchen/bacon
+    EOF
+
+    s.files           = manifest + %w(RDOX ChangeLog)
+    s.bindir          = 'bin'
+    s.executables     << 'bacon'
+    s.require_path    = 'lib'
+    s.has_rdoc        = true
+    s.extra_rdoc_files = ['README', 'RDOX']
+    s.test_files      = []
+
+    s.author          = 'Christian Neukirchen'
+    s.email           = 'chneukirchen at gmail.com'
+    s.homepage        = 'http://github.com/chneukirchen/bacon'
+  end
+
+  Rake::GemPackageTask.new(spec) do |p|
+    p.gem_spec = spec
+    p.need_tar = false
+    p.need_zip = false
+  end
+end
+
+desc "Generate RDoc documentation"
+Rake::RDocTask.new(:rdoc) do |rdoc|
+  rdoc.options << '--line-numbers' << '--inline-source' <<
+    '--main' << 'README' <<
+    '--title' << 'Bacon Documentation' <<
+    '--charset' << 'utf-8'
+  rdoc.rdoc_dir = "doc"
+  rdoc.rdoc_files.include 'README'
+  rdoc.rdoc_files.include 'COPYING'
+  rdoc.rdoc_files.include 'RDOX'
+  rdoc.rdoc_files.include('lib/bacon.rb')
+end
+task :rdoc => ["RDOX"]

Added: MacRuby/trunk/test/libs/bacon/bin/bacon
===================================================================
--- MacRuby/trunk/test/libs/bacon/bin/bacon	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/bin/bacon	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,117 @@
+#!/usr/bin/env ruby
+# -*- ruby -*-
+
+require 'optparse'
+$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib/')
+module Bacon; end
+
+automatic = false
+output = 'SpecDoxOutput'
+
+opts = OptionParser.new("", 24, '  ') { |opts|
+  opts.banner = "Usage: bacon [options] [files | -a] [-- untouched arguments]"
+
+  opts.separator ""
+  opts.separator "Ruby options:"
+
+  lineno = 1
+  opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
+    eval line, TOPLEVEL_BINDING, "-e", lineno
+    lineno += 1
+  }
+
+  opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
+    $DEBUG = true
+  }
+  opts.on("-w", "--warn", "turn warnings on for your script") {
+    $-w = true
+  }
+
+  opts.on("-I", "--include PATH",
+          "specify $LOAD_PATH (may be used more than once)") { |path|
+    $LOAD_PATH.unshift(*path.split(":"))
+  }
+
+  opts.on("-r", "--require LIBRARY",
+          "require the library, before executing your script") { |library|
+    require library
+  }
+
+  opts.separator ""
+  opts.separator "bacon options:"
+
+  opts.on("-s", "--specdox", "do AgileDox-like output (default)") {
+    output = 'SpecDoxOutput'
+  }
+  opts.on("-q", "--quiet",   "do Test::Unit-like non-verbose output") {
+    output = 'TestUnitOutput'
+  }
+  opts.on("-p", "--tap",     "do TAP (Test Anything Protocol) output") {
+    output = 'TapOutput'
+  }
+  opts.on("-k", "--knock",   "do Knock output") {
+    output = 'KnockOutput'
+  }
+
+  opts.on("-o", "--output FORMAT",
+          "do FORMAT (SpecDox/TestUnit/Tap) output") { |format|
+    output = format + "Output" 
+  }
+  opts.on("-Q", "--no-backtrace", "don't print backtraces") {
+    Bacon.const_set :Backtraces, false
+  }
+
+  opts.on("-a", "--automatic", "gather tests from ./test/, include ./lib/") {
+    $LOAD_PATH.unshift "lib"  if File.directory? "lib"
+    automatic = true
+  }
+
+  opts.on('-n', '--name NAME', String,
+          "runs tests matching regexp NAME") { |n|
+    Bacon.const_set :RestrictName, Regexp.new(n)
+  }
+  
+  opts.on('-t', '--testcase TESTCASE', String,
+          "runs tests in TestCases matching regexp TESTCASE") { |t|
+    Bacon.const_set :RestrictContext, Regexp.new(t)
+  }
+
+  opts.separator ""
+  opts.separator "Common options:"
+
+  opts.on_tail("-h", "--help", "Show this message") do
+    puts opts
+    exit
+  end
+
+  opts.on_tail("--version", "Show version") do
+    require 'bacon'
+    puts "bacon #{Bacon::VERSION}"
+    exit
+  end
+
+  opts.parse! ARGV
+}
+
+files = ARGV
+
+if automatic
+  files.concat Dir["test/**/test_*.rb"]
+  files.concat Dir["test/**/spec_*.rb"]
+  files.concat Dir["spec/**/spec_*.rb"]
+end
+
+if files.empty?
+  puts opts.banner
+  exit 1
+end
+
+require 'bacon'
+
+Bacon.extend Bacon.const_get(output) rescue abort "No such formatter: #{output}"
+Bacon.summary_on_exit
+
+files.each { |file|
+  load file
+}
+


Property changes on: MacRuby/trunk/test/libs/bacon/bin/bacon
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/bacon/lib/autotest/bacon.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/lib/autotest/bacon.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/lib/autotest/bacon.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,36 @@
+Autotest.add_hook :initialize do |att|
+  att.clear_mappings
+
+  att.add_mapping(%r%^(test|spec)/.*\.rb$%) do |filename, _|
+    filename
+  end
+
+  att.add_mapping(%r%^lib/(.*)\.rb$%) do |filename, m|
+    lib_path = m[1]
+    spec = File.basename(lib_path)
+    path = File.dirname(lib_path)
+    [
+      "test/#{path}/test_#{spec}.rb",
+      "test/#{path}/spec_#{spec}.rb",
+      "spec/#{path}/spec_#{spec}.rb",
+      # TODO : decide if the follow 'rspec style' name should be allowed?
+      # "spec/#{path}/#{spec}_spec.rb"
+    ]
+  end
+
+  false
+end
+
+class Autotest::Bacon < Autotest
+  def initialize
+    super
+    self.libs = %w[. lib test spec].join(File::PATH_SEPARATOR)
+  end
+
+  def make_test_cmd(files_to_test)
+    args = files_to_test.keys.flatten.join(' ')
+    args = '-a' if args.empty?
+    # TODO : make regex to pass to -n using values
+    "#{ruby} -S bacon -I#{libs} -o TestUnit #{args}"
+  end
+end

Added: MacRuby/trunk/test/libs/bacon/lib/autotest/bacon_rspec.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/lib/autotest/bacon_rspec.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/lib/autotest/bacon_rspec.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,2 @@
+require File.dirname(__FILE__) + '/bacon.rb'
+class Autotest::BaconRspec < Autotest::Bacon; end
\ No newline at end of file

Added: MacRuby/trunk/test/libs/bacon/lib/autotest/discover.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/lib/autotest/discover.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/lib/autotest/discover.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,9 @@
+Autotest.add_discovery do
+  if File.exist?('spec/.bacon') || File.exist?('test/.bacon')
+    class Autotest
+      @@discoveries.delete_if { |d| d.inspect =~ /rspec/ }
+      warn 'Removing rspec from autotest!'
+    end
+    'bacon'
+  end
+end
\ No newline at end of file

Added: MacRuby/trunk/test/libs/bacon/lib/bacon.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/lib/bacon.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/lib/bacon.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,347 @@
+# Bacon -- small RSpec clone.
+#
+# "Truth will sooner come out from error than from confusion." ---Francis Bacon
+
+# Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
+#
+# Bacon is freely distributable under the terms of an MIT-style license.
+# See COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+module Bacon
+  VERSION = "1.1"
+
+  Counter = Hash.new(0)
+  ErrorLog = ""
+  Shared = Hash.new { |_, name|
+    raise NameError, "no such context: #{name.inspect}"
+  }
+
+  RestrictName    = //  unless defined? RestrictName
+  RestrictContext = //  unless defined? RestrictContext
+
+  Backtraces = true  unless defined? Backtraces
+
+  def self.summary_on_exit
+    return  if Counter[:installed_summary] > 0
+    at_exit {
+      handle_summary
+      if $!
+        raise $!
+      elsif Counter[:errors] + Counter[:failed] > 0
+        exit 1
+      end
+    }
+    Counter[:installed_summary] += 1
+  end
+  class <<self; alias summary_at_exit summary_on_exit; end
+
+  module SpecDoxOutput
+    def handle_specification(name)
+      puts name
+      yield
+      puts
+    end
+
+    def handle_requirement(description)
+      print "- #{description}"
+      error = yield
+      puts error.empty? ? "" : " [#{error}]"
+    end
+
+    def handle_summary
+      print ErrorLog  if Backtraces
+      puts "%d specifications (%d requirements), %d failures, %d errors" %
+        Counter.values_at(:specifications, :requirements, :failed, :errors)
+    end
+  end
+
+  module TestUnitOutput
+    def handle_specification(name)  yield  end
+
+    def handle_requirement(description)
+      error = yield
+      if error.empty?
+        print "."
+      else
+        print error[0..0]
+      end
+    end
+
+    def handle_summary
+      puts
+      puts ErrorLog  if Backtraces
+      puts "%d tests, %d assertions, %d failures, %d errors" %
+        Counter.values_at(:specifications, :requirements, :failed, :errors)
+    end
+  end
+
+  module TapOutput
+    def handle_specification(name)  yield  end
+
+    def handle_requirement(description)
+      ErrorLog.replace ""
+      error = yield
+      if error.empty?
+        puts "ok %-3d - %s" % [Counter[:specifications], description]
+      else
+        puts "not ok %d - %s: %s" %
+          [Counter[:specifications], description, error]
+        puts ErrorLog.strip.gsub(/^/, '# ')  if Backtraces
+      end
+    end
+
+    def handle_summary
+      puts "1..#{Counter[:specifications]}"
+      puts "# %d tests, %d assertions, %d failures, %d errors" %
+        Counter.values_at(:specifications, :requirements, :failed, :errors)
+    end
+  end
+
+  module KnockOutput
+    def handle_specification(name)  yield  end
+
+    def handle_requirement(description)
+      ErrorLog.replace ""
+      error = yield
+      if error.empty?
+        puts "ok - %s" % [description]
+      else
+        puts "not ok - %s: %s" % [description, error]
+        puts ErrorLog.strip.gsub(/^/, '# ')  if Backtraces
+      end
+    end
+
+    def handle_summary;  end
+  end
+
+  extend SpecDoxOutput          # default
+
+  class Error < RuntimeError
+    attr_accessor :count_as
+
+    def initialize(count_as, message)
+      @count_as = count_as
+      super message
+    end
+  end
+
+  class Context
+    attr_reader :name, :block
+    
+    def initialize(name, &block)
+      @name = name
+      @before, @after = [], []
+      @block = block
+    end
+    
+    def run
+      return  unless name =~ RestrictContext
+      Bacon.handle_specification(name) { instance_eval(&block) }
+      self
+    end
+
+    def before(&block); @before << block; end
+    def after(&block);  @after << block; end
+
+    def behaves_like(*names)
+      names.each { |name| instance_eval(&Shared[name]) }
+    end
+
+    def it(description, &block)
+      return  unless description =~ RestrictName
+      block ||= lambda { should.flunk "not implemented" }
+      Counter[:specifications] += 1
+      run_requirement description, block
+    end
+    
+    def should(*args, &block)
+      if Counter[:depth]==0
+        it('should '+args.first,&block)
+      else
+        super(*args,&block)
+      end
+    end
+
+    def run_requirement(description, spec)
+      Bacon.handle_requirement description do
+        begin
+          Counter[:depth] += 1
+          rescued = false
+          begin
+            @before.each { |block| instance_eval(&block) }
+            prev_req = Counter[:requirements]
+            instance_eval(&spec)
+          rescue Object => e
+            rescued = true
+            raise e
+          ensure
+            if Counter[:requirements] == prev_req and not rescued
+              raise Error.new(:missing,
+                              "empty specification: #{@name} #{description}")
+            end
+            begin
+              @after.each { |block| instance_eval(&block) }
+            rescue Object => e
+              raise e  unless rescued
+            end
+          end
+        rescue Object => e
+          ErrorLog << "#{e.class}: #{e.message}\n"
+          e.backtrace.find_all { |line| line !~ /bin\/bacon|\/bacon\.rb:\d+/ }.
+            each_with_index { |line, i|
+            ErrorLog << "\t#{line}#{i==0 ? ": #@name - #{description}" : ""}\n"
+          }
+          ErrorLog << "\n"
+
+          if e.kind_of? Error
+            Counter[e.count_as] += 1
+            e.count_as.to_s.upcase
+          else
+            Counter[:errors] += 1
+            "ERROR: #{e.class}"
+          end
+        else
+          ""
+        ensure
+          Counter[:depth] -= 1
+        end
+      end
+    end
+
+    def describe(*args, &block)
+      context = Bacon::Context.new(args.join(' '), &block)
+      @before.each { |b| context.before(&b) }
+      @after.each { |b| context.after(&b) }
+      context.run
+    end
+
+    def raise?(*args, &block); block.raise?(*args); end
+    def throw?(*args, &block); block.throw?(*args); end
+    def change?(*args, &block); block.change?(*args); end
+  end
+end
+
+
+class Object
+  def true?; false; end
+  def false?; false; end
+end
+
+class TrueClass
+  def true?; true; end
+end
+
+class FalseClass
+  def false?; true; end
+end
+
+class Proc
+  def raise?(*exceptions)
+    call
+  rescue *(exceptions.empty? ? RuntimeError : exceptions) => e
+    e
+  else
+    false
+  end
+
+  def throw?(sym)
+    catch(sym) {
+      call
+      return false
+    }
+    return true
+  end
+
+  def change?
+    pre_result = yield
+    called = call
+    post_result = yield
+    pre_result != post_result
+  end
+end
+
+class Numeric
+  def close?(to, delta)
+    (to.to_f - self).abs <= delta.to_f  rescue false
+  end
+end
+
+
+class Object
+  def should(*args, &block)    Should.new(self).be(*args, &block)             end
+end
+
+module Kernel
+  private
+  def describe(*args, &block) Bacon::Context.new(args.join(' '), &block).run  end
+  def shared(name, &block)    Bacon::Shared[name] = block                     end
+end
+
+class Should
+  # Kills ==, ===, =~, eql?, equal?, frozen?, instance_of?, is_a?,
+  # kind_of?, nil?, respond_to?, tainted?
+  instance_methods.each { |name| undef_method name  if name =~ /\?|^\W+$/ }
+
+  def initialize(object)
+    @object = object
+    @negated = false
+  end
+
+  def not(*args, &block)
+    @negated = !@negated
+
+    if args.empty?
+      self
+    else
+      be(*args, &block)
+    end
+  end
+
+  def be(*args, &block)
+    if args.empty?
+      self
+    else
+      block = args.shift  unless block_given?
+      satisfy(*args, &block)
+    end
+  end
+
+  alias a  be
+  alias an be
+
+  def satisfy(*args, &block)
+    if args.size == 1 && String === args.first
+      description = args.shift
+    else
+      description = ""
+    end
+
+    r = yield(@object, *args)
+    if Bacon::Counter[:depth] > 0
+      Bacon::Counter[:requirements] += 1
+      raise Bacon::Error.new(:failed, description)  unless @negated ^ r
+      r
+    else
+      @negated ? !r : !!r
+    end
+  end
+
+  def method_missing(name, *args, &block)
+    name = "#{name}?"  if name.to_s =~ /\w[^?]\z/
+
+    desc = @negated ? "not " : ""
+    desc << @object.inspect << "." << name.to_s
+    desc << "(" << args.map{|x|x.inspect}.join(", ") << ") failed"
+
+    satisfy(desc) { |x| x.__send__(name, *args, &block) }
+  end
+
+  def equal(value)         self == value      end
+  def match(value)         self =~ value      end
+  def identical_to(value)  self.equal? value  end
+  alias same_as identical_to
+
+  def flunk(reason="Flunked")
+    raise Bacon::Error.new(:failed, reason)
+  end
+end

Added: MacRuby/trunk/test/libs/bacon/test/spec_bacon.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/test/spec_bacon.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/test/spec_bacon.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,374 @@
+$-w,w = nil, $-w
+require File.expand_path('../../lib/bacon', __FILE__)
+$-w = w
+
+# Hooray for meta-testing.
+module MetaTests
+  def succeed
+    lambda { |block|
+      block.should.not.raise Bacon::Error
+      true
+    }
+  end
+
+  def fail
+    lambda { |block|
+      block.should.raise Bacon::Error
+      true
+    }
+  end
+
+  def equal_string(x)
+    lambda { |s|
+      x == s.to_s
+    }
+  end
+end
+
+describe "Bacon" do
+  extend MetaTests
+  
+  it "should have should.satisfy" do
+    lambda { should.satisfy { 1 == 1 } }.should succeed
+    lambda { should.satisfy { 1 } }.should succeed
+
+    lambda { should.satisfy { 1 != 1 } }.should fail
+    lambda { should.satisfy { false } }.should fail
+    lambda { should.satisfy { false } }.should fail
+
+    lambda { 1.should.satisfy { |n| n % 2 == 0 } }.should fail
+    lambda { 2.should.satisfy { |n| n % 2 == 0 } }.should succeed
+  end
+
+  it "should have should.equal" do
+    lambda { "string1".should == "string1" }.should succeed
+    lambda { "string1".should == "string2" }.should fail
+    lambda { "1".should == 1 }.should fail
+
+    lambda { "string1".should.equal "string1" }.should succeed
+    lambda { "string1".should.equal "string2" }.should fail
+    lambda { "1".should.equal 1 }.should fail
+  end
+
+  it "should have should.raise" do
+    lambda { lambda { raise "Error" }.should.raise }.should succeed
+    lambda { lambda { raise "Error" }.should.raise RuntimeError }.should succeed
+    lambda { lambda { raise "Error" }.should.not.raise }.should fail
+    lambda { lambda { raise "Error" }.should.not.raise(RuntimeError) }.should fail
+
+    lambda { lambda { 1 + 1 }.should.raise }.should fail
+    lambda {
+      lambda { raise "Error" }.should.raise(Interrupt)
+    }.should.raise
+  end
+
+  it "should have should.raise with a block" do
+    lambda { should.raise { raise "Error" } }.should succeed
+    lambda { should.raise(RuntimeError) { raise "Error" } }.should succeed
+    lambda { should.not.raise { raise "Error" } }.should fail
+    lambda { should.not.raise(RuntimeError) { raise "Error" } }.should fail
+
+    lambda { should.raise { 1 + 1 } }.should fail
+    lambda {
+      should.raise(Interrupt) { raise "Error" }
+    }.should.raise
+  end
+
+  it "should have a should.raise should return the exception" do
+    ex = lambda { raise "foo!" }.should.raise
+    ex.should.be.kind_of RuntimeError
+    ex.message.should =~ /foo/
+  end
+  
+  it "should have should.be.an.instance_of" do
+    lambda { "string".should.be.instance_of String }.should succeed
+    lambda { "string".should.be.instance_of Hash }.should fail
+
+    lambda { "string".should.be.an.instance_of String }.should succeed
+    lambda { "string".should.be.an.instance_of Hash }.should fail
+  end
+
+  it "should have should.be.nil" do
+    lambda { nil.should.be.nil }.should succeed
+    lambda { nil.should.not.be.nil }.should fail
+    lambda { "foo".should.be.nil }.should fail
+    lambda { "foo".should.not.be.nil }.should succeed
+  end
+
+  it "should have should.include" do
+    lambda { [1,2,3].should.include 2 }.should succeed
+    lambda { [1,2,3].should.include 4 }.should fail
+
+    lambda { {1=>2, 3=>4}.should.include 1 }.should succeed
+    lambda { {1=>2, 3=>4}.should.include 2 }.should fail
+  end
+
+  it "should have should.be.a.kind_of" do
+    lambda { Array.should.be.kind_of Module }.should succeed
+    lambda { "string".should.be.kind_of Object }.should succeed
+    lambda { 1.should.be.kind_of Comparable }.should succeed
+
+    lambda { Array.should.be.a.kind_of Module }.should succeed
+
+    lambda { "string".should.be.a.kind_of Class }.should fail
+  end
+
+  it "should have should.match" do
+    lambda { "string".should.match(/strin./) }.should succeed
+    lambda { "string".should =~ /strin./ }.should succeed
+
+    lambda { "string".should.match(/slin./) }.should fail
+    lambda { "string".should =~ /slin./ }.should fail
+  end
+
+  it "should have should.not.raise" do
+    lambda { lambda { 1 + 1 }.should.not.raise }.should succeed
+    lambda { lambda { 1 + 1 }.should.not.raise(Interrupt) }.should succeed
+
+    lambda {
+      lambda {
+        lambda {
+          Kernel.raise ZeroDivisionError.new("ArgumentError")
+        }.should.not.raise(RuntimeError, Comparable)
+      }.should.raise ZeroDivisionError
+    }.should succeed
+      
+    lambda { lambda { raise "Error" }.should.not.raise }.should fail
+  end
+
+  it "should have should.throw" do
+    lambda { lambda { throw :foo }.should.throw(:foo) }.should succeed
+    lambda { lambda {       :foo }.should.throw(:foo) }.should fail
+
+    should.throw(:foo) { throw :foo }
+  end
+
+  it "should have should.not.satisfy" do
+    lambda { should.not.satisfy { 1 == 2 } }.should succeed
+    lambda { should.not.satisfy { 1 == 1 } }.should fail
+  end
+
+  it "should have should.not.equal" do
+    lambda { "string1".should.not == "string2" }.should succeed
+    lambda { "string1".should.not == "string1" }.should fail
+  end
+
+  it "should have should.not.match" do
+    lambda { "string".should.not.match(/sling/) }.should succeed
+    lambda { "string".should.not.match(/string/) }.should fail
+#    lambda { "string".should.not.match("strin") }.should fail
+
+    lambda { "string".should.not =~ /sling/ }.should succeed
+    lambda { "string".should.not =~ /string/ }.should fail
+#    lambda { "string".should.not =~ "strin" }.should fail
+  end
+
+  it "should have should.be.identical_to/same_as" do
+    lambda { s = "string"; s.should.be.identical_to s }.should succeed
+    lambda { "string".should.be.identical_to "string" }.should fail
+
+    lambda { s = "string"; s.should.be.same_as s }.should succeed
+    lambda { "string".should.be.same_as "string" }.should fail
+  end
+
+  it "should have should.respond_to" do
+    lambda { "foo".should.respond_to :to_s }.should succeed
+    lambda { 5.should.respond_to :to_str }.should fail
+    lambda { :foo.should.respond_to :nx }.should fail
+  end
+  
+  it "should have should.be.close" do
+    lambda { 1.4.should.be.close 1.4, 0 }.should succeed
+    lambda { 0.4.should.be.close 0.5, 0.1 }.should succeed
+
+    lambda { 0.4.should.be.close 0.5, 0.05 }.should fail
+    lambda { 0.4.should.be.close Object.new, 0.1 }.should fail
+    lambda { 0.4.should.be.close 0.5, -0.1 }.should fail
+  end
+
+  it "should support multiple negation" do
+    lambda { 1.should.equal 1 }.should succeed
+    lambda { 1.should.not.equal 1 }.should fail
+    lambda { 1.should.not.not.equal 1 }.should succeed
+    lambda { 1.should.not.not.not.equal 1 }.should fail
+
+    lambda { 1.should.equal 2 }.should fail
+    lambda { 1.should.not.equal 2 }.should succeed
+    lambda { 1.should.not.not.equal 2 }.should fail
+    lambda { 1.should.not.not.not.equal 2 }.should succeed
+  end
+
+  it "should have should.<predicate>" do
+    lambda { [].should.be.empty }.should succeed
+    lambda { [1,2,3].should.not.be.empty }.should succeed
+
+    lambda { [].should.not.be.empty }.should fail
+    lambda { [1,2,3].should.be.empty }.should fail
+
+    lambda { {1=>2, 3=>4}.should.has_key 1 }.should succeed
+    lambda { {1=>2, 3=>4}.should.not.has_key 2 }.should succeed
+
+    lambda { nil.should.bla }.should.raise(NoMethodError)
+    lambda { nil.should.not.bla }.should.raise(NoMethodError)
+  end
+
+  it "should have should <operator> (>, >=, <, <=, ===)" do
+    lambda { 2.should.be > 1 }.should succeed
+    lambda { 1.should.be > 2 }.should fail
+
+    lambda { 1.should.be < 2 }.should succeed
+    lambda { 2.should.be < 1 }.should fail
+
+    lambda { 2.should.be >= 1 }.should succeed
+    lambda { 2.should.be >= 2 }.should succeed
+    lambda { 2.should.be >= 2.1 }.should fail
+
+    lambda { 2.should.be <= 1 }.should fail
+    lambda { 2.should.be <= 2 }.should succeed
+    lambda { 2.should.be <= 2.1 }.should succeed
+
+    lambda { Array.should === [1,2,3] }.should succeed
+    lambda { Integer.should === [1,2,3] }.should fail
+
+    lambda { /foo/.should === "foobar" }.should succeed
+    lambda { "foobar".should === /foo/ }.should fail
+  end
+
+  it "should allow for custom shoulds" do
+    lambda { (1+1).should equal_string("2") }.should succeed
+    lambda { (1+2).should equal_string("2") }.should fail
+
+    lambda { (1+1).should.be equal_string("2") }.should succeed
+    lambda { (1+2).should.be equal_string("2") }.should fail
+
+    lambda { (1+1).should.not equal_string("2") }.should fail
+    lambda { (1+2).should.not equal_string("2") }.should succeed
+    lambda { (1+2).should.not.not equal_string("2") }.should fail
+
+    lambda { (1+1).should.not.be equal_string("2") }.should fail
+    lambda { (1+2).should.not.be equal_string("2") }.should succeed
+  end
+
+  it "should have should.flunk" do
+    lambda { should.flunk }.should fail
+    lambda { should.flunk "yikes" }.should fail
+  end
+end
+
+describe "before/after" do
+  before do
+    @a = 1
+    @b = 2
+  end
+
+  before do
+    @a = 2
+  end
+
+  after do
+    @a.should.equal 2
+    @a = 3
+  end
+
+  after do
+    @a.should.equal 3
+  end
+  
+  it "should run in the right order" do
+    @a.should.equal 2
+    @b.should.equal 2
+  end
+  
+  describe "when nested" do
+    before do
+      @c = 5
+    end
+    
+    it "should run from higher level" do
+      @a.should.equal 2
+      @b.should.equal 2
+    end
+    
+    it "should run at the nested level" do
+      @c.should.equal 5
+    end
+    
+    before do
+      @a = 5
+    end
+    
+    it "should run in the right order" do
+      @a.should.equal 5
+      @a = 2
+    end
+  end
+  
+  it "should not run from lower level" do
+    @c.should.be.nil
+  end
+  
+  describe "when nested at a sibling level" do
+    it "should not run from sibling level" do
+      @c.should.be.nil
+    end
+  end
+end
+
+shared "a shared context" do
+  it "gets called where it is included" do
+    true.should.be.true
+  end
+end
+
+shared "another shared context" do
+  it "can access data" do
+    @magic.should.be.equal 42
+  end
+end
+
+describe "shared/behaves_like" do
+  behaves_like "a shared context"
+
+  ctx = self
+  it "raises NameError when the context is not found" do
+    lambda {
+      ctx.behaves_like "whoops"
+    }.should.raise NameError
+  end
+
+  behaves_like "a shared context"
+
+  before {
+    @magic = 42
+  }
+  behaves_like "another shared context"
+end
+
+describe 'describe arguments' do
+
+  def check(ctx,name)
+    ctx.should.be.an.instance_of Bacon::Context
+    ctx.instance_variable_get('@name').should == name
+  end
+
+  it 'should work with string' do
+    check(describe('string') {},'string')
+  end
+
+  it 'should work with symbols' do
+    check(describe(:behaviour) {},'behaviour')
+  end
+   
+  it 'should work with modules' do
+    check(describe(Bacon) {},'Bacon')
+  end
+
+  it 'should work with namespaced modules' do
+    check(describe(Bacon::Context) {},'Bacon::Context')
+  end
+
+  it 'should work with multiple arguments' do
+    check(describe(Bacon::Context, :empty) {},'Bacon::Context empty')
+  end
+
+end

Added: MacRuby/trunk/test/libs/bacon/test/spec_nontrue.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/test/spec_nontrue.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/test/spec_nontrue.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,14 @@
+$false_is_not_true = false.should.not.be.true
+$nil_is_not_true = nil.should.not.be.true
+
+describe 'A non-true value' do
+  it 'should pass negated tests inside specs' do
+    false.should.not.be.true
+    nil.should.not.be.true
+  end
+  
+  it 'should pass negated tests outside specs' do
+    $false_is_not_true.should.be.true
+    $nil_is_not_true.should.be.true
+  end
+end

Added: MacRuby/trunk/test/libs/bacon/test/spec_should.rb
===================================================================
--- MacRuby/trunk/test/libs/bacon/test/spec_should.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/bacon/test/spec_should.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,32 @@
+require File.expand_path('../../lib/bacon', __FILE__)
+
+describe "#should shortcut for #it('should')" do
+  
+  should "be called" do
+    @called = true
+    @called.should.be == true
+  end
+  
+  should "save some characters by typing should" do
+    lambda { should.satisfy { 1 == 1 } }.should.not.raise
+  end
+
+  should "save characters even on failure" do
+    lambda { should.satisfy { 1 == 2 } }.should.raise Bacon::Error
+  end
+
+  should "work nested" do
+    should.satisfy {1==1}
+  end
+  
+  count = Bacon::Counter[:specifications]
+  should "add new specifications" do
+    # XXX this should +=1 but it's +=2
+    (count+1).should == Bacon::Counter[:specifications]
+  end
+
+  should "have been called" do
+    @called.should.be == true
+  end
+
+end

Added: MacRuby/trunk/test/libs/minitest/.autotest
===================================================================
--- MacRuby/trunk/test/libs/minitest/.autotest	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/.autotest	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,15 @@
+# -*- ruby -*-
+
+require 'autotest/restart'
+
+Autotest.add_hook :initialize do |at|
+  at.extra_class_map["MiniSpec"]             = "test/test_mini_spec.rb"
+  at.extra_class_map["TestMiniTestTestCase"] = "test/test_mini_test.rb"
+
+  at.add_exception 'coverage.info'
+  at.add_exception 'coverage'
+end
+
+# require 'autotest/rcov'
+# Autotest::RCov.command = 'rcov_info'
+

Added: MacRuby/trunk/test/libs/minitest/History.txt
===================================================================
--- MacRuby/trunk/test/libs/minitest/History.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/History.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,175 @@
+=== 1.4.2 / 2009-06-25
+
+* 1 bug fix:
+
+  * Fixed info handler for systems that don't have siginfo.
+
+=== 1.4.1 / 2009-06-23
+
+* 1 major enhancement:
+
+  * Handle ^C and other fatal exceptions by failing
+
+* 1 minor enhancement:
+
+  * Added something to catch mixed use of test/unit and minitest if $DEBUG
+
+* 1 bug fix:
+
+  * Added SIGINFO handler for finding slow tests without verbose
+
+=== 1.4.0 / 2009-06-18
+
+* 5 minor enhancement:
+
+  * Added clarification doco.
+  * Added specs and mocks to autorun.
+  * Changed spec test class creation to be non-destructive.
+  * Updated rakefile for new hoe capabilities.
+  * describes are nestable (via subclass). before/after/def inherits, specs don't.
+
+* 3 bug fixes:
+
+  * Fixed location on must/wont.
+  * Switched to __name__ to avoid common ivar name.
+  * Fixed indentation in test file (1.9).
+
+=== 1.3.1 / 2009-01-20
+
+* 1 minor enhancement:
+
+  * Added miniunit/autorun.rb as replacement for test/unit.rb's autorun.
+
+* 16 bug fixes:
+
+  * 1.9 test fixes.
+  * Bug fixes from nobu and akira for really odd scenarios. They run ruby funny.
+  * Fixed (assert|refute)_match's argument order.
+  * Fixed LocalJumpError in autorun if exception thrown before at_exit.
+  * Fixed assert_in_delta (should be >=, not >).
+  * Fixed assert_raises to match Modules.
+  * Fixed capture_io to not dup IOs.
+  * Fixed indentation of capture_io for ruby 1.9 warning.
+  * Fixed location to deal better with custom assertions and load paths. (Yuki)
+  * Fixed order of (must|wont)_include in MiniTest::Spec.
+  * Fixed skip's backtrace.
+  * Got arg order wrong in *_match in tests, message wrong as a result.
+  * Made describe private. For some reason I thought that an attribute of Kernel.
+  * Removed disable_autorun method, added autorun.rb instead.
+  * assert_match escapes if passed string for pattern.
+  * instance_of? is different from ===, use instance_of.
+
+=== 1.3.0 / 2008-10-09
+
+* 2 major enhancements:
+
+  * renamed to minitest and pulled out test/unit compatibility.
+  * mini/test.rb is now minitest/unit.rb, everything else maps directly.
+
+* 12 minor enhancements:
+
+  * assert_match now checks that act can call =~ and converts exp to a
+    regexp only if needed.
+  * Added assert_send... seems useless to me tho.
+  * message now forces to string... ruby-core likes to pass classes and arrays :(
+  * Added -v handling and switched to @verbose from $DEBUG.
+  * Verbose output now includes test class name and adds a sortable running time!
+  * Switched message generation into procs for message deferment.
+  * Added skip and renamed fail to flunk.
+  * Improved output failure messages for assert_instance_of, assert_kind_of
+  * Improved output for assert_respond_to, assert_same.
+  * at_exit now exits false instead of errors+failures.
+  * Made the tests happier and more readable imhfo.
+  * Switched index(s) == 0 to rindex(s, 0) on nobu's suggestion. Faster.
+
+* 5 bug fixes:
+
+  * 1.9: Added encoding normalization in mu_pp.
+  * 1.9: Fixed backtrace filtering (BTs are expanded now)
+  * Added back exception_details to assert_raises. DOH.
+  * Fixed shadowed variable in mock.rb
+  * Fixed stupid muscle memory message bug in assert_send.
+
+=== 1.2.1 / 2008-06-10
+
+* 7 minor enhancements:
+
+  * Added deprecations everywhere in test/unit.
+  * Added test_order to TestCase. :random on mini, :sorted on test/unit (for now).
+  * Big cleanup in test/unit for rails. Thanks Jeremy Kemper!
+  * Minor readability cleanup.
+  * Pushed setup/run/teardown down to testcase allowing specialized testcases.
+  * Removed pp. Tests run 2x faster. :/
+  * Renamed deprecation methods and moved to test/unit/deprecate.rb.
+
+=== 1.2.0 / 2008-06-09
+
+* 2 major enhancements:
+
+  * Added Mini::Spec.
+  * Added Mini::Mock. Thanks Steven Baker!!
+
+* 23 minor enhancements:
+
+  * Added bin/use_miniunit to make it easy to test out miniunit.
+  * Added -n filtering, thanks to Phil Hagelberg!
+  * Added args argument to #run, takes ARGV from at_exit.
+  * Added test name output if $DEBUG.
+  * Added a refute (was deny) for every assert.
+  * Added capture_io and a bunch of nice assertions from zentest.
+  * Added deprecation mechanism for assert_no/not methods to test/unit/assertions.
+  * Added pp output when available.
+  * Added tests for all assertions. Pretty much maxed out coverage.
+  * Added tests to verify consistency and good naming.
+  * Aliased and deprecated all ugly assertions.
+  * Cleaned out test/unit. Moved autorun there.
+  * Code cleanup to make extensions easier. Thanks Chad!
+  * Got spec args reversed in all but a couple assertions. Much more readable.
+  * Improved error messages across the board. Adds your message to the default.
+  * Moved into Mini namespace, renamed to Mini::Test and Mini::Spec.
+  * Pulled the assertions into their own module...
+  * Removed as much code as I could while still maintaining full functionality.
+    * Moved filter_backtrace into MiniTest.
+    * Removed MiniTest::Unit::run. Unnecessary.
+    * Removed location_of_failure. Unnecessary.
+    * Rewrote test/unit's filter_backtrace. Flog from 37.0 to 18.1
+  * Removed assert_send. Google says it is never used.
+  * Renamed MiniTest::Unit.autotest to #run.
+  * Renamed deny to refute.
+  * Rewrote some ugly/confusing default assertion messages.
+  * assert_in_delta now defaults to 0.001 precision. Makes specs prettier.
+
+* 9 bug fixes:
+
+  * Fixed assert_raises to raise outside of the inner-begin/rescue.
+  * Fixed for ruby 1.9 and rubinius.
+  * No longer exits 0 if exception in code PRE-test run causes early exit.
+  * Removed implementors method list from mini/test.rb - too stale.
+  * assert_nothing_raised takes a class as an arg. wtf? STUPID
+  * ".EF" output is now unbuffered.
+  * Bunch of changes to get working with rails... UGH.
+    * Added stupid hacks to deal with rails not requiring their dependencies.
+    * Now bitch loudly if someone defines one of my classes instead of requiring.
+  * Fixed infect method to work better on 1.9.
+  * Fixed all shadowed variable warnings in 1.9.
+
+=== 1.1.0 / 2007-11-08
+
+* 4 major enhancements:
+
+  * Finished writing all missing assertions.
+  * Output matches original test/unit.
+  * Documented every method needed by language implementor.
+  * Fully switched over to self-testing setup.
+
+* 2 minor enhancements:
+
+  * Added deny (assert ! test), our favorite extension to test/unit.
+  * Added .autotest and fairly complete unit tests. (thanks Chad for help here)
+
+=== 1.0.0 / 2006-10-30
+
+* 1 major enhancement
+
+  * Birthday!
+

Added: MacRuby/trunk/test/libs/minitest/Manifest.txt
===================================================================
--- MacRuby/trunk/test/libs/minitest/Manifest.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/Manifest.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,13 @@
+.autotest
+History.txt
+Manifest.txt
+README.txt
+Rakefile
+design_rationale.rb
+lib/minitest/autorun.rb
+lib/minitest/mock.rb
+lib/minitest/spec.rb
+lib/minitest/unit.rb
+test/test_mini_mock.rb
+test/test_mini_spec.rb
+test/test_mini_test.rb

Added: MacRuby/trunk/test/libs/minitest/README.txt
===================================================================
--- MacRuby/trunk/test/libs/minitest/README.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/README.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,60 @@
+= minitest/{unit,spec,mock}
+
+* http://rubyforge.org/projects/bfts
+
+== DESCRIPTION:
+
+minitest/unit is a small and fast replacement for ruby's huge and slow
+test/unit. This is meant to be clean and easy to use both as a regular
+test writer and for language implementors that need a minimal set of
+methods to bootstrap a working unit test suite.
+
+mini/spec is a functionally complete spec engine.
+
+mini/mock, by Steven Baker, is a beautifully tiny mock object framework.
+
+(This package was called miniunit once upon a time)
+
+== FEATURES/PROBLEMS:
+
+* Contains minitest/unit - a simple and clean test system (301 lines!).
+* Contains minitest/spec - a simple and clean spec system (52 lines!).
+* Contains minitest/mock - a simple and clean mock system (35 lines!).
+* Incredibly small and fast runner, but no bells and whistles.
+
+== RATIONALE:
+
+See design_rationale.rb to see how specs and tests work in minitest.
+
+== REQUIREMENTS:
+
++ Ruby 1.8, maybe even 1.6 or lower. No magic is involved.
+
+== INSTALL:
+
++ sudo gem install minitest
+
+== LICENSE:
+
+(The MIT License)
+
+Copyright (c) Ryan Davis, Seattle.rb
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Added: MacRuby/trunk/test/libs/minitest/Rakefile
===================================================================
--- MacRuby/trunk/test/libs/minitest/Rakefile	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/Rakefile	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,42 @@
+# -*- ruby -*-
+
+$TESTING_MINIUNIT = true
+
+require 'rubygems'
+require 'hoe'
+
+Hoe.plugin :seattlerb
+
+Hoe.spec 'minitest' do
+  developer 'Ryan Davis', 'ryand-ruby at zenspider.com'
+
+  self.rubyforge_name = "bfts"
+end
+
+def loc dir
+  system "find #{dir} -name \\*.rb | xargs wc -l | tail -1"
+end
+
+desc "stupid line count"
+task :dickwag do
+  puts
+  puts "miniunit"
+  puts
+  print " lib  loc"; loc "lib"
+  print " test loc"; loc "test"
+  print " totl loc"; loc "lib test"
+  print " flog = "; system "flog -s lib"
+
+  puts
+  puts "test/unit"
+  puts
+  Dir.chdir File.expand_path("~/Work/svn/ruby/ruby_1_8") do
+    print " lib  loc"; loc "lib/test"
+    print " test loc"; loc "test/testunit"
+    print " totl loc"; loc "lib/test test/testunit"
+    print " flog = "; system "flog -s lib/test"
+  end
+  puts
+end
+
+# vim: syntax=Ruby

Added: MacRuby/trunk/test/libs/minitest/design_rationale.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/design_rationale.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/design_rationale.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,52 @@
+# Specs:                               # Equivalent Unit Tests:
+###############################################################################
+describe Thingy do                     # class TestThingy < MiniTest::Unit::TestCase
+  before do                            #   def setup
+    do_some_setup                      #     super
+  end                                  #     do_some_setup
+                                       #   end
+  it "should do the first thing" do    #
+    1.must_equal 1                     #   def test_first_thing
+  end                                  #     assert_equal 1, 1
+                                       #   end
+  describe SubThingy do                # end
+    before do                          #
+      do_more_setup                    # class TestSubThingy < TestThingy
+    end                                #   def setup
+                                       #     super
+    it "should do the second thing" do #     do_more_setup
+      2.must_equal 2                   #   end
+    end                                #
+  end                                  #   def test_second_thing
+end                                    #     assert_equal 2, 2
+                                       #   end
+                                       # end
+###############################################################################
+# runs 2 specs                         # runs 3 tests
+###############################################################################
+# The specs generate:
+
+class ThingySpec < MiniTest::Spec
+  def setup
+    super
+    do_some_setup
+  end
+
+  def test_should_do_the_first_thing
+    assert_equal 1, 1
+  end
+end
+
+class SubThingySpec < ThingySpec
+  def setup
+    super
+    do_more_setup
+  end
+
+  # because only setup/teardown is inherited, not specs
+  remove_method :test_should_do_the_first_thing
+
+  def test_should_do_the_second_thing
+    assert_equal 2, 2
+  end
+end

Added: MacRuby/trunk/test/libs/minitest/lib/minitest/autorun.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/lib/minitest/autorun.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/lib/minitest/autorun.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,5 @@
+require 'minitest/unit'
+require 'minitest/spec'
+require 'minitest/mock'
+
+MiniTest::Unit.autorun

Added: MacRuby/trunk/test/libs/minitest/lib/minitest/mock.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/lib/minitest/mock.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/lib/minitest/mock.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,31 @@
+class MockExpectationError < StandardError; end
+
+module MiniTest
+  class Mock
+    def initialize
+      @expected_calls = {}
+      @actual_calls = Hash.new {|h,k| h[k] = [] }
+    end
+
+    def expect(name, retval, args=[])
+      n, r, a = name, retval, args # for the closure below
+      @expected_calls[name] = { :retval => retval, :args => args }
+      self.class.__send__(:define_method, name) { |*x|
+        raise ArgumentError unless @expected_calls[n][:args].size == x.size
+        @actual_calls[n] << { :retval => r, :args => x }
+        retval
+      }
+      self
+    end
+
+    def verify
+      @expected_calls.each_key do |name|
+        expected = @expected_calls[name]
+        msg = "expected #{name}, #{expected.inspect}"
+        raise MockExpectationError, msg unless
+          @actual_calls.has_key? name and @actual_calls[name].include?(expected)
+      end
+      true
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/minitest/lib/minitest/spec.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/lib/minitest/spec.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/lib/minitest/spec.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,108 @@
+#!/usr/bin/ruby -w
+
+require 'minitest/unit'
+
+class Module
+  def infect_with_assertions pos_prefix, neg_prefix, skip_re, map = {}
+    MiniTest::Assertions.public_instance_methods(false).each do |meth|
+      meth = meth.to_s
+
+      new_name = case meth
+                 when /^assert/ then
+                   meth.sub(/^assert/, pos_prefix.to_s)
+                 when /^refute/ then
+                   meth.sub(/^refute/, neg_prefix.to_s)
+                 end
+      next unless new_name
+      next if new_name =~ skip_re
+
+      regexp, replacement = map.find { |re, _| new_name =~ re }
+      new_name.sub! regexp, replacement if replacement
+
+      # warn "%-22p -> %p %p" % [meth, new_name, regexp]
+      self.class_eval <<-EOM
+        def #{new_name} *args, &block
+          return MiniTest::Spec.current.#{meth}(*args, &self)     if Proc === self
+          return MiniTest::Spec.current.#{meth}(args.first, self) if args.size == 1
+          return MiniTest::Spec.current.#{meth}(self, *args)
+        end
+      EOM
+    end
+  end
+end
+
+Object.infect_with_assertions(:must, :wont,
+                              /^(must|wont)$|wont_(throw)|
+                                 must_(block|not?_|nothing|raise$)/x,
+                              /(must_throw)s/                 => '\1',
+                              /(?!not)_same/                  => '_be_same_as',
+                              /_in_/                          => '_be_within_',
+                              /_operator/                     => '_be',
+                              /_includes/                     => '_include',
+                              /(must|wont)_(.*_of|nil|empty)/ => '\1_be_\2',
+                              /must_raises/                   => 'must_raise')
+
+class Object
+  alias :must_be_close_to :must_be_within_delta
+  alias :wont_be_close_to :wont_be_within_delta
+end
+
+module Kernel
+  def describe desc, &block
+    stack = MiniTest::Spec.describe_stack
+    name  = desc.to_s.split(/\W+/).map { |s| s.capitalize }.join + "Spec"
+    cls   = Object.class_eval "class #{name} < #{stack.last}; end; #{name}"
+
+    cls.nuke_test_methods!
+
+    stack.push cls
+    cls.class_eval(&block)
+    stack.pop
+  end
+  private :describe
+end
+
+class MiniTest::Spec < MiniTest::Unit::TestCase
+  @@describe_stack = [MiniTest::Spec]
+  def self.describe_stack
+    @@describe_stack
+  end
+
+  def self.current
+    @@current_spec
+  end
+
+  def initialize name
+    super
+    @@current_spec = self
+  end
+
+  def self.nuke_test_methods!
+    self.public_instance_methods.grep(/^test_/).each do |name|
+      send :remove_method, name rescue nil
+    end
+  end
+
+  def self.define_inheritable_method name, &block
+    super_method = self.superclass.instance_method name
+
+    define_method name do
+      super_method.bind(self).call if super_method # regular super() warns
+      instance_eval(&block)
+    end
+  end
+
+  def self.before(type = :each, &block)
+    raise "unsupported before type: #{type}" unless type == :each
+    define_inheritable_method :setup, &block
+  end
+
+  def self.after(type = :each, &block)
+    raise "unsupported after type: #{type}" unless type == :each
+    define_inheritable_method :teardown, &block
+  end
+
+  def self.it desc, &block
+    define_method "test_#{desc.gsub(/\W+/, '_').downcase}", &block
+  end
+end

Added: MacRuby/trunk/test/libs/minitest/lib/minitest/unit.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/lib/minitest/unit.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/lib/minitest/unit.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,530 @@
+##
+#
+# Totally minimal drop-in replacement for test-unit
+#
+# TODO: refute -> debunk, prove/rebut, show/deny... lots of possibilities
+
+module MiniTest
+  class Assertion < Exception; end
+  class Skip < Assertion; end
+
+  file = if RUBY_VERSION =~ /^1\.9/ then  # bt's expanded, but __FILE__ isn't :(
+           File.expand_path __FILE__
+         elsif  __FILE__ =~ /^[^\.]/ then # assume both relative
+           require 'pathname'
+           pwd = Pathname.new Dir.pwd
+           pn = Pathname.new File.expand_path(__FILE__)
+           pn = File.join(".", pn.relative_path_from(pwd)) unless pn.relative?
+           pn.to_s
+         else                             # assume both are expanded
+           __FILE__
+         end
+
+  # './lib' in project dir, or '/usr/local/blahblah' if installed
+  MINI_DIR = File.dirname(File.dirname(file))
+
+  def self.filter_backtrace bt
+    return ["No backtrace"] unless bt
+
+    new_bt = []
+    bt.each do |line|
+      break if line.rindex(MINI_DIR, 0)
+      new_bt << line
+    end
+
+    new_bt = bt.reject { |line| line.rindex(MINI_DIR, 0) } if new_bt.empty?
+    new_bt = bt.dup if new_bt.empty?
+    new_bt
+  end
+
+  module Assertions
+    def mu_pp(obj)
+      s = obj.inspect
+      s = s.force_encoding(Encoding.default_external) if defined? Encoding
+      s
+    end
+
+    def _assertions= n
+      @_assertions = n
+    end
+
+    def _assertions
+      @_assertions ||= 0
+    end
+
+    def assert test, msg = nil
+      msg ||= "Failed assertion, no message given."
+      self._assertions += 1
+      unless test then
+        msg = msg.call if Proc === msg
+        raise MiniTest::Assertion, msg
+      end
+      true
+    end
+
+    def assert_block msg = nil
+      msg = message(msg) { "Expected block to return true value" }
+      assert yield, msg
+    end
+
+    def assert_empty obj, msg = nil
+      msg = message(msg) { "Expected #{obj.inspect} to be empty" }
+      assert_respond_to obj, :empty?
+      assert obj.empty?, msg
+    end
+
+    def assert_equal exp, act, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(exp)}, not #{mu_pp(act)}" }
+      assert(exp == act, msg)
+    end
+
+    def assert_in_delta exp, act, delta = 0.001, msg = nil
+      n = (exp - act).abs
+      msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
+      assert delta >= n, msg
+    end
+
+    def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
+      assert_in_delta a, b, [a, b].min * epsilon, msg
+    end
+
+    def assert_includes collection, obj, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" }
+      flip = (obj.respond_to? :include?) && ! (collection.respond_to? :include?) # HACK for specs
+      obj, collection = collection, obj if flip
+      assert_respond_to collection, :include?
+      assert collection.include?(obj), msg
+    end
+
+    def assert_instance_of cls, obj, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" }
+      flip = (Module === obj) && ! (Module === cls) # HACK for specs
+      obj, cls = cls, obj if flip
+      assert obj.instance_of?(cls), msg
+    end
+
+    def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
+      msg = message(msg) {
+        "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
+      flip = (Module === obj) && ! (Module === cls) # HACK for specs
+      obj, cls = cls, obj if flip
+      assert obj.kind_of?(cls), msg
+    end
+
+    def assert_match exp, act, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(exp)} to match #{mu_pp(act)}" }
+      assert_respond_to act, :"=~"
+      exp = /#{Regexp.escape(exp)}/ if String === exp && String === act
+      assert exp =~ act, msg
+    end
+
+    def assert_nil obj, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
+      assert obj.nil?, msg
+    end
+
+    def assert_operator o1, op, o2, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
+      assert o1.__send__(op, o2), msg
+    end
+
+    def assert_raises *exp
+      msg = String === exp.last ? exp.pop : nil
+      should_raise = false
+      begin
+        yield
+        should_raise = true
+      rescue Exception => e
+        assert(exp.any? { |ex|
+                 ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class
+               }, exception_details(e, "#{mu_pp(exp)} exception expected, not"))
+
+        return e
+      end
+
+      exp = exp.first if exp.size == 1
+      flunk "#{mu_pp(exp)} expected but nothing was raised." if should_raise
+    end
+
+    def assert_respond_to obj, meth, msg = nil
+      msg = message(msg) {
+          "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
+        }
+      flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
+      obj, meth = meth, obj if flip
+      assert obj.respond_to?(meth), msg
+    end
+
+    def assert_same exp, act, msg = nil
+      msg = message(msg) {
+        data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
+        "Expected %s (0x%x) to be the same as %s (0x%x)" % data
+      }
+      assert exp.equal?(act), msg
+    end
+
+    def assert_send send_ary, m = nil
+      recv, msg, *args = send_ary
+      m = message(m) {
+        "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" }
+      assert recv.__send__(msg, *args), m
+    end
+
+    def assert_throws sym, msg = nil
+      default = "Expected #{mu_pp(sym)} to have been thrown"
+      caught = true
+      catch(sym) do
+        begin
+          yield
+        rescue ArgumentError => e     # 1.9 exception
+          default += ", not #{e.message.split(/ /).last}"
+        rescue NameError => e         # 1.8 exception
+          default += ", not #{e.name.inspect}"
+        end
+        caught = false
+      end
+
+      assert caught, message(msg) { default }
+    end
+
+    def capture_io
+      require 'stringio'
+
+      orig_stdout, orig_stderr         = $stdout, $stderr
+      captured_stdout, captured_stderr = StringIO.new, StringIO.new
+      $stdout, $stderr                 = captured_stdout, captured_stderr
+
+      yield
+
+      return captured_stdout.string, captured_stderr.string
+    ensure
+      $stdout = orig_stdout
+      $stderr = orig_stderr
+    end
+
+    def exception_details e, msg
+      "#{msg}\nClass: <#{e.class}>\nMessage: <#{e.message.inspect}>\n---Backtrace---\n#{MiniTest::filter_backtrace(e.backtrace).join("\n")}\n---------------"
+    end
+
+    def flunk msg = nil
+      msg ||= "Epic Fail!"
+      assert false, msg
+    end
+
+    def message msg = nil, &default
+      proc {
+        if msg then
+          msg = msg.to_s unless String === msg
+          msg += '.' unless msg.empty?
+          msg += "\n#{default.call}."
+          msg.strip
+        else
+          "#{default.call}."
+        end
+      }
+    end
+
+    # used for counting assertions
+    def pass msg = nil
+      assert true
+    end
+
+    def refute test, msg = nil
+      msg ||= "Failed refutation, no message given"
+      not assert(! test, msg)
+    end
+
+    def refute_empty obj, msg = nil
+      msg = message(msg) { "Expected #{obj.inspect} to not be empty" }
+      assert_respond_to obj, :empty?
+      refute obj.empty?, msg
+    end
+
+    def refute_equal exp, act, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" }
+      refute exp == act, msg
+    end
+
+    def refute_in_delta exp, act, delta = 0.001, msg = nil
+      n = (exp - act).abs
+      msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to not be < #{delta}" }
+      refute delta > n, msg
+    end
+
+    def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
+      refute_in_delta a, b, a * epsilon, msg
+    end
+
+    def refute_includes collection, obj, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" }
+      flip = (obj.respond_to? :include?) && ! (collection.respond_to? :include?) # HACK for specs
+      obj, collection = collection, obj if flip
+      assert_respond_to collection, :include?
+      refute collection.include?(obj), msg
+    end
+
+    def refute_instance_of cls, obj, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(obj)} to not be an instance of #{cls}" }
+      flip = (Module === obj) && ! (Module === cls) # HACK for specs
+      obj, cls = cls, obj if flip
+      refute obj.instance_of?(cls), msg
+    end
+
+    def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
+      msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
+      flip = (Module === obj) && ! (Module === cls) # HACK for specs
+      obj, cls = cls, obj if flip
+      refute obj.kind_of?(cls), msg
+    end
+
+    def refute_match exp, act, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(exp)} to not match #{mu_pp(act)}" }
+      assert_respond_to act, :"=~"
+      exp = /#{Regexp.escape(exp)}/ if String === exp && String === act
+      refute exp =~ act, msg
+    end
+
+    def refute_nil obj, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
+      refute obj.nil?, msg
+    end
+
+    def refute_operator o1, op, o2, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}" }
+      refute o1.__send__(op, o2), msg
+    end
+
+    def refute_respond_to obj, meth, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
+      flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
+      obj, meth = meth, obj if flip
+      refute obj.respond_to?(meth), msg
+    end
+
+    def refute_same exp, act, msg = nil
+      msg = message(msg) { "Expected #{mu_pp(act)} to not be the same as #{mu_pp(exp)}" }
+      refute exp.equal?(act), msg
+    end
+
+    def skip msg = nil, bt = caller
+      msg ||= "Skipped, no message given"
+      raise MiniTest::Skip, msg, bt
+    end
+  end
+
+  class Unit
+    VERSION = "1.4.2"
+
+    attr_accessor :report, :failures, :errors, :skips
+    attr_accessor :test_count, :assertion_count
+    attr_accessor :start_time
+
+    @@installed_at_exit ||= false
+    @@out = $stdout
+
+    def self.autorun
+      at_exit {
+        next if $! # don't run if there was an exception
+        exit_code = MiniTest::Unit.new.run(ARGV)
+        exit false if exit_code && exit_code != 0
+      } unless @@installed_at_exit
+      @@installed_at_exit = true
+    end
+
+    def self.output= stream
+      @@out = stream
+    end
+
+    def location e
+      last_before_assertion = ""
+      e.backtrace.reverse_each do |s|
+        break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
+        last_before_assertion = s
+      end
+      last_before_assertion.sub(/:in .*$/, '')
+    end
+
+    def puke klass, meth, e
+      e = case e
+          when MiniTest::Skip then
+            @skips += 1
+            "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
+          when MiniTest::Assertion then
+            @failures += 1
+            "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
+          else
+            @errors += 1
+            bt = MiniTest::filter_backtrace(e.backtrace).join("\n    ")
+            "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n    #{bt}\n"
+          end
+      @report << e
+      e[0, 1]
+    end
+
+    def initialize
+      @report = []
+      @errors = @failures = @skips = 0
+      @verbose = false
+    end
+
+    ##
+    # Top level driver, controls all output and filtering.
+
+    def run args = []
+      @verbose = args.delete('-v')
+
+      filter = if args.first =~ /^(-n|--name)$/ then
+                 args.shift
+                 arg = args.shift
+                 arg =~ /\/(.*)\// ? Regexp.new($1) : arg
+               else
+                 /./ # anything - ^test_ already filtered by #tests
+               end
+
+      @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
+
+      start = Time.now
+      run_test_suites filter
+
+      @@out.puts
+      @@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
+
+      @report.each_with_index do |msg, i|
+        @@out.puts "\n%3d) %s" % [i + 1, msg]
+      end
+
+      @@out.puts
+
+      status
+
+      return failures + errors if @test_count > 0 # or return nil...
+    rescue Interrupt
+      abort 'Interrupted'
+    end
+
+    def status io = @@out
+      format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
+      io.puts format % [test_count, assertion_count, failures, errors, skips]
+    end
+
+    def run_test_suites filter = /./
+      @test_count, @assertion_count = 0, 0
+      old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
+      TestCase.test_suites.each do |suite|
+        suite.test_methods.grep(filter).each do |test|
+          inst = suite.new test
+          inst._assertions = 0
+          @@out.print "#{suite}##{test}: " if @verbose
+
+          @start_time = Time.now
+          result = inst.run(self)
+
+          @@out.print "%.2f s: " % (Time.now - @start_time) if @verbose
+          @@out.print result
+          @@out.puts if @verbose
+          @test_count += 1
+          @assertion_count += inst._assertions
+        end
+      end
+      @@out.sync = old_sync if @@out.respond_to? :sync=
+      [@test_count, @assertion_count]
+    end
+
+    class TestCase
+      attr_reader :__name__
+
+      PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
+        SystemExit]
+
+      SUPPORTS_INFO_SIGNAL = Signal.list['INFO']
+
+      def run runner
+        trap 'INFO' do
+          warn '%s#%s %.2fs' % [self.class, self.__name__,
+            (Time.now - runner.start_time)]
+          runner.status $stderr
+        end if SUPPORTS_INFO_SIGNAL
+
+        result = '.'
+        begin
+          @passed = nil
+          self.setup
+          self.__send__ self.__name__
+          @passed = true
+        rescue *PASSTHROUGH_EXCEPTIONS
+          raise
+        rescue Exception => e
+          @passed = false
+          result = runner.puke(self.class, self.__name__, e)
+        ensure
+          begin
+            self.teardown
+          rescue *PASSTHROUGH_EXCEPTIONS
+            raise
+          rescue Exception => e
+            result = runner.puke(self.class, self.__name__, e)
+          end
+          trap 'INFO', 'DEFAULT' if SUPPORTS_INFO_SIGNAL
+        end
+        result
+      end
+
+      def initialize name
+        @__name__ = name
+        @passed = nil
+      end
+
+      def self.reset
+        @@test_suites = {}
+      end
+
+      reset
+
+      def self.inherited klass
+        @@test_suites[klass] = true
+      end
+
+      def self.test_order
+        :random
+      end
+
+      def self.test_suites
+        @@test_suites.keys.sort_by { |ts| ts.name }
+      end
+
+      def self.test_methods
+        methods = public_instance_methods(true).grep(/^test/).map { |m|
+          m.to_s
+        }.sort
+
+        if self.test_order == :random then
+          max = methods.size
+          methods = methods.sort_by { rand(max) }
+        end
+
+        methods
+      end
+
+      def setup; end
+      def teardown; end
+
+      def passed?
+        @passed
+      end
+
+      include MiniTest::Assertions
+    end # class TestCase
+  end # class Test
+end # module Mini
+
+if $DEBUG then
+  # this helps me ferret out porting issues
+  module Test; end
+  module Test::Unit; end
+  class Test::Unit::TestCase
+    def self.inherited x
+      raise "You're running minitest and test/unit in the same process: #{x}"
+    end
+  end
+end
+

Added: MacRuby/trunk/test/libs/minitest/test/test_mini_mock.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/test/test_mini_mock.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/test/test_mini_mock.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,77 @@
+require 'minitest/mock'
+require 'minitest/unit'
+
+MiniTest::Unit.autorun
+
+class TestMiniMock < MiniTest::Unit::TestCase
+  def setup
+    @mock = MiniTest::Mock.new.expect(:foo, nil)
+    @mock.expect(:meaning_of_life, 42)
+  end
+
+  def test_should_create_stub_method
+    assert_nil @mock.foo
+  end
+
+  def test_should_allow_return_value_specification
+    assert_equal 42, @mock.meaning_of_life
+  end
+
+  def test_should_blow_up_if_not_called
+    @mock.foo
+
+    util_verify_bad
+  end
+
+  def test_should_not_blow_up_if_everything_called
+    @mock.foo
+    @mock.meaning_of_life
+
+    assert @mock.verify
+  end
+
+  def test_should_allow_expectations_to_be_added_after_creation
+    @mock.expect(:bar, true)
+    assert @mock.bar
+  end
+
+  def test_should_not_verify_if_new_expected_method_is_not_called
+    @mock.foo
+    @mock.meaning_of_life
+    @mock.expect(:bar, true)
+
+    util_verify_bad
+  end
+
+  def test_should_not_verify_if_unexpected_method_is_called
+    assert_raises NoMethodError do
+      @mock.unexpected
+    end
+  end
+
+  def test_should_blow_up_on_wrong_number_of_arguments
+    @mock.foo
+    @mock.meaning_of_life
+    @mock.expect(:sum, 3, [1, 2])
+
+    assert_raises ArgumentError do
+      @mock.sum
+    end
+  end
+
+  def test_should_blow_up_on_wrong_arguments
+    @mock.foo
+    @mock.meaning_of_life
+    @mock.expect(:sum, 3, [1, 2])
+
+    @mock.sum(2, 4)
+
+    util_verify_bad
+  end
+
+  def util_verify_bad
+    assert_raises MockExpectationError do
+      @mock.verify
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/minitest/test/test_mini_spec.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/test/test_mini_spec.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/test/test_mini_spec.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,163 @@
+require 'minitest/spec'
+
+MiniTest::Unit.autorun
+
+describe MiniTest::Spec do
+  before do
+    @assertion_count = 4
+  end
+
+  after do
+    self._assertions.must_equal @assertion_count
+  end
+
+  it "needs to have all methods named well" do
+    @assertion_count = 2
+
+    methods = Object.public_instance_methods.find_all { |n| n =~ /^must|^wont/ }
+    methods.map! { |m| m.to_s } if Symbol === methods.first
+
+    musts, wonts = methods.sort.partition { |m| m =~ /^must/ }
+
+    expected_musts = %w(must_be
+                        must_be_close_to
+                        must_be_empty
+                        must_be_instance_of
+                        must_be_kind_of
+                        must_be_nil
+                        must_be_same_as
+                        must_be_within_delta
+                        must_be_within_epsilon
+                        must_equal
+                        must_include
+                        must_match
+                        must_raise
+                        must_respond_to
+                        must_send
+                        must_throw)
+
+    expected_wonts = expected_musts.map { |m| m.sub(/^must/, 'wont') }
+    expected_wonts.reject! { |m| m =~ /wont_(not|raise|throw|send)/ }
+
+    musts.must_equal expected_musts
+    wonts.must_equal expected_wonts
+  end
+
+  it "needs to verify equality" do
+    (6 * 7).must_equal(42).must_equal true
+    proc { (6 * 9).must_equal(42) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify floats within a delta" do
+    (6.0 * 7).must_be_close_to(42.0).must_equal true
+    proc { 42.002.must_be_close_to 42.0 }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify types of objects" do
+    (6 * 7).must_be_instance_of(Fixnum).must_equal true
+    proc { (6 * 7).must_be_instance_of String }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify kinds of objects" do
+    @assertion_count = 6
+
+    (6 * 7).must_be_kind_of(Fixnum).must_equal true
+    (6 * 7).must_be_kind_of(Numeric).must_equal true
+    proc { (6 * 7).must_be_kind_of String }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify regexp matches" do
+    @assertion_count = 6
+
+    "blah".must_match(/\w+/).must_equal true
+    proc { "blah".must_match(/\d+/) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify nil" do
+    nil.must_be_nil.must_equal true
+    proc { 42.must_be_nil }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify using any operator" do
+    41.must_be(:<, 42).must_equal true
+    proc { 42.must_be(:<, 41) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to catch an expected exception" do
+    @assertion_count = 2
+
+    proc { raise "blah" }.must_raise RuntimeError
+    proc { raise MiniTest::Assertion }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to catch an unexpected exception" do
+    @assertion_count = 2
+
+    proc {
+      proc { raise MiniTest::Assertion }.must_raise(RuntimeError)
+    }.must_raise MiniTest::Assertion
+  end
+
+  it "needs raise if an expected exception is not raised" do
+    @assertion_count = 2
+
+    proc { proc { 42 }.must_raise(RuntimeError) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to be able to catch a MiniTest::Assertion exception" do
+    @assertion_count = 2
+
+    proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify using respond_to" do
+    42.must_respond_to(:+).must_equal true
+    proc { 42.must_respond_to(:clear) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify identity" do
+    1.must_be_same_as(1).must_equal true
+    proc { 1.must_be_same_as 2 }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify throw" do
+    @assertion_count = 6
+
+    proc { throw :blah }.must_throw(:blah).must_equal true
+    proc { proc { }.must_throw(:blah) }.must_raise MiniTest::Assertion
+    proc { proc { throw :xxx }.must_throw(:blah) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify inequality" do
+    42.wont_equal(6 * 9).must_equal false
+    proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify mismatch" do
+    @assertion_count = 6
+    "blah".wont_match(/\d+/).must_equal false
+    proc { "blah".wont_match(/\w+/) }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify non-nil" do
+    42.wont_be_nil.must_equal false
+    proc { nil.wont_be_nil }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to verify non-identity" do
+    1.wont_be_same_as(2).must_equal false
+    proc { 1.wont_be_same_as 1 }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to be sensible about must_include order" do
+    @assertion_count = 6
+    [1, 2, 3].must_include(2).must_equal true
+    proc { [1, 2, 3].must_include 5 }.must_raise MiniTest::Assertion
+  end
+
+  it "needs to be sensible about wont_include order" do
+    @assertion_count = 6
+    [1, 2, 3].wont_include(5).must_equal false
+    proc { [1, 2, 3].wont_include 2 }.must_raise MiniTest::Assertion
+  end
+end


Property changes on: MacRuby/trunk/test/libs/minitest/test/test_mini_spec.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/minitest/test/test_mini_test.rb
===================================================================
--- MacRuby/trunk/test/libs/minitest/test/test_mini_test.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/minitest/test/test_mini_test.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,980 @@
+require 'stringio'
+require 'pathname'
+require 'minitest/unit'
+
+MiniTest::Unit.autorun
+
+module M; end
+class E < StandardError; include M; end
+
+class TestMiniTest < MiniTest::Unit::TestCase
+  def setup
+    srand 42
+    MiniTest::Unit::TestCase.reset
+    @tu = MiniTest::Unit.new
+    @output = StringIO.new("")
+    MiniTest::Unit.output = @output
+    assert_equal [0, 0], @tu.run_test_suites
+  end
+
+  def teardown
+    MiniTest::Unit.output = $stdout
+    Object.send :remove_const, :ATestCase if defined? ATestCase
+  end
+
+  pwd = Pathname.new(File.expand_path(Dir.pwd))
+  basedir = Pathname.new(File.expand_path(MiniTest::MINI_DIR)) + 'mini'
+  basedir = basedir.relative_path_from(pwd).to_s
+  MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}"
+  BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:165:in `run_test_suites'",
+               "#{MINITEST_BASE_DIR}/test.rb:161:in `each'",
+               "#{MINITEST_BASE_DIR}/test.rb:161:in `run_test_suites'",
+               "#{MINITEST_BASE_DIR}/test.rb:158:in `each'",
+               "#{MINITEST_BASE_DIR}/test.rb:158:in `run_test_suites'",
+               "#{MINITEST_BASE_DIR}/test.rb:139:in `run'",
+               "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"]
+
+  def test_filter_backtrace
+    # this is a semi-lame mix of relative paths.
+    # I cheated by making the autotest parts not have ./
+    bt = (["lib/autotest.rb:571:in `add_exception'",
+           "test/test_autotest.rb:62:in `test_add_exception'",
+           "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+          BT_MIDDLE +
+          ["#{MINITEST_BASE_DIR}/test.rb:29",
+           "test/test_autotest.rb:422"])
+    bt = util_expand_bt bt
+
+    ex = ["lib/autotest.rb:571:in `add_exception'",
+          "test/test_autotest.rb:62:in `test_add_exception'"]
+    ex = util_expand_bt ex
+
+    fu = MiniTest::filter_backtrace(bt)
+
+    assert_equal ex, fu
+  end
+
+  def util_expand_bt bt
+    if RUBY_VERSION =~ /^1\.9/ then
+      bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f }
+    else
+      bt
+    end
+  end
+
+  def test_filter_backtrace_all_unit
+    bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+          BT_MIDDLE +
+          ["#{MINITEST_BASE_DIR}/test.rb:29"])
+    ex = bt.clone
+    fu = MiniTest::filter_backtrace(bt)
+    assert_equal ex, fu
+  end
+
+  def test_filter_backtrace_unit_starts
+    bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+          BT_MIDDLE +
+          ["#{MINITEST_BASE_DIR}/mini/test.rb:29",
+           "-e:1"])
+
+    bt = util_expand_bt bt
+
+    ex = ["-e:1"]
+    fu = MiniTest::filter_backtrace(bt)
+    assert_equal ex, fu
+  end
+
+  def test_class_puke_with_assertion_failed
+    exception = MiniTest::Assertion.new "Oh no!"
+    exception.set_backtrace ["unhappy"]
+    assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception)
+    assert_equal 1, @tu.failures
+    assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+    assert_match("method_name(SomeClass) [unhappy]", @tu.report.first)
+  end
+
+  def test_class_puke_with_failure_and_flunk_in_backtrace
+    exception = begin
+                  MiniTest::Unit::TestCase.new('fake tc').flunk
+                rescue MiniTest::Assertion => failure
+                  failure
+                end
+    assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception)
+    refute @tu.report.any?{|line| line =~ /in .flunk/}
+  end
+
+  def test_class_puke_with_assertion_failed_and_long_backtrace
+    bt = (["test/test_some_class.rb:615:in `method_name'",
+           "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'",
+           "test/test_some_class.rb:615:in `each'",
+           "test/test_some_class.rb:614:in `test_method_name'",
+           "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+          BT_MIDDLE +
+          ["#{MINITEST_BASE_DIR}/test.rb:29"])
+    bt = util_expand_bt bt
+
+    ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first
+
+    exception = MiniTest::Assertion.new "Oh no!"
+    exception.set_backtrace bt
+    assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception)
+    assert_equal 1, @tu.failures
+    assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+    assert_match("test_method_name(TestSomeClass) [#{ex_location}]", @tu.report.first)
+  end
+
+  def test_class_puke_with_assertion_failed_and_user_defined_assertions
+    bt = (["lib/test/my/util.rb:16:in `another_method_name'",
+           "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'",
+           "lib/test/my/util.rb:15:in `block in assert_something'",
+           "lib/test/my/util.rb:14:in `each'",
+           "lib/test/my/util.rb:14:in `assert_something'",
+           "test/test_some_class.rb:615:in `each'",
+           "test/test_some_class.rb:614:in `test_method_name'",
+           "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+          BT_MIDDLE +
+          ["#{MINITEST_BASE_DIR}/test.rb:29"])
+    bt = util_expand_bt bt
+
+    ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first
+
+    exception = MiniTest::Assertion.new "Oh no!"
+    exception.set_backtrace bt
+    assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception)
+    assert_equal 1, @tu.failures
+    assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+    assert_match("test_method_name(TestSomeClass) [#{ex_location}]", @tu.report.first)
+  end
+
+  def test_class_puke_with_flunk_and_user_defined_assertions
+    bt = (["lib/test/my/util.rb:16:in `flunk'",
+           "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raises'",
+           "lib/test/my/util.rb:15:in `block in assert_something'",
+           "lib/test/my/util.rb:14:in `each'",
+           "lib/test/my/util.rb:14:in `assert_something'",
+           "test/test_some_class.rb:615:in `each'",
+           "test/test_some_class.rb:614:in `test_method_name'",
+           "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+          BT_MIDDLE +
+          ["#{MINITEST_BASE_DIR}/test.rb:29"])
+    bt = util_expand_bt bt
+
+    ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first
+
+    exception = MiniTest::Assertion.new "Oh no!"
+    exception.set_backtrace bt
+    assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception)
+    assert_equal 1, @tu.failures
+    assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+    assert_match("test_method_name(TestSomeClass) [#{ex_location}]", @tu.report.first)
+  end
+
+  def test_class_puke_with_non_failure_exception
+    exception = Exception.new("Oh no again!")
+    assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception)
+    assert_equal 1, @tu.errors
+    assert_match(/^Exception.*Oh no again!/m, @tu.report.first)
+  end
+
+  def test_class_run_test_suites
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    assert_equal [1, 1], @tu.run_test_suites
+  end
+
+  def test_run_failing # TODO: add error test
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+
+      def test_failure
+        assert false
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    @tu.run
+
+    expected = "Loaded suite blah
+Started
+F.
+Finished in 0.00
+
+  1) Failure:
+test_failure(ATestCase) [FILE:LINE]:
+Failed assertion, no message given.
+
+2 tests, 2 assertions, 1 failures, 0 errors, 0 skips
+"
+    util_assert_report expected
+  end
+
+  def test_run_error
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+
+      def test_error
+        raise "unhandled exception"
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    @tu.run
+
+    expected = "Loaded suite blah
+Started
+E.
+Finished in 0.00
+
+  1) Error:
+test_error(ATestCase):
+RuntimeError: unhandled exception
+    FILE:LINE:in `test_error'
+
+2 tests, 1 assertions, 0 failures, 1 errors, 0 skips
+"
+    util_assert_report expected
+  end
+
+  def test_run_error_teardown
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+
+      def teardown
+        raise "unhandled exception"
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    @tu.run
+
+    expected = "Loaded suite blah
+Started
+E
+Finished in 0.00
+
+  1) Error:
+test_something(ATestCase):
+RuntimeError: unhandled exception
+    FILE:LINE:in `teardown'
+
+1 tests, 1 assertions, 0 failures, 1 errors, 0 skips
+"
+    util_assert_report expected
+  end
+
+  def test_run_skip
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+
+      def test_skip
+        skip "not yet"
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    @tu.run
+
+    expected = "Loaded suite blah
+Started
+S.
+Finished in 0.00
+
+  1) Skipped:
+test_skip(ATestCase) [FILE:LINE]:
+not yet
+
+2 tests, 1 assertions, 0 failures, 0 errors, 1 skips
+"
+    util_assert_report expected
+  end
+
+  def util_assert_report expected = nil
+    expected ||= "Loaded suite blah
+Started
+.
+Finished in 0.00
+
+1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
+"
+    output = @output.string.sub(/Finished in .*/, "Finished in 0.00")
+    output.sub!(/Loaded suite .*/, 'Loaded suite blah')
+    output.sub!(/^(\s+)(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+:/o, '\1FILE:LINE:')
+    output.sub!(/\[(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+\]/o, '[FILE:LINE]')
+    assert_equal(expected, output)
+  end
+
+  def test_run_failing_filtered
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+
+      def test_failure
+        assert false
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    @tu.run(%w(-n /something/))
+
+    util_assert_report
+  end
+
+  def test_run_passing
+    tc = Class.new(MiniTest::Unit::TestCase) do
+      def test_something
+        assert true
+      end
+    end
+
+    Object.const_set(:ATestCase, tc)
+
+    @tu.run
+
+    util_assert_report
+  end
+end
+
+class TestMiniTestTestCase < MiniTest::Unit::TestCase
+  def setup
+    MiniTest::Unit::TestCase.reset
+
+    @tc = MiniTest::Unit::TestCase.new 'fake tc'
+    @zomg = "zomg ponies!"
+    @assertion_count = 1
+  end
+
+  def teardown
+    assert_equal(@assertion_count, @tc._assertions,
+                 "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc._assertions
+    Object.send :remove_const, :ATestCase if defined? ATestCase
+  end
+
+  def test_class_inherited
+    @assertion_count = 0
+
+    Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase))
+
+    assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites
+  end
+
+  def test_class_test_suites
+    @assertion_count = 0
+
+    Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase))
+
+    assert_equal 1, MiniTest::Unit::TestCase.test_suites.size
+    assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites
+  end
+
+  def test_class_asserts_match_refutes
+    @assertion_count = 0
+
+    methods = MiniTest::Assertions.public_instance_methods
+    methods.map! { |m| m.to_s } if Symbol === methods.first
+
+    ignores = %w(assert_block assert_no_match assert_not_equal assert_not_nil
+                 assert_not_same assert_nothing_thrown assert_raise
+                 assert_nothing_raised assert_raises assert_throws assert_send)
+    asserts = methods.grep(/^assert/).sort - ignores
+    refutes = methods.grep(/^refute/).sort - ignores
+
+    assert_empty refutes.map { |n| n.sub(/^refute/, 'assert') } - asserts
+    assert_empty asserts.map { |n| n.sub(/^assert/, 'refute') } - refutes
+  end
+
+  def test_assert
+    @assertion_count = 2
+
+    @tc.assert_equal true, @tc.assert(true), "returns true on success"
+  end
+
+  def test_assert__triggered
+    util_assert_triggered "Failed assertion, no message given." do
+      @tc.assert false
+    end
+  end
+
+  def test_assert__triggered_message
+    util_assert_triggered @zomg do
+      @tc.assert false, @zomg
+    end
+  end
+
+  def test_assert_block
+    @tc.assert_block do
+      true
+    end
+  end
+
+  def test_assert_block_triggered
+    util_assert_triggered 'Expected block to return true value.' do
+      @tc.assert_block do
+        false
+      end
+    end
+  end
+
+  def test_assert_empty
+    @assertion_count = 2
+
+    @tc.assert_empty []
+  end
+
+  def test_assert_empty_triggered
+    @assertion_count = 2
+
+    util_assert_triggered "Expected [1] to be empty." do
+      @tc.assert_empty [1]
+    end
+  end
+
+  def test_assert_equal
+    @tc.assert_equal 1, 1
+  end
+
+  def test_assert_equal_different
+    util_assert_triggered "Expected 1, not 2." do
+      @tc.assert_equal 1, 2
+    end
+  end
+
+  def test_assert_in_delta
+    @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1
+  end
+
+  def test_assert_in_delta_triggered
+    util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to be < 1.0e-06.' do
+      @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001
+    end
+  end
+
+  def test_assert_in_epsilon
+    @assertion_count = 8
+
+    @tc.assert_in_epsilon 10000, 9991
+    @tc.assert_in_epsilon 9991, 10000
+    @tc.assert_in_epsilon 1.0, 1.001
+    @tc.assert_in_epsilon 1.001, 1.0
+
+    @tc.assert_in_epsilon 10000, 9999.1, 0.0001
+    @tc.assert_in_epsilon 9999.1, 10000, 0.0001
+    @tc.assert_in_epsilon 1.0, 1.0001, 0.0001
+    @tc.assert_in_epsilon 1.0001, 1.0, 0.0001
+  end
+
+  def test_assert_in_epsilon_triggered
+    util_assert_triggered 'Expected 10000 - 9990 (10) to be < 9.99.' do
+      @tc.assert_in_epsilon 10000, 9990
+    end
+  end
+
+  def test_assert_includes
+    @assertion_count = 2
+
+    @tc.assert_includes [true], true
+  end
+
+  def test_assert_includes_triggered
+    @assertion_count = 3
+
+    e = @tc.assert_raises MiniTest::Assertion do
+      @tc.assert_includes [true], false
+    end
+
+    expected = "Expected [true] to include false."
+    assert_equal expected, e.message
+  end
+
+  def test_assert_instance_of
+    @tc.assert_instance_of String, "blah"
+  end
+
+  def test_assert_instance_of_triggered
+    util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do
+      @tc.assert_instance_of Array, "blah"
+    end
+  end
+
+  def test_assert_kind_of
+    @tc.assert_kind_of String, "blah"
+  end
+
+  def test_assert_kind_of_triggered
+    util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do
+      @tc.assert_kind_of Array, "blah"
+    end
+  end
+
+  def test_assert_match
+    @assertion_count = 2
+    @tc.assert_match(/\w+/, "blah blah blah")
+  end
+
+  def test_assert_match_object
+    @assertion_count = 2
+
+    pattern = Object.new
+    def pattern.=~(other) true end
+
+    @tc.assert_match pattern, 5
+  end
+
+  def test_assert_match_object_triggered
+    @assertion_count = 2
+
+    pattern = Object.new
+    def pattern.=~(other) false end
+    def pattern.inspect; "<<Object>>" end
+
+    util_assert_triggered 'Expected <<Object>> to match 5.' do
+      @tc.assert_match pattern, 5
+    end
+  end
+
+  def test_assert_match_triggered
+    @assertion_count = 2
+    util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do
+      @tc.assert_match(/\d+/, "blah blah blah")
+    end
+  end
+
+  def test_assert_nil
+    @tc.assert_nil nil
+  end
+
+  def test_assert_nil_triggered
+    util_assert_triggered 'Expected 42 to be nil.' do
+      @tc.assert_nil 42
+    end
+  end
+
+  def test_assert_operator
+    @tc.assert_operator 2, :>, 1
+  end
+
+  def test_assert_operator_triggered
+    util_assert_triggered "Expected 2 to be < 1." do
+      @tc.assert_operator 2, :<, 1
+    end
+  end
+
+  def test_assert_raises
+    @tc.assert_raises RuntimeError do
+      raise "blah"
+    end
+  end
+
+  def test_assert_raises_module
+    @tc.assert_raises M do
+      raise E
+    end
+  end
+
+  def test_assert_raises_triggered_different
+    e = assert_raises MiniTest::Assertion do
+      @tc.assert_raises RuntimeError do
+        raise SyntaxError, "icky"
+      end
+    end
+
+    expected = "[RuntimeError] exception expected, not
+Class: <SyntaxError>
+Message: <\"icky\">
+---Backtrace---
+FILE:LINE:in `test_assert_raises_triggered_different'
+---------------"
+
+    actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+    actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/
+
+    assert_equal expected, actual
+  end
+
+  def test_assert_raises_triggered_none
+    e = assert_raises MiniTest::Assertion do
+      @tc.assert_raises MiniTest::Assertion do
+        # do nothing
+      end
+    end
+
+    expected = "MiniTest::Assertion expected but nothing was raised."
+
+    assert_equal expected, e.message
+  end
+
+  def test_assert_raises_triggered_subclass
+    e = assert_raises MiniTest::Assertion do
+      @tc.assert_raises StandardError do
+        raise E
+      end
+    end
+
+    expected = "[StandardError] exception expected, not
+Class: <E>
+Message: <\"E\">
+---Backtrace---
+FILE:LINE:in `test_assert_raises_triggered_subclass'
+---------------"
+
+    actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+    actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/
+
+    assert_equal expected, actual
+  end
+
+  def test_assert_respond_to
+    @tc.assert_respond_to "blah", :empty?
+  end
+
+  def test_assert_respond_to_triggered
+    util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do
+      @tc.assert_respond_to "blah", :rawr!
+    end
+  end
+
+  def test_assert_same
+    @assertion_count = 3
+
+    o = "blah"
+    @tc.assert_same 1, 1
+    @tc.assert_same :blah, :blah
+    @tc.assert_same o, o
+  end
+
+  def test_assert_same_triggered
+    @assertion_count = 2
+
+    util_assert_triggered 'Expected 2 (0xXXX) to be the same as 1 (0xXXX).' do
+      @tc.assert_same 1, 2
+    end
+
+    s1 = "blah"
+    s2 = "blah"
+
+    util_assert_triggered 'Expected "blah" (0xXXX) to be the same as "blah" (0xXXX).' do
+      @tc.assert_same s1, s2
+    end
+  end
+
+  def test_assert_send
+    @tc.assert_send [1, :<, 2]
+  end
+
+  def test_assert_send_bad
+    util_assert_triggered "Expected 1.>(*[2]) to return true." do
+      @tc.assert_send [1, :>, 2]
+    end
+  end
+
+  def test_assert_throws
+    @tc.assert_throws(:blah) do
+      throw :blah
+    end
+  end
+
+  def test_assert_throws_different
+    util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do
+      @tc.assert_throws(:blah) do
+        throw :not_blah
+      end
+    end
+  end
+
+  def test_assert_throws_unthrown
+    util_assert_triggered 'Expected :blah to have been thrown.' do
+      @tc.assert_throws(:blah) do
+        # do nothing
+      end
+    end
+  end
+
+  def test_capture_io
+    @assertion_count = 0
+
+    out, err = capture_io do
+      puts 'hi'
+      warn 'bye!'
+    end
+
+    assert_equal "hi\n", out
+    assert_equal "bye!\n", err
+  end
+
+  def test_flunk
+    util_assert_triggered 'Epic Fail!' do
+      @tc.flunk
+    end
+  end
+
+  def test_flunk_message
+    util_assert_triggered @zomg do
+      @tc.flunk @zomg
+    end
+  end
+
+  def test_message
+    @assertion_count = 0
+
+    assert_equal "blah2.",         @tc.message { "blah2" }.call
+    assert_equal "blah2.",         @tc.message("") { "blah2" }.call
+    assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call
+  end
+
+  def test_pass
+    @tc.pass
+  end
+
+  def test_test_methods_sorted
+    @assertion_count = 0
+
+    sample_test_case = Class.new(MiniTest::Unit::TestCase)
+
+    class << sample_test_case
+      def test_order; :sorted end
+    end
+
+    sample_test_case.instance_eval do
+      define_method :test_test3 do assert "does not matter" end
+      define_method :test_test2 do assert "does not matter" end
+      define_method :test_test1 do assert "does not matter" end
+    end
+
+    expected = %w(test_test1 test_test2 test_test3)
+    assert_equal expected, sample_test_case.test_methods
+  end
+
+  def test_test_methods_random
+    @assertion_count = 0
+
+    sample_test_case = Class.new(MiniTest::Unit::TestCase)
+
+    class << sample_test_case
+      def test_order; :random end
+    end
+
+    sample_test_case.instance_eval do
+      define_method :test_test1 do assert "does not matter" end
+      define_method :test_test2 do assert "does not matter" end
+      define_method :test_test3 do assert "does not matter" end
+    end
+
+    srand 42
+    expected = %w(test_test1 test_test2 test_test3)
+    max = expected.size
+    expected = expected.sort_by { rand(max) }
+
+    srand 42
+    result = sample_test_case.test_methods
+
+    assert_equal expected, result
+  end
+
+  def test_refute
+    @assertion_count = 2
+
+    @tc.assert_equal false, @tc.refute(false), "returns false on success"
+  end
+
+  def test_refute_empty
+    @assertion_count = 2
+
+    @tc.refute_empty [1]
+  end
+
+  def test_refute_empty_triggered
+    @assertion_count = 2
+
+    util_assert_triggered "Expected [] to not be empty." do
+      @tc.refute_empty []
+    end
+  end
+
+  def test_refute_equal
+    @tc.refute_equal "blah", "yay"
+  end
+
+  def test_refute_equal_triggered
+    util_assert_triggered 'Expected "blah" to not be equal to "blah".' do
+      @tc.refute_equal "blah", "blah"
+    end
+  end
+
+  def test_refute_in_delta
+    @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001
+  end
+
+  def test_refute_in_delta_triggered
+    util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to not be < 0.1.' do
+      @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1
+    end
+  end
+
+  def test_refute_in_epsilon
+    @tc.refute_in_epsilon 10000, 9990
+  end
+
+  def test_refute_in_epsilon_triggered
+    util_assert_triggered 'Expected 10000 - 9991 (9) to not be < 10.0.' do
+      @tc.refute_in_epsilon 10000, 9991
+      fail
+    end
+  end
+
+  def test_refute_includes
+    @assertion_count = 2
+
+    @tc.refute_includes [true], false
+  end
+
+  def test_refute_includes_triggered
+    @assertion_count = 3
+
+    e = @tc.assert_raises MiniTest::Assertion do
+      @tc.refute_includes [true], true
+    end
+
+    expected = "Expected [true] to not include true."
+    assert_equal expected, e.message
+  end
+
+  def test_refute_instance_of
+    @tc.refute_instance_of Array, "blah"
+  end
+
+  def test_refute_instance_of_triggered
+    util_assert_triggered 'Expected "blah" to not be an instance of String.' do
+      @tc.refute_instance_of String, "blah"
+    end
+  end
+
+  def test_refute_kind_of
+    @tc.refute_kind_of Array, "blah"
+  end
+
+  def test_refute_kind_of_triggered
+    util_assert_triggered 'Expected "blah" to not be a kind of String.' do
+      @tc.refute_kind_of String, "blah"
+    end
+  end
+
+  def test_refute_match
+    @assertion_count = 2
+    @tc.refute_match(/\d+/, "blah blah blah")
+  end
+
+  def test_refute_match_object
+    @assertion_count = 2
+    @tc.refute_match Object.new, 5 # default #=~ returns false
+  end
+
+  def test_assert_object_triggered
+    @assertion_count = 2
+
+    pattern = Object.new
+    def pattern.=~(other) false end
+    def pattern.inspect; "<<Object>>" end
+
+    util_assert_triggered 'Expected <<Object>> to match 5.' do
+      @tc.assert_match pattern, 5
+    end
+  end
+
+  def test_refute_match_object_triggered
+    @assertion_count = 2
+
+    pattern = Object.new
+    def pattern.=~(other) true end
+    def pattern.inspect; "<<Object>>" end
+
+    util_assert_triggered 'Expected <<Object>> to not match 5.' do
+      @tc.refute_match pattern, 5
+    end
+  end
+
+  def test_refute_match_triggered
+    @assertion_count = 2
+    util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do
+      @tc.refute_match(/\w+/, "blah blah blah")
+    end
+  end
+
+  def test_refute_nil
+    @tc.refute_nil 42
+  end
+
+  def test_refute_nil_triggered
+    util_assert_triggered 'Expected nil to not be nil.' do
+      @tc.refute_nil nil
+    end
+  end
+
+  def test_refute_operator
+    @tc.refute_operator 2, :<, 1
+  end
+
+  def test_refute_operator_triggered
+    util_assert_triggered "Expected 2 to not be > 1." do
+      @tc.refute_operator 2, :>, 1
+    end
+  end
+
+  def test_refute_respond_to
+    @tc.refute_respond_to "blah", :rawr!
+  end
+
+  def test_refute_respond_to_triggered
+    util_assert_triggered 'Expected "blah" to not respond to empty?.' do
+      @tc.refute_respond_to "blah", :empty?
+    end
+  end
+
+  def test_refute_same
+    @tc.refute_same 1, 2
+  end
+
+  # TODO: "with id <id>" crap from assertions.rb
+  def test_refute_same_triggered
+    util_assert_triggered 'Expected 1 to not be the same as 1.' do
+      @tc.refute_same 1, 1
+    end
+  end
+
+  def test_skip
+    @assertion_count = 0
+
+    util_assert_triggered "haha!", MiniTest::Skip do
+      @tc.skip "haha!"
+    end
+  end
+
+  def util_assert_triggered expected, klass = MiniTest::Assertion
+    e = assert_raises(klass) do
+      yield
+    end
+
+    msg = e.message.sub(/(---Backtrace---).*/m, '\1')
+    msg.gsub!(/\(0x[0-9a-f]+\)/, '(0xXXX)')
+
+    assert_equal expected, msg
+  end
+end


Property changes on: MacRuby/trunk/test/libs/minitest/test/test_mini_test.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/.autotest
===================================================================
--- MacRuby/trunk/test/libs/rubygems/.autotest	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/.autotest	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,24 @@
+# -*- ruby -*-
+
+require 'autotest/restart'
+
+Autotest.add_hook :initialize do |at|
+  at.order = :natural # I am a bad person - Eric Hodel
+  at.testlib = 'minitest/unit' if at.respond_to? :testlib=
+
+  at.add_exception %r%/\.svn/%
+  at.add_exception %r%\.rbc$%
+  at.add_exception %r%test/rubygems%
+
+  at.find_directories.clear
+  at.find_directories.push 'lib', 'test'
+
+  at.add_mapping %r%^lib/rubygems.rb$% do |_, m|
+    "test/test_gem.rb"
+  end
+
+  at.add_mapping %r%^lib/rubygems/(.*).rb$% do |_, m|
+    "test/test_gem_#{m[1].gsub '/', '_'}.rb"
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/.document
===================================================================
--- MacRuby/trunk/test/libs/rubygems/.document	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/.document	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,5 @@
+README
+LICENSE.txt
+GPL.txt
+lib
+release_notes

Added: MacRuby/trunk/test/libs/rubygems/ChangeLog
===================================================================
--- MacRuby/trunk/test/libs/rubygems/ChangeLog	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/ChangeLog	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,5582 @@
+# -*- coding: utf-8 -*-
+
+2009-09-03  John Barnette  <jbarnette at rubyforge.org>
+
+	* LOTS: Use "raise" consistently, not "fail".
+
+2009-09-01  John Barnette  <jbarnette at rubyforge.org>
+
+	* lib/rubygems/version.rb: Gem::Version immutability
+	burndown. Changed canonical internal representation to an
+	Array. Refactored significant amounts of the internals for
+	clarity. Breaking change: Gem::Version::Requirement is no longer
+	available, use Gem::Requirement instead. Breaking change: custom
+	YAML marshaling is gone. Credit to Yehuda Katz for certain bits of
+	a related patch.
+	* test/test_gem_dependency.rb: Moved a bunch of tests over from
+	test_gem_version.rb. Work in progress.
+	* test/test_gem_specification.rb: Removed a failing YAML
+	test. Many more will be going away shortly.
+	* test/test_gem_version.rb: Significant refactoring for
+	maintainability and clarity. Moved a ton of poorly-placed tests to
+	test_gem_dependency.rb for future refactoring.
+
+2009-08-19  Ryan Davis  <ryand-ruby at zenspider.com>
+
+	* lib/rubygems.rb: Cleanup of rdoc and file layout.
+	* lib/rubygems/versions.rb: Added Version#spermy_recommendation
+	and fixed bug in Version::Part#inspect. General cleanup.
+
+2009-07-29  John Barnette <jbarnette at rubyforge.org>
+
+	* lib/rubygems/package/tar_input.rb:  Add Maglev to the list of
+	  implementations with working Zlib. Bug #26790 by Peter McLain.
+
+2009-07-21  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/package.rb:  Remove dangling digest require.  Reported
+	  by Jeremy Kemper.
+
+2009-06-25  Eric Hodel  <drbrain at segment7.net>
+
+	* release_notes/:  Merged into History.txt for Hoe.
+	* lib/rubygems/commands/setup_command.rb:  Streamlined install text.
+
+2009-06-23  Eric Hodel  <drbrain at segment7.net>
+
+	* release_notes/rel_1_3_5.rdoc:  RubyGems 1.3.5 release notes.
+	* lib/rubygems/builder.rb:  Only print out with verbose.
+	* lib/rubygems/package_task.rb:  Only print out with -t.
+
+2009-06-12  Ryan Davis  <ryand at zenspider.com>
+
+	* Rakefile:  Switched to Hoe.
+
+2009-06-10  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems/installer.rb:  --user-install is no longer enabled by
+	  default.
+	* lib/rubygems/source_index.rb:  Fix use of prerelease gems.
+
+2009-06-04  Eric Hodel  <drbrain at segment7.net>
+
+	* util/gem_prelude.rb.template:  Backports from 1.9.
+
+2009-06-03  Eric Hodel  <drbrain at segment7.net>
+
+	* bin/gem:  Support 1.8.6+
+	* lib/rubygems/digest*:  Removed, support dropped for Ruby < 1.8.6
+	* lib/rubygems/installer.rb:  Support env(1) in wrong path, use
+	  /bin/sh if shebang has options.  By Nobu, ruby trunk r22853.
+	* lib/rubygems/config_file.rb:  Switch to stdcall for appdata folder.
+	  [ruby-core:22601].
+	* lib/rubygems.rb:  Use only File::expand_path on 1.9 for home dir.
+	  Don't recklessly create directories.  Simplify RbConfig::datadir
+	  definition.
+
+2009-05-30  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/which_command.rb:  Only print out directory
+	  information to a TTY.
+	* lib/rubygems/rubygems_version.rb:  1.3.4.
+	* doc/release_notes/rel_1_3_4.rdoc:  RubyGems 1.3.4 release notes.
+
+2009-05-28  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/setup_command.rb:  Fix --format-executable
+	  option name.
+	* lib/rubygems/requirement.rb:  Fix typo in #parse.  Bug #26000 by
+	  Mike Gunderloy.
+
+2009-05-21  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Add 'dev' and svn revision for -1 RUBY_PATCHLEVEL
+	  and RUBY_REVISION.
+
+2009-05-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/defaults.rb:  Restore 1.9.1 path behavior.
+	* lib/rubygems/specification.rb:  Fix undefined ivar warning.
+	* lib/rubygems/indexer.rb:  Force loading of builder gem.
+	* test/gemutilities.rb:  Remove gem_prelude code by hand to avoid 1.9
+	  warnings.
+
+2009-05-19  Luis Lavena  <luislavena at gmail.com>
+
+	* test/test_gem_specification.rb: skip symlinks tests on Windows.
+	* test/test_gem_commands_install_command.rb: skip chmod test on
+	  Windows.
+
+2009-05-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems*:  Fix 1.9 warnings about circular require.
+
+2009-05-12  Daniel Berger  <djberg96 at gmail.com>
+
+	* lib/rubygems/remote_fetcher.rb:  Fixed the download method in the
+	  remote_fetcher.rb file so that it handles local installs on MS
+	  Windows when using explicit paths that aren't on the 'C:' drive.
+	  Bug #25882 by Lars Christensen.
+	* lib/rubygems/commands/update_command.rb:  Replaced deprecated
+	  Gem::SourceIndex method 'search' with 'find_name' in the 'execute'
+	  method.
+
+2009-05-07  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/query_command.rb:  Support prerelease version
+	  listing (--prerelease), list locally installed prereleases.
+	* lib/rubygems/source_info_cache.rb:  Gem::SourceInfoCache is
+	  officially unsupported, maintaining its tests is hard.
+	* lib/rubygems/source_index.rb:  Add #all_gems, fix #remove_spec,
+	  #search to work with it.  Prerelease gems can now be used.
+
+2009-05-04  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb: 1.3.3.
+	* doc/release_notes/rel_1_3_3.rdoc:  RubyGems 1.3.3 release notes.
+	* lib/rubygems/specification.rb:  Default has_rdoc to true, ignore
+	  its value.
+	* lib/rubygems/doc_manager.rb:  Always generate RDoc regardless of
+	  #has_rdoc?
+	* lib/rubygems.rb:  Raise Gem::LoadError if Kernel#gem fails due to
+	  previously-loaded gem.  Bug reported by Alf Mikula.
+
+2009-05-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/server_command.rb:  Allow port names with
+	  --port.
+	* lib/rubygems/requirement.rb:  Match prerelease versions and ~>
+	  correctly.  Patch #25759 by Yossef Mendelssohn.
+
+2009-05-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Check bindir for executables, not
+	  root.  Bug reported by David Chelimsky.  Remove Time.today, no way
+	  to override it before RubyGems loads.  Bug #25564 by Emanuele
+	  Vicentini.  Raise Gem::Exception for #installation_path when not
+	  installed.  Bug #25741 by Daniel Berger.  Don't error in #validate
+	  when homepage is nil.  Bug #25677 by Mike Burrows.
+	* lib/rubygems/commands/cleanup_command.rb:  Clean up --user-install
+	  gems.  Bug #25516 by Brett Eisenberg.
+	* lib/rubygems/uninstaller.rb:  Uninstall executables from the correct
+	  directory.  Bug #25555 by Brett Eisenberg.
+	* lib/rubygems/server.rb:  Add search that jumps to RDoc.  Patch
+	  #22959 by Vladimir Dobriakov.
+
+2009-05-01  James Tucker  <jftucker at gmail.com>
+
+	* lib/rubygems.rb: Gem.bin_path now escapes paths with spaces.
+
+2009-04-30  Daniel Berger  <djberg96 at gmail.com>
+
+	* lib/rubygems/commands/install_command.rb:  Replaced deprecated
+	  Gem::SourceIndex method 'search' with 'find_name' when using
+	  the -t option. Fixes bug # 25632 by Daniel Berger.
+
+2009-04-30  James Tucker  <jftucker at gmail.com>
+
+	* lib/rubygems/ext/rake_builder.rb: Use explicit ruby command loading
+	  rubygems to invoke rake.
+
+2009-04-24  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/specification_command.rb:  Added requesting
+	  single fields from a spec.
+
+2009-04-23  James Tucker  <jftucker at gmail.com>
+
+	* lib/rubygems/ext/configure_builder.rb: Support Gem::Command.build_args.
+
+2009-04-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb: 1.3.2.
+
+2009-04-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Complain when summary and
+	  description are identical.
+
+2009-04-08  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Strip directories, complain for
+	  non-files in #validate.
+
+2009-04-07  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Implement #initialize_copy.
+	* lib/rubygems/commands/contents_command.rb:  Add --no-prefix and
+	  --all.
+
+2009-04-06  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/defaults.rb:  Don't allow gem to overwrite ruby on
+	  install.  Fixes bug #24958 by Michael Soulier.
+	* doc/release_notes/rel_1_3_2.rdoc:  Preliminary 1.3.2 release notes.
+	* Rakefile:  Trim off some stale code, switch to Manifest.txt, one
+	  step closer to Hoe!
+
+2009-04-06  Daniel Berger  <djberg96 at gmail.com>
+
+	* test/test_gem_ext_configure_builder.rb: Better handling for MS
+	  Windows.
+	* test/gemutilities.rb: Added the make_command and vc_windows? helper
+	  methods.
+
+2009-04-03  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/: RDoc improvements.
+
+2009-04-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/setup_command.rb:  Fix --destdir.  Patch
+	  #24970 by Richard Brown.
+
+2009-04-02  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems/version.rb: Documentation of prerelease
+	versions. See http://technomancy.us/123 for details.
+
+2009-03-31  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/spec_fetcher.rb:  If the cached specs file won't load,
+	  refetch.  Bug #24961 by Dylan Stamat.
+	* lib/rubygems/defaults.rb:  Add a sanity check to
+	  Gem.default_exec_format.  Workaround for bug #24958 by Michael
+	  Soulier.
+	* lib/rubygems/commands/setup_command.rb:  Fix confusion with option
+	  names.  Patch #24971 by Richard Brown.
+	* lib/rubygems/specification.rb:  Make #validate complain about
+	  not-files.
+	* lib/gauntlet_rubygems.rb:  For verification of the validator.
+
+2009-03-27  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  RubyGems now loads plugins from rubygems_plugin.rb
+	  in installed gems.  This can be used to add commands (See
+	  Gem::CommandManager) or add install/uninstall hooks (See
+	  Gem::Installer and Gem::Uninstaller).
+	* setup.rb:  Ensure we're in a RubyGems dir when installing.
+
+2009-03-26  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/package_task.rb:  Import from Rake's
+	  rake/gempackagetask.rb
+	* Rakefile:  Switched to RDoc::Task from RDoc 2.4.2.
+	* lib/rubygems.rb:  Gem.find_files now returns paths in $LOAD_PATH.
+	* lib/rubygems/commands/sources_command.rb:  Allow sources to be added
+	  behind proxies.  Bug #24785 by Elia Schito.
+
+2009-03-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/install_command.rb:  Fix typo.  Patch #24446
+	  by Luis Parravicini.
+	* lib/rubygems/version.rb:  Handle non-String versions by calling
+	  #to_s.  Patch #24392 by Stephen Bannasch.
+
+2009-03-22  Daniel Berger <djberg96 at gmail.com>
+
+	* lib/rubygems/remote_fetcher.rb: Always escape URI's to deal with spaces
+	  and such, regardless of platform.
+	* lib/rubygesm/validator.rb: Use the test-unit gem if installed.
+	  Part of the fix for RF #24261 by Daniel Berger
+	* lib/rubygems/commands/install_command.rb: Explictly require
+	  rubygems/uninstaller.rb if the user wants to bail because of failed
+	  tests.
+	  Part of the fix for RF #24261 by Daniel Berger
+
+2009-03-17  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/query_command.rb:  Make `gem unpack` work with
+	  more than one gem name, fix warning about installation location.
+
+2009-03-16  James Tucker <jftucker at gmail.com>
+
+	* lib/rubygems.rb: Deprecate ConfigMap[:RUBY_INSTALL_NAME]
+	* lib/rubygems/defaults.rb: Gem.default_exec_format to use 
+		ConfigMap[:ruby_install_name].
+		Fixes Bug #24457
+	* util/gem_prelude.rb.template: Fix potential bug in
+	  Gem.default_exec_format when ConfigMap[:BASERUBY] is not 'ruby'.
+
+2009-03-14  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems/installer.rb: Cleanup quotes on Windows stub scripts.
+	  Fixes Bug #24039.
+	* lib/rubygems/commands/setup_command.rb: ditto.
+
+2008-03-13  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/uninstall_command.rb:  Add --user-install to
+	  allow uninstallation from ~/.gem.  Bug #23760 by Roger Pack.
+	* lib/rubygems/uninstaller.rb:  Automatically uninstall from
+	  Gem.user_dir.
+	* lib/rubygems/commands/update_command.rb:  Rescue InstallError
+	  and continue.  Bug #19268 by Gabriel Wilkins.
+	* lib/rubygems/doc_manager.rb:  Remove some options from the args list
+	  that RDoc no longer supports.
+
+2008-03-12  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  #description no longer removes
+	  newlines.
+	* lib/rubygems/indexer.rb:  Wrap description in a pre and force-wrap
+	  lines to 78 characters for prettier display.
+	* lib/rubygems/commands/setup_command.rb:  Clarify RubyGems RDoc
+	  installation location.  Bug #22656 by Gian Marco Gherardi.
+
+2008-03-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/query_command.rb:  Add platforms to gem list
+	  -d.
+	* lib/rubygems/commands/setup_command.rb:  Allow setup to run from
+	  read-only location.  Patch #21862 by Luis Herrera.
+	* lib/rubygems/package/tar_input.rb:  Use real File methods.  Bug
+	  #23966 by Mike Furr.
+	* lib/rubygems.rb:  Don't add PATCHLEVEL if it's -1.  Patch #24048 by
+	  Jeremy Kemper.
+	* lib/rubygems/package/tar_input.rb:  Choose security policy
+	  correctly.  Bug #24001 by Mike Furr.
+	* lib/rubygems/remote_fetcher.rb:  Handle local paths with spaces.
+	  Bug #24169 by Ryan Davis.
+	* lib/rubygems/specification.rb:  Removed Gem::Specification::list,
+	  causes leaks.  Bug #23668 by Steve Purcell.
+
+2008-03-07  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Use Gem::bin_path in executable stubs to
+	  work around Kernel#load bug.
+	* lib/rubygems/commands/install_command.rb:  Copy user_install down to
+	  Gem::DependencyInstaller.  Patch #23573 by Alf Mikula.
+	* lib/rubygems/command.rb:  Add info on gem server directly to `gem
+	  help`.  Patch #22271 by Hugh Sasse.
+
+2008-03-06  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Don't allow FIXME in specs.
+	* lib/rubygems/commands/spec_command.rb:  Add --ruby and --marshal
+	  formats.
+	* lib/rubygems.rb:  Add Gem::bin_path.  Patch #24114 by James Tucker.
+
+2008-03-04  Eric Hodel  <drbrain at segment7.net>
+
+	* setup.rb:  Moved guts to lib/rubygems/commands/setup_command.rb.
+	* lib/rubygems/indexer.rb:  Added RSS feed generation on full index
+	  update.
+
+2008-03-04  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/*: Prerelease gems go into their own index now and are excluded
+	from other indices. InstallCommand only gets prereleases if explicitly
+	requested. Thanks to Alex Vollmer.
+
+2008-03-04  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/*: Add lots of pretty pretty_print stuff!
+
+2008-02-25  Ryan Davis  <ryand at zenspider.com>
+
+	* lib/rubygems/commands/check_command.rb:  Fix various usability
+	  issues.
+
+2009-02-10  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/specification: Refactored and fixed the installation_path
+	method. It was overwrought and it now no longer uses File::SEPARATOR
+	explicitly.
+	[RubyForge: bug #23879 by Daniel Berger]
+
+2009-02-10  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/validator.rb: The Gem::Validator#verify_gem_file method
+	now explicitly rescues Errno::EINVAL as well as Errno::ENOENT because
+	MS Windows raises a different SystemCallError for empty paths.
+	
+2009-01-21  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/remote_fetcher.rb: Split out nil and file handling in
+	the download method. Modified file URI handling to work properly.
+	[RubyForge: bug #16495 by Paul Sadauskas]
+	
+2009-01-19  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/remote_fetcher.rb: Added uri scheme validation back
+	into the open_uri_or_path method, though it now accepts 'https' and
+	'file' as well.
+	* test/test_gem_remote_fetcher.rb: Updated the test_fetch_size_bad_uri
+	to reflect the updated error message.
+
+2009-01-15  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/remote_fetcher.rb: Removed the open_file_uri_path method
+	since the URI#path method already does the same thing, and changed
+	the file_uri? method so that it explicitly calls .to_s.
+	* lib/rubygems/local_remote_options.rb: Allow file urls.
+
+2009-01-15  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/commands/generate_index_command.rb: Fixed a typo in
+	the description.
+	* test/test_gem_doc_manager.rb: The test_uninstall_doc_unwritable
+	test is now skipped on Windows.
+	* test/test_gem_install_update_options.rb: The
+	test_user_install_disabled_read_only test is now skipped on Windows.
+	* test/test_gem_installer.rb: The test_generate_bin_symlink_no_perms
+	and test_generate_bin_script_no_perms tests are now skipped on Windows.
+
+2009-01-14  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/specification.rb: Added support for a license attribute.
+	[RubyForge: feature #11041 (partial) by Kevin Williams]
+	* lib/rubygems/commands/query_command.rb: Gem detail information now
+	includes license information.
+	* test/test_gem_specification.rb: Added tests for the license attribute.
+
+2009-01-05  Chad Woolley <thewoolleyman at gmail.com>
+
+	* move processing of build args out of gem binary so they are handled correctly via API usage.
+	* lib/rubygems/command.rb: Add class accessor for build_args.
+	* lib/rubygems/ext/rake_builder.rb: Use Gem::Command.build_args instead of ARGV.
+	* lib/rubygems/ext/ext_conf_builder.rb: Use Gem::Command.build_args instead of ARGV.
+	* lib/rubygems/gem_runner.rb: Move build arg processing from gem binary.
+	* lib/rubygems/commands/contents_command.rb: Use nonzero return code (required to make tests pass).
+	* bin/gem: Move build arg processing to gem_runner.rb.
+	[RubyForge: bug #23210]
+
+	* lib/rubygems/config_file.rb:  Fix --config-file option with no
+	equals and subsequent options to properly assign config file.
+	Previously config file was overwritten by subsequent option.
+	Fixes bug #16688.
+
+2009-1-4  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/installer.rb: Remove existing path if it already
+	exists before installing.
+	[RubyForge: patch #22837 by Eric Wong]
+	* lib/rubygems.rb: Minor modification to the location_of_caller
+	method - deal with possible characters after line number
+
+2009-1-3  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems.rb: Better activation error message.
+	[RubyForge: patch #23082 by Tim Carey-Smith]
+
+2009-1-2  Daniel Berger <djberg96 at gmail.com>
+	* lib/rubygems/ext/rake_builder.rb: Quote path if it contains spaces
+	[RubyForge: patch #23003 by Charlie Savage]
+	* lib/rubygems/local_remote_options.rb: Ignore duplicate sources
+	[RubyForge: bug #22277 by Elliot Temple]
+	* lib/rubygems/remote_fetcher.rb: Automatically normalize the URI
+	[RubyForge: bug #22151 by Alex Legler]
+	* lib/rubygems/specification.rb: Ensure that specification_version is
+	a Fixnum [RubyForge: bug #22598 by Tsutomu Kuroda]
+	* lib/rubygems/specification.rb: Bumped the CURRENT_SPECIFICATION_VERSION
+	and added an entry to the SPECIFICATION_VERSION_HISTORY
+
+2009-1-1  Daniel Berger <djberg96 at gmail.com>
+
+	* test/test_gem_dependency.rb: Removed a duplicate "def dep" that
+	was causing a warning.
+	* lib/rubygems/platform.rb: Added an empty? method in order to
+	better handle gem indexing when dealing with gems created
+	prior to 0.9.5. [Rubyforge: bug #22603 by Johnathan Conley]
+	* lib/rubygems.rb: Added an explicit 'require "etc"'.
+	[RubyForge: bug #22313 by Matthew Boedicker]
+
+2008-12-31  Daniel Berger <djberg96 at gmail.com>
+
+	* lib/rubygems/local_remote_options: Allow 'https' as a valid scheme
+	in addition to 'http' [RubyForge: patch #22485 by Duarte Henriques] 
+	* setup.rb: Deal with extraneous quotation mark when autogenerating
+	.bat file on MS Windows [RubyForge: bug #22712 Takayuki Ishikawa]
+	* lib/rubygems/commands/unpack_command.rb: Fixed the --target option
+	[RubyForge: patch #22532 by Bryan Ash]
+
+2008-12-30  Daniel Berger <djberg96 at gmail.com>
+
+	* lib/rubygems/builder.rb: Don't allow .gem file to be added back
+	onto itself [RubyForge: bug #19136, patch #23346 by Daniel Berger]
+	* lib/rubygems/defaults.rb: The default_path now only returns the
+	default_dir if the Gem.user_home doesn't exist
+	[RubyForge: bug #23037 by Pierre PLR]
+	* lib/rubygems.rb: Handle the possibility that Etc.getpwuid might
+	return nil on platforms other than Windows
+	[RubyForge: bug #22764 by Dudley Flanders]
+
+2008-12-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/doc_manager.rb:  Set title for generated documentation.
+	* lib/rubygems/dependency.rb:  Make #=~ work with Gem::Specification.
+
+2008-12-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Fix documentation for
+	Gem::Installer#write_spec.  Issue by okkez.
+
+2008-12-12  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/local_remote_options.rb:  Merge documentation fix by
+	okkez [ruby-dev:37271].
+	* lib/rubygems/source_info_cache_entry.rb:  Merge documentation fix
+	from [ruby-dev:37255].
+
+2008-12-08  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Add Gem::promote_load_path
+
+2008-12-01  Ryan Davis  <ryand-ruby at zenspider.com>
+
+	* lib/rubygems/remote_fetcher.rb: made threadsafe.
+
+2008-11-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/install_command.rb:  Don't do any post-install
+	stuff if no gems were installed.  Issue by Daniel Berger.
+
+2008-11-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb:  Read the file outside the exception
+	block so we raise a sane error.
+	* lib/rubygems/indexer.rb:  Allow the modern index to be updated
+	incrementally.  Allow the legacy and modern indicies to be updated
+	separately.
+
+2008-11-17  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb:  Added ability to only generate modern or
+	legacy indicies.
+
+2008-11-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/timer.rb:  Deprecate and move methods to Gem and
+	Gem::StreamUI.
+
+2008-11-11  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems/, test/: Make Version understand prerelease
+	versions using letters. (eg. '1.2.1.b') Thanks to Josh Susser and
+	Alex Vollmer.
+
+2008-11-03  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Gem name must be a String.
+
+2008-10-31  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/defaults.rb:  Update to support 1.9 libdir.
+	* util/gem_prelude.rb:  Move to .template, automatically fold in
+	defaults.
+
+2008-10-29  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Handle nonexistent home directory.  Bug #22229 by
+	Alexey Verkhovsky.
+
+2008-10-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb, lib/rubygems/custom_require.rb:  Make kernel
+	methods private.  Patch #20801 by James M. Lawrence.  Expose
+	our kernel extensions to RDoc.  Make Gem::location_of_caller behave on
+	Windows.  Patch by Daniel Berger.
+	* doc/release_notes/rel_1_3_1.rdoc:  Final release notes for 1.3.1.
+	* lib/rubygems/rubygems_version.rb:  1.3.1.
+
+2008-10-10  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/unpack_command.rb:  Silence PATH warning.
+
+2008-10-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Fix requires for inflate, deflate, etc.
+	* test/*:  Convert to minitest/unit.
+	* lib/rubygems/validator.rb:  Fix for MiniTest instead of test/unit
+	classic in 1.9.
+
+2008-10-03  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems.rb: Make Gem.dir respect :gemhome value from config.
+	* lib/rubygems/config_file.rb: Expose :gemhome value.
+
+2008-09-26  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems.rb:  Disregard ownership of ~ under Windows while
+	creating ~/.gem.  Fixes issues related to no uid support under
+	Windows.
+
+2008-09-24  Eric Hodel  <drbrain at segment7.net>
+
+	* doc/release_notes/rel_1_3_0.rdoc:  Final release notes for 1.3.0.
+	* lib/rubygems/rubygems_version.rb:  1.3.0.
+	* lib/rubygems/builder.rb:  Examine process status correctly.  Patch
+	  by Nobu.
+	* test/test_gem_ext_rake_builder.rb:  Override Gem.ruby and
+	  ENV['rake'] for 1.9 integration.  Patch by Nobu.
+
+2008-09-16  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems.rb: Use the path set in the config file if
+	applicable.
+	* lib/rubygems/config_file.rb: Expose the path.
+
+2008-09-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Only create ~/.gem by user owning ~.  Bug #21561
+	by Neil Wilson.
+
+2008-09-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb:  Autoload SpecFetcher to improve load
+	time.  Patch #21577 by Simon Chiang.
+	* lib/rubygems/commands/lock_command.rb:  Modernize.  Fix --strict.
+	Patch #21814 by Sven Engelhardt.
+	* lib/rubygems/platform.rb:  Fix for solaris platform.  Patch #21911
+	by Bob Remeika.
+
+2008-09-10  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/install_command.rb:  Describe _version_ in `gem
+	help install`.
+	* lib/rubygems/commands/environment_command.rb:  Describe environment
+	variables and gemrc in `gem help env`.
+	* lib/rubygems.rb:  Warn when executing Gem::manage_gems.
+	* lib/rubygems/doc_manager.rb:  Have RubyGems update the ri cache.
+	* lib/rubygems/source_index.rb:  Ensure specs are read as UTF-8.
+	* lib/rubygems/specification.rb:  Add magic comment to .gemspec files
+	so they are read in as UTF-8.
+
+2008-08-22  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems.rb: Corrected usage of HOMEDRIVE and HOMEPATH on Windows.
+	Escape Gem.ruby if spaces in the path are present. Solves bug related to
+	extensions compile process.
+	* test/test_gem.rb: Added test to verify both conditions.
+
+2008-08-17  Eric Hodel  <drbrain at segment7.net>
+
+	* doc/release_notes/rel_1_3_0.rdoc:  Initial release notes for 1.3.0.
+	* util/CL2notes:  Release note creation helper script.
+
+2008-08-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/local_remote_options.rb:  Added #both? to complement
+	  #local? and #remote?.
+	* lib/rubygems/commands/query_command.rb:  Print out LOCAL/REMOTE with
+	--both, even without a TTY.
+	* lib/rubygems.rb:  Add Gem.find_files, allows a gem to discover
+	features provided by other gems.
+
+2008-08-14  Wilson Bilkovich  <wilson at supremetyrant.com>
+
+	* lib/rubygems/source_index.rb: Deprecate options to 'search' other than
+	Gem::Dependency instances and issue warning until November 2008.
+	* lib/rubygems/platform.rb:	Remove deprecated constant warnings
+	and really deprecate them.
+	* Rakefile: If the SETUP_OPTIONS environment variable is set, pass its
+	contents as arguments to setup.rb
+	* test/test_gem_commands_uninstall_command.rb: Added
+
+2008-08-13  Wilson Bilkovich  <wilson at supremetyrant.com>
+
+	* lib/rubygems/uninstaller.rb:	Fix binary script uninstallation.
+	Bug #21234 by Neil Wilson.
+	* test/test_gem_commands_uninstall_command.rb: Added
+
+2008-08-12  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Try to create directory before diverting
+	to ~/.gems.
+	* lib/rubygems/uninstaller.rb:  Fix uninstallation with -i.  Bug
+	#20812 by John Clayton.  Have #remove_all call #uninstall_gem so hooks
+	get called.  Bug #21242 by Neil Wilson.
+	* lib/rubygems/commands/update_command.rb:  Fix updating RubyGems when
+	no previous rubygems-update is installed.  Bug #20775 by Hemant Kumar.
+
+2008-08-11  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb:  Fix HTTPS support.  Patch #21072 by
+	Alex Arnell.  Fix Not Modified handling.  Bug #21310 by Gordon
+	Thiesfeld.
+
+2008-07-11  Luis Lavena  <luislavena at gmail.com>
+
+	* setup.rb: Properly build --destdir folder structure using Pathname.
+	* test/mockgemui.rb: Fix warnings about instance variables in a module.
+
+2008-07-02  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems/defaults.rb: Add Gem.user_dir to use paths like
+	~/.gem/ruby/1.8/gems and the like instead of just ~/.gem. Update
+	remote fetcher and installer to use it.
+
+2008-07-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Add #gem_home, #bin_dir for hooks.  Use
+	DependencyInstaller's source_index so reinstallation via -i does not
+	fail.
+	* lib/rubygems/uninstaller.rb:  Add #gem_home, #bin_dir for hooks.
+	* lib/rubygems/commands/query_command.rb:  Don't print LOCAL/REMOTE
+	gems if stdout is not a TTY.
+	* lib/rubygems/commands/query_command.rb:  Use the regexp we already
+	have for `gem list --installed`.  Bug #20876 by Nick Hoffman.
+	* lib/rubygems/commands/which_command.rb:  Clarify what `gem which` is
+	for.
+
+2008-06-30  Eric Hodel  <drbrain at segment7.net>
+
+	* test/test_ext_configure_builder.rb:  Locale-free patch by Yusuke
+	Endoh [ruby-core:17444].
+	* lib/rubygems.rb:  Add pre/post (un)install hooks.
+	* lib/rubygems/installer.rb:  Call pre/post install hooks as
+	appropriate.
+	* lib/rubygems/uninstaller.rb:  Call pre/post uninstall hooks as
+	appropriate.  Minor refactoring of #uninstall.
+	* lib/rubygems/package/tar_reader.rb:  Some OSs raise EINVAL on seek.
+	Based on patch in bug #20791 by Neil Wilson.
+	* lib/rubygems/specification.rb:  Correctly check for support of
+	development dependencies for #to_ruby.  Bug #20778 by Evan Weaver.
+	* lib/rubygems/spec_fetcher.rb:  Correctly load all cache file even if
+	latest has been loaded.  Bug #20776 by Uwe Kubosch.
+
+2008-06-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/config_file.rb:  Add Gem::ConfigFile constants for
+	packagers and implementors to override defaults.
+	* test/*:  Fixes to run tests when under test/rubygems/.  Patch by
+	Yusuke ENDOH [ruby-core:17353].
+
+2008-06-24  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb:  Cleanup to support
+	if-modified-since requests.  pair: Ryan Davis
+	* lib/rubygems/indexer:  Force platform to Gem::Platform::RUBY when
+	nil or blank.  Fixes various uninstallable gems.
+
+2008-06-24  Phil Hagelberg <technomancy at gmail.com>
+
+	* lib/rubygems/installer.rb: Fall back on ~/.gem if GEM_HOME is
+	not writable.
+	* lib/rubygems/install_update_options.rb: Allow --user-install or
+	--no-user-install command-line switch to explicitly force whether
+	or not ~/.gem should be used.
+	* lib/rubygems/remote_fetcher.rb: Use ~/.gem/cache if cache dir is
+	not writable.
+	* test/gemutilities.rb: Use MockGemUi for all tests.
+
+2008-06-21  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Load specifications from the future.
+	Roll back specification version change.
+	* lib/rubygems/remote_fetcher.rb:  Reset connection when an HTTP
+	server misbehaves.
+	* setup.rb:  Fix --destdir for windows.
+	* doc/release_notes/rel_1_2_0.rdoc:  Bugs in RubyGems were
+	unintentionally added, order bug fixes by importance.
+	* lib/rubygems/rubygems_version.rb:  1.2.0.
+
+2008-06-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/uninstaller.rb:  Improve output when a gem to uninstall
+	isn't found.  Bug #20746 reported by Chad Wooley.
+	* setup.rb:  Fix rdoc installation with --destdir.  Patch #20739 by
+	Matthew Kent.
+	* lib/rubygems/commands/install_command.rb:  Don't reset GEM_PATH when
+	installing.  Fixes Bug #20746 by Chad Wooley.
+
+2008-06-20  Luis Lavena  <luislavena at gmail.com>
+
+	* setup.rb: Only prepend install_destdir when especified. Fixes
+	installation issues related to Windows paths (/C:/...)
+
+2008-06-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb:  Ensure that the entire
+	dependency chain is installed.  Fixes bug reported by Chad Woolley.
+
+2008-06-18  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/dependency_command.rb:  Restore matching
+	everything when no name is specified, regexp matching.  Fixes bug
+	#20716, bug #20717 by Chad Woolley.
+
+2008-06-18  Chad Woolley  <thewoolleyman at gmail.com>
+
+	* lib/rubygems/config_file.rb:  Fix --config-file option with no
+	equals and subsequent options to properly assign config file.
+	Previously config file was overwritten by subsequent option.
+	Fixes bug #16688.
+
+2008-06-17  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/version.rb:  Gem::Version #hash and #eql? now operate
+	on the version string, terms of the version string, so "1" and "1.0"
+	no longer correspond to the same slot.  Fixes indexer bug reported by
+	Chad Woolley.
+	* setup.rb:  Fix --format-executable.  Patch #20698 by Richard Brown.
+	* util/gem_prelude.rb:  Prevent infinite recursion, check for Gem now.
+	Patch from ruby trunk by nobu.
+	* lib/*:  Spelling cleanup.  Patch from trunk by Evan Farrar.
+	* test/*:  Fixes for win32 test failures reported by Luis Lavena.
+	* util/gem_prelude.rb:  Only remove methods added by gem_prelude.rb.
+
+2008-06-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb:  Fix quick_index generation.
+	* lib/rubygems/specification.rb:  Correctly guard new spec features
+	for older RubyGems.
+	* lib/rubygems/config_file.rb:  Add system-wide config file
+	(/etc/gemrc).  Patch #14723 by Phil Hagelberg.  Add windows code to
+	use appropriate directory.  Code by Daniel Berger.
+	* doc/release_notes/rel_1_2_0.rdoc:  Draft of 1.2.0 release notes.
+
+2008-06-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/server.rb:  Store off if we are returning Marshal
+	format before running =~ again.  Fixes bug reported by Chad Woolley.
+	* lib/rubygems/commands/stale_command.rb:  `gem stale` lists gems by
+	last access time.  Patch #20593 by Aaron Patterson.
+	* lib/rubygems/setup.rb:  Add --vendor and --destdir to setup.rb for
+	packagers.  Patch #20610 by Richard Brown.  Don't look for stub
+	files to remove any more.
+	* lib/rubygems/specification.rb:  Bump specification version and be
+	backwards compatible with type 2 specs.
+	* lib/rubygems/commands/query_command.rb:  Add installed location to
+	details for installed gems.
+
+2008-06-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb:  Only install all dependencies
+	when install_dir option is set.  Don't include satisfied dependencies
+	when gathering dependencies.
+	* lib/rubygems/commands/query_command.rb:  Display authors, rubyforge
+	and homepage urls with details.
+	* lib/rubygems/commands/environment_command.rb:  Add executable
+	directory (from Rubinius).
+	* lib/rubygems/commands/install_command.rb:  Don't set install_dir by
+	default.
+	* lib/rubygems/commands/update_command.rb:  Don't set install_dir by
+	default.  Use #find_missing for efficiency.
+
+2008-06-07  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/server.rb:  Fully mirror Gem::Indexer indexes, set
+	correct content-type headers, always refresh the source index.
+	* lib/rubygems/source_index.rb:  Add spec_dirs so that #refresh! will
+	always reload from the same locations.  #refresh! on manually-built
+	SourceIndex now raises.  Fixes #20509 by Chad Woolley.
+
+2008-06-06  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Remove previous bin_script_path in case
+	it is a symlink.
+	* lib/rubygems/commands/pristine_command.rb:  Force reinstallation of
+	the gem using the installer.  Fixes bug #20387 by Erik Persson.
+	* lib/rubygems/doc_manager.rb:  Ensure args to RDoc are all strings.
+	* lib/rubygems/source_index.rb:  Use find_matching to discover updated
+	specs instead of fetch.
+	* lib/rubygems/commands/query_command.rb:  Platform, not name in spec
+	tuples.
+
+2008-06-05  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/local_remote_options.rb:  Ensure remote repository URLs
+	reference directories.  Fixes bug #20134 by Neil Wilson.
+	* lib/rubygems/source_index.rb:  Gracefully handle ^C or explicit exit
+	while loading .gemspec files from disk.  Fixes bug #20523 by Joel
+	VanderWerf.
+	* lib/rubygems/specification.rb:  Use File#expand_path in
+	installation_path.  Fixes bug #19317 by Hemant Kumar.
+	* lib/rubygems/spec_fetcher.rb:  Fix legacy test against URI.
+	* lib/rubygems/remote_fetcher.rb:  Always raise FetchError from
+	RemoteFetcher.  Fix FetchErrors without URIs.  Refactor Net::HTTP
+	request code to use persistent connections for HEAD requests.  Feature
+	Request #7973 by Christian Schachtzabel.
+	* lib/rubygems.rb:  Don't load custom_require until after the OS and
+	implementation have had a chance to set paths.
+
+2008-06-04  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/source_index.rb:  Only fetch specs we need in
+	#outdated.
+	* lib/rubygems.rb:  Fix typo in ::activate exception.
+	* lib/rubygems/dependency.rb:  For #to_s, display dependency type when
+	nil.
+	* lib/rubygems/dependency_installer.rb:  Reset #installed_gems for
+	every #install.  Fixes bug #19444 by Glenn Rempe.
+	* lib/rubygems/installer.rb:  Don't re-read the disk to check for new
+	gems, add them by hand on install.
+
+2008-06-03  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Add ::gzip, ::gunzip, ::deflate and ::inflate.
+	* lib/rubygems/server.rb:  Add specs and latest_specs indicies.
+	* setup.rb:  Don't require rdoc until needed.  Patch #20414 by Brian
+	Candler.
+	* lib/uninstaller.rb:  Correctly uninstall gems installed with a
+	legacy platform.  Patch #19877 by Luis Lavena.
+	* lib/rubygems/commands/update_command.rb:  Only fetch remote specs
+	when we know what we're looking for.
+
+2008-06-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb:  Remove double slash in
+	#installation_path.  Fixes bug #19896 by Heiko Seebach.
+	* lib/rubygems/remote_fetcher.rb:  Require StringIO.  Fixes bug #19866
+	by Caleb Land.
+	* lib/rubygems.rb:  Require rubygems/defaults/#{RBX_ENGINE}.rb and
+	rubygem/defaults/operating_system.rb if they exist.  (OS require comes
+	first and may be overridden by operating system.)
+
+2008-06-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb:  Ensure identical names, versions and
+	platforms are identical for a smaller index.
+	* lib/rubygems/spec_fetcher.rb:  Only write to cache when we own it.
+	* lib/rubygems.rb:  Honor default_path if GEM_PATH environment
+	variable is not set.  Patch #19502 by Donavan Pantke.
+	* lib/rubygems/installer.rb:  Set file mode indicated by tar file.
+	Patch #19737 by Jason Roelofs.
+
+2008-06-01  John Barnette <jbarnette at rubyforge.org>
+
+	* lib/rubygems.rb: Add Gem.available?(gem, *specs) for easy availability
+	checks at runtime.
+
+2008-05-31  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/dependency_command.rb:  Delay fetching specs
+	until needed.  Reverse dependencies can no longer be calculated for
+	remote sources.  Add backwards compatibility.
+	* lib/rubygems/commands/fetch_command.rb:  Add backwards
+	compatibility.
+
+2008-05-30  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/local_remote_options.rb:  --sources option should not
+	add URIs to Gem.sources.
+	* lib/rubygems/spec_fetcher.rb:  Add #warn_legacy to help handling
+	legacy sources.
+	* luby/rubygems/commands/query_command.rb:  Add backwards
+	compatibility with legacy sources.
+
+2008-05-28  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb:  Add #uri to
+	Gem::RemoteFetcher::FetchError.
+	* lib/rubygems/user_interaction.rb:  Improve RDoc slightly.
+	* lib/rubygems/spec_fetcher.rb:  Introduce backwards compatibility for
+	legacy (pre 1.2) repositories
+	* lib/rubygems/commands/sources_command.rb:  Backwards compatibility
+	and restoration of --update.
+	* lib/rubygems/specification.rb:  Ensure nil-typed dependencies become
+	runtime dependencies.
+
+2008-05-27  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/spec_fetcher.rb:  Switch #fetch, #find_matching to be
+	compatible with Gem::SourceInfoCache#search_with_source.  Add caching
+	for .gemspec files.
+	* lib/rubygems/dependency_installer.rb:  Switch to SpecFetcher.
+	* lib/rubygems/source_index.rb:  Switch #outdated to use SpecFetcher.
+	* lib/rubygems/commands/dependency_command.rb:  Switch to SpecFetcher.
+	* lib/rubygems/commands/outdated_command.rb:  Switch to SpecFetcher.
+	* lib/rubygems/commands/query_command.rb:  Switch to SpecFetcher.
+	* lib/rubygems/commands/sources_command.rb:  Switch to SpecFetcher.
+	* lib/rubygems/commands/update_command.rb:  Switch to SpecFetcher.
+	* lib/rubygems/version.rb:  Handle comparisons with non-Gem::Version
+	objects.
+
+2008-05-13  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/spec_fetcher.rb:  Add caching of specs, latest_specs
+	files.
+	* test/gemutilities.rb:  Ensure Gem.user_home doesn't point to ~.
+
+2008-05-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb:  Add Marshal format index of spec names,
+	versions and platforms.  WIP.
+	* lib/rubygems/spec_fetcher.rb:  WIP for replacement of
+	Gem::SourceInfoCache and SourceInfoCacheEntry.
+	* lib/rubygems/dependency.rb:  Add #=~.
+
+2008-05-07 John Barnette <jbarnette at gmail.com>
+
+	* lib/rubygems/specification.rb, et. al: Let gems have development
+	dependencies, which aren't installed (except when --development is
+	supplied) or activated.
+
+2008-05-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb:  Refactored into simpler more imperative
+	code.
+	* lib/rubygems.rb:  Leave rbconfig/datadir.rb for non-RubyGems use.
+
+2008-04-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/server.rb:  Refresh the source index per request so new
+	gems will be found after server startup.
+
+2008-04-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb:  Only print out "Bulk updating" when
+	verbose, fix #latest_specs documentation.
+	* lib/rubygems/dependency_installer.rb:  Add :cache_dir option for
+	Tinderbox.
+
+2008-04-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/test_utilities.rb:  Expose some internal testing
+	utilities that are of general use.
+
+2008-04-10  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Fix Gem.prefix so it reports nil when rubygems.rb
+	is in sitelibdir, libdir, or doesn't have 'lib' as a parent directory.
+	* doc/release_notes/rel_1_1_1.rdoc:  RubyGems 1.1.1 release notes.
+	* lib/rubygems/rubygems_version.rb:  1.1.1.
+
+2008-04-07  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/server.rb:  Fix fragment URIs.  Patch by James Tucker.
+	* lib/rubygems/commands/update_command.rb:  Pass
+	--no-format-executable to setup.rb.  Patch by Stephen Bannasch.
+
+2008-04-06  Chad Woolley  <thewoolleyman at gmail.com>
+
+	* lib/rubygems.rb:  Add setter Gems.platforms=, to allow platforms
+	to be set/reset when invoking or testing RubyGems programatically.
+	Also force Gems.platforms to automatically reset to default of
+	[Gem::Platform::RUBY, Gem::Platform.local] if cleared.
+	* lib/rubygems/version_option.rb:  Change add_platform_option
+	to initialize Gem.platforms to contain only Gem::Platform::RUBY
+
+2008-04-04  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb:  Make Gem::SourceIndex#refresh!
+	more-correct.  Reported by Paul Haddad.
+	* lib/rubygems.rb:  Add Gem::refresh.  Bug #19176 by Hongli Lai.
+	* lib/rubygems/dependency_installer.rb:  Put downloaded gems into
+	install_dir's cache.  Patch #19182 by Richard Brown.
+
+2008-04-03  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache.rb:  Merge full cache file into
+	latest data.  Don't write cache files when checking for them.  Only
+	update full cache file when we've read it.  Refresh all data when
+	loading all data.
+	* lib/rubygems/dependency_installer.rb:  Fix --force to work without
+	network for dependent gems.  Fix all-fetching test.
+	* lib/rubygems/commands/query_command.rb:  Obey --all flag for gem
+	query.
+	* lib/rubygems/commands/environment_command.rb:  Don't display
+	RubyGemsPackageVersion.
+	* lib/rubygems/indexer.rb:  Fix typo.  Patch by Tom Copeland.
+	* lib/rubygems/command_manager.rb:  Display RubyGemsVersion with
+	--version.
+	* lib/rubygems/commands/pristine_command.rb:  Rebuild extensions along
+	with everything else.  Patch #19281 by Dr. Nic Williams.
+
+2008-04-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Fix prefix to point to directory above RubyGems,
+	so RubyGems will be installed into lib/.
+	* setup.rb:  Work around apple's libdir-installed RubyGems, by
+	installing into sitelibdir.
+	* Rakefile:  Add svnversion to RubyGems version number for `rake
+	install`.
+
+2008-03-31  Luis Lavena  <luislavena at gmail.com>
+
+	* test/: Allow tests to use a random (but controlled) port number
+	instead of a hardcoded one. This helps CI tools when running
+	parallels builds.
+
+2008-03-30  Luis Lavena  <luislavena at gmail.com>
+
+	* test/test_gem.rb: Leave APPLE_GEM_HOME tests only to *nixes.
+	* lib/rubygems/remote_fetcher.rb: Errno::ECONNABORTED raised on Windows
+	on closed Keep-Alive connections.
+
+2008-03-29  Eric Hodel  <drbrain at segment7.net>
+
+	* gemspecs/:  Removed.
+	* examples/:  Removed.
+	* doc/design/:  Removed.
+	* doc/rdoc_templates/:  Removed.
+	* Rakefile:  Package doc/release_notes/.
+	* setup.rb:  Use full path to release_notes, ensure RDoc can be
+	both removed and installed.
+
+2008-03-28  Eric Hodel  <drbrain at segment7.net>
+
+	* bin/gem, Rakefile:  RubyGems now requires Ruby > 1.8.3.
+	* lib/rubygems.rb:  Added Gem.ruby_version, Gem.read_binary,
+	Gem.binary_mode.
+	* lib/, test/:  Read files in binary mode for windows and ruby 1.9.
+	* lib/rubygems/commands/update_command.rb:  Only update once.
+	* lib/rubygems/commands/sources_command.rb:  Ditto.
+	* lib/rubygems/source_index.rb:  Fix #remove_extra, #find_missing so
+	legacy platform gems don't get updated repeatedly.
+	* doc/release_notes/rel_1_1_0.rdoc:  RubyGems 1.1.0 release notes.
+	* lib/rubygems/rubygems_version.rb:  1.1.0.
+
+2008-03-28  Ryan Woodrum  <rwoodrum at avvo.com>
+
+	* lib/rubygems/commands/query_command.rb: Add --installed
+	subcommand to check if a gem and/or version is installed.
+	* test/test_gem_commands_query_command.rb: Add relevant tests.
+	* test/gemutilities.rb: Override exit() for query tests.
+	* test/mockgemui.rb: Add =() to manipulate output values (clear).
+
+2008-03-28  Chad Woolley  <thewoolleyman at gmail.com>
+
+	* lib/rubygems/source_info_cache.rb: Add reset_cache_file.
+
+2008-03-27  Chad Woolley  <thewoolleyman at gmail.com>
+
+	* lib/rubygems/user_interaction.rb: Raise Gem::SystemExitException
+	instead of exiting, kill unused terminate_interaction!.
+	* lib/rubygems/exceptions.rb: Add Gem::SystemExitException.
+	* lib/rubygems/commands/install_command.rb: Raise
+	Gem::SystemExitException instead of exiting.
+	* bin/gem: Rescue Gem::SystemExitException and exit with
+	specified exit_code.
+	* test/test_gem_commands_install_command.rb: Assert on
+	Gem::SystemExitException and exit_code in tests.
+
+2008-03-27  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/sources_command.rb:  Allow sources to be
+	removed without network.  Fixes bug #18644 by Mikel Lindsaar.
+
+2008-03-27  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems/commands/environment_command.rb: Use platform specific
+	PATH_SEPARATOR instead of hardcoded ':'
+	* test/test_gem_commands_unpack_command.rb: Ditto.
+	* test/test_gem_commands_environment_command.rb: Ditto.
+	* test/gemutilities.rb: Fix binary file reads being truncated on
+	Windows.
+	* test/test_gem_commands_install_command.rb: Switch to read_binary.
+	* test/test_gem_commands_update_command.rb: Ditto.
+	* test/test_gem_commands_server_command.rb: Consider full path when
+	evaluating location (instead of hardcoded or missing drive leter).
+	* test/test_gem_installer.rb: Ditto.
+	* test/test_gem_dependency_installer.rb: exclude no-wrapper tests for
+	Windows.
+
+2008-03-26  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems.rb: Handle backslashes that came from GEM_HOME and
+	GEM_PATH on Windows.
+
+2008-03-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb:  Add updating from latest index,
+	default to updating from latest index.  Reduces common-case update
+	to under 3,000 gems at present.
+	* lib/rubygems/remote_fetcher:  Fix error reporting from net/http.
+	* lib/rubygems.rb:  Sort methods, remove last vestiges of autorequire,
+	RDoc cleanup.
+
+2008-03-23  Luis Lavena  <luislavena at gmail.com>
+
+	* setup.rb: generated Windows stubs will honors prefix using Gem.ruby
+	instead of hardcoded 'ruby.exe'
+	* lib/rubygems/installer.rb: generated Windows stubs scripts will now
+	work from differnt directories than Gem::bindir. Fixes bug #16259 by
+	Claus Folke Brobak
+
+2008-03-20  Eric Hodel  <drbrain at segment7.net>
+
+	* test/test_gem_source_info_cache.rb:  Test with real objects now.
+	* lib/rubygems/source_index.rb:  #latest_specs now has latest specs
+	for all platforms.
+	* lib/rubygems/source_info_cache.rb:  Add latest cache data, only load
+	full cache data when needed.
+
+2008-03-20  Luis Lavena  <luislavena at gmail.com>
+
+	* test/gemutilities.rb:  Change all the file processing mechanism to
+	enable binary mode by default (required for Windows file operations
+	dealing with non-printable characters).
+
+2008-03-19  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems/package/tar_output.rb: Adapted code to use #wrap instead
+	of #new when dealing with Zlib::GzipWriter (fixes SEGV and warnings due
+	GzipWriter object not being closed explicitly).
+
+2008-03-12  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb:  Add latest_index.
+
+2008-03-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/defaults.rb:  Add special case for RUBY_ENGINE constant
+	when setting default gem dir.
+	* Rakefile:  Add update_rubinius and diff_rubinius.
+
+2008-03-08  Lincoln Stoll  <lstoll at lstoll.net>
+
+	* lib/rubygems/server.rb:  Drop use of RDoc's TemplatePage in favor of
+	ERB.
+
+2008-03-04  Ryan Davis  <ryan at wrath.local>
+
+	* lib/rubygems/remote_fetcher.rb: Moved #download from
+	DependencyInstaller.
+	* lib/rubygems/commands/fetch_command.rb: Updated to use #download.
+	* lib/rubygems/dependency_installer.rb: install now takes name or dep.
+	Renamed gather_specs_to_download to find_spec_by_name_and_version.
+	Modifed #initialize to not take gem name or version.
+
+2008-03-04  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/package*:  Removed #open_from_io and friends, switched
+	to #open, no special handling for file names.
+	* lib/rubygems/package/tar_output.rb:  Refactored ::open to use
+	instance methods.
+	* lib/rubygems/remote_fetcher.rb:  Print out number of requests made
+	before connection reset.
+
+2008-02-29  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/package/tar_reader/entry.rb:  Removed is_directory and
+	is_file? in favor of file? and directory?.
+
+2008-02-28  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/package.rb:  Broke up Tar bits into separate files.
+	* lib/rubygems/package/tar_reader/entry.rb:  Don't copy TarHeader data
+	into Entry, go through #header instead.  Better tests for
+	TarReader::Entry.
+
+2008-02-27  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb:  Automatically fall back to
+	local-only install on network error.  Fixes bug #15759 by Chauk-Mean P.
+	* lib/rubygems/source_index.rb:  Process spec dirs so that earlier
+	dirs override later dirs.  Fixes bug #14816 by Kurt Stephens.
+
+2008-02-26  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/update_command.rb:  Only update gems that need
+	updates.  Fixes bug #14780 by Mathieu Lajugie.  Don't force
+	remote-only updates.  Properly handle dependencies when updating.
+	Fixes bug #17488 by Hongli Lai.
+	* lib/rubygems/commands/environment_command.rb:  Display path as a
+	usable path.
+	* lib/rubygems.rb:  Don't add APPLE_GEM_HOME with ENV['GEM_HOME'].
+
+2008-02-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb:  Expand sitelibdir when checking prefix.  Fixes bug
+	#17983 by Hemant Kumar.
+	* setup.rb:  Print release notes on installation.  Tell people where
+	`gem` was installed.
+	* bin/update_rubygems:  Added --help output to explain how to install
+	earlier versions of RubyGems.  Added --version option workaround.
+	Fixes bug #16842 by Chad Woolley.
+	* lib/rubygems/install_command.rb:  Give proper exit code on failure.
+	Fixes bug #17438 by Josh Nichols.
+
+2008-02-23  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb:  Change hosts correctly when
+	redirecting.  Handle EOFError from Net::HTTP.
+	* lib/rubygems/commands/specification_command.rb:  Pull specifications
+	from gem files.
+	* lib/rubygems/uninstaller.rb:  When :executable is set, don't ask the
+	user.  Fixes bug #16812 by Matt Mower.  Raise exception instead of
+	printing message when gem is not in GEM_HOME.
+	* lib/rubygems/uninstall_command.rb:  Print message when gem is not in
+	GEM_HOME.
+	* lib/rubygems/commands/cleanup_command.rb:  Clean up all old gems.
+	* lib/rubygems/commands/unpack_command.rb:  Scan every gem path when
+	unpacking.  Fixes bug #17602 by Ryan Davis.
+
+2008-02-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/install_update_options.rb: Add --bindir option to
+	specify destination to install executables into.  Patch #17937 by
+	Donavan Pantke.
+	* lib/rubygems/specification.rb: Fix Time.today == Time.today.  Bug
+	#17413 by Andrei Bocan.
+	* setup.rb: Properly check for deletablitily of user and system
+	caches.  Bug #17869 by Alexey Verkhovsky.  Fix --no-format-executable.
+	Fixes bug #16879 by Charles Nutter.
+
+2008-02-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb: Add persistent connection support.
+	Patch #18180 by Aaron Patterson.
+	* lib/rubygems/installer.rb: Fix #shebang to use the ruby install
+	name.  Patch #16878 by Donavan Pantke.
+	* lib/rubygems/defaults.rb, lib/rubygems.rb: Enable defaults for
+	Gem.path and Gem.bindir.  Patch #17886 by Donavan Pantke.
+	* test/test_gem_ext_configure_builder.rb: Make test_self_build_fail
+	more platform independent.  Patch #17599 by Martin Krauskopf.
+
+2008-02-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/fetch_command.rb: Fix a bug when fetching
+	from non-default sources.  Report non-existent gems instead of
+	crashing.
+
+2008-01-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/update_command.rb: Use portable and safe ENV
+	operation.  Patch by usa in ruby SVN revision 14739.
+	* lib/rubygems/open-uri.rb: Fix tests.  Patch by NARUSE Yui.
+	[ruby-dev:33336]
+
+2007-12-23  Eric Hodel  <drbrain at segment7.net>
+
+	* util/gem_prelude.rb:  Remove methods from Gem, not QuickLoader, to
+	fix warnings.
+
+2007-12-22  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/environment_command.rb:  Put GEM PATHS in the
+	correct order.
+	* lib/rubygems/commands/uninstall_command.rb:  Add --install-dir to
+	specify which local repository to uninstall from.  Patch #15151 by
+	Donavan Pantke.
+	* lib/rubygems/uninstaller.rb:  Only allow uninstallation of gems from
+	specified directory.  Properly clean up executables on uninstall.
+	Patch #15151 by Donavan Pantke.
+	* lib/rubygems/install_update_options.rb:  Add --no-env-shebang
+	option.  Patch #16508 by Donavan Pantke.
+	* util/gem_prelude.rb:  Use require to load rubygems.rb to make
+	$LOADED_FEATURES correct on RubyGems update.
+
+2007-12-21  Eric Hodel  <drbrain at segment7.net>
+
+	* util/gem_prelude.rb:  Place bin before lib so bin stubs work.
+
+2007-12-20  Eric Hodel  <drbrain at segment7.net>
+
+	* Rakefile:  Require Ruby > 1.8.2.  Enable CERT_DIR.
+	* lib/rubygems.rb:  Work with RbConfig and Config.  Bug #16457 by
+	Christian Ramilo, John Barnette.
+	* lib/rubygems/commands/build_command.rb:  Relax yaml? test to work
+	with Ruby 1.8.3.
+	* lib/rubygems/rubygems_version.rb:  1.0.1.
+	* doc/release_notes/rel_1_0_1.rdoc:  RubyGems 1.0.1 release notes.
+
+2007-12-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Revert change that only wrapped
+	executables with #!.
+	* lib/rubygems/specification.rb:  Warn about a lot of things that
+	could be wrong with gemspecs on build, including missing #!.  Use
+	'x86-mswin32' for legacy 'mswin32' platform, fix CURRENT platform.
+	Paired with Luis Lavena.
+	* lib/rubygems/remote_installer.rb:  Deleted.
+	* lib/rubygems.rb:  Removed Kernel#require_gem.
+	* doc/release_notes/rel_1_0_0.rdoc:  RubyGems 1.0 release notes.
+	* lib/rubygems/rubygems_version.rb:  1.0.0.
+
+2007-12-18  Luis Lavena  <luislavena at gmail.com>
+
+	* lib/rubygems/commands/mirror_command.rb: Work around URI::parse
+	processing file:// scheme and drive paths on Windows.
+	* test/test_gem_commands_mirror_command.rb: ditto.
+
+2007-12-17  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Copy files into bindir if they don't
+	have a shebang.  Bug reported by Luis Lavena.
+	* lib/rubygems/server.rb:  Handle platforms in Gem::Server#quick.
+	Exactly match gem names.  Bugs reported by Chad Woolley.
+	* lib/rubygems/platform.rb:  Remove platform constants in favor of
+	Gem::Platform::CURRENT.  Bug reported by Luis Lavena.
+	* lib/rubygems/dependency_installer.rb:  Work around Dir::glob not
+	understanding File::ALT_SEPARATOR.  Bug submitted by Luis Lavena.
+
+2007-12-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb:  Be more verbose in error messages
+	from OpenURI.
+	* lib/rubygems/server.rb:  Be more verbose in error/missing responses.
+
+2007-12-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Output extension build results when
+	really verbose.  From bug #15853 John Croisant.
+	* lib/rubygems/specification.rb:  Fix backwards compatibility with
+	0.9.4, don't allow the platform to be nil or an empty string.  Bug
+	#16177 by Dan Manges.
+	* setup.rb:  Re-exec setup.rb if rubygems is loaded and RUBYOPT is
+	set.  Fixes bug #15974 by Joshua Sierles.
+	* lib/rubygems/update_command.rb:  Tweak formatting of updated
+	message.  Bug #15625 by Bil Kleb.
+	* lib/rubygems/remote_fetcher.rb:  Add URI to exception message for
+	Gem::RemoteFetcher#fetch_size.  Bug #14801 by Bil Kleb.
+
+2007-12-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/query_command.rb:  Don't display duplicate
+	version numbers.  Bug #15828 by Tim Fletcher.
+	* setup.rb:  Fix my stupidity with --help.  Patch #16308 by Stephen
+	Bannasch.  Fix --prefix= argument.  Bug #16002 by Piglop.
+
+2007-12-13  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/server_command.rb:  Fix --no-daemon.  Bug by
+	Chad Woolley.
+	* lib/rubygems/server.rb:  Fix Marshal quick index.  Bug by Chad
+	Woolley.
+	* lib/rubygems/installer.rb: Respect Gem::Specification#bindir.  Bug
+	#16202 by Suraj Kurapati.
+	* lib/rubygems/commands/update_command.rb: Fix `gem update mysql`.
+	Bug #16244 by Stephen Bannasch.
+
+2007-12-12  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb:  Add --format-executable option to
+	install executables with ruby's program-suffix and prefix.  Patch
+	#14688 by Jeremy Kemper.  Also, installing in really-verbose mode
+	prints out written files.
+	* setup.rb:  Add --format-executable option to install gem with ruby's
+	program-suffix and prefix.  Add --help.  Fixes bug #16056 by Chad
+	Woolley.
+	* lib/rubygems/uninstaller.rb:  Fallback to original_platform_name
+	correctly.  Patch #15960 by Nicola Piccinini's friend.
+
+2007-12-11  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/validator.rb:  Correct test run failures when no tests
+	are provided.  Patch #15701 by Jérémy Zurcher.
+	* lib/rubygems/commands/mirror_command.rb:  Don't File.join a
+	URI::HTTP.  Patch #16116 by Morgan Nelson.
+	* lib/rubygems/commands/unpack_command.rb:  Add --target option to
+	`gem unpack`.  Patch #16154 by Kevin Barnes.
+
+2007-12-10  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb:  Revert to nil for the default
+	security policy to avoid requiring OpenSSL.
+	* lib/rubygems/defaults.rb: Consolidate defaults for easier editing.
+	Patch #15150 by Donavan Pantke.
+
+2007-11-27  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb: Remove dependency on forwadable.
+	Patch by Koichi Sasada.
+	* lib/rubygems/specification.rb: Reduce dependency on time.rb.  Patch
+	by Koichi Sasada.
+
+2007-11-26  Rich Kilmer <rich at infoether.com>
+
+	* lib/rubygems/version.rb: Fix bug 15948 with version bump
+	* test/test_gem_version.rb: Test for bug 15948 with version bump
+	* util/gem_prelude.rb: wrap init code with exception handler
+	and skip badly formed directory names
+
+2007-11-23  Rich Kilmer <rich at infoether.com>
+
+	* lib/rubygems.rb: Centralize all CONFIG options into Hash
+	Gem::ConfigMap with keys as symbols, change all references
+	to CONFIG to ConfigMap
+	* lib/rubygems/require_paths_builder.rb: Added to support 
+	building .require_paths file
+	* lib/rubygems/installer.rb: Add building of .require_paths if
+	needed
+	* lib/rubygems/platform.rb: Use new ConfigMap hash for arch
+	* lib/rubygems
+	* util/gem_prelude.rb: new gem prelude for Ruby 1.9
+	* test/test_gem_installer.rb: change to use ConfigMap hash
+	* test/gemutilities.rb: change to use ConfigMap hash
+
+2007-11-21  Daniel Berger <djberg96 at gmail.com>
+
+	* lib/rubygems/platform.rb: Gem::Platform.new now returns
+	Gem::Platform.local if the arch matches Gem::Platform::CURRENT.
+	Bugs #15815 and #15782 submitted by Daniel Berger.
+
+2007-11-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/platform.rb: Handle bare 'mswin32' platform's CPU.
+
+2007-11-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb: 0.9.5.
+
+2007-11-16  Eric Hodel  <drbrain at segment7.net>
+
+	* test/gemutilities: Add a legacy platform gem to the default test
+	gems list.
+	* lib/rubygems/specification.rb: Add Gem::Specification#original_name
+	for legacy purposes
+	* lib/rubygems/indexer.rb: Use #original_name to make the indexer
+	backwards compatible.
+	* lib/rubygems/master_index_builder.rb: Reduce memory consumption.
+
+2007-11-13  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb: 0.9.4.7 beta.
+	* lib/rubygems.rb: Patch for RUBY_FRAMEWORK for OS X 10.5.  Patch
+	submitted by Laurent Sansonetti.
+	* lib/rubygems.rb: cygwin, djgpp, mingw are Windows platforms.  Fixes
+	bug #15537 by Roger Pack.
+
+2007-11-11  Eric Hodel  <drbrain at segment7.net>
+
+	* Rakefile: Tasks for maintaining ruby trunk export of RubyGems.
+	* lib/rubygems/specification.rb: Preserve original platform across
+	serialization.
+	* lib/rubygems/dependency_installer.rb: Retry with original platform
+	name on fetch error.
+
+2007-11-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb: Set #original_platform only once.
+	* lib/rubygems/indexer.rb: Handle legacy platforms.
+	* lib/rubygems/platform.rb: Gem::Platform is a valid argument.  Bug
+	#15511 submitted by Daniel Berger.
+	* lib/rubygems/custom_require.rb: Fix compatibility with 1.8.2.  Bug
+	#14933 submitted by Aaron Patterson.
+	* lib/rubygems/command.rb: Now '-V' enables verbose.  Bug #14951
+	submitted by Sasa Ebach.
+	* lib/rubygems/commands/check_command.rb: Change use of '-v', '-V' to
+	match above.
+	* lib/rubygems/package.rb: #send! is gone again.
+	* lib/rubygems.rb: Don't add custom_require for 1.9.
+	* test/*: Make compatible with 1.9 import.
+
+2007-10-30  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb: Don't re-use @platform to maintain
+	backwards compatibility.
+	* lib/rubygems/platform.rb: Handle nil and 'ruby' platforms in ::new.
+
+2007-10-20	Daniel Berger	<djberg96 at gmail.com>
+
+	* lib/rubygems/uninstaller.rb: Changed '.cmd' to '.bat' in the
+	remove_executables method for MS Windows. Patch from Luis Lavena.
+
+2007-10-18  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb: 0.9.4.6 beta.
+
+2007-10-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/update_command.rb: Don't install with
+	dependencies when updating.  This is a hack.
+
+2007-10-19  Daniel Berger  <djberg96 at gmail.com>
+
+	* setup.rb: gem.cmd stub is now gem.cmd, and the stub generation was
+	changed - now better for NT. Patch #14725 (Luis Lavena).
+	* lib/rubygems/installer.rb: Same as for setup.rb.
+
+2007-10-18  Daniel Berger  <djberg96 at gmail.com>
+
+	* lib/rubygems/platform.rb: Modified the Platform.local method for MS
+	Windows for versions built with VC++ 6. Patch #14727 (Luis Lavena).
+	* test/test_gem_specification.rb: Added version independent tests for
+	MS Windows. Patch #14727 (Luis Lavena).
+
+2007-10-18  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb: Add platform to User-Agent.
+	* lib/rubygems/commands/install_command.rb: Fix typo.  Debian bug
+	#443135 submitted by Reuben Thomas.
+	* lib/rubygems/dependency_installer.rb: Don't install dropped
+	dependencies.  Fixes bug #14724 submitted by Luis Lavena.
+
+2007-10-17  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/update_command.rb: Unset RUBYOPT when running
+	setup.rb
+	* setup.rb: Re-exec without RUBYOPT if it is set.  Fixes bug #14683
+	submitted by Lyle Johnson.
+
+2007-10-16  Daniel Berger  <djberg96 at gmail.com>
+
+	* lib/rubygems/indexer/abstract_index_builder.rb: The compress method
+	now does a binary read to make MS Windows happy.
+
+2007-10-16  Eric Hodel  <drbrain at segment7.net>
+
+	* setup.rb: Installs bin stubs that warn when you try to use the old
+	commands.  Simple mswin deprecation stubs by Luis Lavena.
+
+2007-10-12  Eric Hodel  <drbrain at segment7.net>
+
+	* setup.rb: Remove source caches on install.
+	* doc/release_notes/rel_0_9_5.rdoc: Draft added.
+	* lib/rubygems/rubygems_version.rb: 0.9.4.5 beta.
+
+2007-10-10  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb: Fix small bug found by Alan C.
+	Francis.
+
+2007-10-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb: Use install_dir so custom gem
+	repos can be used.
+	* lib/rubygems/specification.rb: Always set required attributes, even
+	if they match the default.
+
+2007-10-08  Ryan Davis  <ryan at wrath.local>
+
+	* lib/rubygems.rb: Fixed require order so custom_require is
+	last. Added HACK tag to remind Jim to release rake.
+	* test/test_gem_source_index.rb: Fixed latest_specs' tests so
+	failures were much more readable.
+	* lib/rubygems/source_index.rb: Fixed latest_specs to deal with
+	platforms appropriately. Returns array again.
+
+2007-10-08  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/config_file.rb: Boost bulk_threshold to 1000, Marshal
+	format is smaller than yaml format quick index.
+	* lib/rubygems/installer.rb: Make #shebang correctly rewrite env
+	shebangs.
+	* lib/rubygems/specification.rb: Mark Time.today for removal, too much
+	depends upon it now.
+
+2007-10-07  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb: Sped up ::_load.
+	* lib/rubygems/source_index.rb: Sped up #search.
+	* lib/rubygems/version.rb: Replace #to_ints with #ints, and cache
+	result.
+	* lib/rubygems/source_info_cache.rb: Only flush cache when it changes.
+
+2007-10-05  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/user_interaction.rb: Allow customization of completion
+	message for progress reporters.
+	* lib/rubygems/command.rb: Add --quiet option.
+	* lib/rubygems/commands/generate_index_command.rb: Add description.
+
+2007-10-04  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/uninstaller.rb: Also check and uninstall old platform
+	name to ensure legacy platform gems are uninstalled.
+	* lib/rubygems/doc_manager.rb: Remove existing rdoc and ri directory
+	so regenerating docs succeeds even if previously interrupted.
+
+2007-10-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb: Make #outdated search only for gems
+	matching the current platform.
+	* lib/rubygems/commands/dependency_command.rb: Add --platform.
+	* lib/rubygems/commands/outdated_command.rb: Ditto.
+	* lib/rubygems/commands/specification_command.rb: Ditto.
+	* lib/rubygems/commands/update_command.rb: Ditto.
+
+2007-10-02  Wilson Bilkovich  <wilson at supremetyrant.com>
+
+	* lib/rubygems/specification.rb: Custom Marshal format to reduce index
+	size.
+	* lib/rubygems/requirement.rb: Ditto
+	* lib/rubygems/version.rb: Ditto
+
+2007-10-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/platform.rb: Handle mswin32 on VC6.  Partial patch and
+	assistance by Luis Lavena.  Handle cpu-os-version style platforms for
+	command-line arguments.
+
+2007-09-30  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb: Gem::Specification is now
+	forward-compatible while loading.
+
+2007-09-29  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache_entry.rb: Correctly handle URIs.
+	* lib/rubygems/remote_fetcher.rb: ditto.
+	* lib/rubygems/remote_options.rb: Add --update-sources option.  Patch
+	#14246 submitted by Alan Francis.
+	* lib/rubygems/config_file.rb: Add update_sources setting to control
+	automatic refreshing of sources (patch #14246).  Fix bug where things
+	would be overwritten in ~/.gemrc when they shouldn't.
+
+2007-09-28  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems.rb: Gem.ruby now returns the full path.  Added
+	Gem.prefix to make self updating work right.
+	* setup.rb, pre-install.rb, post-install.rb: Replace with a small,
+	simple setup script that works.
+	* lib/rubygems/commands/update_command.rb: Pass rdoc, ri and prefix
+	flags down to setup.rb when self updating.
+
+2007-09-26  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/version_option.rb: Always include RUBY platform,
+	allow RUBY platform as an option.
+	* lib/rubygems/specification.rb: Gems with non-ruby platform sort
+	last (first in preference for installation).
+	* lib/rubygems/platform.rb: Allow matching of legacy platforms.
+	* lib/rubygems/source_index.rb: Add only_platform option to #search.
+
+2007-09-24  Wilson Bilkovich  <wilson at supremetyrant.com>
+	* lib/rubygems/indexer.rb: Generate a Marshal index in parallel to YAML
+	* lib/rubygems/source_index.rb: Fetch a Marshal index if it exists, to
+	avoid the memory cost of parsing a huge YAML file
+	* lib/rubygems/commands/mirror_command.rb: Check for Marshal first
+	* lib/rubygems/indexer/abstract_index_builder.rb: Index refactoring
+	* lib/rubygems/indexer/marshal_index_builder.rb: Build Marshal index
+	* lib/rubygems/indexer/master_index_builder.rb: Simplify YAML generation
+	* lib/rubygems/indexer/quick_index_builder.rb: Build Marshal quickindex
+	* lib/rubygems/server.rb: Serve up Marshal index as well as YAML
+	* lib/rubygems/source_info_cache_entry.rb: Expect a Marshal index
+
+2007-09-23  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/fetch_command.rb: `gem fetch` downloads a gem
+	to the current directory.  Feature request #10752 by Bret Pettichord.
+	* lib/rubygems/commands/local_remote_options.rb, etc.: Fix spelling of
+	'threshold'.
+	* lib/rubygems/installer.rb: Revert feature request #8818, it
+	interferes with `ruby -S` and multiple versions of ruby (1.8 and 1.9).
+	* lib/rubygems/dependency_installer.rb: Fix a bug where the wrong
+	platform gem would be installed.
+	* lib/rubygems/version_option.rb: Add --platform.
+	* lib/rubygems/install_update_options.rb: Verify --security-policy.
+	* lib/rubygems/local_remote_options.rb: Verify --source, --http-proxy.
+
+2007-09-22  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/open-uri.rb: Don't document our OpenURI.
+	* lib/rubygems/commands/generate_index_command.rb: Fix Indexer class
+	change.
+	* lib/rubygems/commands/mirror_command.rb: Fix for 1.9.
+	* lib/rubygems/commands/pristine_command.rb: Have `gem pristine`
+	give a better report of what it accomplished.
+	* lib/rubygems/command.rb: Add optional description field.
+	* lib/rubygems/installer.rb: Hack around broken Pathname#absolute? on
+	windows.  Patch #14139 by Jim Hughes.
+
+2007-09-20  Eric Hodel  <drbrain at segment7.net>
+
+	* misc files: Tests pass on 1.9.
+	* test/gemutilities.rb: Added Object#send! stub for 1.8.
+	* test/test_open_uri.rb: Require gem_open_uri.rb to avoid warnings.
+	* lib/rubygems/commands/sources_command.rb: Clarify `gem sources -c`
+	and what `gem sources` does.  Patch by Hugh Sasse.
+
+2007-09-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/platform.rb: Make Gem::Platform a class.
+	* lib/rubygems/specification.rb: Gem::Specification#validate returns
+	true, non-Gem::Platform platforms are no longer allowed.
+	* test/gemutilities.rb: 1.9 compatiblity fixes.
+	* lib/rubygems/dependency_installer.rb: Work around a bug in URI.parse
+	which misinterprets "C:/".  Patch #13537 submitted by Daniel Berger.
+	* lib/rubygems/format.rb: Ensure file handles are closed.  Patch
+	#13533 submitted by Daniel Berger.
+	* test/test_gem_installer.rb: Win32 path fix.  Patch #13528 submitted
+	by Daniel Berger.
+	* test/gemutilities.rb: Make the platform be a win32 platform on
+	win32.  Fixes confusion in generate_bin_symlink tests.  Patch #13529
+	submitted by Daniel Berger.
+	* test/test_gem_specification.rb: Sequel to above.  Patch
+	#13535 submitted by Daniel Berger.
+	* lib/rubygems/source_index.rb: Make the updating cache message more
+	clear.  Patch #12778 submitted by Bil Kleb.
+	* lib/rubygems/server.rb: Allow gem's rdoc-style.css to be used.
+	Patch #13589 by Stephen Bannasch.
+	* lib/rubygems/indexer.rb: Fail on missing builder gem only when
+	trying to use the indexer.  Fixes bug #13939 by Bryan Stearns.
+	* lib/rubygems/indexer/indexer.rb: Move Indexer up one level in
+	nesting.
+	* lib/rubygems/indexer/compressor.rb: Only used in
+	Gem::Indexer::AbstractIndexBuilder subclasses, merged there.
+	* lib/rubygems/command_aids.rb: Merged Gem::CommandAids into
+	Gem::Command since that's the only place it gets used.
+	* misc other files: mswin fixes.  Paired with Daniel Berger.
+
+2007-08-24  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb: Fix #full_name for versionless
+	platforms.
+	* lib/rubygems/command_manager.rb: We're only looking for NameError.
+	* lib/rubygems/command.rb: 1.9 fix.
+	* lib/rubygems/format.rb: ditto.
+	* lib/rubygems/installer.rb: ditto.
+
+2007-08-24  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb: 0.9.4.4
+
+2007-08-23  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/platform.rb: Add HPUX, AIX and NetBSD.  Thanks to
+	Daniel Berger, Yutaka KANEMOTO and Andre Nathan respectively.
+	* lib/rubygems/installer.rb: Move all option setting to #initialize to
+	make `gem pristine` work again.
+	* lib/rubygems/commands/environment_command.rb: Include platforms.
+	* lib/rubygems/dependency_installer.rb: Support local non-root
+	installation.
+
+2007-08-22  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb: Don't reinstall dependencies
+	existing in the install dir.  Don't install dependencies for older
+	versions of the gem we're installing.  #installed_gems now contains
+	loaded gemspecs.  Always prefer local gems.  Handle globs correctly.
+	All deps are now installed into the install_dir.
+	* lib/rubygems/commands/install_command.rb: Switch to
+	Gem::DependencyInstaller.  Warn when -y is given, it will be removed.
+	Try our best to install everything the user asked.
+	* lib/rubygems.rb: Gem.bindir now handles Pathname correctly.
+	* lib/rubygems/remote_fetcher.rb: Don't downcase anymore.
+
+2007-08-21  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb: Add installation from local
+	gems.  Install gems in the correct order.  Handle -E, -f,
+	--ignore-dependencies, -i, -r, -l, -b, -P, -w, -v options for `gem
+	install`
+	* test/gemutilities.rb: Work around OS X /private/tmp.
+	* lib/rubygems/platform.rb: Switch to using arch instead of target_*
+	for JRuby compatibility.  Thanks to Nick Sieger.
+
+2007-08-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_installer.rb: Add working but unfinished
+	Gem::DependencyInstaller.
+	* lib/rubygems/source_info_cache.rb: Add #search_with_source.
+	* lib/rubygems/dependency_list.rb: Move #fill_dependencies to
+	Gem::DependencyInstaller
+	* lib/rubygems/platform.rb: Split from specification.rb.  Add methods
+	to recognize platforms from Config::CONFIG.
+	* lib/rubygems.rb: Add Gem::platforms.
+	* lib/rubygems/specification.rb: Disallow String platforms.
+
+2007-08-18  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache.rb: Search by Gem::Dependenency.
+	* lib/rubygems/source_index: Search by Gem::Dependenency.
+	* lib/rubygems/version.rb: Version can be String or Integer.
+	Gem::Requirement::default is now >= 0.  Gem::Requirement can be built
+	from a Gem::Dependency.
+	* lib/rubygems/dependency_list.rb: Uses TSort now.  Add
+	Gem::DependencyList#fill_dependencies.
+	* lib/rubygems/server.rb: Support quick index.
+
+2007-08-17  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/dependency_list.rb: For diamond dependencies with
+	different versions on the bottom of the diamond, trim all but the
+	latest dependency.  This will prevent gems like hoe from being
+	installed multiple times.
+
+2007-08-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb: Support building mkrf extensions.  Fixes
+	bug #11313.  Patch by Jeremy Hinegardner.
+	* lib/rubygems/installer.rb: Ensure bin files are executable.  Fixes
+	bug #8985 submitted by Ara Howard.
+	* lib/rubygems/installer.rb: Insert installing gem home dir into bin
+	wrapper.  Patch #8818 by Ara Howard.
+
+2007-08-13  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/uninstall_command.rb: Gems with version of 0
+	can now be uninstalled.
+
+2007-08-11  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/config_file.rb: Command-line args override ~/.gemrc
+	now.  Gem.sources is pulled from ~/.gemrc now.  Gem::ConfigFile can
+	write itself out now.
+	* lib/rubygems/commands/sources_command.rb: Now writes out
+	Gem.configuration on changes.  No longer checks source cache on
+	--list.
+
+2007-08-09  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache.rb: Make Gem::SourceInfoCache#search
+	only search gems in Gem.sources.
+	* lib/rubygems.rb: Make Gem::configuration a real Gem::ConfigFile
+	object.
+	* lib/rubygems/commands/query_command.rb: Fix `gem query --details`.
+	Add `gem query --no-versions`.
+	* lib/rubygems/local_remote_options.rb: Make `gem mumble --source URL`
+	only use that source.
+	* lib/rubygems/config_file.rb: Fix Gem::ConfigFile#[]= to match
+	Gem::ConfigFile#[].
+
+2007-08-08  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/commands/specification_command.rb: Match only exact gem
+	names.  Fixes bug #9681.  Patch by Michael DeCandia.
+	* lib/rubygems/commands/unpack_command.rb: Match only exact gem names.
+	Fixes bug #9681.  Patch by Michael DeCandia.
+	* lib/rubygems/commands/contents_command.rb: Match only exact gem
+	names.  Fixes bug #9681.  Patch by Michael DeCandia
+	* lib/rubygems/remote_fetcher.rb: Perform a GET request if the HEAD
+	request doesn't have Content-Length.  Fixes bug #9771.  Patch by Ben
+	Bleything.
+	* lib/rubygems.rb: Clear Gem::searcher when we Gem::clear_paths.
+	Fixes bug #12886.  Submitted by Peter Williams.
+	* lib/rubygems.rb: Add #default_sources and rework #sources to use it.
+	* post-install.rb: No longer runs install_sources.
+	* pkgs/sources: Updated to something what a 0.0.2 would look like, if
+	we ever make one.
+
+2007-08-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/gem_commands.rb: Removed and broken up into individual
+	files.
+	* lib/rubygems/command_manager.rb: Lazily loads gem commands.  Now to
+	use CommandManager just "require 'rubygems/command_manager'" and
+	everything will be there.
+
+2007-08-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/*, test/*: Pushed down dependencies as far as reasonable.
+	Removed Gem::manage_gems.  Now only 14 files are loaded with "require
+	'rubygems'".  Added tests for `gem build` and `gem cert`.
+	* lib/rubygems/extensions.rb: Added common place for all extensions.
+
+2007-07-26  Eric Hodel  <drbrain at segment7.net>
+
+	* test/test_gem_ext_configure_builder.rb: Linux has different behavior
+	for `sh ./configure` when configure is missing.  Fix adapted from
+	Patch #10019 by Donavan Pantke.
+	* lib/rubygems/commands/pristine_command.rb: Compare fully-qualified
+	paths.  Fixes bug #7976 by Lyle Johnson.
+	* lib/rubygems/config_file.rb: Add ConfigFile#[]=, so --proxy
+	command-line option works.  Fixes #8152 by Justin Sabelkko.
+	* lib/rubygems/post-install.rb: Make sure we use the
+	latest-and-greatest RubyGems when running post-install.rb.  Fixes Bug
+	#8411 by Duy Nguyen.
+	* lib/rubygems/remote_fetcher.rb: An empty HTTP_PROXY means no proxy.
+	Fixes Bug #9042 by Michael Brodhead.
+	* lib/rubygems/version.rb: Disallow newlines in version string.  Strip
+	spaces from version string.  Fixes Bug #9499 by Bryce Kerley.
+	* lib/rubygems/commands/sources_command.rb: Fix spelling error.  Fixes
+	Bug #11064 by Chris Eskow.
+
+2007-07-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/indexer.rb: Create the index in /tmp, then move it into
+	place when we're done.  This will prevent spurious bulk index updates
+	from occurring while the quick index is missing.  Remove the option to
+	not build the quick index.
+	* lib/rubygems/commands/generate_index_command.rb: --no-quick is gone.
+	* lib/rubygems/user_interaction.rb: If stdin is not a tty, it is
+	unlikely that gem is going to get a response when asking a question.
+	Patch #10660 by Paul Brannan.
+	* lib/rubygems/validator.rb: Output test failures when using install
+	-t.  Patch #10659 by Paul Brannan.
+	* lib/rubygems/custom_require.rb (Kernel#require): Only rescue a
+	LoadError that matches the file we are requiring.  Patch #10723 by
+	Tyler Rick.
+	* lib/rubygems/remote_fetcher.rb: Support HTTP basic authentication.
+	Patch #8121 by Max Dunn.
+	* lib/rubygems/commands/install_command.rb: Don't raise an error when
+	a gem has no tests.  Patch #11824 by Katsuyuki MIYAMUKO.
+
+2007-07-23  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/commands/contents_command.rb: Add --lib-only option, remove
+	useless --list option.  Feature request #9498 by Martin DeMello.
+	* lib/rubygems/specification.rb: Restrict to only files in
+	#require_paths.  Add #required_rubygems_version.  Feature request
+	#7780 by Eric Hodel.
+	* lib/rubygems/commands/dependency_command.rb: Display dependencies for
+	remote gems.  Feature request #12133 by Eric Hodel.  -r for reverse
+	dependencies is now -R.
+	* lib/rubygems/commands/specification_command.rb: Display
+	specifications for remote gems.  Feature request #12133 by Eric Hodel.
+	* lib/rubygems/installer.rb (Gem::Installer#install): Check
+	required_rubygems_version.
+	* lib/rubygems/user_interaction.rb
+	(Gem::UserInteraction#choose_from_list): Check result for EOF.  Fixes
+	bug #8018.  Patch by Jos Backus.
+	* post-install.rb: Install using absolute path.  Fixes bug #10675.
+	Patch by Jeremy Burks.
+	* lib/rubygems/commands/environment_command.rb: Add RUBY VERSION to
+	environment output.
+	* lib/rubygems/command.rb: Don't worry about duplicated command-line
+	options, OptionParser takes care of them for us.
+
+2007-07-22  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb (Gem::Specification#files): Make it
+	faster
+	* lib/rubygems/command.rb: Better documentation.  -v flag now lets you
+	get to "really verbose" mode which makes the verbose progress meter
+	work.  Add command groups to separate types of commands easily.
+	* lib/rubygems/commands/which_command.rb, bin/gemwhich: Move `gemwhich`
+	under `gem`.
+	* lib/rubygems/commands/mirror_command.rb, bin/gem_mirror: Move
+	`gem_mirror` under `gem`.
+	* lib/rubygems/commands/lock_command.rb, bin/gemlock: Move `gemlock`
+	under `gem`.
+	* lib/rubygems/commands/server_command.rb, bin/gem_server: Move
+	`gem_server` under `gem`.
+	* lib/rubygems/doc_manager.rb (Gem::DocManager#initialize): Only raise
+	when operating on the filesystem.
+	* lib/rubygems/server.rb: Remove option processing, now in
+	Gem::Commands::ServerCommand.
+	* lib/rubygems/commands/generate_index.rb, bin/index_gem_repository.rb:
+	Move `index_gem_repository.rb` to `gem generate_index`.
+	* lib/rubygems/indexer (Gem::Indexer): Extract from
+	index_gem_repository.rb and merge RubyForge changes.
+	* lib/rubygems/command_manager.rb (Gem::CommandManager#run): Print
+	backtrace when --debug is set too.
+	* lib/rubygems/command_manager.rb (Gem::CommandManager#load_and_instantiate):
+	Don't infinitely loop in retry.
+	* bin/gemri: Removed.  Everybody should have ri integration now.
+	* lib/rubygems/config_file.rb: Allow settings to be examined.  Pull
+	settings from .gemrc.
+	* lib/rubygems/commands/environment_command.rb: Add ruby executable
+	and configuration settings to `gem env`.
+	* lib/rubygems/indexer/indexer.rb (Gem::Indexer::Indexer#build_index):
+	Now uses UserInteraction.
+	* various: Use UserInteraction for output.
+	* lib/gemconfigure.rb: Removed. Same as multiple gem commands.
+	* lib/rubygems/commands/contents_command.rb: Removed extra --verbose
+	option.
+	* lib/rubygems/gem_commands.rb (Gem::LocalRemoteOptions): Moved -B,
+	--source, -p from Gem::Commands::common_options.
+
+2007-07-22  Chad Fowler  <chad at chadfowler.com>
+
+	* lib/rubygems/gem_commands.rb: Added another example to the gem
+	example output (Gile Bowkett)
+	* test/test_documentation_generation.rb, lib/rubygems/doc_manager.rb:
+	Added a test for documentation generation and fixed a bug when doc
+	location is not writable.
+
+2007-06-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/gem_path_searcher.rb (Gem::GemPathSearcher): Moved out
+	of lib/rubygems/custom_require.rb and added tests.
+
+2007-06-02  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/source_info_cache.rb (Gem::try_file): Fix for issue
+	where a non-existing source cache file causes the gem command to
+	not find a gem.  This fixes it by marshalling out an empty
+	hash.  (Thanks to Nick Sieger for this fix).
+
+2007-06-01  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems.rb
+	(Gem::OperationNotSupportedError::latest_partials): Changed from
+	match data style to $1 style regexp (on the recommendation of
+	better performance).
+
+2007-05-30  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/source_index.rb (Gem::SourceIndex::update):
+	Modified to get the bulk_threshhold from the configuration.
+	(Gem::SourceIndex::convert_specs): Ryan removed the "reduce_specs"
+	method because it is not needed any more and is creating memory
+	overhead.
+
+	* lib/rubygems/config_file.rb (Gem::ConfigFile): Added
+	bulk_threshhold field to ConfigFile.
+	(Gem::ConfigFile::initialize): Initialize bulk threshhold to 500.
+
+	* lib/rubygems/command.rb
+	(Gem::Command::specific_extra_args_hash): Added
+	-B (--bulk-threshhold) option to allow user specified bulk
+	download threshhold.
+
+2007-05-23  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/commands/sources_command.rb
+	(Gem::Commands::SourcesCommand::initialize): Added a --clear-all
+	option to the sources subcommand.  Clear-all will remove the cache
+	files.
+
+	* lib/rubygems/source_info_cache.rb (Gem): Moved system_cache_file
+	and user_cache_file to class methods so that we can get the file
+	names without creating a SourceInfoCache instance.
+
+2007-05-23  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache.rb: Teach SIC to repair itself
+	when it encounters a bad cache file.
+
+2007-05-14  Chad Fowler  <chad at chadfowler.com>
+		* lib/rubygems/command_manager.rb: Re-added registration for
+	gem cleanup command which I accidentally removed during refactoring.
+
+2007-05-10  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb: Uncommented the require
+	'sources' line.
+
+	* lib/rubygems/source_info_cache.rb: Uncommented the require
+	'sources' line.
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to version 0.9.3
+	in preparation for release.
+
+	* lib/rubygems/package.rb (Gem::TarInput::zipped_stream):
+	Zipped_stream now always uses the in memory string IO buffer.
+	There were just too many problems with ZLib (on windows)
+	otherwise.
+
+2007-03-26  Jim Weirich  <jim at weirichhouse.org>
+
+	*  (Index): new digest technique.
+
+	* lib/rubygems/validator.rb (Gem::Validator::verify_gem): Removed
+	really old MD5 and replaced with gem based digests.  
+	
+	* experimental/deployment.rb (Gem::Deployment::Manager::initialize):
+	New digest technique.
+
+	* experimental/test_deployment.rb (TestDeployment::test_deployed_file):
+	New digest technique.
+
+2007-03-26  Chad Fowler <chad at chadfowler.com>
+
+	* Extracted the big ball of mud that was gem_commands.rb into    
+	separate files.
+
+2007-03-17  Chad Fowler <chad at chadfowler.com>
+
+	* Various ruby 1.8.6 fixes for failing tests.
+	
+	* Updated setup.rb to 3.4.1
+	
+	* Renamed cmd_manager to command_manager to keep names consistent
+	
+	* lib/installer.rb: Rework path checking to use Pathname (ara howard bug #8811)
+	
+2007-03-02  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems.rb: Add bin directory before library directory,
+	otherwise gems like rake don't work.
+
+2007-03-01  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/open-uri.rb: Fix all the infinite loop errors.
+
+	* lib/rubygems.rb: Add dirs from activate after -I and ENV['RUBYLIB']
+	dirs.  Otherwise gems won't allow -I to work when #gem is called.
+
+2007-02-11  Chad Fowler <chad at chadfowler.com>
+
+	* test/gemutilities.rb: Fix to make Windows tests pass. (Anatol Pomozov)
+
+2007-02-05  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to version 0.9.2
+	and made a release.
+
+2007-02-04  Chad Fowler <chad at chadfowler.com>
+
+	* Fixed failing tests (changed from assert_equal to assert_match to 
+	  deal with ARGV inconsistencies in test vs. production).
+
+2007-02-03  Jim Weirich  <jim at weirichhouse.org>
+
+	* Bumped version to 0.9.1.1.
+
+	* lib/rubygems/gem_open_uri.rb: Added the patched open-uri back
+	into the gems software.  Evidently, the 1.8 version of open-uri
+	does not handle authenticating proxies with username and password.
+
+	* lib/rubygems/source_info_cache.rb (Gem::cache_data): Added
+	rescue block to capture bad file loads.  The original rescue was
+	only around the marshal load (bug was probably introduced when the
+	file data was preloaded into a string).
+	(Gem::set_cache_data): Added set_cache_data to be used during
+	testing to avoid reload the cache file over and over.
+
+	* lib/rubygems/gem_commands.rb: Added require for command class so
+	that this file can be loaded independently.
+
+	* lib/rubygems/source_index.rb (Gem::SourceIndex::outdated): Minor
+	cleanup.
+
+	* test/gemutilities.rb
+	(RubyGemTestCase::util_setup_source_info_cache): Minor cleanup
+
+	* test/test_gem_source_info_cache.rb
+	(TestGemSourceInfoCache::test_write_cache_user): Switched to using
+	set_cache_data here and several other places to avoid rereading
+	the cache data over and over again.
+
+2007-02-02  Chad Fowler  <chad at chadfowler.com>
+
+	* lib/rubygems/gem_commands.rb:
+	Fixed gem unpack (broken since 0.9.1)
+
+2007-01-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache.rb (Gem::SourceInfoCache#cache_data):
+	Read the source_cache in binary mode for mswin.
+
+2007-01-16  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Released 0.9.1.
+
+2007-01-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb (Gem::Installer#extract_files): Only allow
+	installation to absolute directories.  (Call File::expand_path first).
+	More informative message for attempting to install with bad path.
+	* post-install.rb: Install sources first, since its rather important.
+
+2007-01-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_info_cache.rb: require 'fileutils', as its
+	needed.
+
+2007-01-12  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb (Gem::Installer#extract_files): Don't
+	allow gems to place files outside the installation directory.  Fixes
+	bug 7751 by Gavin Sinclair.
+
+2007-01-08  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/specification.rb
+	(Gem::Specification::test_suite_file): Added rescue clause for
+	default_executable.
+	(Gem::Specification::add_bindir): Added rescue clause for
+	add_bindir.
+
+	* test/test_specification.rb
+	(TestSpecification::test_pathologically_bad_non_array_stuff_doesnt_goof_up_files):
+	Added a sanity check on hash for some pathologically bad case.
+	(TestSpecification::test_pathologically_bad_exectuables_doesnt_goof_up_hash):
+	Added sanity check for pathologically bad executables field.
+
+2007-01-08  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/gem_commands.rb (Gem::PristineCommand#execute): Better
+	messaging.
+	* lib/rubygems.rb, lib/rubygems/custom_require.rb: Correctly include
+	documentation for methods added to Kernel.
+
+2007-01-07  Eric Hodel  <drbrain at segment7.net>
+
+	* Rakefile: Include GPL.txt.  Fixes bug #7572 by David Lee.
+
+2007-01-06  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to version
+	0.9.0.9.
+
+	* lib/rubygems/specification.rb
+	(Gem::Specification::test_suite_file): Rewrote default_executable
+	to be a bit more explicit.
+	(Gem::Specification::add_bindir): Rewrote the 'files' accessor to
+	handle pathologically bad input.
+	(Gem::Specification::copy_of): Added as_array private method.
+
+	* Rakefile (package_version): Added '*.out' to clobber list.
+	Removed the broken-1.0.0.gem file from the clobber list.
+
+	* test/test_specification.rb
+	(TestSpecification::test_default_executable):
+	Seriously beefed up tests for certain specification issues.
+
+	* test/gemenvironment.rb (TestEnvironment::create): Added the 'f'
+	flag to deleting 'gemhome'.
+
+2006-12-30  Eric Hodel  <drbrain at segment7.net>
+
+	* post-install.rb, lib/rubygems/server.rb: RubyGems now installs RDoc
+	and ri for itself.
+
+2006-12-28  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb (Gem::Installer#build_extensions):
+	Extension build failures now raise Gem::Installer::ExtensionBuildErrors.
+
+2006-12-26  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/package.rb (Gem::Package::TarInput#initialize): Bad
+	packages now raise FormatError instead of a generic RuntimeError.
+	* lib/rubygems/installer.rb (Gem::Installer#install): Raise an
+	InstallError when we have a bad gem file.
+
+2006-12-25  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/custom_require.rb (Gem::GemPathSearcher::find):
+	Removed SUFFIX_PATTERN.  Evidently this was miss during an earlier
+	attempt to remove it.
+	(Gem::GemPathSearcher::matching_file): Changed reference to
+	SUFFIX_PATTERN into a call to Gem.suffix_pattern.
+
+	* Removed tab characters from numerous source files.
+	
+	* lib/rubygems/installer.rb (Gem::Uninstaller::uninstall): Removed
+	stray tab characters.
+
+	* lib/rubygems.rb (Kernel::require_gem): Added file and line
+	number information to require_gem worning (makes it easier to
+	track down those offending lines of code).
+	(Kernel::location_of_caller): Added helper function to determine
+	file and line number of caller.
+
+2006-12-25  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb (Gem::Installer#app_script_text):
+	Simpler, more readable bin script.
+	* lib/rubygems/gem_commands.rb (Gem::PristineCommand#execute):
+	Regenerate bin scripts.  This will clean up require_gem in scripts.
+
+2006-12-24  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb (Gem::RemoteFetcher#fetch_path):
+	Rescue various errors and return a more-friendly error.
+
+2006-12-23  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/command.rb lib/rubygems/gem_commands.rb: Make help
+	output fit in 80 columns.
+	* lib/rubygems/rubygems_version.rb: Bump version to 0.9.0.8, beta
+	time!  (Oops, didn't go into beta.)
+
+2006-12-20  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_fetcher.rb (Gem::RemoteFetcher#fetch_size): Give
+	a sensible error on bad URIs.
+	* lib/rubygems/gem_commands.rb (Gem::SourceCommand): Allow management
+	of sources in source_cache.  Fixes bug #1128.
+	* lib/rubygems.rb (Kernel#require_gem): Add deprecation warning in
+	favor of gem.
+
+2006-12-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb (Gem::ExtBuilder): Refactored for
+	uniformity.
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller#specs_n_sources_matching): Don't display gems
+	that can't be installed.
+	* lib/rubygems.rb, pre-install.rb: Fix installation errors on 1.9.
+	Fixes bug #4536 by Ryan Davis.
+	* lib/rubygems/source_index.rb, lib/rubygems/gem_commands.rb,
+	lib/rubygems-custom_require.rb: Use File.join with glob strings.
+	Fixes bug #1096 submitted by Chad Fowler.
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller#install_dependencies): Make --force actually
+	force.  Fixes bug #7365 by Robert James.
+
+2006-12-18  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/gem_commands (Gem::OutdatedCommand): Add a way to see
+	which gems are out-of-date.
+
+	* setup.rb: Ignore errors for .config and InstalledFiles when
+	the source path is read-only/NFS.  Fixes bugs #1395 and #1374.  Patch
+	by Ryan Davis.
+
+	* bin/gem_server: Pull code out into lib/rubygems/server.rb for
+	reusability.  Closes Feature Request #2220 by Chris Morris.
+
+2006-12-16  Chad Fowler <chad at chadfowler.com>
+
+	* test/: Added functional test for extension gems proving that
+	non-compiling extensions don't result in success message.
+
+	* lib/rubygems/specification.rb: Raise exception if loaded spec is
+	nil.  Closes bug #7299.
+
+	* test/gemenvironment.rb: Clean out gemhome every time to avoid dirty
+	directory failing tests.
+
+	* lib/rubygems/installer.rb: Change uninstall to require a full gem
+	name (not a partial match).  Fixes bug #6007 and related unreported
+	issues.
+
+2006-12-15  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller): Correctly uninstall
+	executables if GEM_HOME is set.  Patch #2264 by Sylvain Joyeux.
+
+	* lib/rubygems.rb (Gem::loaded_specs): Expose list of currently loaded
+	gems.
+
+	* lib/rubygems/gem_commands (Gem::UninstallCommand): Allow multiple
+	gems to be uninstalled at once.
+
+2006-12-14  Eric Hodel  <drbrain at segment7.net>
+
+	* post-install.rb: Don't attempt to read unreadable files.  Fixes
+	bug #2851.
+
+2006-12-13  Eric Hodel  <drbrain at segment7.net>
+
+	* pre-install.rb.rb, post-install.rb: Don't call manage_gems because
+	we don't have sources installed yet.  Bump version requirement to
+	1.8.2 since rubygems/open-uri.rb was removed.  Should fix bug #6206.
+
+	* lib/rubygems/installer.rb (Gem::Installer#build_extensions): Capture
+	stderr into results when building extensions.
+
+	* lib/rubygems/gem_commands.rb (Gem::ContentsCommand): Allow version
+	to be passed to gem contents.  Not backwards compatible, -v now -V and
+	vice versa.  Select newest gem for contents.  Fixes bugs #2723, #7225.
+	Patches by Sava Chankov, Tom Pollard.
+
+	* lib/rubygems/gem_commands.rb (Gem::InstallCommand#execute): Allow
+	install errors to result in non-zero exit code.  Fixes bug #2773.
+
+2006-12-03  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/remote_installer.rb (Gem::RemoteInstaller#install):
+	Add :cache_dir option to override the default.
+
+	* lib/rubygems/remote_installer.rb (Gem::RemoteInstaller#download_gem): 
+	Check cache to see if the gem has been cached before downloading.
+
+2006-12-02  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems.rb (Gem::OperationNotSupportedError::suffixes,
+	Gem::OperationNotSupportedError::suffix_pattern): Removed
+	duplicate copies of the SUFFIX_PATTERN by providing a global
+	method Gem.suffixes and Gem.suffix_pattern.
+
+	* lib/rubygems/remote_fetcher.rb (Gem::open_uri_or_path): Reworked
+	the connection options for the open-uri call.  Since we are not
+	using the rubygems supplied open_uri, we can use some new options
+	available that make proxy handling much easier.
+	(Gem::file_uri): Renamed is_file_uri to file_uri?.
+
+	* lib/rubygems/loadpath_manager.rb (Gem::LoadPathManager::self):
+	Added .jar to list of suffixes.
+
+	* test/functional.rb (FunctionalTest::test_env_remotesources):
+	Changed test to uses Gem.sources (the sources method on
+	remote_fetcher was removed).
+
+	* test/test_remote_fetcher.rb (TestRemoteFetcher): Renamed some of
+	the test constants and instance variables so that they were more
+	consistent and explained the tests a wee bit better.
+	(TestRemoteFetcher::test_no_proxy): Added assert_data_from_server
+	and assert_data_from_proxy to make it clear what the test was
+	doing and give better error messages on errors.
+	(TestRemoteFetcher::assert_data_from_server): Added
+	assert_data_from_server.
+	(TestRemoteFetcher::assert_data_from_proxy): Added
+	assert_data_from_proxy.
+
+2006-11-30  Chad Fowler <chad at chadfowler.com>
+
+	* lib/rubygems/open-uri.rb: Removed the duplicated library.
+
+2006-11-30  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification (Gem::Specification#eql?): Allow gemspecs
+	to be used intelligently with Array#- and Array#uniq.
+
+	* lib/rubygems/installer.rb: Return extension-building results in
+	Exception on build failure.
+
+	* lib/rubygems/remote_installer.rb: Ensure gems with similar names
+	cannot be matched for install.  (Broken when searching was removed
+	from RemoteInstaller.)
+
+2006-11-29  Eric Hodel  <drbrain at segment7.net>
+
+	* post-install.rb: Now requires rbconfig.
+
+	* lib/rubygems/specification.rb, lib/rubygems/version.rb: Fixed many
+	ivar warnings due to YAML specs.
+
+	* lib/rubygems/validator.rb, lib/rubygems/validator.rb
+	(Gem::Validator#unit_test Gem::RemoteInstaller::): Ensure the
+	current directory is restored.
+
+	* lib/rubygems/remote_fetcher.rb, lib/rubygems/remote_installer.rb,
+	lib/rubygems/installer.rb: Raise more-friendly and less-deadly errors.
+
+	* lib/rubygems/remote_installer.rb (Gem::RemoteInstaller#install):
+	Create version requirement correctly.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller#find_gem_to_install): Allow RemoteInstaller to
+	work with SilentUI.
+
+	* lib/rubygems/remote_fetcher.rb (RemoteFetcher#open_uri_or_path):
+	Don't double-require open-uri.
+
+2006-11-27  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/specification.rb
+	(Gem::Specification#default_executable):  Fixed bug where @executables
+	could be nil when loaded from index.
+
+2006-11-21  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/source_index.rb (Gem::SourceIndex#latest_specs):  Grab
+	the latest versions of everything in the index.  Written by Ryan
+	Davis.
+
+2006-11-20  Rich Kilmer  <rich at infoether.com>
+
+	* lib/rubygems/cmd_manager.rb: Added PristineCommand
+
+	* lib/rubygems/gem_commands.rb: Added PristineCommand to restore
+	gems to pristine condition in the event of files begin deleted
+	based on the cached .gem file
+
+2006-11-19  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/*_fetcher.rb: Removed code specific to remote source
+	index updating.
+
+	* lib/rubygems/remote_installer.rb (Gem::RemoteInstaller#search):
+	Moved to Gem::SourceInfoCache#search
+
+	* lib/rubygems/source_info_cache.rb: Taught to update itself
+
+	* lib/rubygems/source_info_cache_entry.rb: Taught to update itself
+
+	* lib/rubygems/source_index.rb: Taught to update itself from a uri.
+
+2006-11-18  Chad Fowler  <chad at chadfowler.com>
+
+	* lib/rubygems/installer.rb: Applied Kevin Clark's patch to make
+	RubyGems recognize mkrf files.
+
+2006-11-17  Eric Hodel  <drbrain at segment7.net>
+
+	* test/test_remote_fetcher.rb:  Don't allow files in Dir.pwd to make
+	tests fail.  Spotted by Chad Fowler.
+
+	* lib/rubygems/remote_installer.rb (Gem::RemoteFetcher,
+	Gem::CacheFetcher):  Break out of remote_installer.rb into separate
+	files.
+
+	* lib/rubygems/remote_installer.rb (Gem::SourceInfoCache,
+	Gem::SourceInfoCacheEntry):  Allow requiring just the source cache
+	without the remote fetcher.
+
+2006-11-16  Eric Hodel  <drbrain at segment7.net>
+
+	* test/test_local_cache.rb: Moved to better name
+
+	* test/test_gem_source_info_cache.rb: Renamed test methods to match
+	implementations.  Sorted test names.
+
+	* lib/rubygems/remote_installer (Gem::SourceInfoCache): cache_data no
+	longer resets dirty flag.  Sped up source cache loading.  Exposed
+	cache file name in use.
+	
+2006-11-15  Eric Hodel  <drbrain at segment7.net>
+
+	* test/, lib/: Made files -w clean.
+
+	* test/: Made tests run independently.
+
+	* Rakefile: Tests now run with warnings on.
+
+2006-11-14  Eric Hodel  <drbrain at segment7.net>
+
+	* lib/rubygems/user_interaction.rb (Gem::StreamUI#progress_reporter):
+	Fix for Gem.configuration.verbose = nil, false
+
+	* lib/rubygems.rb (Gem::configuration): Fix RakeFileUtils pollution.
+
+2006-10-05  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/installer.rb (Gem::Installer::shebang): Updated to
+	optionally call env_shebang if the command line option is set.
+	(Gem::Installer::shebang_env): Added this method.
+
+2006-09-25  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to version
+	0.9.0.6.
+
+	* lib/rubygems/security.rb (Gem::Security::Exception): Added
+	permissions for cert files and directories.
+	(Gem::Security::Policy::verify_gem): File.exists? => File.exist?
+	(Gem::Security::self.verify_trust_dir): Beefed up code to create
+	trust directory structure.
+	(Gem::Security::self): Apply permissions when creating trust
+	files.
+
+	* lib/rubygems/package.rb (TarInput::initialize): File.exists? =>
+	File.exist?
+
+2006-09-24  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems.rb
+	(Gem::OperationNotSupportedError::configuration): Added
+	method_missing to configuration hash to allow nicer reference
+	syntax.
+
+2006-09-22  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::initialize): Proxy patch fixup to
+	escape user/password from Anatol Pomozov.
+	(Gem::RemoteSourceFetcher::connect_to): Proxy patch fixup to
+	escape user/password from Anatol Pomozov.
+
+	* test/test_remote_fetcher.rb (TestRemoteFetcher::setup): Proxy
+	patch fixup to escape user/password from Anatol Pomozov.
+	(TestRemoteFetcher::test_no_proxy): Proxy patch fixup to escape
+	user/password from Anatol Pomozov.
+
+	* test/io_capture.rb (Gem::IoCapture): Created new IoCapture
+	module to handle capturing output of code under test.
+
+	* test/test_installer.rb
+	(TestInstaller::test_generate_bin_symlinks_win32): Removed ugly
+	$TESTING hack and substituted new io capture module.
+	(TestInstaller::test_install_with_message): Removed one-off stdout
+	capture and replaced with new IO Capture module.
+
+2006-09-19  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to version
+	0.9.0.3.
+
+	* test/test_version_comparison.rb (TestRequirementEquality): Added
+	more tests for Dependency equality testing and one additions check
+	for requirement vs non-requirement equality.
+
+	* lib/rubygems/version.rb (Gem::Dependency::==) Fixed '=' bug in
+	'==' code.
+
+2006-09-18 Chad Fowler <chad at chadfowler.com>
+
+	* lib/rubygems/remote_installer.rb
+	Only show the last 3 gem versions on a multiplatform remote
+	install list.
+
+2006-09-18  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller::install): Added Hugh Sasse's patch for
+	skipping gems on install.
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to 0.9.0.2.
+
+	* lib/rubygems/version.rb (Gem::Dependency::hash): Added hash code
+	--http-proxy, the ENV var http_proxy and with no proxy.
+
+2006-08-26  Jim Weirich  <jim at weirichhouse.org>
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller::download_gem): Fixed download_gems so that
+	it properly passes the proxy option to the fetcher class. (based
+	on patch by Andy Shen).
+
+2006-08-12  Jim Weirich  <jim at weirichhouse.org>
+
+	* bin/index_gem_repository.rb (Indexer::sanitize): Added a
+	sanitize step to the gem index generation in the hope of avoiding
+	problems with non-ASCII names in the yaml data.
+
+2006-06-14  Jim Weirich  <jim at weirichhouse.org>
+
+	* Rakefile (announce): Added 1.9 hack for ENV['CERT_DIR'].  Remove
+	this in the future if 1.9 behavior changes.
+
+2006-06-13  Jim Weirich  <jim at weirichhouse.org>
+
+	* Rakefile: ENV['CERT_DIR'] is now '' rather than nil.
+
+	* lib/rubygems/specification.rb (Gem::Specification::initialize):
+	Eric added some 1.9 compatibility code (funcall vs send).
+
+	* lib/rubygems/package.rb (TarOutput::self): Eric added some 1.9
+	compatibility code (funcall vs send).
+
+	* experimental/deployment.rb (Gem::Deployment): Moved the
+	deployment code out of the live code base into the experimental
+	directory.  The code wasn't used and the tests were not all
+	passing.
+
+2006-06-11  Jim Weirich  <jim at weirichhouse.org>
+
+	* bin/gemri: Added gemri to bin directory.
+
+	* lib/rubygems/custom_require.rb (Gem::GemPathSearcher::find):
+	Added .rbw to suffix pattern in custom_require.
+
+2006-06-07  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems.rb: Added copyright notices to all Ruby files.
+
+2006-04-07  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_commands.rb (Gem::RDocCommand::execute): Added
+	RI option to the rdoc subcommand.
+
+2006-04-05  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/test_parse_commands.rb
+	(TestParseCommands::test_parsing_update_options): Fixed unit tests
+	to assert that the install dir is expanded.
+
+	* lib/rubygems/doc_manager.rb (Gem::DocManager::generate_ri):
+	Break out from generate_rdoc to support installing all RI docs
+	first.
+
+	* lib/rubygems/gem_commands.rb
+	(Gem::InstallUpdateOptions::add_install_update_options): Expanded
+	repository directory to absolute path.
+	(Gem::InstallCommand::execute): Make sure that *all* of the RI
+	documents are generated before generating any RDocs (due to a bug
+	in the RDoc library).
+
+	* lib/rubygems/installer.rb (Gem::ExtExtConfBuilder::self): Fixed
+	typo in ExtExtConfBuilder that prevented C based gems to install.
+	(Gem::ExtExtConfBuilder::self): Installed patch to prevent the
+	overriding of target_prefix in native extensions (thanks to Aaron
+	Patterson for the patch).
+
+2006-04-04  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped to version
+	0.8.11.10.
+
+	* lib/rubygems/incremental_fetcher.rb
+	(Gem::IncrementalFetcher::update_cache): Now falls back to bulk
+	updates if the number of gems if over 50.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::source_index): Added "bulk" to the
+	update message to differentiate it from the incremental message.
+
+	* lib/rubygems/specification.rb
+	(Gem::Specification::Specification): Modified to add dashes to
+	gemspecs generated under Ruby 1.8.3.  This makes it easier to run
+	RubyGems on a 1.8.2 system.
+
+2006-04-01  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/doc_manager.rb (Gem::DocManager::run_rdoc): Changed
+	exception handler to print error message if document generation
+	fails, but then to continue with the rest of the installation.
+	Permission errors still terminate the install because if one
+	install fails because of permission problems, chances are that all
+	will fail.
+	(Gem::DocManager::install_ri): Removed wrapping of exceptions with
+	DocumentError.  Most exceptions now don't propagate out of
+	run_rdoc.
+	(Gem::DocManager::install_rdoc): Removed wrapping of exceptions
+	with DocumentError.  Most exceptions now don't propagate out of
+	run_rdoc.
+
+2006-02-23  Jim Weirich  <jim at weirichhouse.org>
+
+	* bin/index_gem_repository.rb (MasterIndexBuilder::cleanup): Fixed
+	bug where we were trying to read the index file (to compress it)
+	before it was closed, often leading to a truncated index file.
+
+Tue Jan 24 16:26:13 2006  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/config_file.rb
+	Luca Pireddu reported a fatal error when permissions on
+	.gemrc were too restrictive.  Fixed.
+
+Tue Dec  6 14:51:13 2005  Jim Weirich  <jim at tardis>
+
+	* lib/rubygems/source_index.rb
+		(Gem::SourceIndex::load_specification): Added an untaint call to
+		make the code run in SAFE=1 mode under 1.8.3.
+	(Gem::SourceIndex::load_gems_in): Untaint here too.
+
+	* lib/rubygems/installer.rb (Gem::Installer::install): Untaint
+		here too.
+	(Gem::Installer::extract_files): Untaint here too.
+
+	* lib/rubygems/custom_require.rb
+		(Gem::GemPathSearcher::matching_file): Untaint here too.
+
+	* test/gemenvironment.rb: Added $SAFE=1 to the test environment to
+		make sure we can run in $SAFE mode.
+
+2005-12-03  Jim Weirich  <jim at tardis>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Bumped version to
+	0.8.11.6'
+
+	* lib/rubygems/user_interaction.rb
+	(Gem::StreamUI::SimpleProgressReporter::done): Added several new
+	progress reporters.
+
+	* lib/rubygems/command.rb
+	(Gem::Command::specific_extra_args_hash): Added --verbose
+	processing.
+	
+	* lib/rubygems/config_file.rb (Gem::ConfigFile::handle_arguments):
+	Added --traceback as alias for --backtrace (I always get them
+	confused).
+	(Gem::ConfigFile::initialize): Added a verbose option.
+
+2005-11-28  Jim Weirich  <jim at tardis>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::SourceInfoCacheEntry::replace_source_index): Fixed the
+	SourceIndexCacheEntry so that it will manufacture an empty source
+	index if given a nil value for the +si+ value.
+
+2005-11-08  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems.rb: Ara Howard's fix to allow 0.0.0 to be a valid gem
+	version.
+
+2005-11-08  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: Fixed bug in gem unpack.  It was
+	sorting incorrectly, resulting in the wrong version being unpacked in
+	some edge cases. Thanks to Jakob Skjerning for the detailed bug report.
+
+2005-11-03  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/installer.rb: Fixed bug that would cause the executables
+	from the wrong gem to be uninstalled if the names matched the same
+	regex.  Thanks Eric Hodel.
+
+2005-11-01  Jim Weirich  <jim at tardis>
+	* lib/rubygems/gem_commands.rb (Gem::UpdateCommand::initialize):
+	Upgrade => Update change.
+	(Gem::UpdateCommand::execute): Upgrade => Update change.
+	(Gem::UpdateCommand::execute): Upgrade => Update change.
+
+2005-11-01  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: Allow gem unpack to accept a gem file
+	path instead of gem name: gem unpack mygem-1.0.0.gem.
+
+2005-10-31  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/installer.rb: Tilman Sauerbeck's patch to support
+	extensions built with Rake!
+
+2005-09-13  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/package.rb (TarInput::initialize): Removed
+	requirement for SSL when signatures are found in a gem.  Only
+	require SSL if the security policy requires checking the
+	signatures.
+
+	* lib/rubygems/custom_require.rb (Kernel::require): Disabled
+	autorequire during custom require.
+
+2005-09-07  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_openssl.rb (Gem::ensure_ssl_available): Added a
+	test in gem_openssl to make sure the ruby portion of ssl is also
+	loaded.
+
+2005-08-31  Jim Weirich  <jim at weirichhouse.org>
+
+	* Rakefile (install): Changed the rake install task to use setup.rb.
+
+2005-07-08  Chad Fowler  <chad at chadfowler.com>
+
+	* lib/rubygems/remote_installer.rb: Applied Daniel Roux's patch
+	to make RubyGems work with authenticating proxies.
+
+2005-07-08  Jim Weirich  <jim at weirichhouse.org>
+
+	* Preparing for release 0.8.11.
+
+2005-06-12  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/installer.rb
+	(Gem::Installer::installation_satisfies_dependency): Refactored
+	dependency check into ensure_dependency! and
+	installation_satisfies_dependency?.
+
+2005-06-12  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems.rb,lib/rubygems/installer.rb: Applied Mark Hubbart's
+	* lib/rubygems/remote_installer.rb: Applied David Glasser's install-
+	* Applied Paul Duncan's incredibly complete gem signing patch.
+	Thanks, Paul!
+	* lib/rubygems/installer.rb: Fixed bug in installer that caused
+	dependency installation not to work.
+
+2005-06-06  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/specification.rb: Fixed Erik hatcher's reported bug
+	of gem directories having "-" at the end of their names (e.g.
+	"BlueCloth-1.0.0-".
+
+2005-06-01  Jim Weirich  <jim at weirichhouse.org>
+
+	* scripts/specdoc.rb (_resolve_links): Updated to generate hieraki
+	format so it can be included in the docs.rubygems.org site.
+
+	* test/test_specification.rb (TestSpecification::test_to_ruby):
+	Fixed test on date that hard-coded a specific date.
+
+2005-05-29  Jim Weirich  <jim at weirichhouse.org>
+
+	* Changes from the Seattle Code fest: (1) Package list command
+	(e.g. gem inspect GEM).  (2) .gemrc settings now allow cvsrc like
+	options to set defaults per subcommand.  (3) The autorequire spec
+	attribute will now accept a list.  (4) Binwrappers vs symlinks
+	(more info to follow).  (5) Substituted Time for Date in specs,
+	increasing performance dramatically in an important area.
+
+2005-05-04  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems.rb (Gem::Exception::find_home): Changed rescue
+	clause from Exception to StandardError.  Exception doesn't seem to
+	catch everything ... I'm not sure I understand why.
+
+2005-04-29  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/specifiation.rb: Marcel Molina's patch to discover
+	which attributes in the spec are Array attributes.
+
+2005-04-27  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: -y is now a synonym for 
+	--include-dependencies
+
+2005-04-21  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/installer.rb: Added non-require_gem dependency check
+	for installation.
+
+2005-04-03  Chad Fowler <chad at chadfowler.com>
+
+	* pre-install.rb: Added version check to RubyGems installation.
+
+2005-03-25  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/rubygems_version.rb (Gem): Created release for
+	0.8.10.
+
+	* lib/rubygems/gem_commands.rb
+	(Gem::UpdateCommand::do_rubygems_update): Update --system now runs
+	the ruby command directly rather than trying to load the
+	update-rubygems command.  There were too many things to go wrong
+	with the old way.
+
+2005-03-24  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller::find_dependencies_not_installed): Fixed to
+	reload source index before attempting to detect dependencies.
+
+2005-03-23  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller::find_dependencies_not_installed): Switched
+	to using SourceIndex#find_name to detect missing dependencies,
+	avoiding a gem activation during an install.
+
+	* lib/rubygems/installer.rb (Gem::Installer::install): Removed
+	activate call from install step.  If we need to do something about
+	dependencies at this time, then we need a better way to do them.
+
+	* lib/rubygems.rb: Removed the require for rubygems/timer.
+
+2005-03-16  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/gemenvironment.rb (TestEnvironment::create): Added require
+	on gem/builder.
+
+	* lib/rubygems/source_index.rb (Gem::SourceIndex::initialize):
+	Allowing default argument to new to be an empty hash.
+	(Gem::SourceIndex::from_installed_gems): Refactored into a class
+	method that invokes a instance method.
+	(Gem::SourceIndex::refresh): Refresh now does a complete reload
+	from disk.  This should be more accurate that the earlier version.
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller::uninstall): removed
+	unneeded refresh!.
+
+	* lib/rubygems.rb (Gem::Exception::source_index): Removed
+	automatic refresh from Gem.source_index ... it wasn't reliable
+	when removing installed gems.
+	(Gem::Exception::activate): Added detection of previously loaded
+	gems.
+
+2005-03-15  Chad Fowler  <chad at chadfowler.com>
+
+	* bin/gem_server: (htonl) rdoc opens in existing browser window.
+
+2005-03-14  Jim Weirich  <jim at weirichhouse.org>
+
+	* Released 0.8.8
+	
+2005-03-14  Jim Weirich  <jim at weirichhouse.org>
+
+	* Released 0.8.7
+	
+2005-03-13  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/installer.rb (Gem::Installer#shebang): Refactored and
+	stripped result to avoid ^M issues.
+
+2005-03-11  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_commands.rb (Gem::DependencyCommand): Added a
+	new command "gem dependency" to show the dependencies of an
+	installed gem.
+
+	* lib/rubygems/cmd_manager.rb (Gem::CommandManager::initialize):
+	Added DependencyCommand to the command manager registrar.
+
+	* lib/rubygems/version.rb (Gem::Requirement): Unnested Requirement
+	from the Version class.  There was no benefit to having it nested.
+	Gem::Version::Requirement is set to point to the new class so to
+	be compatible with old gems.
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller::ask_if_ok): Changed
+	uninstaller confirm message to read 'Continue with uninstall'.
+	Its clearer that way.
+
+	* lib/rubygems.rb (Gem::Exception::required_location): Switch to
+	use SourceIndex#find_name rather than search.  Made sure a nil
+	value is returned with a path is not found.
+
+	* lib/rubygems/source_index.rb (Gem::SourceIndex::search): Changed
+	parameter name to gem_pattern to emphasize using Regex in search.
+	(Gem::SourceIndex::find_name): Added find_name to handle the
+	common case of searching for an exact match on the short name.
+
+	* lib/rubygems.rb (Gem::Exception::activate): Make sure that
+	activate more closely adheres to honoring the auto_require=>false
+	request.
+	(Gem::Exception::report_activate_error): Out of line error
+	reporting for activate.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller::find_dependencies_not_installed): Found
+	another location that was using require_gem with auto_require.
+	Fixed to use :auto_require=>false.
+
+	* lib/rubygems/gem_commands.rb
+	(Gem::InstallUpdateOptions::add_install_update_options): Added
+	--ignore-dependencies option.  Still needs to be wired to logic.
+
+	* lib/rubygems/installer.rb (Gem::Installer::install): Added call
+	to require_gem_with_options.
+
+	* lib/rubygems.rb (Kernel::require_gem_with_options): Added to
+	allow easier specification of the autorequire flag for
+	Gem.activate.
+
+2005-03-10  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::normalize_uri): Normialize a URI to
+	start with http:// if it does not already.
+
+	* test/test_deployment.rb (TestDeployment::xtest_deploy_sources):
+	Disabled this test.  It is part of the new deployment software and
+	is not working yet.
+
+2005-03-09  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/gemconfigure.rb (Gem::self): Added to aid dynamic
+	versioning.
+
+	* lib/rubygems/command.rb (Gem::Command::command_manager): Moved
+	command_manager to base class.
+
+	* lib/rubygems/gem_commands.rb (Gem::CleanupCommand::execute):
+	Both implicit and explicit gems now work with cleanup.  
+
+2005-03-08  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller::ok_to_remove):
+	Fixed source index to be loaded from the installed gems when doing
+	an "OK TO REMOVE" dependency check.
+
+2005-03-06  Rich Kilmer <rich at infoether.com>
+	* lib/rubygems/deployment.rb: beginning of a deployment capability
+
+	* test/test_deployment.rb: first tests of new deployment system
+
+2005-03-04  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: Small bugfix for the case when you
+	pass in a gem name (or more) to cleanup for the cleanup command.
+
+2005-03-04  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller::ok_to_remove):
+	Reworked logic in uninstall to be intelligent about dependencies.
+	We only complain about dependencies if removing a gem will cause a
+	dependency error.  The uninstaller now checks for :ignore, :all
+	and :executables options.
+
+	* lib/rubygems/cmd_manager.rb (Gem::CommandManager::initialize):
+	Registered Cleanup command.
+
+	* lib/rubygems/gem_commands.rb (Gem::CleanupCommand): Added
+	Cleanup command to gem.
+	(Gem::UninstallCommand::initialize): Added --all, --ignore and
+	--executables options to uninstall.  This helps to avoid excessive
+	YESes all the time.
+
+2005-02-28  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::LocalSourceInfoCache::write_cache): Open cache file in
+	binary mode.
+
+2005-02-28  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/config_file.rb: don't warn about not being able to
+	find config file.
+	* lib/rubygems/doc_manager.rb: (for DHH) don't install rdoc docs for
+	* lib/rubygems/gem_commands.rb: Print which gems are updated on 'gem
+	update'.  If --system is used, report that the rubygems system
+	software has been updated.
+	* lib/rubygems/installer.rb: Cleaned up the uninstall has_dependents
+	logic and output.  It was misleading and buggy before.
+
+2005-02-27  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/config_file.rb
+	(Gem::ConfigFile::default_config_file_name): Fixed bug in finding
+	home directory for the .gemrc file.
+
+2005-02-27  Chad Fowler  <chad at chadfowler.com>
+
+	* Released 0.8.6
+
+	* Fixed a small bug with shebang construction
+
+2005-02-26  Jim Weirich  <jim at weirichhouse.org>
+
+	* Released 0.8.5
+
+	* lib/rubygems/doc_manager.rb (Gem::DocManager::generate_rdoc):
+	Removed warning about generating rdocs on gems w/o an rdoc flag.
+
+	* lib/rubygems/gem_commands.rb
+	(Gem::UpdateCommand::do_rubygems_update): Added --system option to
+	update to specifically update the version of rubygems.
+	(Gem::UpdateCommand::which_to_update): Fixed some refactoring bugs
+	in the which_to_update method.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::LocalSourceInfoCache::read_cache): switched to Marshal
+	rather than Yaml for local cache.
+
+	* bin/gem: Added requirement for Ruby >= 1.8.0.
+
+2005-02-10  Chad Fowler  <chad at chadfowler.com>
+	* bin/gem_server: Added Martin Ankerl's wonderful new gem_server
+	template
+
+2005-01-27  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: Fixed
+	`gem update` so it accepts a list of gems to update and _only_
+	updates those.
+	* lib/rubygems/installer.rb: Fixed a bug in the new shebang code.
+	* lib/rubygems/remote_installer.rb: Attempt to fix Curt Hibbs'  
+	reported Proxy bug without actually having a proxy to test with.
+
+2005-01-22  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/custom_require.rb: Lyle Johnson's fix for Bug #1379
+
+2005-01-20  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/validator.rb: Applied Austin Ziegler/Kasper Schiess's
+	patch to fix unit test running bug.
+
+2005-01-14  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/installer.rb: attempt at fixing Ryan Davis's
+	reported Shebang bug.  STILL NOT WORKING, because it doesn't work
+	with ^M characters.
+	* lib/rubygems/config_file.rb: small but ugly error fixed if no
+	config file exists.
+	* lib/rubygems/remote_installer.rb: Fixed bug http://rubyforge.org/tracker/index.php?func=detail&aid=1331&group_id=126&atid=575.
+
+2005-01-01  Chad Fowler  <chad at chadfowler.com>
+	* Released 0.8.4
+
+2004-12-31  Jim Weirich  <jim at weirichhouse.org>
+
+	* Rakefile: Switch to standard Rake test tasks.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::read_data): Added a retry to try a
+	lower case gem name if the open failed.  This fixes a problem
+	where case differences are preventing some gems from installing.
+
+2004-12-29  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_commands.rb (Gem::InstallCommand::execute):
+	Changed the RemoteInstaller to take an options hash rather than
+	individual options.  This will leave the interface more resilient
+	to changes as more options are added
+	(e.g. --install_dependencies).
+
+	* lib/rubygems/specification.rb (Gem::Specification): Marked array
+	attributes explicitly.  This allows for explicit conversion to
+	arrays when assigned.
+
+	* test/test_specification.rb
+	(TestSimpleSpecification::test_array_attributes): Added test for
+	array_attributes forcing values to arrays.
+
+2004-12-28  Jim Weirich  <jim at tardis>
+
+	* lib/rubygems.rb (Gem::Exception::ensure_gem_subdirectories):
+	Fixed the Ryan Davis patch to work correctly when directories are
+	not writable.
+	
+2004-12-18  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/version.rb: Erik Veenstra's sort patch.
+	* lib/rubygems.rb: Ryan Davis's installation bug fix.
+
+2004-12-14  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* test/test_loadmanager.rb: invalidated it as a unit test; it's
+	incompatible with custom_require.rb.
+
+2004-12-12  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/custom_require.rb: simple bug fix.
+
+2004-12-12  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/custom_require.rb: new file to replace
+	loadpath_manager.rb and speed up the custom require functionality.
+
+	* lib/rubygems/timer.rb: new file; simple benchmarking tool that's
+	useful at the moment but needn't stay in RubyGems permanently.
+
+	* lib/rubygems/source_index.rb: include Enumerable and implement #size
+	and #length.
+
+	* lib/rubygems/specification.rb: removed lazy initialisation of
+	attributes to reduce #copy_of invocations; folded
+	Specification.copy_of into Specification#copy_of.
+
+	* lib/rubygems.rb: require 'rubygems/custom_require' instead of
+	'rubygems/loadpath_manager'; removed out of date documentation; added
+	"require 'rubygems/timer'" to temporarily assist with benchmarks.
+
+2004-12-07  Jim Weirich  <jim at weirichhouse.org>
+
+	* Released 0.8.3
+
+2004-12-06  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/test_specification.rb
+	(TestLegacyYamlSpecification::test_load): Fixed test to avoid the
+	__FILE__ stuff.  Running tests from rakefile guarantees that the
+	file paths start from the right location.
+
+	* pkgs/sources/sources.gemspec: Made Gem.sources_spec idempotent.
+
+	* lib/rubygems/specification.rb (Gem::Specification::initialize):
+	Added @@gather to Gem::Specification to facilitate proper loads.
+	(Gem::Specification::Specification): Added Specification.load.
+
+	* lib/rubygems/source_index.rb (Gem::SourceIndex): Fixed comments
+	'long name' => 'full name'.
+
+	* lib/rubygems/gem_commands.rb (Gem::BuildCommand::load_gemspecs):
+	Changed to use Gem.Specification.load.
+
+	* Rakefile: Added sources-*.gem to clobber list.
+	(egrep): Upgraded the DBG finder to include breakpoint.
+
+	* post-install.rb (install_sources): Using block version of chdir.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::LocalSourceInfoCache::read_cache): Fixed initialization of
+	cache.
+
+	* lib/rubygems.rb: Updated version to 0.8.2.
+
+2004-12-04  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::LocalSourceInfoCache::writable_file): Now just returns the
+	selected cache file (which was selected based on writability).
+	(Gem::LocalSourceInfoCache::try_file): Added try_file to determine
+	if a file is a candidate for a cache file.
+	(Gem::LocalSourceInfoCache::select_cache_file): Added failure if
+	there are not valid cache file candidates.
+
+	* lib/rubygems.rb (Gem::Exception): Renamed @@cache to
+	@@source_index.
+	(Gem::Exception::source_index): Renamed Gem.cache to
+	Gem.source_index (but left cache as an alias).
+
+2004-12-03  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb (Gem::LocalSourceInfoCache):
+	Added a local cache manager object to implement the read/write
+	policies on the system and user cache files.
+	(Gem::LocalSourceInfoCache::update): Added update and flush to the
+	caching fetcher so that it knows when it needs to update the local
+	cache files.
+	(Gem::RemoteInstaller::initialize): Switched to using a cached
+	fetcher in the remote installer.  All the caching logic was
+	removed from the installer.  User writable cache files are now
+	supported.
+	(Gem::RemoteInstaller::write_gem_to_file): write_gem_to_file now
+	will create the path if needed.
+
+2004-12-02  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/package.rb (TarInput::zipped_stream): To workaround
+	a problem with earlier than 1.2.1, we read the zipped data into a
+	string, and then return an IO object on that string.
+	(TarInput::each): Refactored getting a stream to the zipped data
+	into <tt>zipped_stream</tt>.
+
+2004-12-01  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::convert_spec): We now proprocess the
+	yaml string data to reduce it in size.  This was done to
+	workaround a problem with large YAML files (although it is just a
+	temporary fix because our yaml data keeps growing and growing).
+
+	* Rakefile: Added more targets to the clobber target.
+
+	* test/test_remote_fetcher.rb
+	(TestRemoteFetcher::test_explicit_proxy): Added tests for proxy
+	support.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::connect_to): Refactored to add proxy
+	support.
+
+2004-11-28  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/loadpath_manager.rb: Added Mauricio's patch to work
+	around string contains null byte issue.
+
+2004-11-27  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteSourceFetcher::get_size): Switched from open-uri with
+	early abort to an HTTP.head call to get the size of the yaml file
+	on the server.
+
+2004-11-26  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/test_specification.rb
+	(TestDefaultSpecification::test_defaults): Added test for some
+	basic defaults in a gem spec.
+
+	* test/test_remote_installer.rb (MockFetcher::source_info): Made
+	the fake test data more realistic.
+	(TestRemoteInstaller::test_source_info): Improved tests.
+
+2004-11-26  Jim Weirich  <jim at tardis>
+
+	* test/test_remote_installer.rb (MockFetcher): Added MockFetcher
+	to make testing the remote installer easier. Currently there are
+	two remote installer test classes.  Eventually TestRemoteInstaller
+	will succeed RemoteInstallerTest, which is very incomplete.
+
+	* test/test_package.rb (TC_TarReader::TC_TarInput): Made the unit
+	test ignore the setgid bit.  The setgid bit doesn't work on my
+	laptop for some reason.  This may be a problem with my laptop
+	rather than with this code.  Should investigate further.
+
+	* lib/rubygems/remote_installer.rb (Gem::RemoteSourceFetcher):
+	Added a Fetcher object to the remote installer to handle all the
+	details of getting the remote information.  This allows testing
+	the logic of the remote installer without actually doing remote
+	calls.
+	(Gem::RemoteInstaller::sources): Renamed get_caches to
+	source_info.  The problem is that cache is too generic and there
+	are actually several things that we will cache in the system.
+
+	* lib/rubygems/cache.rb (Gem::Cache::self): Changed interface to
+	from_installed_gems slightly.
+	(Gem::Cache::self): Reordered rescue clauses so that the syntax
+	exception might actually be handled.
+
+	* lib/rubygems.rb (Gem::Exception::ensure_gem_subdirectories):
+	Dumped the check_gem_subdirectories method to use the almost
+	identical ensure_gem_subdirectories method.
+	(Gem::Exception::ensure_gem_subdirectories): Only attempt to
+	create the gem subdirectories if we can actually write them.
+
+	* bin/gem_server: Added date of last file modification to header
+	of /yaml.  This is in preparation for using a head command with
+	date/time stamping in fetching the source cache.
+
+2004-11-25  Ryan Davis <ryand at zenspider.com>
+	* lib/rubygems.rb: Added GEM_SKIP functionality, which will tell
+	loadpath_manager not to load specific libs from gems.  For
+	testing/ development purposes.  Created by Ryan Davis.
+
+2004-11-24  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/specification.rb: Allow multiple authors per gem.
+	* lib/rubygems/gem_commands.rb: command line error message if you
+	run 'gem install' with no args.
+	* lib/rubygems/loadpath_manager.rb: Fixed @specs bug as reported by
+	Lothar Schulz on ruby-talk.
+
+2004-11-07  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems.rb,lib/rubygems/installer.rb,lib/rubygems/cache.rb
+	lib/rubygems/remote_installer.rb,lib/rubygems/gem_commands.rb: 
+	Fixes to make non-root installation work properly.  Still need to
+	fix uninstallation.
+	* lib/rubygems/gem_commands.rb: Allow multiple gems/gem names on the
+	command line for install.
+
+2004-10-31  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/version.rb,test/test_version_comparison.rb: Patrick May's
+	* post-install.rb: Patrick May's fix for rubygems lib not being found
+	during install.
+
+2004-10-29  Chad Fowler <chad at chadfowler.com>
+	* packages/,pkgs,install.rb: renamed "packages" to "pkgs" to avoid
+	* remote_installer.rb: Added user-agent reporting for remote
+	operations
+	* setup.rb,install.rb,bin/update_rubygems: removed install.rb and 
+	added setup.rb and post-install.rb.  Changed update_rubygems so that
+	params passed to it can be passed on to setup.rb
+		
+2004-10-25  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/installer.rb
+	(Gem::Uninstaller::remove_executables): Corrected spelling of
+	"addtion".
+
+2004-10-24  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/version.rb (Gem::Version::Requirement::self): Now
+	properly handles arrays of version constraints.
+
+	* lib/rubygems/loadpath_manager.rb
+	(Gem::LoadPathManager::Gem::Specification): Added comments
+	describing the fast Spec class purpose. Added to_s to
+	Gem::Specification (both fast and slow versions).
+	(Gem::LoadPathManager.paths): Returns (cached) list of gem paths.
+	(Gem::LoadPathManager::self): Refactored to use glob_over in
+	search_loadpaths and search_gempaths.
+
+	* lib/rubygems/installer.rb: Added some requires.
+
+	* lib/rubygems/cache.rb (Gem::Cache::refresh): Fixed refresh! to
+	call load_specification on the Cache class, not on itself.
+
+	* lib/rubygems.rb (Gem::Exception::activate): added comments to
+	activate.  Also made sure that partial name matches in the gem
+	cache search were avoided.
+	(Gem::Exception::clear_paths): Added code to clear the gem cache
+	when reseting the gem paths.
+	(Gem::Exception::require): Added a function to take a gem name and
+	a library file name (in that gem) and return a path to the library
+	in the gem.  David HH was interested in this in order to speed up
+	some require statements under ModRuby.  Eventually I hope we won't
+	need these special tricks.
+	(Gem::Exception::latest_partials): Fixed bug that assumed exactly
+	three digits in a version number.
+
+	* Rakefile (egrep): Added two tasks to find all the FIXME/TODO
+	markers in the source code comments and to find the DBG print
+	lines.
+
+2004-10-23  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/test_specification.rb
+	(TestSimpleSpecification::test_add_bindir_to_list_of_files):
+	Verify that an executable doesn't need the bindir if bindir is
+	set.
+	(TestSimpleSpecification::test_no_bindir_in_list_of_files): Added
+	test the verify that exectuable can be written without a default
+	binder.
+
+	* lib/rubygems/installer.rb
+	(Gem::Installer::generate_bin_scripts): Added check so that the
+	bindir is access only when there are actually executables to
+	install.  Checking for an installable bindir was giving permission
+	errors when installing test gems.
+
+2004-10-21  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/installer.rb: Show extension build errors during install
+	in addition to logging them to gem_make.out
+
+2004-10-02  Chad Fowler <chad at chadfowler.com>
+
+	* lib/rubygems/validator.rb,lib/rubygems/gem_commands.rb: Added
+	--test option for "gem check" that runs unit tests on already-
+	installed gems.
+
+2004-09-30  Rich Kilmer  <rich at infoether.com>
+
+	* lib/rubygems/specification.rb -  externalized the loaded_from runtime 
+	var on specification
+	* lib/rubygems/cache.rb - optimized cache refresh! method and refactored 
+	processing of files when building cache.
+	* lib/rubygems/loadpath_manager.rb - fixed bug in loadpath manager in 
+	finding native extensions that have ext on os x, win32 and solaris
+
+2004-09-20  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb:  If file match during local install is
+	a directory, don't try to treat it erroneously as a gem (bug reported
+	by Rich).
+	* lib/rubygems.rb:  Fixed small bug in #latest_load_paths
+
+	(NOTE: It looks like 0.8.0/0.8.1 was released in this timeframe)
+	
+2004-09-14  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems.rb: Fixed bug in require_gem (thanks Jamis Buck!)
+	that would require a gem based on an inexact search of its name
+	in the local cache.  This caused copland-webrick to be loaded
+	when a request was made for "copland".
+
+2004-09-12  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/specification.rb, test/test_specification.rb: Removed
+	library_stubs attribute.
+
+2004-09-12  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* scripts/specdoc.rb: Check that all attributes are documented; and
+	  improved formatting.
+	* scripts/specdoc.yaml: test_suite_file -> test_files; finished
+	  documentation.
+	* scripts/specdoc.data: misc changes.
+
+2004-09-11  Chad Fowler <chad at chadfowler.com>
+
+	* test/test_parse_commands.rb: Fix failing unit tests due to Rich's fix from
+
+	* lib/rubygems/specification.rb: Add bindir to executable path on file list
+
+2004-09-11  Rich Kilmer <rich at infoether.com>
+
+	* lib/rubygems/gem_commands.rb - got rid of stub options
+
+	* lib/rubygems/install.rb - changed output of messages so the UI would format
+	better 
+
+	* bin/gem_server - exit! from ^c
+
+2004-09-09  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/loadpath_manager.rb: Small bug when gem specs have ruby 
+	version requirements.
+	* lib/rubygems/specification.rb, lib/rubygems/gem_commands.rb: Fixed failing
+	functional test.
+
+2004-09-08  Chad Fowler <chad at chadfowler.com>
+	* install.rb: added stub removal to the install process
+
+2004-09-06  Chad Fowler <chad at chadfowler.com>
+	* test/test_package.rb: Fixed failing unit test as per Mauricio's email to 
+	the rubygems list.
+	* Fixed minor issues with Windows cmd file generation.
+
+2004-09-06  Rich Kilmer <rich at infoether.com>
+	* lib/rubygems/remote_installer.rb - enabled caching of source caches
+	based on the size of the yaml.Z/yaml file.
+	
+2004-08-29  Chad Fowler <chad at chadfowler.com>
+	* /lib/rubygems/gem_command.rb: small big fix for local gem installs
+	on Windows.
+
+2004-08-28  Rich Kilmer <rich at infoether.com>
+
+	* /lib/rubygems/installer.rb, /lib/rubygems/doc_manager.rb, 
+	/lib/rubygems/cmd_manager.rb - Added an exception: FilePermissionError
+	which checks to ensure write access to the install/uninstall/rdoc 
+	destination directories and raises a nice error instead of the standard
+	one. 
+
+2004-08-28  Rich Kilmer <rich at infoether.com>
+
+	* /lib/rubygems/installer.rb - commented out stub addition and removal
+
+2004-08-28  Rich Kilmer <rich at infoether.com>
+
+	* /lib/rubygems.rb, /lib/rubygems/loadpath_manager.rb -
+	this adds all the loadpath_manager stuff with the 'ultimate require hack' to
+	rubygems.rb.  Also, require_gem methods body has been extracted into a method
+	Gem.activate that differs in the calling signature in that the second param is
+	a boolean that determines whether to autorequire or not.
+
+2004-08-27  Rich Kilmer <rich at infoether.com>
+
+	* lib/rubygems/user_interaction - added ask_yes_no as a method
+	which returns true/false and formats/processes the [yn] stuff.
+	it also has an optional second parameter of true/false for the
+	default value.
+
+	* lib/rubygems/installer.rb, lib/rubygems/remote_installer.rb, 
+	lib/rubygems/command_manager.rb - changed all places where ask 
+	was used with [Yn] to ask_yes_no
+
+2004-08-24  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/installer.rb: Library stubs are now installed as per
+	  'library_stubs' gemspec attribute.  A stub is (still) also installed
+	  for the 'autorequire' attribute.  All library stub handling
+	  refactored into two new classes: LibraryStubs and LibraryStub.
+
+	* test/test_parse_commands.rb: as per 2004-08-17 below, the 'update'
+	  command takes --rdoc as its default now.
+
+2004-08-22  Rich Kilmer <rich at infoether.com>
+	* lib/rubygems/installer.rb: fixed stub generation...i added the version 
+	stuff that only app stubs should have...sorry!
+
+2004-08-17  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb: --rdoc is default on 'update' command,
+	  consistent with 'install'.  'default_str' methods changed to reflect
+	  --rdoc being default now.
+
+2004-08-21  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: Proper checking for gems in local 
+	directory on local install.  rescue Gem::LoadError to avoid ugly
+	backtrace.
+	* lib/rubygems/installer.rb: created Gem::LoadError to hold extra
+	metadata.  Setting up for proper dependency installation on local
+	installs.
+	
+2004-08-20  Chad Fowler  <chad at chadfowler.com>
+	
+	* lib/rubygems/specification.rb: Fixed small bug in the previous spec
+	change commit.
+
+	* lib/rubygems/cache.rb: Prevent catastrophic failure if a gemspec is 
+	corrupted.
+
+	* lib/rubygems/installer.rb: Fixed (in not a great way) a bug that would
+	cause a zero-length spec file to be written to the gem specifications
+	directory.
+
+2004-08-19  Chad Fowler  <chad at chadfowler.com>
+
+	* lib/rubygems/specification.rb: #files auto-includes any #extensions,
+	#extra_rdoc_files, #test_files, etc. that weren't explicitly added
+	to the file list.
+
+2004-08-18  Chad Fowler  <chad at chadfowler.com>
+
+	* lib/rubygems/specification.rb: One more bug with #test_files.
+	Default value of [] wasn't set, resulting in an attempt to call
+	#empty? on nil.
+
+	* lib/rubygems/gem_commands.rb: Unit tests appear to be working now.
+	Still more testing to do.
+
+	* lib/rubygems/remote_installer.rb, lib/rubygems/installer.rb: Fixed
+	minor bugs in default selections for questions asked during 
+	installation and uninstallation
+	
+2004-08-17  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/specification.rb:
+	  - #test_suite_file and #test_files now work on older gems.
+	  - Added Specification.from_yaml for loading YAML gemspecs
+	  - #to_ruby doesn't emit 'specification_version'
+
+	* lib/rubygems/gem_commands.rb: Updated test-on-install code to use
+	  Specification#test_files instead of #unit_test_suite.
+
+	* lib/rubygems/old_format.rb: Use Specification.from_yaml
+	* lib/rubygems/package.rb:    Ditto
+
+2004-08-17  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/command.rb: --debug option to turn on $DEBUG
+	* lib/rubygems/config_file.rb: ditto
+
+2004-08-11  Rich Kilmer <rich at infoether.com>
+	* lib/rubygems/installer.rb: The application stub now defaults to 
+	the latest version of the library, and optionally allows an initial 
+	parameter conforming to _VERSION_ to be passed to select a prior 
+	version of the library (this initial parameter, if present, is shifted 
+	off of ARGV). This change was re-added...I erased it somehow :(
+
+2004-08-11  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb:
+	  - 'gem spec X' displays spec for _latest_ version of X.  Added
+	    '--all' option if you want to see all versions.
+	  - RDocCommand code cleanup and slight change: document _all_
+	    versions of the gem by default, not just the first.
+
+	* lib/rubygems/doc_manager.rb: removed 'kilmer' default template
+	  option and obsolete error message.
+
+2004-08-12  Chad Fowler <chad at chadfowler.com>
+	* Added "gem rdoc" command for generating docs for already-installed
+	gems
+
+2004-08-11  Rich Kilmer <rich at infoether.com>
+	* bin/generate_yaml_index: updated to work with new gem format (and use the Gem::Format
+	 class to read).  Will deploy after testing on RubyForge.
+	* lib/rubygems/gem_commands.rb: generate rdoc by default on installs (I think this is
+	 just good practice.
+	* lib/rubygems/remote_install.rb: raise an exception if dependent gems cannot be found 
+	 on remote_install
+
+2004-08-11  Chad Fowler <chad at chadfowler.com>
+	* lib/rubygems/gem_commands.rb: query is now case insensitive (as it used to be)
+	* lib/rubygems/installer.rb: gem_make.out wasn't being written when an extension failed to compile.
+
+2004-08-11  Rich Kilmer <rich at infoether.com>
+
+	* removed String.to_requirement...we should not modify 
+	  base classes in Ruby! modified to get rid of said to_requirement 
+	  with Gem::Version::Requirement.create(obj)
+
+	* specification.rb - fixed constructor bug of version requirement...
+	  it now defaults to Requirement.default
+
+2004-08-11  Chad Fowler <chad at chadfowler.com>
+
+	* One more specification.rb bug fixed.
+
+2004-08-11  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/specification.rb:
+	  - Added convenience class methods: attribute_names,
+	    attribute_defaults, default_value, required_attributes, and
+	    required_attribute?.
+
+	  - IMPORTANT: attribute readers now use lazy initialization, just
+	    like some of them did before the 2004-08-01 change.  This was done
+	    to fix the breakage when loading older gemspecs.
+
+	  - IMPORTANT: replaced instance variable access with attribute reader
+	    method calls in many cases.  This is in line with the above change.
+
+	  - Good documentation for the "attribute" method.
+
+	  - Renamed _copy -> _copy_of.
+
+	* lib/rubygems/cache.rb:
+	  - Some fairly shallow changes. Exception handling needs improvement.
+
+	* lib/rubygems/version.rb:
+	  - (Version.create) new method (for convenience)
+	  - (Version::Requirement.create) new method (for convenience)
+	  - (Version::Requirement.default) new method (for consistency)
+
+	* test/test_specification.rb: test attribute_names instead of
+	  attributes.  Other "class convenience" methods remain to be tested
+	  at this stage.  Also added test classes for legacy gemspecs.
+
+	* test/data/legacy/keyedlist-0.4.0.ruby: added.
+	* test/data/legacy/keyedlist-0.4.0.yaml: added.
+
+2004-08-06  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/specification.rb:
+	  - Added convenience class methods: attribute_names,
+	    attribute_defaults, default_value, required_attributes, and
+	    required_attribute?.
+
+	  - IMPORTANT: attribute readers now use lazy initialization, just
+	    like some of them did before the 2004-08-01 change.  This was done
+	    to fix the breakage when loading older gemspecs.
+
+	  - Good documentation for the "attribute" method.
+
+	  - Renamed _copy -> _copy_of.
+
+	* test/test_specification.rb: test attribute_names instead of
+	  attributes.  Other "class convenience" methods remain to be tested
+	  at this stage.
+
+2004-08-01  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/specification.rb:
+	  - (Re)defined class methods: attribute, attributes,
+	    required_attribute, read_only, overwrite_accessor.	@@attributes
+	    contains a list of attribute names and default values.  This
+	    allows higher-level specification of gemspec attributes, and the
+	    handling of them in a DRY fashion.
+
+	  - to_yaml_properties now includes all properties, to ensure
+	    correct deserialization of a Gem::Specification object.
+
+	  - #to_ruby and #to_yaml_properties rewritten to use @@attributes
+
+	  - Introduced 'specification_version' attribute and three constants:
+	    NONEXISTENT_SPECIFICATION_VERSION, CURRENT_SPECIFICATION_VERSION, and
+	    SPECIFICATION_VERSION_HISTORY.  This allows us to track changes to
+	    the spec format.
+
+	  - Refactored several "helper" methods, using the new class method
+	    'attribute_alias_singular', which provides a "singular" alias for
+	    a "plural" attribute (e.g. require_path and require_paths).
+
+	  - All gemspec attributes now defined in a uniform fashion, which
+	    implies that they all have valid instance variables on
+	    initialization.  Previously, some attributes were lazily
+	    initialized.
+
+	  - Introduced attribute 'library_stubs', to allow the specification
+	    of several stub files.  (That feature not implemented, though.)
+
+	  - Introduced attribute 'test_files' and deprecated 'test_suite_file'.
+
+	  - Provided #warn_deprecated stub of a method, but don't know what to
+	    do with it.
+
+	  - Deprecated #has_test_suite? in favour of (new) #has_unit_tests?
+
+	  - Used overwrite_accessor to provide special behaviour for the
+	    setting of some attributes.
+
+	  - The 'date' attribute is now a Date object.	We don't need high
+	    resolution, and Time objects, being system-dependent, are not nice
+	    to deal with.
+
+	  - Various code style changes.
+
+	  - Summary: uniform treatment of gemspec attributes; reduced code by
+	    refactoring; 'test_suite_file' deprecated for 'test_files';
+	    'library_stubs' introduced; spec versioning introduced.
+
+	* lib/rubygems/version.rb: (Dependency) added #to_s, #==, and an
+	  alias (requirements_list -> requirement_list).
+
+	* test/test_specification.rb: several new tests: _singular_attributes,
+	  _deprecated_attributes, _defaults, _to_{yaml,ruby}_and_back,
+	  _directly_setting_dependencies_doesnt_work, and more.  Plus a new
+	  class to give Specification a more thorough workout (TestSpecificationComplex).
+
+	* scripts/runtest.rb: require 'pp' so it's always available in unit
+	  tests.
+
+2004-07-30  Rich Kilmer  <rich at infoether.com>
+
+	* lib/rubygems/installer.rb The application stub now defaults 
+	  to the latest version of the library, and optionally allows 
+	  an initial parameter conforming to _VERSION_ to be passed
+	  to select a prior version of the library (this initial 
+	  parameter, if present, is shifted off of ARGV).
+
+	* lib/rubygems/version.rb correct? is now a class method on
+	  Version enabling Gem::Version.correct?(...)
+
+	* lib/rubygems/install.rb make it so uninstalling a gem will
+	  not remove executables if another version of that gem is 
+	  installed and needs those executables
+
+2004-07-26  Jim Weirich  <jim at tardis>
+
+	* lib/rubygems.rb (Gem::Exception::latest_load_paths): Added
+	latest_load_paths and refactored all_load_paths to use common
+	code.
+
+2004-07-25  Rich Kilmer  <rich at infoether.com>
+	* fixed bug in using --source in command.rb (removed short -s version)
+
+	* changed spec to use the RUBY_PLATFORM for Platform::CURRENT
+
+	* added ability to choose from list of available gems on remote install
+	  if (1) some of the gems are binary and (2) there are move than one.
+	  If the gems are all source gems, the latest is selected.
+
+2004-07-25  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems.rb (Gem::Exception::all_load_paths): Added
+	all_load_paths utility function.
+
+	* bin/update_rubygems: Added a command to update the gem
+	installation based on a update gem.
+
+	* Rakefile: Pulled package file list out into a constant so it can
+	be reused between the package command and the gem package command.
+	Added a gem package target to support rubygems updates.
+
+2004-07-22  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/version.rb:
+	  * (Requirement#initialize) initialize @version to avoid warning
+	  * (Dependency#initialize) initialize @version_requirement to avoid
+	    warning
+
+2004-07-19  Chad Fowler     <chad at chadfowler.com>
+	* install.rb: Shebang line should point to the ruby version used during
+	installation.
+
+2004-07-19  Assaph Mehr     <assaph at avaya.com>
+	* lib/rubygems/command.rb, packages/sources/lib/sources.rb: Added
+	command-line-configurable sources.
+
+2004-07-18  Chad Fowler	    <chad at chadfowler.com>
+	* lib/rubygems/validator.rb: Fixed a bug that would cause "managed"
+	files to appear to be unmanaged due to differences in how the paths
+	were formatted.
+
+2004-07-17  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb (InstallCommand#execute): removed clear
+	  bug (name -> gem.name).
+
+2004-07-14  Rich Kilmer     <rich at infoether.com>
+	* added old_format.rb which is used in the (hack) in format.rb 
+	  to detect the older version of a gem, and if present, switches 
+	  to that class instead.
+	* fixed the ARGV passing in bin/gem to ingore args past -- which
+	  are used for passing params to source gems (extconf.rb)
+
+2004-07-13  Chad Fowler	    <chad at chadfowler.com>
+	* lib/rubygems/installer.rb, lib/rubygems/package.rb, 
+	lib/rubygems/format.rb, test/test_package.rb: Added Mauricio 
+	Fernandez's patch to replace old gem format with tar.gz format.
+	Fixed some failing unit tests that resulted.  Still a couple left.
+	* lib/rubygems.rb: Fixed a bug introduced by the previous patch.
+
+2004-07-13  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems.rb: (#require_gem) added the ability to do
+	  "require_gem 'rake/packagetask'", for instance, which is a
+	  shortcut for "require_gem 'rake'; require 'rake/packagetask'".
+
+2004-07-13  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb: refactored --version option
+	  in all cases to the new VersionOption module.
+
+2004-07-13  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/cmd_manager.rb: added 'unpack' command.
+
+	* lib/rubygems/gem_commands.rb (UnpackCommand): added.
+
+	* lib/rubygems/installer.rb (Installer#unpack): added.
+
+2004-07-09  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/user_interaction.rb (Gem::StreamUI::ask and
+	Gem::StreamUI::choose_from_list): Added flush before each gets.
+
+2004-07-05  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/command.rb (Gem::Command#defaults_str): added.
+
+	* lib/rubygems/command.rb (Gem::Command#create_option_parser):
+	  Defaults for the options are included in the parser output.
+
+	* lib/rubygems/gem_commands.rb: all commands which have options
+	  and defaults now have #defaults_str implemented.
+
+2004-07-05  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/command.rb (Gem::Command#create_option_parser):
+	Make the argument and option sections optional.  They are only
+	printed if there are options or arguments defined.
+
+2004-07-05  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb:
+	  - scrubbed up the 'help' command a bit, removing its options
+	  - added information to 'help commands'
+
+2004-07-04  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb:
+	  - modified generic help and examples
+	  - improved 'list' and 'search' help, and fixed bug in 'search'
+
+	* lib/rubygems/cmd_manager.rb: 
+	  - explicit support for top-level commands --help and --version
+	  - no more support for --examples and --commands
+
+2004-07-04  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* lib/rubygems/gem_commands.rb:
+	  - added 'list' and 'search' commands ('list' is no longer an alias
+	    for 'query')
+	  - modified return value from all 'arguments' methods (see command.rb)
+
+	* lib/rubygems/cmd_manager.rb: added 'search' command.
+
+	* lib/rubygems/command.rb:
+	    (Command#create_option_parser): enhanced the option parser for 'help'
+					    display
+	    (Command#remove_option): added (to support 'list' and 'search')
+
+	* Rakefile: added 'gem' target.  Runs "local" (not installed) command
+	  and libraries.
+
+2004-07-04  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* Rakefile: added 'install' target.
+
+	* lib/rubygems/cmd_manager.rb: code formatting.
+
+	* lib/rubygems/gem_commands.rb:
+	  - refactored common install and update options into new module
+	    InstallUpdateOptions
+	      . consolidated option pairs (e.g. --test & --no-test ==> --[no-]test)
+	      . --gen-rdoc is now --rdoc
+	  - (UninstallCommand) corrected typo
+	  - (InstallCommand) corrected output with local install
+
+	* test/test_parse_commands.rb: :%s/--gen-rdoc/--rdoc/g
+
+2004-07-03  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_commands.rb (Gem::InstallCommand::initialize):
+	Added --no-gen-rdoc and --no-test to allow the user to override
+	.gemrc default options.
+
+	* lib/rubygems/doc_manager.rb (Gem::DocManager::generate_rdoc):
+	Concatenate the local rdoc options to the end of the spec's rdoc
+	options.
+	(Gem::DocManager::configured_args): Added configured_args as a
+	place to store local rdoc options.
+
+	* lib/rubygems/gem_runner.rb (Gem::GemRunner::do_configuration):
+	Configuration handled in do_configuration now.
+	(Gem::GemRunner::do_configuration): Set the local rdoc
+	configuration from the config file.
+
+	* lib/rubygems/command.rb (Gem::Command::handles): Added a
+	handles? method to Command so that we can detect which extra
+	arguments can be used with a command.
+	(Gem::Command::add_extra_args): New method to add the config
+	file's extra arguments to the front of the argument list.
+	(Gem::Command::extra_args): Added extra_args to Command class to
+	hold the extra args discovered in the config file.
+
+	* Rakefile: Added TEST=filename option to all the test targets.
+
+	* test/functional.rb (FunctionalTest::test_gemrc): Added
+	functional test for gemrc.
+
+	* scripts/gemdoc.data: Added an example to the specification command.
+
+	* lib/rubygems.rb (Gem::Exception::manage_gems): Added gem_runner
+	and config_file to manage_gems.
+	(Gem::Exception::use_paths): use_paths now accepts (and ignores)
+	nil parameters.
+
+	* bin/gem: Make Gem::GemRunner the top level object.  It now
+	creates and calls the CommandManager /after/ the arguments are
+	processed.
+
+	* Rakefile: Added test/data/gemhome to clobber list.
+
+2004-07-01  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/test_specification.rb
+	(TestSpecification::test_rdoc_files_included): Test for rdoc files
+	included in file list.	Test for redundent file removal.
+
+	* lib/rubygems/specification.rb (Gem::Specification::validate):
+	Added gem version to validation requirement.  Added normalize to
+	remove redundent files in lists.
+
+	* lib/rubygems/gem_commands.rb (Gem::InfoCommand::usage): Added
+	usage and arguments methods for InfoCommand.
+	(Gem::SpecificationCommand::usage): Fixed several usage comments.
+
+2004-06-30  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_commands.rb (Gem::InstallCommand::usage):
+	Upcased the comment on the usage statement (and corresponding
+	option).  This makes the variable part of the command
+	(e.g. GEMNAME) stand out from the static parts.
+
+	* lib/rubygems/cmd_manager.rb (Gem::CommandManager::process_args):
+	Downcased commands before searching (allows upper case or mixed
+	case for commands on command line).
+
+	* install.rb (install_rb): Fixed bug where the installer falsely
+	triggered the old repository upgrade when the directory part of
+	the file contained the matching "-digits." pattern.  Now the
+	pattern must be in the file's base name.
+
+2004-06-26  Gavin Sinclair  <gsinclair at soyabean.com.au>
+
+	* scripts/specdoc.rb: added (to generate gem specificiation document)
+	* scripts/specdoc.data: added (supports specdoc.rb)
+	* scripts/specdoc.yaml: added (supports specdoc.rb)
+
+2004-06-27  Jim Weirich  <jim at weirichhouse.org>
+
+	* scripts/gemdoc.data Removed extraneous <em> marker. 
+
+	* lib/rubygems/specification.rb
+	(Gem::Specification::satisfies_requirement): HA!  Caught another
+	version_requirement vs version_requirements error.  (I really
+	regret the decision to change that name.)
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller::has_dependents):
+	Changed call to alert to alert_warning.
+
+	* lib/rubygems/gem_commands.rb (Gem::UninstallCommand::execute):
+	Again, remove local error handling to allow the error to perculate
+	up the chain to the top level.
+
+	* lib/rubygems/doc_manager.rb (Gem::DocManager::generate_rdoc):
+	Removed one level of exception handling.  Only catching RDocErrors
+	at the outermost level.  And instead of reporting the error and
+	swallowing it, I convert it to a Gem::DocumentError (with the same
+	error message).  This is for better error handling.
+
+	* lib/rubygems/command.rb (Gem::Command::handle_options): Removed
+	exception handling from handle_options.  This allows errors to be
+	handled at the top level.  Makes for a more consistent error
+	interface.
+
+	* lib/rubygems/doc_manager.rb (Gem::DocumentError): Added
+	DocumentError to wrap RDocErrors (which derive from Exception
+	... yuck).
+
+	* lib/rubygems/cmd_manager.rb (Gem::RemoteError): RemoteError and
+	LocalInstallationError are now Gem::Exceptions (rather than
+	StandardErrors).  
+
+	* lib/rubygems.rb (Gem::Exception): Changed base of Gem::Exception
+	to RuntimeError (was ::Exception).  Apps using gem as a library
+	would have to catch Gem::Exceptions explicitly (yuck), or catch
+	Exceptions generically.  Catching Exceptions will catch
+	EVERYTHING, including things like SystemExit.  By makeing
+	Gem::Exception a RuntimeError, apps can catch RuntimeError or even
+	StandardError.
+
+2004-06-26  Jim Weirich  <jim at weirichhouse.org>
+
+	* test/functional.rb (FunctionalTest::test_all_command_helps):
+	Added functional test to show all commands have usage messaegs.
+
+	* lib/rubygems/gem_commands.rb (Gem::HelpCommand::execute): Added
+	version option to help (gem help version).
+	(Gem): Cleaned up the help text.  Dropped unneeded verbage.
+
+	* lib/rubygems/cmd_manager.rb
+	(Gem::CommandManager::find_command_possibilities): Added
+	find_command_possibilities to help the Help command look for
+	commands.
+
+	* lib/rubygems/installer.rb (Gem::Uninstaller::uninstall): Fixed
+	null pointer bug where a list was destroyed in a method.
+
+	* lib/rubygems/gem_commands.rb (Gem::BuildCommand::load_gemspecs):
+	yaml gemspec files are now accepted by the build command.
+
+	* lib/rubygems/command.rb (Gem::Command::parser): Created an
+	on-demand option parser for all commands.
+	(Gem::Command::handle_options): Command line option hash is now
+	and instance variable with a reader.
+
+	* Rakefile: Linked package version to the value in the rubygems.rb
+	file.  The gem env command now shows both gem version (e.g. 0.6)
+	and the package version (e.g. 0.6.1).
+
+2004-06-25  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/gem_commands.rb (Gem::InfoCommand): Dropped the
+	version command (its available via gem env).  Added a gem info
+	command to extract the yaml from a gemfile.
+	(Gem::LocalRemoteOptions): Refactored the local/remote options
+	(adding and testing) into a mixin module.
+
+	* test/test_version_comparison.rb
+	(TestDependencies::test_normalization): Added some tests for the
+	normalization issues mentions below.
+
+	* lib/rubygems/version.rb (Gem::Dependency::normalize): Old gems
+	have requirements and dependencies incoded in the Yaml spec in an
+	out of date format.  When loaded, they have incorrect instance
+	variables for modern objects.  I added a normalize call to handle
+	transforming out dated objects in to modern objects. (Remember
+	this next time we change the data structure of something in the
+	spec file.)
+	(Gem::Version::Requirement::parse): Requirements are comparable
+	now, just so that we can test them with asserts.
+
+	* lib/rubygems/remote_installer.rb
+	(Gem::RemoteInstaller::find_dependencies_not_installed): Fixed
+	recursive call to require_gem to properly pass dependency
+	information.
+	
+	* lib/rubygems/installer.rb (Gem::Uninstaller::has_dependents):
+	Fixed reference to version_requirement (needs to be plural).
+
+	* lib/rubygems/command.rb (Gem::Command::invoke): Command now
+	handles it own help messages.  Commands no longer have to return
+	true/false to trigger help messages.
+
+	* lib/rubygems/cmd_manager.rb (Gem::CommandManager::process_args):
+	Moved help handling into the help command.
+
+	* lib/rubygems/gem_commands.rb (Gem::HelpCommand): Renamed the
+	base command to HelpCommand and made it handle a lot of the help
+	options.  Still need work on individual command helps.
+
+	* test/functional.rb (FunctionalTest::test_env_version): Added a
+	bunch of new functional tests for the environment command.
+
+	* lib/rubygems/gem_commands.rb (Gem::InstallCommand::execute):
+	Made multiple gem names an error for now.  Should look at later.
+
+	* lib/rubygems/cmd_manager.rb (Gem::ListCommand): Added list as an
+	alias to query.
+	(Gem::UpdateCommand::initialize): Corrected spelling of install
+	(intall) in several places.
+
+	* bin/gem_server: Added Gem.manage_gems to the gem_server to fix
+	missing requirements.
+
+	* lib/rubygems/cmd_manager.rb (Gem::InstallCommand::initialize):
+	Added missing --both option to install.
+
+	* test/test_command.rb
+	(TestCommand::test_invode_with_bad_options): Catch the termination
+	request.
+
+	* test/mockgemui.rb (MockGemUi::terminate_interaction): Make the
+	mock UI throw an exception when a termination is requested.  This
+	makes sure that we don't miss accidental terminations.
+
+	* lib/rubygems/cmd_manager.rb (Gem::CommandManager::find_command):
+	Added find_command to handle best matching command names.
+
+	* test/functional.rb (FunctionalTest::test_build): Updated
+	functional tests to use the new command structure.
+
+	* lib/rubygems/version.rb (Gem::Version::Requirement): Changed the
+	pessimistic version comparison operator to "~>".  I like to think
+	of it as "approximately greater than".	(It was ">*").
+
+	* bin/gem: Moved gem2 into the standard gem script location.  It
+	is now stable enough to use as the standard command.
+
+	* lib/rubygems/cmd_manager.rb (Gem::CommandManager::run): Added
+	run method to trap errors while running commands.  Makes for
+	prettier output.
+	(Gem::CommandManager): Move *all* commands to their own classes.
+	Simplified CommandManager.  Lowered the coupling between
+	CommandManager and the Commands (the commands don't even need to
+	know about the manager anymore).  CommandManager maybe created
+	with "new" for testing (the script will continue to use
+	"instance").
+	(Gem::RubyGemsInfoCommand): New command.
+	(Gem::VersionCommand): New command.
+
+2004-06-24  Jim Weirich  <jim at weirichhouse.org>
+	
+	* lib/rubygems/user_interaction.rb (Gem::UserInteraction):
+	Significantly rewrote the whole user interaction scheme.  We are
+	now using an UI object that responds to the standard list of UI
+	commands (e.g. say, alert, ask).  The UserInteraction module
+	defines all the interaction methods to be forwarded to the default
+	UI objects.  The "ui" method returns that default object (and you
+	can use self.ui=(new_ui) to change it).  Also the use_ui(new_ui) {
+	} command is convienent for switching the UI object for a short
+	period of time.
+
+2004-06-18  Rich Kilmer <rich at infoether.com>
+	* broke test_cmd_manager.rb into test_parse_commands and 
+	test_process_commands to test the parsing of command line options
+	and the funtionality, respectively. 
+
+2004-06-18  Rich Kilmer <rich at infoether.com>
+	* added new unit test file: test/test_cmd_manager.rb to test the 
+	command manager classes.  this is just the first few tests which
+	will be expanded to a full test suite.
+
+2004-06-17  Chad FOwler <chad at chadfowler.com>
+
+	* lib/rubygems/installer.rb: Fixed bug in windows batch file generation
+	which was causing file not found errors.
+	* lib/rubygems/installer.rb: Uninstall now removes scripts and batch 
+	* lib/rubygems/specification.rb: Fixed install bug.  Thanks to Mark 
+	Sparshatt for the fix (via the rubyforge bug tracker). 
+
+2004-06-17  Jim Weirich  <jim at weirichhouse.org>
+
+	* lib/rubygems/doc_manager.rb (Gem::DocManager::generate_rdoc):
+	Changed rdoc generation to do a chdir into the base source
+	directory and then to use a relative path for all the source
+	files.	This makes the generated RDOC html look better and may fix
+	the windows drive/rdoc bug as a side effect.
+
+2004-06-17  Rich Kilmer <rich at infoether.com>
+	* Added ability to capture the UserInteraction with:
+	c = Gem::UserInteraction.capture
+	and then you can override specific methods like 'say':
+	c.on_say {|statement| puts "you said: #{statement}"}
+
+2004-06-15  Rich Kilmer <rich at infoether.com>
+	* Added refactored command handling in rubygems/cmd_manager.rb and a 
+	(temporary) bin/gem2 command file to test things out.  Once we feel
+	comfortable, we can replace gem with gem2.
+
+2004-06-10  Rich Kilmer <rich at infoether.com>
+	* Isolated all user interaction to pass through module methods on a new
+	Gem::UserInteraction module.  Those methods will be the method of abstracting
+	the interaction of RubyGems for use in a GUI-based solution.
+
+2004-06-10  Rich Kilmer <rich at infoether.com>
+	* require 'rubygems' now minimally requires only the files needed
+	for runtime access to gems...not management of gems.  To manage
+	gems you now additionally need to execute Gem::manage_gems prior
+	to using the builder/installer/etc.  This makes gemspecs not 
+	backward compatible unless they add that line to the gemspec 
+	after the require 'rubygems' line.
+
+2004-06-10  Gavin Sinclair <gsinclair at soyabean.com.au>
+	* bin/gem: --upgrade-all was broken, probably as a result of the
+	  search changes listed below.
+
+2004-06-09  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/remote_install.rb: delegate search functionality to
+	  Cache class, bringing remote and local search and list together into
+	  one piece of code.
+	* bin/gem, lib/rubygems/validator.rb: move all STDIO work to bin/gem.
+	  Validator.alien now returns a hash of ErrorData objects.
+	* bin/gem, lib/rubygems/installer.rb: move most of the STDIO stuff to
+	  bin/gem, communicating via exceptions in this case.
+
+2004-06-08  Rich Kilmer  <rich at infoether.com>
+	* Fixed the drive problem on win32 (hopefully) so multiple drives
+	  should now work.  Its still a hack until rdoc is fixed.
+
+2004-06-08  Chad Fowler  <chad at chadfowler.com>
+	* Fixed bug caused by method change on Version::Requirement
+
+2004-06-08  Rich Kilmer <rich at infoether.com>
+	* fixed bug in doc_manager.rb whereby the extra_rdoc_files should
+	  be appended to the list of directories prior to prepending the
+	  full path.
+
+2004-06-08  Gavin Sinclair <gsinclair at soyabean.com.au>
+	* bin/gem_server: List installed gems in [name,version] order.
+
+2004-06-08  Gavin Sinclair <gsinclair at soyabean.com.au>
+	* lib/rubygems/installer.rb: don't warn about not being able to
+	  install a library stub if a library stub is already installed.
+	  Still warn if it's not a library stub that's there already.
+
+2004-06-08  Gavin Sinclair <gsinclair at soyabean.com.au>
+	* bin/gem: renamed --upgrade-dist to --upgrade--all and fixed bug.
+	* lib/rubygems/installer.rb: fixed bug with Ruby version assertion.
+
+2004-06-07  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/remote_installer.rb, lib/rubygems/version.rb: Fixed old
+	  dependency on #version method for Gem::Version::Requirement
+	* bin/gem: new --upgrade-dist option allows one to upgrade every
+	  installed gem
+	* lib/rubygems/specification.rb,lib/rubygems/installer.rb: new
+	  #required_ruby_version attribute added to gem specification for specifying a
+	  dependency on which version of ruby the gem needs.	Format it accepts is
+	  the same as the Gem::Version::Requirement format.
+
+2004-06-06  Chad Fowler  <chad at chadfowler.com>
+	* bin/gem: install_stub is once again the default due to requests.
+
+2004-06-04  Chad Fowler  <chad at chadfowler.com>
+	* lib/rubygems/specification.rb, lib/rubygems/doc_manager.rb:  
+	Allow arbitrary files to be added for rdoc to run over them (as per
+	Jim's request).
+
+2004-06-04  Chad Fowler  <chad at chadfowler.com>
+	* bin/gem:  Reformatted --search and --list output such that
+	multiple versions of a gem are compressed into a single entry
+	(with version numbers in parentheses)
+
+2004-05-31  Jim Weirich  <jweirich at one.net>
+
+	* lib/rubygems/version.rb (Gem::Dependency): Dependency attribute
+	renamed to version_requirements (made plural).
+	(Gem::Version::bump): Added bump to implement pessimistic
+	operator.
+	(Gem::Version::Requirement): Added pessimistic operator to list of
+	operators. Operators now implemented using lambda.
+
+	* lib/rubygems.rb (Kernel::require_gem): require_gem now takes an
+	array of requirement strings.
+
+	* lib/rubygems/version.rb (Gem::Version::Requirement::initialize):
+	Simplified initialization by making parse a bit smarter.
+	(Gem::Version::Requirement::satisfied_by): Simplified by using
+	all?
+	(Gem::Version::Requirement::satisfy): Added explicit one
+	requirement satisfy test.
+	(Gem::Version::Requirement::parse): parse now returns a two
+	element string array (operator and version string).  We don't
+	bother converting to an integer array during parsing.
+
+2004-05-31 18:38 chadfowler
+
+	* gemspec now supports #rdoc_options, to which you can append
+	strings that will be passed to rdoc as additional options.
+
+2004-05-08 21:57  chadfowler
+
+	* Using Gem::RubyGemsVersion to match the release number.  If we
+	need to use this as an internal version format specifier in the
+	future, we can use the Gem::Version semantics.
+
+2004-05-30 14:33 gsinclair
+
+	* bin/gem: Split --help into --help (basic), --help-options (what
+	  --help used to be), and --help-examples.
+
+2004-04-30 15:57  chadfowler
+
+	* bin/gem: --install-stub is no longer the default ;)
+
+2004-04-30 15:51  chadfowler
+
+	* lib/rubygems/installer.rb: Rich Kilmer (who kicks butt) figured
+	  out how to fix the library stub stuff.
+
+2004-04-29 19:12  chadfowler
+
+	* lib/rubygems/doc_manager.rb: Dick Davies fixed a bug in the doc
+	  generator.
+
+2004-04-29 13:41  gsinclair
+
+	* lib/rubygems/installer.rb: Added skeleton code and comments to
+	  uninstall stub apps and libs
+
+2004-04-29 12:20  gsinclair
+
+	* install.rb: Don't install library stub for 'sources'
+
+2004-04-29 12:20  gsinclair
+
+	* lib/rubygems/installer.rb: Improvements to library stub
+	  installation: * don't overwrite existing file (emit warning) *
+	  nice warning if there's a permission problem * observe
+	  --[no-]install-stub flag (rather, observe the argument to
+	  #install)
+
+2004-04-29 12:16  gsinclair
+
+	* bin/gem: --install-stub is now the default
+
+2004-04-26 20:20  chadfowler
+
+	* test/test_remote_installer.rb: Cleaning up after Gavin and his
+	  test-breaking self. ;)
+
+2004-04-26 12:06  gsinclair
+
+	* bin/gem, lib/rubygems/installer.rb,
+	  lib/rubygems/remote_installer.rb: Installing a gem now causes a
+	  library stub to be installed as well, allowing you to require
+	  'package' without knowing it's a gem.
+
+2004-04-25 23:18  chadfowler
+
+	* lib/rubygems/: installer.rb, specification.rb: Prompt user if
+	  trying to uninstall a gem that other gems *may* depend on.
+
+2004-04-25 09:27  chadfowler
+
+	* test/test_remote_installer.rb: Changed expected test results to
+	  match new (old) gem naming scheme--"ruby" doesn't appear as a
+	  platform in the gem name.
+
+2004-04-25 05:50  gsinclair
+
+	* bin/gem: Changed @directory -> @install_dir for clarity
+
+2004-04-25 05:47  gsinclair
+
+	* bin/gem: Improved display of gems, platform-wise
+
+2004-04-25 05:46  gsinclair
+
+	* lib/rubygems/specification.rb: Added documentation
+
+2004-04-25 04:17  jimweirich
+
+	* test/functional.rb: Fixed functional test to properly name a Ruby
+	  platform gem.
+
+2004-04-25 04:17  jimweirich
+
+	* packages/sources/.cvsignore, test/data/one/.cvsignore: Ignore the
+	  proper gem name.
+
+2004-04-25 04:17  jimweirich
+
+	* lib/rubygems/specification.rb: Undefined several attributes that
+	  were redefined to avoid warnings.
+
+2004-04-25 04:17  jimweirich
+
+	* lib/rubygems.rb: Need to initialize @gem_home and @gem_path with
+	  ||= to avoid warning.
+
+2004-04-25 03:40  gsinclair
+
+	* lib/rubygems.rb, test/test_gempaths.rb: RUBY_GEMS -> GEM_PATH
+	  (environment variable)
+
+2004-04-25 03:33  gsinclair
+
+	* lib/rubygems/specification.rb: Pretty-print the specification
+
+2004-04-25 03:18  gsinclair
+
+	* lib/rubygems/specification.rb: Handle platform in a (hopefully)
+	  consistent manner
+
+2004-04-25 03:16  gsinclair
+
+	* install.rb: Use return value from Builder#build to locate gem
+	  file
+
+2004-04-25 03:09  gsinclair
+
+	* lib/rubygems/builder.rb: Return file name from #build
+
+2004-04-25 02:32  gsinclair
+
+	* lib/rubygems/specification.rb: Platform goes at the *end* of the
+	  full name now.
+
+2004-04-22 06:19  chadfowler
+
+	* test/test_remote_installer.rb: Fixed test to reflect fewer cache
+	  sources :(
+
+2004-04-21 17:19  rich
+
+	* lib/rubygems/remote_installer.rb: added support to download the
+	  yaml index as a .Z (zlib compressed) file if it exists, then move
+	  on to the plain yaml file if it does not
+
+2004-04-20 20:23  chadfowler
+
+	* examples/application/an-app.gemspec, lib/rubygems/format.rb,
+	  packages/sources/lib/sources.rb: Committed Dick Davies' patch to
+	  fix broken tests.
+
+2004-04-18 01:51  gsinclair
+
+	* bin/gem, lib/rubygems/doc_manager.rb: RDoc generation observes
+	  'rdoc' config file value
+
+2004-04-17 12:15  gsinclair
+
+	* bin/gem: Improved 'build' error output
+
+2004-04-17 12:12  gsinclair
+
+	* lib/: rubygems.rb, rubygems/remote_installer.rb,
+	  rubygems/specification.rb, rubygems/validator.rb: All
+	  gems-related exceptions now extend Gem::Exception
+
+2004-04-17 12:11  gsinclair
+
+	* lib/rubygems/specification.rb: Improved handling of summary and
+	  decription strings - convert to single line
+
+2004-04-17 01:09  gsinclair
+
+	* bin/gem: Prevent remote install attempt if local install was
+	  successful
+
+2004-04-17 00:49  gsinclair
+
+	* lib/rubygems/builder.rb: Better formatted the output code
+
+2004-04-16 21:31  gsinclair
+
+	* lib/rubygems/remote_installer.rb: Stoopid coding error (thanks
+	  Kent Sibilev)
+
+2004-04-16 00:00  rich
+
+	* lib/rubygems/installer.rb: added code to optionally use nmake
+	  instead of make on win32 systems
+
+2004-04-15 20:12  gsinclair
+
+	* bin/gem, lib/rubygems/remote_installer.rb: Clarified proxy
+	  handling and interface: --[no-]http-proxy [URL]
+
+2004-04-13 00:16  jimweirich
+
+	* bin/gem, test/bogussources.rb, test/functional.rb: Oops, missed
+	  an instance of GEM_PATH in the gem binary.
+
+2004-04-12 21:28  jimweirich
+
+	* lib/rubygems/cache.rb: Oops.	Missed a GEM_PATH.
+
+2004-04-12 21:11  jimweirich
+
+	* test/test_remote_installer.rb: removed setting of environment
+	  variable for now.
+
+2004-04-12 21:09  jimweirich
+
+	* Rakefile, lib/rubygems.rb, lib/rubygems/cache.rb,
+	  lib/rubygems/installer.rb, packages/sources/.cvsignore,
+	  scripts/runtest.rb, test/.cvsignore, test/bogussources.rb,
+	  test/test_format.rb, test/test_gempaths.rb,
+	  test/test_remote_installer.rb, test/test_validator.rb: Added
+	  test/temp to the clobber list.  Broke out tests into inline to
+	  avoid test dependencies on rubygem.
+
+2004-04-12 07:52  chadfowler
+
+	* lib/: rubygems.rb, rubygems/installer.rb,
+	  rubygems/remote_installer.rb: Cleaning up output strings wrt
+	  formating of "gem (version)".
+
+2004-04-12 07:41  chadfowler
+
+	* lib/rubygems/installer.rb: Gavin Sinclair's uninstall bug.
+
+2004-04-11 15:26  jimweirich
+
+	* test/data/one/: .cvsignore, one-ruby-0.0.1.gem:  removed
+	  one-ruby*.gem from source control.  This gem is automatically
+	  generated in testing.
+
+2004-04-11 10:50  chadfowler
+
+	* bin/gem: Gavin Sinclair's test code enhancements
+
+2004-04-11 07:50  chadfowler
+
+	* bin/gem, lib/rubygems/installer.rb,
+	  lib/rubygems/remote_installer.rb, lib/rubygems/specification.rb,
+	  test/insure_session.rb, test/test_remote_installer.rb,
+	  test/data/one/one-ruby-0.0.1.gem: Gavin Sinclair patches to make
+	  installer return types less ambiguous.
+
+2004-04-09 10:29  chadfowler
+
+	* lib/rubygems/installer.rb, test/data/one/one-ruby-0.0.1.gem: gem
+	  -u input validation patch by Ville Aine
+
+2004-04-07 07:49  chadfowler
+
+	* bin/gem, lib/rubygems/cache.rb, test/data/one/one-ruby-0.0.1.gem:
+	  Finally have passing tests.
+
+2004-04-07 07:24  chadfowler
+
+	* lib/rubygems/remote_installer.rb,
+	  test/data/one/one-ruby-0.0.1.gem: Allow default option to work on
+	  remote dependency prompt.
+
+2004-04-07 07:05  chadfowler
+
+	* lib/rubygems/remote_installer.rb, test/test_remote_installer.rb,
+	  test/data/one/one-ruby-0.0.1.gem: Applied George Marrows' patch
+	  to remote_install
+
+2004-04-07 06:23  chadfowler
+
+	* bin/gem, test/data/one/one-ruby-0.0.1.gem: No longer "seeing"
+	  double on remote searches
+
+2004-04-05 07:39  chadfowler
+
+	* Rakefile, test/test_remote_installer.rb,
+	  test/data/one/one-ruby-0.0.1.gem: remote_installer tests aren't
+	  completely hosed anymore.
+
+2004-04-05 06:16  chadfowler
+
+	* Rakefile, test/data/one/one-ruby-0.0.1.gem: Rake target for
+	  running all tests (unit + functional) "alltests"
+
+2004-04-05 00:48  jimweirich
+
+	* test/: insure_session.rb, data/one/README.one,
+	  data/one/one-ruby-0.0.1.gem, data/one/one.gemspec,
+	  data/one/lib/one.rb: added for functional tests
+
+2004-04-05 00:48  jimweirich
+
+	* test/functional.rb: Moved session gem detection to insure_session
+	  file.  Modified functional tests to use gem command.	Removed
+	  some directory stuff because rake guarantees the starting
+	  directory.  Added test_info functional test.	Added test_build
+	  functional test.  Added assert status.
+
+2004-04-05 00:48  jimweirich
+
+	* lib/rubygems/remote_installer.rb: Changed exceptions to inherit
+	  from RunTimeError
+
+2004-04-05 00:48  jimweirich
+
+	* bin/gem: Changed Installer to RemoteInstaller in rubygems-info.
+
+2004-04-05 00:48  jimweirich
+
+	* Rakefile: Added generated test gem to clobber list.  Added
+	  functional test target to rakefile.
+
+2004-04-04 21:17  chadfowler
+
+	* packages/sources/lib/sources.rb: Added gems mirror at
+	  http://gems.chadfowler.com
+
+2004-04-04 20:51  chadfowler
+
+	* bin/gem, lib/rubygems/remote_installer.rb, test/functional.rb:
+	  More improved error messages (don't show stack trace when using
+	  bin/gem)
+
+2004-04-04 20:43  chadfowler
+
+	* lib/rubygems/cache.rb: Only read specs that end in "gemspec".
+	  The code doesn't handle non-gemspecs very well at all.
+
+2004-04-04 20:15  chadfowler
+
+	* test/mock/gems/specifications/sources-0.0.1.gemspec: [no log
+	  message]
+
+2004-04-04 20:09  chadfowler
+
+	* test/mock/gems/gems/sources-0.0.1/lib/sources.rb: Rearranging
+	  things a bit
+
+2004-04-04 20:02  chadfowler
+
+	* bin/gem, lib/rubygems/remote_installer.rb, test/bogussources.rb,
+	  test/functional.rb: Better error messages on unresolvable host.
+
+2004-04-04 12:50  chadfowler
+
+	* redist/session.gem, test/bogussources.rb, test/functional.rb:
+	  Added the beginnings of a functional test suite.
+
+2004-04-03 22:02  chadfowler
+
+	* lib/rubygems/validator.rb: Just had to explicitly rescue
+	  VerificationError.  All is well.
+
+2004-04-03 22:01  chadfowler
+
+	* lib/rubygems/validator.rb: Mauricio fixed a problem with alien
+	  (just failed to update it when we changed the gem directory), but
+	  now there's another issue I can't find.  Anyway, this fix is
+	  obviously needed.  But alien is broken anyway.
+
+2004-04-03 21:57  chadfowler
+
+	* install.rb, lib/rubygems/builder.rb: Batsman's bug report and
+	  code for the bugs I introduced today. :)
+
+2004-04-03 09:50  chadfowler
+
+	* lib/rubygems/specification.rb: Defaulting a spec's require_path
+	  to [] to avoid downstream errors.
+
+2004-04-03 09:06  chadfowler
+
+	* lib/rubygems/builder.rb, test/test_builder.rb: builder now
+	  validates the gemspec.
+
+2004-04-03 08:48  chadfowler
+
+	* lib/rubygems/specification.rb, test/test_specification.rb: Added
+	  checking for gem specs to make sure they have all required
+	  attributes.
+
+2004-04-03 08:06  chadfowler
+
+	* gemspecs/rublog.gemspec: My original rublog gem was broken, in
+	  that it didn't have a require_path.
+
+2004-04-02 07:48  chadfowler
+
+	* lib/rubygems/remote_installer.rb: Prompt for installation of
+	  dependencies.
+
+	  For now, there is a puts/gets in the middle of
+	  remote_installer.rb  This should probably be cleaned up later
+	  (return control flow to the gem program to install the
+	  dependencies, for example.
+
+2004-04-02 07:37  chadfowler
+
+	* TODO: [no log message]
+
+2004-04-02 07:34  chadfowler
+
+	* test/: simple_gem.rb, test_format.rb: Some things I forgot to cvs
+	  add earlier.
+
+2004-04-02 07:29  chadfowler
+
+	* example/: test.gemspec, lib/test.rb, lib/test/wow.rb: Removing
+	  example directory in favor of "examples" directory (just better
+	  organized).
+
+2004-04-02 07:26  chadfowler
+
+	* test/test_all.rb: Removed test_all.rb.  Rake is obviously a
+	  better way to do it.
+
+2004-03-31 19:13  chadfowler
+
+	* lib/rubygems/format.rb, lib/rubygems/installer.rb,
+	  lib/rubygems/validator.rb, test/test_all.rb,
+	  test/test_validator.rb: More tests and refactoring to support
+	  them.
+
+2004-03-30 02:41  rich
+
+	* lib/rubygems/installer.rb: allow passing parameters to extconf.rb
+	  with:
+
+	  ruby -i blah.gem --local -- --with-option
+
+	  everything past the -- will go to the extconf.rb...just like
+	  setup.rb
+
+2004-03-30 02:34  rich
+
+	* lib/rubygems/: installer.rb, specification.rb: very initial
+	  capability to build source gems.  this only lets you build native
+	  extensions so long as you do not have to specify --with-
+	  directories
+
+2004-03-29 08:31  rich
+
+	* install.rb: switched migration of old gems to new ./gems subdir
+	  to use FileUtils rather than ftools...hope to fix reported win32
+	  error.
+
+2004-03-29 01:04  rich
+
+	* lib/rubygems/doc_manager.rb: fixed bug in pathing based on new
+	  directory structure
+
+2004-03-29 01:03  rich
+
+	* lib/rubygems/remote_installer.rb: fixed bug in default for proxy
+	  (should default to nil not true)
+
+2004-03-29 01:03  rich
+
+	* bin/gem: updated with patch to allow for config file with minor
+	  difference from gavin's patch which passes a nil to the
+	  RemoteInstaller if the proxy does not exist
+
+2004-03-28 23:22  rich
+
+	* install.rb: added code to migrate gems if they are in the old
+	  directory structure
+
+2004-03-28 21:30  rich
+
+	* install.rb, lib/rubygems.rb, lib/rubygems/installer.rb,
+	  lib/rubygems/specification.rb: changed path of installed gems to
+	  be:
+
+	  ruby/gems/1.8/gems
+
+	  which cleans up the root.
+
+2004-03-28 18:53  chadfowler
+
+	* test/test_all.rb: This is the file to run for all of the tests.
+
+	  test_remote_installer is commented out for now.  The open URI
+	  patch that George gave us makes the code a lot nicer to look at,
+	  but a little harder to test.
+
+2004-03-28 18:50  chadfowler
+
+	* lib/rubygems/remote_installer.rb, test/test_cache.rb,
+	  test/test_remote_installer.rb: Added some tests for cache search
+
+2004-03-28 12:19  chadfowler
+
+	* bin/gem, lib/rubygems/validator.rb, test/test_validator.rb: Some
+	  tests for the validator.
+
+	  Made the validator more testable.
+
+2004-03-28 09:30  chadfowler
+
+	* bin/gem, lib/rubygems/validator.rb: Fixed a problem with false
+	  alarms in the validator.
+
+2004-03-27 08:23  chadfowler
+
+	* bin/gem: No longer have an option to pass http proxy host into
+	  the gem program.  Only reads it from the environment.  This is
+	  because George's patch (and open-uri) work this way, and I'm lazy
+	  right now.
+
+2004-03-27 08:17  chadfowler
+
+	* lib/rubygems/remote_installer.rb: George Marrows' nice patch to
+	  remove a bunch of code from remote_installer.
+
+	  Our remote_installer tests are failing.  We really need to start
+	  paying attention to the test directory. :(`
+
+2004-03-24 23:26  jimweirich
+
+	* install.rb: Do not install commands ending in ~.
+
+2004-03-24 23:25  jimweirich
+
+	* lib/rubygems/specification.rb: Changed executables from accessor
+	  to writer to avoid redefinition.
+
+2004-03-21 21:10  jimweirich
+
+	* bin/gem: fixed uninitialized directory option
+
+2004-03-21 15:34  jimweirich
+
+	* bin/gem: removed carriage returns that screwed up the #! line
+
+2004-03-21 09:02  chadfowler
+
+	* bin/gem: Gavin's bin/gem refactoring.
+
+2004-03-20 17:03  jimweirich
+
+	* bin/gem: added wrapping to gem listing
+
+2004-03-20 12:22  chadfowler
+
+	* install.rb: More cleaning by Gavin Sinclair
+
+2004-03-20 12:08  chadfowler
+
+	* examples/application/an-app.gemspec,
+	  examples/application/bin/myapp,
+	  examples/application/lib/somefunctionality.rb, lib/rubygems.rb,
+	  lib/rubygems/installer.rb, lib/rubygems/specification.rb: Added
+	  functionality for installing applications into the system bindir.
+	  Needs cleaning and refactoring.
+
+2004-03-20 07:53  chadfowler
+
+	* bin/gem: [no log message]
+
+2004-03-19 23:03  chadfowler
+
+	* bin/gem: More intuitive default.
+
+2004-03-19 10:45  chadfowler
+
+	* bin/gem: * Some minor rearranging of the test stuff so that
+	  installation errors will also abort the test run * Don't try to
+	  run tests if none are included with the gem
+
+2004-03-18 22:27  chadfowler
+
+	* bin/gem, example/lib/test.rb, lib/rubygems/cache.rb,
+	  lib/rubygems/specification.rb: * Preliminary support for: gem -i
+	  blah-0.0.1.gem --run-tests Needs to be cleaned up considerably.
+	  * Introduction of new gemspec metadata "unit_test_suite", which
+	  will be require'd in order to load all unit tests
+
+2004-03-17 09:33  chadfowler
+
+	* bin/gem: Applied Gavin Sinclair's patch to make help output
+	  better.
+
+2004-03-16 21:55  chadfowler
+
+	* bin/gem: Added --remote-list option for gem command to display
+	  all gems on server.
+
+2004-03-16 21:50  chadfowler
+
+	* bin/gem, doc/UserDoc.html: Fixed --help case inconsistencies and
+	  documentation typos as per Scott Harper's email.
+
+2004-03-16 21:41  chadfowler
+
+	* bin/gem: --list and --search display are the same.
+
+2004-03-16 21:33  chadfowler
+
+	* bin/gem: Implemented some of Scott Harper's search suggestions:
+	  case insensitive sort of returned gems and display description
+	  with gem name in search results.
+
+2004-03-16 21:20  chadfowler
+
+	* bin/gem, lib/rubygems/remote_installer.rb: http_proxy  option
+	  implemented
+
+2004-03-15 07:19  chadfowler
+
+	* lib/rubygems/remote_installer.rb: Installation is now case
+	  insensitive (like search)
+
+2004-03-15 07:07  chadfowler
+
+	* TODO, bin/gem, lib/rubygems/remote_installer.rb: Better error
+	  messages.  updated TODO list.
+
+2004-03-14 21:02  chadfowler
+
+	* bin/gem, lib/rubygems/remote_installer.rb: --dir didn't work with
+	  remote-install.  Now it does.
+
+2004-03-14 17:48  rich
+
+	* bin/gem: fixed uninstall bug
+
+2004-03-14 17:18  rich
+
+	* lib/rubygems/doc_manager.rb: changed to remove <drive>: on
+	  win32...ug
+
+2004-03-14 16:15  rich
+
+	* install.rb: fixed typo
+
+2004-03-14 16:13  rich
+
+	* install.rb: generate cmd files
+
+2004-03-14 16:13  rich
+
+	* bin/: gem.cmd, gem_server.cmd: now generate cmd files
+
+2004-03-14 15:52  chadfowler
+
+	* bin/gem: Fixed a small bug with --gen-rdoc and the remote
+	  installer.
+
+2004-03-14 15:38  chadfowler
+
+	* lib/rubygems.rb: Back to version 1.0 ;)
+
+2004-03-14 15:36  chadfowler
+
+	* lib/rubygems.rb: Updated rubygemsversion
+
+2004-03-14 15:31  chadfowler
+
+	* README: credits
+
+2004-03-14 15:24  rich
+
+	* README: initial readme
+
+2004-03-14 15:12  rich
+
+	* doc/UserDoc.html: updated w/doc on documentation ;-)
+
+2004-03-14 15:01  rich
+
+	* gemspecs/jabber4r.gemspec: added jabber4r gemspec
+
+2004-03-14 14:58  rich
+
+	* bin/gem_server: change the documentation path to /
+
+2004-03-14 14:57  rich
+
+	* install.rb: remove installing .rb files from ./bin
+
+2004-03-14 14:32  rich
+
+	* doc/: DevDoc.txt, GemSpecification.txt, UserDoc.html,
+	  UserDoc.txt: updated with latest docs
+
+2004-03-14 12:05  chadfowler
+
+	* test/test_remote_installer.rb: Fixed tests.
+
+2004-03-14 11:31  chadfowler
+
+	* lib/rubygems/specification.rb: Fixed bug that would manifest
+	  itself if a gem creator put apostrophes/single-quotes in the gem
+	  spec.
+
+2004-03-14 00:04  rich
+
+	* doc/: UserDoc.html, UserDoc.txt: finished user's guide
+
+2004-03-13 21:48  rich
+
+	* doc/: DevDoc.html, UserDoc.html, UserDoc.txt: updated user's
+	  guide...will finish section on ruby's library mgt soon ;-)
+
+2004-03-13 20:48  chadfowler
+
+	* doc/DevDoc.txt: Added documentation on making and distributing
+	  gems
+
+2004-03-13 20:20  chadfowler
+
+	* TODO: [no log message]
+
+2004-03-13 19:51  rich
+
+	* doc/: DevDoc.html, DevDoc.txt, GemSpecification.html,
+	  GemSpecification.txt, UserDoc.html, UserDoc.txt, doc.css,
+	  makedoc.rb: added these doc (wiki) files from
+	  http://rubygems.rubyforge.org/
+
+2004-03-13 17:56  chadfowler
+
+	* TODO, gemspecs/README, gemspecs/cgikit-1.1.0.gemspec,
+	  gemspecs/linguistics.gemspec, gemspecs/ook.gemspec,
+	  gemspecs/progressbar.gemspec, gemspecs/redcloth.gemspec,
+	  gemspecs/rublog.gemspec, gemspecs/ruby-doom.gemspec,
+	  gemspecs/rubyjdwp.gemspec, gemspecs/statistics.gemspec: Added
+	  some gemspecs for actual RAA packages.
+
+2004-03-13 14:35  chadfowler
+
+	* TODO, lib/rubygems/remote_installer.rb: Preliminary HTTP Proxy
+	  support.  Untested.
+
+2004-03-13 09:11  chadfowler
+
+	* packages/sources/lib/sources.rb: Changed to point to rubyforge
+
+2004-03-12 22:40  rich
+
+	* bin/generate_yaml_index.rb: generates a yaml index for a gems
+	  repository
+
+2004-03-12 22:02  chadfowler
+
+	* bin/gem_server: No longer serving gem specs.
+
+2004-03-12 21:42  chadfowler
+
+	* TODO, bin/gem_server.cgi: We decided to trash gem_server.cgi in
+	  favor of the static content generator Rich is working on.
+
+2004-03-12 21:15  chadfowler
+
+	* TODO: [no log message]
+
+2004-03-12 20:11  chadfowler
+
+	* bin/gem, lib/rubygems/installer.rb,
+	  lib/rubygems/remote_installer.rb: Basic search funtionality in.
+
+	  Slight refactoring of Installer and RemoteInstaller
+
+2004-03-12 18:28  chadfowler
+
+	* TODO: [no log message]
+
+2004-03-12 16:37  chadfowler
+
+	* TODO: [no log message]
+
+2004-03-12 16:14  chadfowler
+
+	* TODO: More TODO items
+
+2004-03-08 13:50  chadfowler
+
+	* TODO, bin/gem_server, example/test.gemspec: Use rdoc templates
+	  for HTML.  Nearly XHTML compliant.
+
+2004-03-08 08:21  chadfowler
+
+	* TODO: Added TODO list
+
+2004-03-08 08:12  chadfowler
+
+	* lib/rubygems/validator.rb: Fixed a small (but crippling) bug in
+	  the validator.
+
+2004-01-24 13:49  chadfowler
+
+	* bin/gem, lib/rubygems.rb, lib/rubygems/cache.rb,
+	  lib/rubygems/validator.rb, lib/rubygems/version.rb: More cleanup.
+
+2004-01-24 13:29  chadfowler
+
+	* bin/gem, lib/rubygems/remote_installer.rb: A little cleaning of
+	  (Remote)Installer inconsistencies
+
+2004-01-24 13:23  chadfowler
+
+	* bin/gem: Removed the weird instance variable thing we had going
+	  on. :)
+
+2004-01-07 17:34  chadfowler
+
+	* bin/gem: removed old cruft
+
+2003-12-24 11:32  chadfowler
+
+	* lib/rubygems/validator.rb: Gem validation was returning false
+	  negatives (corrupted gems were not reporting their corruption).
+
+2003-12-18 14:18  chadfowler
+
+	* lib/rubygems/cache.rb: Lyle noticed some out of date rdoc
+	  documentation.  Thanks Lyle!
+
+2003-12-03 08:05  chadfowler
+
+	* install.rb: Gavin's patch for installing the files in bin/ on
+	  rubygems installation.
+
+2003-11-30 00:36  chadfowler
+
+	* lib/rubygems/specification.rb: Little warnings adjustment
+
+2003-11-29 17:27  jimweirich
+
+	* Rakefile: added Rakefile to package
+
+2003-11-29 16:23  jimweirich
+
+	* lib/rubygems/specification.rb: Removed defined? and initialized
+	  @platform
+
+2003-11-29 16:08  jimweirich
+
+	* lib/rubygems/specification.rb: Initialized @loaded and check
+	  defined?(@platform) to silence some -w warnings.
+
+2003-11-29 09:26  rich
+
+	* bin/gem_server, lib/rubygems/doc_manager.rb: updated to support
+	  /doc URL to generate list of installed gems w/doc link for rdoc
+	  generated links.
+
+2003-11-29 08:30  rich
+
+	* lib/rubygems/doc_manager.rb: minor format change of error message
+
+2003-11-29 08:29  rich
+
+	* bin/gem, lib/rubygems/builder.rb, lib/rubygems/doc_manager.rb,
+	  lib/rubygems/installer.rb: instantiates DocManager now.  errors
+	  out on no install of RDoc.  warns if .gemspec does not specify
+	  having rdoc, but rdoc is generated
+
+2003-11-29 02:13  rich
+
+	* bin/gem, lib/rubygems.rb, lib/rubygems/doc_manager.rb,
+	  lib/rubygems/format.rb, lib/rubygems/installer.rb,
+	  lib/rubygems/specification.rb: added capability to generate rdoc
+	  on install of gem (--gen-rdoc).  this doc is placed in
+	  Gem.dir+doc+gem.full_name fixed but in installer when moving to
+	  format (not calling each) added doc manager to add/remove
+	  documenatation (right now only rdoc)
+
+2003-11-29 01:28  rich
+
+	* lib/rubygems/specification.rb: should not define the attr_readers
+	  for requirements/dependencies so undef is unnecessary
+
+2003-11-29 00:12  jimweirich
+
+	* lib/rubygems/specification.rb: Undefing dependencies and
+	  requirements removes warning when used with -w.
+
+2003-11-29 00:12  jimweirich
+
+	* lib/rubygems.rb: Using defined?($GEM_PATH) avoids warning when
+	  used with -w switch.
+
+2003-11-28 15:58  chadfowler
+
+	* bin/gem, example/test.gemspec, lib/rubygems.rb,
+	  lib/rubygems/installer.rb, lib/rubygems/validator.rb,
+	  lib/rubygems/format.rb: Separated gem file reading into a
+	  separate class/file.
+
+2003-11-28 15:20  rich
+
+	* lib/rubygems/specification.rb: added has_rdoc?/has_rdoc methods
+	  ... will be used to autogenerate rdoc
+
+2003-11-28 12:30  chadfowler
+
+	* lib/rubygems/validator.rb: Rdoc added
+
+2003-11-28 11:51  chadfowler
+
+	* bin/gem, lib/rubygems.rb, lib/rubygems/validator.rb: A little
+	  rearranging of the validation/alien code.  It's still ugly, but
+	  at least it's in its own file now. :)
+
+2003-11-28 11:40  chadfowler
+
+	* bin/gem: Removed a little cruft.
+
+2003-11-27 11:04  chadfowler
+
+	* bin/gem: Print success message for each gem *not* containing
+	  errors.
+
+2003-11-27 11:00  chadfowler
+
+	* bin/gem, lib/rubygems/installer.rb: Preliminary support for gem
+	  directory validation (--alien).  Looks for bad or missing gem
+	  files, missing spec files, files installed that aren't part of
+	  the gem, checksum mismatches, etc.
+
+	  Very ugly code.  Very ugly output.  Work in progress.
+
+2003-11-24 11:58  rich
+
+	* lib/rubygems/specification.rb: change full_name to include
+	  platform
+
+2003-11-24 09:15  chadfowler
+
+	* bin/gem: Option for HTTP Proxy server for remote-install.  Not
+	  yet implemented.
+
+2003-11-23 20:22  chadfowler
+
+	* lib/rubygems/builder.rb: Removed a stray \" in builder's success
+	  message
+
+2003-11-23 20:16  chadfowler
+
+	* lib/rubygems/specification.rb: Leaving escape in but commenting
+	  out its functionality because it hosed some other things up.
+	  Need to revisit this for the case where:
+
+	   s.summary = "Chad's Thing" # It's the apostrophe
+
+2003-11-23 20:08  chadfowler
+
+	* lib/rubygems/specification.rb: Escape quotes to avoid invalid
+	  gemspecs in the #{Gem.dir}/specifications directory
+
+2003-11-23 19:21  chadfowler
+
+	* bin/gem: Less ugly error message on file IO problems.
+
+2003-11-22 22:34  chadfowler
+
+	* bin/gem: Very simple support for validating a gem.  Will probably
+	  move this into the libs eventually.
+
+2003-11-22 20:53  chadfowler
+
+	* example/test.gemspec, lib/rubygems/builder.rb: Generate MD5
+	  checksum for gem and store it in the file.  Will be used to
+	  validate gem file before installation.
+
+2003-11-22 13:58  chadfowler
+
+	* install.rb, lib/rubygems/remote_installer.rb,
+	  packages/sources/sources.gemspec,
+	  packages/sources/lib/sources.rb: remote-install sources are now
+	  installed as a ruby gem at the time of rubygems installation.
+	  sources gemspec included in the rubygems distribution.
+
+2003-11-22 12:52  chadfowler
+
+	* bin/gem: Allow gem info by --version
+
+2003-11-22 11:50  chadfowler
+
+	* lib/: rubygems.rb, rubygems/cache.rb: Fixed the bug I introduced
+	  by fixing Rich's bug with gem cache caching. ;)
+
+	  Gem::Cache now has a #refresh! method.
+
+2003-11-22 10:16  chadfowler
+
+	* bin/gem, lib/rubygems.rb, lib/rubygems/installer.rb,
+	  lib/rubygems/remote_installer.rb: - Fixed bug in Gem.cache
+	  (though we may want to revisit it for in-memory caching - Command
+	  line configurable version for uninstall
+
+2003-11-22 00:28  rich
+
+	* lib/rubygems/cache.rb: rdoc'd search method
+
+2003-11-22 00:24  rich
+
+	* bin/gem, lib/rubygems/cache.rb, lib/rubygems/version.rb,
+	  test/test_version_comparison.rb: removed search_by_name because
+	  search does the same thing.  version::requirement was updated to
+	  that if you did not specific a version operation, it assumes an =
+	  sign.  updated tests accordingly
+
+2003-11-21 23:58  rich
+
+	* lib/rubygems/: cache.rb, installer.rb: allow version to be
+	  specified in uninstall (if called programatically)
+
+2003-11-21 23:52  rich
+
+	* lib/: rubygems.rb, rubygems/cache.rb, rubygems/installer.rb,
+	  rubygems/specification.rb: > moved all searching into cache..and
+	  now search by name/version and return an
+	  ordered list (.last == highest version).
+	  > modified uninstaller to allow selecting a specific version to
+	  uninstall if
+	  multiple versions are installed.
+	  > implemented comparison function on specification.
+	  > changed require_gem to use new search of cache function
+
+2003-11-21 21:06  chadfowler
+
+	* bin/gem, lib/rubygems/remote_installer.rb: Added ability to
+	  specify optional version requirement for remote installations
+
+2003-11-21 20:25  chadfowler
+
+	* test/test_remote_installer.rb: Removed carriage returns
+
+2003-11-21 19:04  chadfowler
+
+	* bin/gem_server: Converted from getopts to optparse.
+
+2003-11-21 18:31  rich
+
+	* lib/rubygems.rb: changed the order in which operations are
+	  performed in require_gem.  it now requires dependent gems prior
+	  to adding the require_paths to a gem.  otherwise we could have
+	  had a LoadError on a dependent gem but the paths were already
+	  added...potential problem
+
+2003-11-21 18:21  rich
+
+	* lib/rubygems/installer.rb: updated to ensure
+	  (specifications/cache) directories exist for a provided path
+
+2003-11-21 18:01  rich
+
+	* lib/rubygems/specification.rb: updated rdoc
+
+2003-11-21 17:59  rich
+
+	* bin/gem, lib/rubygems/builder.rb, lib/rubygems/installer.rb,
+	  lib/rubygems/specification.rb: fixed various bugs with the
+	  $GEM_PATH stuff, specifically on uninstall.  Also, changed to
+	  allow specifying a directory on install (--dir) and force install
+	  (--force).  Changed the builder generated ruby header to use
+	  optparse.
+
+2003-11-21 07:03  chadfowler
+
+	* lib/: rubygems.rb, rubygems/cache.rb,
+	  rubygems/remote_installer.rb: Remote installation of dependencies
+	  now works.  It downloads all dependent gems or errors out.
+
+	  Fixed bug in require_gem.  Wrong call to cache.
+
+2003-11-21 00:59  rich
+
+	* bin/gem, example/test.gemspec, lib/rubygems.rb,
+	  lib/rubygems/cache.rb, lib/rubygems/installer.rb,
+	  lib/rubygems/specification.rb: added capability to support
+	  multiple paths $GEM_PATH in Ruby and RUBY_GEMS in the ARGV.  Lots
+	  of changes were needed to support this.  also added the --force
+	  and --dir options to gem installtion
+
+2003-11-20 22:50  chadfowler
+
+	* bin/gem: Switched to optparse.  Not a whole lot gained, but it
+	  seems to be the way Ruby is going.  It's nice not to have to do
+	  the "when" stuff, I guess.
+
+2003-11-19 23:41  chadfowler
+
+	* lib/rubygems/: installer.rb, remote_installer.rb: Added
+	  chadfowler.com to the hardcoded remote install list.
+
+	  Fixed a dangling YAML.load that broke uninstall.
+
+2003-11-19 22:56  rich
+
+	* lib/rubygems.rb: fixed bug in loading rubygems
+
+2003-11-19 22:51  chadfowler
+
+	* bin/: gem_server, gem_server.cgi: require 'yaml' :)
+
+2003-11-19 22:44  rich
+
+	* lib/: rubygems.rb, rubygems/cache.rb, rubygems/specification.rb:
+	  changed the format of stuff stored in the spec directory to ruby
+	  instead of YAML.  This allows us to not have to load yaml in
+	  'require_gem'.  switched the specification list to a Cache
+	  object.
+
+2003-11-19 21:56  rich
+
+	* lib/rubygems/installer.rb: write the spec file in ruby and not in
+	  yaml format (in the spec dir)
+
+2003-11-19 20:32  rich
+
+	* lib/rubygems/specification.rb: added to_ruby method to generate a
+	  ruby string that can be eval'ed in to build a Gem Specification
+
+2003-11-17 21:37  jimweirich
+
+	* bin/: gem_server, gem_server.cgi: removed carriage returns
+
+2003-11-17 21:19  chadfowler
+
+	* install.rb: Accidentally left some junk in the file.
+
+2003-11-17 19:50  dblack
+
+	* test/test_version_comparison.rb: * Test cases for Version.rb
+
+2003-11-17 19:50  dblack
+
+	* lib/rubygems/version.rb: * Split off tests into
+	  rubygems/tests/test_version_comparison.rb
+
+2003-11-17 12:37  chadfowler
+
+	* install.rb: Create File.join(Config::CONFIG['libdir'], "ruby",
+	  "gems") + "specifications" and + "cache" during installation.
+
+	  Need to remove this from rubygems.rb and replace with
+	  ensure_directory call.
+
+2003-11-17 12:29  rich
+
+	* lib/rubygems/version.rb: rdoc added
+
+2003-11-17 11:31  rich
+
+	* lib/rubygems/specification.rb: rdoc added
+
+2003-11-17 10:38  rich
+
+	* lib/rubygems/: cache.rb, installer.rb: made rdoc comments and
+	  renamed some variables
+
+2003-11-17 08:48  dblack
+
+	* lib/rubygems/version.rb: * Added stricter checking of incoming
+	  Requirement string
+
+	  * Added unit tests at end of file
+
+2003-11-17 07:32  chadfowler
+
+	* bin/: gem_server, gem_server.cgi: Refactored gem_server program
+	  and added an equivalent CGI version.
+
+2003-11-17 00:14  rich
+
+	* lib/: rubygems.rb, rubygems/builder.rb, rubygems/cache.rb: added
+	  rdoc documentation
+
+2003-11-16 17:15  chadfowler
+
+	* bin/: gem.cmd, gem_server.cmd: Added some batch files for Windows
+
+2003-11-16 17:08  rich
+
+	* install.rb, bin/gem, bin/gem_server, example/test.gemspec,
+	  example/lib/test.rb, example/lib/test/wow.rb, lib/rubygems.rb,
+	  lib/rubygems/builder.rb, lib/rubygems/cache.rb,
+	  lib/rubygems/installer.rb, lib/rubygems/remote_installer.rb,
+	  lib/rubygems/specification.rb, lib/rubygems/version.rb,
+	  test/test_remote_installer.rb: Initial import developed at
+	  RubyConf 2003 by:
+
+	  Rich Kilmer Chad Fowler David Black Paul Brannon Jim Weirich
+
+2003-11-16 17:08  rich
+
+	* install.rb, bin/gem, bin/gem_server, example/test.gemspec,
+	  example/lib/test.rb, example/lib/test/wow.rb, lib/rubygems.rb,
+	  lib/rubygems/builder.rb, lib/rubygems/cache.rb,
+	  lib/rubygems/installer.rb, lib/rubygems/remote_installer.rb,
+	  lib/rubygems/specification.rb, lib/rubygems/version.rb,
+	  test/test_remote_installer.rb: Initial revision
+
+Local variables:
+indent-tabs-mode: t
+tab-width: 8
+end:

Added: MacRuby/trunk/test/libs/rubygems/GPL.txt
===================================================================
--- MacRuby/trunk/test/libs/rubygems/GPL.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/GPL.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Added: MacRuby/trunk/test/libs/rubygems/History.txt
===================================================================
--- MacRuby/trunk/test/libs/rubygems/History.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/History.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,799 @@
+=== 1.3.5 / 2009-06-??
+
+Bug fixes:
+
+* Fix use of prerelease gems.
+* Gem.bin_path no longer escapes path with spaces. Bug #25935 and #26458.
+
+Deprecation Notices:
+
+* Bulk index update is no longer supported (the code currently remains, but not
+  the tests)
+* Gem::manage_gems was removed in 1.3.3.
+* Time::today was removed in 1.3.3.
+
+=== 1.3.4 / 2009-05-03
+
+Bug Fixes:
+
+* Fixed various warnings
+* Gem::ruby_version works correctly for 1.8 branch and trunk
+* Prerelease gems now show up in `gem list` and can be used
+* Fixed option name for `gem setup --format-executable`
+* RubyGems now matches Ruby > 1.9.1 gem paths
+* Gem::RemoteFetcher#download now works for explicit Windows paths across
+  drives.  Bug #25882 by Lars Christensen
+* Fix typo in Gem::Requirement#parse.  Bug #26000 by Mike Gunderloy.
+
+Deprecation Notices:
+
+* Bulk index update is no longer supported (the code currently remains, but not
+  the tests)
+* Gem::manage_gems was removed in 1.3.3.
+* Time::today was removed in 1.3.3.
+
+=== 1.3.3 / 2009-05-04
+
+New Features:
+
+* `gem server` allows port names (from /etc/services) with --port.
+* `gem server` now has search that jumps to RDoc.  Patch #22959 by Vladimir
+  Dobriakov.
+* `gem spec` can retrieve single fields from a spec (like `gem spec rake
+  authors`).
+* Gem::Specification#has_rdoc= is deprecated and ignored (defaults to true)
+* RDoc is now generated regardless of Gem::Specification#has_rdoc?
+
+Bug Fixes:
+
+* `gem clean` now cleans up --user-install gems.  Bug #25516 by Brett
+  Eisenberg.
+* Gem.bin_path now escapes paths with spaces.
+* Rake extension builder uses explicit correctly loads rubygems when invoking
+  rake.
+* Prerelease versions now match "~>" correctly.  Patch #25759 by Yossef
+  Mendelssohn.
+* Check bindir for executables, not root when validating.  Bug reported by
+  David Chelimsky.
+* Remove Time.today, no way to override it before RubyGems loads.  Bug #25564
+  by Emanuele Vicentini
+* Raise Gem::Exception for #installation_path when not installed.  Bug #25741
+  by Daniel Berger.
+* Don't raise in Gem::Specification#validate when homepage is nil.  Bug #25677
+  by Mike Burrows.
+* Uninstall executables from the correct directory.  Bug #25555 by Brett
+  Eisenberg.
+* Raise Gem::LoadError if Kernel#gem fails due to previously-loaded gem.  Bug
+  reported by Alf Mikula.
+
+Deprecation Notices:
+
+* Gem::manage_gems has been removed.
+* Time::today has been removed early.  There was no way to make it warn and be
+  easy to override with user code.
+
+=== 1.3.2 / 2009-04-15
+
+Select New Features:
+
+* RubyGems now loads plugins from rubygems_plugin.rb in installed gems.
+  This can be used to add commands (See Gem::CommandManager) or add
+  install/uninstall hooks (See Gem::Installer and Gem::Uninstaller).
+* Gem::Version now understands prerelease versions using letters. (eg.
+  '1.2.1.b')  Thanks to Josh Susser, Alex Vollmer and Phil Hagelberg.
+* RubyGems now includes a Rake task for creating gems which replaces rake's
+  Rake::GemPackageTask.  See Gem::PackageTask.
+* Gem::find_files now returns paths in $LOAD_PATH.
+* Added Gem::promote_load_path for use with Gem::find_files
+* Added Gem::bin_path to make finding executables easier.  Patch #24114 by
+  James Tucker.
+* Various improvements to build arguments for installing gems.
+* `gem contents` added --all and --no-prefix.
+* Gem::Specification
+  * #validate strips directories and errors on not-files.
+  * #description no longer removes newlines.
+  * #name must be a String.
+  * FIXME and TODO are no longer allowed in various fields.
+  * Added support for a license attribute.  Feature #11041 (partial).
+  * Removed Gem::Specification::list, too much process growth.  Bug #23668 by
+    Steve Purcell.
+* `gem generate_index`
+  * Can now generate an RSS feed.
+  * Modern indicies can now be updated incrementally.
+  * Legacy indicies can be updated separately from modern.
+
+Select Bugs Fixed:
+
+* Better gem activation error message. Patch #23082.
+* Kernel methods are now private.  Patch #20801 by James M. Lawrence.
+* Fixed various usability issues with `gem check`.
+* `gem update` now rescues InstallError and continues.  Bug #19268 by Gabriel
+  Wilkins.
+* Allow 'https', 'file' as a valid schemes for --source.  Patch #22485.
+* `gem install`
+  * Now removes existing path before installing.  Bug #22837.
+  * Uses Gem::bin_path in executable stubs to work around Kernel#load bug in
+    1.9.
+  * Correctly handle build args (after --) via the API.  Bug #23210.
+* --user-install
+  * `gem install --no-user-install` now works.  Patch #23573 by Alf Mikula.
+  * `gem uninstall` can now uninstall from ~/.gem.  Bug #23760 by Roger Pack.
+* setup.rb
+  * Clarify RubyGems RDoc installation location.  Bug #22656 by Gian Marco
+    Gherardi.
+  * Allow setup to run from read-only location.  Patch #21862 by Luis Herrera.
+  * Fixed overwriting ruby executable when BASERUBY was not set.  Bug #24958
+    by Michael Soulier.
+  * Ensure we're in a RubyGems dir when installing.
+  * Deal with extraneous quotation mark when autogenerating .bat file on MS
+    Windows.  Bug #22712.
+
+Deprecation Notices:
+
+* Gem::manage_gems has been removed.
+* Time::today will be removed in RubyGems 1.4.
+
+Special thanks to Chad Wooley for backwards compatibility testing and Luis
+Lavena and Daniel Berger for continuing windows support.
+
+=== 1.3.1 / 2008-10-28
+
+Bugs fixed:
+
+* Disregard ownership of ~ under Windows while creating ~/.gem.  Fixes
+  issues related to no uid support under Windows.
+* Fix requires for Gem::inflate, Gem::deflate, etc.
+* Make Gem.dir respect :gemhome value from config.  (Note: this feature may be
+  removed since it is hard to implement on 1.9.)
+* Kernel methods are now private.  Patch #20801 by James M. Lawrence.
+* Gem::location_of_caller now behaves on Windows.  Patch by Daniel Berger.
+* Silence PATH warning.
+
+Deprecation Notices:
+
+* Gem::manage_gems will be removed on or after March 2009.
+
+=== 1.3.0 / 2008-09-25
+
+New features:
+
+* RubyGems doesn't print LOCAL/REMOTE titles for `gem query` and friends if
+  stdout is not a TTY, except with --both.
+* Added Gem.find_files, allows a gem to discover features provided by other
+  gems.
+* Added pre/post (un)install hooks for packagers of RubyGems.  (Not for gems
+  themselves).
+* RubyGems now installs gems into ~/.gem if GEM_HOME is not writable.  Use
+  --no-user-install command-line switch to disable this behavior.
+* Fetching specs for update now uses If-Modified-Since requests.
+* RubyGems now updates the ri cache when the rdoc gem is installed and
+  documentation is generated.
+
+Deprecation Notices:
+
+* Gem::manage_gems now warns when called.  It will be removed on or after March
+  2009.
+
+Bugs Fixed:
+
+* RubyGems 1.3.0+ now updates when no previous rubygems-update is installed.
+  Bug #20775 by Hemant Kumar.
+* RubyGems now uses the regexp we already have for `gem list --installed`.  Bug
+  #20876 by Nick Hoffman.
+* Platform is now forced to Gem::Platform::RUBY when nil or blank in the
+  indexer.  Fixes various uninstallable gems.
+* Handle EINVAL on seek.  Based on patch in bug #20791 by Neil Wilson.
+* Fix HTTPS support.  Patch #21072 by Alex Arnell.
+* RubyGems now loads all cache files even if latest has been loaded.  Bug
+  #20776 by Uwe Kubosch.
+* RubyGems checks for support of development dependencies for #to_ruby.  Bug
+  #20778 by Evan Weaver.
+* Now specifications from the future can be loaded.
+* Binary script uninstallation fixed.  Bug #21234 by Neil Wilson.
+* Uninstallation with -i fixed.  Bug #20812 by John Clayton.
+* Gem::Uninstaller#remove_all now calls Gem::Uninstaller#uninstall_gem so hooks
+  get called.  Bug #21242 by Neil Wilson.
+* Gem.ruby now properly escaped on windows.  Fixes problem with extension
+  compilation.
+* `gem lock --strict` works again.  Patch #21814 by Sven Engelhardt.
+* Platform detection for Solaris was improved.  Patch #21911 by Bob Remeika.
+
+Other Changes Include:
+
+* `gem help install` now describes _version_ argument to executable stubs
+* `gem help environment` describes environment variables and ~/.gemrc and
+  /etc/gemrc
+* On-disk gemspecs are now read in UTF-8 and written with a UTF-8 magic comment
+* Rakefile
+  * If the SETUP_OPTIONS environment variable is set, pass its contents as
+    arguments to setup.rb
+* lib/rubygems/platform.rb
+  * Remove deprecated constant warnings and really deprecate them.  (WIN32,
+    etc).
+* lib/rubygems/remote_fetcher.rb
+  * Now uses ~/.gem/cache if the cache dir in GEM_HOME is not writable.
+* lib/rubygems/source_index.rb
+  * Deprecate options to 'search' other than Gem::Dependency instances and
+    issue warning until November 2008.
+* setup.rb
+  * --destdir folder structure now built using Pathname, so it works for
+    Windows platforms.
+* test/*
+  * Fixes to run tests when under test/rubygems/.  Patch by Yusuke ENDOH
+    [ruby-core:17353].
+* test/test_ext_configure_builder.rb
+  * Locale-free patch by Yusuke Endoh [ruby-core:17444].
+
+=== 1.2.0 / 2008-06-21
+
+New features:
+
+* RubyGems no longer performs bulk updates and instead only fetches the gemspec
+  files it needs.  Alternate sources will need to upgrade to RubyGems 1.2 to
+  allow RubyGems to take advantage of the new metadata updater.  If a pre 1.2
+  remote source is in the sources list, RubyGems will revert to the bulk update
+  code for compatibility.
+* RubyGems now has runtime and development dependency types.  Use
+  #add_development_dependency and #add_runtime_dependency.  All typeless
+  dependencies are considered to be runtime dependencies.
+* RubyGems will now require rubygems/defaults/operating_system.rb and
+  rubygems/defaults/#{RBX_ENGINE}.rb if they exist.  This allows packagers and
+  ruby implementers to add custom behavior to RubyGems via these files.  (If
+  the RubyGems API is insufficient, please suggest improvements via the
+  RubyGems list.)
+* /etc/gemrc (and windows equivalent) for global settings
+* setup.rb now handles --vendor and --destdir for packagers
+* `gem stale` command that lists gems by last access time
+
+Bugs Fixed:
+
+* File modes from gems are now honored, patch #19737
+* Marshal Gem::Specification objects from the future can now be loaded.
+* A trailing / is now added to remote sources when missing, bug #20134
+* Gems with legacy platforms will now be correctly uninstalled, patch #19877
+* `gem install --no-wrappers` followed by `gem install --wrappers` no longer
+  overwrites executables
+* `gem pristine` now forces reinstallation of gems, bug #20387
+* RubyGems gracefully handles ^C while loading .gemspec files from disk, bug
+  #20523
+* Paths are expanded in more places, bug #19317, bug #19896
+* Gem::DependencyInstaller resets installed gems every install, bug #19444
+* Gem.default_path is now honored if GEM_PATH is not set, patch #19502
+
+Other Changes Include:
+
+* setup.rb
+  * stub files created by RubyGems 0.7.x and older are no longer removed.  When
+    upgrading from these ancient versions, upgrade to 1.1.x first to clean up
+    stubs.
+  * RDoc is no longer required until necessary, patch #20414
+* `gem server`
+  * Now completely matches the output of `gem generate_index` and
+    has correct content types
+  * Refreshes from source directories for every hit.  The server will no longer
+    need to be restarted after installing gems.
+* `gem query --details` and friends now display author, homepage, rubyforge url
+  and installed location
+* `gem install` without -i no longer reinstalls dependencies if they are in
+  GEM_PATH but not in GEM_HOME
+* Gem::RemoteFetcher now performs persistent connections for HEAD requests,
+  bug #7973
+
+=== 1.1.1 / 2008-04-11
+
+Bugs Fixed:
+
+* Gem.prefix now returns non-nil only when RubyGems was installed outside
+  sitelibdir or libdir.
+* The `gem server` gem list now correctly links to gem details.
+* `gem update --system` now passes --no-format-executable to setup.rb.
+* Gem::SourceIndex#refresh! now works with multiple gem repositories.
+* Downloaded gems now go into --install-dir's cache directory.
+* Various fixes to downloading gem metadata.
+* `gem install --force` now ignores network errors too.
+* `gem pristine` now rebuilds extensions.
+* `gem update --system` now works on virgin Apple ruby.
+* Gem::RemoteFetcher handles Errno::ECONNABORTED.
+* Printing of release notes fixed.
+
+=== 1.1.0 / 2008-03-29
+
+New features:
+
+* RubyGems now uses persistent connections on index updates.  Index updates are
+  much faster now.
+* RubyGems only updates from a latest index by default, cutting candidate gems
+  for updates to roughly 1/4 (at present).  Index updates are even faster
+  still.
+  * `gem list -r` may only show the latest version of a gem, add --all to see
+    all gems.
+* `gem spec` now extracts specifications from .gem files.
+* `gem query --installed` to aid automation of checking for gems.
+
+Bugs Fixed:
+
+* RubyGems works with both Config and RbConfig now.
+* Executables are now cleaned upon uninstall.
+* You can now uninstall from a particular directory.
+* Updating from non-default sources fixed.
+* Executable stubs now use ruby install name in shebang.
+* `gem unpack` checks every directory in Gem.path now.
+* `gem install` now exits with non-zero exit code when appropriate.
+* `gem update` only updates gems that need updates.
+* `gem update` doesn't force remote-only updates.
+* `gem update` handles dependencies properly when updating.
+* Gems are now loaded in Gem.path order.
+* Gem stub scripts on windows now work outside Gem.bindir.
+* `gem sources -r` now works without network access.
+
+Other Changes Include:
+
+* RubyGems now requires Ruby > 1.8.3.
+* Release notes are now printed upon installation.
+* `gem env path` now prints a usable path.
+* `gem install` reverts to local-only installation upon network error.
+* Tar handling code refactoring and cleanup.
+* Gem::DependencyInstaller's API has changed.
+
+For a full list of changes to RubyGems, see the ChangeLog file.
+
+=== 1.0.1 / 2007-12-20
+
+Bugs Fixed:
+
+* Installation on Ruby 1.8.3 through 1.8.5 fixed
+* `gem build` on 1.8.3 fixed
+
+Other Changes Include:
+
+* Since RubyGems 0.9.5, RubyGems is no longer supported on Ruby 1.8.2 or older,
+  this is official in RubyGems 1.0.1.
+
+=== 1.0.0 / 2007-12-20
+
+Major New Features Include:
+
+* RubyGems warns about various problems with gemspecs during gem building
+* More-consistent versioning for the RubyGems software
+
+Other Changes Include:
+
+* Fixed various bugs and problems with installing gems on Windows
+* Fixed using `gem server` for installing gems
+* Various operations are even more verbose with --verbose
+* Built gems are now backwards compatible with 0.9.4
+* Improved detection of RUBYOPT loading rubygems
+* `ruby setup.rb` now has a --help option
+* Gem::Specification#bindir is now respected on installation
+* Executable stubs can now be installed to match ruby's name, so if ruby is
+  installed as 'ruby18', foo_exec will be installed as 'foo_exec18'
+* `gem unpack` can now unpack into a specific directory with --target
+* OpenSSL is no longer required by default
+
+Deprecations and Deletions:
+
+* Kernel#require_gem has been removed
+* Executables without a shebang will not be wrapped in a future version, this
+  may cause such executables to fail to operate on installation
+* Gem::Platform constants other than RUBY and CURRENT have been removed
+* Gem::RemoteInstaller was removed
+* Gem::Specification#test_suite_file and #test_suite_file= are deprecated in
+  favor of #test_file and #test_file=
+* Gem::Specification#autorequire= has been deprecated
+* Time::today will be removed in a future version
+
+=== 0.9.5 / 2007-11-19
+
+Major New Features Include:
+
+* Platform support
+* Automatic installation of platform gems
+* New bandwidth and memory friendlier index file format
+* "Offline" mode (--no-update-sources)
+* Bulk update threshold can be specified (-B, --bulk-threshold)
+* New `gem fetch` command
+* `gem` now has "really verbose" output when you specify -v
+* Improved stubs and `gem.bat` on mswin, including better compatiblity
+  with the One-Click Installer.
+
+Other Changes Include:
+
+* Time::today is deprecated and will be removed at a future date
+* Gem::manage_gems is deprecated and will be removed at a future date
+* `gem install --include-dependencies` (-y) is now deprecated since it is the
+  default, use --ignore-dependencies to turn off automatic dependency
+  installation
+* Multi-version diamond dependencies only are installed once
+* Processing a YAML bulk index update takes less memory
+* `gem install -i` makes sure all depenencies are installed
+* `gem update --system` reinstalls into the prefix it was originally installed
+  in
+* `gem update --system` respects --no-rdoc and --no-ri flags
+* HTTP basic authentication support for proxies
+* Gem::Specification#platforms should no longer be a String, use
+  Gem::Platform::CURRENT when building binary gems instead
+* `gem env` has more diagnostic information
+* require 'rubygems' loads less code
+* sources.gem is gone, RubyGems now uses built-in defaults
+* `gem install --source` will no longer add --source by default, use `gem
+  sources --add` to make it a permanent extra source
+* `gem query` (list) no longer prints details by default
+* Exact gem names are matched in various places
+* mkrf extensions are now supported
+* A gem can depend on a specific RubyGems version
+* `gem_server` is now `gem server`
+* `gemlock` is now `gem lock`
+* `gem_mirror` is now `gem mirror`
+* `gemwhich` is now `gem which`
+* `gemri` is no longer included with RubyGems
+* `index_gem_repository.rb` is now `gem generate_index`
+* `gem` performs more validation of parameters
+* Custom rdoc styles are now supported
+* Gem indexer no longer removes quick index during index creation
+* Kernel#require only rescues a LoadError for the file being required now
+* `gem dependencies` can now display some information for remote gems
+* Updating RubyGems now works with RUBYOPT=-rubygems
+
+Special thanks to:
+
+* Daniel Berger
+* Luis Lavena
+* Tom Copeland
+* Wilson Bilkovich
+
+=== 0.9.4 / 2007-05-23
+
+If you are experiencing problems with the source index (e.g. strange
+"No Method" errors), or problems with zlib (e.g. "Buffer Error"
+messsage), we recommend upgrading to RubyGems 0.9.4.
+
+Bug Fixes Include:
+
+* Several people have been experiencing problems with no method errors
+  on the source index cache.  The source index cache is now a bit more
+  self healing.  Furthermore, if the source index cache is
+  irreparable, then it is automatically dropped and reloaded.
+* The source cache files may now be dropped with the "gem sources
+  --clear-all" command.  (This command may require root is the system
+  source cache is in a root protected area).
+* Several sub-commands were accidently dropped from the "gem" command.
+  These commands have been restored.
+
+=== 0.9.3 / 2007-05-10
+
+Bug Fixes Include:
+
+The ZLib library on Windows will occasionally complains about a buffer error
+when unpacking gems.  The Gems software has a workaround for that problem, but
+the workaround was only enabled for versions of ZLib 1.2.1 or earlier.  We
+have received several reports of the error occuring with ZLib 1.2.3, so we
+have permanently enabled the work around on all versions.
+
+=== 0.9.2 / 2007-02-05
+
+Bug Fixes Include:
+
+* The "unpack" command now works properly.
+* User name and password are now passed properly to the authenticating
+  proxy when downloading gems.
+
+=== 0.9.1 / 2007-01-16
+
+See ChangeLog
+
+=== 0.9.0 / 2006-06-28
+
+Finally, the much anticipated RubyGems version 0.9.0 is now available.
+This release includes a number of new features and bug fixes.  The
+number one change is that we can now download the gem index
+incrementally.  This will greatly speed up the gem command when only a
+few gems are out of date.
+
+Major Enhancments include:
+
+* The gem index is now downloaded incrementally, only updating entries
+  that are out of date.  If more than 50 entries are out of date, we
+  revert back to a bulk download.
+* Several patches related to allowing RubyGems to work with
+  authenticating proxies (from Danie Roux and Anatol Pomozov).  Just
+  put the user and password in the proxy URL (e.g. -p
+  http://user:password@proxy.address.com:8080) or use the
+  HTTP_PROXY_USER and HTTP_PROXY_PASS environment variables.
+* The gem unpack command can now accept a file path rather than just a
+  install gem name.
+* Both RI and RDOC documents are now generated by default.
+* A gemri command is included to read gem RI docs (only needed for
+  Ruby 1.8.4 or earlier).
+
+Minor enhancements include:
+
+* Verison 0.0.0 is now a valid gem version.
+* Better detection of missing SSL functionality.
+* SSL is not required if the security policy does not require
+  signature checking.
+* Rake built extensions are now supported (Tilman Sauerbeck).
+* Several autorequire bug fixes.
+* --traceback is now an alias for --backtrace (I can never remember
+  which one it is).
+* SAFE=1 compatibility fixes.
+* .rbw is now a supported suffix for RubyGem's custom require.
+* Several Ruby 1.9 compatibility fixes (Eric Hodel).
+
+Bug Fixes:
+
+* Added dashes to gemspecs generated in Ruby 1.8.3.  This solves some
+  cross-Ruby version compatibility issues.
+* Fixed bug where the wrong executables could be uninstalled (Eric
+  Hodel).
+* Fixed bug where gem unpack occasionally unpacked the wrong gem.
+* Fixed bug where a fatal error occured when permissions on .gemrc
+  were too restrictive (reported by Luca Pireddu).
+* Fixed prefix handling for native expressions (patch by Aaron Patterson).
+* Fixed several Upgrade => Update typos.
+
+=== 0.8.11 / 2005-07-13
+
+* -y is a synonym for --include-dependencies.
+* Better handling of errors in the top level rescue clause.
+* Package list command (e.g. gem inspect GEM).
+* .gemrc now allows cvsrc-like options to set defaults per subcommand.
+* The autorequire gem spec field will now accept a list.
+* Substituted Time for Date in specs, increasing performance
+  dramatically.
+* Fixed reported bug of gem directories ending in "-" (reported by
+  Erik Hatcher).
+* Fixed but in installer that caused dependency installation to not
+  work.
+* Added Paul Duncan's gem signing patch.
+* Added Mark Hubbart's Framework patch (for better integration with OS
+  X).
+* Added David Glasser's install-from-mirror patch.
+* Additional internal structural cleanup and test reorganization.
+
+=== 0.8.10 / 2005-03-27
+
+* In multi-user environments, it is common to supply mulitple versions of gems
+  (for example Rails), allowing individual users to select the version of the
+  gem they desire.  This allows a user to be insulated from updates to that
+  gem.  RubyGems 0.8.10 fixes a problem where gems could occasionally become
+  confused about the current versions of libraries selected by the user.
+* The other annoying bug is that if there are any existing rubygems-update gems
+  installed, then the "gem update --system" command will download a new
+  update, but install the latest update prior to the download.
+
+=== 0.8.9
+
+Never released
+
+=== 0.8.8 / 2005-03-14
+
+* Moved the master definition of class Requirement back under version.
+  Kept the body of Requirement under Gem.
+
+=== 0.8.7 / 2005-03-14
+
+Even though it has only been a few weeks since that last release,
+there are quite a number of new features in 0.8.7.  A complete list of
+new features will be given below, but here is a summary of the hot
+items.
+
+* The bug that prevented some users from installing rails has been
+  squashed.  A big thanks to Bill Guindon (aGorilla) for helping track
+  that one down.
+
+There are several new commands available on the gem command:
+
+* gem cleanup GEMNAME -- Cleanup (uninstall) all the old versions of
+  gem.  If the gem name is omitted, the entire repository is cleaned.
+* gem dependency GEMNAME -- Show the dependencies for the named gems.
+  This is really helpful when trying to figure out what gem needs what
+  other gem.
+
+There changes to the existing commands as well.
+
+* gem uninstall is much smarter about removing gems from the
+  repository.  Lists of gems are now uninstalled in proper dependency
+  order (ie. if A depends on B, A is uninstalled first).  Also,
+  warnings about broken dependencies occur only when removing the
+  *last* gem that supports a dependency is removed.
+
+Both gem install and gem uninstall support some new command line
+options that can reduce the amount of yes/no queries given the user.
+For install we have:
+
+* --ignore-dependencies -- Only install requests gems, no
+  dependendecies are automatically installed.
+* --include-dependencies -- Automatically install dependencies,
+  without confirmation.
+
+For gem uninstall, the new options are:
+
+* --all -- Uninstall all matching gems without confirmation.
+* --ignore-dependencies -- Uninstall, even if dependencies are broken.
+* --executables -- Remove executables without confirmation
+
+Under general cleanup, gems will not, by default, run RDoc on packages
+that do not have the RDoc flag set.
+
+And finally there is a new library file 'gemconfigure' to aid in
+writing version sensitive applications (without undue dependencies on
+RubyGems); and 'gemwhich', a short script to locate libraries in the
+file system.  You can read more about them here:
+
+* gemconfigure: http://docs.rubygems.org/read/chapter/4#page73
+* gemwhich: http://docs.rubygems.org/read/chapter/17
+
+=== 0.8.6 / 2005-02-27
+
+* Fixed a small bug with shebang construction
+
+=== 0.8.5 / 2005-02-26
+
+Do you know how you used to dread getting the following message while
+installing gems?
+
+  Updating Gem source index for: http://gems.rubyforge.org
+
+It could take up to 30 seconds (on my machine, even worse on others) for
+that crazy source index to update.
+
+This latest release of RubyGems speeds that wait time up considerably.
+The following table gives the following times for installing RedCloth
+with a required source index update on three system we had available to
+us.  No RDoc generation was included in the following times.
+
+  RubyGems    Linux         Mac OSX      Windows
+  0.8.4       33 secs       73 secs      58 secs
+  0.8.5        8 secs       14 secs      21 secs
+
+The new caching code is at least 3x faster than previous versions.  Woo
+Hoo!
+
+=== 0.8.4 / 2005-01-01
+
+* Rubygems 0.8.3's installer was broken unless you already had an older
+  version of RubyGems installed.  That's fixed.
+* Change in the way Gem::Specification internally deals with lazy attributes
+  and defaults, bringing (with some loadpath_manager changes) a fairly
+  significant increase in speed.
+* Support for lower-cased Gem file names (for you, Paul Duncan :)
+* Erik Veenstra's patch for making Gem versions sortable.
+
+=== 0.8.3 / 2004-12-07
+
+No real earth shattering news here, but there were a number of really
+annoying issues involving other libraries that RubyGems depends upon.
+0.8.3 contains some workarounds for these issues.  In particular:
+
+* Added workaround for the null byte in Dir string issue. (see
+  http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/121702).
+  (Thanks to Mauricio Fernández for the quick response on this one).
+* Added workaround for old version of Zlib on windows that caused
+  Ruwiki to fail to install. (see
+  http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/121770)
+* Added workaround for large YAML file issues.  (We dynamically cut
+  down the size of the source index YAML file and seem to have worked
+  around immediate issues.
+
+There has been some minor usability enhancements and changes ...
+
+* A user specific source index cache can be used when the site-wide
+  cache is unwritable (i.e. because you are running as a non-admin).
+  This *greatly* speeds up gem commands run in non-admin mode when the
+  site-wide cache is out of date.
+* The gem command now used an HTTP HEAD command to detect if the
+  server's source index needs to be downloaed.
+* gem check gemname --test will run unit tests on installed gems that
+  have unit tests.
+* Multiple gem names are allowed on the gem install command line.
+  This means you can do:
+  
+    gem install rake rails needle postgres-pr pimki
+  
+  (Ok, you get the idea)
+* Multiple authors my be specified in a Gem spec.
+* Switched to using setup.rb (rather than a custom install script) for
+  the installation of RubyGems itself.  If you have installed RubyGems
+  before, double check the installation instructions and make sure you
+  use setup.rb instead of install.rb.
+* Ryan Davis has provided a patch so you can use an env variable
+  (GEM_SKIP), to tell loadpath_manager not to load gems of those
+  names.  This was useful for him while testing libs that he had in
+  development.
+
+=== 0.8.1 / 2009-09-14
+
+* Quick release to capture some bug fixes.
+
+=== 0.8.0 / 2009-09-12
+
+* Remove need for library stubs.  Set the RUBYOPT environment variable to
+  include "rrubygems", and a normal require will find gem files.  Continue to
+  use 'require_gem gem_name, version' to specify gem versions.
+* Deprecated "test_suite_file" gemspec attribute in favor of "test_files" array.
+* Generates rdoc by default on installs.
+* Adopted tar/gzip file format, thanks to Mauricio Fernandez.
+* "gem rdoc" allows generation of rdoc after gem installation (will add a "gem
+  test"
+* Application stubs can now accept an optional parameter of _VERSION_ that will
+  run an arbitrary version of the application requested.
+* Various bug fixes
+* Various platform-independency improvements
+* "gem spec --all" displays spec info for all installed version of a given gem.
+* Dynamic caching of sources
+* Support for user-definable sources on the command line (thanks Assaph Mehr)
+* More intelligent support for platform-dependent gems.  Use Platform::CURRENT
+  when building a gem to set its platform to the one you're building on.
+  Installation displays a choice of platform-dependent gems, allowing the user
+  to pick.
+* Added "gem unpack" for "unpacking" a gem to the current directory
+
+=== 0.7.0 / 2004-07-09
+
+See ChangeLog
+
+=== 0.6.0 / 2004-06-08
+
+* Collapse output of --search and --list (and gem_server) operations so that
+  each gem is listed only once, with each of its versions listed on the same
+  line.
+* bin/gem: new --upgrade-all option allows one to upgrade every installed gem
+* new #required_ruby_version attribute added to gem specification for
+  specifying a dependency on which version of ruby the gem needs.  Format it
+  accepts is the same as the Gem::Version::Requirement format:
+  
+    spec.required_ruby_version = "> 1.8.0"
+* --install-stub defaults to true, so library stubs are created
+
+=== 0.5.0 / 2004-06-06
+
+* Jim added the ability to specify version constraints to avoid API
+  incompatibilities.  This has been the subject of much debate for the past
+  couple of months, with many ideas and code contributed by Eivind Eklund and
+  Mauricio Fernandez.  The following set of assertions shows how it works:
+  
+    assert_inadequate("1.3", "~> 1.4")
+    assert_adequate(  "1.4", "~> 1.4")
+    assert_adequate(  "1.5", "~> 1.4")
+    assert_inadequate("2.0", "~> 1.4") # This one is key--the new operator
+				       # disallows major version number
+				       # differences.
+* Group gem search output when multiple versions exist for a given gem:
+  
+    activerecord (0.7.8, 0.7.7, 0.7.6, 0.7.5)
+      Implements the ActiveRecord pattern for ORM.
+* Add arbitrary RDoc-able files via gemspec (not just Ruby source files) for
+  people who have, for example, README.rdoc in their distributions.  Add to
+  gemspec via: spec.extra_rdoc_files = ["list", "of", "files"].  Ruby files are
+  automatically included.
+* Some small bug fixes
+
+=== 0.4.0 / 2004-05-31
+
+* Minor bug fixes including Windows compatability issues
+
+=== 0.3.0 / 2004-04-30
+
+* Cleanup of command-line arguments and handling.  Most commands accept a
+  --local or --remote modifier.
+* Creation of Application Gems (packages that include executable programs).
+  See http://rubygems.rubyforge.org/wiki/wiki.pl?DeveloperGuide for information
+  on how to use it.
+* Basic functionality for installing binary gems from source (:extensions
+  property of gem specification holds an array of paths to extconf.rb files to
+  be used for compilation)
+* Install library "stub" allowing a normal 'require' to work (which then does
+  the rubygems require and 'require_gem'
+* --run-tests runs the test suite specified by the "test_suite_file" property
+  of a gem specification
+* HTTP Proxy support works.  Rewrite of HTTP code.
+* Unit and functional tests added (see Rakefile).
+* Prompt before remote-installing dependencies during gem installation.
+* Config file for storing preferences for 'gem' command usage.
+* Generally improved error messages (still more work to do)
+* Rearranged gem directory structure for cleanliness.
+
+=== 0.2.0 / 2004-03-14
+
+* Initial public release
+

Added: MacRuby/trunk/test/libs/rubygems/LICENSE.txt
===================================================================
--- MacRuby/trunk/test/libs/rubygems/LICENSE.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/LICENSE.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,53 @@
+RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim
+Weirich and others.  You can redistribute it and/or modify it under
+either the terms of the GPL (see the GPL.txt file), or the conditions
+below:
+
+  1. You may make and give away verbatim copies of the source form of the
+     software without restriction, provided that you duplicate all of the
+     original copyright notices and associated disclaimers.
+
+  2. You may modify your copy of the software in any way, provided that
+     you do at least ONE of the following:
+
+       a) place your modifications in the Public Domain or otherwise
+          make them Freely Available, such as by posting said
+	  modifications to Usenet or an equivalent medium, or by allowing
+	  the author to include your modifications in the software.
+
+       b) use the modified software only within your corporation or
+          organization.
+
+       c) rename any non-standard executables so the names do not conflict
+	  with standard executables, which must also be provided.
+
+       d) make other distribution arrangements with the author.
+
+  3. You may distribute the software in object code or executable
+     form, provided that you do at least ONE of the following:
+
+       a) distribute the executables and library files of the software,
+	  together with instructions (in the manual page or equivalent)
+	  on where to get the original distribution.
+
+       b) accompany the distribution with the machine-readable source of
+	  the software.
+
+       c) give non-standard executables non-standard names, with
+          instructions on where to get the original software distribution.
+
+       d) make other distribution arrangements with the author.
+
+  4. You may modify and include the part of the software into any other
+     software (possibly commercial).  
+
+  5. The scripts and library files supplied as input to or produced as 
+     output from the software do not automatically fall under the
+     copyright of the software, but belong to whomever generated them, 
+     and may be sold commercially, and may be aggregated with this
+     software.
+
+  6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+     IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+     PURPOSE.

Added: MacRuby/trunk/test/libs/rubygems/Manifest.txt
===================================================================
--- MacRuby/trunk/test/libs/rubygems/Manifest.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/Manifest.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,181 @@
+.autotest
+.document
+ChangeLog
+GPL.txt
+History.txt
+LICENSE.txt
+Manifest.txt
+README
+Rakefile
+bin/gem
+bin/update_rubygems
+cruise_config.rb
+lib/gauntlet_rubygems.rb
+lib/rbconfig/datadir.rb
+lib/rubygems.rb
+lib/rubygems/builder.rb
+lib/rubygems/command.rb
+lib/rubygems/command_manager.rb
+lib/rubygems/commands/build_command.rb
+lib/rubygems/commands/cert_command.rb
+lib/rubygems/commands/check_command.rb
+lib/rubygems/commands/cleanup_command.rb
+lib/rubygems/commands/contents_command.rb
+lib/rubygems/commands/dependency_command.rb
+lib/rubygems/commands/environment_command.rb
+lib/rubygems/commands/fetch_command.rb
+lib/rubygems/commands/generate_index_command.rb
+lib/rubygems/commands/help_command.rb
+lib/rubygems/commands/install_command.rb
+lib/rubygems/commands/list_command.rb
+lib/rubygems/commands/lock_command.rb
+lib/rubygems/commands/mirror_command.rb
+lib/rubygems/commands/outdated_command.rb
+lib/rubygems/commands/pristine_command.rb
+lib/rubygems/commands/query_command.rb
+lib/rubygems/commands/rdoc_command.rb
+lib/rubygems/commands/search_command.rb
+lib/rubygems/commands/server_command.rb
+lib/rubygems/commands/setup_command.rb
+lib/rubygems/commands/sources_command.rb
+lib/rubygems/commands/specification_command.rb
+lib/rubygems/commands/stale_command.rb
+lib/rubygems/commands/uninstall_command.rb
+lib/rubygems/commands/unpack_command.rb
+lib/rubygems/commands/update_command.rb
+lib/rubygems/commands/which_command.rb
+lib/rubygems/config_file.rb
+lib/rubygems/custom_require.rb
+lib/rubygems/defaults.rb
+lib/rubygems/dependency.rb
+lib/rubygems/dependency_installer.rb
+lib/rubygems/dependency_list.rb
+lib/rubygems/doc_manager.rb
+lib/rubygems/exceptions.rb
+lib/rubygems/ext.rb
+lib/rubygems/ext/builder.rb
+lib/rubygems/ext/configure_builder.rb
+lib/rubygems/ext/ext_conf_builder.rb
+lib/rubygems/ext/rake_builder.rb
+lib/rubygems/format.rb
+lib/rubygems/gem_openssl.rb
+lib/rubygems/gem_path_searcher.rb
+lib/rubygems/gem_runner.rb
+lib/rubygems/indexer.rb
+lib/rubygems/install_update_options.rb
+lib/rubygems/installer.rb
+lib/rubygems/local_remote_options.rb
+lib/rubygems/old_format.rb
+lib/rubygems/package.rb
+lib/rubygems/package/f_sync_dir.rb
+lib/rubygems/package/tar_header.rb
+lib/rubygems/package/tar_input.rb
+lib/rubygems/package/tar_output.rb
+lib/rubygems/package/tar_reader.rb
+lib/rubygems/package/tar_reader/entry.rb
+lib/rubygems/package/tar_writer.rb
+lib/rubygems/package_task.rb
+lib/rubygems/platform.rb
+lib/rubygems/remote_fetcher.rb
+lib/rubygems/require_paths_builder.rb
+lib/rubygems/requirement.rb
+lib/rubygems/security.rb
+lib/rubygems/server.rb
+lib/rubygems/source_index.rb
+lib/rubygems/source_info_cache.rb
+lib/rubygems/source_info_cache_entry.rb
+lib/rubygems/spec_fetcher.rb
+lib/rubygems/specification.rb
+lib/rubygems/test_utilities.rb
+lib/rubygems/text.rb
+lib/rubygems/timer.rb
+lib/rubygems/uninstaller.rb
+lib/rubygems/user_interaction.rb
+lib/rubygems/validator.rb
+lib/rubygems/version.rb
+lib/rubygems/version_option.rb
+lib/ubygems.rb
+pkgs/sources/lib/sources.rb
+pkgs/sources/sources.gemspec
+setup.rb
+test/bogussources.rb
+test/data/gem-private_key.pem
+test/data/gem-public_cert.pem
+test/fake_certlib/openssl.rb
+test/foo/discover.rb
+test/functional.rb
+test/gem_installer_test_case.rb
+test/gem_package_tar_test_case.rb
+test/gemutilities.rb
+test/insure_session.rb
+test/mockgemui.rb
+test/private_key.pem
+test/public_cert.pem
+test/rubygems_plugin.rb
+test/simple_gem.rb
+test/test_config.rb
+test/test_gem.rb
+test/test_gem_builder.rb
+test/test_gem_command.rb
+test/test_gem_command_manager.rb
+test/test_gem_commands_build_command.rb
+test/test_gem_commands_cert_command.rb
+test/test_gem_commands_check_command.rb
+test/test_gem_commands_contents_command.rb
+test/test_gem_commands_dependency_command.rb
+test/test_gem_commands_environment_command.rb
+test/test_gem_commands_fetch_command.rb
+test/test_gem_commands_generate_index_command.rb
+test/test_gem_commands_install_command.rb
+test/test_gem_commands_list_command.rb
+test/test_gem_commands_lock_command.rb
+test/test_gem_commands_mirror_command.rb
+test/test_gem_commands_outdated_command.rb
+test/test_gem_commands_pristine_command.rb
+test/test_gem_commands_query_command.rb
+test/test_gem_commands_server_command.rb
+test/test_gem_commands_sources_command.rb
+test/test_gem_commands_specification_command.rb
+test/test_gem_commands_stale_command.rb
+test/test_gem_commands_uninstall_command.rb
+test/test_gem_commands_unpack_command.rb
+test/test_gem_commands_update_command.rb
+test/test_gem_config_file.rb
+test/test_gem_dependency.rb
+test/test_gem_dependency_installer.rb
+test/test_gem_dependency_list.rb
+test/test_gem_doc_manager.rb
+test/test_gem_ext_configure_builder.rb
+test/test_gem_ext_ext_conf_builder.rb
+test/test_gem_ext_rake_builder.rb
+test/test_gem_format.rb
+test/test_gem_gem_path_searcher.rb
+test/test_gem_gem_runner.rb
+test/test_gem_indexer.rb
+test/test_gem_install_update_options.rb
+test/test_gem_installer.rb
+test/test_gem_local_remote_options.rb
+test/test_gem_package_tar_header.rb
+test/test_gem_package_tar_input.rb
+test/test_gem_package_tar_output.rb
+test/test_gem_package_tar_reader.rb
+test/test_gem_package_tar_reader_entry.rb
+test/test_gem_package_tar_writer.rb
+test/test_gem_package_task.rb
+test/test_gem_platform.rb
+test/test_gem_remote_fetcher.rb
+test/test_gem_requirement.rb
+test/test_gem_server.rb
+test/test_gem_source_index.rb
+test/test_gem_source_info_cache.rb
+test/test_gem_source_info_cache_entry.rb
+test/test_gem_spec_fetcher.rb
+test/test_gem_specification.rb
+test/test_gem_stream_ui.rb
+test/test_gem_uninstaller.rb
+test/test_gem_validator.rb
+test/test_gem_version.rb
+test/test_gem_version_option.rb
+test/test_kernel.rb
+util/CL2notes
+util/gem_prelude.rb.template

Added: MacRuby/trunk/test/libs/rubygems/README
===================================================================
--- MacRuby/trunk/test/libs/rubygems/README	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/README	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,40 @@
+= RubyGems
+
+* http://rubygems.rubyforge.org/
+* http://rubyforge.org/projects/rubygems
+* http://rubygems.org/
+
+== DESCRIPTION
+
+RubyGems is a package management framework for Ruby.
+
+This gem is an update for the RubyGems software. You must have an
+installation of RubyGems before this update can be applied.
+
+See Gem for information on RubyGems (or `ri Gem`)
+
+To upgrade to the latest RubyGems, run:
+
+  $ gem update --system  # you might need to be an administrator or root
+
+NOTE:  RubyGems 1.1 and 1.2 have problems upgrading when there is no
+rubygems-update installed.  You will need to use the following instructions
+if you see "Nothing to update".
+
+If you have an older version of RubyGems installed, then you can still
+do it in two steps:
+
+  $ gem install rubygems-update  # again, might need to be admin/root
+  $ update_rubygems              # ... here too
+
+If you don't have any RubyGems install, there is still the pre-gem approach to
+getting software, doing it manually:
+
+1. Download from: http://rubyforge.org/frs/?group_id=126
+2. Unpack into a directory and cd there
+3. Install with: ruby setup.rb  # you may need admin/root privilege
+
+For more details and other options, see:
+
+  ruby setup.rb --help
+

Added: MacRuby/trunk/test/libs/rubygems/Rakefile
===================================================================
--- MacRuby/trunk/test/libs/rubygems/Rakefile	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/Rakefile	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,183 @@
+# -*- ruby -*-
+
+$:.unshift 'lib'
+
+require 'rubygems'
+require 'rubygems/package_task'
+
+require 'hoe'
+
+Hoe.plugin :minitest
+
+hoe = Hoe.spec 'rubygems-update' do
+  self.rubyforge_name = 'rubygems'
+  self.author         = ['Jim Weirich', 'Chad Fowler', 'Eric Hodel']
+  self.email          = %w[rubygems-developers at rubyforge.org]
+  self.readme_file    = 'README'
+  self.need_zip       = false
+  self.need_tar       = false
+
+  spec_extras[:required_ruby_version] = Gem::Requirement.new '> 1.8.3'
+  spec_extras[:executables]           = ['update_rubygems']
+
+  clean_globs.push('**/debug.log',
+                   '*.out',
+                   '.config',
+                   'data__',
+                   'html',
+                   'logs',
+                   'pkgs/sources/sources*.gem',
+                   'scripts/*.hieraki',
+                   'util/gem_prelude.rb')
+
+  extra_dev_deps << ['builder', '~> 2.1']
+  extra_dev_deps << ['hoe-seattlerb', '~> 1.2']
+  extra_dev_deps << ['minitest', '~> 1.4']
+  extra_dev_deps << ['session', '~> 2.4']
+
+  spec_extras['rdoc_options'] = proc do |rdoc_options|
+    rdoc_options << "--title=RubyGems #{self.version} Documentation"
+  end
+end
+
+desc "Run just the functional tests"
+Rake::TestTask.new(:test_functional) do |t|
+  t.test_files = FileList['test/functional*.rb']
+  t.warning = true
+end
+
+# --------------------------------------------------------------------
+# Creating a release
+
+task :release => [:clobber, :sanity_check, :test_functional,
+                  :test, :package, :tag]
+
+task :release_to_rubyforge do
+  files = Dir["rubygems-update*.gem"]
+  rf.add_file rubyforge_name, name, version, files.first
+end
+
+pkg_dir_path = "pkg/rubygems-update-#{hoe.version}"
+task pkg_dir_path do
+  mv pkg_dir_path, "pkg/rubygems-#{hoe.version}"
+end
+
+task :package => [pkg_dir_path, :sanity_check] do
+  Dir.chdir 'pkg' do
+    sh "tar -czf rubygems-#{hoe.version}.tgz rubygems-#{hoe.version}"
+    sh "zip -q -r rubygems-#{hoe.version}.zip rubygems-#{hoe.version}"
+  end
+end
+
+task :sanity_check do
+  abort "svn status dirty. commit or revert them" unless `svn st`.empty?
+end
+
+task :tag => [:sanity_check] do
+  reltag = "REL_#{PKG_VERSION.gsub(/\./, '_')}"
+  svn_url = "svn+ssh://rubyforge.org/var/svn/rubygems"
+  sh %{svn copy #{svn_url}/trunk #{svn_url}/tags/#{reltag}}
+end
+
+# Misc Tasks ---------------------------------------------------------
+
+desc "build util/gem_prelude.rb from the template and defaults.rb"
+file 'util/gem_prelude.rb' =>
+     %w[util/gem_prelude.rb.template lib/rubygems/defaults.rb Rakefile] do
+  gem_prelude = File.read 'util/gem_prelude.rb.template'
+  defaults = File.read 'lib/rubygems/defaults.rb'
+
+  raise 'template error' unless defaults.sub!(/^module Gem\n/, '')
+  raise 'template error' unless defaults.sub!(/^end\n/, '')
+
+  defaults[0, 0] = "  # begin rubygems/defaults\n"
+  defaults << "  # end rubygems/defaults\n"
+  defaults.gsub!(/^/, '  ')
+
+  raise 'template error' unless
+    gem_prelude.sub!(/^# WARN\n/,
+                     "# THIS FILE WAS AUTOGENERATED, DO NOT EDIT\n")
+  raise 'template error' unless
+    gem_prelude.sub!(/^    # INCLUDE rubygems\/defaults\n/, defaults)
+
+  rm_f 'util/gem_prelude.rb'
+
+  open 'util/gem_prelude.rb', 'w' do |io|
+    io.write gem_prelude
+    io.chmod 0444
+  end
+end
+
+# These tasks expect to have the following directory structure:
+#
+#   git/git.rubini.us/code # Rubinius git HEAD checkout
+#   svn/ruby/trunk         # ruby subversion HEAD checkout
+#   svn/rubygems/trunk     # RubyGems subversion HEAD checkout
+#
+# If you don't have this directory structure, set RUBY_PATH and/or
+# RUBINIUS_PATH.
+
+def rsync_with dir
+  rsync_options = "-avP --exclude '*svn*' --exclude '*swp' --exclude '*rbc'" +
+    "--exclude '*.rej' --exclude '*.orig' --exclude 'lib/rubygems/defaults/*'"
+  sh "rsync #{rsync_options} bin/gem             #{dir}/bin/gem"
+  sh "rsync #{rsync_options} lib/                #{dir}/lib"
+  sh "rsync #{rsync_options} test/               #{dir}/test/rubygems"
+  sh "rsync #{rsync_options} util/gem_prelude.rb #{dir}/gem_prelude.rb"
+end
+
+def diff_with dir
+  diff_options = "-urpN --exclude '*svn*' --exclude '*swp' --exclude '*rbc'"
+  sh "diff #{diff_options} bin/gem             #{dir}/bin/gem;         true"
+  sh "diff #{diff_options} lib/ubygems.rb      #{dir}/lib/ubygems.rb;  true"
+  sh "diff #{diff_options} lib/rubygems.rb     #{dir}/lib/rubygems.rb; true"
+  sh "diff #{diff_options} lib/rubygems        #{dir}/lib/rubygems;    true"
+  sh "diff #{diff_options} lib/rbconfig        #{dir}/lib/rbconfig;    true"
+  sh "diff #{diff_options} test                #{dir}/test/rubygems;   true"
+  sh "diff #{diff_options} util/gem_prelude.rb #{dir}/gem_prelude.rb;  true"
+end
+
+rubinius_dir = ENV['RUBINIUS_PATH'] || '../../../git/git.rubini.us/code'
+ruby_dir     = ENV['RUBY_PATH']     || '../../ruby/trunk'
+
+desc "Updates Ruby HEAD with the currently checked-out copy of RubyGems."
+task :update_ruby     => 'util/gem_prelude.rb' do
+  rsync_with ruby_dir
+end
+
+desc "Updates Rubinius HEAD with the currently checked-out copy of RubyGems."
+task :update_rubinius => 'util/gem_prelude.rb' do
+  rsync_with rubinius_dir
+end
+
+desc "Diffs Ruby HEAD with the currently checked-out copy of RubyGems."
+task :diff_ruby       => 'util/gem_prelude.rb' do
+  diff_with ruby_dir
+end
+
+desc "Diffs Rubinius HEAD with the currently checked-out copy of RubyGems."
+task :diff_rubinius   => 'util/gem_prelude.rb' do
+  diff_with rubinius_dir
+end
+
+desc "Get coverage for a specific test, no system RubyGems."
+task "rcov:for", [:test] do |task, args|
+  mgem  = Gem.source_index.find_name("minitest").first rescue nil
+  rgem  = Gem.source_index.find_name(/rcov/).first
+  libs  = rgem.require_paths.map { |p| File.join rgem.full_gem_path, p }
+  rcov  = File.join rgem.full_gem_path, rgem.bindir, rgem.default_executable
+
+  if mgem
+    libs << mgem.require_paths.map { |p| File.join mgem.full_gem_path, p }
+  end
+
+  libs << "lib:test"
+
+  flags  = []
+  flags << "-I" << libs.flatten.join(":")
+
+  rflags  = []
+  rflags << "-i" << "lib/rubygems"
+
+  ruby "#{flags.join ' '} #{rcov} #{rflags.join ' '} #{args[:test]}"
+end

Added: MacRuby/trunk/test/libs/rubygems/bin/gem
===================================================================
--- MacRuby/trunk/test/libs/rubygems/bin/gem	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/bin/gem	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+require 'rubygems/gem_runner'
+require 'rubygems/exceptions'
+
+required_version = Gem::Requirement.new ">= 1.8.6"
+
+unless required_version.satisfied_by? Gem.ruby_version then
+  abort "Expected Ruby Version #{required_version}, is #{Gem.ruby_version}"
+end
+
+args = ARGV.clone
+
+begin
+  Gem::GemRunner.new.run args
+rescue Gem::SystemExitException => e
+  exit e.exit_code
+end
+


Property changes on: MacRuby/trunk/test/libs/rubygems/bin/gem
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/bin/update_rubygems
===================================================================
--- MacRuby/trunk/test/libs/rubygems/bin/update_rubygems	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/bin/update_rubygems	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,38 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+
+if ARGV.include? '-h' or ARGV.include? '--help' then
+  puts "rubygems_update [options]"
+  puts
+  puts "This will install the latest version of RubyGems."
+  puts
+  puts "\t--version=X.Y\tUpdate rubygems from the X.Y version."
+  exit
+end
+
+unless ARGV.grep(/--version=([\d\.]*)/).empty? then
+  exec "#{Gem.ruby} -S #{$PROGRAM_NAME} _#{$1}_"
+end
+
+update_dir = $LOAD_PATH.find { |fn| fn =~ /rubygems-update/ }
+
+if update_dir.nil?
+  puts "Error: Cannot find RubyGems Update Path!"
+  puts
+  puts "RubyGems has already been updated."
+  puts "The rubygems-update gem may now be uninstalled."
+  puts "E.g.    gem uninstall rubygems-update"
+else
+  update_dir = File.dirname(update_dir)
+  Dir.chdir update_dir
+  update_dir =~ /([0-9.]*)$/
+  RGVERSION = $1
+  puts "Installing RubyGems #{RGVERSION}"
+  system "#{Gem.ruby} setup.rb #{ARGV.join(' ')}"
+end


Property changes on: MacRuby/trunk/test/libs/rubygems/bin/update_rubygems
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/cruise_config.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/cruise_config.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/cruise_config.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,23 @@
+# Project-specific configuration for CruiseControl.rb
+require 'socket'
+
+Project.configure do |project|
+  
+  # Send email notifications about broken and fixed builds to email1 at your.site, email2 at your.site (default: send to nobody)
+  project.email_notifier.emails = ['rubygems-developers at rubyforge.org'] if Socket.gethostname =~ /ci.pivotallabs.com/
+
+  # Set email 'from' field to john at doe.com:
+  project.email_notifier.from = 'devnull+rubygems-ci at pivotallabs.com'
+
+  # Build the project by invoking rake task 'custom'
+  # project.rake_task = 'custom'
+
+  # Build the project by invoking shell script "build_my_app.sh". Keep in mind that when the script is invoked,
+  # current working directory is <em>[cruise&nbsp;data]</em>/projects/your_project/work, so if you do not keep build_my_app.sh
+  # in version control, it should be '../build_my_app.sh' instead
+  project.build_command = 'rake check_extra_deps default'
+
+  # Ping Subversion for new revisions every 5 minutes (default: 30 seconds)
+  project.scheduler.polling_interval = 5.minutes
+
+end

Added: MacRuby/trunk/test/libs/rubygems/lib/gauntlet_rubygems.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/gauntlet_rubygems.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/gauntlet_rubygems.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,50 @@
+require 'rubygems'
+require 'gauntlet'
+
+##
+# GemGauntlet validates all current gems. Currently these packages are
+# borked:
+#
+# Asami-0.04           : No such file or directory - bin/Asami.rb
+# ObjectGraph-1.0.1    : No such file or directory - bin/objectgraph
+# evil-ruby-0.1.0      : authors must be Array of Strings
+# fresh_cookies-1.0.0  : authors must be Array of Strings
+# plugems_deploy-0.2.0 : authors must be Array of Strings
+# pmsrb-0.2.0          : authors must be Array of Strings
+# pqa-1.6              : authors must be Array of Strings
+# rant-0.5.7           : authors must be Array of Strings
+# rvsh-0.4.5           : No such file or directory - bin/rvsh
+# xen-0.1.2.1          : authors must be Array of Strings
+
+class GemGauntlet < Gauntlet
+  def run(name)
+    warn name
+
+    spec = begin
+             Gem::Specification.load 'gemspec'
+           rescue SyntaxError
+             Gem::Specification.from_yaml File.read('gemspec')
+           end
+    spec.validate
+
+    self.data[name] = false
+    self.dirty = true
+  rescue SystemCallError, Gem::InvalidSpecificationException => e
+    self.data[name] = e.message
+    self.dirty = true
+  end
+
+  def should_skip?(name)
+    self.data[name] == false
+  end
+
+  def report
+    self.data.sort.reject { |k,v| !v }.each do |k,v|
+      puts "%-21s: %s" % [k, v]
+    end
+  end
+end
+
+gauntlet = GemGauntlet.new
+gauntlet.run_the_gauntlet ARGV.shift
+gauntlet.report

Added: MacRuby/trunk/test/libs/rubygems/lib/rbconfig/datadir.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rbconfig/datadir.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rbconfig/datadir.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,20 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+module RbConfig
+
+  ##
+  # Return the path to the data directory associated with the given package
+  # name.  Normally this is just
+  # "#{RbConfig::CONFIG['datadir']}/#{package_name}", but may be modified by
+  # packages like RubyGems to handle versioned data directories.
+
+  def self.datadir(package_name)
+    File.join(CONFIG['datadir'], package_name)
+  end unless RbConfig.respond_to?(:datadir)
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,92 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+##
+# The Builder class processes RubyGem specification files
+# to produce a .gem file.
+
+class Gem::Builder
+
+  include Gem::UserInteraction
+
+  ##
+  # Constructs a builder instance for the provided specification
+  #
+  # spec:: [Gem::Specification] The specification instance
+
+  def initialize(spec)
+    require "yaml"
+    require "rubygems/package"
+    require "rubygems/security"
+
+    @spec = spec
+  end
+
+  ##
+  # Builds the gem from the specification.  Returns the name of the file
+  # written.
+
+  def build
+    @spec.mark_version
+    @spec.validate
+    @signer = sign
+    write_package
+    say success if Gem.configuration.verbose
+    @spec.file_name
+  end
+
+  def success
+    <<-EOM
+  Successfully built RubyGem
+  Name: #{@spec.name}
+  Version: #{@spec.version}
+  File: #{@spec.file_name}
+EOM
+  end
+
+  private
+
+  ##
+  # If the signing key was specified, then load the file, and swap to the
+  # public key (TODO: we should probably just omit the signing key in favor of
+  # the signing certificate, but that's for the future, also the signature
+  # algorithm should be configurable)
+
+  def sign
+    signer = nil
+
+    if @spec.respond_to?(:signing_key) and @spec.signing_key then
+      signer = Gem::Security::Signer.new @spec.signing_key, @spec.cert_chain
+      @spec.signing_key = nil
+      @spec.cert_chain = signer.cert_chain.map { |cert| cert.to_s }
+    end
+
+    signer
+  end
+
+  def write_package
+    open @spec.file_name, 'wb' do |gem_io|
+      Gem::Package.open gem_io, 'w', @signer do |pkg|
+        pkg.metadata = @spec.to_yaml
+
+        @spec.files.each do |file|
+          next if File.directory? file
+          next if file == @spec.file_name # Don't add gem onto itself
+
+          stat = File.stat file
+          mode = stat.mode & 0777
+          size = stat.size
+
+          pkg.add_file_simple file, mode, size do |tar_io|
+            tar_io.write open(file, "rb") { |f| f.read }
+          end
+        end
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,511 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'optparse'
+require 'rubygems/user_interaction'
+
+##
+# Base class for all Gem commands.  When creating a new gem command, define
+# #new, #execute, #arguments, #defaults_str, #description and #usage
+# (as appropriate).  See the above mentioned methods for details.
+#
+# A very good example to look at is Gem::Commands::ContentsCommand
+
+class Gem::Command
+
+  include Gem::UserInteraction
+
+  ##
+  # The name of the command.
+
+  attr_reader :command
+
+  ##
+  # The options for the command.
+
+  attr_reader :options
+
+  ##
+  # The default options for the command.
+
+  attr_accessor :defaults
+
+  ##
+  # The name of the command for command-line invocation.
+
+  attr_accessor :program_name
+
+  ##
+  # A short description of the command.
+
+  attr_accessor :summary
+
+  ##
+  # Arguments used when building gems
+
+  def self.build_args
+    @build_args ||= []
+  end
+  
+  def self.build_args=(value)
+    @build_args = value
+  end
+
+  def self.common_options
+    @common_options ||= []
+  end
+
+  def self.add_common_option(*args, &handler)
+    Gem::Command.common_options << [args, handler]
+  end
+
+  def self.extra_args
+    @extra_args ||= []
+  end
+
+  def self.extra_args=(value)
+    case value
+    when Array
+      @extra_args = value
+    when String
+      @extra_args = value.split
+    end
+  end
+
+  ##
+  # Return an array of extra arguments for the command.  The extra arguments
+  # come from the gem configuration file read at program startup.
+
+  def self.specific_extra_args(cmd)
+    specific_extra_args_hash[cmd]
+  end
+
+  ##
+  # Add a list of extra arguments for the given command.  +args+ may be an
+  # array or a string to be split on white space.
+
+  def self.add_specific_extra_args(cmd,args)
+    args = args.split(/\s+/) if args.kind_of? String
+    specific_extra_args_hash[cmd] = args
+  end
+
+  ##
+  # Accessor for the specific extra args hash (self initializing).
+
+  def self.specific_extra_args_hash
+    @specific_extra_args_hash ||= Hash.new do |h,k|
+      h[k] = Array.new
+    end
+  end
+
+  ##
+  # Initializes a generic gem command named +command+.  +summary+ is a short
+  # description displayed in `gem help commands`.  +defaults+ are the default
+  # options.  Defaults should be mirrored in #defaults_str, unless there are
+  # none.
+  #
+  # When defining a new command subclass, use add_option to add command-line
+  # switches.
+  #
+  # Unhandled arguments (gem names, files, etc.) are left in
+  # <tt>options[:args]</tt>.
+
+  def initialize(command, summary=nil, defaults={})
+    @command = command
+    @summary = summary
+    @program_name = "gem #{command}"
+    @defaults = defaults
+    @options = defaults.dup
+    @option_groups = Hash.new { |h,k| h[k] = [] }
+    @parser = nil
+    @when_invoked = nil
+  end
+
+  ##
+  # True if +long+ begins with the characters from +short+.
+
+  def begins?(long, short)
+    return false if short.nil?
+    long[0, short.length] == short
+  end
+
+  ##
+  # Override to provide command handling.
+  #
+  # #options will be filled in with your parsed options, unparsed options will
+  # be left in <tt>options[:args]</tt>.
+  #
+  # See also: #get_all_gem_names, #get_one_gem_name,
+  # #get_one_optional_argument
+
+  def execute
+    raise Gem::Exception, "generic command has no actions"
+  end
+
+  ##
+  # Get all gem names from the command line.
+
+  def get_all_gem_names
+    args = options[:args]
+
+    if args.nil? or args.empty? then
+      raise Gem::CommandLineError,
+            "Please specify at least one gem name (e.g. gem build GEMNAME)"
+    end
+
+    gem_names = args.select { |arg| arg !~ /^-/ }
+  end
+
+  ##
+  # Get the single gem name from the command line.  Fail if there is no gem
+  # name or if there is more than one gem name given.
+
+  def get_one_gem_name
+    args = options[:args]
+
+    if args.nil? or args.empty? then
+      raise Gem::CommandLineError,
+            "Please specify a gem name on the command line (e.g. gem build GEMNAME)"
+    end
+
+    if args.size > 1 then
+      raise Gem::CommandLineError,
+            "Too many gem names (#{args.join(', ')}); please specify only one"
+    end
+
+    args.first
+  end
+
+  ##
+  # Get a single optional argument from the command line.  If more than one
+  # argument is given, return only the first. Return nil if none are given.
+
+  def get_one_optional_argument
+    args = options[:args] || []
+    args.first
+  end
+
+  ##
+  # Override to provide details of the arguments a command takes.  It should
+  # return a left-justified string, one argument per line.
+  #
+  # For example:
+  #
+  #   def usage
+  #     "#{program_name} FILE [FILE ...]"
+  #   end
+  #   
+  #   def arguments
+  #     "FILE          name of file to find"
+  #   end
+
+  def arguments
+    ""
+  end
+
+  ##
+  # Override to display the default values of the command options. (similar to
+  # +arguments+, but displays the default values).
+  #
+  # For example:
+  #
+  #   def defaults_str
+  #     --no-gems-first --no-all
+  #   end
+
+  def defaults_str
+    ""
+  end
+
+  ##
+  # Override to display a longer description of what this command does.
+
+  def description
+    nil
+  end
+
+  ##
+  # Override to display the usage for an individual gem command.
+  #
+  # The text "[options]" is automatically appended to the usage text.
+
+  def usage
+    program_name
+  end
+
+  ##
+  # Display the help message for the command.
+
+  def show_help
+    parser.program_name = usage
+    say parser
+  end
+
+  ##
+  # Invoke the command with the given list of arguments.
+
+  def invoke(*args)
+    handle_options(args)
+    if options[:help]
+      show_help
+    elsif @when_invoked
+      @when_invoked.call(options)
+    else
+      execute
+    end
+  end
+
+  ##
+  # Call the given block when invoked.
+  #
+  # Normal command invocations just executes the +execute+ method of the
+  # command.  Specifying an invocation block allows the test methods to
+  # override the normal action of a command to determine that it has been
+  # invoked correctly.
+
+  def when_invoked(&block)
+    @when_invoked = block
+  end
+
+  ##
+  # Add a command-line option and handler to the command.
+  #
+  # See OptionParser#make_switch for an explanation of +opts+.
+  #
+  # +handler+ will be called with two values, the value of the argument and
+  # the options hash.
+  #
+  # If the first argument of add_option is a Symbol, it's used to group
+  # options in output.  See `gem help list` for an example.
+
+  def add_option(*opts, &handler) # :yields: value, options
+    group_name = Symbol === opts.first ? opts.shift : :options
+
+    @option_groups[group_name] << [opts, handler]
+  end
+
+  ##
+  # Remove previously defined command-line argument +name+.
+
+  def remove_option(name)
+    @option_groups.each do |_, option_list|
+      option_list.reject! { |args, _| args.any? { |x| x =~ /^#{name}/ } }
+    end
+  end
+
+  ##
+  # Merge a set of command options with the set of default options (without
+  # modifying the default option hash).
+
+  def merge_options(new_options)
+    @options = @defaults.clone
+    new_options.each do |k,v| @options[k] = v end
+  end
+
+  ##
+  # True if the command handles the given argument list.
+
+  def handles?(args)
+    begin
+      parser.parse!(args.dup)
+      return true
+    rescue
+      return false
+    end
+  end
+
+  ##
+  # Handle the given list of arguments by parsing them and recording the
+  # results.
+
+  def handle_options(args)
+    args = add_extra_args(args)
+    @options = @defaults.clone
+    parser.parse!(args)
+    @options[:args] = args
+  end
+
+  ##
+  # Adds extra args from ~/.gemrc
+
+  def add_extra_args(args)
+    result = []
+
+    s_extra = Gem::Command.specific_extra_args(@command)
+    extra = Gem::Command.extra_args + s_extra
+
+    until extra.empty? do
+      ex = []
+      ex << extra.shift
+      ex << extra.shift if extra.first.to_s =~ /^[^-]/
+      result << ex if handles?(ex)
+    end
+
+    result.flatten!
+    result.concat(args)
+    result
+  end
+
+  private
+
+  ##
+  # Create on demand parser.
+
+  def parser
+    create_option_parser if @parser.nil?
+    @parser
+  end
+
+  def create_option_parser
+    @parser = OptionParser.new
+
+    @parser.separator("")
+    regular_options = @option_groups.delete :options
+
+    configure_options "", regular_options
+
+    @option_groups.sort_by { |n,_| n.to_s }.each do |group_name, option_list|
+      configure_options group_name, option_list
+    end
+
+    configure_options "Common", Gem::Command.common_options
+
+    @parser.separator("")
+    unless arguments.empty?
+      @parser.separator("  Arguments:")
+      arguments.split(/\n/).each do |arg_desc|
+        @parser.separator("    #{arg_desc}")
+      end
+      @parser.separator("")
+    end
+
+    @parser.separator("  Summary:")
+    wrap(@summary, 80 - 4).split("\n").each do |line|
+      @parser.separator("    #{line.strip}")
+    end
+
+    if description then
+      formatted = description.split("\n\n").map do |chunk|
+        wrap(chunk, 80 - 4)
+      end.join("\n")
+
+      @parser.separator ""
+      @parser.separator "  Description:"
+      formatted.split("\n").each do |line|
+        @parser.separator "    #{line.rstrip}"
+      end
+    end
+
+    unless defaults_str.empty?
+      @parser.separator("")
+      @parser.separator("  Defaults:")
+      defaults_str.split(/\n/).each do |line|
+        @parser.separator("    #{line}")
+      end
+    end
+  end
+
+  def configure_options(header, option_list)
+    return if option_list.nil? or option_list.empty?
+
+    header = header.to_s.empty? ? '' : "#{header} "
+    @parser.separator "  #{header}Options:"
+
+    option_list.each do |args, handler|
+      dashes = args.select { |arg| arg =~ /^-/ }
+      @parser.on(*args) do |value|
+        handler.call(value, @options)
+      end
+    end
+
+    @parser.separator ''
+  end
+
+  ##
+  # Wraps +text+ to +width+
+
+  def wrap(text, width) # :doc:
+    text.gsub(/(.{1,#{width}})( +|$\n?)|(.{1,#{width}})/, "\\1\\3\n")
+  end
+
+  # ----------------------------------------------------------------
+  # Add the options common to all commands.
+
+  add_common_option('-h', '--help',
+                    'Get help on this command') do |value, options|
+    options[:help] = true
+  end
+
+  add_common_option('-V', '--[no-]verbose',
+                    'Set the verbose level of output') do |value, options|
+    # Set us to "really verbose" so the progress meter works
+    if Gem.configuration.verbose and value then
+      Gem.configuration.verbose = 1
+    else
+      Gem.configuration.verbose = value
+    end
+  end
+
+  add_common_option('-q', '--quiet', 'Silence commands') do |value, options|
+    Gem.configuration.verbose = false
+  end
+
+  # Backtrace and config-file are added so they show up in the help
+  # commands.  Both options are actually handled before the other
+  # options get parsed.
+
+  add_common_option('--config-file FILE',
+                    'Use this config file instead of default') do
+  end
+
+  add_common_option('--backtrace',
+                    'Show stack backtrace on errors') do
+  end
+
+  add_common_option('--debug',
+                    'Turn on Ruby debugging') do
+  end
+
+  # :stopdoc:
+
+  HELP = %{
+    RubyGems is a sophisticated package manager for Ruby.  This is a
+    basic help message containing pointers to more information.
+
+      Usage:
+        gem -h/--help
+        gem -v/--version
+        gem command [arguments...] [options...]
+
+      Examples:
+        gem install rake
+        gem list --local
+        gem build package.gemspec
+        gem help install
+
+      Further help:
+        gem help commands            list all 'gem' commands
+        gem help examples            show some examples of usage
+        gem help platforms           show information about platforms
+        gem help <COMMAND>           show help on COMMAND
+                                       (e.g. 'gem help install')
+        gem server                   present a web page at
+                                     http://localhost:8808/
+                                     with info about installed gems
+      Further information:
+        http://rubygems.rubyforge.org
+  }.gsub(/^    /, '')
+
+  # :startdoc:
+
+end
+
+##
+# This is where Commands will be placed in the namespace
+
+module Gem::Commands
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/command_manager.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/command_manager.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/command_manager.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,174 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'timeout'
+require 'rubygems/command'
+require 'rubygems/user_interaction'
+
+##
+# The command manager registers and installs all the individual sub-commands
+# supported by the gem command.
+#
+# Extra commands can be provided by writing a rubygems_plugin.rb
+# file in an installed gem.  You should register your command against the
+# Gem::CommandManager instance, like this:
+#
+#   # file rubygems_plugin.rb
+#   require 'rubygems/command_manager'
+#
+#   class Gem::Commands::EditCommand < Gem::Command
+#     # ...
+#   end
+#
+#   Gem::CommandManager.instance.register_command :edit
+#
+# See Gem::Command for instructions on writing gem commands.
+
+class Gem::CommandManager
+
+  include Gem::UserInteraction
+
+  ##
+  # Return the authoritative instance of the command manager.
+
+  def self.instance
+    @command_manager ||= new
+  end
+
+  ##
+  # Register all the subcommands supported by the gem command.
+
+  def initialize
+    @commands = {}
+    register_command :build
+    register_command :cert
+    register_command :check
+    register_command :cleanup
+    register_command :contents
+    register_command :dependency
+    register_command :environment
+    register_command :fetch
+    register_command :generate_index
+    register_command :help
+    register_command :install
+    register_command :list
+    register_command :lock
+    register_command :mirror
+    register_command :outdated
+    register_command :pristine
+    register_command :query
+    register_command :rdoc
+    register_command :search
+    register_command :server
+    register_command :sources
+    register_command :specification
+    register_command :stale
+    register_command :uninstall
+    register_command :unpack
+    register_command :update
+    register_command :which
+  end
+
+  ##
+  # Register the command object.
+
+  def register_command(command_obj)
+    @commands[command_obj] = false
+  end
+
+  ##
+  # Return the registered command from the command name.
+
+  def [](command_name)
+    command_name = command_name.intern
+    return nil if @commands[command_name].nil?
+    @commands[command_name] ||= load_and_instantiate(command_name)
+  end
+
+  ##
+  # Return a sorted list of all command names (as strings).
+
+  def command_names
+    @commands.keys.collect {|key| key.to_s}.sort
+  end
+
+  ##
+  # Run the config specified by +args+.
+
+  def run(args)
+    process_args(args)
+  rescue StandardError, Timeout::Error => ex
+    alert_error "While executing gem ... (#{ex.class})\n    #{ex.to_s}"
+    ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
+      Gem.configuration.backtrace
+    terminate_interaction(1)
+  rescue Interrupt
+    alert_error "Interrupted"
+    terminate_interaction(1)
+  end
+
+  def process_args(args)
+    args = args.to_str.split(/\s+/) if args.respond_to?(:to_str)
+    if args.size == 0
+      say Gem::Command::HELP
+      terminate_interaction(1)
+    end
+    case args[0]
+    when '-h', '--help'
+      say Gem::Command::HELP
+      terminate_interaction(0)
+    when '-v', '--version'
+      say Gem::RubyGemsVersion
+      terminate_interaction(0)
+    when /^-/
+      alert_error "Invalid option: #{args[0]}.  See 'gem --help'."
+      terminate_interaction(1)
+    else
+      cmd_name = args.shift.downcase
+      cmd = find_command(cmd_name)
+      cmd.invoke(*args)
+    end
+  end
+
+  def find_command(cmd_name)
+    possibilities = find_command_possibilities cmd_name
+    if possibilities.size > 1 then
+      raise "Ambiguous command #{cmd_name} matches [#{possibilities.join(', ')}]"
+    elsif possibilities.size < 1 then
+      raise "Unknown command #{cmd_name}"
+    end
+
+    self[possibilities.first]
+  end
+
+  def find_command_possibilities(cmd_name)
+    len = cmd_name.length
+
+    command_names.select { |n| cmd_name == n[0, len] }
+  end
+
+  private
+
+  def load_and_instantiate(command_name)
+    command_name = command_name.to_s
+    retried = false
+
+    begin
+      const_name = command_name.capitalize.gsub(/_(.)/) { $1.upcase }
+      Gem::Commands.const_get("#{const_name}Command").new
+    rescue NameError
+      if retried then
+        raise
+      else
+        retried = true
+        require "rubygems/commands/#{command_name}_command"
+        retry
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/build_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/build_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/build_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,53 @@
+require 'rubygems/command'
+require 'rubygems/builder'
+
+class Gem::Commands::BuildCommand < Gem::Command
+
+  def initialize
+    super('build', 'Build a gem from a gemspec')
+  end
+
+  def arguments # :nodoc:
+    "GEMSPEC_FILE  gemspec file name to build a gem for"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMSPEC_FILE"
+  end
+
+  def execute
+    gemspec = get_one_gem_name
+    if File.exist?(gemspec)
+      specs = load_gemspecs(gemspec)
+      specs.each do |spec|
+        Gem::Builder.new(spec).build
+      end
+    else
+      alert_error "Gemspec file not found: #{gemspec}"
+    end
+  end
+
+  def load_gemspecs(filename)
+    if yaml?(filename)
+      result = []
+      open(filename) do |f|
+        begin
+          while not f.eof? and spec = Gem::Specification.from_yaml(f)
+            result << spec
+          end
+        rescue Gem::EndOfYAMLException => e
+          # OK
+        end
+      end
+    else
+      result = [Gem::Specification.load(filename)]
+    end
+    result
+  end
+
+  def yaml?(filename)
+    line = open(filename) { |f| line = f.gets }
+    result = line =~ %r{!ruby/object:Gem::Specification}
+    result
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cert_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cert_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cert_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,86 @@
+require 'rubygems/command'
+require 'rubygems/security'
+
+class Gem::Commands::CertCommand < Gem::Command
+
+  def initialize
+    super 'cert', 'Manage RubyGems certificates and signing settings'
+
+    add_option('-a', '--add CERT',
+               'Add a trusted certificate.') do |value, options|
+      cert = OpenSSL::X509::Certificate.new(File.read(value))
+      Gem::Security.add_trusted_cert(cert)
+      say "Added '#{cert.subject.to_s}'"
+    end
+
+    add_option('-l', '--list',
+               'List trusted certificates.') do |value, options|
+      glob_str = File::join(Gem::Security::OPT[:trust_dir], '*.pem')
+      Dir::glob(glob_str) do |path|
+        begin
+          cert = OpenSSL::X509::Certificate.new(File.read(path))
+          # this could probably be formatted more gracefully
+          say cert.subject.to_s
+        rescue OpenSSL::X509::CertificateError
+          next
+        end
+      end
+    end
+
+    add_option('-r', '--remove STRING',
+               'Remove trusted certificates containing',
+               'STRING.') do |value, options|
+      trust_dir = Gem::Security::OPT[:trust_dir]
+      glob_str = File::join(trust_dir, '*.pem')
+
+      Dir::glob(glob_str) do |path|
+        begin
+          cert = OpenSSL::X509::Certificate.new(File.read(path))
+          if cert.subject.to_s.downcase.index(value)
+            say "Removed '#{cert.subject.to_s}'"
+            File.unlink(path)
+          end
+        rescue OpenSSL::X509::CertificateError
+          next
+        end
+      end
+    end
+
+    add_option('-b', '--build EMAIL_ADDR',
+               'Build private key and self-signed',
+               'certificate for EMAIL_ADDR.') do |value, options|
+      vals = Gem::Security.build_self_signed_cert(value)
+      File.chmod 0600, vals[:key_path]
+      say "Public Cert: #{vals[:cert_path]}"
+      say "Private Key: #{vals[:key_path]}"
+      say "Don't forget to move the key file to somewhere private..."
+    end
+
+    add_option('-C', '--certificate CERT',
+               'Certificate for --sign command.') do |value, options|
+      cert = OpenSSL::X509::Certificate.new(File.read(value))
+      Gem::Security::OPT[:issuer_cert] = cert
+    end
+
+    add_option('-K', '--private-key KEY',
+               'Private key for --sign command.') do |value, options|
+      key = OpenSSL::PKey::RSA.new(File.read(value))
+      Gem::Security::OPT[:issuer_key] = key
+    end
+
+    add_option('-s', '--sign NEWCERT',
+               'Sign a certificate with my key and',
+               'certificate.') do |value, options|
+      cert = OpenSSL::X509::Certificate.new(File.read(value))
+      my_cert = Gem::Security::OPT[:issuer_cert]
+      my_key = Gem::Security::OPT[:issuer_key]
+      cert = Gem::Security.sign_cert(cert, my_key, my_cert)
+      File.open(value, 'wb') { |file| file.write(cert.to_pem) }
+    end
+  end
+
+  def execute
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/check_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/check_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/check_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,80 @@
+require 'rubygems/command'
+require 'rubygems/version_option'
+require 'rubygems/validator'
+
+class Gem::Commands::CheckCommand < Gem::Command
+
+  include Gem::VersionOption
+
+  def initialize
+    super 'check', 'Check installed gems',
+          :verify => false, :alien => false
+
+    add_option(      '--verify FILE',
+               'Verify gem file against its internal',
+               'checksum') do |value, options|
+      options[:verify] = value
+    end
+
+    add_option('-a', '--alien', "Report 'unmanaged' or rogue files in the",
+               "gem repository") do |value, options|
+      options[:alien] = true
+    end
+
+    add_option('-v', '--verbose', "Spew more words") do |value, options|
+      options[:verbose] = true
+    end
+
+    add_option('-t', '--test', "Run unit tests for gem") do |value, options|
+      options[:test] = true
+    end
+
+    add_version_option 'run tests for'
+  end
+
+  def execute
+    if options[:test]
+      version = options[:version] || Gem::Requirement.default
+      dep = Gem::Dependency.new get_one_gem_name, version
+      gem_spec = Gem::SourceIndex.from_installed_gems.search(dep).first
+      Gem::Validator.new.unit_test(gem_spec)
+    end
+
+    if options[:alien]
+      say "Performing the 'alien' operation"
+      say
+      gems = get_all_gem_names rescue []
+      Gem::Validator.new.alien(gems).sort.each do |key, val|
+        unless val.empty? then
+          say "#{key} has #{val.size} problems"
+          val.each do |error_entry|
+            say "  #{error_entry.path}:"
+            say "    #{error_entry.problem}"
+          end
+        else
+          say "#{key} is error-free" if options[:verbose]
+        end
+        say
+      end
+    end
+
+    if options[:verify]
+      gem_name = options[:verify]
+      unless gem_name
+        alert_error "Must specify a .gem file with --verify NAME"
+        return
+      end
+      unless File.exist?(gem_name)
+        alert_error "Unknown file: #{gem_name}."
+        return
+      end
+      say "Verifying gem: '#{gem_name}'"
+      begin
+        Gem::Validator.new.verify_gem_file(gem_name)
+      rescue Exception => e
+        alert_error "#{gem_name} is invalid."
+      end
+    end
+  end
+
+end

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cleanup_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cleanup_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/cleanup_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,106 @@
+require 'rubygems/command'
+require 'rubygems/source_index'
+require 'rubygems/dependency_list'
+require 'rubygems/uninstaller'
+
+class Gem::Commands::CleanupCommand < Gem::Command
+
+  def initialize
+    super 'cleanup',
+          'Clean up old versions of installed gems in the local repository',
+          :force => false, :test => false, :install_dir => Gem.dir
+
+    add_option('-d', '--dryrun', "") do |value, options|
+      options[:dryrun] = true
+    end
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to cleanup"
+  end
+
+  def defaults_str # :nodoc:
+    "--no-dryrun"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The cleanup command removes old gems from GEM_HOME.  If an older version is
+installed elsewhere in GEM_PATH the cleanup command won't touch it.
+    EOF
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [GEMNAME ...]"
+  end
+
+  def execute
+    say "Cleaning up installed gems..."
+    primary_gems = {}
+
+    Gem.source_index.each do |name, spec|
+      if primary_gems[spec.name].nil? or
+         primary_gems[spec.name].version < spec.version then
+        primary_gems[spec.name] = spec
+      end
+    end
+
+    gems_to_cleanup = []
+
+    unless options[:args].empty? then
+      options[:args].each do |gem_name|
+        dep = Gem::Dependency.new gem_name, Gem::Requirement.default
+        specs = Gem.source_index.search dep
+        specs.each do |spec|
+          gems_to_cleanup << spec
+        end
+      end
+    else
+      Gem.source_index.each do |name, spec|
+        gems_to_cleanup << spec
+      end
+    end
+
+    gems_to_cleanup = gems_to_cleanup.select { |spec|
+      primary_gems[spec.name].version != spec.version
+    }
+
+    deplist = Gem::DependencyList.new
+    gems_to_cleanup.uniq.each do |spec| deplist.add spec end
+
+    deps = deplist.strongly_connected_components.flatten.reverse
+
+    deps.each do |spec|
+      if options[:dryrun] then
+        say "Dry Run Mode: Would uninstall #{spec.full_name}"
+      else
+        say "Attempting to uninstall #{spec.full_name}"
+
+        options[:args] = [spec.name]
+
+        uninstall_options = {
+          :executables => false,
+          :version => "= #{spec.version}",
+        }
+
+        if Gem.user_dir == spec.installation_path then
+          uninstall_options[:install_dir] = spec.installation_path
+        end
+
+        uninstaller = Gem::Uninstaller.new spec.name, uninstall_options
+
+        begin
+          uninstaller.uninstall
+        rescue Gem::DependencyRemovalException, Gem::InstallError,
+               Gem::GemNotInHomeException => e
+          say "Unable to uninstall #{spec.full_name}:"
+          say "\t#{e.class}: #{e.message}"
+        end
+      end
+    end
+
+    say "Clean Up Complete"
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/contents_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/contents_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/contents_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,98 @@
+require 'rubygems/command'
+require 'rubygems/version_option'
+
+class Gem::Commands::ContentsCommand < Gem::Command
+
+  include Gem::VersionOption
+
+  def initialize
+    super 'contents', 'Display the contents of the installed gems',
+          :specdirs => [], :lib_only => false
+
+    add_version_option
+
+    add_option(      '--all',
+               "Contents for all gems") do |all, options|
+      options[:all] = all
+    end
+
+    add_option('-s', '--spec-dir a,b,c', Array,
+               "Search for gems under specific paths") do |spec_dirs, options|
+      options[:specdirs] = spec_dirs
+    end
+
+    add_option('-l', '--[no-]lib-only',
+               "Only return files in the Gem's lib_dirs") do |lib_only, options|
+      options[:lib_only] = lib_only
+    end
+
+    add_option(      '--[no-]prefix',
+               "Don't include installed path prefix") do |prefix, options|
+      options[:prefix] = prefix
+    end
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to list contents for"
+  end
+
+  def defaults_str # :nodoc:
+    "--no-lib-only --prefix"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME [GEMNAME ...]"
+  end
+
+  def execute
+    version = options[:version] || Gem::Requirement.default
+
+    spec_dirs = options[:specdirs].map do |i|
+      [i, File.join(i, "specifications")]
+    end.flatten
+
+    path_kind = if spec_dirs.empty? then
+                  spec_dirs = Gem::SourceIndex.installed_spec_directories
+                  "default gem paths"
+                else
+                  "specified path"
+                end
+
+    si = Gem::SourceIndex.from_gems_in(*spec_dirs)
+
+    gem_names = if options[:all] then
+                  si.map { |_, spec| spec.name }
+                else
+                  get_all_gem_names
+                end
+
+    gem_names.each do |name|
+      gem_spec = si.find_name(name, version).last
+
+      unless gem_spec then
+        say "Unable to find gem '#{name}' in #{path_kind}"
+
+        if Gem.configuration.verbose then
+          say "\nDirectories searched:"
+          spec_dirs.each { |dir| say dir }
+        end
+
+        terminate_interaction 1 if gem_names.length == 1
+      end
+
+      files = options[:lib_only] ? gem_spec.lib_files : gem_spec.files
+
+      files.each do |f|
+        path = if options[:prefix] then
+                 File.join gem_spec.full_gem_path, f
+               else
+                 f
+               end
+
+        say path
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/dependency_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/dependency_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/dependency_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,188 @@
+require 'rubygems/command'
+require 'rubygems/local_remote_options'
+require 'rubygems/version_option'
+require 'rubygems/source_info_cache'
+
+class Gem::Commands::DependencyCommand < Gem::Command
+
+  include Gem::LocalRemoteOptions
+  include Gem::VersionOption
+
+  def initialize
+    super 'dependency',
+          'Show the dependencies of an installed gem',
+          :version => Gem::Requirement.default, :domain => :local
+
+    add_version_option
+    add_platform_option
+
+    add_option('-R', '--[no-]reverse-dependencies',
+               'Include reverse dependencies in the output') do
+      |value, options|
+      options[:reverse_dependencies] = value
+    end
+
+    add_option('-p', '--pipe',
+               "Pipe Format (name --version ver)") do |value, options|
+      options[:pipe_format] = value
+    end
+
+    add_local_remote_options
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to show dependencies for"
+  end
+
+  def defaults_str # :nodoc:
+    "--local --version '#{Gem::Requirement.default}' --no-reverse-dependencies"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME"
+  end
+
+  def execute
+    options[:args] << '' if options[:args].empty?
+    specs = {}
+
+    source_indexes = Hash.new do |h, source_uri|
+      h[source_uri] = Gem::SourceIndex.new
+    end
+
+    pattern = if options[:args].length == 1 and
+                 options[:args].first =~ /\A\/(.*)\/(i)?\z/m then
+                flags = $2 ? Regexp::IGNORECASE : nil
+                Regexp.new $1, flags
+              else
+                /\A#{Regexp.union(*options[:args])}/
+              end
+
+    dependency = Gem::Dependency.new pattern, options[:version]
+
+    if options[:reverse_dependencies] and remote? and not local? then
+      alert_error 'Only reverse dependencies for local gems are supported.'
+      terminate_interaction 1
+    end
+
+    if local? then
+      Gem.source_index.search(dependency).each do |spec|
+        source_indexes[:local].add_spec spec
+      end
+    end
+
+    if remote? and not options[:reverse_dependencies] then
+      fetcher = Gem::SpecFetcher.fetcher
+
+      begin
+        fetcher.find_matching(dependency).each do |spec_tuple, source_uri|
+          spec = fetcher.fetch_spec spec_tuple, URI.parse(source_uri)
+
+          source_indexes[source_uri].add_spec spec
+        end
+      rescue Gem::RemoteFetcher::FetchError => e
+        raise unless fetcher.warn_legacy e do
+          require 'rubygems/source_info_cache'
+
+          specs = Gem::SourceInfoCache.search_with_source dependency, false
+
+          specs.each do |spec, source_uri|
+            source_indexes[source_uri].add_spec spec
+          end
+        end
+      end
+    end
+
+    if source_indexes.empty? then
+      patterns = options[:args].join ','
+      say "No gems found matching #{patterns} (#{options[:version]})" if
+        Gem.configuration.verbose
+
+      terminate_interaction 1
+    end
+
+    specs = {}
+
+    source_indexes.values.each do |source_index|
+      source_index.gems.each do |name, spec|
+        specs[spec.full_name] = [source_index, spec]
+      end
+    end
+
+    reverse = Hash.new { |h, k| h[k] = [] }
+
+    if options[:reverse_dependencies] then
+      specs.values.each do |_, spec|
+        reverse[spec.full_name] = find_reverse_dependencies spec
+      end
+    end
+
+    if options[:pipe_format] then
+      specs.values.sort_by { |_, spec| spec }.each do |_, spec|
+        unless spec.dependencies.empty?
+          spec.dependencies.each do |dep|
+            say "#{dep.name} --version '#{dep.version_requirements}'"
+          end
+        end
+      end
+    else
+      response = ''
+
+      specs.values.sort_by { |_, spec| spec }.each do |_, spec|
+        response << print_dependencies(spec)
+        unless reverse[spec.full_name].empty? then
+          response << "  Used by\n"
+          reverse[spec.full_name].each do |sp, dep|
+            response << "    #{sp} (#{dep})\n"
+          end
+        end
+        response << "\n"
+      end
+
+      say response
+    end
+  end
+
+  def print_dependencies(spec, level = 0)
+    response = ''
+    response << '  ' * level + "Gem #{spec.full_name}\n"
+    unless spec.dependencies.empty? then
+      spec.dependencies.each do |dep|
+        response << '  ' * level + "  #{dep}\n"
+      end
+    end
+    response
+  end
+
+  # Retuns list of [specification, dep] that are satisfied by spec.
+  def find_reverse_dependencies(spec)
+    result = []
+
+    Gem.source_index.each do |name, sp|
+      sp.dependencies.each do |dep|
+        dep = Gem::Dependency.new(*dep) unless Gem::Dependency === dep
+
+        if spec.name == dep.name and
+           dep.version_requirements.satisfied_by?(spec.version) then
+          result << [sp.full_name, dep]
+        end
+      end
+    end
+
+    result
+  end
+
+  def find_gems(name, source_index)
+    specs = {}
+
+    spec_list = source_index.search name, options[:version]
+
+    spec_list.each do |spec|
+      specs[spec.full_name] = [source_index, spec]
+    end
+
+    specs
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/environment_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/environment_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/environment_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,128 @@
+require 'rubygems/command'
+
+class Gem::Commands::EnvironmentCommand < Gem::Command
+
+  def initialize
+    super 'environment', 'Display information about the RubyGems environment'
+  end
+
+  def arguments # :nodoc:
+    args = <<-EOF
+          packageversion  display the package version
+          gemdir          display the path where gems are installed
+          gempath         display path used to search for gems
+          version         display the gem format version
+          remotesources   display the remote gem servers
+          <omitted>       display everything
+    EOF
+    return args.gsub(/^\s+/, '')
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The RubyGems environment can be controlled through command line arguments,
+gemrc files, environment variables and built-in defaults.
+
+Command line argument defaults and some RubyGems defaults can be set in
+~/.gemrc file for individual users and a /etc/gemrc for all users.  A gemrc
+is a YAML file with the following YAML keys:
+
+  :sources: A YAML array of remote gem repositories to install gems from
+  :verbose: Verbosity of the gem command.  false, true, and :really are the
+            levels
+  :update_sources: Enable/disable automatic updating of repository metadata
+  :backtrace: Print backtrace when RubyGems encounters an error
+  :bulk_threshold: Switch to a bulk update when this many sources are out of
+                   date (legacy setting)
+  :gempath: The paths in which to look for gems
+  gem_command: A string containing arguments for the specified gem command
+
+Example:
+
+  :verbose: false
+  install: --no-wrappers
+  update: --no-wrappers
+
+RubyGems' default local repository can be overriden with the GEM_PATH and
+GEM_HOME environment variables.  GEM_HOME sets the default repository to
+install into.  GEM_PATH allows multiple local repositories to be searched for
+gems.
+
+If you are behind a proxy server, RubyGems uses the HTTP_PROXY,
+HTTP_PROXY_USER and HTTP_PROXY_PASS environment variables to discover the
+proxy server.
+
+If you are packaging RubyGems all of RubyGems' defaults are in
+lib/rubygems/defaults.rb.  You may override these in
+lib/rubygems/defaults/operating_system.rb
+    EOF
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [arg]"
+  end
+
+  def execute
+    out = ''
+    arg = options[:args][0]
+    case arg
+    when /^packageversion/ then
+      out << Gem::RubyGemsPackageVersion
+    when /^version/ then
+      out << Gem::RubyGemsVersion
+    when /^gemdir/, /^gemhome/, /^home/, /^GEM_HOME/ then
+      out << Gem.dir
+    when /^gempath/, /^path/, /^GEM_PATH/ then
+      out << Gem.path.join(File::PATH_SEPARATOR)
+    when /^remotesources/ then
+      out << Gem.sources.join("\n")
+    when nil then
+      out = "RubyGems Environment:\n"
+
+      out << "  - RUBYGEMS VERSION: #{Gem::RubyGemsVersion}\n"
+
+      out << "  - RUBY VERSION: #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
+      out << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
+      out << ") [#{RUBY_PLATFORM}]\n"
+
+      out << "  - INSTALLATION DIRECTORY: #{Gem.dir}\n"
+
+      out << "  - RUBYGEMS PREFIX: #{Gem.prefix}\n" unless Gem.prefix.nil?
+
+      out << "  - RUBY EXECUTABLE: #{Gem.ruby}\n"
+
+      out << "  - EXECUTABLE DIRECTORY: #{Gem.bindir}\n"
+
+      out << "  - RUBYGEMS PLATFORMS:\n"
+      Gem.platforms.each do |platform|
+        out << "    - #{platform}\n"
+      end
+
+      out << "  - GEM PATHS:\n"
+      out << "     - #{Gem.dir}\n"
+
+      path = Gem.path.dup
+      path.delete Gem.dir
+      path.each do |p|
+        out << "     - #{p}\n"
+      end
+
+      out << "  - GEM CONFIGURATION:\n"
+      Gem.configuration.each do |name, value|
+        out << "     - #{name.inspect} => #{value.inspect}\n"
+      end
+
+      out << "  - REMOTE SOURCES:\n"
+      Gem.sources.each do |s|
+        out << "     - #{s}\n"
+      end
+
+    else
+      raise Gem::CommandLineError, "Unknown enviroment option [#{arg}]"
+    end
+    say out
+    true
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/fetch_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/fetch_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/fetch_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,62 @@
+require 'rubygems/command'
+require 'rubygems/local_remote_options'
+require 'rubygems/version_option'
+require 'rubygems/source_info_cache'
+
+class Gem::Commands::FetchCommand < Gem::Command
+
+  include Gem::LocalRemoteOptions
+  include Gem::VersionOption
+
+  def initialize
+    super 'fetch', 'Download a gem and place it in the current directory'
+
+    add_bulk_threshold_option
+    add_proxy_option
+    add_source_option
+
+    add_version_option
+    add_platform_option
+  end
+
+  def arguments # :nodoc:
+    'GEMNAME       name of gem to download'
+  end
+
+  def defaults_str # :nodoc:
+    "--version '#{Gem::Requirement.default}'"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME [GEMNAME ...]"
+  end
+
+  def execute
+    version = options[:version] || Gem::Requirement.default
+    all = Gem::Requirement.default
+
+    gem_names = get_all_gem_names
+
+    gem_names.each do |gem_name|
+      dep = Gem::Dependency.new gem_name, version
+
+      specs_and_sources = Gem::SpecFetcher.fetcher.fetch dep, all
+
+      specs_and_sources.sort_by { |spec,| spec.version }
+
+      spec, source_uri = specs_and_sources.last
+
+      if spec.nil? then
+        alert_error "Could not find #{gem_name} in any repository"
+        next
+      end
+
+      path = Gem::RemoteFetcher.fetcher.download spec, source_uri
+      FileUtils.mv path, spec.file_name
+
+      say "Downloaded #{spec.full_name}"
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/generate_index_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/generate_index_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/generate_index_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,133 @@
+require 'rubygems/command'
+require 'rubygems/indexer'
+
+##
+# Generates a index files for use as a gem server.
+#
+# See `gem help generate_index`
+
+class Gem::Commands::GenerateIndexCommand < Gem::Command
+
+  def initialize
+    super 'generate_index',
+          'Generates the index files for a gem server directory',
+          :directory => '.', :build_legacy => true, :build_modern => true
+
+    add_option '-d', '--directory=DIRNAME',
+               'repository base dir containing gems subdir' do |dir, options|
+      options[:directory] = File.expand_path dir
+    end
+
+    add_option '--[no-]legacy',
+               'Generate indexes for RubyGems older than',
+               '1.2.0' do |value, options|
+      unless options[:build_modern] or value then
+        raise OptionParser::InvalidOption, 'no indicies will be built'
+      end
+
+      options[:build_legacy] = value
+    end
+
+    add_option '--[no-]modern',
+               'Generate indexes for RubyGems newer',
+               'than 1.2.0' do |value, options|
+      unless options[:build_legacy] or value then
+        raise OptionParser::InvalidOption, 'no indicies will be built'
+      end
+
+      options[:build_modern] = value
+    end
+
+    add_option '--update',
+               'Update modern indexes with gems added',
+               'since the last update' do |value, options|
+      options[:update] = value
+    end
+
+    add_option :RSS, '--rss-gems-host=GEM_HOST',
+               'Host name where gems are served from,',
+               'used for GUID and enclosure values' do |value, options|
+      options[:rss_gems_host] = value
+    end
+
+    add_option :RSS, '--rss-host=HOST',
+               'Host name for more gems information,',
+               'used for RSS feed link' do |value, options|
+      options[:rss_host] = value
+    end
+
+    add_option :RSS, '--rss-title=TITLE',
+               'Set title for RSS feed' do |value, options|
+      options[:rss_title] = value
+    end
+  end
+
+  def defaults_str # :nodoc:
+    "--directory . --legacy --modern"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The generate_index command creates a set of indexes for serving gems
+statically.  The command expects a 'gems' directory under the path given to
+the --directory option.  The given directory will be the directory you serve
+as the gem repository.
+
+For `gem generate_index --directory /path/to/repo`, expose /path/to/repo via
+your HTTP server configuration (not /path/to/repo/gems).
+
+When done, it will generate a set of files like this:
+
+  gems/*.gem                                   # .gem files you want to
+                                               # index
+
+  specs.<version>.gz                           # specs index
+  latest_specs.<version>.gz                    # latest specs index
+  prerelease_specs.<version>.gz                # prerelease specs index
+  quick/Marshal.<version>/<gemname>.gemspec.rz # Marshal quick index file
+
+  # these files support legacy RubyGems
+  quick/index
+  quick/index.rz                               # quick index manifest
+  quick/<gemname>.gemspec.rz                   # legacy YAML quick index
+                                               # file
+  Marshal.<version>
+  Marshal.<version>.Z                          # Marshal full index
+  yaml
+  yaml.Z                                       # legacy YAML full index
+
+The .Z and .rz extension files are compressed with the inflate algorithm.
+The Marshal version number comes from ruby's Marshal::MAJOR_VERSION and
+Marshal::MINOR_VERSION constants.  It is used to ensure compatibility.
+The yaml indexes exist for legacy RubyGems clients and fallback in case of
+Marshal version changes.
+
+If --rss-host and --rss-gem-host are given an RSS feed will be generated at
+index.rss containing gems released in the last two days.
+    EOF
+  end
+
+  def execute
+    if options[:update] and
+       (options[:rss_host] or options[:rss_gems_host]) then
+      alert_error '--update not compatible with RSS generation'
+      terminate_interaction 1
+    end
+
+    if not File.exist?(options[:directory]) or
+       not File.directory?(options[:directory]) then
+      alert_error "unknown directory name #{directory}."
+      terminate_interaction 1
+    else
+      indexer = Gem::Indexer.new options.delete(:directory), options
+
+      if options[:update] then
+        indexer.update_index
+      else
+        indexer.generate_index
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/help_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/help_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/help_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,172 @@
+require 'rubygems/command'
+
+class Gem::Commands::HelpCommand < Gem::Command
+
+  # :stopdoc:
+  EXAMPLES = <<-EOF
+Some examples of 'gem' usage.
+
+* Install 'rake', either from local directory or remote server:
+
+    gem install rake
+
+* Install 'rake', only from remote server:
+
+    gem install rake --remote
+
+* Install 'rake' from remote server, and run unit tests,
+  and generate RDocs:
+
+    gem install --remote rake --test --rdoc --ri
+
+* Install 'rake', but only version 0.3.1, even if dependencies
+  are not met, and into a user-specific directory:
+
+    gem install rake --version 0.3.1 --force --user-install
+
+* List local gems whose name begins with 'D':
+
+    gem list D
+
+* List local and remote gems whose name contains 'log':
+
+    gem search log --both
+
+* List only remote gems whose name contains 'log':
+
+    gem search log --remote
+
+* Uninstall 'rake':
+
+    gem uninstall rake
+
+* Create a gem:
+
+    See http://rubygems.rubyforge.org/wiki/wiki.pl?CreateAGemInTenMinutes
+
+* See information about RubyGems:
+
+    gem environment
+
+* Update all gems on your system:
+
+    gem update
+  EOF
+
+  PLATFORMS = <<-'EOF'
+RubyGems platforms are composed of three parts, a CPU, an OS, and a
+version.  These values are taken from values in rbconfig.rb.  You can view
+your current platform by running `gem environment`.
+
+RubyGems matches platforms as follows:
+
+  * The CPU must match exactly, unless one of the platforms has
+    "universal" as the CPU.
+  * The OS must match exactly.
+  * The versions must match exactly unless one of the versions is nil.
+
+For commands that install, uninstall and list gems, you can override what
+RubyGems thinks your platform is with the --platform option.  The platform
+you pass must match "#{cpu}-#{os}" or "#{cpu}-#{os}-#{version}".  On mswin
+platforms, the version is the compiler version, not the OS version.  (Ruby
+compiled with VC6 uses "60" as the compiler version, VC8 uses "80".)
+
+Example platforms:
+
+  x86-freebsd        # Any FreeBSD version on an x86 CPU
+  universal-darwin-8 # Darwin 8 only gems that run on any CPU
+  x86-mswin32-80     # Windows gems compiled with VC8
+
+When building platform gems, set the platform in the gem specification to
+Gem::Platform::CURRENT.  This will correctly mark the gem with your ruby's
+platform.
+  EOF
+  # :startdoc:
+
+  def initialize
+    super 'help', "Provide help on the 'gem' command"
+  end
+
+  def arguments # :nodoc:
+    args = <<-EOF
+      commands      List all 'gem' commands
+      examples      Show examples of 'gem' usage
+      <command>     Show specific help for <command>
+    EOF
+    return args.gsub(/^\s+/, '')
+  end
+
+  def usage # :nodoc:
+    "#{program_name} ARGUMENT"
+  end
+
+  def execute
+    command_manager = Gem::CommandManager.instance
+    arg = options[:args][0]
+
+    if begins? "commands", arg then
+      out = []
+      out << "GEM commands are:"
+      out << nil
+
+      margin_width = 4
+
+      desc_width = command_manager.command_names.map { |n| n.size }.max + 4
+
+      summary_width = 80 - margin_width - desc_width
+      wrap_indent = ' ' * (margin_width + desc_width)
+      format = "#{' ' * margin_width}%-#{desc_width}s%s"
+
+      command_manager.command_names.each do |cmd_name|
+        summary = command_manager[cmd_name].summary
+        summary = wrap(summary, summary_width).split "\n"
+        out << sprintf(format, cmd_name, summary.shift)
+        until summary.empty? do
+          out << "#{wrap_indent}#{summary.shift}"
+        end
+      end
+
+      out << nil
+      out << "For help on a particular command, use 'gem help COMMAND'."
+      out << nil
+      out << "Commands may be abbreviated, so long as they are unambiguous."
+      out << "e.g. 'gem i rake' is short for 'gem install rake'."
+
+      say out.join("\n")
+
+    elsif begins? "options", arg then
+      say Gem::Command::HELP
+
+    elsif begins? "examples", arg then
+      say EXAMPLES
+
+    elsif begins? "platforms", arg then
+      say PLATFORMS
+
+    elsif options[:help] then
+      command = command_manager[options[:help]]
+      if command
+        # help with provided command
+        command.invoke("--help")
+      else
+        alert_error "Unknown command #{options[:help]}.  Try 'gem help commands'"
+      end
+
+    elsif arg then
+      possibilities = command_manager.find_command_possibilities(arg.downcase)
+      if possibilities.size == 1
+        command = command_manager[possibilities.first]
+        command.invoke("--help")
+      elsif possibilities.size > 1
+        alert_warning "Ambiguous command #{arg} (#{possibilities.join(', ')})"
+      else
+        alert_warning "Unknown command #{arg}. Try gem help commands"
+      end
+
+    else
+      say Gem::Command::HELP
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/install_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/install_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/install_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,174 @@
+require 'rubygems/command'
+require 'rubygems/doc_manager'
+require 'rubygems/install_update_options'
+require 'rubygems/dependency_installer'
+require 'rubygems/local_remote_options'
+require 'rubygems/validator'
+require 'rubygems/version_option'
+
+##
+# Gem installer command line tool
+#
+# See `gem help install`
+
+class Gem::Commands::InstallCommand < Gem::Command
+
+  include Gem::VersionOption
+  include Gem::LocalRemoteOptions
+  include Gem::InstallUpdateOptions
+
+  def initialize
+    defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
+      :generate_rdoc     => true,
+      :generate_ri       => true,
+      :format_executable => false,
+      :test              => false,
+      :version           => Gem::Requirement.default,
+    })
+
+    super 'install', 'Install a gem into the local repository', defaults
+
+    add_install_update_options
+    add_local_remote_options
+    add_platform_option
+    add_version_option
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to install"
+  end
+
+  def defaults_str # :nodoc:
+    "--both --version '#{Gem::Requirement.default}' --rdoc --ri --no-force\n" \
+    "--no-test --install-dir #{Gem.dir}"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The install command installs local or remote gem into a gem repository.
+
+For gems with executables ruby installs a wrapper file into the executable
+directory by default.  This can be overridden with the --no-wrappers option.
+The wrapper allows you to choose among alternate gem versions using _version_.
+
+For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer
+version is also installed.
+
+If an extension fails to compile during gem installation the gem
+specification is not written out, but the gem remains unpacked in the
+repository.  You may need to specify the path to the library's headers and
+libraries to continue.  You can do this by adding a -- between RubyGems'
+options and the extension's build options:
+
+  $ gem install some_extension_gem
+  [build fails]
+  Gem files will remain installed in \\
+  /path/to/gems/some_extension_gem-1.0 for inspection.
+  Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out
+  $ gem install some_extension_gem -- --with-extension-lib=/path/to/lib
+  [build succeeds]
+  $ gem list some_extension_gem
+
+  *** LOCAL GEMS ***
+
+  some_extension_gem (1.0)
+  $
+
+If you correct the compilation errors by editing the gem files you will need
+to write the specification by hand.  For example:
+
+  $ gem install some_extension_gem
+  [build fails]
+  Gem files will remain installed in \\
+  /path/to/gems/some_extension_gem-1.0 for inspection.
+  Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out
+  $ [cd /path/to/gems/some_extension_gem-1.0]
+  $ [edit files or what-have-you and run make]
+  $ gem spec ../../cache/some_extension_gem-1.0.gem --ruby > \\
+             ../../specifications/some_extension_gem-1.0.gemspec
+  $ gem list some_extension_gem
+
+  *** LOCAL GEMS ***
+
+  some_extension_gem (1.0)
+  $
+
+    EOF
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags"
+  end
+
+  def execute
+    if options[:include_dependencies] then
+      alert "`gem install -y` is now default and will be removed"
+      alert "use --ignore-dependencies to install only the gems you list"
+    end
+
+    installed_gems = []
+
+    ENV.delete 'GEM_PATH' if options[:install_dir].nil? and RUBY_VERSION > '1.9'
+
+    exit_code = 0
+
+    get_all_gem_names.each do |gem_name|
+      begin
+        inst = Gem::DependencyInstaller.new options
+        inst.install gem_name, options[:version]
+
+        inst.installed_gems.each do |spec|
+          say "Successfully installed #{spec.full_name}"
+        end
+
+        installed_gems.push(*inst.installed_gems)
+      rescue Gem::InstallError => e
+        alert_error "Error installing #{gem_name}:\n\t#{e.message}"
+        exit_code |= 1
+      rescue Gem::GemNotFoundException => e
+        alert_error e.message
+        exit_code |= 2
+      end
+    end
+
+    unless installed_gems.empty? then
+      gems = installed_gems.length == 1 ? 'gem' : 'gems'
+      say "#{installed_gems.length} #{gems} installed"
+
+      # NOTE: *All* of the RI documents must be generated first.  For some
+      # reason, RI docs cannot be generated after any RDoc documents are
+      # generated.
+
+      if options[:generate_ri] then
+        installed_gems.each do |gem|
+          Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri
+        end
+
+        Gem::DocManager.update_ri_cache
+      end
+
+      if options[:generate_rdoc] then
+        installed_gems.each do |gem|
+          Gem::DocManager.new(gem, options[:rdoc_args]).generate_rdoc
+        end
+      end
+
+      if options[:test] then
+        installed_gems.each do |spec|
+          gem_spec = Gem::SourceIndex.from_installed_gems.find_name(spec.name, spec.version.version).first
+          result = Gem::Validator.new.unit_test(gem_spec)
+          if result and not result.passed?
+            unless ask_yes_no("...keep Gem?", true)
+              require 'rubygems/uninstaller'
+              Gem::Uninstaller.new(spec.name, :version => spec.version.version).uninstall
+            end
+          end
+        end
+      end
+    end
+
+    raise Gem::SystemExitException, exit_code
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/list_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/list_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/list_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,35 @@
+require 'rubygems/command'
+require 'rubygems/commands/query_command'
+
+##
+# An alternate to Gem::Commands::QueryCommand that searches for gems starting
+# with the the supplied argument.
+
+class Gem::Commands::ListCommand < Gem::Commands::QueryCommand
+
+  def initialize
+    super 'list', 'Display gems whose name starts with STRING'
+
+    remove_option('--name-matches')
+  end
+
+  def arguments # :nodoc:
+    "STRING        start of gem name to look for"
+  end
+
+  def defaults_str # :nodoc:
+    "--local --no-details"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [STRING]"
+  end
+
+  def execute
+    string = get_one_optional_argument || ''
+    options[:name] = /^#{string}/i
+    super
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/lock_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/lock_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/lock_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,110 @@
+require 'rubygems/command'
+
+class Gem::Commands::LockCommand < Gem::Command
+
+  def initialize
+    super 'lock', 'Generate a lockdown list of gems',
+          :strict => false
+
+    add_option '-s', '--[no-]strict',
+               'fail if unable to satisfy a dependency' do |strict, options|
+      options[:strict] = strict
+    end
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to lock\nVERSION       version of gem to lock"
+  end
+
+  def defaults_str # :nodoc:
+    "--no-strict"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The lock command will generate a list of +gem+ statements that will lock down
+the versions for the gem given in the command line.  It will specify exact
+versions in the requirements list to ensure that the gems loaded will always
+be consistent.  A full recursive search of all effected gems will be
+generated.
+
+Example:
+
+  gemlock rails-1.0.0 > lockdown.rb
+
+will produce in lockdown.rb:
+
+  require "rubygems"
+  gem 'rails', '= 1.0.0'
+  gem 'rake', '= 0.7.0.1'
+  gem 'activesupport', '= 1.2.5'
+  gem 'activerecord', '= 1.13.2'
+  gem 'actionpack', '= 1.11.2'
+  gem 'actionmailer', '= 1.1.5'
+  gem 'actionwebservice', '= 1.0.0'
+
+Just load lockdown.rb from your application to ensure that the current
+versions are loaded.  Make sure that lockdown.rb is loaded *before* any
+other require statements.
+
+Notice that rails 1.0.0 only requires that rake 0.6.2 or better be used.
+Rake-0.7.0.1 is the most recent version installed that satisfies that, so we
+lock it down to the exact version.
+    EOF
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME-VERSION [GEMNAME-VERSION ...]"
+  end
+
+  def complain(message)
+    if options[:strict] then
+      raise Gem::Exception, message
+    else
+      say "# #{message}"
+    end
+  end
+
+  def execute
+    say "require 'rubygems'"
+
+    locked = {}
+
+    pending = options[:args]
+
+    until pending.empty? do
+      full_name = pending.shift
+
+      spec = Gem::SourceIndex.load_specification spec_path(full_name)
+
+      if spec.nil? then
+        complain "Could not find gem #{full_name}, try using the full name"
+        next
+      end
+
+      say "gem '#{spec.name}', '= #{spec.version}'" unless locked[spec.name]
+      locked[spec.name] = true
+
+      spec.runtime_dependencies.each do |dep|
+        next if locked[dep.name]
+        candidates = Gem.source_index.search dep
+
+        if candidates.empty? then
+          complain "Unable to satisfy '#{dep}' from currently installed gems"
+        else
+          pending << candidates.last.full_name
+        end
+      end
+    end
+  end
+
+  def spec_path(gem_full_name)
+    gemspecs = Gem.path.map do |path|
+      File.join path, "specifications", "#{gem_full_name}.gemspec"
+    end
+
+    gemspecs.find { |gemspec| File.exist? gemspec }
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/mirror_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/mirror_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/mirror_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,111 @@
+require 'yaml'
+require 'zlib'
+
+require 'rubygems/command'
+require 'open-uri'
+
+class Gem::Commands::MirrorCommand < Gem::Command
+
+  def initialize
+    super 'mirror', 'Mirror a gem repository'
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The mirror command uses the ~/.gemmirrorrc config file to mirror remote gem
+repositories to a local path. The config file is a YAML document that looks
+like this:
+
+  ---
+  - from: http://gems.example.com # source repository URI
+    to: /path/to/mirror           # destination directory
+
+Multiple sources and destinations may be specified.
+    EOF
+  end
+
+  def execute
+    config_file = File.join Gem.user_home, '.gemmirrorrc'
+
+    raise "Config file #{config_file} not found" unless File.exist? config_file
+
+    mirrors = YAML.load_file config_file
+
+    raise "Invalid config file #{config_file}" unless mirrors.respond_to? :each
+
+    mirrors.each do |mir|
+      raise "mirror missing 'from' field" unless mir.has_key? 'from'
+      raise "mirror missing 'to' field" unless mir.has_key? 'to'
+
+      get_from = mir['from']
+      save_to = File.expand_path mir['to']
+
+      raise "Directory not found: #{save_to}" unless File.exist? save_to
+      raise "Not a directory: #{save_to}" unless File.directory? save_to
+
+      gems_dir = File.join save_to, "gems"
+
+      if File.exist? gems_dir then
+        raise "Not a directory: #{gems_dir}" unless File.directory? gems_dir
+      else
+        Dir.mkdir gems_dir
+      end
+
+      source_index_data = ''
+
+      say "fetching: #{get_from}/Marshal.#{Gem.marshal_version}.Z"
+
+      get_from = URI.parse get_from
+
+      if get_from.scheme.nil? then
+        get_from = get_from.to_s
+      elsif get_from.scheme == 'file' then
+        # check if specified URI contains a drive letter (file:/D:/Temp)
+        get_from = get_from.to_s
+        get_from = if get_from =~ /^file:.*[a-z]:/i then
+                     get_from[6..-1]
+                   else
+                     get_from[5..-1]
+                   end
+      end
+
+      open File.join(get_from.to_s, "Marshal.#{Gem.marshal_version}.Z"), "rb" do |y|
+        source_index_data = Zlib::Inflate.inflate y.read
+        open File.join(save_to, "Marshal.#{Gem.marshal_version}"), "wb" do |out|
+          out.write source_index_data
+        end
+      end
+
+      source_index = Marshal.load source_index_data
+
+      progress = ui.progress_reporter source_index.size,
+                                      "Fetching #{source_index.size} gems"
+      source_index.each do |fullname, gem|
+        gem_file = gem.file_name
+        gem_dest = File.join gems_dir, gem_file
+
+        unless File.exist? gem_dest then
+          begin
+            open "#{get_from}/gems/#{gem_file}", "rb" do |g|
+              contents = g.read
+              open gem_dest, "wb" do |out|
+                out.write contents
+              end
+            end
+          rescue
+            old_gf = gem_file
+            gem_file = gem_file.downcase
+            retry if old_gf != gem_file
+            alert_error $!
+          end
+        end
+
+        progress.updated gem_file
+      end
+
+      progress.done
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/outdated_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/outdated_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/outdated_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,33 @@
+require 'rubygems/command'
+require 'rubygems/local_remote_options'
+require 'rubygems/spec_fetcher'
+require 'rubygems/version_option'
+
+class Gem::Commands::OutdatedCommand < Gem::Command
+
+  include Gem::LocalRemoteOptions
+  include Gem::VersionOption
+
+  def initialize
+    super 'outdated', 'Display all gems that need updates'
+
+    add_local_remote_options
+    add_platform_option
+  end
+
+  def execute
+    locals = Gem::SourceIndex.from_installed_gems
+
+    locals.outdated.sort.each do |name|
+      local = locals.find_name(name).last
+
+      dep = Gem::Dependency.new local.name, ">= #{local.version}"
+      remotes = Gem::SpecFetcher.fetcher.fetch dep
+      remote = remotes.last.first
+
+      say "#{local.name} (#{local.version} < #{remote.version})"
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/pristine_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/pristine_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/pristine_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,93 @@
+require 'fileutils'
+require 'rubygems/command'
+require 'rubygems/format'
+require 'rubygems/installer'
+require 'rubygems/version_option'
+
+class Gem::Commands::PristineCommand < Gem::Command
+
+  include Gem::VersionOption
+
+  def initialize
+    super 'pristine',
+          'Restores installed gems to pristine condition from files located in the gem cache',
+          :version => Gem::Requirement.default
+
+    add_option('--all',
+               'Restore all installed gems to pristine',
+               'condition') do |value, options|
+      options[:all] = value
+    end
+
+    add_version_option('restore to', 'pristine condition')
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       gem to restore to pristine condition (unless --all)"
+  end
+
+  def defaults_str # :nodoc:
+    "--all"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The pristine command compares the installed gems with the contents of the
+cached gem and restores any files that don't match the cached gem's copy.
+
+If you have made modifications to your installed gems, the pristine command
+will revert them.  After all the gem's files have been checked all bin stubs
+for the gem are regenerated.
+
+If the cached gem cannot be found, you will need to use `gem install` to
+revert the gem.
+    EOF
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [args]"
+  end
+
+  def execute
+    gem_name = nil
+
+    specs = if options[:all] then
+              Gem::SourceIndex.from_installed_gems.map do |name, spec|
+                spec
+              end
+            else
+              gem_name = get_one_gem_name
+              Gem::SourceIndex.from_installed_gems.find_name(gem_name,
+                                                          options[:version])
+            end
+
+    if specs.empty? then
+      raise Gem::Exception,
+            "Failed to find gem #{gem_name} #{options[:version]}"
+    end
+
+    install_dir = Gem.dir # TODO use installer option
+
+    raise Gem::FilePermissionError.new(install_dir) unless
+      File.writable?(install_dir)
+
+    say "Restoring gem(s) to pristine condition..."
+
+    specs.each do |spec|
+      gem = Dir[File.join(Gem.dir, 'cache', spec.file_name)].first
+
+      if gem.nil? then
+        alert_error "Cached gem for #{spec.full_name} not found, use `gem install` to restore"
+        next
+      end
+
+      # TODO use installer options
+      installer = Gem::Installer.new gem, :wrappers => true, :force => true
+      installer.install
+
+      say "Restored #{spec.full_name}"
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/query_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/query_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/query_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,264 @@
+require 'rubygems/command'
+require 'rubygems/local_remote_options'
+require 'rubygems/spec_fetcher'
+require 'rubygems/version_option'
+require 'rubygems/text'
+
+class Gem::Commands::QueryCommand < Gem::Command
+
+  include Gem::Text
+  include Gem::LocalRemoteOptions
+  include Gem::VersionOption
+
+  def initialize(name = 'query',
+                 summary = 'Query gem information in local or remote repositories')
+    super name, summary,
+         :name => //, :domain => :local, :details => false, :versions => true,
+         :installed => false, :version => Gem::Requirement.default
+
+    add_option('-i', '--[no-]installed',
+               'Check for installed gem') do |value, options|
+      options[:installed] = value
+    end
+
+    add_version_option
+
+    add_option('-n', '--name-matches REGEXP',
+               'Name of gem(s) to query on matches the',
+               'provided REGEXP') do |value, options|
+      options[:name] = /#{value}/i
+    end
+
+    add_option('-d', '--[no-]details',
+               'Display detailed information of gem(s)') do |value, options|
+      options[:details] = value
+    end
+
+    add_option(      '--[no-]versions',
+               'Display only gem names') do |value, options|
+      options[:versions] = value
+      options[:details] = false unless value
+    end
+
+    add_option('-a', '--all',
+               'Display all gem versions') do |value, options|
+      options[:all] = value
+    end
+
+    add_option(      '--prerelease',
+               'Display prerelease versions') do |value, options|
+      options[:prerelease] = value
+    end
+
+    add_local_remote_options
+  end
+
+  def defaults_str # :nodoc:
+    "--local --name-matches // --no-details --versions --no-installed"
+  end
+
+  def execute
+    exit_code = 0
+
+    name = options[:name]
+    prerelease = options[:prerelease]
+
+    if options[:installed] then
+      if name.source.empty? then
+        alert_error "You must specify a gem name"
+        exit_code |= 4
+      elsif installed? name, options[:version] then
+        say "true"
+      else
+        say "false"
+        exit_code |= 1
+      end
+
+      raise Gem::SystemExitException, exit_code
+    end
+
+    dep = Gem::Dependency.new name, Gem::Requirement.default
+
+    if local? then
+      if prerelease and not both? then
+        alert_warning "prereleases are always shown locally"
+      end
+
+      if ui.outs.tty? or both? then
+        say
+        say "*** LOCAL GEMS ***"
+        say
+      end
+
+      specs = Gem.source_index.search dep
+
+      spec_tuples = specs.map do |spec|
+        [[spec.name, spec.version, spec.original_platform, spec], :local]
+      end
+
+      output_query_results spec_tuples
+    end
+
+    if remote? then
+      if ui.outs.tty? or both? then
+        say
+        say "*** REMOTE GEMS ***"
+        say
+      end
+
+      all = options[:all]
+
+      begin
+        fetcher = Gem::SpecFetcher.fetcher
+        spec_tuples = fetcher.find_matching dep, all, false, prerelease
+      rescue Gem::RemoteFetcher::FetchError => e
+        if prerelease then
+          raise Gem::OperationNotSupportedError,
+                "Prereleases not supported on legacy repositories"
+        end
+
+        raise unless fetcher.warn_legacy e do
+          require 'rubygems/source_info_cache'
+
+          dep.name = '' if dep.name == //
+
+          specs = Gem::SourceInfoCache.search_with_source dep, false, all
+
+          spec_tuples = specs.map do |spec, source_uri|
+            [[spec.name, spec.version, spec.original_platform, spec],
+             source_uri]
+          end
+        end
+      end
+
+      output_query_results spec_tuples
+    end
+  end
+
+  private
+
+  ##
+  # Check if gem +name+ version +version+ is installed.
+
+  def installed?(name, version = Gem::Requirement.default)
+    dep = Gem::Dependency.new name, version
+    !Gem.source_index.search(dep).empty?
+  end
+
+  def output_query_results(spec_tuples)
+    output = []
+    versions = Hash.new { |h,name| h[name] = [] }
+
+    spec_tuples.each do |spec_tuple, source_uri|
+      versions[spec_tuple.first] << [spec_tuple, source_uri]
+    end
+
+    versions = versions.sort_by do |(name,_),_|
+      name.downcase
+    end
+
+    versions.each do |gem_name, matching_tuples|
+      matching_tuples = matching_tuples.sort_by do |(name, version,_),_|
+        version
+      end.reverse
+
+      platforms = Hash.new { |h,version| h[version] = [] }
+
+      matching_tuples.map do |(name, version, platform,_),_|
+        platforms[version] << platform if platform
+      end
+
+      seen = {}
+
+      matching_tuples.delete_if do |(name, version,_),_|
+        if seen[version] then
+          true
+        else
+          seen[version] = true
+          false
+        end
+      end
+
+      entry = gem_name.dup
+
+      if options[:versions] then
+        versions = matching_tuples.map { |(name, version,_),_| version }.uniq
+        entry << " (#{versions.join ', '})"
+      end
+
+      if options[:details] then
+        detail_tuple = matching_tuples.first
+
+        spec = if detail_tuple.first.length == 4 then
+                 detail_tuple.first.last
+               else
+                 uri = URI.parse detail_tuple.last
+                 Gem::SpecFetcher.fetcher.fetch_spec detail_tuple.first, uri
+               end
+
+        entry << "\n"
+
+        non_ruby = platforms.any? do |_, pls|
+          pls.any? { |pl| pl != Gem::Platform::RUBY }
+        end
+
+        if non_ruby then
+          if platforms.length == 1 then
+            title = platforms.values.length == 1 ? 'Platform' : 'Platforms'
+            entry << "    #{title}: #{platforms.values.sort.join ', '}\n"
+          else
+            entry << "    Platforms:\n"
+            platforms.sort_by do |version,|
+              version
+            end.each do |version, pls|
+              label = "        #{version}: "
+              data = format_text pls.sort.join(', '), 68, label.length
+              data[0, label.length] = label
+              entry << data << "\n"
+            end
+          end
+        end
+
+        authors = "Author#{spec.authors.length > 1 ? 's' : ''}: "
+        authors << spec.authors.join(', ')
+        entry << format_text(authors, 68, 4)
+
+        if spec.rubyforge_project and not spec.rubyforge_project.empty? then
+          rubyforge = "Rubyforge: http://rubyforge.org/projects/#{spec.rubyforge_project}"
+          entry << "\n" << format_text(rubyforge, 68, 4)
+        end
+
+        if spec.homepage and not spec.homepage.empty? then
+          entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4)
+        end
+
+        if spec.license and not spec.license.empty? then
+          licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: "
+          licenses << spec.licenses.join(', ')
+          entry << "\n" << format_text(licenses, 68, 4)
+        end
+
+        if spec.loaded_from then
+          if matching_tuples.length == 1 then
+            loaded_from = File.dirname File.dirname(spec.loaded_from)
+            entry << "\n" << "    Installed at: #{loaded_from}"
+          else
+            label = 'Installed at'
+            matching_tuples.each do |(_,version,_,s),|
+              loaded_from = File.dirname File.dirname(s.loaded_from)
+              entry << "\n" << "    #{label} (#{version}): #{loaded_from}"
+              label = ' ' * label.length
+            end
+          end
+        end
+
+        entry << "\n\n" << format_text(spec.summary, 68, 4)
+      end
+      output << entry
+    end
+
+    say output.join(options[:details] ? "\n\n" : "\n")
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/rdoc_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/rdoc_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/rdoc_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,76 @@
+require 'rubygems/command'
+require 'rubygems/version_option'
+require 'rubygems/doc_manager'
+
+class Gem::Commands::RdocCommand < Gem::Command
+  include Gem::VersionOption
+
+  def initialize
+    super 'rdoc', 'Generates RDoc for pre-installed gems',
+          :version => Gem::Requirement.default,
+          :include_rdoc => true, :include_ri => true
+
+    add_option('--all',
+               'Generate RDoc/RI documentation for all',
+               'installed gems') do |value, options|
+      options[:all] = value
+    end
+
+    add_option('--[no-]rdoc',
+               'Include RDoc generated documents') do |value, options|
+      options[:include_rdoc] = value
+    end
+
+    add_option('--[no-]ri',
+               'Include RI generated documents') do |value, options|
+      options[:include_ri] = value
+    end
+
+    add_version_option
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       gem to generate documentation for (unless --all)"
+  end
+
+  def defaults_str # :nodoc:
+    "--version '#{Gem::Requirement.default}' --rdoc --ri"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [args]"
+  end
+
+  def execute
+    if options[:all] then
+      specs = Gem::SourceIndex.from_installed_gems.collect { |name, spec|
+        spec
+      }
+    else
+      gem_name = get_one_gem_name
+      dep = Gem::Dependency.new gem_name, options[:version]
+      specs = Gem::SourceIndex.from_installed_gems.search dep
+    end
+
+    if specs.empty?
+      raise "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}"
+    end
+
+    if options[:include_ri]
+      specs.each do |spec|
+        Gem::DocManager.new(spec).generate_ri
+      end
+
+      Gem::DocManager.update_ri_cache
+    end
+
+    if options[:include_rdoc]
+      specs.each do |spec|
+        Gem::DocManager.new(spec).generate_rdoc
+      end
+    end
+
+    true
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/search_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/search_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/search_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,31 @@
+require 'rubygems/command'
+require 'rubygems/commands/query_command'
+
+class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
+
+  def initialize
+    super 'search', 'Display all gems whose name contains STRING'
+
+    remove_option '--name-matches'
+  end
+
+  def arguments # :nodoc:
+    "STRING        fragment of gem name to search for"
+  end
+
+  def defaults_str # :nodoc:
+    "--local --no-details"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [STRING]"
+  end
+
+  def execute
+    string = get_one_optional_argument
+    options[:name] = /#{string}/i
+    super
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/server_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/server_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/server_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,70 @@
+require 'rubygems/command'
+require 'rubygems/server'
+
+class Gem::Commands::ServerCommand < Gem::Command
+
+  def initialize
+    super 'server', 'Documentation and gem repository HTTP server',
+          :port => 8808, :gemdir => Gem.dir, :daemon => false
+
+    OptionParser.accept :Port do |port|
+      if port =~ /\A\d+\z/ then
+        port = Integer port
+        raise OptionParser::InvalidArgument, "#{port}: not a port number" if
+          port > 65535
+
+        port
+      else
+        begin
+          Socket.getservbyname port
+        rescue SocketError => e
+          raise OptionParser::InvalidArgument, "#{port}: no such named service"
+        end
+      end
+    end
+
+    add_option '-p', '--port=PORT', :Port,
+               'port to listen on' do |port, options|
+      options[:port] = port
+    end
+
+    add_option '-d', '--dir=GEMDIR',
+               'directory from which to serve gems' do |gemdir, options|
+      options[:gemdir] = File.expand_path gemdir
+    end
+
+    add_option '--[no-]daemon', 'run as a daemon' do |daemon, options|
+      options[:daemon] = daemon
+    end
+  end
+
+  def defaults_str # :nodoc:
+    "--port 8808 --dir #{Gem.dir} --no-daemon"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+The server command starts up a web server that hosts the RDoc for your
+installed gems and can operate as a server for installation of gems on other
+machines.
+
+The cache files for installed gems must exist to use the server as a source
+for gem installation.
+
+To install gems from a running server, use `gem install GEMNAME --source
+http://gem_server_host:8808`
+
+You can set up a shortcut to gem server documentation using the URL:
+
+  http://localhost:8808/rdoc?q=%s - Firefox
+  http://localhost:8808/rdoc?q=* - LaunchBar
+
+    EOF
+  end
+
+  def execute
+    Gem::Server.run options
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/setup_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/setup_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/setup_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,363 @@
+require 'rubygems/command'
+require 'fileutils'
+require 'rbconfig'
+require 'tmpdir'
+require 'pathname'
+
+##
+# Installs RubyGems itself.  This command is ordinarily only available from a
+# RubyGems checkout or tarball.
+
+class Gem::Commands::SetupCommand < Gem::Command
+
+  def initialize
+    super 'setup', 'Install RubyGems',
+          :format_executable => true, :rdoc => true, :ri => true,
+          :site_or_vendor => :sitelibdir,
+          :destdir => '', :prefix => ''
+
+    add_option '--prefix=PREFIX',
+               'Prefix path for installing RubyGems',
+               'Will not affect gem repository location' do |prefix, options|
+      options[:prefix] = File.expand_path prefix
+    end
+
+    add_option '--destdir=DESTDIR',
+               'Root directory to install RubyGems into',
+               'Mainly used for packaging RubyGems' do |destdir, options|
+      options[:destdir] = File.expand_path destdir
+    end
+
+    add_option '--[no-]vendor',
+               'Install into vendorlibdir not sitelibdir',
+               '(Requires Ruby 1.8.7)' do |vendor, options|
+      if vendor and Gem.ruby_version < Gem::Version.new('1.8.7') then
+        raise OptionParser::InvalidOption,
+              "requires ruby 1.8.7+ (you have #{Gem.ruby_version})"
+      end
+
+      options[:site_or_vendor] = vendor ? :vendorlibdir : :sitelibdir
+    end
+
+    add_option '--[no-]format-executable',
+               'Makes `gem` match ruby',
+               'If ruby is ruby18, gem will be gem18' do |value, options|
+      options[:format_executable] = value
+    end
+
+    add_option '--[no-]rdoc',
+               'Generate RDoc documentation for RubyGems' do |value, options|
+      options[:rdoc] = value
+    end
+
+    add_option '--[no-]ri',
+               'Generate RI documentation for RubyGems' do |value, options|
+      options[:ri] = value
+    end
+  end
+
+  def check_ruby_version
+    required_version = Gem::Requirement.new '>= 1.8.6'
+
+    unless required_version.satisfied_by? Gem.ruby_version then
+      alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}"
+      terminate_interaction 1
+    end
+  end
+
+  def defaults_str # :nodoc:
+    "--format-executable --rdoc --ri"
+  end
+
+  def description # :nodoc:
+    <<-EOF
+Installs RubyGems itself.
+
+RubyGems installs RDoc for itself in GEM_HOME.  By default this is:
+  #{Gem.dir}
+
+If you prefer a different directory, set the GEM_HOME environment variable.
+
+RubyGems will install the gem command with a name matching ruby's
+prefix and suffix.  If ruby was installed as `ruby18`, gem will be
+installed as `gem18`.
+
+By default, this RubyGems will install gem as:
+  #{Gem.default_exec_format % 'gem'}
+    EOF
+  end
+
+  def execute
+    @verbose = Gem.configuration.really_verbose
+
+    install_destdir = options[:destdir]
+
+    unless install_destdir.empty? then
+      ENV['GEM_HOME'] ||= File.join(install_destdir,
+                                    Gem.default_dir.gsub(/^[a-zA-Z]:/, ''))
+    end
+
+    check_ruby_version
+
+    if Gem.configuration.really_verbose then
+      extend FileUtils::Verbose
+    else
+      extend FileUtils
+    end
+
+    lib_dir, bin_dir = make_destination_dirs install_destdir
+
+    install_lib lib_dir
+
+    install_executables bin_dir
+
+    remove_old_bin_files bin_dir
+
+    remove_source_caches install_destdir
+
+    say "RubyGems #{Gem::VERSION} installed"
+
+    install_rdoc
+
+    say
+    if @verbose then
+      say "-" * 78
+      say
+    end
+
+    release_notes = File.join Dir.pwd, 'History.txt'
+
+    release_notes = if File.exist? release_notes then
+                      open release_notes do |io|
+                        text = io.gets '==='
+                        text << io.gets('===')
+                        text[0...-3]
+                      end
+                    else
+                      "Oh-no! Unable to find release notes!"
+                    end
+
+    say release_notes
+
+    say
+    say "-" * 78
+    say
+
+    say "RubyGems installed the following executables:"
+    say @bin_file_names.map { |name| "\t#{name}\n" }
+    say
+
+    unless @bin_file_names.grep(/#{File::SEPARATOR}gem$/) then
+      say "If `gem` was installed by a previous RubyGems installation, you may need"
+      say "to remove it by hand."
+      say
+    end
+  end
+
+  def install_executables(bin_dir)
+    say "Installing gem executable" if @verbose
+
+    @bin_file_names = []
+
+    Dir.chdir 'bin' do
+      bin_files = Dir['*']
+
+      bin_files.delete 'update_rubygems'
+
+      bin_files.each do |bin_file|
+        bin_file_formatted = if options[:format_executable] then
+                               Gem.default_exec_format % bin_file
+                             else
+                               bin_file
+                             end
+
+        dest_file = File.join bin_dir, bin_file_formatted
+        bin_tmp_file = File.join Dir.tmpdir, bin_file
+
+        begin
+          bin = File.readlines bin_file
+          bin[0] = "#!#{Gem.ruby}\n"
+
+          File.open bin_tmp_file, 'w' do |fp|
+            fp.puts bin.join
+          end
+
+          install bin_tmp_file, dest_file, :mode => 0755
+          @bin_file_names << dest_file
+        ensure
+          rm bin_tmp_file
+        end
+
+        next unless Gem.win_platform?
+
+        begin
+          bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
+
+          File.open bin_cmd_file, 'w' do |file|
+            file.puts <<-TEXT
+ at ECHO OFF
+IF NOT "%~f0" == "~f0" GOTO :WinNT
+@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
+GOTO :EOF
+:WinNT
+@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
+TEXT
+          end
+
+          install bin_cmd_file, "#{dest_file}.bat", :mode => 0755
+        ensure
+          rm bin_cmd_file
+        end
+      end
+    end
+  end
+
+  def install_lib(lib_dir)
+    say "Installing RubyGems" if @verbose
+
+    Dir.chdir 'lib' do
+      lib_files = Dir[File.join('**', '*rb')]
+
+      lib_files.each do |lib_file|
+        dest_file = File.join lib_dir, lib_file
+        dest_dir = File.dirname dest_file
+        mkdir_p dest_dir unless File.directory? dest_dir
+
+        install lib_file, dest_file, :mode => 0644
+      end
+    end
+  end
+
+  def install_rdoc
+    gem_doc_dir = File.join Gem.dir, 'doc'
+    rubygems_name = "rubygems-#{Gem::RubyGemsVersion}"
+    rubygems_doc_dir = File.join gem_doc_dir, rubygems_name
+
+    if File.writable? gem_doc_dir and
+       (not File.exist? rubygems_doc_dir or
+        File.writable? rubygems_doc_dir) then
+      say "Removing old RubyGems RDoc and ri" if @verbose
+      Dir[File.join(Gem.dir, 'doc', 'rubygems-[0-9]*')].each do |dir|
+        rm_rf dir
+      end
+
+      if options[:ri] then
+        ri_dir = File.join rubygems_doc_dir, 'ri'
+        say "Installing #{rubygems_name} ri into #{ri_dir}" if @verbose
+        run_rdoc '--ri', '--op', ri_dir
+      end
+
+      if options[:rdoc] then
+        rdoc_dir = File.join rubygems_doc_dir, 'rdoc'
+        say "Installing #{rubygems_name} rdoc into #{rdoc_dir}" if @verbose
+        run_rdoc '--op', rdoc_dir
+      end
+    elsif @verbose then
+      say "Skipping RDoc generation, #{gem_doc_dir} not writable"
+      say "Set the GEM_HOME environment variable if you want RDoc generated"
+    end
+  end
+
+  def make_destination_dirs(install_destdir)
+    lib_dir = nil
+    bin_dir = nil
+
+    prefix = options[:prefix]
+    site_or_vendor = options[:site_or_vendor]
+
+    if prefix.empty? then
+      lib_dir = Gem::ConfigMap[site_or_vendor]
+      bin_dir = Gem::ConfigMap[:bindir]
+    else
+      # Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets
+      # confused about installation location, so switch back to
+      # sitelibdir/vendorlibdir.
+      if defined?(APPLE_GEM_HOME) and
+        # just in case Apple and RubyGems don't get this patched up proper.
+        (prefix == Gem::ConfigMap[:libdir] or
+         # this one is important
+         prefix == File.join(Gem::ConfigMap[:libdir], 'ruby')) then
+         lib_dir = Gem::ConfigMap[site_or_vendor]
+         bin_dir = Gem::ConfigMap[:bindir]
+      else
+        lib_dir = File.join prefix, 'lib'
+        bin_dir = File.join prefix, 'bin'
+      end
+    end
+
+    unless install_destdir.empty? then
+      lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '')
+      bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '')
+    end
+
+    mkdir_p lib_dir
+    mkdir_p bin_dir
+
+    return lib_dir, bin_dir
+  end
+
+  def remove_old_bin_files(bin_dir)
+    old_bin_files = {
+      'gem_mirror' => 'gem mirror',
+      'gem_server' => 'gem server',
+      'gemlock' => 'gem lock',
+      'gemri' => 'ri',
+      'gemwhich' => 'gem which',
+      'index_gem_repository.rb' => 'gem generate_index',
+    }
+
+    old_bin_files.each do |old_bin_file, new_name|
+      old_bin_path = File.join bin_dir, old_bin_file
+      next unless File.exist? old_bin_path
+
+      deprecation_message = "`#{old_bin_file}` has been deprecated.  Use `#{new_name}` instead."
+
+      File.open old_bin_path, 'w' do |fp|
+        fp.write <<-EOF
+#!#{Gem.ruby}
+
+abort "#{deprecation_message}"
+    EOF
+      end
+
+      next unless Gem.win_platform?
+
+      File.open "#{old_bin_path}.bat", 'w' do |fp|
+        fp.puts %{@ECHO.#{deprecation_message}}
+      end
+    end
+  end
+
+  def remove_source_caches(install_destdir)
+    if install_destdir.empty?
+      require 'rubygems/source_info_cache'
+
+      user_cache_file = File.join(install_destdir,
+                                  Gem::SourceInfoCache.user_cache_file)
+      system_cache_file = File.join(install_destdir,
+                                    Gem::SourceInfoCache.system_cache_file)
+
+      say "Removing old source_cache files" if Gem.configuration.really_verbose
+      rm_f user_cache_file if File.writable? File.dirname(user_cache_file)
+      rm_f system_cache_file if File.writable? File.dirname(system_cache_file)
+    end
+  end
+
+  def run_rdoc(*args)
+    begin
+      gem 'rdoc'
+    rescue Gem::LoadError
+    end
+
+    require 'rdoc/rdoc'
+
+    args << '--quiet'
+    args << '--main' << 'README'
+    args << '.' << 'README' << 'LICENSE.txt' << 'GPL.txt'
+
+    r = RDoc::RDoc.new
+    r.document args
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/sources_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/sources_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/sources_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,157 @@
+require 'fileutils'
+require 'rubygems/command'
+require 'rubygems/remote_fetcher'
+require 'rubygems/source_info_cache'
+require 'rubygems/spec_fetcher'
+require 'rubygems/local_remote_options'
+
+class Gem::Commands::SourcesCommand < Gem::Command
+
+  include Gem::LocalRemoteOptions
+
+  def initialize
+    super 'sources',
+          'Manage the sources and cache file RubyGems uses to search for gems'
+
+    add_option '-a', '--add SOURCE_URI', 'Add source' do |value, options|
+      options[:add] = value
+    end
+
+    add_option '-l', '--list', 'List sources' do |value, options|
+      options[:list] = value
+    end
+
+    add_option '-r', '--remove SOURCE_URI', 'Remove source' do |value, options|
+      options[:remove] = value
+    end
+
+    add_option '-c', '--clear-all',
+               'Remove all sources (clear the cache)' do |value, options|
+      options[:clear_all] = value
+    end
+
+    add_option '-u', '--update', 'Update source cache' do |value, options|
+      options[:update] = value
+    end
+
+    add_proxy_option
+  end
+
+  def defaults_str
+    '--list'
+  end
+
+  def execute
+    options[:list] = !(options[:add] ||
+                       options[:clear_all] ||
+                       options[:remove] ||
+                       options[:update])
+
+    if options[:clear_all] then
+      path = Gem::SpecFetcher.fetcher.dir
+      FileUtils.rm_rf path
+
+      if not File.exist?(path) then
+        say "*** Removed specs cache ***"
+      elsif not File.writable?(path) then
+        say "*** Unable to remove source cache (write protected) ***"
+      else
+        say "*** Unable to remove source cache ***"
+      end
+
+      sic = Gem::SourceInfoCache
+      remove_cache_file 'user',          sic.user_cache_file
+      remove_cache_file 'latest user',   sic.latest_user_cache_file
+      remove_cache_file 'system',        sic.system_cache_file
+      remove_cache_file 'latest system', sic.latest_system_cache_file
+    end
+
+    if options[:add] then
+      source_uri = options[:add]
+      uri = URI.parse source_uri
+
+      begin
+        Gem::SpecFetcher.fetcher.load_specs uri, 'specs'
+        Gem.sources << source_uri
+        Gem.configuration.write
+
+        say "#{source_uri} added to sources"
+      rescue URI::Error, ArgumentError
+        say "#{source_uri} is not a URI"
+      rescue Gem::RemoteFetcher::FetchError => e
+        yaml_uri = uri + 'yaml'
+        gem_repo = Gem::RemoteFetcher.fetcher.fetch_size yaml_uri rescue false
+
+        if e.uri =~ /specs\.#{Regexp.escape Gem.marshal_version}\.gz$/ and
+           gem_repo then
+
+          alert_warning <<-EOF
+RubyGems 1.2+ index not found for:
+\t#{source_uri}
+
+Will cause RubyGems to revert to legacy indexes, degrading performance.
+          EOF
+
+          say "#{source_uri} added to sources"
+        else
+          say "Error fetching #{source_uri}:\n\t#{e.message}"
+        end
+      end
+    end
+
+    if options[:remove] then
+      source_uri = options[:remove]
+
+      unless Gem.sources.include? source_uri then
+        say "source #{source_uri} not present in cache"
+      else
+        Gem.sources.delete source_uri
+        Gem.configuration.write
+
+        say "#{source_uri} removed from sources"
+      end
+    end
+
+    if options[:update] then
+      fetcher = Gem::SpecFetcher.fetcher
+
+      if fetcher.legacy_repos.empty? then
+        Gem.sources.each do |update_uri|
+          update_uri = URI.parse update_uri
+          fetcher.load_specs update_uri, 'specs'
+          fetcher.load_specs update_uri, 'latest_specs'
+        end
+      else
+        Gem::SourceInfoCache.cache true
+        Gem::SourceInfoCache.cache.flush
+      end
+
+      say "source cache successfully updated"
+    end
+
+    if options[:list] then
+      say "*** CURRENT SOURCES ***"
+      say
+
+      Gem.sources.each do |source|
+        say source
+      end
+    end
+  end
+
+  private
+
+  def remove_cache_file(desc, path)
+    FileUtils.rm_rf path
+
+    if not File.exist?(path) then
+      say "*** Removed #{desc} source cache ***"
+    elsif not File.writable?(path) then
+      say "*** Unable to remove #{desc} source cache (write protected) ***"
+    else
+      say "*** Unable to remove #{desc} source cache ***"
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/specification_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/specification_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/specification_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,124 @@
+require 'yaml'
+require 'rubygems/command'
+require 'rubygems/local_remote_options'
+require 'rubygems/version_option'
+require 'rubygems/source_info_cache'
+require 'rubygems/format'
+
+class Gem::Commands::SpecificationCommand < Gem::Command
+
+  include Gem::LocalRemoteOptions
+  include Gem::VersionOption
+
+  def initialize
+    super 'specification', 'Display gem specification (in yaml)',
+          :domain => :local, :version => Gem::Requirement.default,
+          :format => :yaml
+
+    add_version_option('examine')
+    add_platform_option
+
+    add_option('--all', 'Output specifications for all versions of',
+               'the gem') do |value, options|
+      options[:all] = true
+    end
+
+    add_option('--ruby', 'Output ruby format') do |value, options|
+      options[:format] = :ruby
+    end
+
+    add_option('--yaml', 'Output RUBY format') do |value, options|
+      options[:format] = :yaml
+    end
+
+    add_option('--marshal', 'Output Marshal format') do |value, options|
+      options[:format] = :marshal
+    end
+
+    add_local_remote_options
+  end
+
+  def arguments # :nodoc:
+    <<-ARGS
+GEMFILE       name of gem to show the gemspec for
+FIELD         name of gemspec field to show
+    ARGS
+  end
+
+  def defaults_str # :nodoc:
+    "--local --version '#{Gem::Requirement.default}' --yaml"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} [GEMFILE] [FIELD]"
+  end
+
+  def execute
+    specs = []
+    gem = options[:args].shift
+
+    unless gem then
+      raise Gem::CommandLineError,
+            "Please specify a gem name or file on the command line"
+    end
+
+    dep = Gem::Dependency.new gem, options[:version]
+
+    field = get_one_optional_argument
+
+    if field then
+      field = field.intern
+
+      if options[:format] == :ruby then
+        raise Gem::CommandLineError, "--ruby and FIELD are mutually exclusive"
+      end
+
+      unless Gem::Specification.attribute_names.include? field then
+        raise Gem::CommandLineError,
+              "no field %p on Gem::Specification" % field.to_s
+      end
+    end
+
+    if local? then
+      if File.exist? gem then
+        specs << Gem::Format.from_file_by_path(gem).spec rescue nil
+      end
+
+      if specs.empty? then
+        specs.push(*Gem.source_index.search(dep))
+      end
+    end
+
+    if remote? then
+      found = Gem::SpecFetcher.fetcher.fetch dep
+
+      specs.push(*found.map { |spec,| spec })
+    end
+
+    if specs.empty? then
+      alert_error "Unknown gem '#{gem}'"
+      terminate_interaction 1
+    end
+
+    output = lambda do |s|
+      s = s.send field if field
+
+      say case options[:format]
+          when :ruby then s.to_ruby
+          when :marshal then Marshal.dump s
+          else s.to_yaml
+          end
+
+      say "\n"
+    end
+
+    if options[:all] then
+      specs.each(&output)
+    else
+      spec = specs.sort_by { |s| s.version }.last
+      output[spec]
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/stale_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/stale_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/stale_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,27 @@
+require 'rubygems/command'
+
+class Gem::Commands::StaleCommand < Gem::Command
+  def initialize
+    super('stale', 'List gems along with access times')
+  end
+
+  def usage # :nodoc:
+    "#{program_name}"
+  end
+
+  def execute
+    gem_to_atime = {}
+    Gem.source_index.each do |name, spec|
+      Dir["#{spec.full_gem_path}/**/*.*"].each do |file|
+        next if File.directory?(file)
+        stat = File.stat(file)
+        gem_to_atime[name] ||= stat.atime
+        gem_to_atime[name] = stat.atime if gem_to_atime[name] < stat.atime
+      end
+    end
+
+    gem_to_atime.sort_by { |_, atime| atime }.each do |name, atime|
+      say "#{name} at #{atime.strftime '%c'}"
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/uninstall_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/uninstall_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/uninstall_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,83 @@
+require 'rubygems/command'
+require 'rubygems/version_option'
+require 'rubygems/uninstaller'
+
+##
+# Gem uninstaller command line tool
+#
+# See `gem help uninstall`
+
+class Gem::Commands::UninstallCommand < Gem::Command
+
+  include Gem::VersionOption
+
+  def initialize
+    super 'uninstall', 'Uninstall gems from the local repository',
+          :version => Gem::Requirement.default, :user_install => true
+
+    add_option('-a', '--[no-]all',
+      'Uninstall all matching versions'
+      ) do |value, options|
+      options[:all] = value
+    end
+
+    add_option('-I', '--[no-]ignore-dependencies',
+               'Ignore dependency requirements while',
+               'uninstalling') do |value, options|
+      options[:ignore] = value
+    end
+
+    add_option('-x', '--[no-]executables',
+                 'Uninstall applicable executables without',
+                 'confirmation') do |value, options|
+      options[:executables] = value
+    end
+
+    add_option('-i', '--install-dir DIR',
+               'Directory to uninstall gem from') do |value, options|
+      options[:install_dir] = File.expand_path(value)
+    end
+
+    add_option('-n', '--bindir DIR',
+               'Directory to remove binaries from') do |value, options|
+      options[:bin_dir] = File.expand_path(value)
+    end
+
+    add_option('--[no-]user-install',
+               'Uninstall from user\'s home directory',
+               'in addition to GEM_HOME.') do |value, options|
+      options[:user_install] = value
+    end
+
+    add_version_option
+    add_platform_option
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to uninstall"
+  end
+
+  def defaults_str # :nodoc:
+    "--version '#{Gem::Requirement.default}' --no-force " \
+    "--install-dir #{Gem.dir}\n" \
+    "--user-install"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME [GEMNAME ...]"
+  end
+
+  def execute
+    get_all_gem_names.each do |gem_name|
+      begin
+        Gem::Uninstaller.new(gem_name, options).uninstall
+      rescue Gem::GemNotInHomeException => e
+        spec = e.spec
+        alert("In order to remove #{spec.name}, please execute:\n" \
+              "\tgem uninstall #{spec.name} --install-dir=#{spec.installation_path}")
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/unpack_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/unpack_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/unpack_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,97 @@
+require 'fileutils'
+require 'rubygems/command'
+require 'rubygems/installer'
+require 'rubygems/version_option'
+
+class Gem::Commands::UnpackCommand < Gem::Command
+
+  include Gem::VersionOption
+
+  def initialize
+    super 'unpack', 'Unpack an installed gem to the current directory',
+          :version => Gem::Requirement.default,
+          :target  => Dir.pwd
+
+    add_option('--target=DIR', 'target directory for unpacking') do |value, options|
+      options[:target] = value
+    end
+
+    add_version_option
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to unpack"
+  end
+
+  def defaults_str # :nodoc:
+    "--version '#{Gem::Requirement.default}'"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME"
+  end
+
+  #--
+  # TODO: allow, e.g., 'gem unpack rake-0.3.1'.  Find a general solution for
+  # this, so that it works for uninstall as well.  (And check other commands
+  # at the same time.)
+
+  def execute
+    get_all_gem_names.each do |name|
+      path = get_path name, options[:version]
+
+      if path then
+        basename = File.basename(path).sub(/\.gem$/, '')
+        target_dir = File.expand_path File.join(options[:target], basename)
+        FileUtils.mkdir_p target_dir
+        Gem::Installer.new(path, :unpack => true).unpack target_dir
+        say "Unpacked gem: '#{target_dir}'"
+      else
+        alert_error "Gem '#{name}' not installed."
+      end
+    end
+  end
+
+  # Return the full path to the cached gem file matching the given
+  # name and version requirement.  Returns 'nil' if no match.
+  #
+  # Example:
+  #
+  #   get_path('rake', '> 0.4')   # -> '/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem'
+  #   get_path('rake', '< 0.1')   # -> nil
+  #   get_path('rak')             # -> nil (exact name required)
+  #--
+  # TODO: This should be refactored so that it's a general service. I don't
+  # think any of our existing classes are the right place though.  Just maybe
+  # 'Cache'?
+  #
+  # TODO: It just uses Gem.dir for now.  What's an easy way to get the list of
+  # source directories?
+  def get_path(gemname, version_req)
+    return gemname if gemname =~ /\.gem$/i
+
+    specs = Gem::source_index.find_name gemname, version_req
+
+    selected = specs.sort_by { |s| s.version }.last
+
+    return nil if selected.nil?
+
+    # We expect to find (basename).gem in the 'cache' directory.
+    # Furthermore, the name match must be exact (ignoring case).
+    if gemname =~ /^#{selected.name}$/i
+      filename = selected.file_name
+      path = nil
+
+      Gem.path.find do |gem_dir|
+        path = File.join gem_dir, 'cache', filename
+        File.exist? path
+      end
+
+      path
+    else
+      nil
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/update_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/update_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/update_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,202 @@
+require 'rubygems/command'
+require 'rubygems/command_manager'
+require 'rubygems/install_update_options'
+require 'rubygems/local_remote_options'
+require 'rubygems/spec_fetcher'
+require 'rubygems/version_option'
+require 'rubygems/commands/install_command'
+
+class Gem::Commands::UpdateCommand < Gem::Command
+
+  include Gem::InstallUpdateOptions
+  include Gem::LocalRemoteOptions
+  include Gem::VersionOption
+
+  def initialize
+    super 'update',
+          'Update the named gems (or all installed gems) in the local repository',
+      :generate_rdoc => true,
+      :generate_ri   => true,
+      :force         => false,
+      :test          => false
+
+    add_install_update_options
+
+    add_option('--system',
+               'Update the RubyGems system software') do |value, options|
+      options[:system] = value
+    end
+
+    add_local_remote_options
+
+    add_platform_option
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to update"
+  end
+
+  def defaults_str # :nodoc:
+    "--rdoc --ri --no-force --no-test --install-dir #{Gem.dir}"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME [GEMNAME ...]"
+  end
+
+  def execute
+    hig = {}
+
+    if options[:system] then
+      say "Updating RubyGems"
+
+      unless options[:args].empty? then
+        raise "No gem names are allowed with the --system option"
+      end
+
+      rubygems_update = Gem::Specification.new
+      rubygems_update.name = 'rubygems-update'
+      rubygems_update.version = Gem::Version.new Gem::RubyGemsVersion
+      hig['rubygems-update'] = rubygems_update
+
+      options[:user_install] = false
+    else
+      say "Updating installed gems"
+
+      hig = {} # highest installed gems
+
+      Gem.source_index.each do |name, spec|
+        if hig[spec.name].nil? or hig[spec.name].version < spec.version then
+          hig[spec.name] = spec
+        end
+      end
+    end
+
+    gems_to_update = which_to_update hig, options[:args]
+
+    updated = []
+
+    installer = Gem::DependencyInstaller.new options
+
+    gems_to_update.uniq.sort.each do |name|
+      next if updated.any? { |spec| spec.name == name }
+      success = false
+
+      say "Updating #{name}"
+      begin
+        installer.install name
+        success = true
+      rescue Gem::InstallError => e
+        alert_error "Error installing #{name}:\n\t#{e.message}"
+        success = false
+      end
+
+      installer.installed_gems.each do |spec|
+        updated << spec
+        say "Successfully installed #{spec.full_name}" if success
+      end
+    end
+
+    if gems_to_update.include? "rubygems-update" then
+      Gem.source_index.refresh!
+
+      update_gems = Gem.source_index.find_name 'rubygems-update'
+
+      latest_update_gem = update_gems.sort_by { |s| s.version }.last
+
+      say "Updating RubyGems to #{latest_update_gem.version}"
+      installed = do_rubygems_update latest_update_gem.version
+
+      say "RubyGems system software updated" if installed
+    else
+      if updated.empty? then
+        say "Nothing to update"
+      else
+        say "Gems updated: #{updated.map { |spec| spec.name }.join ', '}"
+
+        if options[:generate_ri] then
+          updated.each do |gem|
+            Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri
+          end
+
+          Gem::DocManager.update_ri_cache
+        end
+
+        if options[:generate_rdoc] then
+          updated.each do |gem|
+            Gem::DocManager.new(gem, options[:rdoc_args]).generate_rdoc
+          end
+        end
+      end
+    end
+  end
+
+  ##
+  # Update the RubyGems software to +version+.
+
+  def do_rubygems_update(version)
+    args = []
+    args.push '--prefix', Gem.prefix unless Gem.prefix.nil?
+    args << '--no-rdoc' unless options[:generate_rdoc]
+    args << '--no-ri' unless options[:generate_ri]
+    args << '--no-format-executable' if options[:no_format_executable]
+
+    update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"
+
+    Dir.chdir update_dir do
+      say "Installing RubyGems #{version}"
+      setup_cmd = "#{Gem.ruby} setup.rb #{args.join ' '}"
+
+      # Make sure old rubygems isn't loaded
+      old = ENV["RUBYOPT"]
+      ENV.delete("RUBYOPT")
+      system setup_cmd
+      ENV["RUBYOPT"] = old if old
+    end
+  end
+
+  def which_to_update(highest_installed_gems, gem_names)
+    result = []
+
+    highest_installed_gems.each do |l_name, l_spec|
+      next if not gem_names.empty? and
+              gem_names.all? { |name| /#{name}/ !~ l_spec.name }
+
+      dependency = Gem::Dependency.new l_spec.name, "> #{l_spec.version}"
+
+      begin
+        fetcher = Gem::SpecFetcher.fetcher
+        spec_tuples = fetcher.find_matching dependency
+      rescue Gem::RemoteFetcher::FetchError => e
+        raise unless fetcher.warn_legacy e do
+          require 'rubygems/source_info_cache'
+
+          dependency.name = '' if dependency.name == //
+
+          specs = Gem::SourceInfoCache.search_with_source dependency
+
+          spec_tuples = specs.map do |spec, source_uri|
+            [[spec.name, spec.version, spec.original_platform], source_uri]
+          end
+        end
+      end
+
+      matching_gems = spec_tuples.select do |(name, version, platform),|
+        name == l_name and Gem::Platform.match platform
+      end
+
+      highest_remote_gem = matching_gems.sort_by do |(name, version),|
+        version
+      end.last
+
+      if highest_remote_gem and
+         l_spec.version < highest_remote_gem.first[1] then
+        result << l_name
+      end
+    end
+
+    result
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/which_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/which_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/commands/which_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,87 @@
+require 'rubygems/command'
+require 'rubygems/gem_path_searcher'
+
+class Gem::Commands::WhichCommand < Gem::Command
+
+  EXT = %w[.rb .rbw .so .dll .bundle] # HACK
+
+  def initialize
+    super 'which', 'Find the location of a library file you can require',
+          :search_gems_first => false, :show_all => false
+
+    add_option '-a', '--[no-]all', 'show all matching files' do |show_all, options|
+      options[:show_all] = show_all
+    end
+
+    add_option '-g', '--[no-]gems-first',
+               'search gems before non-gems' do |gems_first, options|
+      options[:search_gems_first] = gems_first
+    end
+  end
+
+  def arguments # :nodoc:
+    "FILE          name of file to find"
+  end
+
+  def defaults_str # :nodoc:
+    "--no-gems-first --no-all"
+  end
+
+  def usage # :nodoc:
+    "#{program_name} FILE [FILE ...]"
+  end
+
+  def execute
+    searcher = Gem::GemPathSearcher.new
+
+    options[:args].each do |arg|
+      dirs = $LOAD_PATH
+      spec = searcher.find arg
+
+      if spec then
+        if options[:search_gems_first] then
+          dirs = gem_paths(spec) + $LOAD_PATH
+        else
+          dirs = $LOAD_PATH + gem_paths(spec)
+        end
+
+        say "(checking gem #{spec.full_name} for #{arg})" if
+          Gem.configuration.verbose and $stdout.tty?
+      end
+
+      paths = find_paths arg, dirs
+
+      if paths.empty? then
+        say "Can't find ruby library file or shared library #{arg}"
+      else
+        say paths
+      end
+    end
+  end
+
+  def find_paths(package_name, dirs)
+    result = []
+
+    dirs.each do |dir|
+      EXT.each do |ext|
+        full_path = File.join dir, "#{package_name}#{ext}"
+        if File.exist? full_path then
+          result << full_path
+          return result unless options[:show_all]
+        end
+      end
+    end
+
+    result
+  end
+
+  def gem_paths(spec)
+    spec.require_paths.collect { |d| File.join spec.full_gem_path, d }
+  end
+
+  def usage # :nodoc:
+    "#{program_name} FILE [...]"
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/config_file.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/config_file.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/config_file.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,272 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'yaml'
+
+# Store the gem command options specified in the configuration file.  The
+# config file object acts much like a hash.
+
+class Gem::ConfigFile
+
+  DEFAULT_BACKTRACE = false
+  DEFAULT_BENCHMARK = false
+  DEFAULT_BULK_THRESHOLD = 1000
+  DEFAULT_VERBOSITY = true
+  DEFAULT_UPDATE_SOURCES = true
+
+  ##
+  # For Ruby packagers to set configuration defaults.  Set in
+  # rubygems/defaults/operating_system.rb
+
+  OPERATING_SYSTEM_DEFAULTS = {}
+
+  ##
+  # For Ruby implementers to set configuration defaults.  Set in
+  # rubygems/defaults/#{RUBY_ENGINE}.rb
+
+  PLATFORM_DEFAULTS = {}
+
+  system_config_path =
+    begin
+      require 'Win32API'
+
+      CSIDL_COMMON_APPDATA = 0x0023
+      path = 0.chr * 260
+      if RUBY_VERSION > '1.9' then
+        SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'PLPLP',
+                                       'L', :stdcall
+        SHGetFolderPath.call nil, CSIDL_COMMON_APPDATA, nil, 1, path
+      else
+        SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'LLLLP',
+                                       'L'
+        SHGetFolderPath.call 0, CSIDL_COMMON_APPDATA, 0, 1, path
+      end
+
+      path.strip
+    rescue LoadError
+      '/etc'
+    end
+
+  SYSTEM_WIDE_CONFIG_FILE = File.join system_config_path, 'gemrc'
+
+  # List of arguments supplied to the config file object.
+  attr_reader :args
+
+  # Where to look for gems
+  attr_accessor :path
+
+  attr_accessor :home
+
+  # True if we print backtraces on errors.
+  attr_writer :backtrace
+
+  # True if we are benchmarking this run.
+  attr_accessor :benchmark
+
+  # Bulk threshold value.  If the number of missing gems are above
+  # this threshold value, then a bulk download technique is used.
+  attr_accessor :bulk_threshold
+
+  # Verbose level of output:
+  # * false -- No output
+  # * true -- Normal output
+  # * :loud -- Extra output
+  attr_accessor :verbose
+
+  # True if we want to update the SourceInfoCache every time, false otherwise
+  attr_accessor :update_sources
+
+  # Create the config file object.  +args+ is the list of arguments
+  # from the command line.
+  #
+  # The following command line options are handled early here rather
+  # than later at the time most command options are processed.
+  #
+  # * --config-file and --config-file==NAME -- Obviously these need
+  #   to be handled by the ConfigFile object to ensure we get the
+  #   right config file.
+  #
+  # * --backtrace -- Backtrace needs to be turned on early so that
+  #   errors before normal option parsing can be properly handled.
+  #
+  # * --debug -- Enable Ruby level debug messages.  Handled early
+  #   for the same reason as --backtrace.
+  #
+  def initialize(arg_list)
+    @config_file_name = nil
+    need_config_file_name = false
+
+    arg_list = arg_list.map do |arg|
+      if need_config_file_name then
+        @config_file_name = arg
+        need_config_file_name = false
+        nil
+      elsif arg =~ /^--config-file=(.*)/ then
+        @config_file_name = $1
+        nil
+      elsif arg =~ /^--config-file$/ then
+        need_config_file_name = true
+        nil
+      else
+        arg
+      end
+    end.compact
+
+    @backtrace = DEFAULT_BACKTRACE
+    @benchmark = DEFAULT_BENCHMARK
+    @bulk_threshold = DEFAULT_BULK_THRESHOLD
+    @verbose = DEFAULT_VERBOSITY
+    @update_sources = DEFAULT_UPDATE_SOURCES
+
+    operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
+    platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
+    system_config = load_file SYSTEM_WIDE_CONFIG_FILE
+    user_config = load_file config_file_name.dup.untaint
+
+    @hash = operating_system_config.merge platform_config
+    @hash = @hash.merge system_config
+    @hash = @hash.merge user_config
+
+    # HACK these override command-line args, which is bad
+    @backtrace = @hash[:backtrace] if @hash.key? :backtrace
+    @benchmark = @hash[:benchmark] if @hash.key? :benchmark
+    @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold
+    Gem.sources = @hash[:sources] if @hash.key? :sources
+    @verbose = @hash[:verbose] if @hash.key? :verbose
+    @update_sources = @hash[:update_sources] if @hash.key? :update_sources
+    @path = @hash[:gempath] if @hash.key? :gempath
+    @home = @hash[:gemhome] if @hash.key? :gemhome
+
+    handle_arguments arg_list
+  end
+
+  def load_file(filename)
+    begin
+      YAML.load(File.read(filename)) if filename and File.exist?(filename)
+    rescue ArgumentError
+      warn "Failed to load #{config_file_name}"
+    rescue Errno::EACCES
+      warn "Failed to load #{config_file_name} due to permissions problem."
+    end or {}
+  end
+
+  # True if the backtrace option has been specified, or debug is on.
+  def backtrace
+    @backtrace or $DEBUG
+  end
+
+  # The name of the configuration file.
+  def config_file_name
+    @config_file_name || Gem.config_file
+  end
+
+  # Delegates to @hash
+  def each(&block)
+    hash = @hash.dup
+    hash.delete :update_sources
+    hash.delete :verbose
+    hash.delete :benchmark
+    hash.delete :backtrace
+    hash.delete :bulk_threshold
+
+    yield :update_sources, @update_sources
+    yield :verbose, @verbose
+    yield :benchmark, @benchmark
+    yield :backtrace, @backtrace
+    yield :bulk_threshold, @bulk_threshold
+
+    yield 'config_file_name', @config_file_name if @config_file_name
+
+    hash.each(&block)
+  end
+
+  # Handle the command arguments.
+  def handle_arguments(arg_list)
+    @args = []
+
+    arg_list.each do |arg|
+      case arg
+      when /^--(backtrace|traceback)$/ then
+        @backtrace = true
+      when /^--bench(mark)?$/ then
+        @benchmark = true
+      when /^--debug$/ then
+        $DEBUG = true
+      else
+        @args << arg
+      end
+    end
+  end
+
+  # Really verbose mode gives you extra output.
+  def really_verbose
+    case verbose
+    when true, false, nil then false
+    else true
+    end
+  end
+
+  # to_yaml only overwrites things you can't override on the command line.
+  def to_yaml # :nodoc:
+    yaml_hash = {}
+    yaml_hash[:backtrace] = @hash.key?(:backtrace) ? @hash[:backtrace] :
+      DEFAULT_BACKTRACE
+    yaml_hash[:benchmark] = @hash.key?(:benchmark) ? @hash[:benchmark] :
+      DEFAULT_BENCHMARK
+    yaml_hash[:bulk_threshold] = @hash.key?(:bulk_threshold) ?
+      @hash[:bulk_threshold] : DEFAULT_BULK_THRESHOLD
+    yaml_hash[:sources] = Gem.sources
+    yaml_hash[:update_sources] = @hash.key?(:update_sources) ?
+      @hash[:update_sources] : DEFAULT_UPDATE_SOURCES
+    yaml_hash[:verbose] = @hash.key?(:verbose) ? @hash[:verbose] :
+      DEFAULT_VERBOSITY
+
+    keys = yaml_hash.keys.map { |key| key.to_s }
+    keys << 'debug'
+    re = Regexp.union(*keys)
+
+    @hash.each do |key, value|
+      key = key.to_s
+      next if key =~ re
+      yaml_hash[key.to_s] = value
+    end
+
+    yaml_hash.to_yaml
+  end
+
+  # Writes out this config file, replacing its source.
+  def write
+    File.open config_file_name, 'w' do |fp|
+      fp.write self.to_yaml
+    end
+  end
+
+  # Return the configuration information for +key+.
+  def [](key)
+    @hash[key.to_s]
+  end
+
+  # Set configuration option +key+ to +value+.
+  def []=(key, value)
+    @hash[key.to_s] = value
+  end
+
+  def ==(other) # :nodoc:
+    self.class === other and
+    @backtrace == other.backtrace and
+    @benchmark == other.benchmark and
+    @bulk_threshold == other.bulk_threshold and
+    @verbose == other.verbose and
+    @update_sources == other.update_sources and
+    @hash == other.hash
+  end
+
+  protected
+
+  attr_reader :hash
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/custom_require.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/custom_require.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/custom_require.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,46 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+
+module Kernel
+
+  ##
+  # The Kernel#require from before RubyGems was loaded.
+
+  alias gem_original_require require
+
+  ##
+  # When RubyGems is required, Kernel#require is replaced with our own which
+  # is capable of loading gems on demand.
+  #
+  # When you call <tt>require 'x'</tt>, this is what happens:
+  # * If the file can be loaded from the existing Ruby loadpath, it
+  #   is.
+  # * Otherwise, installed gems are searched for a file that matches.
+  #   If it's found in gem 'y', that gem is activated (added to the
+  #   loadpath).
+  #
+  # The normal <tt>require</tt> functionality of returning false if
+  # that file has already been loaded is preserved.
+
+  def require(path) # :doc:
+    gem_original_require path
+  rescue LoadError => load_error
+    if load_error.message =~ /#{Regexp.escape path}\z/ and
+       spec = Gem.searcher.find(path) then
+      Gem.activate(spec.name, "= #{spec.version}")
+      gem_original_require path
+    else
+      raise load_error
+    end
+  end
+
+  private :require
+  private :gem_original_require
+
+end
+


Property changes on: MacRuby/trunk/test/libs/rubygems/lib/rubygems/custom_require.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/defaults.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/defaults.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/defaults.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,103 @@
+module Gem
+
+  @post_install_hooks   ||= []
+  @post_uninstall_hooks ||= []
+  @pre_uninstall_hooks  ||= []
+  @pre_install_hooks    ||= []
+
+  ##
+  # An Array of the default sources that come with RubyGems
+
+  def self.default_sources
+    %w[http://gems.rubyforge.org/]
+  end
+
+  ##
+  # Default home directory path to be used if an alternate value is not
+  # specified in the environment
+
+  def self.default_dir
+    if defined? RUBY_FRAMEWORK_VERSION then
+      File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
+                ConfigMap[:ruby_version]
+    # 1.9.2dev reverted to 1.8 style path
+    elsif RUBY_VERSION > '1.9' and RUBY_VERSION < '1.9.2' then
+      File.join(ConfigMap[:libdir], ConfigMap[:ruby_install_name], 'gems',
+                ConfigMap[:ruby_version])
+    else
+      File.join(ConfigMap[:libdir], ruby_engine, 'gems',
+                ConfigMap[:ruby_version])
+    end
+  end
+
+  ##
+  # Path for gems in the user's home directory
+
+  def self.user_dir
+    File.join(Gem.user_home, '.gem', ruby_engine,
+              ConfigMap[:ruby_version])
+  end
+
+  ##
+  # Default gem load path
+
+  def self.default_path
+    if File.exist?(Gem.user_home)
+      [user_dir, default_dir]
+    else
+      [default_dir]
+    end
+  end
+
+  ##
+  # Deduce Ruby's --program-prefix and --program-suffix from its install name
+
+  def self.default_exec_format
+    exec_format = ConfigMap[:ruby_install_name].sub('ruby', '%s') rescue '%s'
+
+    unless exec_format =~ /%s/ then
+      raise Gem::Exception,
+        "[BUG] invalid exec_format #{exec_format.inspect}, no %s"
+    end
+
+    exec_format
+  end
+
+  ##
+  # The default directory for binaries
+
+  def self.default_bindir
+    if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
+      '/usr/bin'
+    else # generic install
+      ConfigMap[:bindir]
+    end
+  end
+
+  ##
+  # The default system-wide source info cache directory
+
+  def self.default_system_source_cache_dir
+    File.join Gem.dir, 'source_cache'
+  end
+
+  ##
+  # The default user-specific source info cache directory
+
+  def self.default_user_source_cache_dir
+    File.join Gem.user_home, '.gem', 'source_cache'
+  end
+
+  ##
+  # A wrapper around RUBY_ENGINE const that may not be defined
+
+  def self.ruby_engine
+    if defined? RUBY_ENGINE then
+      RUBY_ENGINE
+    else
+      'ruby'
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,149 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+##
+# The Dependency class holds a Gem name and a Gem::Requirement
+
+class Gem::Dependency
+
+  ##
+  # Valid dependency types.
+  #--
+  # When this list is updated, be sure to change
+  # Gem::Specification::CURRENT_SPECIFICATION_VERSION as well.
+
+  TYPES = [
+    :development,
+    :runtime,
+  ]
+
+  ##
+  # Dependency name or regular expression.
+
+  attr_accessor :name
+
+  ##
+  # Dependency type.
+
+  attr_reader :type
+
+  ##
+  # Dependent versions.
+
+  attr_writer :version_requirements
+
+  ##
+  # Orders dependencies by name only.
+
+  def <=>(other)
+    [@name] <=> [other.name]
+  end
+
+  ##
+  # Constructs a dependency with +name+ and +requirements+.
+
+  def initialize(name, version_requirements, type=:runtime)
+    @name = name
+
+    unless TYPES.include? type
+      raise ArgumentError, "Valid types are #{TYPES.inspect}, not #{@type.inspect}"
+    end
+
+    @type = type
+
+    @version_requirements = Gem::Requirement.create version_requirements
+    @version_requirement = nil   # Avoid warnings.
+  end
+
+  def version_requirements
+    normalize if defined? @version_requirement and @version_requirement
+    @version_requirements
+  end
+
+  def requirement_list
+    version_requirements.as_list
+  end
+
+  alias requirements_list requirement_list
+
+  def normalize
+    # TODO: sad panda is sad
+    ver = @version_requirement.instance_variable_get :@version
+    @version_requirements = Gem::Requirement.new([ver])
+    @version_requirement = nil
+  end
+
+  def to_s # :nodoc:
+    "#{name} (#{version_requirements}, #{@type || :runtime})"
+  end
+
+  def pretty_print(q) # :nodoc:
+    q.group 1, 'Gem::Dependency.new(', ')' do
+      q.pp @name
+      q.text ','
+      q.breakable
+
+      q.pp @version_requirements
+
+      q.text ','
+      q.breakable
+
+      q.pp @type
+    end
+  end
+
+  def ==(other) # :nodoc:
+    self.class === other &&
+      self.name == other.name &&
+      self.type == other.type &&
+      self.version_requirements == other.version_requirements
+  end
+
+  ##
+  # Uses this dependency as a pattern to compare to +other+.  This dependency
+  # will match if the name matches the other's name, and other has only an
+  # equal version requirement that satisfies this dependency.
+
+  def =~(other)
+    other = if self.class === other then
+              other
+            else
+              return false unless other.respond_to? :name and
+                                  other.respond_to? :version
+
+              Gem::Dependency.new other.name, other.version
+            end
+
+    pattern = @name
+    pattern = /\A#{Regexp.escape @name}\Z/ unless Regexp === pattern
+
+    return false unless pattern =~ other.name
+
+    reqs = other.version_requirements.requirements
+
+    return false unless reqs.length == 1
+    return false unless reqs.first.first == '='
+
+    version = reqs.first.last
+
+    version_requirements.satisfied_by? version
+  end
+
+  ##
+  # A dependency's hash is the sum of the hash of the #name, #type and
+  # #version_requirements
+
+  def hash
+    name.hash + type.hash + version_requirements.hash
+  end
+
+  def inspect # :nodoc:
+    "<%s type=%p name=%p requirements=%p>" % [self.class, @type, @name,
+      version_requirements.to_s]
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_installer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_installer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_installer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,261 @@
+require 'rubygems'
+require 'rubygems/dependency_list'
+require 'rubygems/installer'
+require 'rubygems/spec_fetcher'
+require 'rubygems/user_interaction'
+
+##
+# Installs a gem along with all its dependencies from local and remote gems.
+
+class Gem::DependencyInstaller
+
+  include Gem::UserInteraction
+
+  attr_reader :gems_to_install
+  attr_reader :installed_gems
+
+  DEFAULT_OPTIONS = {
+    :env_shebang => false,
+    :domain => :both, # HACK dup
+    :force => false,
+    :format_executable => false, # HACK dup
+    :ignore_dependencies => false,
+    :prerelease => false,
+    :security_policy => nil, # HACK NoSecurity requires OpenSSL.  AlmostNo? Low?
+    :wrappers => true,
+  }
+
+  ##
+  # Creates a new installer instance.
+  #
+  # Options are:
+  # :cache_dir:: Alternate repository path to store .gem files in.
+  # :domain:: :local, :remote, or :both.  :local only searches gems in the
+  #           current directory.  :remote searches only gems in Gem::sources.
+  #           :both searches both.
+  # :env_shebang:: See Gem::Installer::new.
+  # :force:: See Gem::Installer#install.
+  # :format_executable:: See Gem::Installer#initialize.
+  # :ignore_dependencies:: Don't install any dependencies.
+  # :install_dir:: See Gem::Installer#install.
+  # :prerelease:: Allow prerelease versions
+  # :security_policy:: See Gem::Installer::new and Gem::Security.
+  # :user_install:: See Gem::Installer.new
+  # :wrappers:: See Gem::Installer::new
+
+  def initialize(options = {})
+    if options[:install_dir] then
+      spec_dir = options[:install_dir], 'specifications'
+      @source_index = Gem::SourceIndex.from_gems_in spec_dir
+    else
+      @source_index = Gem.source_index
+    end
+
+    options = DEFAULT_OPTIONS.merge options
+
+    @bin_dir = options[:bin_dir]
+    @development = options[:development]
+    @domain = options[:domain]
+    @env_shebang = options[:env_shebang]
+    @force = options[:force]
+    @format_executable = options[:format_executable]
+    @ignore_dependencies = options[:ignore_dependencies]
+    @prerelease = options[:prerelease]
+    @security_policy = options[:security_policy]
+    @user_install = options[:user_install]
+    @wrappers = options[:wrappers]
+
+    @installed_gems = []
+
+    @install_dir = options[:install_dir] || Gem.dir
+    @cache_dir = options[:cache_dir] || @install_dir
+  end
+
+  ##
+  # Returns a list of pairs of gemspecs and source_uris that match
+  # Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources)
+  # sources.  Gems are sorted with newer gems prefered over older gems, and
+  # local gems preferred over remote gems.
+
+  def find_gems_with_sources(dep)
+    gems_and_sources = []
+
+    if @domain == :both or @domain == :local then
+      Dir[File.join(Dir.pwd, "#{dep.name}-[0-9]*.gem")].each do |gem_file|
+        spec = Gem::Format.from_file_by_path(gem_file).spec
+        gems_and_sources << [spec, gem_file] if spec.name == dep.name
+      end
+    end
+
+    if @domain == :both or @domain == :remote then
+      begin
+        requirements = dep.version_requirements.requirements.map do |req, ver|
+          req
+        end
+
+        all = !@prerelease && (requirements.length > 1 ||
+                (requirements.first != ">=" and requirements.first != ">"))
+
+        found = Gem::SpecFetcher.fetcher.fetch dep, all, true, @prerelease
+        gems_and_sources.push(*found)
+
+      rescue Gem::RemoteFetcher::FetchError => e
+        if Gem.configuration.really_verbose then
+          say "Error fetching remote data:\t\t#{e.message}"
+          say "Falling back to local-only install"
+        end
+        @domain = :local
+      end
+    end
+
+    gems_and_sources.sort_by do |gem, source|
+      [gem, source =~ /^http:\/\// ? 0 : 1] # local gems win
+    end
+  end
+
+  ##
+  # Gathers all dependencies necessary for the installation from local and
+  # remote sources unless the ignore_dependencies was given.
+
+  def gather_dependencies
+    specs = @specs_and_sources.map { |spec,_| spec }
+
+    dependency_list = Gem::DependencyList.new
+    dependency_list.add(*specs)
+
+    unless @ignore_dependencies then
+      to_do = specs.dup
+      seen = {}
+
+      until to_do.empty? do
+        spec = to_do.shift
+        next if spec.nil? or seen[spec.name]
+        seen[spec.name] = true
+
+        deps = spec.runtime_dependencies
+        deps |= spec.development_dependencies if @development
+
+        deps.each do |dep|
+          results = find_gems_with_sources(dep).reverse
+
+          results.reject! do |dep_spec,|
+            to_do.push dep_spec
+
+            @source_index.any? do |_, installed_spec|
+              dep.name == installed_spec.name and
+                dep.version_requirements.satisfied_by? installed_spec.version
+            end
+          end
+
+          results.each do |dep_spec, source_uri|
+            next if seen[dep_spec.name]
+            @specs_and_sources << [dep_spec, source_uri]
+            dependency_list.add dep_spec
+          end
+        end
+      end
+    end
+
+    @gems_to_install = dependency_list.dependency_order.reverse
+  end
+
+  ##
+  # Finds a spec and the source_uri it came from for gem +gem_name+ and
+  # +version+.  Returns an Array of specs and sources required for
+  # installation of the gem.
+
+  def find_spec_by_name_and_version gem_name, version = Gem::Requirement.default
+    spec_and_source = nil
+
+    glob = if File::ALT_SEPARATOR then
+             gem_name.gsub File::ALT_SEPARATOR, File::SEPARATOR
+           else
+             gem_name
+           end
+
+    local_gems = Dir["#{glob}*"].sort.reverse
+
+    unless local_gems.empty? then
+      local_gems.each do |gem_file|
+        next unless gem_file =~ /gem$/
+        begin
+          spec = Gem::Format.from_file_by_path(gem_file).spec
+          spec_and_source = [spec, gem_file]
+          break
+        rescue SystemCallError, Gem::Package::FormatError
+        end
+      end
+    end
+
+    if spec_and_source.nil? then
+      dep = Gem::Dependency.new gem_name, version
+      spec_and_sources = find_gems_with_sources(dep).reverse
+
+      spec_and_source = spec_and_sources.find { |spec, source|
+        Gem::Platform.match spec.platform
+      }
+    end
+
+    if spec_and_source.nil? then
+      raise Gem::GemNotFoundException,
+        "could not find gem #{gem_name} locally or in a repository"
+    end
+
+    @specs_and_sources = [spec_and_source]
+  end
+
+  ##
+  # Installs the gem and all its dependencies.  Returns an Array of installed
+  # gems specifications.
+
+  def install dep_or_name, version = Gem::Requirement.default
+    if String === dep_or_name then
+      find_spec_by_name_and_version dep_or_name, version
+    else
+      @specs_and_sources = [find_gems_with_sources(dep_or_name).last]
+    end
+
+    @installed_gems = []
+
+    gather_dependencies
+
+    @gems_to_install.each do |spec|
+      last = spec == @gems_to_install.last
+      # HACK is this test for full_name acceptable?
+      next if @source_index.any? { |n,_| n == spec.full_name } and not last
+
+      # TODO: make this sorta_verbose so other users can benefit from it
+      say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose
+
+      _, source_uri = @specs_and_sources.assoc spec
+      begin
+        local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri,
+                                                             @cache_dir
+      rescue Gem::RemoteFetcher::FetchError
+        next if @force
+        raise
+      end
+
+      inst = Gem::Installer.new local_gem_path,
+                                :bin_dir             => @bin_dir,
+                                :development         => @development,
+                                :env_shebang         => @env_shebang,
+                                :force               => @force,
+                                :format_executable   => @format_executable,
+                                :ignore_dependencies => @ignore_dependencies,
+                                :install_dir         => @install_dir,
+                                :security_policy     => @security_policy,
+                                :source_index        => @source_index,
+                                :user_install        => @user_install,
+                                :wrappers            => @wrappers
+
+      spec = inst.install
+
+      @installed_gems << spec
+    end
+
+    @installed_gems
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_list.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_list.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/dependency_list.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,185 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'tsort'
+
+class Gem::DependencyList
+
+  include Enumerable
+  include TSort
+
+  def self.from_source_index(src_index)
+    deps = new
+
+    src_index.each do |full_name, spec|
+      deps.add spec
+    end
+
+    deps
+  end
+
+  def initialize
+    @specs = []
+  end
+
+  ##
+  # Adds +gemspecs+ to the dependency list.
+
+  def add(*gemspecs)
+    @specs.push(*gemspecs)
+  end
+
+  ##
+  # Return a list of the specifications in the dependency list, sorted in
+  # order so that no spec in the list depends on a gem earlier in the list.
+  #
+  # This is useful when removing gems from a set of installed gems.  By
+  # removing them in the returned order, you don't get into as many dependency
+  # issues.
+  #
+  # If there are circular dependencies (yuck!), then gems will be returned in
+  # order until only the circular dependents and anything they reference are
+  # left.  Then arbitrary gemspecs will be returned until the circular
+  # dependency is broken, after which gems will be returned in dependency
+  # order again.
+
+  def dependency_order
+    sorted = strongly_connected_components.flatten
+
+    result = []
+    seen = {}
+
+    sorted.each do |spec|
+      if index = seen[spec.name] then
+        if result[index].version < spec.version then
+          result[index] = spec
+        end
+      else
+        seen[spec.name] = result.length
+        result << spec
+      end
+    end
+
+    result.reverse
+  end
+
+  ##
+  # Iterator over dependency_order
+
+  def each(&block)
+    dependency_order.each(&block)
+  end
+
+  def find_name(full_name)
+    @specs.find { |spec| spec.full_name == full_name }
+  end
+
+  ##
+  # Are all the dependencies in the list satisfied?
+
+  def ok?
+    @specs.all? do |spec|
+      spec.runtime_dependencies.all? do |dep|
+        @specs.find { |s| s.satisfies_requirement? dep }
+      end
+    end
+  end
+
+  ##
+  # Is is ok to remove a gem from the dependency list?
+  #
+  # If removing the gemspec creates breaks a currently ok dependency, then it
+  # is NOT ok to remove the gem.
+
+  def ok_to_remove?(full_name)
+    gem_to_remove = find_name full_name
+
+    siblings = @specs.find_all { |s|
+      s.name == gem_to_remove.name &&
+        s.full_name != gem_to_remove.full_name
+    }
+
+    deps = []
+
+    @specs.each do |spec|
+      spec.dependencies.each do |dep|
+        deps << dep if gem_to_remove.satisfies_requirement?(dep)
+      end
+    end
+
+    deps.all? { |dep|
+      siblings.any? { |s|
+        s.satisfies_requirement? dep
+      }
+    }
+  end
+
+  def remove_by_name(full_name)
+    @specs.delete_if { |spec| spec.full_name == full_name }
+  end
+
+  ##
+  # Return a hash of predecessors.  <tt>result[spec]</tt> is an Array of
+  # gemspecs that have a dependency satisfied by the named spec.
+
+  def spec_predecessors
+    result = Hash.new { |h,k| h[k] = [] }
+
+    specs = @specs.sort.reverse
+
+    specs.each do |spec|
+      specs.each do |other|
+        next if spec == other
+
+        other.dependencies.each do |dep|
+          if spec.satisfies_requirement? dep then
+            result[spec] << other
+          end
+        end
+      end
+    end
+
+    result
+  end
+
+  def tsort_each_node(&block)
+    @specs.each(&block)
+  end
+
+  def tsort_each_child(node, &block)
+    specs = @specs.sort.reverse
+
+    node.dependencies.each do |dep|
+      specs.each do |spec|
+        if spec.satisfies_requirement? dep then
+          begin
+            yield spec
+          rescue TSort::Cyclic
+          end
+          break
+        end
+      end
+    end
+  end
+
+  private
+
+  ##
+  # Count the number of gemspecs in the list +specs+ that are not in
+  # +ignored+.
+
+  def active_count(specs, ignored)
+    result = 0
+
+    specs.each do |spec|
+      result += 1 unless ignored[spec.full_name]
+    end
+
+    result
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/doc_manager.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/doc_manager.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/doc_manager.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,230 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'fileutils'
+require 'rubygems'
+
+##
+# The documentation manager generates RDoc and RI for RubyGems.
+
+class Gem::DocManager
+
+  include Gem::UserInteraction
+
+  @configured_args = []
+
+  def self.configured_args
+    @configured_args ||= []
+  end
+
+  def self.configured_args=(args)
+    case args
+    when Array
+      @configured_args = args
+    when String
+      @configured_args = args.split
+    end
+  end
+
+  ##
+  # Load RDoc from a gem if it is available, otherwise from Ruby's stdlib
+
+  def self.load_rdoc
+    begin
+      gem 'rdoc'
+    rescue Gem::LoadError
+      # use built-in RDoc
+    end
+
+    begin
+      require 'rdoc/rdoc'
+
+      @rdoc_version = if defined? RDoc::VERSION then
+                        Gem::Version.new RDoc::VERSION
+                      else
+                        Gem::Version.new '1.0.1' # HACK parsing is hard
+                      end
+
+    rescue LoadError => e
+      raise Gem::DocumentError,
+          "ERROR: RDoc documentation generator not installed: #{e}"
+    end
+  end
+
+  def self.rdoc_version
+    @rdoc_version
+  end
+
+  ##
+  # Updates the RI cache for RDoc 2 if it is installed
+
+  def self.update_ri_cache
+    load_rdoc rescue return
+
+    return unless defined? RDoc::VERSION # RDoc 1 does not have VERSION
+
+    require 'rdoc/ri/driver'
+
+    options = {
+      :use_cache => true,
+      :use_system => true,
+      :use_site => true,
+      :use_home => true,
+      :use_gems => true,
+      :formatter => RDoc::RI::Formatter,
+    }
+
+    driver = RDoc::RI::Driver.new(options).class_cache
+  end
+
+  ##
+  # Create a document manager for +spec+. +rdoc_args+ contains arguments for
+  # RDoc (template etc.) as a String.
+
+  def initialize(spec, rdoc_args="")
+    @spec = spec
+    @doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
+    @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
+  end
+
+  ##
+  # Is the RDoc documentation installed?
+
+  def rdoc_installed?
+    File.exist?(File.join(@doc_dir, "rdoc"))
+  end
+
+  ##
+  # Generate the RI documents for this gem spec.
+  #
+  # Note that if both RI and RDoc documents are generated from the same
+  # process, the RI docs should be done first (a likely bug in RDoc will cause
+  # RI docs generation to fail if run after RDoc).
+
+  def generate_ri
+    setup_rdoc
+    install_ri # RDoc bug, ri goes first
+
+    FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+  end
+
+  ##
+  # Generate the RDoc documents for this gem spec.
+  #
+  # Note that if both RI and RDoc documents are generated from the same
+  # process, the RI docs should be done first (a likely bug in RDoc will cause
+  # RI docs generation to fail if run after RDoc).
+
+  def generate_rdoc
+    setup_rdoc
+    install_rdoc
+
+    FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+  end
+
+  ##
+  # Generate and install RDoc into the documentation directory
+
+  def install_rdoc
+    rdoc_dir = File.join @doc_dir, 'rdoc'
+
+    FileUtils.rm_rf rdoc_dir
+
+    say "Installing RDoc documentation for #{@spec.full_name}..."
+    run_rdoc '--op', rdoc_dir
+  end
+
+  ##
+  # Generate and install RI into the documentation directory
+
+  def install_ri
+    ri_dir = File.join @doc_dir, 'ri'
+
+    FileUtils.rm_rf ri_dir
+
+    say "Installing ri documentation for #{@spec.full_name}..."
+    run_rdoc '--ri', '--op', ri_dir
+  end
+
+  ##
+  # Run RDoc with +args+, which is an ARGV style argument list
+
+  def run_rdoc(*args)
+    args << @spec.rdoc_options
+    args << self.class.configured_args
+    args << '--quiet'
+    args << @spec.require_paths.clone
+    args << @spec.extra_rdoc_files
+    args << '--title' << "#{@spec.full_name} Documentation"
+    args = args.flatten.map do |arg| arg.to_s end
+
+    if self.class.rdoc_version >= Gem::Version.new('2.4.0') then
+      args.delete '--inline-source'
+      args.delete '--promiscuous'
+      args.delete '-p'
+      args.delete '--one-file'
+      # HACK more
+    end
+
+    r = RDoc::RDoc.new
+
+    old_pwd = Dir.pwd
+    Dir.chdir(@spec.full_gem_path)
+    begin
+      r.document args
+    rescue Errno::EACCES => e
+      dirname = File.dirname e.message.split("-")[1].strip
+      raise Gem::FilePermissionError.new(dirname)
+    rescue RuntimeError => ex
+      alert_error "While generating documentation for #{@spec.full_name}"
+      ui.errs.puts "... MESSAGE:   #{ex}"
+      ui.errs.puts "... RDOC args: #{args.join(' ')}"
+      ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
+      Gem.configuration.backtrace
+      ui.errs.puts "(continuing with the rest of the installation)"
+    ensure
+      Dir.chdir(old_pwd)
+    end
+  end
+
+  def setup_rdoc
+    if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then
+      raise Gem::FilePermissionError.new(@doc_dir)
+    end
+
+    FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+
+    self.class.load_rdoc
+  end
+
+  ##
+  # Remove RDoc and RI documentation
+
+  def uninstall_doc
+    raise Gem::FilePermissionError.new(@spec.installation_path) unless
+    File.writable? @spec.installation_path
+
+    original_name = [
+      @spec.name, @spec.version, @spec.original_platform].join '-'
+
+    doc_dir = File.join @spec.installation_path, 'doc', @spec.full_name
+    unless File.directory? doc_dir then
+      doc_dir = File.join @spec.installation_path, 'doc', original_name
+    end
+
+    FileUtils.rm_rf doc_dir
+
+    ri_dir = File.join @spec.installation_path, 'ri', @spec.full_name
+
+    unless File.directory? ri_dir then
+      ri_dir = File.join @spec.installation_path, 'ri', original_name
+    end
+
+    FileUtils.rm_rf ri_dir
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/exceptions.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/exceptions.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/exceptions.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,82 @@
+##
+# Base exception class for RubyGems.  All exception raised by RubyGems are a
+# subclass of this one.
+class Gem::Exception < RuntimeError; end
+
+class Gem::CommandLineError < Gem::Exception; end
+
+class Gem::DependencyError < Gem::Exception; end
+
+class Gem::DependencyRemovalException < Gem::Exception; end
+
+##
+# Raised when attempting to uninstall a gem that isn't in GEM_HOME.
+
+class Gem::GemNotInHomeException < Gem::Exception
+  attr_accessor :spec
+end
+
+class Gem::DocumentError < Gem::Exception; end
+
+##
+# Potentially raised when a specification is validated.
+class Gem::EndOfYAMLException < Gem::Exception; end
+
+##
+# Signals that a file permission error is preventing the user from
+# installing in the requested directories.
+class Gem::FilePermissionError < Gem::Exception
+  def initialize(path)
+    super("You don't have write permissions into the #{path} directory.")
+  end
+end
+
+##
+# Used to raise parsing and loading errors
+class Gem::FormatException < Gem::Exception
+  attr_accessor :file_path
+end
+
+class Gem::GemNotFoundException < Gem::Exception; end
+
+class Gem::InstallError < Gem::Exception; end
+
+##
+# Potentially raised when a specification is validated.
+class Gem::InvalidSpecificationException < Gem::Exception; end
+
+class Gem::OperationNotSupportedError < Gem::Exception; end
+
+##
+# Signals that a remote operation cannot be conducted, probably due to not
+# being connected (or just not finding host).
+#--
+# TODO: create a method that tests connection to the preferred gems server.
+# All code dealing with remote operations will want this.  Failure in that
+# method should raise this error.
+class Gem::RemoteError < Gem::Exception; end
+
+class Gem::RemoteInstallationCancelled < Gem::Exception; end
+
+class Gem::RemoteInstallationSkipped < Gem::Exception; end
+
+##
+# Represents an error communicating via HTTP.
+class Gem::RemoteSourceException < Gem::Exception; end
+
+class Gem::VerificationError < Gem::Exception; end
+
+##
+# Raised to indicate that a system exit should occur with the specified
+# exit_code
+
+class Gem::SystemExitException < SystemExit
+  attr_accessor :exit_code
+
+  def initialize(exit_code)
+    @exit_code = exit_code
+
+    super "Exiting RubyGems with exit_code #{exit_code}"
+  end
+
+end

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,54 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+class Gem::Ext::Builder
+
+  def self.class_name
+    name =~ /Ext::(.*)Builder/
+    $1.downcase
+  end
+
+  def self.make(dest_path, results)
+    unless File.exist? 'Makefile' then
+      raise Gem::InstallError, "Makefile not found:\n\n#{results.join "\n"}" 
+    end
+
+    mf = File.read('Makefile')
+    mf = mf.gsub(/^RUBYARCHDIR\s*=\s*\$[^$]*/, "RUBYARCHDIR = #{dest_path}")
+    mf = mf.gsub(/^RUBYLIBDIR\s*=\s*\$[^$]*/, "RUBYLIBDIR = #{dest_path}")
+
+    File.open('Makefile', 'wb') {|f| f.print mf}
+
+    make_program = ENV['make']
+    unless make_program then
+      make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
+    end
+
+    ['', ' install'].each do |target|
+      cmd = "#{make_program}#{target}"
+      results << cmd
+      results << `#{cmd} #{redirector}`
+
+      raise Gem::InstallError, "make#{target} failed:\n\n#{results}" unless
+        $?.success?
+    end
+  end
+
+  def self.redirector
+    '2>&1'
+  end
+
+  def self.run(command, results)
+    results << command
+    results << `#{command} #{redirector}`
+
+    unless $?.success? then
+      raise Gem::InstallError, "#{class_name} failed:\n\n#{results.join "\n"}"
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/configure_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/configure_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/configure_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,25 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/ext/builder'
+
+class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder
+
+  def self.build(extension, directory, dest_path, results)
+    unless File.exist?('Makefile') then
+      cmd = "sh ./configure --prefix=#{dest_path}"
+      cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty?
+
+      run cmd, results
+    end
+
+    make dest_path, results
+
+    results
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/ext_conf_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/ext_conf_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/ext_conf_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,24 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/ext/builder'
+require 'rubygems/command'
+
+class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
+
+  def self.build(extension, directory, dest_path, results)
+    cmd = "#{Gem.ruby} #{File.basename extension}"
+    cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty?
+
+    run cmd, results
+
+    make dest_path, results
+
+    results
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/rake_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/rake_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext/rake_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,31 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/ext/builder'
+require 'rubygems/command'
+
+class Gem::Ext::RakeBuilder < Gem::Ext::Builder
+
+  def self.build(extension, directory, dest_path, results)
+    if File.basename(extension) =~ /mkrf_conf/i then
+      cmd = "#{Gem.ruby} #{File.basename extension}"
+      cmd << " #{Gem::Command.build_args.join " "}" unless Gem::Command.build_args.empty?
+      run cmd, results
+    end
+
+    # Deal with possible spaces in the path, e.g. C:/Program Files
+    dest_path = '"' + dest_path + '"' if dest_path.include?(' ')
+
+    cmd = ENV['rake'] || "#{Gem.ruby} -rubygems #{Gem.bin_path('rake')}" rescue Gem.default_exec_format % 'rake'
+    cmd += " RUBYARCHDIR=#{dest_path} RUBYLIBDIR=#{dest_path}" # ENV is frozen
+
+    run cmd, results
+
+    results
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/ext.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,18 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+
+##
+# Classes for building C extensions live here.
+
+module Gem::Ext; end
+
+require 'rubygems/ext/builder'
+require 'rubygems/ext/configure_builder'
+require 'rubygems/ext/ext_conf_builder'
+require 'rubygems/ext/rake_builder'
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/format.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/format.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/format.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,87 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'fileutils'
+
+require 'rubygems/package'
+
+##
+# Gem::Format knows the guts of the RubyGem .gem file format and provides the
+# capability to read gem files
+
+class Gem::Format
+
+  attr_accessor :spec, :file_entries, :gem_path
+
+  extend Gem::UserInteraction
+
+  ##
+  # Constructs an instance of a Format object, representing the gem's
+  # data structure.
+  #
+  # gem:: [String] The file name of the gem
+  #
+  def initialize(gem_path)
+    @gem_path = gem_path
+  end
+
+  ##
+  # Reads the named gem file and returns a Format object, representing 
+  # the data from the gem file
+  #
+  # file_path:: [String] Path to the gem file
+
+  def self.from_file_by_path(file_path, security_policy = nil)
+    format = nil
+
+    unless File.exist?(file_path)
+      raise Gem::Exception, "Cannot load gem at [#{file_path}] in #{Dir.pwd}"
+    end
+
+    # check for old version gem
+    if File.read(file_path, 20).include?("MD5SUM =")
+      require 'rubygems/old_format'
+
+      format = Gem::OldFormat.from_file_by_path(file_path)
+    else
+      open file_path, Gem.binary_mode do |io|
+        format = from_io io, file_path, security_policy
+      end
+    end
+
+    return format
+  end
+
+  ##
+  # Reads a gem from an io stream and returns a Format object, representing
+  # the data from the gem file
+  #
+  # io:: [IO] Stream from which to read the gem
+
+  def self.from_io(io, gem_path="(io)", security_policy = nil)
+    format = new gem_path
+
+    Gem::Package.open io, 'r', security_policy do |pkg|
+      format.spec = pkg.metadata
+      format.file_entries = []
+
+      pkg.each do |entry|
+        size = entry.header.size
+        mode = entry.header.mode
+
+        format.file_entries << [{
+            "size" => size, "mode" => mode, "path" => entry.full_name,
+          },
+          entry.read
+        ]
+      end
+    end
+
+    format
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_openssl.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_openssl.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_openssl.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,94 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+#--
+# Some system might not have OpenSSL installed, therefore the core
+# library file openssl might not be available.  We localize testing
+# for the presence of OpenSSL in this file.
+#++
+
+module Gem
+  class << self
+    ##
+    # Is SSL (used by the signing commands) available on this
+    # platform?
+
+    def ssl_available?
+      @ssl_available
+    end
+
+    ##
+    # Is SSL available?
+
+    attr_writer :ssl_available
+
+    ##
+    # Ensure that SSL is available.  Throw an exception if it is not.
+
+    def ensure_ssl_available
+      unless ssl_available?
+        raise Gem::Exception, "SSL is not installed on this system"
+      end
+    end
+  end
+end
+
+begin
+  require 'openssl'
+
+  # Reference a constant defined in the .rb portion of ssl (just to
+  # make sure that part is loaded too).
+
+  dummy = OpenSSL::Digest::SHA1
+
+  Gem.ssl_available = true
+
+  class OpenSSL::X509::Certificate # :nodoc:
+    # Check the validity of this certificate.
+    def check_validity(issuer_cert = nil, time = Time.now)
+      ret = if @not_before && @not_before > time
+              [false, :expired, "not valid before '#@not_before'"]
+            elsif @not_after && @not_after < time
+              [false, :expired, "not valid after '#@not_after'"]
+            elsif issuer_cert && !verify(issuer_cert.public_key)
+              [false, :issuer, "#{issuer_cert.subject} is not issuer"]
+            else
+              [true, :ok, 'Valid certificate']
+            end
+
+      # return hash
+      { :is_valid => ret[0], :error => ret[1], :desc => ret[2] }
+    end
+  end
+
+rescue LoadError, StandardError
+  Gem.ssl_available = false
+end
+
+# :stopdoc:
+
+module Gem::SSL
+
+  # We make our own versions of the constants here.  This allows us
+  # to reference the constants, even though some systems might not
+  # have SSL installed in the Ruby core package.
+  #
+  # These constants are only used during load time.  At runtime, any
+  # method that makes a direct reference to SSL software must be
+  # protected with a Gem.ensure_ssl_available call.
+
+  if Gem.ssl_available? then
+    PKEY_RSA = OpenSSL::PKey::RSA
+    DIGEST_SHA1 = OpenSSL::Digest::SHA1
+  else
+    PKEY_RSA = :rsa
+    DIGEST_SHA1 = :sha1
+  end
+
+end
+
+# :startdoc:
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_path_searcher.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_path_searcher.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_path_searcher.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,102 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+##
+# GemPathSearcher has the capability to find loadable files inside
+# gems.  It generates data up front to speed up searches later.
+
+class Gem::GemPathSearcher
+
+  ##
+  # Initialise the data we need to make searches later.
+
+  def initialize
+    # We want a record of all the installed gemspecs, in the order
+    # we wish to examine them.
+    @gemspecs = init_gemspecs
+    # Map gem spec to glob of full require_path directories.
+    # Preparing this information may speed up searches later.
+    @lib_dirs = {}
+    @gemspecs.each do |spec|
+      @lib_dirs[spec.object_id] = lib_dirs_for(spec)
+    end
+  end
+
+  ##
+  # Look in all the installed gems until a matching _path_ is found.
+  # Return the _gemspec_ of the gem where it was found.  If no match
+  # is found, return nil.
+  #
+  # The gems are searched in alphabetical order, and in reverse
+  # version order.
+  #
+  # For example:
+  #
+  #   find('log4r')              # -> (log4r-1.1 spec)
+  #   find('log4r.rb')           # -> (log4r-1.1 spec)
+  #   find('rake/rdoctask')      # -> (rake-0.4.12 spec)
+  #   find('foobarbaz')          # -> nil
+  #
+  # Matching paths can have various suffixes ('.rb', '.so', and
+  # others), which may or may not already be attached to _file_.
+  # This method doesn't care about the full filename that matches;
+  # only that there is a match.
+
+  def find(path)
+    @gemspecs.find do |spec| matching_file? spec, path end
+  end
+
+  ##
+  # Works like #find, but finds all gemspecs matching +path+.
+
+  def find_all(path)
+    @gemspecs.select do |spec|
+      matching_file? spec, path
+    end
+  end
+
+  ##
+  # Attempts to find a matching path using the require_paths of the given
+  # +spec+.
+
+  def matching_file?(spec, path)
+    !matching_files(spec, path).empty?
+  end
+
+  ##
+  # Returns files matching +path+ in +spec+.
+  #--
+  # Some of the intermediate results are cached in @lib_dirs for speed.
+
+  def matching_files(spec, path)
+    glob = File.join @lib_dirs[spec.object_id], "#{path}#{Gem.suffix_pattern}"
+    Dir[glob].select { |f| File.file? f.untaint }
+  end
+
+  ##
+  # Return a list of all installed gemspecs, sorted by alphabetical order and
+  # in reverse version order.  (bar-2, bar-1, foo-2)
+
+  def init_gemspecs
+    specs = Gem.source_index.map { |_, spec| spec }
+
+    specs.sort { |a, b|
+      names = a.name <=> b.name
+      next names if names.nonzero?
+      b.version <=> a.version
+    }
+  end
+
+  ##
+  # Returns library directories glob for a gemspec.  For example,
+  #   '/usr/local/lib/ruby/gems/1.8/gems/foobar-1.0/{lib,ext}'
+
+  def lib_dirs_for(spec)
+    "#{spec.full_gem_path}/{#{spec.require_paths.join(',')}}"
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_runner.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_runner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/gem_runner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,78 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/command_manager'
+require 'rubygems/config_file'
+require 'rubygems/doc_manager'
+
+##
+# Run an instance of the gem program.
+#
+# Gem::GemRunner is only intended for internal use by RubyGems itself.  It
+# does not form any public API and may change at any time for any reason.
+#
+# If you would like to duplicate functionality of `gem` commands, use the
+# classes they call directly.
+
+class Gem::GemRunner
+
+  def initialize(options={})
+    @command_manager_class = options[:command_manager] || Gem::CommandManager
+    @config_file_class = options[:config_file] || Gem::ConfigFile
+    @doc_manager_class = options[:doc_manager] || Gem::DocManager
+  end
+
+  ##
+  # Run the gem command with the following arguments.
+
+  def run(args)
+    start_time = Time.now
+
+    if args.include?('--')
+      # We need to preserve the original ARGV to use for passing gem options
+      # to source gems.  If there is a -- in the line, strip all options after
+      # it...its for the source building process.
+      build_args = args[args.index("--") + 1...args.length]
+      args = args[0...args.index("--")]
+    end
+
+    Gem::Command.build_args = build_args if build_args
+
+    do_configuration args
+    cmd = @command_manager_class.instance
+
+    cmd.command_names.each do |command_name|
+      config_args = Gem.configuration[command_name]
+      config_args = case config_args
+                    when String
+                      config_args.split ' '
+                    else
+                      Array(config_args)
+                    end
+      Gem::Command.add_specific_extra_args command_name, config_args
+    end
+
+    cmd.run Gem.configuration.args
+    end_time = Time.now
+
+    if Gem.configuration.benchmark then
+      printf "\nExecution time: %0.2f seconds.\n", end_time - start_time
+      puts "Press Enter to finish"
+      STDIN.gets
+    end
+  end
+
+  private
+
+  def do_configuration(args)
+    Gem.configuration = @config_file_class.new(args)
+    Gem.use_paths(Gem.configuration[:gemhome], Gem.configuration[:gempath])
+    Gem::Command.extra_args = Gem.configuration[:gem]
+    @doc_manager_class.configured_args = Gem.configuration[:rdoc]
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/indexer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/indexer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/indexer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,712 @@
+require 'fileutils'
+require 'tmpdir'
+require 'zlib'
+
+require 'rubygems'
+require 'rubygems/format'
+
+begin
+  gem 'builder'
+  require 'builder/xchar'
+rescue LoadError
+end
+
+##
+# Top level class for building the gem repository index.
+
+class Gem::Indexer
+
+  include Gem::UserInteraction
+
+  ##
+  # Build indexes for RubyGems older than 1.2.0 when true
+
+  attr_accessor :build_legacy
+
+  ##
+  # Build indexes for RubyGems 1.2.0 and newer when true
+
+  attr_accessor :build_modern
+
+  ##
+  # Index install location
+
+  attr_reader :dest_directory
+
+  ##
+  # Specs index install location
+
+  attr_reader :dest_specs_index
+
+  ##
+  # Latest specs index install location
+
+  attr_reader :dest_latest_specs_index
+
+  ##
+  # Prerelease specs index install location
+
+  attr_reader :dest_prerelease_specs_index
+
+  ##
+  # Index build directory
+
+  attr_reader :directory
+
+  ##
+  # Create an indexer that will index the gems in +directory+.
+
+  def initialize(directory, options = {})
+    unless ''.respond_to? :to_xs then
+      raise "Gem::Indexer requires that the XML Builder library be installed:" \
+           "\n\tgem install builder"
+    end
+
+    options = { :build_legacy => true, :build_modern => true }.merge options
+
+    @build_legacy = options[:build_legacy]
+    @build_modern = options[:build_modern]
+
+    @rss_title = options[:rss_title]
+    @rss_host = options[:rss_host]
+    @rss_gems_host = options[:rss_gems_host]
+
+    @dest_directory = directory
+    @directory = File.join Dir.tmpdir, "gem_generate_index_#{$$}"
+
+    marshal_name = "Marshal.#{Gem.marshal_version}"
+
+    @master_index = File.join @directory, 'yaml'
+    @marshal_index = File.join @directory, marshal_name
+
+    @quick_dir = File.join @directory, 'quick'
+
+    @quick_marshal_dir = File.join @quick_dir, marshal_name
+
+    @quick_index = File.join @quick_dir, 'index'
+    @latest_index = File.join @quick_dir, 'latest_index'
+
+    @specs_index = File.join @directory, "specs.#{Gem.marshal_version}"
+    @latest_specs_index = File.join @directory,
+                                    "latest_specs.#{Gem.marshal_version}"
+    @prerelease_specs_index = File.join(@directory,
+                                        "prerelease_specs.#{Gem.marshal_version}")
+
+    @dest_specs_index = File.join @dest_directory,
+                                  "specs.#{Gem.marshal_version}"
+    @dest_latest_specs_index = File.join @dest_directory,
+                                         "latest_specs.#{Gem.marshal_version}"
+    @dest_prerelease_specs_index = File.join @dest_directory,
+                                            "prerelease_specs.#{Gem.marshal_version}"
+
+    @rss_index = File.join @directory, 'index.rss'
+
+    @files = []
+  end
+
+  ##
+  # Abbreviate the spec for downloading.  Abbreviated specs are only used for
+  # searching, downloading and related activities and do not need deployment
+  # specific information (e.g. list of files).  So we abbreviate the spec,
+  # making it much smaller for quicker downloads.
+
+  def abbreviate(spec)
+    spec.files = []
+    spec.test_files = []
+    spec.rdoc_options = []
+    spec.extra_rdoc_files = []
+    spec.cert_chain = []
+    spec
+  end
+
+  ##
+  # Build various indicies
+
+  def build_indicies(index)
+    # Marshal gemspecs are used by both modern and legacy RubyGems
+    build_marshal_gemspecs index
+    build_legacy_indicies index if @build_legacy
+    build_modern_indicies index if @build_modern
+    build_rss index
+
+    compress_indicies
+  end
+
+  ##
+  # Builds indicies for RubyGems older than 1.2.x
+
+  def build_legacy_indicies(index)
+    progress = ui.progress_reporter index.size,
+                                    "Generating YAML quick index gemspecs for #{index.size} gems",
+                                    "Complete"
+
+    Gem.time 'Generated YAML quick index gemspecs' do
+      index.released_gems.each do |original_name, spec|
+        spec_file_name = "#{original_name}.gemspec.rz"
+        yaml_name = File.join @quick_dir, spec_file_name
+
+        yaml_zipped = Gem.deflate spec.to_yaml
+        open yaml_name, 'wb' do |io| io.write yaml_zipped end
+
+        progress.updated original_name
+      end
+
+      progress.done
+    end
+
+    say "Generating quick index"
+
+    Gem.time 'Generated quick index' do
+      open @quick_index, 'wb' do |io|
+        io.puts index.sort.map { |_, spec| spec.original_name }
+      end
+    end
+
+    say "Generating latest index"
+
+    Gem.time 'Generated latest index' do
+      open @latest_index, 'wb' do |io|
+        io.puts index.latest_specs.sort.map { |spec| spec.original_name }
+      end
+    end
+
+    # Don't need prerelease legacy index
+
+    say "Generating Marshal master index"
+
+    Gem.time 'Generated Marshal master index' do
+      open @marshal_index, 'wb' do |io|
+        io.write index.dump
+      end
+    end
+
+    progress = ui.progress_reporter index.size,
+                                    "Generating YAML master index for #{index.size} gems (this may take a while)",
+                                    "Complete"
+
+    Gem.time 'Generated YAML master index' do
+      open @master_index, 'wb' do |io|
+        io.puts "--- !ruby/object:#{index.class}"
+        io.puts "gems:"
+
+        gems = index.sort_by { |name, gemspec| gemspec.sort_obj }
+        gems.each do |original_name, gemspec|
+          yaml = gemspec.to_yaml.gsub(/^/, '    ')
+          yaml = yaml.sub(/\A    ---/, '') # there's a needed extra ' ' here
+          io.print "  #{original_name}:"
+          io.puts yaml
+
+          progress.updated original_name
+        end
+      end
+
+      progress.done
+    end
+
+    @files << @quick_dir
+    @files << @master_index
+    @files << "#{@master_index}.Z"
+    @files << @marshal_index
+    @files << "#{@marshal_index}.Z"
+  end
+
+  ##
+  # Builds Marshal quick index gemspecs.
+
+  def build_marshal_gemspecs(index)
+    progress = ui.progress_reporter index.size,
+                                    "Generating Marshal quick index gemspecs for #{index.size} gems",
+                                    "Complete"
+
+    files = []
+
+    Gem.time 'Generated Marshal quick index gemspecs' do
+      index.gems.each do |original_name, spec|
+        spec_file_name = "#{original_name}.gemspec.rz"
+        marshal_name = File.join @quick_marshal_dir, spec_file_name
+
+        marshal_zipped = Gem.deflate Marshal.dump(spec)
+        open marshal_name, 'wb' do |io| io.write marshal_zipped end
+
+        files << marshal_name
+
+        progress.updated original_name
+      end
+
+      progress.done
+    end
+
+    @files << @quick_marshal_dir
+
+    files
+  end
+
+  ##
+  # Build a single index for RubyGems 1.2 and newer
+
+  def build_modern_index(index, file, name)
+    say "Generating #{name} index"
+
+    Gem.time "Generated #{name} index" do
+      open(file, 'wb') do |io|
+        specs = index.map do |*spec|
+          # We have to splat here because latest_specs is an array,
+          # while the others are hashes. See the TODO in source_index.rb
+          spec = spec.flatten.last
+          platform = spec.original_platform
+
+          # win32-api-1.0.4-x86-mswin32-60
+          unless String === platform then
+            alert_warning "Skipping invalid platform in gem: #{spec.full_name}"
+            next
+          end
+
+          platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
+          [spec.name, spec.version, platform]
+        end
+
+        specs = compact_specs(specs)
+        Marshal.dump(specs, io)
+      end
+    end
+  end
+
+  ##
+  # Builds indicies for RubyGems 1.2 and newer. Handles full, latest, prerelease
+
+  def build_modern_indicies(index)
+    build_modern_index(index.released_specs.sort, @specs_index, 'specs')
+    build_modern_index(index.latest_specs.sort,
+                       @latest_specs_index,
+                       'latest specs')
+    build_modern_index(index.prerelease_specs.sort,
+                       @prerelease_specs_index,
+                       'prerelease specs')
+
+    @files += [@specs_index,
+               "#{@specs_index}.gz",
+               @latest_specs_index,
+               "#{@latest_specs_index}.gz",
+               @prerelease_specs_index,
+               "#{@prerelease_specs_index}.gz"]
+  end
+
+  ##
+  # Builds an RSS feed for past two days gem releases according to the gem's
+  # date.
+
+  def build_rss(index)
+    if @rss_host.nil? or @rss_gems_host.nil? then
+      if Gem.configuration.really_verbose then
+        alert_warning "no --rss-host or --rss-gems-host, RSS generation disabled"
+      end
+      return
+    end
+
+    require 'cgi'
+    require 'rubygems/text'
+
+    extend Gem::Text
+
+    Gem.time 'Generated rss' do
+      open @rss_index, 'wb' do |io|
+        rss_host = CGI.escapeHTML @rss_host
+        rss_title = CGI.escapeHTML(@rss_title || 'gems')
+
+        io.puts <<-HEADER
+<?xml version="1.0"?>
+<rss version="2.0">
+  <channel>
+    <title>#{rss_title}</title>
+    <link>http://#{rss_host}</link>
+    <description>Recently released gems from http://#{rss_host}</description>
+    <generator>RubyGems v#{Gem::RubyGemsVersion}</generator>
+    <docs>http://cyber.law.harvard.edu/rss/rss.html</docs>
+        HEADER
+
+        today = Gem::Specification::TODAY
+        yesterday = today - 86400
+
+        index = index.select do |_, spec|
+          spec_date = spec.date
+
+          case spec_date
+          when Date
+            Time.parse(spec_date.to_s) >= yesterday
+          when Time
+            spec_date >= yesterday
+          end
+        end
+
+        index = index.select do |_, spec|
+          spec_date = spec.date
+
+          case spec_date
+          when Date
+            Time.parse(spec_date.to_s) <= today
+          when Time
+            spec_date <= today
+          end
+        end
+
+        index.sort_by { |_, spec| [-spec.date.to_i, spec] }.each do |_, spec|
+          gem_path = CGI.escapeHTML "http://#{@rss_gems_host}/gems/#{spec.file_name}"
+          size = File.stat(spec.loaded_from).size rescue next
+
+          description = spec.description || spec.summary || ''
+          authors = Array spec.authors
+          emails = Array spec.email
+          authors = emails.zip(authors).map do |email, author|
+            email += " (#{author})" if author and not author.empty?
+          end.join ', '
+
+          description = description.split(/\n\n+/).map do |chunk|
+            format_text chunk, 78
+          end
+
+          description = description.join "\n\n"
+
+          item = ''
+
+          item << <<-ITEM
+    <item>
+      <title>#{CGI.escapeHTML spec.full_name}</title>
+      <description>
+&lt;pre&gt;#{CGI.escapeHTML description.chomp}&lt;/pre&gt;
+      </description>
+      <author>#{CGI.escapeHTML authors}</author>
+      <guid>#{CGI.escapeHTML spec.full_name}</guid>
+      <enclosure url=\"#{gem_path}\"
+                 length=\"#{size}\" type=\"application/octet-stream\" />
+      <pubDate>#{spec.date.rfc2822}</pubDate>
+          ITEM
+
+          item << <<-ITEM if spec.homepage
+      <link>#{CGI.escapeHTML spec.homepage}</link>
+          ITEM
+
+          item << <<-ITEM
+    </item>
+          ITEM
+
+          io.puts item
+        end
+
+        io.puts <<-FOOTER
+  </channel>
+</rss>
+        FOOTER
+      end
+    end
+
+    @files << @rss_index
+  end
+
+  ##
+  # Collect specifications from .gem files from the gem directory.
+
+  def collect_specs(gems = gem_file_list)
+    index = Gem::SourceIndex.new
+
+    progress = ui.progress_reporter gems.size,
+                                    "Loading #{gems.size} gems from #{@dest_directory}",
+                                    "Loaded all gems"
+
+    Gem.time 'loaded' do
+      gems.each do |gemfile|
+        if File.size(gemfile.to_s) == 0 then
+          alert_warning "Skipping zero-length gem: #{gemfile}"
+          next
+        end
+
+        begin
+          spec = Gem::Format.from_file_by_path(gemfile).spec
+          spec.loaded_from = gemfile
+
+          unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
+            expected_name = spec.full_name
+            expected_name << " (#{spec.original_name})" if
+              spec.original_name != spec.full_name
+            alert_warning "Skipping misnamed gem: #{gemfile} should be named #{expected_name}"
+            next
+          end
+
+          abbreviate spec
+          sanitize spec
+
+          index.add_spec spec, spec.original_name
+
+          progress.updated spec.original_name
+
+        rescue SignalException => e
+          alert_error "Received signal, exiting"
+          raise
+        rescue Exception => e
+          alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
+        end
+      end
+
+      progress.done
+    end
+
+    index
+  end
+
+  ##
+  # Compresses indicies on disk
+  #--
+  # All future files should be compressed using gzip, not deflate
+
+  def compress_indicies
+    say "Compressing indicies"
+
+    Gem.time 'Compressed indicies' do
+      if @build_legacy then
+        compress @quick_index, 'rz'
+        paranoid @quick_index, 'rz'
+
+        compress @latest_index, 'rz'
+        paranoid @latest_index, 'rz'
+
+        compress @marshal_index, 'Z'
+        paranoid @marshal_index, 'Z'
+
+        compress @master_index, 'Z'
+        paranoid @master_index, 'Z'
+      end
+
+      if @build_modern then
+        gzip @specs_index
+        gzip @latest_specs_index
+        gzip @prerelease_specs_index
+      end
+    end
+  end
+
+  ##
+  # Compacts Marshal output for the specs index data source by using identical
+  # objects as much as possible.
+
+  def compact_specs(specs)
+    names = {}
+    versions = {}
+    platforms = {}
+
+    specs.map do |(name, version, platform)|
+      names[name] = name unless names.include? name
+      versions[version] = version unless versions.include? version
+      platforms[platform] = platform unless platforms.include? platform
+
+      [names[name], versions[version], platforms[platform]]
+    end
+  end
+
+  ##
+  # Compress +filename+ with +extension+.
+
+  def compress(filename, extension)
+    data = Gem.read_binary filename
+
+    zipped = Gem.deflate data
+
+    open "#{filename}.#{extension}", 'wb' do |io|
+      io.write zipped
+    end
+  end
+
+  ##
+  # List of gem file names to index.
+
+  def gem_file_list
+    Dir.glob(File.join(@dest_directory, "gems", "*.gem"))
+  end
+
+  ##
+  # Builds and installs indicies.
+
+  def generate_index
+    make_temp_directories
+    index = collect_specs
+    build_indicies index
+    install_indicies
+  rescue SignalException
+  ensure
+    FileUtils.rm_rf @directory
+  end
+
+  ##
+  # Zlib::GzipWriter wrapper that gzips +filename+ on disk.
+
+  def gzip(filename)
+    Zlib::GzipWriter.open "#{filename}.gz" do |io|
+      io.write Gem.read_binary(filename)
+    end
+  end
+
+  ##
+  # Install generated indicies into the destination directory.
+
+  def install_indicies
+    verbose = Gem.configuration.really_verbose
+
+    say "Moving index into production dir #{@dest_directory}" if verbose
+
+    files = @files.dup
+    files.delete @quick_marshal_dir if files.include? @quick_dir
+
+    if files.include? @quick_marshal_dir and
+       not files.include? @quick_dir then
+      files.delete @quick_marshal_dir
+      quick_marshal_dir = @quick_marshal_dir.sub @directory, ''
+
+      dst_name = File.join @dest_directory, quick_marshal_dir
+
+      FileUtils.mkdir_p File.dirname(dst_name), :verbose => verbose
+      FileUtils.rm_rf dst_name, :verbose => verbose
+      FileUtils.mv @quick_marshal_dir, dst_name, :verbose => verbose,
+                   :force => true
+    end
+
+    files = files.map do |path|
+      path.sub @directory, ''
+    end
+
+    files.each do |file|
+      src_name = File.join @directory, file
+      dst_name = File.join @dest_directory, file
+
+      FileUtils.rm_rf dst_name, :verbose => verbose
+      FileUtils.mv src_name, @dest_directory, :verbose => verbose,
+                   :force => true
+    end
+  end
+
+  ##
+  # Make directories for index generation
+
+  def make_temp_directories
+    FileUtils.rm_rf @directory
+    FileUtils.mkdir_p @directory, :mode => 0700
+    FileUtils.mkdir_p @quick_marshal_dir
+  end
+
+  ##
+  # Ensure +path+ and path with +extension+ are identical.
+
+  def paranoid(path, extension)
+    data = Gem.read_binary path
+    compressed_data = Gem.read_binary "#{path}.#{extension}"
+
+    unless data == Gem.inflate(compressed_data) then
+      raise "Compressed file #{compressed_path} does not match uncompressed file #{path}"
+    end
+  end
+
+  ##
+  # Sanitize the descriptive fields in the spec.  Sometimes non-ASCII
+  # characters will garble the site index.  Non-ASCII characters will
+  # be replaced by their XML entity equivalent.
+
+  def sanitize(spec)
+    spec.summary = sanitize_string(spec.summary)
+    spec.description = sanitize_string(spec.description)
+    spec.post_install_message = sanitize_string(spec.post_install_message)
+    spec.authors = spec.authors.collect { |a| sanitize_string(a) }
+
+    spec
+  end
+
+  ##
+  # Sanitize a single string.
+
+  def sanitize_string(string)
+    # HACK the #to_s is in here because RSpec has an Array of Arrays of
+    # Strings for authors.  Need a way to disallow bad values on gempsec
+    # generation.  (Probably won't happen.)
+    string ? string.to_s.to_xs : string
+  end
+
+  ##
+  # Perform an in-place update of the repository from newly added gems.  Only
+  # works for modern indicies, and sets #build_legacy to false when run.
+
+  def update_index
+    @build_legacy = false
+
+    make_temp_directories
+
+    specs_mtime = File.stat(@dest_specs_index).mtime
+    newest_mtime = Time.at 0
+
+    updated_gems = gem_file_list.select do |gem|
+      gem_mtime = File.stat(gem).mtime
+      newest_mtime = gem_mtime if gem_mtime > newest_mtime
+      gem_mtime >= specs_mtime
+    end
+
+    if updated_gems.empty? then
+      say 'No new gems'
+      terminate_interaction 0
+    end
+
+    index = collect_specs updated_gems
+
+    files = build_marshal_gemspecs index
+
+    Gem.time 'Updated indexes' do
+      update_specs_index index.released_gems, @dest_specs_index, @specs_index
+      update_specs_index index.released_gems, @dest_latest_specs_index, @latest_specs_index
+      update_specs_index(index.prerelease_gems, @dest_prerelease_specs_index,
+                         @prerelease_specs_index)
+    end
+
+    compress_indicies
+
+    verbose = Gem.configuration.really_verbose
+
+    say "Updating production dir #{@dest_directory}" if verbose
+
+    files << @specs_index
+    files << "#{@specs_index}.gz"
+    files << @latest_specs_index
+    files << "#{@latest_specs_index}.gz"
+    files << @prerelease_specs_index
+    files << "#{@prerelease_specs_index}.gz"
+
+    files = files.map do |path|
+      path.sub @directory, ''
+    end
+
+    files.each do |file|
+      src_name = File.join @directory, file
+      dst_name = File.join @dest_directory, File.dirname(file)
+
+      FileUtils.mv src_name, dst_name, :verbose => verbose,
+                   :force => true
+
+      File.utime newest_mtime, newest_mtime, dst_name
+    end
+  end
+
+  ##
+  # Combines specs in +index+ and +source+ then writes out a new copy to
+  # +dest+.  For a latest index, does not ensure the new file is minimal.
+
+  def update_specs_index(index, source, dest)
+    specs_index = Marshal.load Gem.read_binary(source)
+
+    index.each do |_, spec|
+      platform = spec.original_platform
+      platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
+      specs_index << [spec.name, spec.version, platform]
+    end
+
+    specs_index = compact_specs specs_index.uniq.sort
+
+    open dest, 'wb' do |io|
+      Marshal.dump specs_index, io
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/install_update_options.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/install_update_options.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/install_update_options.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,124 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+require 'rubygems/security'
+
+##
+# Mixin methods for install and update options for Gem::Commands
+
+module Gem::InstallUpdateOptions
+
+  ##
+  # Add the install/update options to the option parser.
+
+  def add_install_update_options
+    OptionParser.accept Gem::Security::Policy do |value|
+      value = Gem::Security::Policies[value]
+      raise OptionParser::InvalidArgument, value if value.nil?
+      value
+    end
+
+    add_option(:"Install/Update", '-i', '--install-dir DIR',
+               'Gem repository directory to get installed',
+               'gems') do |value, options|
+      options[:install_dir] = File.expand_path(value)
+    end
+
+    add_option(:"Install/Update", '-n', '--bindir DIR',
+	       'Directory where binary files are',
+	       'located') do |value, options|
+      options[:bin_dir] = File.expand_path(value)
+    end
+
+    add_option(:"Install/Update", '-d', '--[no-]rdoc',
+               'Generate RDoc documentation for the gem on',
+               'install') do |value, options|
+      options[:generate_rdoc] = value
+    end
+
+    add_option(:"Install/Update", '--[no-]ri',
+               'Generate RI documentation for the gem on',
+               'install') do |value, options|
+      options[:generate_ri] = value
+    end
+
+    add_option(:"Install/Update", '-E', '--[no-]env-shebang',
+               "Rewrite the shebang line on installed",
+               "scripts to use /usr/bin/env") do |value, options|
+      options[:env_shebang] = value
+    end
+
+    add_option(:"Install/Update", '-f', '--[no-]force',
+               'Force gem to install, bypassing dependency',
+               'checks') do |value, options|
+      options[:force] = value
+    end
+
+    add_option(:"Install/Update", '-t', '--[no-]test',
+               'Run unit tests prior to installation') do |value, options|
+      options[:test] = value
+    end
+
+    add_option(:"Install/Update", '-w', '--[no-]wrappers',
+               'Use bin wrappers for executables',
+               'Not available on dosish platforms') do |value, options|
+      options[:wrappers] = value
+    end
+
+    add_option(:"Install/Update", '-P', '--trust-policy POLICY',
+               Gem::Security::Policy,
+               'Specify gem trust policy') do |value, options|
+      options[:security_policy] = value
+    end
+
+    add_option(:"Install/Update", '--ignore-dependencies',
+               'Do not install any required dependent gems') do |value, options|
+      options[:ignore_dependencies] = value
+    end
+
+    add_option(:"Install/Update", '-y', '--include-dependencies',
+               'Unconditionally install the required',
+               'dependent gems') do |value, options|
+      options[:include_dependencies] = value
+    end
+
+    add_option(:"Install/Update",       '--[no-]format-executable',
+               'Make installed executable names match ruby.',
+               'If ruby is ruby18, foo_exec will be',
+               'foo_exec18') do |value, options|
+      options[:format_executable] = value
+    end
+
+    add_option(:"Install/Update",       '--[no-]user-install',
+               'Install in user\'s home directory instead',
+               'of GEM_HOME.') do |value, options|
+      options[:user_install] = value
+    end
+
+    add_option(:"Install/Update", "--development",
+                "Install any additional development",
+                "dependencies") do |value, options|
+      options[:development] = true
+    end
+
+    add_option(:"Install/Update", "--prerelease",
+               "Install prerelease versions of a gem if",
+               "available. Defaults to skipping",
+               "prereleases.") do |value, options|
+      options[:prerelease] = true
+    end
+  end
+
+  ##
+  # Default options for the gem install command.
+
+  def install_update_defaults_str
+    '--rdoc --no-force --no-test --wrappers'
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/installer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/installer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/installer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,559 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'fileutils'
+require 'pathname'
+require 'rbconfig'
+
+require 'rubygems/format'
+require 'rubygems/ext'
+require 'rubygems/require_paths_builder'
+
+##
+# The installer class processes RubyGem .gem files and installs the files
+# contained in the .gem into the Gem.path.
+#
+# Gem::Installer does the work of putting files in all the right places on the
+# filesystem including unpacking the gem into its gem dir, installing the
+# gemspec in the specifications dir, storing the cached gem in the cache dir,
+# and installing either wrappers or symlinks for executables.
+#
+# The installer fires pre and post install hooks.  Hooks can be added either
+# through a rubygems_plugin.rb file in an installed gem or via a
+# rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb
+# file.  See Gem.pre_install and Gem.post_install for details.
+
+class Gem::Installer
+
+  ##
+  # Paths where env(1) might live.  Some systems are broken and have it in
+  # /bin
+
+  ENV_PATHS = %w[/usr/bin/env /bin/env]
+
+  ##
+  # Raised when there is an error while building extensions.
+  #
+  class ExtensionBuildError < Gem::InstallError; end
+
+  include Gem::UserInteraction
+
+  include Gem::RequirePathsBuilder
+
+  ##
+  # The directory a gem's executables will be installed into
+
+  attr_reader :bin_dir
+
+  ##
+  # The gem repository the gem will be installed into
+
+  attr_reader :gem_home
+
+  ##
+  # The Gem::Specification for the gem being installed
+
+  attr_reader :spec
+
+  @path_warning = false
+
+  class << self
+
+    ##
+    # True if we've warned about PATH not including Gem.bindir
+
+    attr_accessor :path_warning
+
+    attr_writer :exec_format
+
+    # Defaults to use Ruby's program prefix and suffix.
+    def exec_format
+      @exec_format ||= Gem.default_exec_format
+    end
+
+  end
+
+  ##
+  # Constructs an Installer instance that will install the gem located at
+  # +gem+.  +options+ is a Hash with the following keys:
+  #
+  # :env_shebang:: Use /usr/bin/env in bin wrappers.
+  # :force:: Overrides all version checks and security policy checks, except
+  #          for a signed-gems-only policy.
+  # :ignore_dependencies:: Don't raise if a dependency is missing.
+  # :install_dir:: The directory to install the gem into.
+  # :format_executable:: Format the executable the same as the ruby executable.
+  #                      If your ruby is ruby18, foo_exec will be installed as
+  #                      foo_exec18.
+  # :security_policy:: Use the specified security policy.  See Gem::Security
+  # :wrappers:: Install wrappers if true, symlinks if false.
+
+  def initialize(gem, options={})
+    @gem = gem
+
+    options = {
+      :bin_dir      => nil,
+      :env_shebang  => false,
+      :exec_format  => false,
+      :force        => false,
+      :install_dir  => Gem.dir,
+      :source_index => Gem.source_index,
+    }.merge options
+
+    @env_shebang         = options[:env_shebang]
+    @force               = options[:force]
+    gem_home             = options[:install_dir]
+    @gem_home            = Pathname.new(gem_home).expand_path
+    @ignore_dependencies = options[:ignore_dependencies]
+    @format_executable   = options[:format_executable]
+    @security_policy     = options[:security_policy]
+    @wrappers            = options[:wrappers]
+    @bin_dir             = options[:bin_dir]
+    @development         = options[:development]
+    @source_index        = options[:source_index]
+
+    begin
+      @format = Gem::Format.from_file_by_path @gem, @security_policy
+    rescue Gem::Package::FormatError
+      raise Gem::InstallError, "invalid gem format for #{@gem}"
+    end
+
+    if options[:user_install] and not options[:unpack] then
+      @gem_home = Gem.user_dir
+
+      user_bin_dir = File.join(@gem_home, 'bin')
+      unless ENV['PATH'].split(File::PATH_SEPARATOR).include? user_bin_dir then
+        unless self.class.path_warning then
+          alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t  gem executables will not run."
+          self.class.path_warning = true
+        end
+      end
+    end
+
+    FileUtils.mkdir_p @gem_home
+    raise Gem::FilePermissionError, @gem_home unless File.writable? @gem_home
+
+    @spec = @format.spec
+
+    @gem_dir = File.join(@gem_home, "gems", @spec.full_name).untaint
+  end
+
+  ##
+  # Installs the gem and returns a loaded Gem::Specification for the installed
+  # gem.
+  #
+  # The gem will be installed with the following structure:
+  #
+  #   @gem_home/
+  #     cache/<gem-version>.gem #=> a cached copy of the installed gem
+  #     gems/<gem-version>/... #=> extracted files
+  #     specifications/<gem-version>.gemspec #=> the Gem::Specification
+
+  def install
+    # If we're forcing the install then disable security unless the security
+    # policy says that we only install singed gems.
+    @security_policy = nil if @force and @security_policy and
+                              not @security_policy.only_signed
+
+    unless @force then
+      if rrv = @spec.required_ruby_version then
+        unless rrv.satisfied_by? Gem.ruby_version then
+          raise Gem::InstallError, "#{@spec.name} requires Ruby version #{rrv}"
+        end
+      end
+
+      if rrgv = @spec.required_rubygems_version then
+        unless rrgv.satisfied_by? Gem::Version.new(Gem::RubyGemsVersion) then
+          raise Gem::InstallError,
+                "#{@spec.name} requires RubyGems version #{rrgv}"
+        end
+      end
+
+      unless @ignore_dependencies then
+        deps = @spec.runtime_dependencies
+        deps |= @spec.development_dependencies if @development
+
+        deps.each do |dep_gem|
+          ensure_dependency @spec, dep_gem
+        end
+      end
+    end
+
+    Gem.pre_install_hooks.each do |hook|
+      hook.call self
+    end
+
+    FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
+
+    Gem.ensure_gem_subdirectories @gem_home
+
+    FileUtils.mkdir_p @gem_dir
+
+    extract_files
+    generate_bin
+    build_extensions
+    write_spec
+
+    write_require_paths_file_if_needed
+
+    # HACK remove?  Isn't this done in multiple places?
+    cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop
+    unless File.exist? cached_gem then
+      FileUtils.cp @gem, File.join(@gem_home, "cache")
+    end
+
+    say @spec.post_install_message unless @spec.post_install_message.nil?
+
+    @spec.loaded_from = File.join(@gem_home, 'specifications', @spec.spec_name)
+
+    @source_index.add_spec @spec
+
+    Gem.post_install_hooks.each do |hook|
+      hook.call self
+    end
+
+    return @spec
+  rescue Zlib::GzipFile::Error
+    raise Gem::InstallError, "gzip error installing #{@gem}"
+  end
+
+  ##
+  # Ensure that the dependency is satisfied by the current installation of
+  # gem.  If it is not an exception is raised.
+  #
+  # spec       :: Gem::Specification
+  # dependency :: Gem::Dependency
+
+  def ensure_dependency(spec, dependency)
+    unless installation_satisfies_dependency? dependency then
+      raise Gem::InstallError, "#{spec.name} requires #{dependency}"
+    end
+
+    true
+  end
+
+  ##
+  # True if the gems in the source_index satisfy +dependency+.
+
+  def installation_satisfies_dependency?(dependency)
+    @source_index.find_name(dependency.name, dependency.version_requirements).size > 0
+  end
+
+  ##
+  # Unpacks the gem into the given directory.
+
+  def unpack(directory)
+    @gem_dir = directory
+    @format = Gem::Format.from_file_by_path @gem, @security_policy
+    extract_files
+  end
+
+  ##
+  # Writes the .gemspec specification (in Ruby) to the gem home's
+  # specifications directory.
+
+  def write_spec
+    rubycode = @spec.to_ruby
+
+    file_name = File.join @gem_home, 'specifications', @spec.spec_name
+
+    file_name.untaint
+
+    File.open(file_name, "w") do |file|
+      file.puts rubycode
+    end
+  end
+
+  ##
+  # Creates windows .bat files for easy running of commands
+
+  def generate_windows_script(bindir, filename)
+    if Gem.win_platform? then
+      script_name = filename + ".bat"
+      script_path = File.join bindir, File.basename(script_name)
+      File.open script_path, 'w' do |file|
+        file.puts windows_stub_script(bindir, filename)
+      end
+
+      say script_path if Gem.configuration.really_verbose
+    end
+  end
+
+  def generate_bin
+    return if @spec.executables.nil? or @spec.executables.empty?
+
+    # If the user has asked for the gem to be installed in a directory that is
+    # the system gem directory, then use the system bin directory, else create
+    # (or use) a new bin dir under the gem_home.
+    bindir = @bin_dir ? @bin_dir : Gem.bindir(@gem_home)
+
+    Dir.mkdir bindir unless File.exist? bindir
+    raise Gem::FilePermissionError.new(bindir) unless File.writable? bindir
+
+    @spec.executables.each do |filename|
+      filename.untaint
+      bin_path = File.expand_path File.join(@gem_dir, @spec.bindir, filename)
+      mode = File.stat(bin_path).mode | 0111
+      File.chmod mode, bin_path
+
+      if @wrappers then
+        generate_bin_script filename, bindir
+      else
+        generate_bin_symlink filename, bindir
+      end
+    end
+  end
+
+  ##
+  # Creates the scripts to run the applications in the gem.
+  #--
+  # The Windows script is generated in addition to the regular one due to a
+  # bug or misfeature in the Windows shell's pipe.  See
+  # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379
+
+  def generate_bin_script(filename, bindir)
+    bin_script_path = File.join bindir, formatted_program_filename(filename)
+
+    exec_path = File.join @gem_dir, @spec.bindir, filename
+
+    # HACK some gems don't have #! in their executables, restore 2008/06
+    #if File.read(exec_path, 2) == '#!' then
+      FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
+
+      File.open bin_script_path, 'w', 0755 do |file|
+        file.print app_script_text(filename)
+      end
+
+      say bin_script_path if Gem.configuration.really_verbose
+
+      generate_windows_script bindir, filename
+    #else
+    #  FileUtils.rm_f bin_script_path
+    #  FileUtils.cp exec_path, bin_script_path,
+    #               :verbose => Gem.configuration.really_verbose
+    #end
+  end
+
+  ##
+  # Creates the symlinks to run the applications in the gem.  Moves
+  # the symlink if the gem being installed has a newer version.
+
+  def generate_bin_symlink(filename, bindir)
+    if Gem.win_platform? then
+      alert_warning "Unable to use symlinks on Windows, installing wrapper"
+      generate_bin_script filename, bindir
+      return
+    end
+
+    src = File.join @gem_dir, 'bin', filename
+    dst = File.join bindir, formatted_program_filename(filename)
+
+    if File.exist? dst then
+      if File.symlink? dst then
+        link = File.readlink(dst).split File::SEPARATOR
+        cur_version = Gem::Version.create(link[-3].sub(/^.*-/, ''))
+        return if @spec.version < cur_version
+      end
+      File.unlink dst
+    end
+
+    FileUtils.symlink src, dst, :verbose => Gem.configuration.really_verbose
+  end
+
+  ##
+  # Generates a #! line for +bin_file_name+'s wrapper copying arguments if
+  # necessary.
+
+  def shebang(bin_file_name)
+    ruby_name = Gem::ConfigMap[:ruby_install_name] if @env_shebang
+    path = File.join @gem_dir, @spec.bindir, bin_file_name
+    first_line = File.open(path, "rb") {|file| file.gets}
+
+    if /\A#!/ =~ first_line then
+      # Preserve extra words on shebang line, like "-w".  Thanks RPA.
+      shebang = first_line.sub(/\A\#!.*?ruby\S*(?=(\s+\S+))/, "#!#{Gem.ruby}")
+      opts = $1
+      shebang.strip! # Avoid nasty ^M issues.
+    end
+
+    if not ruby_name then
+      "#!#{Gem.ruby}#{opts}"
+    elsif opts then
+      "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
+    else
+      # Create a plain shebang line.
+      @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
+      "#!#{@env_path} #{ruby_name}"
+    end
+  end
+
+  ##
+  # Return the text for an application file.
+
+  def app_script_text(bin_file_name)
+    <<-TEXT
+#{shebang bin_file_name}
+#
+# This file was generated by RubyGems.
+#
+# The application '#{@spec.name}' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = "#{Gem::Requirement.default}"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+  version = $1
+  ARGV.shift
+end
+
+gem '#{@spec.name}', version
+load Gem.bin_path('#{@spec.name}', '#{bin_file_name}', version)
+TEXT
+  end
+
+  ##
+  # return the stub script text used to launch the true ruby script
+
+  def windows_stub_script(bindir, bin_file_name)
+    <<-TEXT
+ at ECHO OFF
+IF NOT "%~f0" == "~f0" GOTO :WinNT
+@"#{File.basename(Gem.ruby).chomp('"')}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
+GOTO :EOF
+:WinNT
+@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
+TEXT
+  end
+
+  ##
+  # Builds extensions.  Valid types of extensions are extconf.rb files,
+  # configure scripts and rakefiles or mkrf_conf files.
+
+  def build_extensions
+    return if @spec.extensions.empty?
+    say "Building native extensions.  This could take a while..."
+    start_dir = Dir.pwd
+    dest_path = File.join @gem_dir, @spec.require_paths.first
+    ran_rake = false # only run rake once
+
+    @spec.extensions.each do |extension|
+      break if ran_rake
+      results = []
+
+      builder = case extension
+                when /extconf/ then
+                  Gem::Ext::ExtConfBuilder
+                when /configure/ then
+                  Gem::Ext::ConfigureBuilder
+                when /rakefile/i, /mkrf_conf/i then
+                  ran_rake = true
+                  Gem::Ext::RakeBuilder
+                else
+                  results = ["No builder for extension '#{extension}'"]
+                  nil
+                end
+
+      begin
+        Dir.chdir File.join(@gem_dir, File.dirname(extension))
+        results = builder.build(extension, @gem_dir, dest_path, results)
+
+        say results.join("\n") if Gem.configuration.really_verbose
+
+      rescue => ex
+        results = results.join "\n"
+
+        File.open('gem_make.out', 'wb') { |f| f.puts results }
+
+        message = <<-EOF
+ERROR: Failed to build gem native extension.
+
+#{results}
+
+Gem files will remain installed in #{@gem_dir} for inspection.
+Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
+        EOF
+
+        raise ExtensionBuildError, message
+      ensure
+        Dir.chdir start_dir
+      end
+    end
+  end
+
+  ##
+  # Reads the file index and extracts each file into the gem directory.
+  #
+  # Ensures that files can't be installed outside the gem directory.
+
+  def extract_files
+    expand_and_validate_gem_dir
+
+    raise ArgumentError, "format required to extract from" if @format.nil?
+
+    @format.file_entries.each do |entry, file_data|
+      path = entry['path'].untaint
+
+      if path =~ /\A\// then # for extra sanity
+        raise Gem::InstallError,
+              "attempt to install file into #{entry['path'].inspect}"
+      end
+
+      path = File.expand_path File.join(@gem_dir, path)
+
+      if path !~ /\A#{Regexp.escape @gem_dir}/ then
+        msg = "attempt to install file into %p under %p" %
+                [entry['path'], @gem_dir]
+        raise Gem::InstallError, msg
+      end
+
+      FileUtils.rm_rf(path) if File.exists?(path)
+      FileUtils.mkdir_p File.dirname(path)
+
+      File.open(path, "wb") do |out|
+        out.write file_data
+      end
+
+      FileUtils.chmod entry['mode'], path
+
+      say path if Gem.configuration.really_verbose
+    end
+  end
+
+  ##
+  # Prefix and suffix the program filename the same as ruby.
+
+  def formatted_program_filename(filename)
+    if @format_executable then
+      self.class.exec_format % File.basename(filename)
+    else
+      filename
+    end
+  end
+
+  private
+
+  ##
+  # HACK Pathname is broken on windows.
+
+  def absolute_path? pathname
+    pathname.absolute? or (Gem.win_platform? and pathname.to_s =~ /\A[a-z]:/i)
+  end
+
+  def expand_and_validate_gem_dir
+    @gem_dir = Pathname.new(@gem_dir).expand_path
+
+    unless absolute_path?(@gem_dir) then # HACK is this possible after #expand_path?
+      raise ArgumentError, "install directory %p not absolute" % @gem_dir
+    end
+
+    @gem_dir = @gem_dir.to_s
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/local_remote_options.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/local_remote_options.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/local_remote_options.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,135 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'uri'
+require 'rubygems'
+
+##
+# Mixin methods for local and remote Gem::Command options.
+
+module Gem::LocalRemoteOptions
+
+  ##
+  # Allows OptionParser to handle HTTP URIs.
+
+  def accept_uri_http
+    OptionParser.accept URI::HTTP do |value|
+      begin
+        uri = URI.parse value
+      rescue URI::InvalidURIError
+        raise OptionParser::InvalidArgument, value
+      end
+
+      unless ['http', 'https', 'file'].include?(uri.scheme)
+         raise OptionParser::InvalidArgument, value
+      end
+
+      value
+    end
+  end
+
+  ##
+  # Add local/remote options to the command line parser.
+
+  def add_local_remote_options
+    add_option(:"Local/Remote", '-l', '--local',
+               'Restrict operations to the LOCAL domain') do |value, options|
+      options[:domain] = :local
+    end
+
+    add_option(:"Local/Remote", '-r', '--remote',
+      'Restrict operations to the REMOTE domain') do |value, options|
+      options[:domain] = :remote
+    end
+
+    add_option(:"Local/Remote", '-b', '--both',
+               'Allow LOCAL and REMOTE operations') do |value, options|
+      options[:domain] = :both
+    end
+
+    add_bulk_threshold_option
+    add_source_option
+    add_proxy_option
+    add_update_sources_option
+  end
+
+  ##
+  # Add the --bulk-threshold option
+
+  def add_bulk_threshold_option
+    add_option(:"Local/Remote", '-B', '--bulk-threshold COUNT',
+               "Threshold for switching to bulk",
+               "synchronization (default #{Gem.configuration.bulk_threshold})") do
+      |value, options|
+      Gem.configuration.bulk_threshold = value.to_i
+    end
+  end
+
+  ##
+  # Add the --http-proxy option
+
+  def add_proxy_option
+    accept_uri_http
+
+    add_option(:"Local/Remote", '-p', '--[no-]http-proxy [URL]', URI::HTTP,
+               'Use HTTP proxy for remote operations') do |value, options|
+      options[:http_proxy] = (value == false) ? :no_proxy : value
+      Gem.configuration[:http_proxy] = options[:http_proxy]
+    end
+  end
+
+  ##
+  # Add the --source option
+
+  def add_source_option
+    accept_uri_http
+
+    add_option(:"Local/Remote", '--source URL', URI::HTTP,
+               'Use URL as the remote source for gems') do |source, options|
+      source << '/' if source !~ /\/\z/
+
+      if options[:added_source] then
+        Gem.sources << source unless Gem.sources.include?(source)
+      else
+        options[:added_source] = true
+        Gem.sources.replace [source]
+      end
+    end
+  end
+
+  ##
+  # Add the --update-sources option
+
+  def add_update_sources_option
+    add_option(:"Local/Remote", '-u', '--[no-]update-sources',
+               'Update local source cache') do |value, options|
+      Gem.configuration.update_sources = value
+    end
+  end
+
+  ##
+  # Is fetching of local and remote information enabled?
+
+  def both?
+    options[:domain] == :both
+  end
+
+  ##
+  # Is local fetching enabled?
+
+  def local?
+    options[:domain] == :local || options[:domain] == :both
+  end
+
+  ##
+  # Is remote fetching enabled?
+
+  def remote?
+    options[:domain] == :remote || options[:domain] == :both
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/old_format.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/old_format.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/old_format.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,152 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+require 'fileutils'
+require 'yaml'
+require 'zlib'
+
+##
+# The format class knows the guts of the RubyGem .gem file format and provides
+# the capability to read gem files
+
+class Gem::OldFormat
+
+  attr_accessor :spec, :file_entries, :gem_path
+
+  ##
+  # Constructs an instance of a Format object, representing the gem's data
+  # structure.
+  #
+  # gem:: [String] The file name of the gem
+
+  def initialize(gem_path)
+    @gem_path = gem_path
+  end
+
+  ##
+  # Reads the named gem file and returns a Format object, representing the
+  # data from the gem file
+  #
+  # file_path:: [String] Path to the gem file
+
+  def self.from_file_by_path(file_path)
+    unless File.exist?(file_path)
+      raise Gem::Exception, "Cannot load gem file [#{file_path}]"
+    end
+
+    File.open(file_path, 'rb') do |file|
+      from_io(file, file_path)
+    end
+  end
+
+  ##
+  # Reads a gem from an io stream and returns a Format object, representing
+  # the data from the gem file
+  #
+  # io:: [IO] Stream from which to read the gem
+
+  def self.from_io(io, gem_path="(io)")
+    format = self.new(gem_path)
+    skip_ruby(io)
+    format.spec = read_spec(io)
+    format.file_entries = []
+    read_files_from_gem(io) do |entry, file_data|
+      format.file_entries << [entry, file_data]
+    end
+    format
+  end
+
+  private
+
+  ##
+  # Skips the Ruby self-install header.  After calling this method, the
+  # IO index will be set after the Ruby code.
+  #
+  # file:: [IO] The IO to process (skip the Ruby code)
+
+  def self.skip_ruby(file)
+    end_seen = false
+    loop {
+      line = file.gets
+      if(line == nil || line.chomp == "__END__") then
+        end_seen = true
+        break
+      end
+    }
+
+    if end_seen == false then
+      raise Gem::Exception.new("Failed to find end of ruby script while reading gem")
+    end
+  end
+
+  ##
+  # Reads the specification YAML from the supplied IO and constructs
+  # a Gem::Specification from it.  After calling this method, the
+  # IO index will be set after the specification header.
+  #
+  # file:: [IO] The IO to process
+
+  def self.read_spec(file)
+    yaml = ''
+
+    read_until_dashes file do |line|
+      yaml << line
+    end
+
+    Gem::Specification.from_yaml yaml
+  rescue YAML::Error => e
+    raise Gem::Exception, "Failed to parse gem specification out of gem file"
+  rescue ArgumentError => e
+    raise Gem::Exception, "Failed to parse gem specification out of gem file"
+  end
+
+  ##
+  # Reads lines from the supplied IO until a end-of-yaml (---) is
+  # reached
+  #
+  # file:: [IO] The IO to process
+  # block:: [String] The read line
+
+  def self.read_until_dashes(file)
+    while((line = file.gets) && line.chomp.strip != "---") do
+      yield line
+    end
+  end
+
+  ##
+  # Reads the embedded file data from a gem file, yielding an entry
+  # containing metadata about the file and the file contents themselves
+  # for each file that's archived in the gem.
+  # NOTE: Many of these methods should be extracted into some kind of
+  # Gem file read/writer
+  #
+  # gem_file:: [IO] The IO to process
+
+  def self.read_files_from_gem(gem_file)
+    errstr = "Error reading files from gem"
+    header_yaml = ''
+    begin
+      self.read_until_dashes(gem_file) do |line|
+        header_yaml << line
+      end
+      header = YAML.load(header_yaml)
+      raise Gem::Exception, errstr unless header
+
+      header.each do |entry|
+        file_data = ''
+        self.read_until_dashes(gem_file) do |line|
+          file_data << line
+        end
+        yield [entry, Zlib::Inflate.inflate(file_data.strip.unpack("m")[0])]
+      end
+    rescue Zlib::DataError => e
+      raise Gem::Exception, errstr
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/f_sync_dir.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/f_sync_dir.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/f_sync_dir.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,22 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+module Gem::Package::FSyncDir
+
+  private
+
+  ##
+  # make sure this hits the disc
+
+  def fsync_dir(dirname)
+    dir = open dirname, 'r'
+    dir.fsync
+  rescue # ignore IOError if it's an unpatched (old) Ruby
+  ensure
+    dir.close if dir rescue nil
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_header.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_header.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_header.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,265 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+##
+#--
+# struct tarfile_entry_posix {
+#   char name[100];     # ASCII + (Z unless filled)
+#   char mode[8];       # 0 padded, octal, null
+#   char uid[8];        # ditto
+#   char gid[8];        # ditto
+#   char size[12];      # 0 padded, octal, null
+#   char mtime[12];     # 0 padded, octal, null
+#   char checksum[8];   # 0 padded, octal, null, space
+#   char typeflag[1];   # file: "0"  dir: "5"
+#   char linkname[100]; # ASCII + (Z unless filled)
+#   char magic[6];      # "ustar\0"
+#   char version[2];    # "00"
+#   char uname[32];     # ASCIIZ
+#   char gname[32];     # ASCIIZ
+#   char devmajor[8];   # 0 padded, octal, null
+#   char devminor[8];   # o padded, octal, null
+#   char prefix[155];   # ASCII + (Z unless filled)
+# };
+#++
+# A header for a tar file
+
+class Gem::Package::TarHeader
+
+  ##
+  # Fields in the tar header
+
+  FIELDS = [
+    :checksum,
+    :devmajor,
+    :devminor,
+    :gid,
+    :gname,
+    :linkname,
+    :magic,
+    :mode,
+    :mtime,
+    :name,
+    :prefix,
+    :size,
+    :typeflag,
+    :uid,
+    :uname,
+    :version,
+  ]
+
+  ##
+  # Pack format for a tar header
+
+  PACK_FORMAT = 'a100' + # name
+                'a8'   + # mode
+                'a8'   + # uid
+                'a8'   + # gid
+                'a12'  + # size
+                'a12'  + # mtime
+                'a7a'  + # chksum
+                'a'    + # typeflag
+                'a100' + # linkname
+                'a6'   + # magic
+                'a2'   + # version
+                'a32'  + # uname
+                'a32'  + # gname
+                'a8'   + # devmajor
+                'a8'   + # devminor
+                'a155'   # prefix
+
+  ##
+  # Unpack format for a tar header
+
+  UNPACK_FORMAT = 'A100' + # name
+                  'A8'   + # mode
+                  'A8'   + # uid
+                  'A8'   + # gid
+                  'A12'  + # size
+                  'A12'  + # mtime
+                  'A8'   + # checksum
+                  'A'    + # typeflag
+                  'A100' + # linkname
+                  'A6'   + # magic
+                  'A2'   + # version
+                  'A32'  + # uname
+                  'A32'  + # gname
+                  'A8'   + # devmajor
+                  'A8'   + # devminor
+                  'A155'   # prefix
+
+  attr_reader(*FIELDS)
+
+  ##
+  # Creates a tar header from IO +stream+
+
+  def self.from(stream)
+    header = stream.read 512
+    empty = (header == "\0" * 512)
+
+    fields = header.unpack UNPACK_FORMAT
+
+    name     = fields.shift
+    mode     = fields.shift.oct
+    uid      = fields.shift.oct
+    gid      = fields.shift.oct
+    size     = fields.shift.oct
+    mtime    = fields.shift.oct
+    checksum = fields.shift.oct
+    typeflag = fields.shift
+    linkname = fields.shift
+    magic    = fields.shift
+    version  = fields.shift.oct
+    uname    = fields.shift
+    gname    = fields.shift
+    devmajor = fields.shift.oct
+    devminor = fields.shift.oct
+    prefix   = fields.shift
+
+    new :name     => name,
+        :mode     => mode,
+        :uid      => uid,
+        :gid      => gid,
+        :size     => size,
+        :mtime    => mtime,
+        :checksum => checksum,
+        :typeflag => typeflag,
+        :linkname => linkname,
+        :magic    => magic,
+        :version  => version,
+        :uname    => uname,
+        :gname    => gname,
+        :devmajor => devmajor,
+        :devminor => devminor,
+        :prefix   => prefix,
+
+        :empty    => empty
+
+    # HACK unfactor for Rubinius
+    #new :name     => fields.shift,
+    #    :mode     => fields.shift.oct,
+    #    :uid      => fields.shift.oct,
+    #    :gid      => fields.shift.oct,
+    #    :size     => fields.shift.oct,
+    #    :mtime    => fields.shift.oct,
+    #    :checksum => fields.shift.oct,
+    #    :typeflag => fields.shift,
+    #    :linkname => fields.shift,
+    #    :magic    => fields.shift,
+    #    :version  => fields.shift.oct,
+    #    :uname    => fields.shift,
+    #    :gname    => fields.shift,
+    #    :devmajor => fields.shift.oct,
+    #    :devminor => fields.shift.oct,
+    #    :prefix   => fields.shift,
+
+    #    :empty => empty
+  end
+
+  ##
+  # Creates a new TarHeader using +vals+
+
+  def initialize(vals)
+    unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] then
+      raise ArgumentError, ":name, :size, :prefix and :mode required"
+    end
+
+    vals[:uid] ||= 0
+    vals[:gid] ||= 0
+    vals[:mtime] ||= 0
+    vals[:checksum] ||= ""
+    vals[:typeflag] ||= "0"
+    vals[:magic] ||= "ustar"
+    vals[:version] ||= "00"
+    vals[:uname] ||= "wheel"
+    vals[:gname] ||= "wheel"
+    vals[:devmajor] ||= 0
+    vals[:devminor] ||= 0
+
+    FIELDS.each do |name|
+      instance_variable_set "@#{name}", vals[name]
+    end
+
+    @empty = vals[:empty]
+  end
+
+  ##
+  # Is the tar entry empty?
+
+  def empty?
+    @empty
+  end
+
+  def ==(other) # :nodoc:
+    self.class === other and
+    @checksum == other.checksum and
+    @devmajor == other.devmajor and
+    @devminor == other.devminor and
+    @gid      == other.gid      and
+    @gname    == other.gname    and
+    @linkname == other.linkname and
+    @magic    == other.magic    and
+    @mode     == other.mode     and
+    @mtime    == other.mtime    and
+    @name     == other.name     and
+    @prefix   == other.prefix   and
+    @size     == other.size     and
+    @typeflag == other.typeflag and
+    @uid      == other.uid      and
+    @uname    == other.uname    and
+    @version  == other.version
+  end
+
+  def to_s # :nodoc:
+    update_checksum
+    header
+  end
+
+  ##
+  # Updates the TarHeader's checksum
+
+  def update_checksum
+    header = header " " * 8
+    @checksum = oct calculate_checksum(header), 6
+  end
+
+  private
+
+  def calculate_checksum(header)
+    header.unpack("C*").inject { |a, b| a + b }
+  end
+
+  def header(checksum = @checksum)
+    header = [
+      name,
+      oct(mode, 7),
+      oct(uid, 7),
+      oct(gid, 7),
+      oct(size, 11),
+      oct(mtime, 11),
+      checksum,
+      " ",
+      typeflag,
+      linkname,
+      magic,
+      oct(version, 2),
+      uname,
+      gname,
+      oct(devmajor, 7),
+      oct(devminor, 7),
+      prefix
+    ]
+
+    header = header.pack PACK_FORMAT
+
+    header << ("\0" * ((512 - header.size) % 512))
+  end
+
+  def oct(num, len)
+    "%0#{len}o" % num
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_input.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_input.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_input.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,219 @@
+# -*- coding: iso-8859-1 -*-
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+class Gem::Package::TarInput
+
+  include Gem::Package::FSyncDir
+  include Enumerable
+
+  attr_reader :metadata
+
+  private_class_method :new
+
+  def self.open(io, security_policy = nil,  &block)
+    is = new io, security_policy
+
+    yield is
+  ensure
+    is.close if is
+  end
+
+  def initialize(io, security_policy = nil)
+    @io = io
+    @tarreader = Gem::Package::TarReader.new @io
+    has_meta = false
+
+    data_sig, meta_sig, data_dgst, meta_dgst = nil, nil, nil, nil
+    dgst_algo = security_policy ? Gem::Security::OPT[:dgst_algo] : nil
+
+    @tarreader.each do |entry|
+      case entry.full_name
+      when "metadata"
+        @metadata = load_gemspec entry.read
+        has_meta = true
+      when "metadata.gz"
+        begin
+          # if we have a security_policy, then pre-read the metadata file
+          # and calculate it's digest
+          sio = nil
+          if security_policy
+            Gem.ensure_ssl_available
+            sio = StringIO.new(entry.read)
+            meta_dgst = dgst_algo.digest(sio.string)
+            sio.rewind
+          end
+
+          gzis = Zlib::GzipReader.new(sio || entry)
+          # YAML wants an instance of IO
+          @metadata = load_gemspec(gzis)
+          has_meta = true
+        ensure
+          gzis.close unless gzis.nil?
+        end
+      when 'metadata.gz.sig'
+        meta_sig = entry.read
+      when 'data.tar.gz.sig'
+        data_sig = entry.read
+      when 'data.tar.gz'
+        if security_policy
+          Gem.ensure_ssl_available
+          data_dgst = dgst_algo.digest(entry.read)
+        end
+      end
+    end
+
+    if security_policy then
+      Gem.ensure_ssl_available
+
+      # map trust policy from string to actual class (or a serialized YAML
+      # file, if that exists)
+      if String === security_policy then
+        if Gem::Security::Policies.key? security_policy then
+          # load one of the pre-defined security policies
+          security_policy = Gem::Security::Policies[security_policy]
+        elsif File.exist? security_policy then
+          # FIXME: this doesn't work yet
+          security_policy = YAML.load File.read(security_policy)
+        else
+          raise Gem::Exception, "Unknown trust policy '#{security_policy}'"
+        end
+      end
+
+      if data_sig && data_dgst && meta_sig && meta_dgst then
+        # the user has a trust policy, and we have a signed gem
+        # file, so use the trust policy to verify the gem signature
+
+        begin
+          security_policy.verify_gem(data_sig, data_dgst, @metadata.cert_chain)
+        rescue Exception => e
+          raise "Couldn't verify data signature: #{e}"
+        end
+
+        begin
+          security_policy.verify_gem(meta_sig, meta_dgst, @metadata.cert_chain)
+        rescue Exception => e
+          raise "Couldn't verify metadata signature: #{e}"
+        end
+      elsif security_policy.only_signed
+        raise Gem::Exception, "Unsigned gem"
+      else
+        # FIXME: should display warning here (trust policy, but
+        # either unsigned or badly signed gem file)
+      end
+    end
+
+    @tarreader.rewind
+    @fileops = Gem::FileOperations.new
+
+    raise Gem::Package::FormatError, "No metadata found!" unless has_meta
+  end
+
+  def close
+    @io.close
+    @tarreader.close
+  end
+
+  def each(&block)
+    @tarreader.each do |entry|
+      next unless entry.full_name == "data.tar.gz"
+      is = zipped_stream entry
+
+      begin
+        Gem::Package::TarReader.new is do |inner|
+          inner.each(&block)
+        end
+      ensure
+        is.close if is
+      end
+    end
+
+    @tarreader.rewind
+  end
+
+  def extract_entry(destdir, entry, expected_md5sum = nil)
+    if entry.directory? then
+      dest = File.join destdir, entry.full_name
+
+      if File.directory? dest then
+        @fileops.chmod entry.header.mode, dest, :verbose => false
+      else
+        @fileops.mkdir_p dest, :mode => entry.header.mode, :verbose => false
+      end
+
+      fsync_dir dest
+      fsync_dir File.join(dest, "..")
+
+      return
+    end
+
+    # it's a file
+    md5 = Digest::MD5.new if expected_md5sum
+    destdir = File.join destdir, File.dirname(entry.full_name)
+    @fileops.mkdir_p destdir, :mode => 0755, :verbose => false
+    destfile = File.join destdir, File.basename(entry.full_name)
+    @fileops.chmod 0600, destfile, :verbose => false rescue nil # Errno::ENOENT
+
+    open destfile, "wb", entry.header.mode do |os|
+      loop do
+        data = entry.read 4096
+        break unless data
+        # HACK shouldn't we check the MD5 before writing to disk?
+        md5 << data if expected_md5sum
+        os.write(data)
+      end
+
+      os.fsync
+    end
+
+    @fileops.chmod entry.header.mode, destfile, :verbose => false
+    fsync_dir File.dirname(destfile)
+    fsync_dir File.join(File.dirname(destfile), "..")
+
+    if expected_md5sum && expected_md5sum != md5.hexdigest then
+      raise Gem::Package::BadCheckSum
+    end
+  end
+
+  # Attempt to YAML-load a gemspec from the given _io_ parameter.  Return
+  # nil if it fails.
+  def load_gemspec(io)
+    Gem::Specification.from_yaml io
+  rescue Gem::Exception
+    nil
+  end
+
+  ##
+  # Return an IO stream for the zipped entry.
+  #
+  # NOTE:  Originally this method used two approaches, Return a GZipReader
+  # directly, or read the GZipReader into a string and return a StringIO on
+  # the string.  The string IO approach was used for versions of ZLib before
+  # 1.2.1 to avoid buffer errors on windows machines.  Then we found that
+  # errors happened with 1.2.1 as well, so we changed the condition.  Then
+  # we discovered errors occurred with versions as late as 1.2.3.  At this
+  # point (after some benchmarking to show we weren't seriously crippling
+  # the unpacking speed) we threw our hands in the air and declared that
+  # this method would use the String IO approach on all platforms at all
+  # times.  And that's the way it is.
+
+  def zipped_stream(entry)
+    if defined? Rubinius or defined? Maglev then
+      # these implementations have working Zlib
+      zis = Zlib::GzipReader.new entry
+      dis = zis.read
+      is = StringIO.new(dis)
+    else
+      # This is Jamis Buck's Zlib workaround for some unknown issue
+      entry.read(10) # skip the gzip header
+      zis = Zlib::Inflate.new(-Zlib::MAX_WBITS)
+      is = StringIO.new(zis.inflate(entry.read))
+    end
+  ensure
+    zis.finish if zis
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_output.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_output.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_output.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,143 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+##
+# TarOutput is a wrapper to TarWriter that builds gem-format tar file.
+#
+# Gem-format tar files contain the following files:
+# [data.tar.gz] A gzipped tar file containing the files that compose the gem
+#               which will be extracted into the gem/ dir on installation.
+# [metadata.gz] A YAML format Gem::Specification.
+# [data.tar.gz.sig] A signature for the gem's data.tar.gz.
+# [metadata.gz.sig] A signature for the gem's metadata.gz.
+#
+# See TarOutput::open for usage details.
+
+class Gem::Package::TarOutput
+
+  ##
+  # Creates a new TarOutput which will yield a TarWriter object for the
+  # data.tar.gz portion of a gem-format tar file.
+  #
+  # See #initialize for details on +io+ and +signer+.
+  #
+  # See #add_gem_contents for details on adding metadata to the tar file.
+
+  def self.open(io, signer = nil, &block) # :yield: data_tar_writer
+    tar_outputter = new io, signer
+    tar_outputter.add_gem_contents(&block)
+    tar_outputter.add_metadata
+    tar_outputter.add_signatures
+
+  ensure
+    tar_outputter.close
+  end
+
+  ##
+  # Creates a new TarOutput that will write a gem-format tar file to +io+.  If
+  # +signer+ is given, the data.tar.gz and metadata.gz will be signed and
+  # the signatures will be added to the tar file.
+
+  def initialize(io, signer)
+    @io = io
+    @signer = signer
+
+    @tar_writer = Gem::Package::TarWriter.new @io
+
+    @metadata = nil
+
+    @data_signature = nil
+    @meta_signature = nil
+  end
+
+  ##
+  # Yields a TarWriter for the data.tar.gz inside a gem-format tar file.
+  # The yielded TarWriter has been extended with a #metadata= method for
+  # attaching a YAML format Gem::Specification which will be written by
+  # add_metadata.
+
+  def add_gem_contents
+    @tar_writer.add_file "data.tar.gz", 0644 do |inner|
+      sio = @signer ? StringIO.new : nil
+      Zlib::GzipWriter.wrap(sio || inner) do |os|
+
+        Gem::Package::TarWriter.new os do |data_tar_writer|
+          # :stopdoc:
+          def data_tar_writer.metadata() @metadata end
+          def data_tar_writer.metadata=(metadata) @metadata = metadata end
+          # :startdoc:
+
+          yield data_tar_writer
+
+          @metadata = data_tar_writer.metadata
+        end
+      end
+
+      # if we have a signing key, then sign the data
+      # digest and return the signature
+      if @signer then
+        digest = Gem::Security::OPT[:dgst_algo].digest sio.string
+        @data_signature = @signer.sign digest
+        inner.write sio.string
+      end
+    end
+
+    self
+  end
+
+  ##
+  # Adds metadata.gz to the gem-format tar file which was saved from a
+  # previous #add_gem_contents call.
+
+  def add_metadata
+    return if @metadata.nil?
+
+    @tar_writer.add_file "metadata.gz", 0644 do |io|
+      begin
+        sio = @signer ? StringIO.new : nil
+        gzos = Zlib::GzipWriter.new(sio || io)
+        gzos.write @metadata
+      ensure
+        gzos.flush
+        gzos.finish
+
+        # if we have a signing key, then sign the metadata digest and return
+        # the signature
+        if @signer then
+          digest = Gem::Security::OPT[:dgst_algo].digest sio.string
+          @meta_signature = @signer.sign digest
+          io.write sio.string
+        end
+      end
+    end
+  end
+
+  ##
+  # Adds data.tar.gz.sig and metadata.gz.sig to the gem-format tar files if
+  # a Gem::Security::Signer was sent to initialize.
+
+  def add_signatures
+    if @data_signature then
+      @tar_writer.add_file 'data.tar.gz.sig', 0644 do |io|
+        io.write @data_signature
+      end
+    end
+
+    if @meta_signature then
+      @tar_writer.add_file 'metadata.gz.sig', 0644 do |io|
+        io.write @meta_signature
+      end
+    end
+  end
+
+  ##
+  # Closes the TarOutput.
+
+  def close
+    @tar_writer.close
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader/entry.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader/entry.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader/entry.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,140 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+##
+# Class for reading entries out of a tar file
+
+class Gem::Package::TarReader::Entry
+
+  ##
+  # Header for this tar entry
+
+  attr_reader :header
+
+  ##
+  # Creates a new tar entry for +header+ that will be read from +io+
+
+  def initialize(header, io)
+    @closed = false
+    @header = header
+    @io = io
+    @orig_pos = @io.pos
+    @read = 0
+  end
+
+  def check_closed # :nodoc:
+    raise IOError, "closed #{self.class}" if closed?
+  end
+
+  ##
+  # Number of bytes read out of the tar entry
+
+  def bytes_read
+    @read
+  end
+
+  ##
+  # Closes the tar entry
+
+  def close
+    @closed = true
+  end
+
+  ##
+  # Is the tar entry closed?
+
+  def closed?
+    @closed
+  end
+
+  ##
+  # Are we at the end of the tar entry?
+
+  def eof?
+    check_closed
+
+    @read >= @header.size
+  end
+
+  ##
+  # Full name of the tar entry
+
+  def full_name
+    if @header.prefix != "" then
+      File.join @header.prefix, @header.name
+    else
+      @header.name
+    end
+  end
+
+  ##
+  # Read one byte from the tar entry
+
+  def getc
+    check_closed
+
+    return nil if @read >= @header.size
+
+    ret = @io.getc
+    @read += 1 if ret
+
+    ret
+  end
+
+  ##
+  # Is this tar entry a directory?
+
+  def directory?
+    @header.typeflag == "5"
+  end
+
+  ##
+  # Is this tar entry a file?
+
+  def file?
+    @header.typeflag == "0"
+  end
+
+  ##
+  # The position in the tar entry
+
+  def pos
+    check_closed
+
+    bytes_read
+  end
+
+  ##
+  # Reads +len+ bytes from the tar file entry, or the rest of the entry if
+  # nil
+
+  def read(len = nil)
+    check_closed
+
+    return nil if @read >= @header.size
+
+    len ||= @header.size - @read
+    max_read = [len, @header.size - @read].min
+
+    ret = @io.read max_read
+    @read += ret.size
+
+    ret
+  end
+
+  ##
+  # Rewinds to the beginning of the tar file entry
+
+  def rewind
+    check_closed
+
+    raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos=
+
+    @io.pos = @orig_pos
+    @read = 0
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_reader.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,105 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+##
+# TarReader reads tar files and allows iteration over their items
+
+class Gem::Package::TarReader
+
+  include Gem::Package
+
+  ##
+  # Raised if the tar IO is not seekable
+
+  class UnexpectedEOF < StandardError; end
+
+  ##
+  # Creates a new TarReader on +io+ and yields it to the block, if given.
+
+  def self.new(io)
+    reader = super
+
+    return reader unless block_given?
+
+    begin
+      yield reader
+    ensure
+      reader.close
+    end
+
+    nil
+  end
+
+  ##
+  # Creates a new tar file reader on +io+ which needs to respond to #pos,
+  # #eof?, #read, #getc and #pos=
+
+  def initialize(io)
+    @io = io
+    @init_pos = io.pos
+  end
+
+  ##
+  # Close the tar file
+
+  def close
+  end
+
+  ##
+  # Iterates over files in the tarball yielding each entry
+
+  def each
+    loop do
+      return if @io.eof?
+
+      header = Gem::Package::TarHeader.from @io
+      return if header.empty?
+
+      entry = Gem::Package::TarReader::Entry.new header, @io
+      size = entry.header.size
+
+      yield entry
+
+      skip = (512 - (size % 512)) % 512
+      pending = size - entry.bytes_read
+
+      begin
+        # avoid reading...
+        @io.seek pending, IO::SEEK_CUR
+        pending = 0
+      rescue Errno::EINVAL, NameError
+        while pending > 0 do
+          bytes_read = @io.read([pending, 4096].min).size
+          raise UnexpectedEOF if @io.eof?
+          pending -= bytes_read
+        end
+      end
+
+      @io.read skip # discard trailing zeros
+
+      # make sure nobody can use #read, #getc or #rewind anymore
+      entry.close
+    end
+  end
+
+  alias each_entry each
+
+  ##
+  # NOTE: Do not call #rewind during #each
+
+  def rewind
+    if @init_pos == 0 then
+      raise Gem::Package::NonSeekableIO unless @io.respond_to? :rewind
+      @io.rewind
+    else
+      raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos=
+      @io.pos = @init_pos
+    end
+  end
+
+end
+
+require 'rubygems/package/tar_reader/entry'
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_writer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_writer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package/tar_writer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,240 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+##
+# Allows writing of tar files
+
+class Gem::Package::TarWriter
+
+  class FileOverflow < StandardError; end
+
+  ##
+  # IO wrapper that allows writing a limited amount of data
+
+  class BoundedStream
+
+    ##
+    # Maximum number of bytes that can be written
+
+    attr_reader :limit
+
+    ##
+    # Number of bytes written
+
+    attr_reader :written
+
+    ##
+    # Wraps +io+ and allows up to +limit+ bytes to be written
+
+    def initialize(io, limit)
+      @io = io
+      @limit = limit
+      @written = 0
+    end
+
+    ##
+    # Writes +data+ onto the IO, raising a FileOverflow exception if the
+    # number of bytes will be more than #limit
+
+    def write(data)
+      if data.size + @written > @limit
+        raise FileOverflow, "You tried to feed more data than fits in the file."
+      end
+      @io.write data
+      @written += data.size
+      data.size
+    end
+
+  end
+
+  ##
+  # IO wrapper that provides only #write
+
+  class RestrictedStream
+
+    ##
+    # Creates a new RestrictedStream wrapping +io+
+
+    def initialize(io)
+      @io = io
+    end
+
+    ##
+    # Writes +data+ onto the IO
+
+    def write(data)
+      @io.write data
+    end
+
+  end
+
+  ##
+  # Creates a new TarWriter, yielding it if a block is given
+
+  def self.new(io)
+    writer = super
+
+    return writer unless block_given?
+
+    begin
+      yield writer
+    ensure
+      writer.close
+    end
+
+    nil
+  end
+
+  ##
+  # Creates a new TarWriter that will write to +io+
+
+  def initialize(io)
+    @io = io
+    @closed = false
+  end
+
+  ##
+  # Adds file +name+ with permissions +mode+, and yields an IO for writing the
+  # file to
+
+  def add_file(name, mode) # :yields: io
+    check_closed
+
+    raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos=
+
+    name, prefix = split_name name
+
+    init_pos = @io.pos
+    @io.write "\0" * 512 # placeholder for the header
+
+    yield RestrictedStream.new(@io) if block_given?
+
+    size = @io.pos - init_pos - 512
+
+    remainder = (512 - (size % 512)) % 512
+    @io.write "\0" * remainder
+
+    final_pos = @io.pos
+    @io.pos = init_pos
+
+    header = Gem::Package::TarHeader.new :name => name, :mode => mode,
+                                         :size => size, :prefix => prefix
+
+    @io.write header
+    @io.pos = final_pos
+
+    self
+  end
+
+  ##
+  # Add file +name+ with permissions +mode+ +size+ bytes long.  Yields an IO
+  # to write the file to.
+
+  def add_file_simple(name, mode, size) # :yields: io
+    check_closed
+
+    name, prefix = split_name name
+
+    header = Gem::Package::TarHeader.new(:name => name, :mode => mode,
+                                         :size => size, :prefix => prefix).to_s
+
+    @io.write header
+    os = BoundedStream.new @io, size
+
+    yield os if block_given?
+
+    min_padding = size - os.written
+    @io.write("\0" * min_padding)
+
+    remainder = (512 - (size % 512)) % 512
+    @io.write("\0" * remainder)
+
+    self
+  end
+
+  ##
+  # Raises IOError if the TarWriter is closed
+
+  def check_closed
+    raise IOError, "closed #{self.class}" if closed?
+  end
+
+  ##
+  # Closes the TarWriter
+
+  def close
+    check_closed
+
+    @io.write "\0" * 1024
+    flush
+
+    @closed = true
+  end
+
+  ##
+  # Is the TarWriter closed?
+
+  def closed?
+    @closed
+  end
+
+  ##
+  # Flushes the TarWriter's IO
+
+  def flush
+    check_closed
+
+    @io.flush if @io.respond_to? :flush
+  end
+
+  ##
+  # Creates a new directory in the tar file +name+ with +mode+
+
+  def mkdir(name, mode)
+    check_closed
+
+    name, prefix = split_name(name)
+
+    header = Gem::Package::TarHeader.new :name => name, :mode => mode,
+                                         :typeflag => "5", :size => 0,
+                                         :prefix => prefix
+
+    @io.write header
+
+    self
+  end
+
+  ##
+  # Splits +name+ into a name and prefix that can fit in the TarHeader
+
+  def split_name(name) # :nodoc:
+    raise Gem::Package::TooLongFileName if name.size > 256
+
+    if name.size <= 100 then
+      prefix = ""
+    else
+      parts = name.split(/\//)
+      newname = parts.pop
+      nxt = ""
+
+      loop do
+        nxt = parts.pop
+        break if newname.size + 1 + nxt.size > 100
+        newname = nxt + "/" + newname
+      end
+
+      prefix = (parts + [nxt]).join "/"
+      name = newname
+
+      if name.size > 100 or prefix.size > 155 then
+        raise Gem::Package::TooLongFileName 
+      end
+    end
+
+    return name, prefix
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,94 @@
+#++
+# Copyright (C) 2004 Mauricio Julio Fern\xE1ndez Pradier
+# See LICENSE.txt for additional licensing information.
+#--
+
+require 'fileutils'
+require 'find'
+require 'stringio'
+require 'yaml'
+require 'zlib'
+
+require 'rubygems/security'
+require 'rubygems/specification'
+
+# Wrapper for FileUtils meant to provide logging and additional operations if
+# needed.
+class Gem::FileOperations
+
+  def initialize(logger = nil)
+    @logger = logger
+  end
+
+  def method_missing(meth, *args, &block)
+    case
+    when FileUtils.respond_to?(meth)
+      @logger.log "#{meth}: #{args}" if @logger
+      FileUtils.send meth, *args, &block
+    when Gem::FileOperations.respond_to?(meth)
+      @logger.log "#{meth}: #{args}" if @logger
+      Gem::FileOperations.send meth, *args, &block
+    else
+      super
+    end
+  end
+
+end
+
+module Gem::Package
+
+  class Error < StandardError; end
+  class NonSeekableIO < Error; end
+  class ClosedIO < Error; end
+  class BadCheckSum < Error; end
+  class TooLongFileName < Error; end
+  class FormatError < Error; end
+
+  def self.open(io, mode = "r", signer = nil, &block)
+    tar_type = case mode
+               when 'r' then TarInput
+               when 'w' then TarOutput
+               else
+                 raise "Unknown Package open mode"
+               end
+
+    tar_type.open(io, signer, &block)
+  end
+
+  def self.pack(src, destname, signer = nil)
+    TarOutput.open(destname, signer) do |outp|
+      dir_class.chdir(src) do
+        outp.metadata = (file_class.read("RPA/metadata") rescue nil)
+        find_class.find('.') do |entry|
+          case
+          when file_class.file?(entry)
+            entry.sub!(%r{\./}, "")
+            next if entry =~ /\ARPA\//
+            stat = File.stat(entry)
+            outp.add_file_simple(entry, stat.mode, stat.size) do |os|
+              file_class.open(entry, "rb") do |f|
+                os.write(f.read(4096)) until f.eof?
+              end
+            end
+          when file_class.dir?(entry)
+            entry.sub!(%r{\./}, "")
+            next if entry == "RPA"
+            outp.mkdir(entry, file_class.stat(entry).mode)
+          else
+            raise "Don't know how to pack this yet!"
+          end
+        end
+      end
+    end
+  end
+
+end
+
+require 'rubygems/package/f_sync_dir'
+require 'rubygems/package/tar_header'
+require 'rubygems/package/tar_input'
+require 'rubygems/package/tar_output'
+require 'rubygems/package/tar_reader'
+require 'rubygems/package/tar_reader/entry'
+require 'rubygems/package/tar_writer'
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/package_task.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/package_task.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/package_task.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,123 @@
+# Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require 'rubygems'
+begin
+  gem 'rake'
+rescue Gem::LoadError
+end
+
+require 'rake/packagetask'
+
+##
+# Create a package based upon a Gem::Specification.  Gem packages, as well as
+# zip files and tar/gzipped packages can be produced by this task.
+#
+# In addition to the Rake targets generated by Rake::PackageTask, a
+# Gem::PackageTask will also generate the following tasks:
+#
+# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.gem"</b>]
+#   Create a RubyGems package with the given name and version.
+#
+# Example using a Gem::Specification:
+#
+#   require 'rubygems'
+#   require 'rubygems/package_task'
+#   
+#   spec = Gem::Specification.new do |s|
+#     s.platform = Gem::Platform::RUBY
+#     s.summary = "Ruby based make-like utility."
+#     s.name = 'rake'
+#     s.version = PKG_VERSION
+#     s.requirements << 'none'
+#     s.require_path = 'lib'
+#     s.autorequire = 'rake'
+#     s.files = PKG_FILES
+#     s.description = <<-EOF
+#   Rake is a Make-like program implemented in Ruby. Tasks
+#   and dependencies are specified in standard Ruby syntax.
+#     EOF
+#   end
+#   
+#   Gem::PackageTask.new(spec) do |pkg|
+#     pkg.need_zip = true
+#     pkg.need_tar = true
+#   end
+
+class Gem::PackageTask < Rake::PackageTask
+
+  ##
+  # Ruby Gem::Specification containing the metadata for this package.  The
+  # name, version and package_files are automatically determined from the
+  # gemspec and don't need to be explicitly provided.
+
+  attr_accessor :gem_spec
+
+  ##
+  # Create a Gem Package task library.  Automatically define the gem if a
+  # block is given.  If no block is supplied, then #define needs to be called
+  # to define the task.
+
+  def initialize(gem_spec)
+    init gem_spec
+    yield self if block_given?
+    define if block_given?
+  end
+
+  ##
+  # Initialization tasks without the "yield self" or define operations.
+
+  def init(gem)
+    super gem.name, gem.version
+    @gem_spec = gem
+    @package_files += gem_spec.files if gem_spec.files
+  end
+
+  ##
+  # Create the Rake tasks and actions specified by this Gem::PackageTask.
+  # (+define+ is automatically called if a block is given to +new+).
+
+  def define
+    super
+
+    task :package => [:gem]
+
+    gem_file = gem_spec.file_name
+    gem_path = File.join package_dir, gem_file
+
+    desc "Build the gem file #{gem_file}"
+    task :gem => [gem_path]
+
+    trace = Rake.application.options.trace
+    Gem.configuration.verbose = trace
+
+    file gem_path => [package_dir] + @gem_spec.files do
+      when_writing "Creating #{gem_spec.file_name}" do
+        Gem::Builder.new(gem_spec).build
+        verbose trace do
+          mv gem_file, gem_path
+        end
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/platform.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/platform.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/platform.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,180 @@
+##
+# Available list of platforms for targeting Gem installations.
+
+class Gem::Platform
+
+  @local = nil
+
+  attr_accessor :cpu
+
+  attr_accessor :os
+
+  attr_accessor :version
+
+  def self.local
+    arch = Gem::ConfigMap[:arch]
+    arch = "#{arch}_60" if arch =~ /mswin32$/
+    @local ||= new(arch)
+  end
+
+  def self.match(platform)
+    Gem.platforms.any? do |local_platform|
+      platform.nil? or local_platform == platform or
+        (local_platform != Gem::Platform::RUBY and local_platform =~ platform)
+    end
+  end
+
+  def self.new(arch) # :nodoc:
+    case arch
+    when Gem::Platform::CURRENT then
+      Gem::Platform.local
+    when Gem::Platform::RUBY, nil, '' then
+      Gem::Platform::RUBY
+    else
+      super
+    end
+  end
+
+  def initialize(arch)
+    case arch
+    when Array then
+      @cpu, @os, @version = arch
+    when String then
+      arch = arch.split '-'
+
+      if arch.length > 2 and arch.last !~ /\d/ then # reassemble x86-linux-gnu
+        extra = arch.pop
+        arch.last << "-#{extra}"
+      end
+
+      cpu = arch.shift
+
+      @cpu = case cpu
+             when /i\d86/ then 'x86'
+             else cpu
+             end
+
+      if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ then # for command-line
+        @os, @version = arch
+        return
+      end
+
+      os, = arch
+      @cpu, os = nil, cpu if os.nil? # legacy jruby
+
+      @os, @version = case os
+                      when /aix(\d+)/ then             [ 'aix',       $1  ]
+                      when /cygwin/ then               [ 'cygwin',    nil ]
+                      when /darwin(\d+)?/ then         [ 'darwin',    $1  ]
+                      when /freebsd(\d+)/ then         [ 'freebsd',   $1  ]
+                      when /hpux(\d+)/ then            [ 'hpux',      $1  ]
+                      when /^java$/, /^jruby$/ then    [ 'java',      nil ]
+                      when /^java([\d.]*)/ then        [ 'java',      $1  ]
+                      when /linux/ then                [ 'linux',     $1  ]
+                      when /mingw32/ then              [ 'mingw32',   nil ]
+                      when /(mswin\d+)(\_(\d+))?/ then
+                        os, version = $1, $3
+                        @cpu = 'x86' if @cpu.nil? and os =~ /32$/
+                        [os, version]
+                      when /netbsdelf/ then            [ 'netbsdelf', nil ]
+                      when /openbsd(\d+\.\d+)/ then    [ 'openbsd',   $1  ]
+                      when /solaris(\d+\.\d+)/ then    [ 'solaris',   $1  ]
+                      # test
+                      when /^(\w+_platform)(\d+)/ then [ $1,          $2  ]
+                      else                             [ 'unknown',   nil ]
+                      end
+    when Gem::Platform then
+      @cpu = arch.cpu
+      @os = arch.os
+      @version = arch.version
+    else
+      raise ArgumentError, "invalid argument #{arch.inspect}"
+    end
+  end
+
+  def inspect
+    "#<%s:0x%x @cpu=%p, @os=%p, @version=%p>" % [self.class, object_id, *to_a]
+  end
+
+  def to_a
+    [@cpu, @os, @version]
+  end
+
+  def to_s
+    to_a.compact.join '-'
+  end
+  
+  def empty?
+    to_s.empty?
+  end
+
+  ##
+  # Is +other+ equal to this platform?  Two platforms are equal if they have
+  # the same CPU, OS and version.
+
+  def ==(other)
+    self.class === other and
+      @cpu == other.cpu and @os == other.os and @version == other.version
+  end
+
+  ##
+  # Does +other+ match this platform?  Two platforms match if they have the
+  # same CPU, or either has a CPU of 'universal', they have the same OS, and
+  # they have the same version, or either has no version.
+
+  def ===(other)
+    return nil unless Gem::Platform === other
+
+    # cpu
+    (@cpu == 'universal' or other.cpu == 'universal' or @cpu == other.cpu) and
+
+    # os
+    @os == other.os and
+
+    # version
+    (@version.nil? or other.version.nil? or @version == other.version)
+  end
+
+  ##
+  # Does +other+ match this platform?  If +other+ is a String it will be
+  # converted to a Gem::Platform first.  See #=== for matching rules.
+
+  def =~(other)
+    case other
+    when Gem::Platform then # nop
+    when String then
+      # This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007
+      other = case other
+              when /^i686-darwin(\d)/     then ['x86',       'darwin',  $1    ]
+              when /^i\d86-linux/         then ['x86',       'linux',   nil   ]
+              when 'java', 'jruby'        then [nil,         'java',    nil   ]
+              when /mswin32(\_(\d+))?/    then ['x86',       'mswin32', $2    ]
+              when 'powerpc-darwin'       then ['powerpc',   'darwin',  nil   ]
+              when /powerpc-darwin(\d)/   then ['powerpc',   'darwin',  $1    ]
+              when /sparc-solaris2.8/     then ['sparc',     'solaris', '2.8' ]
+              when /universal-darwin(\d)/ then ['universal', 'darwin',  $1    ]
+              else                             other
+              end
+
+      other = Gem::Platform.new other
+    else
+      return nil
+    end
+
+    self === other
+  end
+
+  ##
+  # A pure-ruby gem that may use Gem::Specification#extensions to build
+  # binary files.
+
+  RUBY = 'ruby'
+
+  ##
+  # A platform-specific gem that is built for the packaging ruby's platform.
+  # This will be replaced with Gem::Platform::local.
+
+  CURRENT = 'current'
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/remote_fetcher.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/remote_fetcher.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/remote_fetcher.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,367 @@
+require 'net/http'
+require 'stringio'
+require 'time'
+require 'uri'
+
+require 'rubygems'
+
+##
+# RemoteFetcher handles the details of fetching gems and gem information from
+# a remote source.
+
+class Gem::RemoteFetcher
+
+  include Gem::UserInteraction
+
+  ##
+  # A FetchError exception wraps up the various possible IO and HTTP failures
+  # that could happen while downloading from the internet.
+
+  class FetchError < Gem::Exception
+
+    ##
+    # The URI which was being accessed when the exception happened.
+
+    attr_accessor :uri
+
+    def initialize(message, uri)
+      super message
+      @uri = uri
+    end
+
+    def to_s # :nodoc:
+      "#{super} (#{uri})"
+    end
+
+  end
+
+  @fetcher = nil
+
+  ##
+  # Cached RemoteFetcher instance.
+
+  def self.fetcher
+    @fetcher ||= self.new Gem.configuration[:http_proxy]
+  end
+
+  ##
+  # Initialize a remote fetcher using the source URI and possible proxy
+  # information.
+  #
+  # +proxy+
+  # * [String]: explicit specification of proxy; overrides any environment
+  #             variable setting
+  # * nil: respect environment variables (HTTP_PROXY, HTTP_PROXY_USER,
+  #        HTTP_PROXY_PASS)
+  # * <tt>:no_proxy</tt>: ignore environment variables and _don't_ use a proxy
+
+  def initialize(proxy = nil)
+    Socket.do_not_reverse_lookup = true
+
+    @connections = {}
+    @requests = Hash.new 0
+    @proxy_uri =
+      case proxy
+      when :no_proxy then nil
+      when nil then get_proxy_from_env
+      when URI::HTTP then proxy
+      else URI.parse(proxy)
+      end
+  end
+
+  ##
+  # Moves the gem +spec+ from +source_uri+ to the cache dir unless it is
+  # already there.  If the source_uri is local the gem cache dir copy is
+  # always replaced.
+
+  def download(spec, source_uri, install_dir = Gem.dir)
+    if File.writable?(install_dir)
+      cache_dir = File.join install_dir, 'cache'
+    else
+      cache_dir = File.join(Gem.user_dir, 'cache')
+    end
+
+    gem_file_name = spec.file_name
+    local_gem_path = File.join cache_dir, gem_file_name
+
+    FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
+
+   # Always escape URI's to deal with potential spaces and such
+    unless URI::Generic === source_uri
+      source_uri = URI.parse(URI.escape(source_uri))
+    end
+
+    scheme = source_uri.scheme
+
+    # URI.parse gets confused by MS Windows paths with forward slashes.
+    scheme = nil if scheme =~ /^[a-z]$/i
+
+    case scheme
+    when 'http', 'https' then
+      unless File.exist? local_gem_path then
+        begin
+          say "Downloading gem #{gem_file_name}" if
+            Gem.configuration.really_verbose
+
+          remote_gem_path = source_uri + "gems/#{gem_file_name}"
+
+          gem = self.fetch_path remote_gem_path
+        rescue Gem::RemoteFetcher::FetchError
+          raise if spec.original_platform == spec.platform
+
+          alternate_name = "#{spec.original_name}.gem"
+
+          say "Failed, downloading gem #{alternate_name}" if
+            Gem.configuration.really_verbose
+
+          remote_gem_path = source_uri + "gems/#{alternate_name}"
+
+          gem = self.fetch_path remote_gem_path
+        end
+
+        File.open local_gem_path, 'wb' do |fp|
+          fp.write gem
+        end
+      end
+    when 'file' then
+      begin
+        path = source_uri.path
+        path = File.dirname(path) if File.extname(path) == '.gem'
+
+        remote_gem_path = File.join(path, 'gems', gem_file_name)
+
+        FileUtils.cp(remote_gem_path, local_gem_path)
+      rescue Errno::EACCES
+        local_gem_path = source_uri.to_s
+      end
+
+      say "Using local gem #{local_gem_path}" if
+        Gem.configuration.really_verbose
+    when nil then # TODO test for local overriding cache
+      begin
+        if Gem.win_platform? && source_uri.scheme && !source_uri.path.include?(':')
+          FileUtils.cp URI.unescape(source_uri.scheme + ':' + source_uri.path), local_gem_path
+        else
+          FileUtils.cp URI.unescape(source_uri.path), local_gem_path
+        end
+      rescue Errno::EACCES
+        local_gem_path = source_uri.to_s
+      end
+
+      say "Using local gem #{local_gem_path}" if
+        Gem.configuration.really_verbose
+    else
+      raise Gem::InstallError, "unsupported URI scheme #{source_uri.scheme}"
+    end
+
+    local_gem_path
+  end
+
+  ##
+  # Downloads +uri+ and returns it as a String.
+
+  def fetch_path(uri, mtime = nil, head = false)
+    data = open_uri_or_path uri, mtime, head
+    data = Gem.gunzip data if data and not head and uri.to_s =~ /gz$/
+    data
+  rescue FetchError
+    raise
+  rescue Timeout::Error
+    raise FetchError.new('timed out', uri)
+  rescue IOError, SocketError, SystemCallError => e
+    raise FetchError.new("#{e.class}: #{e}", uri)
+  end
+
+  ##
+  # Returns the size of +uri+ in bytes.
+
+  def fetch_size(uri) # TODO: phase this out
+    response = fetch_path(uri, nil, true)
+
+    response['content-length'].to_i
+  end
+
+  def escape(str)
+    return unless str
+    URI.escape(str)
+  end
+
+  def unescape(str)
+    return unless str
+    URI.unescape(str)
+  end
+
+  ##
+  # Returns an HTTP proxy URI if one is set in the environment variables.
+
+  def get_proxy_from_env
+    env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
+
+    return nil if env_proxy.nil? or env_proxy.empty?
+
+    uri = URI.parse(normalize_uri(env_proxy))
+
+    if uri and uri.user.nil? and uri.password.nil? then
+      # Probably we have http_proxy_* variables?
+      uri.user = escape(ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'])
+      uri.password = escape(ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'])
+    end
+
+    uri
+  end
+
+  ##
+  # Normalize the URI by adding "http://" if it is missing.
+
+  def normalize_uri(uri)
+    (uri =~ /^(https?|ftp|file):/) ? uri : "http://#{uri}"
+  end
+
+  ##
+  # Creates or an HTTP connection based on +uri+, or retrieves an existing
+  # connection, using a proxy if needed.
+
+  def connection_for(uri)
+    net_http_args = [uri.host, uri.port]
+
+    if @proxy_uri then
+      net_http_args += [
+        @proxy_uri.host,
+        @proxy_uri.port,
+        @proxy_uri.user,
+        @proxy_uri.password
+      ]
+    end
+
+    connection_id = net_http_args.join ':'
+    @connections[connection_id] ||= Net::HTTP.new(*net_http_args)
+    connection = @connections[connection_id]
+
+    if uri.scheme == 'https' and not connection.started? then
+      require 'net/https'
+      connection.use_ssl = true
+      connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
+    end
+
+    connection.start unless connection.started?
+
+    connection
+  end
+
+  ##
+  # Read the data from the (source based) URI, but if it is a file:// URI,
+  # read from the filesystem instead.
+
+  def open_uri_or_path(uri, last_modified = nil, head = false, depth = 0)
+    raise "block is dead" if block_given?
+
+    uri = URI.parse uri unless URI::Generic === uri
+
+    # This check is redundant unless Gem::RemoteFetcher is likely
+    # to be used directly, since the scheme is checked elsewhere.
+    # - Daniel Berger
+    unless ['http', 'https', 'file'].include?(uri.scheme)
+     raise ArgumentError, 'uri scheme is invalid'
+    end
+
+    if uri.scheme == 'file'
+      path = uri.path
+
+      # Deal with leading slash on Windows paths
+      if path[0].chr == '/' && path[1].chr =~ /[a-zA-Z]/ && path[2].chr == ':'
+         path = path[1..-1]
+      end
+
+      return Gem.read_binary(path)
+    end
+
+    fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get
+    response   = request uri, fetch_type, last_modified
+
+    case response
+    when Net::HTTPOK, Net::HTTPNotModified then
+      head ? response : response.body
+    when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
+         Net::HTTPTemporaryRedirect then
+      raise FetchError.new('too many redirects', uri) if depth > 10
+
+      open_uri_or_path(response['Location'], last_modified, head, depth + 1)
+    else
+      raise FetchError.new("bad response #{response.message} #{response.code}", uri)
+    end
+  end
+
+  ##
+  # Performs a Net::HTTP request of type +request_class+ on +uri+ returning
+  # a Net::HTTP response object.  request maintains a table of persistent
+  # connections to reduce connect overhead.
+
+  def request(uri, request_class, last_modified = nil)
+    request = request_class.new uri.request_uri
+
+    unless uri.nil? || uri.user.nil? || uri.user.empty? then
+      request.basic_auth uri.user, uri.password
+    end
+
+    ua = "RubyGems/#{Gem::RubyGemsVersion} #{Gem::Platform.local}"
+    ua << " Ruby/#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
+    ua << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
+    ua << ")"
+
+    request.add_field 'User-Agent', ua
+    request.add_field 'Connection', 'keep-alive'
+    request.add_field 'Keep-Alive', '30'
+
+    if last_modified then
+      last_modified = last_modified.utc
+      request.add_field 'If-Modified-Since', last_modified.rfc2822
+    end
+
+    connection = connection_for uri
+
+    retried = false
+    bad_response = false
+
+    begin
+      @requests[connection.object_id] += 1
+      response = connection.request request
+      say "#{request.method} #{response.code} #{response.message}: #{uri}" if
+        Gem.configuration.really_verbose
+    rescue Net::HTTPBadResponse
+      reset connection
+
+      raise FetchError.new('too many bad responses', uri) if bad_response
+
+      bad_response = true
+      retry
+    # HACK work around EOFError bug in Net::HTTP
+    # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
+    # to install gems.
+    rescue EOFError, Errno::ECONNABORTED, Errno::ECONNRESET
+      requests = @requests[connection.object_id]
+      say "connection reset after #{requests} requests, retrying" if
+        Gem.configuration.really_verbose
+
+      raise FetchError.new('too many connection resets', uri) if retried
+
+      reset connection
+
+      retried = true
+      retry
+    end
+
+    response
+  end
+
+  ##
+  # Resets HTTP connection +connection+.
+
+  def reset(connection)
+    @requests.delete connection.object_id
+
+    connection.finish
+    connection.start
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/require_paths_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/require_paths_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/require_paths_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,17 @@
+require 'rubygems'
+
+module Gem::RequirePathsBuilder
+  def write_require_paths_file_if_needed(spec = @spec, gem_home = @gem_home)
+    return if spec.require_paths == ["lib"] &&
+              (spec.bindir.nil? || spec.bindir == "bin")
+    file_name = File.join(gem_home, 'gems', "#{@spec.full_name}", ".require_paths")
+    file_name.untaint
+    File.open(file_name, "w") do |file|
+      spec.require_paths.each do |path|
+        file.puts path
+      end
+      file.puts spec.bindir if spec.bindir
+    end
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/requirement.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/requirement.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/requirement.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,170 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+##
+# Requirement version includes a prefaced comparator in addition
+# to a version number.
+#
+# A Requirement object can actually contain multiple, er,
+# requirements, as in (> 1.2, < 2.0).
+
+class Gem::Requirement
+
+  include Comparable
+
+  attr_reader :requirements
+
+  OPS = {
+    "="  =>  lambda { |v, r| v == r },
+    "!=" =>  lambda { |v, r| v != r },
+    ">"  =>  lambda { |v, r| v > r },
+    "<"  =>  lambda { |v, r| v < r },
+    ">=" =>  lambda { |v, r| v >= r },
+    "<=" =>  lambda { |v, r| v <= r },
+    "~>" =>  lambda { |v, r| v = v.release; v >= r && v < r.bump }
+  }
+
+  OP_RE = OPS.keys.map{ |k| Regexp.quote k }.join '|'
+
+  ##
+  # Factory method to create a Gem::Requirement object.  Input may be a
+  # Version, a String, or nil.  Intended to simplify client code.
+  #
+  # If the input is "weird", the default version requirement is returned.
+
+  def self.create(input)
+    case input
+    when Gem::Requirement then
+      input
+    when Gem::Version, Array then
+      new input
+    else
+      if input.respond_to? :to_str then
+        self.new [input.to_str]
+      else
+        self.default
+      end
+    end
+  end
+
+  ##
+  # A default "version requirement" can surely _only_ be '>= 0'.
+  #--
+  # This comment once said:
+  #
+  # "A default "version requirement" can surely _only_ be '> 0'."
+
+  def self.default
+    self.new ['>= 0']
+  end
+
+  ##
+  # Constructs a Requirement from +requirements+ which can be a String, a
+  # Gem::Version, or an Array of those.  See #parse for details on the
+  # formatting of requirement strings.
+
+  def initialize(requirements)
+    @requirements = case requirements
+                    when Array then
+                      requirements.map do |requirement|
+                        parse(requirement)
+                      end
+                    else
+                      [parse(requirements)]
+                    end
+    @version = nil   # Avoid warnings.
+  end
+
+  ##
+  # Marshal raw requirements, rather than the full object
+
+  def marshal_dump # :nodoc:
+    [@requirements]
+  end
+
+  ##
+  # Load custom marshal format
+
+  def marshal_load(array) # :nodoc:
+    @requirements = array[0]
+    @version = nil
+  end
+
+  def to_s # :nodoc:
+    as_list.join(", ")
+  end
+
+  def pretty_print(q) # :nodoc:
+    q.group 1, 'Gem::Requirement.new(', ')' do
+      q.pp as_list
+    end
+  end
+
+  def as_list
+    normalize
+    @requirements.map do |op, version| "#{op} #{version}" end
+  end
+
+  def normalize
+    return if not defined? @version or @version.nil?
+    @requirements = [parse(@version)]
+    @nums = nil
+    @version = nil
+    @op = nil
+  end
+
+  ##
+  # True if this requirement satisfied by the Gem::Version +version+.
+
+  def satisfied_by?(version)
+    normalize
+    @requirements.all? { |op, rv| satisfy?(op, version, rv) }
+  end
+
+  ##
+  # Is "+version+ +op+ +required_version+" satisfied?
+
+  def satisfy?(op, version, required_version)
+    OPS[op].call(version, required_version)
+  end
+
+  def prerelease?
+    # TODO: why is @requirements a nested array?
+    @requirements.any?{ |r| r[1].prerelease? }
+  end
+
+  ##
+  # Parse the version requirement obj returning the operator and version.
+  #
+  # The requirement can be a String or a Gem::Version.  A String can be an
+  # operator (<, <=, =, >=, >, !=, ~>), a version number, or both, operator
+  # first.
+
+  def parse(obj)
+    case obj
+    when /^\s*(#{OP_RE})\s*(#{Gem::Version::VERSION_PATTERN})\s*$/o then
+      [$1, Gem::Version.new($2)]
+    when /^\s*(#{Gem::Version::VERSION_PATTERN})\s*$/o then
+      ['=', Gem::Version.new($1)]
+    when /^\s*(#{OP_RE})\s*$/o then
+      [$1, Gem::Version.new('0')]
+    when Gem::Version then
+      ['=', obj]
+    else
+      raise ArgumentError, "Illformed requirement [#{obj.inspect}]"
+    end
+  end
+
+  def <=>(other) # :nodoc:
+    to_s <=> other.to_s
+  end
+
+  def hash # :nodoc:
+    to_s.hash
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/security.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/security.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/security.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,786 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+require 'rubygems/gem_openssl'
+
+# = Signed Gems README
+#
+# == Table of Contents
+# * Overview
+# * Walkthrough
+# * Command-Line Options
+# * OpenSSL Reference
+# * Bugs/TODO
+# * About the Author
+#
+# == Overview
+#
+# Gem::Security implements cryptographic signatures in RubyGems.  The section
+# below is a step-by-step guide to using signed gems and generating your own.
+#
+# == Walkthrough
+#
+# In order to start signing your gems, you'll need to build a private key and
+# a self-signed certificate.  Here's how:
+#
+#   # build a private key and certificate for gemmaster at example.com
+#   $ gem cert --build gemmaster at example.com
+#
+# This could take anywhere from 5 seconds to 10 minutes, depending on the
+# speed of your computer (public key algorithms aren't exactly the speediest
+# crypto algorithms in the world).  When it's finished, you'll see the files
+# "gem-private_key.pem" and "gem-public_cert.pem" in the current directory.
+#
+# First things first: take the "gem-private_key.pem" file and move it
+# somewhere private, preferably a directory only you have access to, a floppy
+# (yuck!), a CD-ROM, or something comparably secure.  Keep your private key
+# hidden; if it's compromised, someone can sign packages as you (note: PKI has
+# ways of mitigating the risk of stolen keys; more on that later).
+#
+# Now, let's sign an existing gem.  I'll be using my Imlib2-Ruby bindings, but
+# you can use whatever gem you'd like.  Open up your existing gemspec file and
+# add the following lines:
+#
+#   # signing key and certificate chain
+#   s.signing_key = '/mnt/floppy/gem-private_key.pem'
+#   s.cert_chain  = ['gem-public_cert.pem']
+#
+# (Be sure to replace "/mnt/floppy" with the ultra-secret path to your private
+# key).
+#
+# After that, go ahead and build your gem as usual.  Congratulations, you've
+# just built your first signed gem!  If you peek inside your gem file, you'll
+# see a couple of new files have been added:
+#
+#   $ tar tf tar tf Imlib2-Ruby-0.5.0.gem
+#   data.tar.gz
+#   data.tar.gz.sig
+#   metadata.gz
+#   metadata.gz.sig
+#
+# Now let's verify the signature.  Go ahead and install the gem, but add the
+# following options: "-P HighSecurity", like this:
+#
+#   # install the gem with using the security policy "HighSecurity"
+#   $ sudo gem install Imlib2-Ruby-0.5.0.gem -P HighSecurity
+#
+# The -P option sets your security policy -- we'll talk about that in just a
+# minute.  Eh, what's this?
+#
+#   Attempting local installation of 'Imlib2-Ruby-0.5.0.gem'
+#   ERROR:  Error installing gem Imlib2-Ruby-0.5.0.gem[.gem]: Couldn't
+#   verify data signature: Untrusted Signing Chain Root: cert =
+#   '/CN=gemmaster/DC=example/DC=com', error = 'path
+#   "/root/.rubygems/trust/cert-15dbb43a6edf6a70a85d4e784e2e45312cff7030.pem"
+#   does not exist'
+#
+# The culprit here is the security policy.  RubyGems has several different
+# security policies.  Let's take a short break and go over the security
+# policies.  Here's a list of the available security policies, and a brief
+# description of each one:
+#
+# * NoSecurity - Well, no security at all.  Signed packages are treated like
+#   unsigned packages.
+# * LowSecurity - Pretty much no security.  If a package is signed then
+#   RubyGems will make sure the signature matches the signing
+#   certificate, and that the signing certificate hasn't expired, but
+#   that's it.  A malicious user could easily circumvent this kind of
+#   security.
+# * MediumSecurity - Better than LowSecurity and NoSecurity, but still
+#   fallible.  Package contents are verified against the signing
+#   certificate, and the signing certificate is checked for validity,
+#   and checked against the rest of the certificate chain (if you don't
+#   know what a certificate chain is, stay tuned, we'll get to that).
+#   The biggest improvement over LowSecurity is that MediumSecurity
+#   won't install packages that are signed by untrusted sources.
+#   Unfortunately, MediumSecurity still isn't totally secure -- a
+#   malicious user can still unpack the gem, strip the signatures, and
+#   distribute the gem unsigned.
+# * HighSecurity - Here's the bugger that got us into this mess.
+#   The HighSecurity policy is identical to the MediumSecurity policy,
+#   except that it does not allow unsigned gems.  A malicious user
+#   doesn't have a whole lot of options here; he can't modify the
+#   package contents without invalidating the signature, and he can't
+#   modify or remove signature or the signing certificate chain, or
+#   RubyGems will simply refuse to install the package.  Oh well, maybe
+#   he'll have better luck causing problems for CPAN users instead :).
+#
+# So, the reason RubyGems refused to install our shiny new signed gem was
+# because it was from an untrusted source.  Well, my code is infallible
+# (hah!), so I'm going to add myself as a trusted source.
+#
+# Here's how:
+#
+#     # add trusted certificate
+#     gem cert --add gem-public_cert.pem
+#
+# I've added my public certificate as a trusted source.  Now I can install
+# packages signed my private key without any hassle.  Let's try the install
+# command above again:
+#
+#   # install the gem with using the HighSecurity policy (and this time
+#   # without any shenanigans)
+#   $ sudo gem install Imlib2-Ruby-0.5.0.gem -P HighSecurity
+#
+# This time RubyGems should accept your signed package and begin installing.
+# While you're waiting for RubyGems to work it's magic, have a look at some of
+# the other security commands:
+#
+#   Usage: gem cert [options]
+#
+#   Options:
+#     -a, --add CERT          Add a trusted certificate.
+#     -l, --list              List trusted certificates.
+#     -r, --remove STRING     Remove trusted certificates containing STRING.
+#     -b, --build EMAIL_ADDR  Build private key and self-signed certificate
+#                             for EMAIL_ADDR.
+#     -C, --certificate CERT  Certificate for --sign command.
+#     -K, --private-key KEY   Private key for --sign command.
+#     -s, --sign NEWCERT      Sign a certificate with my key and certificate.
+#
+# (By the way, you can pull up this list any time you'd like by typing "gem
+# cert --help")
+#
+# Hmm.  We've already covered the "--build" option, and the "--add", "--list",
+# and "--remove" commands seem fairly straightforward; they allow you to add,
+# list, and remove the certificates in your trusted certificate list.  But
+# what's with this "--sign" option?
+#
+# To answer that question, let's take a look at "certificate chains", a
+# concept I mentioned earlier.  There are a couple of problems with
+# self-signed certificates: first of all, self-signed certificates don't offer
+# a whole lot of security.  Sure, the certificate says Yukihiro Matsumoto, but
+# how do I know it was actually generated and signed by matz himself unless he
+# gave me the certificate in person?
+#
+# The second problem is scalability.  Sure, if there are 50 gem authors, then
+# I have 50 trusted certificates, no problem.  What if there are 500 gem
+# authors?  1000?  Having to constantly add new trusted certificates is a
+# pain, and it actually makes the trust system less secure by encouraging
+# RubyGems users to blindly trust new certificates.
+#
+# Here's where certificate chains come in.  A certificate chain establishes an
+# arbitrarily long chain of trust between an issuing certificate and a child
+# certificate.  So instead of trusting certificates on a per-developer basis,
+# we use the PKI concept of certificate chains to build a logical hierarchy of
+# trust.  Here's a hypothetical example of a trust hierarchy based (roughly)
+# on geography:
+#
+#
+#                         --------------------------
+#                         | rubygems at rubyforge.org |
+#                         --------------------------
+#                                     |
+#                   -----------------------------------
+#                   |                                 |
+#       ----------------------------    -----------------------------
+#       | seattle.rb at zenspider.com |    | dcrubyists at richkilmer.com |
+#       ----------------------------    -----------------------------
+#            |                |                 |             |
+#     ---------------   ----------------   -----------   --------------
+#     | alf at seattle |   | bob at portland |   | pabs at dc |   | tomcope at dc |
+#     ---------------   ----------------   -----------   --------------
+#
+#
+# Now, rather than having 4 trusted certificates (one for alf at seattle,
+# bob at portland, pabs at dc, and tomecope at dc), a user could actually get by with 1
+# certificate: the "rubygems at rubyforge.org" certificate.  Here's how it works:
+#
+# I install "Alf2000-Ruby-0.1.0.gem", a package signed by "alf at seattle".  I've
+# never heard of "alf at seattle", but his certificate has a valid signature from
+# the "seattle.rb at zenspider.com" certificate, which in turn has a valid
+# signature from the "rubygems at rubyforge.org" certificate.  Voila!  At this
+# point, it's much more reasonable for me to trust a package signed by
+# "alf at seattle", because I can establish a chain to "rubygems at rubyforge.org",
+# which I do trust.
+#
+# And the "--sign" option allows all this to happen.  A developer creates
+# their build certificate with the "--build" option, then has their
+# certificate signed by taking it with them to their next regional Ruby meetup
+# (in our hypothetical example), and it's signed there by the person holding
+# the regional RubyGems signing certificate, which is signed at the next
+# RubyConf by the holder of the top-level RubyGems certificate.  At each point
+# the issuer runs the same command:
+#
+#   # sign a certificate with the specified key and certificate
+#   # (note that this modifies client_cert.pem!)
+#   $ gem cert -K /mnt/floppy/issuer-priv_key.pem -C issuer-pub_cert.pem
+#      --sign client_cert.pem
+#
+# Then the holder of issued certificate (in this case, our buddy
+# "alf at seattle"), can start using this signed certificate to sign RubyGems.
+# By the way, in order to let everyone else know about his new fancy signed
+# certificate, "alf at seattle" would change his gemspec file to look like this:
+#
+#   # signing key (still kept in an undisclosed location!)
+#   s.signing_key = '/mnt/floppy/alf-private_key.pem'
+#   
+#   # certificate chain (includes the issuer certificate now too)
+#   s.cert_chain  = ['/home/alf/doc/seattlerb-public_cert.pem',
+#                    '/home/alf/doc/alf_at_seattle-public_cert.pem']
+#
+# Obviously, this RubyGems trust infrastructure doesn't exist yet.  Also, in
+# the "real world" issuers actually generate the child certificate from a
+# certificate request, rather than sign an existing certificate.  And our
+# hypothetical infrastructure is missing a certificate revocation system.
+# These are that can be fixed in the future...
+#
+# I'm sure your new signed gem has finished installing by now (unless you're
+# installing rails and all it's dependencies, that is ;D).  At this point you
+# should know how to do all of these new and interesting things:
+#
+# * build a gem signing key and certificate
+# * modify your existing gems to support signing
+# * adjust your security policy
+# * modify your trusted certificate list
+# * sign a certificate
+#
+# If you've got any questions, feel free to contact me at the email address
+# below.  The next couple of sections
+#
+#
+# == Command-Line Options
+#
+# Here's a brief summary of the certificate-related command line options:
+#
+#   gem install
+#     -P, --trust-policy POLICY        Specify gem trust policy.
+#
+#   gem cert
+#     -a, --add CERT                   Add a trusted certificate.
+#     -l, --list                       List trusted certificates.
+#     -r, --remove STRING              Remove trusted certificates containing
+#                                      STRING.
+#     -b, --build EMAIL_ADDR           Build private key and self-signed
+#                                      certificate for EMAIL_ADDR.
+#     -C, --certificate CERT           Certificate for --sign command.
+#     -K, --private-key KEY            Private key for --sign command.
+#     -s, --sign NEWCERT               Sign a certificate with my key and
+#                                      certificate.
+#
+# A more detailed description of each options is available in the walkthrough
+# above.
+#
+#
+# == OpenSSL Reference
+#
+# The .pem files generated by --build and --sign are just basic OpenSSL PEM
+# files.  Here's a couple of useful commands for manipulating them:
+#
+#   # convert a PEM format X509 certificate into DER format:
+#   # (note: Windows .cer files are X509 certificates in DER format)
+#   $ openssl x509 -in input.pem -outform der -out output.der
+#   
+#   # print out the certificate in a human-readable format:
+#   $ openssl x509 -in input.pem -noout -text
+#
+# And you can do the same thing with the private key file as well:
+#
+#   # convert a PEM format RSA key into DER format:
+#   $ openssl rsa -in input_key.pem -outform der -out output_key.der
+#   
+#   # print out the key in a human readable format:
+#   $ openssl rsa -in input_key.pem -noout -text
+#
+# == Bugs/TODO
+#
+# * There's no way to define a system-wide trust list.
+# * custom security policies (from a YAML file, etc)
+# * Simple method to generate a signed certificate request
+# * Support for OCSP, SCVP, CRLs, or some other form of cert
+#   status check (list is in order of preference)
+# * Support for encrypted private keys
+# * Some sort of semi-formal trust hierarchy (see long-winded explanation
+#   above)
+# * Path discovery (for gem certificate chains that don't have a self-signed
+#   root) -- by the way, since we don't have this, THE ROOT OF THE CERTIFICATE
+#   CHAIN MUST BE SELF SIGNED if Policy#verify_root is true (and it is for the
+#   MediumSecurity and HighSecurity policies)
+# * Better explanation of X509 naming (ie, we don't have to use email
+#   addresses)
+# * Possible alternate signing mechanisms (eg, via PGP).  this could be done
+#   pretty easily by adding a :signing_type attribute to the gemspec, then add
+#   the necessary support in other places
+# * Honor AIA field (see note about OCSP above)
+# * Maybe honor restriction extensions?
+# * Might be better to store the certificate chain as a PKCS#7 or PKCS#12
+#   file, instead of an array embedded in the metadata.  ideas?
+# * Possibly embed signature and key algorithms into metadata (right now
+#   they're assumed to be the same as what's set in Gem::Security::OPT)
+#
+# == About the Author
+#
+# Paul Duncan <pabs at pablotron.org>
+# http://pablotron.org/
+
+module Gem::Security
+
+  class Exception < Gem::Exception; end
+
+  #
+  # default options for most of the methods below
+  #
+  OPT = {
+    # private key options
+    :key_algo   => Gem::SSL::PKEY_RSA,
+    :key_size   => 2048,
+
+    # public cert options
+    :cert_age   => 365 * 24 * 3600, # 1 year
+    :dgst_algo  => Gem::SSL::DIGEST_SHA1,
+
+    # x509 certificate extensions
+    :cert_exts  => {
+      'basicConstraints'      => 'CA:FALSE',
+      'subjectKeyIdentifier'  => 'hash',
+      'keyUsage'              => 'keyEncipherment,dataEncipherment,digitalSignature',
+  },
+
+  # save the key and cert to a file in build_self_signed_cert()?
+  :save_key   => true,
+  :save_cert  => true,
+
+  # if you define either of these, then they'll be used instead of
+  # the output_fmt macro below
+  :save_key_path => nil,
+  :save_cert_path => nil,
+
+  # output name format for self-signed certs
+  :output_fmt => 'gem-%s.pem',
+  :munge_re   => Regexp.new(/[^a-z0-9_.-]+/),
+
+  # output directory for trusted certificate checksums
+  :trust_dir => File::join(Gem.user_home, '.gem', 'trust'),
+
+  # default permissions for trust directory and certs
+  :perms => {
+    :trust_dir      => 0700,
+    :trusted_cert   => 0600,
+    :signing_cert   => 0600,
+    :signing_key    => 0600,
+  },
+  }
+
+  #
+  # A Gem::Security::Policy object encapsulates the settings for verifying
+  # signed gem files.  This is the base class.  You can either declare an
+  # instance of this or use one of the preset security policies below.
+  #
+  class Policy
+    attr_accessor :verify_data, :verify_signer, :verify_chain,
+      :verify_root, :only_trusted, :only_signed
+
+    #
+    # Create a new Gem::Security::Policy object with the given mode and
+    # options.
+    #
+    def initialize(policy = {}, opt = {})
+      # set options
+      @opt = Gem::Security::OPT.merge(opt)
+
+      # build policy
+      policy.each_pair do |key, val|
+        case key
+        when :verify_data   then @verify_data   = val
+        when :verify_signer then @verify_signer = val
+        when :verify_chain  then @verify_chain  = val
+        when :verify_root   then @verify_root   = val
+        when :only_trusted  then @only_trusted  = val
+        when :only_signed   then @only_signed   = val
+        end
+      end
+    end
+
+    #
+    # Get the path to the file for this cert.
+    #
+    def self.trusted_cert_path(cert, opt = {})
+      opt = Gem::Security::OPT.merge(opt)
+
+      # get digest algorithm, calculate checksum of root.subject
+      algo = opt[:dgst_algo]
+      dgst = algo.hexdigest(cert.subject.to_s)
+
+      # build path to trusted cert file
+      name = "cert-#{dgst}.pem"
+
+      # join and return path components
+      File::join(opt[:trust_dir], name)
+    end
+
+    #
+    # Verify that the gem data with the given signature and signing chain
+    # matched this security policy at the specified time.
+    #
+    def verify_gem(signature, data, chain, time = Time.now)
+      Gem.ensure_ssl_available
+      cert_class = OpenSSL::X509::Certificate
+      exc = Gem::Security::Exception
+      chain ||= []
+
+      chain = chain.map{ |str| cert_class.new(str) }
+      signer, ch_len = chain[-1], chain.size
+
+      # make sure signature is valid
+      if @verify_data
+        # get digest algorithm (TODO: this should be configurable)
+        dgst = @opt[:dgst_algo]
+
+        # verify the data signature (this is the most important part, so don't
+        # screw it up :D)
+        v = signer.public_key.verify(dgst.new, signature, data)
+        raise exc, "Invalid Gem Signature" unless v
+
+        # make sure the signer is valid
+        if @verify_signer
+          # make sure the signing cert is valid right now
+          v = signer.check_validity(nil, time)
+          raise exc, "Invalid Signature: #{v[:desc]}" unless v[:is_valid]
+        end
+      end
+
+      # make sure the certificate chain is valid
+      if @verify_chain
+        # iterate down over the chain and verify each certificate against it's
+        # issuer
+        (ch_len - 1).downto(1) do |i|
+          issuer, cert = chain[i - 1, 2]
+          v = cert.check_validity(issuer, time)
+          raise exc, "%s: cert = '%s', error = '%s'" % [
+              'Invalid Signing Chain', cert.subject, v[:desc]
+          ] unless v[:is_valid]
+        end
+
+        # verify root of chain
+        if @verify_root
+          # make sure root is self-signed
+          root = chain[0]
+          raise exc, "%s: %s (subject = '%s', issuer = '%s')" % [
+              'Invalid Signing Chain Root',
+              'Subject does not match Issuer for Gem Signing Chain',
+              root.subject.to_s,
+              root.issuer.to_s,
+          ] unless root.issuer.to_s == root.subject.to_s
+
+          # make sure root is valid
+          v = root.check_validity(root, time)
+          raise exc, "%s: cert = '%s', error = '%s'" % [
+              'Invalid Signing Chain Root', root.subject, v[:desc]
+          ] unless v[:is_valid]
+
+          # verify that the chain root is trusted
+          if @only_trusted
+            # get digest algorithm, calculate checksum of root.subject
+            algo = @opt[:dgst_algo]
+            path = Gem::Security::Policy.trusted_cert_path(root, @opt)
+
+            # check to make sure trusted path exists
+            raise exc, "%s: cert = '%s', error = '%s'" % [
+                'Untrusted Signing Chain Root',
+                root.subject.to_s,
+                "path \"#{path}\" does not exist",
+            ] unless File.exist?(path)
+
+            # load calculate digest from saved cert file
+            save_cert = OpenSSL::X509::Certificate.new(File.read(path))
+            save_dgst = algo.digest(save_cert.public_key.to_s)
+
+            # create digest of public key
+            pkey_str = root.public_key.to_s
+            cert_dgst = algo.digest(pkey_str)
+
+            # now compare the two digests, raise exception
+            # if they don't match
+            raise exc, "%s: %s (saved = '%s', root = '%s')" % [
+                'Invalid Signing Chain Root',
+                "Saved checksum doesn't match root checksum",
+                save_dgst, cert_dgst,
+            ] unless save_dgst == cert_dgst
+          end
+        end
+
+        # return the signing chain
+        chain.map { |cert| cert.subject }
+      end
+    end
+  end
+
+  #
+  # No security policy: all package signature checks are disabled.
+  #
+  NoSecurity = Policy.new(
+    :verify_data      => false,
+    :verify_signer    => false,
+    :verify_chain     => false,
+    :verify_root      => false,
+    :only_trusted     => false,
+    :only_signed      => false
+  )
+
+  #
+  # AlmostNo security policy: only verify that the signing certificate is the
+  # one that actually signed the data.  Make no attempt to verify the signing
+  # certificate chain.
+  #
+  # This policy is basically useless. better than nothing, but can still be
+  # easily spoofed, and is not recommended.
+  #
+  AlmostNoSecurity = Policy.new(
+    :verify_data      => true,
+    :verify_signer    => false,
+    :verify_chain     => false,
+    :verify_root      => false,
+    :only_trusted     => false,
+    :only_signed      => false
+  )
+
+  #
+  # Low security policy: only verify that the signing certificate is actually
+  # the gem signer, and that the signing certificate is valid.
+  #
+  # This policy is better than nothing, but can still be easily spoofed, and
+  # is not recommended.
+  #
+  LowSecurity = Policy.new(
+    :verify_data      => true,
+    :verify_signer    => true,
+    :verify_chain     => false,
+    :verify_root      => false,
+    :only_trusted     => false,
+    :only_signed      => false
+  )
+
+  #
+  # Medium security policy: verify the signing certificate, verify the signing
+  # certificate chain all the way to the root certificate, and only trust root
+  # certificates that we have explicitly allowed trust for.
+  #
+  # This security policy is reasonable, but it allows unsigned packages, so a
+  # malicious person could simply delete the package signature and pass the
+  # gem off as unsigned.
+  #
+  MediumSecurity = Policy.new(
+    :verify_data      => true,
+    :verify_signer    => true,
+    :verify_chain     => true,
+    :verify_root      => true,
+    :only_trusted     => true,
+    :only_signed      => false
+  )
+
+  #
+  # High security policy: only allow signed gems to be installed, verify the
+  # signing certificate, verify the signing certificate chain all the way to
+  # the root certificate, and only trust root certificates that we have
+  # explicitly allowed trust for.
+  #
+  # This security policy is significantly more difficult to bypass, and offers
+  # a reasonable guarantee that the contents of the gem have not been altered.
+  #
+  HighSecurity = Policy.new(
+    :verify_data      => true,
+    :verify_signer    => true,
+    :verify_chain     => true,
+    :verify_root      => true,
+    :only_trusted     => true,
+    :only_signed      => true
+  )
+
+  #
+  # Hash of configured security policies
+  #
+  Policies = {
+    'NoSecurity'       => NoSecurity,
+    'AlmostNoSecurity' => AlmostNoSecurity,
+    'LowSecurity'      => LowSecurity,
+    'MediumSecurity'   => MediumSecurity,
+    'HighSecurity'     => HighSecurity,
+  }
+
+  #
+  # Sign the cert cert with @signing_key and @signing_cert, using the digest
+  # algorithm opt[:dgst_algo]. Returns the newly signed certificate.
+  #
+  def self.sign_cert(cert, signing_key, signing_cert, opt = {})
+    opt = OPT.merge(opt)
+
+    # set up issuer information
+    cert.issuer = signing_cert.subject
+    cert.sign(signing_key, opt[:dgst_algo].new)
+
+    cert
+  end
+
+  #
+  # Make sure the trust directory exists.  If it does exist, make sure it's
+  # actually a directory.  If not, then create it with the appropriate
+  # permissions.
+  #
+  def self.verify_trust_dir(path, perms)
+    # if the directory exists, then make sure it is in fact a directory.  if
+    # it doesn't exist, then create it with the appropriate permissions
+    if File.exist?(path)
+      # verify that the trust directory is actually a directory
+      unless File.directory?(path)
+        err = "trust directory #{path} isn't a directory"
+        raise Gem::Security::Exception, err
+      end
+    else
+      # trust directory doesn't exist, so create it with permissions
+      FileUtils.mkdir_p(path)
+      FileUtils.chmod(perms, path)
+    end
+  end
+
+  #
+  # Build a certificate from the given DN and private key.
+  #
+  def self.build_cert(name, key, opt = {})
+    Gem.ensure_ssl_available
+    opt = OPT.merge(opt)
+
+    # create new cert
+    ret = OpenSSL::X509::Certificate.new
+
+    # populate cert attributes
+    ret.version = 2
+    ret.serial = 0
+    ret.public_key = key.public_key
+    ret.not_before = Time.now
+    ret.not_after = Time.now + opt[:cert_age]
+    ret.subject = name
+
+    # add certificate extensions
+    ef = OpenSSL::X509::ExtensionFactory.new(nil, ret)
+    ret.extensions = opt[:cert_exts].map { |k, v| ef.create_extension(k, v) }
+
+    # sign cert
+    i_key, i_cert = opt[:issuer_key] || key, opt[:issuer_cert] || ret
+    ret = sign_cert(ret, i_key, i_cert, opt)
+
+    # return cert
+    ret
+  end
+
+  #
+  # Build a self-signed certificate for the given email address.
+  #
+  def self.build_self_signed_cert(email_addr, opt = {})
+    Gem.ensure_ssl_available
+    opt = OPT.merge(opt)
+    path = { :key => nil, :cert => nil }
+
+    # split email address up
+    cn, dcs = email_addr.split('@')
+    dcs = dcs.split('.')
+
+    # munge email CN and DCs
+    cn = cn.gsub(opt[:munge_re], '_')
+    dcs = dcs.map { |dc| dc.gsub(opt[:munge_re], '_') }
+
+    # create DN
+    name = "CN=#{cn}/" << dcs.map { |dc| "DC=#{dc}" }.join('/')
+    name = OpenSSL::X509::Name::parse(name)
+
+    # build private key
+    key = opt[:key_algo].new(opt[:key_size])
+
+    # method name pretty much says it all :)
+    verify_trust_dir(opt[:trust_dir], opt[:perms][:trust_dir])
+
+    # if we're saving the key, then write it out
+    if opt[:save_key]
+      path[:key] = opt[:save_key_path] || (opt[:output_fmt] % 'private_key')
+      File.open(path[:key], 'wb') do |file|
+        file.chmod(opt[:perms][:signing_key])
+        file.write(key.to_pem)
+      end
+    end
+
+    # build self-signed public cert from key
+    cert = build_cert(name, key, opt)
+
+    # if we're saving the cert, then write it out
+    if opt[:save_cert]
+      path[:cert] = opt[:save_cert_path] || (opt[:output_fmt] % 'public_cert')
+      File.open(path[:cert], 'wb') do |file|
+        file.chmod(opt[:perms][:signing_cert])
+        file.write(cert.to_pem)
+      end
+    end
+
+    # return key, cert, and paths (if applicable)
+    { :key => key, :cert => cert,
+      :key_path => path[:key], :cert_path => path[:cert] }
+  end
+
+  #
+  # Add certificate to trusted cert list.
+  #
+  # Note: At the moment these are stored in OPT[:trust_dir], although that
+  # directory may change in the future.
+  #
+  def self.add_trusted_cert(cert, opt = {})
+    opt = OPT.merge(opt)
+
+    # get destination path
+    path = Gem::Security::Policy.trusted_cert_path(cert, opt)
+
+    # verify trust directory (can't write to nowhere, you know)
+    verify_trust_dir(opt[:trust_dir], opt[:perms][:trust_dir])
+
+    # write cert to output file
+    File.open(path, 'wb') do |file|
+      file.chmod(opt[:perms][:trusted_cert])
+      file.write(cert.to_pem)
+    end
+
+    # return nil
+    nil
+  end
+
+  #
+  # Basic OpenSSL-based package signing class.
+  #
+  class Signer
+    attr_accessor :key, :cert_chain
+
+    def initialize(key, cert_chain)
+      Gem.ensure_ssl_available
+      @algo = Gem::Security::OPT[:dgst_algo]
+      @key, @cert_chain = key, cert_chain
+
+      # check key, if it's a file, and if it's key, leave it alone
+      if @key && !@key.kind_of?(OpenSSL::PKey::PKey)
+        @key = OpenSSL::PKey::RSA.new(File.read(@key))
+      end
+
+      # check cert chain, if it's a file, load it, if it's cert data, convert
+      # it into a cert object, and if it's a cert object, leave it alone
+      if @cert_chain
+        @cert_chain = @cert_chain.map do |cert|
+          # check cert, if it's a file, load it, if it's cert data, convert it
+          # into a cert object, and if it's a cert object, leave it alone
+          if cert && !cert.kind_of?(OpenSSL::X509::Certificate)
+            cert = File.read(cert) if File::exist?(cert)
+            cert = OpenSSL::X509::Certificate.new(cert)
+          end
+          cert
+        end
+      end
+    end
+
+    #
+    # Sign data with given digest algorithm
+    #
+    def sign(data)
+      @key.sign(@algo.new, data)
+    end
+
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/server.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/server.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/server.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,813 @@
+require 'webrick'
+require 'yaml'
+require 'zlib'
+require 'erb'
+
+require 'rubygems'
+require 'rubygems/doc_manager'
+
+##
+# Gem::Server and allows users to serve gems for consumption by
+# `gem --remote-install`.
+#
+# gem_server starts an HTTP server on the given port and serves the following:
+# * "/" - Browsing of gem spec files for installed gems
+# * "/specs.#{Gem.marshal_version}.gz" - specs name/version/platform index
+# * "/latest_specs.#{Gem.marshal_version}.gz" - latest specs
+#   name/version/platform index
+# * "/quick/" - Individual gemspecs
+# * "/gems" - Direct access to download the installable gems
+# * "/rdoc?q=" - Search for installed rdoc documentation
+# * legacy indexes:
+#   * "/Marshal.#{Gem.marshal_version}" - Full SourceIndex dump of metadata
+#     for installed gems
+#   * "/yaml" - YAML dump of metadata for installed gems - deprecated
+#
+# == Usage
+#
+#   gem_server = Gem::Server.new Gem.dir, 8089, false
+#   gem_server.run
+#
+#--
+# TODO Refactor into a real WEBrick servlet to remove code duplication.
+
+class Gem::Server
+
+  include ERB::Util
+  include Gem::UserInteraction
+
+  SEARCH = <<-SEARCH
+      <form class="headerSearch" name="headerSearchForm" method="get" action="/rdoc">
+        <div id="search" style="float:right">
+          <span>Filter/Search</span>
+          <input id="q" type="text" style="width:10em" name="q"/>
+          <button type="submit" style="display:none" />
+        </div>
+      </form>
+  SEARCH
+
+  DOC_TEMPLATE = <<-'DOC_TEMPLATE'
+  <?xml version="1.0" encoding="iso-8859-1"?>
+  <!DOCTYPE html
+       PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <title>RubyGems Documentation Index</title>
+    <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
+  </head>
+  <body>
+    <div id="fileHeader">
+<%= SEARCH %>
+      <h1>RubyGems Documentation Index</h1>
+    </div>
+    <!-- banner header -->
+
+  <div id="bodyContent">
+    <div id="contextContent">
+      <div id="description">
+        <h1>Summary</h1>
+  <p>There are <%=values["gem_count"]%> gems installed:</p>
+  <p>
+  <%= values["specs"].map { |v| "<a href=\"##{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
+  <h1>Gems</h1>
+
+  <dl>
+  <% values["specs"].each do |spec| %>
+  	<dt>
+  	<% if spec["first_name_entry"] then %>
+  	  <a name="<%=spec["name"]%>"></a>
+  	<% end %>
+
+  	<b><%=spec["name"]%> <%=spec["version"]%></b>
+
+  	<% if spec["rdoc_installed"] then %>
+  	  <a href="<%=spec["doc_path"]%>">[rdoc]</a>
+  	<% else %>
+  	  <span title="rdoc not installed">[rdoc]</span>
+  	<% end %>
+
+  	<% if spec["homepage"] then %>
+  		<a href="<%=spec["homepage"]%>" title="<%=spec["homepage"]%>">[www]</a>
+  	<% else %>
+  		<span title="no homepage available">[www]</span>
+  	<% end %>
+
+  	<% if spec["has_deps"] then %>
+  	 - depends on
+  		<%= spec["dependencies"].map { |v| "<a href=\"##{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
+  	<% end %>
+  	</dt>
+  	<dd>
+  	<%=spec["summary"]%>
+  	<% if spec["executables"] then %>
+  	  <br/>
+
+  		<% if spec["only_one_executable"] then %>
+  		    Executable is
+  		<% else %>
+  		    Executables are
+  		<%end%>
+
+  		<%= spec["executables"].map { |v| "<span class=\"context-item-name\">#{v["executable"]}</span>"}.join ', ' %>.
+
+  	<%end%>
+  	<br/>
+  	<br/>
+  	</dd>
+  <% end %>
+  </dl>
+
+      </div>
+     </div>
+    </div>
+  <div id="validator-badges">
+    <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+  </div>
+  </body>
+  </html>
+  DOC_TEMPLATE
+
+  # CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
+  RDOC_CSS = <<-RDOC_CSS
+body {
+    font-family: Verdana,Arial,Helvetica,sans-serif;
+    font-size:   90%;
+    margin: 0;
+    margin-left: 40px;
+    padding: 0;
+    background: white;
+}
+
+h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
+h1 { font-size: 150%; }
+h2,h3,h4 { margin-top: 1em; }
+
+a { background: #eef; color: #039; text-decoration: none; }
+a:hover { background: #039; color: #eef; }
+
+/* Override the base stylesheets Anchor inside a table cell */
+td > a {
+  background: transparent;
+  color: #039;
+  text-decoration: none;
+}
+
+/* and inside a section title */
+.section-title > a {
+  background: transparent;
+  color: #eee;
+  text-decoration: none;
+}
+
+/* === Structural elements =================================== */
+
+div#index {
+    margin: 0;
+    margin-left: -40px;
+    padding: 0;
+    font-size: 90%;
+}
+
+
+div#index a {
+    margin-left: 0.7em;
+}
+
+div#index .section-bar {
+   margin-left: 0px;
+   padding-left: 0.7em;
+   background: #ccc;
+   font-size: small;
+}
+
+
+div#classHeader, div#fileHeader {
+    width: auto;
+    color: white;
+    padding: 0.5em 1.5em 0.5em 1.5em;
+    margin: 0;
+    margin-left: -40px;
+    border-bottom: 3px solid #006;
+}
+
+div#classHeader a, div#fileHeader a {
+    background: inherit;
+    color: white;
+}
+
+div#classHeader td, div#fileHeader td {
+    background: inherit;
+    color: white;
+}
+
+
+div#fileHeader {
+    background: #057;
+}
+
+div#classHeader {
+    background: #048;
+}
+
+
+.class-name-in-header {
+  font-size:  180%;
+  font-weight: bold;
+}
+
+
+div#bodyContent {
+    padding: 0 1.5em 0 1.5em;
+}
+
+div#description {
+    padding: 0.5em 1.5em;
+    background: #efefef;
+    border: 1px dotted #999;
+}
+
+div#description h1,h2,h3,h4,h5,h6 {
+    color: #125;;
+    background: transparent;
+}
+
+div#validator-badges {
+    text-align: center;
+}
+div#validator-badges img { border: 0; }
+
+div#copyright {
+    color: #333;
+    background: #efefef;
+    font: 0.75em sans-serif;
+    margin-top: 5em;
+    margin-bottom: 0;
+    padding: 0.5em 2em;
+}
+
+
+/* === Classes =================================== */
+
+table.header-table {
+    color: white;
+    font-size: small;
+}
+
+.type-note {
+    font-size: small;
+    color: #DEDEDE;
+}
+
+.xxsection-bar {
+    background: #eee;
+    color: #333;
+    padding: 3px;
+}
+
+.section-bar {
+   color: #333;
+   border-bottom: 1px solid #999;
+    margin-left: -20px;
+}
+
+
+.section-title {
+    background: #79a;
+    color: #eee;
+    padding: 3px;
+    margin-top: 2em;
+    margin-left: -30px;
+    border: 1px solid #999;
+}
+
+.top-aligned-row {  vertical-align: top }
+.bottom-aligned-row { vertical-align: bottom }
+
+/* --- Context section classes ----------------------- */
+
+.context-row { }
+.context-item-name { font-family: monospace; font-weight: bold; color: black; }
+.context-item-value { font-size: small; color: #448; }
+.context-item-desc { color: #333; padding-left: 2em; }
+
+/* --- Method classes -------------------------- */
+.method-detail {
+    background: #efefef;
+    padding: 0;
+    margin-top: 0.5em;
+    margin-bottom: 1em;
+    border: 1px dotted #ccc;
+}
+.method-heading {
+  color: black;
+  background: #ccc;
+  border-bottom: 1px solid #666;
+  padding: 0.2em 0.5em 0 0.5em;
+}
+.method-signature { color: black; background: inherit; }
+.method-name { font-weight: bold; }
+.method-args { font-style: italic; }
+.method-description { padding: 0 0.5em 0 0.5em; }
+
+/* --- Source code sections -------------------- */
+
+a.source-toggle { font-size: 90%; }
+div.method-source-code {
+    background: #262626;
+    color: #ffdead;
+    margin: 1em;
+    padding: 0.5em;
+    border: 1px dashed #999;
+    overflow: hidden;
+}
+
+div.method-source-code pre { color: #ffdead; overflow: hidden; }
+
+/* --- Ruby keyword styles --------------------- */
+
+.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
+
+.ruby-constant  { color: #7fffd4; background: transparent; }
+.ruby-keyword { color: #00ffff; background: transparent; }
+.ruby-ivar    { color: #eedd82; background: transparent; }
+.ruby-operator  { color: #00ffee; background: transparent; }
+.ruby-identifier { color: #ffdead; background: transparent; }
+.ruby-node    { color: #ffa07a; background: transparent; }
+.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
+.ruby-regexp  { color: #ffa07a; background: transparent; }
+.ruby-value   { color: #7fffd4; background: transparent; }
+  RDOC_CSS
+
+  RDOC_NO_DOCUMENTATION = <<-'NO_DOC'
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <title>Found documentation</title>
+    <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
+  </head>
+  <body>
+    <div id="fileHeader">
+<%= SEARCH %>
+      <h1>No documentation found</h1>
+    </div>
+
+    <div id="bodyContent">
+      <div id="contextContent">
+        <div id="description">
+          <p>No gems matched <%= h query.inspect %></p>
+
+          <p>
+            Back to <a href="/">complete gem index</a>
+          </p>
+
+        </div>
+      </div>
+    </div>
+    <div id="validator-badges">
+      <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+    </div>
+  </body>
+</html>
+  NO_DOC
+
+  RDOC_SEARCH_TEMPLATE = <<-'RDOC_SEARCH'
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <title>Found documentation</title>
+    <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
+  </head>
+  <body>
+    <div id="fileHeader">
+<%= SEARCH %>
+      <h1>Found documentation</h1>
+    </div>
+    <!-- banner header -->
+
+    <div id="bodyContent">
+      <div id="contextContent">
+        <div id="description">
+          <h1>Summary</h1>
+          <p><%=doc_items.length%> documentation topics found.</p>
+          <h1>Topics</h1>
+
+          <dl>
+          <% doc_items.each do |doc_item| %>
+            <dt>
+              <b><%=doc_item[:name]%></b>
+              <a href="<%=doc_item[:url]%>">[rdoc]</a>
+            </dt>
+            <dd>
+              <%=doc_item[:summary]%>
+              <br/>
+              <br/>
+            </dd>
+          <% end %>
+          </dl>
+
+          <p>
+            Back to <a href="/">complete gem index</a>
+          </p>
+
+        </div>
+      </div>
+    </div>
+    <div id="validator-badges">
+      <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+    </div>
+  </body>
+</html>
+  RDOC_SEARCH
+
+  def self.run(options)
+    new(options[:gemdir], options[:port], options[:daemon]).run
+  end
+
+  def initialize(gem_dir, port, daemon)
+    Socket.do_not_reverse_lookup = true
+
+    @gem_dir = gem_dir
+    @port = port
+    @daemon = daemon
+    logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
+    @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
+
+    @spec_dir = File.join @gem_dir, 'specifications'
+
+    unless File.directory? @spec_dir then
+      raise ArgumentError, "#{@gem_dir} does not appear to be a gem repository"
+    end
+
+    @source_index = Gem::SourceIndex.from_gems_in @spec_dir
+  end
+
+  def Marshal(req, res)
+    @source_index.refresh!
+
+    res['date'] = File.stat(@spec_dir).mtime
+
+    index = Marshal.dump @source_index
+
+    if req.request_method == 'HEAD' then
+      res['content-length'] = index.length
+      return
+    end
+
+    if req.path =~ /Z$/ then
+      res['content-type'] = 'application/x-deflate'
+      index = Gem.deflate index
+    else
+      res['content-type'] = 'application/octet-stream'
+    end
+
+    res.body << index
+  end
+
+  def latest_specs(req, res)
+    @source_index.refresh!
+
+    res['content-type'] = 'application/x-gzip'
+
+    res['date'] = File.stat(@spec_dir).mtime
+
+    specs = @source_index.latest_specs.sort.map do |spec|
+      platform = spec.original_platform
+      platform = Gem::Platform::RUBY if platform.nil?
+      [spec.name, spec.version, platform]
+    end
+
+    specs = Marshal.dump specs
+
+    if req.path =~ /\.gz$/ then
+      specs = Gem.gzip specs
+      res['content-type'] = 'application/x-gzip'
+    else
+      res['content-type'] = 'application/octet-stream'
+    end
+
+    if req.request_method == 'HEAD' then
+      res['content-length'] = specs.length
+    else
+      res.body << specs
+    end
+  end
+
+  def quick(req, res)
+    @source_index.refresh!
+
+    res['content-type'] = 'text/plain'
+    res['date'] = File.stat(@spec_dir).mtime
+
+    case req.request_uri.path
+    when '/quick/index' then
+      res.body << @source_index.map { |name,| name }.sort.join("\n")
+    when '/quick/index.rz' then
+      index = @source_index.map { |name,| name }.sort.join("\n")
+      res['content-type'] = 'application/x-deflate'
+      res.body << Gem.deflate(index)
+    when '/quick/latest_index' then
+      index = @source_index.latest_specs.map { |spec| spec.full_name }
+      res.body << index.sort.join("\n")
+    when '/quick/latest_index.rz' then
+      index = @source_index.latest_specs.map { |spec| spec.full_name }
+      res['content-type'] = 'application/x-deflate'
+      res.body << Gem.deflate(index.sort.join("\n"))
+    when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)-([0-9.]+)(-.*?)?\.gemspec\.rz$| then
+      dep = Gem::Dependency.new $2, $3
+      specs = @source_index.search dep
+      marshal_format = $1
+
+      selector = [$2, $3, $4].map { |s| s.inspect }.join ' '
+
+      platform = if $4 then
+                   Gem::Platform.new $4.sub(/^-/, '')
+                 else
+                   Gem::Platform::RUBY
+                 end
+
+      specs = specs.select { |s| s.platform == platform }
+
+      if specs.empty? then
+        res.status = 404
+        res.body = "No gems found matching #{selector}"
+      elsif specs.length > 1 then
+        res.status = 500
+        res.body = "Multiple gems found matching #{selector}"
+      elsif marshal_format then
+        res['content-type'] = 'application/x-deflate'
+        res.body << Gem.deflate(Marshal.dump(specs.first))
+      else # deprecated YAML format
+        res['content-type'] = 'application/x-deflate'
+        res.body << Gem.deflate(specs.first.to_yaml)
+      end
+    else
+      raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found."
+    end
+  end
+
+  def root(req, res)
+    @source_index.refresh!
+    res['date'] = File.stat(@spec_dir).mtime
+
+    raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." unless
+      req.path == '/'
+
+    specs = []
+    total_file_count = 0
+
+    @source_index.each do |path, spec|
+      total_file_count += spec.files.size
+      deps = spec.dependencies.map do |dep|
+        { "name"    => dep.name,
+          "type"    => dep.type,
+          "version" => dep.version_requirements.to_s, }
+      end
+
+      deps = deps.sort_by { |dep| [dep["name"].downcase, dep["version"]] }
+      deps.last["is_last"] = true unless deps.empty?
+
+      # executables
+      executables = spec.executables.sort.collect { |exec| {"executable" => exec} }
+      executables = nil if executables.empty?
+      executables.last["is_last"] = true if executables
+
+      specs << {
+        "authors"             => spec.authors.sort.join(", "),
+        "date"                => spec.date.to_s,
+        "dependencies"        => deps,
+        "doc_path"            => "/doc_root/#{spec.full_name}/rdoc/index.html",
+        "executables"         => executables,
+        "only_one_executable" => (executables && executables.size == 1),
+        "full_name"           => spec.full_name,
+        "has_deps"            => !deps.empty?,
+        "homepage"            => spec.homepage,
+        "name"                => spec.name,
+        "rdoc_installed"      => Gem::DocManager.new(spec).rdoc_installed?,
+        "summary"             => spec.summary,
+        "version"             => spec.version.to_s,
+      }
+    end
+
+    specs << {
+      "authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others",
+      "dependencies" => [],
+      "doc_path" => "/doc_root/rubygems-#{Gem::RubyGemsVersion}/rdoc/index.html",
+      "executables" => [{"executable" => 'gem', "is_last" => true}],
+      "only_one_executable" => true,
+      "full_name" => "rubygems-#{Gem::RubyGemsVersion}",
+      "has_deps" => false,
+      "homepage" => "http://rubygems.org/",
+      "name" => 'rubygems',
+      "rdoc_installed" => true,
+      "summary" => "RubyGems itself",
+      "version" => Gem::RubyGemsVersion,
+    }
+
+    specs = specs.sort_by { |spec| [spec["name"].downcase, spec["version"]] }
+    specs.last["is_last"] = true
+
+    # tag all specs with first_name_entry
+    last_spec = nil
+    specs.each do |spec|
+      is_first = last_spec.nil? || (last_spec["name"].downcase != spec["name"].downcase)
+      spec["first_name_entry"] = is_first
+      last_spec = spec
+    end
+
+    # create page from template
+    template = ERB.new(DOC_TEMPLATE)
+    res['content-type'] = 'text/html'
+
+    values = { "gem_count" => specs.size.to_s, "specs" => specs,
+               "total_file_count" => total_file_count.to_s }
+
+    result = template.result binding
+    res.body = result
+  end
+
+  ##
+  # Can be used for quick navigation to the rdoc documentation.  You can then
+  # define a search shortcut for your browser.  E.g. in Firefox connect
+  # 'shortcut:rdoc' to http://localhost:8808/rdoc?q=%s template. Then you can
+  # directly open the ActionPack documentation by typing 'rdoc actionp'. If
+  # there are multiple hits for the search term, they are presented as a list
+  # with links.
+  #
+  # Search algorithm aims for an intuitive search:
+  # 1. first try to find the gems and documentation folders which name
+  #    starts with the search term
+  # 2. search for entries, that *contain* the search term
+  # 3. show all the gems
+  #
+  # If there is only one search hit, user is immediately redirected to the
+  # documentation for the particular gem, otherwise a list with results is
+  # shown.
+  #
+  # === Additional trick - install documentation for ruby core
+  #
+  # Note: please adjust paths accordingly use for example 'locate yaml.rb' and
+  # 'gem environment' to identify directories, that are specific for your
+  # local installation
+  #
+  # 1. install ruby sources
+  #      cd /usr/src
+  #      sudo apt-get source ruby
+  #
+  # 2. generate documentation
+  #      rdoc -o /usr/lib/ruby/gems/1.8/doc/core/rdoc \
+  #        /usr/lib/ruby/1.8 ruby1.8-1.8.7.72
+  #
+  # By typing 'rdoc core' you can now access the core documentation
+
+  def rdoc(req, res)
+    query = req.query['q']
+    show_rdoc_for_pattern("#{query}*", res) && return
+    show_rdoc_for_pattern("*#{query}*", res) && return
+
+    template = ERB.new RDOC_NO_DOCUMENTATION
+
+    res['content-type'] = 'text/html'
+    res.body = template.result binding
+  end
+
+  ##
+  # Returns true and prepares http response, if rdoc for the requested gem
+  # name pattern was found.
+  #
+  # The search is based on the file system content, not on the gems metadata.
+  # This allows additional documentation folders like 'core' for the ruby core
+  # documentation - just put it underneath the main doc folder.
+
+  def show_rdoc_for_pattern(pattern, res)
+    found_gems = Dir.glob("#{@gem_dir}/doc/#{pattern}").select {|path|
+      File.exist? File.join(path, 'rdoc/index.html')
+    }
+    case found_gems.length
+    when 0
+      return false
+    when 1
+      new_path = File.basename(found_gems[0])
+      res.status = 302
+      res['Location'] = "/doc_root/#{new_path}/rdoc/index.html"
+      return true
+    else
+      doc_items = []
+      found_gems.each do |file_name|
+        base_name = File.basename(file_name)
+        doc_items << {
+          :name => base_name,
+          :url => "/doc_root/#{base_name}/rdoc/index.html",
+          :summary => ''
+        }
+      end
+
+      template = ERB.new(RDOC_SEARCH_TEMPLATE)
+      res['content-type'] = 'text/html'
+      result = template.result binding
+      res.body = result
+      return true
+    end
+  end
+
+  def run
+    @server.listen nil, @port
+
+    say "Starting gem server on http://localhost:#{@port}/"
+
+    WEBrick::Daemon.start if @daemon
+
+    @server.mount_proc "/yaml", method(:yaml)
+    @server.mount_proc "/yaml.Z", method(:yaml)
+
+    @server.mount_proc "/Marshal.#{Gem.marshal_version}", method(:Marshal)
+    @server.mount_proc "/Marshal.#{Gem.marshal_version}.Z", method(:Marshal)
+
+    @server.mount_proc "/specs.#{Gem.marshal_version}", method(:specs)
+    @server.mount_proc "/specs.#{Gem.marshal_version}.gz", method(:specs)
+
+    @server.mount_proc "/latest_specs.#{Gem.marshal_version}",
+                       method(:latest_specs)
+    @server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz",
+                       method(:latest_specs)
+
+    @server.mount_proc "/quick/", method(:quick)
+
+    @server.mount_proc("/gem-server-rdoc-style.css") do |req, res|
+      res['content-type'] = 'text/css'
+      res['date'] = File.stat(@spec_dir).mtime
+      res.body << RDOC_CSS
+    end
+
+    @server.mount_proc "/", method(:root)
+
+    @server.mount_proc "/rdoc", method(:rdoc)
+
+    paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
+    paths.each do |mount_point, mount_dir|
+      @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
+                    File.join(@gem_dir, mount_dir), true)
+    end
+
+    trap("INT") { @server.shutdown; exit! }
+    trap("TERM") { @server.shutdown; exit! }
+
+    @server.start
+  end
+
+  def specs(req, res)
+    @source_index.refresh!
+
+    res['date'] = File.stat(@spec_dir).mtime
+
+    specs = @source_index.sort.map do |_, spec|
+      platform = spec.original_platform
+      platform = Gem::Platform::RUBY if platform.nil?
+      [spec.name, spec.version, platform]
+    end
+
+    specs = Marshal.dump specs
+
+    if req.path =~ /\.gz$/ then
+      specs = Gem.gzip specs
+      res['content-type'] = 'application/x-gzip'
+    else
+      res['content-type'] = 'application/octet-stream'
+    end
+
+    if req.request_method == 'HEAD' then
+      res['content-length'] = specs.length
+    else
+      res.body << specs
+    end
+  end
+
+  def yaml(req, res)
+    @source_index.refresh!
+
+    res['date'] = File.stat(@spec_dir).mtime
+
+    index = @source_index.to_yaml
+
+    if req.path =~ /Z$/ then
+      res['content-type'] = 'application/x-deflate'
+      index = Gem.deflate index
+    else
+      res['content-type'] = 'text/plain'
+    end
+
+    if req.request_method == 'HEAD' then
+      res['content-length'] = index.length
+      return
+    end
+
+    res.body << index
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_index.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_index.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_index.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,597 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/user_interaction'
+require 'rubygems/specification'
+
+# :stopdoc:
+module Gem
+  autoload :SpecFetcher, 'rubygems/spec_fetcher'
+end
+# :startdoc:
+
+##
+# The SourceIndex object indexes all the gems available from a
+# particular source (e.g. a list of gem directories, or a remote
+# source).  A SourceIndex maps a gem full name to a gem
+# specification.
+#
+# NOTE:: The class used to be named Cache, but that became
+#        confusing when cached source fetchers where introduced. The
+#        constant Gem::Cache is an alias for this class to allow old
+#        YAMLized source index objects to load properly.
+
+class Gem::SourceIndex
+
+  include Enumerable
+
+  include Gem::UserInteraction
+
+  attr_reader :gems # :nodoc:
+
+  ##
+  # Directories to use to refresh this SourceIndex when calling refresh!
+
+  attr_accessor :spec_dirs
+
+  class << self
+    include Gem::UserInteraction
+
+    ##
+    # Factory method to construct a source index instance for a given
+    # path.
+    #
+    # deprecated::
+    #   If supplied, from_installed_gems will act just like
+    #   +from_gems_in+.  This argument is deprecated and is provided
+    #   just for backwards compatibility, and should not generally
+    #   be used.
+    #
+    # return::
+    #   SourceIndex instance
+
+    def from_installed_gems(*deprecated)
+      if deprecated.empty?
+        from_gems_in(*installed_spec_directories)
+      else
+        from_gems_in(*deprecated) # HACK warn
+      end
+    end
+
+    ##
+    # Returns a list of directories from Gem.path that contain specifications.
+
+    def installed_spec_directories
+      Gem.path.collect { |dir| File.join(dir, "specifications") }
+    end
+
+    ##
+    # Creates a new SourceIndex from the ruby format gem specifications in
+    # +spec_dirs+.
+
+    def from_gems_in(*spec_dirs)
+      source_index = new
+      source_index.spec_dirs = spec_dirs
+      source_index.refresh!
+    end
+
+    ##
+    # Loads a ruby-format specification from +file_name+ and returns the
+    # loaded spec.
+
+    def load_specification(file_name)
+      return nil unless file_name and File.exist? file_name
+
+      spec_code = if RUBY_VERSION < '1.9' then
+                    File.read file_name
+                  else
+                    File.read file_name, :encoding => 'UTF-8'
+                  end.untaint
+
+      begin
+        gemspec = eval spec_code, binding, file_name
+
+        if gemspec.is_a?(Gem::Specification)
+          gemspec.loaded_from = file_name
+          return gemspec
+        end
+        alert_warning "File '#{file_name}' does not evaluate to a gem specification"
+      rescue SignalException, SystemExit
+        raise
+      rescue SyntaxError => e
+        alert_warning e
+        alert_warning spec_code
+      rescue Exception => e
+        alert_warning "#{e.inspect}\n#{spec_code}"
+        alert_warning "Invalid .gemspec format in '#{file_name}'"
+      end
+
+      return nil
+    end
+
+  end
+
+  ##
+  # Constructs a source index instance from the provided specifications, which
+  # is a Hash of gem full names and Gem::Specifications.
+  #--
+  # TODO merge @gems and @prerelease_gems and provide a separate method
+  # #prerelease_gems
+
+  def initialize(specifications={})
+    @gems = {}
+    specifications.each{ |full_name, spec| add_spec spec }
+    @spec_dirs = nil
+  end
+
+  # TODO: remove method
+  def all_gems
+    @gems
+  end
+
+  def prerelease_gems
+    @gems.reject{ |name, gem| !gem.version.prerelease? }
+  end
+
+  def released_gems
+    @gems.reject{ |name, gem| gem.version.prerelease? }
+  end
+
+  ##
+  # Reconstruct the source index from the specifications in +spec_dirs+.
+
+  def load_gems_in(*spec_dirs)
+    @gems.clear
+
+    spec_dirs.reverse_each do |spec_dir|
+      spec_files = Dir.glob File.join(spec_dir, '*.gemspec')
+
+      spec_files.each do |spec_file|
+        gemspec = self.class.load_specification spec_file.untaint
+        add_spec gemspec if gemspec
+      end
+    end
+
+    self
+  end
+
+  ##
+  # Returns an Array specifications for the latest released versions
+  # of each gem in this index.
+
+  def latest_specs
+    result = Hash.new { |h,k| h[k] = [] }
+    latest = {}
+
+    sort.each do |_, spec|
+      name = spec.name
+      curr_ver = spec.version
+      prev_ver = latest.key?(name) ? latest[name].version : nil
+
+      next if curr_ver.prerelease?
+      next unless prev_ver.nil? or curr_ver >= prev_ver or
+                  latest[name].platform != Gem::Platform::RUBY
+
+      if prev_ver.nil? or
+         (curr_ver > prev_ver and spec.platform == Gem::Platform::RUBY) then
+        result[name].clear
+        latest[name] = spec
+      end
+
+      if spec.platform != Gem::Platform::RUBY then
+        result[name].delete_if do |result_spec|
+          result_spec.platform == spec.platform
+        end
+      end
+
+      result[name] << spec
+    end
+
+    # TODO: why is this a hash while @gems is an array? Seems like
+    # structural similarity would be good.
+    result.values.flatten
+  end
+
+  ##
+  # An array including only the prerelease gemspecs
+
+  def prerelease_specs
+    prerelease_gems.values
+  end
+
+  ##
+  # An array including only the released gemspecs
+
+  def released_specs
+    released_gems.values
+  end
+
+  ##
+  # Add a gem specification to the source index.
+
+  def add_spec(gem_spec, name = gem_spec.full_name)
+    # No idea why, but the Indexer wants to insert them using original_name
+    # instead of full_name. So we make it an optional arg.
+    @gems[name] = gem_spec
+  end
+
+  ##
+  # Add gem specifications to the source index.
+
+  def add_specs(*gem_specs)
+    gem_specs.each do |spec|
+      add_spec spec
+    end
+  end
+
+  ##
+  # Remove a gem specification named +full_name+.
+
+  def remove_spec(full_name)
+    @gems.delete full_name
+  end
+
+  ##
+  # Iterate over the specifications in the source index.
+
+  def each(&block) # :yields: gem.full_name, gem
+    @gems.each(&block)
+  end
+
+  ##
+  # The gem specification given a full gem spec name.
+
+  def specification(full_name)
+    @gems[full_name]
+  end
+
+  ##
+  # The signature for the source index.  Changes in the signature indicate a
+  # change in the index.
+
+  def index_signature
+    require 'digest'
+
+    Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
+  end
+
+  ##
+  # The signature for the given gem specification.
+
+  def gem_signature(gem_full_name)
+    require 'digest'
+
+    Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
+  end
+
+  def size
+    @gems.size
+  end
+  alias length size
+
+  ##
+  # Find a gem by an exact match on the short name.
+
+  def find_name(gem_name, version_requirement = Gem::Requirement.default)
+    dep = Gem::Dependency.new gem_name, version_requirement
+    search dep
+  end
+
+  ##
+  # Search for a gem by Gem::Dependency +gem_pattern+.  If +only_platform+
+  # is true, only gems matching Gem::Platform.local will be returned.  An
+  # Array of matching Gem::Specification objects is returned.
+  #
+  # For backwards compatibility, a String or Regexp pattern may be passed as
+  # +gem_pattern+, and a Gem::Requirement for +platform_only+.  This
+  # behavior is deprecated and will be removed.
+
+  def search(gem_pattern, platform_only = false)
+    version_requirement = nil
+    only_platform = false
+
+    # TODO - Remove support and warning for legacy arguments after 2008/11
+    unless Gem::Dependency === gem_pattern
+      warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name"
+    end
+
+    case gem_pattern
+    when Regexp then
+      version_requirement = platform_only || Gem::Requirement.default
+    when Gem::Dependency then
+      only_platform = platform_only
+      version_requirement = gem_pattern.version_requirements
+      gem_pattern = if Regexp === gem_pattern.name then
+                      gem_pattern.name
+                    elsif gem_pattern.name.empty? then
+                      //
+                    else
+                      /^#{Regexp.escape gem_pattern.name}$/
+                    end
+    else
+      version_requirement = platform_only || Gem::Requirement.default
+      gem_pattern = /#{gem_pattern}/i
+    end
+
+    unless Gem::Requirement === version_requirement then
+      version_requirement = Gem::Requirement.create version_requirement
+    end
+
+    specs = all_gems.values.select do |spec|
+      spec.name =~ gem_pattern and
+        version_requirement.satisfied_by? spec.version
+    end
+
+    if only_platform then
+      specs = specs.select do |spec|
+        Gem::Platform.match spec.platform
+      end
+    end
+
+    specs.sort_by { |s| s.sort_obj }
+  end
+
+  ##
+  # Replaces the gems in the source index from specifications in the
+  # directories this source index was created from.  Raises an exception if
+  # this source index wasn't created from a directory (via from_gems_in or
+  # from_installed_gems, or having spec_dirs set).
+
+  def refresh!
+    raise 'source index not created from disk' if @spec_dirs.nil?
+    load_gems_in(*@spec_dirs)
+  end
+
+  ##
+  # Returns an Array of Gem::Specifications that are not up to date.
+
+  def outdated
+    outdateds = []
+
+    latest_specs.each do |local|
+      dependency = Gem::Dependency.new local.name, ">= #{local.version}"
+
+      begin
+        fetcher = Gem::SpecFetcher.fetcher
+        remotes = fetcher.find_matching dependency
+        remotes = remotes.map { |(name, version,_),_| version }
+      rescue Gem::RemoteFetcher::FetchError => e
+        raise unless fetcher.warn_legacy e do
+          require 'rubygems/source_info_cache'
+
+          specs = Gem::SourceInfoCache.search_with_source dependency, true
+
+          remotes = specs.map { |spec,| spec.version }
+        end
+      end
+
+      latest = remotes.sort.last
+
+      outdateds << local.name if latest and local.version < latest
+    end
+
+    outdateds
+  end
+
+  ##
+  # Updates this SourceIndex from +source_uri+.  If +all+ is false, only the
+  # latest gems are fetched.
+
+  def update(source_uri, all)
+    source_uri = URI.parse source_uri unless URI::Generic === source_uri
+    source_uri.path += '/' unless source_uri.path =~ /\/$/
+
+    use_incremental = false
+
+    begin
+      gem_names = fetch_quick_index source_uri, all
+      remove_extra gem_names
+      missing_gems = find_missing gem_names
+
+      return false if missing_gems.size.zero?
+
+      say "Missing metadata for #{missing_gems.size} gems" if
+      missing_gems.size > 0 and Gem.configuration.really_verbose
+
+      use_incremental = missing_gems.size <= Gem.configuration.bulk_threshold
+    rescue Gem::OperationNotSupportedError => ex
+      alert_error "Falling back to bulk fetch: #{ex.message}" if
+      Gem.configuration.really_verbose
+      use_incremental = false
+    end
+
+    if use_incremental then
+      update_with_missing(source_uri, missing_gems)
+    else
+      new_index = fetch_bulk_index(source_uri)
+      @gems.replace(new_index.gems)
+    end
+
+    true
+  end
+
+  def ==(other) # :nodoc:
+    self.class === other and @gems == other.gems 
+  end
+
+  def dump
+    Marshal.dump(self)
+  end
+
+  private
+
+  def fetcher
+    require 'rubygems/remote_fetcher'
+
+    Gem::RemoteFetcher.fetcher
+  end
+
+  def fetch_index_from(source_uri)
+    @fetch_error = nil
+
+    indexes = %W[
+        Marshal.#{Gem.marshal_version}.Z
+        Marshal.#{Gem.marshal_version}
+        yaml.Z
+        yaml
+      ]
+
+    indexes.each do |name|
+      spec_data = nil
+      index = source_uri + name
+      begin
+        spec_data = fetcher.fetch_path index
+        spec_data = unzip(spec_data) if name =~ /\.Z$/
+
+        if name =~ /Marshal/ then
+          return Marshal.load(spec_data)
+        else
+          return YAML.load(spec_data)
+        end
+      rescue => e
+        if Gem.configuration.really_verbose then
+          alert_error "Unable to fetch #{name}: #{e.message}"
+        end
+
+        @fetch_error = e
+      end
+    end
+
+    nil
+  end
+
+  def fetch_bulk_index(source_uri)
+    say "Bulk updating Gem source index for: #{source_uri}" if
+      Gem.configuration.verbose
+
+    index = fetch_index_from(source_uri)
+    if index.nil? then
+      raise Gem::RemoteSourceException,
+              "Error fetching remote gem cache: #{@fetch_error}"
+    end
+    @fetch_error = nil
+    index
+  end
+
+  ##
+  # Get the quick index needed for incremental updates.
+
+  def fetch_quick_index(source_uri, all)
+    index = all ? 'index' : 'latest_index'
+
+    zipped_index = fetcher.fetch_path source_uri + "quick/#{index}.rz"
+
+    unzip(zipped_index).split("\n")
+  rescue ::Exception => e
+    unless all then
+      say "Latest index not found, using quick index" if
+        Gem.configuration.really_verbose
+
+      fetch_quick_index source_uri, true
+    else
+      raise Gem::OperationNotSupportedError,
+            "No quick index found: #{e.message}"
+    end
+  end
+
+  ##
+  # Make a list of full names for all the missing gemspecs.
+
+  def find_missing(spec_names)
+    unless defined? @originals then
+      @originals = {}
+      each do |full_name, spec|
+        @originals[spec.original_name] = spec
+      end
+    end
+
+    spec_names.find_all { |full_name|
+      @originals[full_name].nil?
+    }
+  end
+
+  def remove_extra(spec_names)
+    dictionary = spec_names.inject({}) { |h, k| h[k] = true; h }
+    each do |name, spec|
+      remove_spec name unless dictionary.include? spec.original_name
+    end
+  end
+
+  ##
+  # Unzip the given string.
+
+  def unzip(string)
+    require 'zlib'
+    Gem.inflate string
+  end
+
+  ##
+  # Tries to fetch Marshal representation first, then YAML
+
+  def fetch_single_spec(source_uri, spec_name)
+    @fetch_error = nil
+
+    begin
+      marshal_uri = source_uri + "quick/Marshal.#{Gem.marshal_version}/#{spec_name}.gemspec.rz"
+      zipped = fetcher.fetch_path marshal_uri
+      return Marshal.load(unzip(zipped))
+    rescue => ex
+      @fetch_error = ex
+
+      if Gem.configuration.really_verbose then
+        say "unable to fetch marshal gemspec #{marshal_uri}: #{ex.class} - #{ex}"
+      end
+    end
+
+    begin
+      yaml_uri = source_uri + "quick/#{spec_name}.gemspec.rz"
+      zipped = fetcher.fetch_path yaml_uri
+      return YAML.load(unzip(zipped))
+    rescue => ex
+      @fetch_error = ex
+      if Gem.configuration.really_verbose then
+        say "unable to fetch YAML gemspec #{yaml_uri}: #{ex.class} - #{ex}"
+      end
+    end
+
+    nil
+  end
+
+  ##
+  # Update the cached source index with the missing names.
+
+  def update_with_missing(source_uri, missing_names)
+    progress = ui.progress_reporter(missing_names.size,
+        "Updating metadata for #{missing_names.size} gems from #{source_uri}")
+    missing_names.each do |spec_name|
+      gemspec = fetch_single_spec(source_uri, spec_name)
+      if gemspec.nil? then
+        ui.say "Failed to download spec #{spec_name} from #{source_uri}:\n" \
+                 "\t#{@fetch_error.message}"
+      else
+        add_spec gemspec
+        progress.updated spec_name
+      end
+      @fetch_error = nil
+    end
+    progress.done
+    progress.count
+  end
+
+end
+
+# :stopdoc:
+module Gem
+
+  ##
+  # Cache is an alias for SourceIndex to allow older YAMLized source index
+  # objects to load properly.
+
+  Cache = SourceIndex
+
+end
+# :startdoc:
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,393 @@
+require 'fileutils'
+
+require 'rubygems'
+require 'rubygems/source_info_cache_entry'
+require 'rubygems/user_interaction'
+
+##
+# SourceInfoCache stores a copy of the gem index for each gem source.
+#
+# There are two possible cache locations, the system cache and the user cache:
+# * The system cache is preferred if it is writable or can be created.
+# * The user cache is used otherwise
+#
+# Once a cache is selected, it will be used for all operations.
+# SourceInfoCache will not switch between cache files dynamically.
+#
+# Cache data is a Hash mapping a source URI to a SourceInfoCacheEntry.
+#
+#--
+# To keep things straight, this is how the cache objects all fit together:
+#
+#   Gem::SourceInfoCache
+#     @cache_data = {
+#       source_uri => Gem::SourceInfoCacheEntry
+#         @size = source index size
+#         @source_index = Gem::SourceIndex
+#       ...
+#     }
+
+class Gem::SourceInfoCache
+
+  include Gem::UserInteraction
+
+  ##
+  # The singleton Gem::SourceInfoCache.  If +all+ is true, a full refresh will
+  # be performed if the singleton instance is being initialized.
+
+  def self.cache(all = false)
+    return @cache if @cache
+    @cache = new
+    @cache.refresh all if Gem.configuration.update_sources
+    @cache
+  end
+
+  def self.cache_data
+    cache.cache_data
+  end
+
+  ##
+  # The name of the system cache file.
+
+  def self.latest_system_cache_file
+    File.join File.dirname(system_cache_file),
+              "latest_#{File.basename system_cache_file}"
+  end
+
+  ##
+  # The name of the latest user cache file.
+
+  def self.latest_user_cache_file
+    File.join File.dirname(user_cache_file),
+              "latest_#{File.basename user_cache_file}"
+  end
+
+  ##
+  # Reset all singletons, discarding any changes.
+
+  def self.reset
+    @cache = nil
+    @system_cache_file = nil
+    @user_cache_file = nil
+  end
+
+  ##
+  # Search all source indexes.  See Gem::SourceInfoCache#search.
+
+  def self.search(*args)
+    cache.search(*args)
+  end
+
+  ##
+  # Search all source indexes returning the source_uri.  See
+  # Gem::SourceInfoCache#search_with_source.
+
+  def self.search_with_source(*args)
+    cache.search_with_source(*args)
+  end
+
+  ##
+  # The name of the system cache file. (class method)
+
+  def self.system_cache_file
+    @system_cache_file ||= Gem.default_system_source_cache_dir
+  end
+
+  ##
+  # The name of the user cache file.
+
+  def self.user_cache_file
+    @user_cache_file ||=
+      ENV['GEMCACHE'] || Gem.default_user_source_cache_dir
+  end
+
+  def initialize # :nodoc:
+    @cache_data = nil
+    @cache_file = nil
+    @dirty = false
+    @only_latest = true
+  end
+
+  ##
+  # The most recent cache data.
+
+  def cache_data
+    return @cache_data if @cache_data
+    cache_file # HACK writable check
+
+    @only_latest = true
+
+    @cache_data = read_cache_data latest_cache_file
+
+    @cache_data
+  end
+
+  ##
+  # The name of the cache file.
+
+  def cache_file
+    return @cache_file if @cache_file
+    @cache_file = (try_file(system_cache_file) or
+      try_file(user_cache_file) or
+      raise "unable to locate a writable cache file")
+  end
+
+  ##
+  # Write the cache to a local file (if it is dirty).
+
+  def flush
+    write_cache if @dirty
+    @dirty = false
+  end
+
+  def latest_cache_data
+    latest_cache_data = {}
+
+    cache_data.each do |repo, sice|
+      latest = sice.source_index.latest_specs
+
+      new_si = Gem::SourceIndex.new
+      new_si.add_specs(*latest)
+
+      latest_sice = Gem::SourceInfoCacheEntry.new new_si, sice.size
+      latest_cache_data[repo] = latest_sice
+    end
+
+    latest_cache_data
+  end
+
+  ##
+  # The name of the latest cache file.
+
+  def latest_cache_file
+    File.join File.dirname(cache_file), "latest_#{File.basename cache_file}"
+  end
+
+  ##
+  # The name of the latest system cache file.
+
+  def latest_system_cache_file
+    self.class.latest_system_cache_file
+  end
+
+  ##
+  # The name of the latest user cache file.
+
+  def latest_user_cache_file
+    self.class.latest_user_cache_file
+  end
+
+  ##
+  # Merges the complete cache file into this Gem::SourceInfoCache.
+
+  def read_all_cache_data
+    if @only_latest then
+      @only_latest = false
+      all_data = read_cache_data cache_file
+
+      cache_data.update all_data do |source_uri, latest_sice, all_sice|
+        all_sice.source_index.gems.update latest_sice.source_index.gems
+
+        Gem::SourceInfoCacheEntry.new all_sice.source_index, latest_sice.size
+      end
+
+      begin
+        refresh true
+      rescue Gem::RemoteFetcher::FetchError
+      end
+    end
+  end
+
+  ##
+  # Reads cached data from +file+.
+
+  def read_cache_data(file)
+    # Marshal loads 30-40% faster from a String, and 2MB on 20061116 is small
+    data = open file, 'rb' do |fp| fp.read end
+    cache_data = Marshal.load data
+
+    cache_data.each do |url, sice|
+      next unless sice.is_a?(Hash)
+      update
+
+      cache = sice['cache']
+      size  = sice['size']
+
+      if cache.is_a?(Gem::SourceIndex) and size.is_a?(Numeric) then
+        new_sice = Gem::SourceInfoCacheEntry.new cache, size
+        cache_data[url] = new_sice
+      else # irreperable, force refetch.
+        reset_cache_for url, cache_data
+      end
+    end
+
+    cache_data
+  rescue Errno::ENOENT
+    {}
+  rescue => e
+    if Gem.configuration.really_verbose then
+      say "Exception during cache_data handling: #{e.class} - #{e}"
+      say "Cache file was: #{file}"
+      say "\t#{e.backtrace.join "\n\t"}"
+    end
+
+    {}
+  end
+
+  ##
+  # Refreshes each source in the cache from its repository.  If +all+ is
+  # false, only latest gems are updated.
+
+  def refresh(all)
+    Gem.sources.each do |source_uri|
+      cache_entry = cache_data[source_uri]
+      if cache_entry.nil? then
+        cache_entry = Gem::SourceInfoCacheEntry.new nil, 0
+        cache_data[source_uri] = cache_entry
+      end
+
+      update if cache_entry.refresh source_uri, all
+    end
+
+    flush
+  end
+
+  def reset_cache_for(url, cache_data)
+    say "Reseting cache for #{url}" if Gem.configuration.really_verbose
+
+    sice = Gem::SourceInfoCacheEntry.new Gem::SourceIndex.new, 0
+    sice.refresh url, false # HACK may be unnecessary, see ::cache and #refresh
+
+    cache_data[url] = sice
+    cache_data
+  end
+
+  def reset_cache_data
+    @cache_data = nil
+    @only_latest = true
+  end
+
+  ##
+  # Force cache file to be reset, useful for integration testing of rubygems
+
+  def reset_cache_file
+    @cache_file = nil
+  end
+
+  ##
+  # Searches all source indexes.  See Gem::SourceIndex#search for details on
+  # +pattern+ and +platform_only+.  If +all+ is set to true, the full index
+  # will be loaded before searching.
+
+  def search(pattern, platform_only = false, all = false)
+    read_all_cache_data if all
+
+    cache_data.map do |source_uri, sic_entry|
+      next unless Gem.sources.include? source_uri
+      # TODO - Remove this gunk after 2008/11
+      unless pattern.kind_of?(Gem::Dependency)
+        pattern = Gem::Dependency.new(pattern, Gem::Requirement.default) 
+      end
+      sic_entry.source_index.search pattern, platform_only
+    end.flatten.compact
+  end
+
+  # Searches all source indexes for +pattern+.  If +only_platform+ is true,
+  # only gems matching Gem.platforms will be selected.  Returns an Array of
+  # pairs containing the Gem::Specification found and the source_uri it was
+  # found at.
+  def search_with_source(pattern, only_platform = false, all = false)
+    read_all_cache_data if all
+
+    results = []
+
+    cache_data.map do |source_uri, sic_entry|
+      next unless Gem.sources.include? source_uri
+
+      # TODO - Remove this gunk after 2008/11
+      unless pattern.kind_of?(Gem::Dependency)
+        pattern = Gem::Dependency.new(pattern, Gem::Requirement.default) 
+      end
+
+      sic_entry.source_index.search(pattern, only_platform).each do |spec|
+        results << [spec, source_uri]
+      end
+    end
+
+    results
+  end
+
+  ##
+  # Set the source info cache data directly.  This is mainly used for unit
+  # testing when we don't want to read a file system to grab the cached source
+  # index information.  The +hash+ should map a source URL into a
+  # SourceInfoCacheEntry.
+
+  def set_cache_data(hash)
+    @cache_data = hash
+    update
+  end
+
+  ##
+  # The name of the system cache file.
+
+  def system_cache_file
+    self.class.system_cache_file
+  end
+
+  ##
+  # Determine if +path+ is a candidate for a cache file.  Returns +path+ if
+  # it is, nil if not.
+
+  def try_file(path)
+    return path if File.writable? path
+    return nil if File.exist? path
+
+    dir = File.dirname path
+
+    unless File.exist? dir then
+      begin
+        FileUtils.mkdir_p dir
+      rescue RuntimeError, SystemCallError
+        return nil
+      end
+    end
+
+    return path if File.writable? dir
+
+    nil
+  end
+
+  ##
+  # Mark the cache as updated (i.e. dirty).
+
+  def update
+    @dirty = true
+  end
+
+  ##
+  # The name of the user cache file.
+
+  def user_cache_file
+    self.class.user_cache_file
+  end
+
+  ##
+  # Write data to the proper cache files.
+
+  def write_cache
+    if not File.exist?(cache_file) or not @only_latest then
+      open cache_file, 'wb' do |io|
+        io.write Marshal.dump(cache_data)
+      end
+    end
+
+    open latest_cache_file, 'wb' do |io|
+      io.write Marshal.dump(latest_cache_data)
+    end
+  end
+
+  reset
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache_entry.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache_entry.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/source_info_cache_entry.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,56 @@
+require 'rubygems'
+require 'rubygems/source_index'
+require 'rubygems/remote_fetcher'
+
+##
+# Entries held by a SourceInfoCache.
+
+class Gem::SourceInfoCacheEntry
+
+  ##
+  # The source index for this cache entry.
+
+  attr_reader :source_index
+
+  ##
+  # The size of the source entry.  Used to determine if the source index has
+  # changed.
+
+  attr_reader :size
+
+  ##
+  # Create a cache entry.
+
+  def initialize(si, size)
+    @source_index = si || Gem::SourceIndex.new({})
+    @size = size
+    @all = false
+  end
+
+  def refresh(source_uri, all)
+    begin
+      marshal_uri = URI.join source_uri.to_s, "Marshal.#{Gem.marshal_version}"
+      remote_size = Gem::RemoteFetcher.fetcher.fetch_size marshal_uri
+    rescue Gem::RemoteSourceException
+      yaml_uri = URI.join source_uri.to_s, 'yaml'
+      remote_size = Gem::RemoteFetcher.fetcher.fetch_size yaml_uri
+    end
+
+    # TODO Use index_signature instead of size?
+    return false if @size == remote_size and @all
+
+    updated = @source_index.update source_uri, all
+    @size = remote_size
+    @all = all
+
+    updated
+  end
+
+  def ==(other) # :nodoc:
+    self.class === other and
+    @size == other.size and
+    @source_index == other.source_index
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/spec_fetcher.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/spec_fetcher.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/spec_fetcher.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,278 @@
+require 'zlib'
+require 'fileutils'
+
+require 'rubygems/remote_fetcher'
+require 'rubygems/user_interaction'
+
+##
+# SpecFetcher handles metadata updates from remote gem repositories.
+
+class Gem::SpecFetcher
+
+  include Gem::UserInteraction
+
+  ##
+  # The SpecFetcher cache dir.
+
+  attr_reader :dir # :nodoc:
+
+  ##
+  # Cache of latest specs
+
+  attr_reader :latest_specs # :nodoc:
+
+  ##
+  # Cache of all released specs
+
+  attr_reader :specs # :nodoc:
+
+  ##
+  # Cache of prerelease specs
+
+  attr_reader :prerelease_specs # :nodoc:
+
+  @fetcher = nil
+
+  def self.fetcher
+    @fetcher ||= new
+  end
+
+  def self.fetcher=(fetcher) # :nodoc:
+    @fetcher = fetcher
+  end
+
+  def initialize
+    @dir = File.join Gem.user_home, '.gem', 'specs'
+    @update_cache = File.stat(Gem.user_home).uid == Process.uid
+
+    @specs = {}
+    @latest_specs = {}
+    @prerelease_specs = {}
+
+    @fetcher = Gem::RemoteFetcher.fetcher
+  end
+
+  ##
+  # Retuns the local directory to write +uri+ to.
+
+  def cache_dir(uri)
+    File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(uri.path)
+  end
+
+  ##
+  # Fetch specs matching +dependency+.  If +all+ is true, all matching
+  # (released) versions are returned.  If +matching_platform+ is
+  # false, all platforms are returned. If +prerelease+ is true,
+  # prerelease versions are included.
+
+  def fetch(dependency, all = false, matching_platform = true, prerelease = false)
+    specs_and_sources = find_matching dependency, all, matching_platform, prerelease
+
+    specs_and_sources.map do |spec_tuple, source_uri|
+      [fetch_spec(spec_tuple, URI.parse(source_uri)), source_uri]
+    end
+
+  rescue Gem::RemoteFetcher::FetchError => e
+    raise unless warn_legacy e do
+      require 'rubygems/source_info_cache'
+
+      return Gem::SourceInfoCache.search_with_source(dependency,
+                                                     matching_platform, all)
+    end
+  end
+
+  def fetch_spec(spec, source_uri)
+    spec = spec - [nil, 'ruby', '']
+    spec_file_name = "#{spec.join '-'}.gemspec"
+
+    uri = source_uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"
+
+    cache_dir = cache_dir uri
+
+    local_spec = File.join cache_dir, spec_file_name
+
+    if File.exist? local_spec then
+      spec = Gem.read_binary local_spec
+    else
+      uri.path << '.rz'
+
+      spec = @fetcher.fetch_path uri
+      spec = Gem.inflate spec
+
+      if @update_cache then
+        FileUtils.mkdir_p cache_dir
+
+        open local_spec, 'wb' do |io|
+          io.write spec
+        end
+      end
+    end
+
+    # TODO: Investigate setting Gem::Specification#loaded_from to a URI
+    Marshal.load spec
+  end
+
+  ##
+  # Find spec names that match +dependency+.  If +all+ is true, all
+  # matching released versions are returned.  If +matching_platform+
+  # is false, gems for all platforms are returned.
+
+  def find_matching(dependency, all = false, matching_platform = true, prerelease = false)
+    found = {}
+
+    list(all, prerelease).each do |source_uri, specs|
+      found[source_uri] = specs.select do |spec_name, version, spec_platform|
+        dependency =~ Gem::Dependency.new(spec_name, version) and
+          (not matching_platform or Gem::Platform.match(spec_platform))
+      end
+    end
+
+    specs_and_sources = []
+
+    found.each do |source_uri, specs|
+      uri_str = source_uri.to_s
+      specs_and_sources.push(*specs.map { |spec| [spec, uri_str] })
+    end
+
+    specs_and_sources
+  end
+
+  ##
+  # Returns Array of gem repositories that were generated with RubyGems less
+  # than 1.2.
+
+  def legacy_repos
+    Gem.sources.reject do |source_uri|
+      source_uri = URI.parse source_uri
+      spec_path = source_uri + "specs.#{Gem.marshal_version}.gz"
+
+      begin
+        @fetcher.fetch_size spec_path
+      rescue Gem::RemoteFetcher::FetchError
+        begin
+          @fetcher.fetch_size(source_uri + 'yaml') # re-raise if non-repo
+        rescue Gem::RemoteFetcher::FetchError
+          alert_error "#{source_uri} does not appear to be a repository"
+          raise
+        end
+        false
+      end
+    end
+  end
+
+  ##
+  # Returns a list of gems available for each source in Gem::sources.  If
+  # +all+ is true, all released versions are returned instead of only latest
+  # versions. If +prerelease+ is true, include prerelease versions.
+
+  def list(all = false, prerelease = false)
+    # TODO: make type the only argument
+    type = if all
+             :all
+           elsif prerelease
+             :prerelease
+           else
+             :latest
+           end
+
+    list = {}
+
+    file = { :latest => 'latest_specs',
+      :prerelease => 'prerelease_specs',
+      :all => 'specs' }[type]
+
+    cache = { :latest => @latest_specs,
+      :prerelease => @prerelease_specs,
+      :all => @specs }[type]
+    
+    Gem.sources.each do |source_uri|
+      source_uri = URI.parse source_uri
+
+      unless cache.include? source_uri
+        cache[source_uri] = load_specs source_uri, file
+      end
+
+      list[source_uri] = cache[source_uri]
+    end
+
+    if type == :all
+      list.values.map do |gems|
+        gems.reject! { |g| g[1].prerelease? }
+      end
+    end
+
+    list
+  end
+
+  ##
+  # Loads specs in +file+, fetching from +source_uri+ if the on-disk cache is
+  # out of date.
+
+  def load_specs(source_uri, file)
+    file_name  = "#{file}.#{Gem.marshal_version}"
+    spec_path  = source_uri + "#{file_name}.gz"
+    cache_dir  = cache_dir spec_path
+    local_file = File.join(cache_dir, file_name)
+    loaded     = false
+
+    if File.exist? local_file then
+      spec_dump = @fetcher.fetch_path spec_path, File.mtime(local_file)
+
+      if spec_dump.nil? then
+        spec_dump = Gem.read_binary local_file
+      else
+        loaded = true
+      end
+    else
+      spec_dump = @fetcher.fetch_path spec_path
+      loaded = true
+    end
+
+    specs = begin
+              Marshal.load spec_dump
+            rescue ArgumentError
+              spec_dump = @fetcher.fetch_path spec_path
+              loaded = true
+
+              Marshal.load spec_dump
+            end
+
+    if loaded and @update_cache then
+      begin
+        FileUtils.mkdir_p cache_dir
+
+        open local_file, 'wb' do |io|
+          Marshal.dump specs, io
+        end
+      rescue
+      end
+    end
+
+    specs
+  end
+
+  ##
+  # Warn about legacy repositories if +exception+ indicates only legacy
+  # repositories are available, and yield to the block.  Returns false if the
+  # exception indicates some other FetchError.
+
+  def warn_legacy(exception)
+    uri = exception.uri.to_s
+    if uri =~ /specs\.#{Regexp.escape Gem.marshal_version}\.gz$/ then
+      alert_warning <<-EOF
+RubyGems 1.2+ index not found for:
+\t#{legacy_repos.join "\n\t"}
+
+RubyGems will revert to legacy indexes degrading performance.
+      EOF
+
+      yield
+
+      return true
+    end
+
+    false
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/specification.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/specification.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/specification.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,1455 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/version'
+require 'rubygems/requirement'
+require 'rubygems/platform'
+
+# :stopdoc:
+class Date; end # for ruby_code if date.rb wasn't required
+# :startdoc:
+
+##
+# The Specification class contains the metadata for a Gem.  Typically
+# defined in a .gemspec file or a Rakefile, and looks like this:
+#
+#   spec = Gem::Specification.new do |s|
+#     s.name = 'example'
+#     s.version = '1.0'
+#     s.summary = 'Example gem specification'
+#     ...
+#   end
+#
+# For a great way to package gems, use Hoe.
+
+class Gem::Specification
+
+  ##
+  # Allows deinstallation of gems with legacy platforms.
+
+  attr_accessor :original_platform # :nodoc:
+
+  ##
+  # The the version number of a specification that does not specify one
+  # (i.e. RubyGems 0.7 or earlier).
+
+  NONEXISTENT_SPECIFICATION_VERSION = -1
+
+  ##
+  # The specification version applied to any new Specification instances
+  # created.  This should be bumped whenever something in the spec format
+  # changes.
+  #--
+  # When updating this number, be sure to also update #to_ruby.
+  #
+  # NOTE RubyGems < 1.2 cannot load specification versions > 2.
+
+  CURRENT_SPECIFICATION_VERSION = 3
+
+  ##
+  # An informal list of changes to the specification.  The highest-valued
+  # key should be equal to the CURRENT_SPECIFICATION_VERSION.
+
+  SPECIFICATION_VERSION_HISTORY = {
+    -1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'],
+    1  => [
+      'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"',
+      '"test_file=x" is a shortcut for "test_files=[x]"'
+    ],
+    2  => [
+      'Added "required_rubygems_version"',
+      'Now forward-compatible with future versions',
+    ],
+    3 => [
+       'Added Fixnum validation to the specification_version'
+    ]
+  }
+
+  # :stopdoc:
+  MARSHAL_FIELDS = { -1 => 16, 1 => 16, 2 => 16, 3 => 17 }
+
+  now = Time.at(Time.now.to_i)
+  TODAY = now - ((now.to_i + now.gmt_offset) % 86400)
+  # :startdoc:
+
+  ##
+  # Optional block used to gather newly defined instances.
+
+  @@gather = nil
+
+  ##
+  # List of attribute names: [:name, :version, ...]
+
+  @@required_attributes = []
+
+  ##
+  # List of _all_ attributes and default values:
+  #
+  #   [[:name, nil],
+  #    [:bindir, 'bin'],
+  #    ...]
+
+  @@attributes = []
+
+  @@nil_attributes = []
+  @@non_nil_attributes = [:@original_platform]
+
+  ##
+  # List of array attributes
+
+  @@array_attributes = []
+
+  ##
+  # Map of attribute names to default values.
+
+  @@default_value = {}
+
+  ##
+  # Names of all specification attributes
+
+  def self.attribute_names
+    @@attributes.map { |name, default| name }
+  end
+
+  ##
+  # Default values for specification attributes
+
+  def self.attribute_defaults
+    @@attributes.dup
+  end
+
+  ##
+  # The default value for specification attribute +name+
+
+  def self.default_value(name)
+    @@default_value[name]
+  end
+
+  ##
+  # Required specification attributes
+
+  def self.required_attributes
+    @@required_attributes.dup
+  end
+
+  ##
+  # Is +name+ a required attribute?
+
+  def self.required_attribute?(name)
+    @@required_attributes.include? name.to_sym
+  end
+
+  ##
+  # Specification attributes that are arrays (appendable and so-forth)
+
+  def self.array_attributes
+    @@array_attributes.dup
+  end
+
+  ##
+  # Specifies the +name+ and +default+ for a specification attribute, and
+  # creates a reader and writer method like Module#attr_accessor.
+  #
+  # The reader method returns the default if the value hasn't been set.
+
+  def self.attribute(name, default=nil)
+    ivar_name = "@#{name}".intern
+    if default.nil? then
+      @@nil_attributes << ivar_name
+    else
+      @@non_nil_attributes << [ivar_name, default]
+    end
+
+    @@attributes << [name, default]
+    @@default_value[name] = default
+    attr_accessor(name)
+  end
+
+  ##
+  # Same as :attribute, but ensures that values assigned to the attribute
+  # are array values by applying :to_a to the value.
+
+  def self.array_attribute(name)
+    @@non_nil_attributes << ["@#{name}".intern, []]
+
+    @@array_attributes << name
+    @@attributes << [name, []]
+    @@default_value[name] = []
+    code = %{
+      def #{name}
+        @#{name} ||= []
+      end
+      def #{name}=(value)
+        @#{name} = Array(value)
+      end
+    }
+
+    module_eval code, __FILE__, __LINE__ - 9
+  end
+
+  ##
+  # Same as attribute above, but also records this attribute as mandatory.
+
+  def self.required_attribute(*args)
+    @@required_attributes << args.first
+    attribute(*args)
+  end
+
+  ##
+  # Sometimes we don't want the world to use a setter method for a
+  # particular attribute.
+  #
+  # +read_only+ makes it private so we can still use it internally.
+
+  def self.read_only(*names)
+    names.each do |name|
+      private "#{name}="
+    end
+  end
+
+  # Shortcut for creating several attributes at once (each with a default
+  # value of +nil+).
+
+  def self.attributes(*args)
+    args.each do |arg|
+      attribute(arg, nil)
+    end
+  end
+
+  ##
+  # Some attributes require special behaviour when they are accessed.  This
+  # allows for that.
+
+  def self.overwrite_accessor(name, &block)
+    remove_method name
+    define_method(name, &block)
+  end
+
+  ##
+  # Defines a _singular_ version of an existing _plural_ attribute (i.e. one
+  # whose value is expected to be an array).  This means just creating a
+  # helper method that takes a single value and appends it to the array.
+  # These are created for convenience, so that in a spec, one can write
+  #
+  #   s.require_path = 'mylib'
+  #
+  # instead of:
+  #
+  #   s.require_paths = ['mylib']
+  #
+  # That above convenience is available courtesy of:
+  #
+  #   attribute_alias_singular :require_path, :require_paths
+
+  def self.attribute_alias_singular(singular, plural)
+    define_method("#{singular}=") { |val|
+      send("#{plural}=", [val])
+    }
+    define_method("#{singular}") {
+      val = send("#{plural}")
+      val.nil? ? nil : val.first
+    }
+  end
+
+  ##
+  # Dump only crucial instance variables.
+  #--
+  # MAINTAIN ORDER!
+
+  def _dump(limit)
+    Marshal.dump [
+      @rubygems_version,
+      @specification_version,
+      @name,
+      @version,
+      (Time === @date ? @date : (require 'time'; Time.parse(@date.to_s))),
+      @summary,
+      @required_ruby_version,
+      @required_rubygems_version,
+      @original_platform,
+      @dependencies,
+      @rubyforge_project,
+      @email,
+      @authors,
+      @description,
+      @homepage,
+      @has_rdoc,
+      @new_platform,
+      @licenses
+    ]
+  end
+
+  ##
+  # Load custom marshal format, re-initializing defaults as needed
+
+  def self._load(str)
+    array = Marshal.load str
+
+    spec = Gem::Specification.new
+    spec.instance_variable_set :@specification_version, array[1]
+
+    current_version = CURRENT_SPECIFICATION_VERSION
+
+    field_count = if spec.specification_version > current_version then
+                    spec.instance_variable_set :@specification_version,
+                                               current_version
+                    MARSHAL_FIELDS[current_version]
+                  else
+                    MARSHAL_FIELDS[spec.specification_version]
+                  end
+
+    if array.size < field_count then
+      raise TypeError, "invalid Gem::Specification format #{array.inspect}"
+    end
+
+    spec.instance_variable_set :@rubygems_version,          array[0]
+    # spec version
+    spec.instance_variable_set :@name,                      array[2]
+    spec.instance_variable_set :@version,                   array[3]
+    spec.instance_variable_set :@date,                      array[4]
+    spec.instance_variable_set :@summary,                   array[5]
+    spec.instance_variable_set :@required_ruby_version,     array[6]
+    spec.instance_variable_set :@required_rubygems_version, array[7]
+    spec.instance_variable_set :@original_platform,         array[8]
+    spec.instance_variable_set :@dependencies,              array[9]
+    spec.instance_variable_set :@rubyforge_project,         array[10]
+    spec.instance_variable_set :@email,                     array[11]
+    spec.instance_variable_set :@authors,                   array[12]
+    spec.instance_variable_set :@description,               array[13]
+    spec.instance_variable_set :@homepage,                  array[14]
+    spec.instance_variable_set :@has_rdoc,                  array[15]
+    spec.instance_variable_set :@new_platform,              array[16]
+    spec.instance_variable_set :@platform,                  array[16].to_s
+    spec.instance_variable_set :@license,                   array[17]
+    spec.instance_variable_set :@loaded,                    false
+
+    spec
+  end
+
+  ##
+  # List of depedencies that will automatically be activated at runtime.
+
+  def runtime_dependencies
+    dependencies.select { |d| d.type == :runtime || d.type == nil }
+  end
+
+  ##
+  # List of dependencies that are used for development
+
+  def development_dependencies
+    dependencies.select { |d| d.type == :development }
+  end
+
+  def test_suite_file # :nodoc:
+    warn 'test_suite_file deprecated, use test_files'
+    test_files.first
+  end
+
+  def test_suite_file=(val) # :nodoc:
+    warn 'test_suite_file= deprecated, use test_files='
+    @test_files = [] unless defined? @test_files
+    @test_files << val
+  end
+
+  ##
+  # true when this gemspec has been loaded from a specifications directory.
+  # This attribute is not persisted.
+
+  attr_accessor :loaded
+
+  ##
+  # Path this gemspec was loaded from.  This attribute is not persisted.
+
+  attr_accessor :loaded_from
+
+  ##
+  # Returns an array with bindir attached to each executable in the
+  # executables list
+
+  def add_bindir(executables)
+    return nil if executables.nil?
+
+    if @bindir then
+      Array(executables).map { |e| File.join(@bindir, e) }
+    else
+      executables
+    end
+  rescue
+    return nil
+  end
+
+  ##
+  # Files in the Gem under one of the require_paths
+
+  def lib_files
+    @files.select do |file|
+      require_paths.any? do |path|
+        file.index(path) == 0
+      end
+    end
+  end
+
+  ##
+  # True if this gem was loaded from disk
+
+  alias :loaded? :loaded
+
+  ##
+  # True if this gem has files in test_files
+
+  def has_unit_tests?
+    not test_files.empty?
+  end
+
+  # :stopdoc:
+  alias has_test_suite? has_unit_tests?
+  # :startdoc:
+
+  ##
+  # Specification constructor.  Assigns the default values to the attributes
+  # and yields itself for further initialization.
+
+  def initialize
+    @new_platform = nil
+    assign_defaults
+    @loaded = false
+    @loaded_from = nil
+
+    yield self if block_given?
+
+    @@gather.call(self) if @@gather
+  end
+
+  ##
+  # Duplicates array_attributes from +other_spec+ so state isn't shared.
+
+  def initialize_copy(other_spec)
+    other_ivars = other_spec.instance_variables
+    other_ivars = other_ivars.map { |ivar| ivar.intern } if # for 1.9
+      other_ivars.any? { |ivar| String === ivar }
+
+    self.class.array_attributes.each do |name|
+      name = :"@#{name}"
+      next unless other_ivars.include? name
+      instance_variable_set name, other_spec.instance_variable_get(name).dup
+    end
+  end
+
+  ##
+  # Each attribute has a default value (possibly nil).  Here, we initialize
+  # all attributes to their default value.  This is done through the
+  # accessor methods, so special behaviours will be honored.  Furthermore,
+  # we take a _copy_ of the default so each specification instance has its
+  # own empty arrays, etc.
+
+  def assign_defaults
+    @@nil_attributes.each do |name|
+      instance_variable_set name, nil
+    end
+
+    @@non_nil_attributes.each do |name, default|
+      value = case default
+              when Time, Numeric, Symbol, true, false, nil then default
+              else default.dup
+              end
+
+      instance_variable_set name, value
+    end
+
+    # HACK
+    instance_variable_set :@new_platform, Gem::Platform::RUBY
+  end
+
+  ##
+  # Special loader for YAML files.  When a Specification object is loaded
+  # from a YAML file, it bypasses the normal Ruby object initialization
+  # routine (#initialize).  This method makes up for that and deals with
+  # gems of different ages.
+  #
+  # 'input' can be anything that YAML.load() accepts: String or IO.
+
+  def self.from_yaml(input)
+    input = normalize_yaml_input input
+    spec = YAML.load input
+
+    if spec && spec.class == FalseClass then
+      raise Gem::EndOfYAMLException
+    end
+
+    unless Gem::Specification === spec then
+      raise Gem::Exception, "YAML data doesn't evaluate to gem specification"
+    end
+
+    unless (spec.instance_variables.include? '@specification_version' or
+            spec.instance_variables.include? :@specification_version) and
+           spec.instance_variable_get :@specification_version
+      spec.instance_variable_set :@specification_version,
+                                 NONEXISTENT_SPECIFICATION_VERSION
+    end
+
+    spec
+  end
+
+  ##
+  # Loads ruby format gemspec from +filename+
+
+  def self.load(filename)
+    gemspec = nil
+    raise "NESTED Specification.load calls not allowed!" if @@gather
+    @@gather = proc { |gs| gemspec = gs }
+    data = File.read(filename)
+    eval(data)
+    gemspec
+  ensure
+    @@gather = nil
+  end
+
+  ##
+  # Make sure the YAML specification is properly formatted with dashes
+
+  def self.normalize_yaml_input(input)
+    result = input.respond_to?(:read) ? input.read : input
+    result = "--- " + result unless result =~ /^--- /
+    result
+  end
+
+  ##
+  # Sets the rubygems_version to the current RubyGems version
+
+  def mark_version
+    @rubygems_version = Gem::RubyGemsVersion
+  end
+
+  ##
+  # Ignore unknown attributes while loading
+
+  def method_missing(sym, *a, &b) # :nodoc:
+    if @specification_version > CURRENT_SPECIFICATION_VERSION and
+      sym.to_s =~ /=$/ then
+      warn "ignoring #{sym} loading #{full_name}" if $DEBUG
+    else
+      super
+    end
+  end
+
+  ##
+  # Adds a development dependency named +gem+ with +requirements+ to this
+  # Gem.  For example:
+  #
+  #   spec.add_development_dependency 'jabber4r', '> 0.1', '<= 0.5'
+  #
+  # Development dependencies aren't installed by default and aren't
+  # activated when a gem is required.
+
+  def add_development_dependency(gem, *requirements)
+    add_dependency_with_type(gem, :development, *requirements)
+  end
+
+  ##
+  # Adds a runtime dependency named +gem+ with +requirements+ to this Gem.
+  # For example:
+  #
+  #   spec.add_runtime_dependency 'jabber4r', '> 0.1', '<= 0.5'
+
+  def add_runtime_dependency(gem, *requirements)
+    add_dependency_with_type(gem, :runtime, *requirements)
+  end
+
+  ##
+  # Adds a runtime dependency
+
+  alias add_dependency add_runtime_dependency
+
+  ##
+  # Returns the full name (name-version) of this Gem.  Platform information
+  # is included (name-version-platform) if it is specified and not the
+  # default Ruby platform.
+
+  def full_name
+    if platform == Gem::Platform::RUBY or platform.nil? then
+      "#{@name}-#{@version}"
+    else
+      "#{@name}-#{@version}-#{platform}"
+    end
+  end
+
+  ##
+  # Returns the full name (name-version) of this gemspec using the original
+  # platform.  For use with legacy gems.
+
+  def original_name # :nodoc:
+    if platform == Gem::Platform::RUBY or platform.nil? then
+      "#{@name}-#{@version}"
+    else
+      "#{@name}-#{@version}-#{@original_platform}"
+    end
+  end
+
+  ##
+  # The full path to the gem (install path + full name).
+
+  def full_gem_path
+    path = File.join installation_path, 'gems', full_name
+    return path if File.directory? path
+    File.join installation_path, 'gems', original_name
+  end
+
+  ##
+  # The default (generated) file name of the gem.  See also #spec_name.
+  #
+  #   spec.file_name # => "example-1.0.gem"
+
+  def file_name
+    full_name + '.gem'
+  end
+
+  ##
+  # The directory that this gem was installed into.
+
+  def installation_path
+    unless @loaded_from then
+      raise Gem::Exception, "spec #{full_name} is not from an installed gem"
+    end
+
+    File.expand_path File.dirname(File.dirname(@loaded_from))
+  end
+
+  ##
+  # Checks if this specification meets the requirement of +dependency+.
+
+  def satisfies_requirement?(dependency)
+    return @name == dependency.name &&
+      dependency.version_requirements.satisfied_by?(@version)
+  end
+
+  ##
+  # Returns an object you can use to sort specifications in #sort_by.
+
+  def sort_obj
+    [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
+  end
+
+  ##
+  # The default name of the gemspec.  See also #file_name
+  #
+  #   spec.spec_name # => "example-1.0.gemspec"
+
+  def spec_name
+    full_name + '.gemspec'
+  end
+
+  def <=>(other) # :nodoc:
+    sort_obj <=> other.sort_obj
+  end
+
+  ##
+  # Tests specs for equality (across all attributes).
+
+  def ==(other) # :nodoc:
+    self.class === other && same_attributes?(other)
+  end
+
+  alias eql? == # :nodoc:
+
+  ##
+  # True if this gem has the same attributes as +other+.
+
+  def same_attributes?(other)
+    @@attributes.each do |name, default|
+      return false unless self.send(name) == other.send(name)
+    end
+    true
+  end
+
+  private :same_attributes?
+
+  def hash # :nodoc:
+    @@attributes.inject(0) { |hash_code, (name, default_value)|
+      n = self.send(name).hash
+      hash_code + n
+    }
+  end
+
+  def to_yaml(opts = {}) # :nodoc:
+    mark_version
+
+    attributes = @@attributes.map { |name,| name.to_s }.sort
+    attributes = attributes - %w[name version platform]
+
+    yaml = YAML.quick_emit object_id, opts do |out|
+      out.map taguri, to_yaml_style do |map|
+        map.add 'name', @name
+        map.add 'version', @version
+        platform = case @original_platform
+                   when nil, '' then
+                     'ruby'
+                   when String then
+                     @original_platform
+                   else
+                     @original_platform.to_s
+                   end
+        map.add 'platform', platform
+
+        attributes.each do |name|
+          map.add name, instance_variable_get("@#{name}")
+        end
+      end
+    end
+  end
+
+  def yaml_initialize(tag, vals) # :nodoc:
+    vals.each do |ivar, val|
+      instance_variable_set "@#{ivar}", val
+    end
+
+    @original_platform = @platform # for backwards compatibility
+    self.platform = Gem::Platform.new @platform
+  end
+
+  ##
+  # Returns a Ruby code representation of this specification, such that it
+  # can be eval'ed and reconstruct the same specification later.  Attributes
+  # that still have their default values are omitted.
+
+  def to_ruby
+    mark_version
+    result = []
+    result << "# -*- encoding: utf-8 -*-"
+    result << nil
+    result << "Gem::Specification.new do |s|"
+
+    result << "  s.name = #{ruby_code name}"
+    result << "  s.version = #{ruby_code version}"
+    unless platform.nil? or platform == Gem::Platform::RUBY then
+      result << "  s.platform = #{ruby_code original_platform}"
+    end
+    result << ""
+    result << "  s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version="
+
+    handled = [
+      :dependencies,
+      :name,
+      :platform,
+      :required_rubygems_version,
+      :specification_version,
+      :version,
+    ]
+
+    attributes = @@attributes.sort_by { |attr_name,| attr_name.to_s }
+
+    attributes.each do |attr_name, default|
+      next if handled.include? attr_name
+      current_value = self.send(attr_name)
+      if current_value != default or
+         self.class.required_attribute? attr_name then
+        result << "  s.#{attr_name} = #{ruby_code current_value}"
+      end
+    end
+
+    result << nil
+    result << "  if s.respond_to? :specification_version then"
+    result << "    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION"
+    result << "    s.specification_version = #{specification_version}"
+    result << nil
+
+    result << "    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then"
+
+    unless dependencies.empty? then
+      dependencies.each do |dep|
+        version_reqs_param = dep.requirements_list.inspect
+        dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
+        result << "      s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{version_reqs_param})"
+      end
+    end
+
+    result << "    else"
+
+    unless dependencies.empty? then
+      dependencies.each do |dep|
+        version_reqs_param = dep.requirements_list.inspect
+        result << "      s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
+      end
+    end
+
+    result << '    end'
+
+    result << "  else"
+      dependencies.each do |dep|
+        version_reqs_param = dep.requirements_list.inspect
+        result << "    s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
+      end
+    result << "  end"
+
+    result << "end"
+    result << nil
+
+    result.join "\n"
+  end
+
+  ##
+  # Checks that the specification contains all required fields, and does a
+  # very basic sanity check.
+  #
+  # Raises InvalidSpecificationException if the spec does not pass the
+  # checks..
+
+  def validate
+    extend Gem::UserInteraction
+    normalize
+
+    if rubygems_version != Gem::RubyGemsVersion then
+      raise Gem::InvalidSpecificationException,
+            "expected RubyGems version #{Gem::RubyGemsVersion}, was #{rubygems_version}"
+    end
+
+    @@required_attributes.each do |symbol|
+      unless self.send symbol then
+        raise Gem::InvalidSpecificationException,
+              "missing value for attribute #{symbol}"
+      end
+    end
+
+    unless String === name then
+      raise Gem::InvalidSpecificationException,
+            "invalid value for attribute name: \"#{name.inspect}\""
+    end
+
+    if require_paths.empty? then
+      raise Gem::InvalidSpecificationException,
+            'specification must have at least one require_path'
+    end
+
+    @files.delete_if            do |file| File.directory? file end
+    @test_files.delete_if       do |file| File.directory? file end
+    @executables.delete_if      do |file|
+      File.directory? File.join(bindir, file)
+    end
+    @extra_rdoc_files.delete_if do |file| File.directory? file end
+    @extensions.delete_if       do |file| File.directory? file end
+
+    non_files = files.select do |file|
+      !File.file? file
+    end
+
+    unless non_files.empty? then
+      non_files = non_files.map { |file| file.inspect }
+      raise Gem::InvalidSpecificationException,
+            "[#{non_files.join ", "}] are not files"
+    end
+
+    unless specification_version.is_a?(Fixnum)
+      raise Gem::InvalidSpecificationException,
+            'specification_version must be a Fixnum (did you mean version?)'
+    end
+
+    case platform
+    when Gem::Platform, Gem::Platform::RUBY then # ok
+    else
+      raise Gem::InvalidSpecificationException,
+            "invalid platform #{platform.inspect}, see Gem::Platform"
+    end
+
+    unless Array === authors and
+           authors.all? { |author| String === author } then
+      raise Gem::InvalidSpecificationException,
+            'authors must be Array of Strings'
+    end
+
+    licenses.each { |license|
+      if license.length > 64
+        raise Gem::InvalidSpecificationException,
+          "each license must be 64 characters or less"
+      end
+    }
+
+    # reject FIXME and TODO
+
+    unless authors.grep(/FIXME|TODO/).empty? then
+      raise Gem::InvalidSpecificationException,
+            '"FIXME" or "TODO" is not an author'
+    end
+
+    unless Array(email).grep(/FIXME|TODO/).empty? then
+      raise Gem::InvalidSpecificationException,
+            '"FIXME" or "TODO" is not an email address'
+    end
+
+    if description =~ /FIXME|TODO/ then
+      raise Gem::InvalidSpecificationException,
+            '"FIXME" or "TODO" is not a description'
+    end
+
+    if summary =~ /FIXME|TODO/ then
+      raise Gem::InvalidSpecificationException,
+            '"FIXME" or "TODO" is not a summary'
+    end
+
+    if homepage and not homepage.empty? and
+       homepage !~ /\A[a-z][a-z\d+.-]*:/i then
+      raise Gem::InvalidSpecificationException,
+            "\"#{homepage}\" is not a URI"
+    end
+
+    # Warnings
+
+    %w[author description email homepage rubyforge_project summary].each do |attribute|
+      value = self.send attribute
+      alert_warning "no #{attribute} specified" if value.nil? or value.empty?
+    end
+
+    if summary and not summary.empty? and description == summary then
+      alert_warning 'description and summary are identical'
+    end
+
+    alert_warning "deprecated autorequire specified" if autorequire
+
+    executables.each do |executable|
+      executable_path = File.join bindir, executable
+      shebang = File.read(executable_path, 2) == '#!'
+
+      alert_warning "#{executable_path} is missing #! line" unless shebang
+    end
+
+    true
+  end
+
+  ##
+  # Normalize the list of files so that:
+  # * All file lists have redundancies removed.
+  # * Files referenced in the extra_rdoc_files are included in the package
+  #   file list.
+
+  def normalize
+    if defined?(@extra_rdoc_files) and @extra_rdoc_files then
+      @extra_rdoc_files.uniq!
+      @files ||= []
+      @files.concat(@extra_rdoc_files)
+    end
+    @files.uniq! if @files
+  end
+
+  ##
+  # Return a list of all gems that have a dependency on this gemspec.  The
+  # list is structured with entries that conform to:
+  #
+  #   [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
+
+  def dependent_gems
+    out = []
+    Gem.source_index.each do |name,gem|
+      gem.dependencies.each do |dep|
+        if self.satisfies_requirement?(dep) then
+          sats = []
+          find_all_satisfiers(dep) do |sat|
+            sats << sat
+          end
+          out << [gem, dep, sats]
+        end
+      end
+    end
+    out
+  end
+
+  def to_s # :nodoc:
+    "#<Gem::Specification name=#{@name} version=#{@version}>"
+  end
+
+  def pretty_print(q) # :nodoc:
+    q.group 2, 'Gem::Specification.new do |s|', 'end' do
+      q.breakable
+
+      attributes = @@attributes.sort_by { |attr_name,| attr_name.to_s }
+
+      attributes.each do |attr_name, default|
+        current_value = self.send attr_name
+        if current_value != default or
+           self.class.required_attribute? attr_name then
+
+          q.text "s.#{attr_name} = "
+
+          if attr_name == :date then
+            current_value = current_value.utc
+
+            q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})"
+          else
+            q.pp current_value
+          end
+
+          q.breakable
+        end
+      end
+    end
+  end
+
+  ##
+  # Adds a dependency on gem +dependency+ with type +type+ that requires
+  # +requirements+.  Valid types are currently <tt>:runtime</tt> and
+  # <tt>:development</tt>.
+
+  def add_dependency_with_type(dependency, type, *requirements)
+    requirements = if requirements.empty? then
+                     Gem::Requirement.default
+                   else
+                     requirements.flatten
+                   end
+
+    unless dependency.respond_to?(:name) &&
+      dependency.respond_to?(:version_requirements)
+
+      dependency = Gem::Dependency.new(dependency, requirements, type)
+    end
+
+    dependencies << dependency
+  end
+
+  private :add_dependency_with_type
+
+  ##
+  # Finds all gems that satisfy +dep+
+
+  def find_all_satisfiers(dep)
+    Gem.source_index.each do |_, gem|
+      yield gem if gem.satisfies_requirement? dep
+    end
+  end
+
+  private :find_all_satisfiers
+
+  ##
+  # Return a string containing a Ruby code representation of the given
+  # object.
+
+  def ruby_code(obj)
+    case obj
+    when String            then '%q{' + obj + '}'
+    when Array             then obj.inspect
+    when Gem::Version      then obj.to_s.inspect
+    when Date              then '%q{' + obj.strftime('%Y-%m-%d') + '}'
+    when Time              then '%q{' + obj.strftime('%Y-%m-%d') + '}'
+    when Numeric           then obj.inspect
+    when true, false, nil  then obj.inspect
+    when Gem::Platform     then "Gem::Platform.new(#{obj.to_a.inspect})"
+    when Gem::Requirement  then "Gem::Requirement.new(#{obj.to_s.inspect})"
+    else raise Gem::Exception, "ruby_code case not handled: #{obj.class}"
+    end
+  end
+
+  private :ruby_code
+
+  # :section: Required gemspec attributes
+
+  ##
+  # :attr_accessor: rubygems_version
+  #
+  # The version of RubyGems used to create this gem
+
+  required_attribute :rubygems_version, Gem::RubyGemsVersion
+
+  ##
+  # :attr_accessor: specification_version
+  #
+  # The Gem::Specification version of this gemspec
+
+  required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
+
+  ##
+  # :attr_accessor: name
+  #
+  # This gem's name
+
+  required_attribute :name
+
+  ##
+  # :attr_accessor: version
+  #
+  # This gem's version
+
+  required_attribute :version
+
+  ##
+  # :attr_accessor: date
+  #
+  # The date this gem was created
+
+  required_attribute :date, TODAY
+
+  ##
+  # :attr_accessor: summary
+  #
+  # A short summary of this gem's description.  Displayed in `gem list -d`.
+
+  required_attribute :summary
+
+  ##
+  # :attr_accessor: require_paths
+  #
+  # Paths in the gem to add to $LOAD_PATH when this gem is activated
+
+  required_attribute :require_paths, ['lib']
+
+  # :section: Optional gemspec attributes
+
+  ##
+  # :attr_accessor: email
+  #
+  # A contact email for this gem
+
+  attribute :email
+
+  ##
+  # :attr_accessor: homepage
+  #
+  # The URL of this gem's home page
+
+  attribute :homepage
+
+  ##
+  # :attr_accessor: rubyforge_project
+  #
+  # The rubyforge project this gem lives under.  i.e. RubyGems'
+  # rubyforge_project is "rubygems".
+
+  attribute :rubyforge_project
+
+  ##
+  # :attr_accessor: description
+  #
+  # A long description of this gem
+
+  attribute :description
+
+  ##
+  # :attr_accessor: autorequire
+  #
+  # Autorequire was used by old RubyGems to automatically require a file.
+  # It no longer is supported.
+
+  attribute :autorequire
+
+  ##
+  # :attr_accessor: default_executable
+  #
+  # The default executable for this gem.
+
+  attribute :default_executable
+
+  ##
+  # :attr_accessor: bindir
+  #
+  # The path in the gem for executable scripts
+
+  attribute :bindir, 'bin'
+
+  ##
+  # :attr_accessor: has_rdoc
+  #
+  # Deprecated and ignored, defaults to true.
+  #
+  # Formerly used to indicate this gem was RDoc-capable.
+
+  attribute :has_rdoc, true
+
+  ##
+  # True if this gem supports RDoc
+
+  alias :has_rdoc? :has_rdoc
+
+  ##
+  # :attr_accessor: required_ruby_version
+  #
+  # The ruby of version required by this gem
+
+  attribute :required_ruby_version, Gem::Requirement.default
+
+  ##
+  # :attr_accessor: required_rubygems_version
+  #
+  # The RubyGems version required by this gem
+
+  attribute :required_rubygems_version, Gem::Requirement.default
+
+  ##
+  # :attr_accessor: platform
+  #
+  # The platform this gem runs on.  See Gem::Platform for details.
+
+  attribute :platform, Gem::Platform::RUBY
+
+  ##
+  # :attr_accessor: signing_key
+  #
+  # The key used to sign this gem.  See Gem::Security for details.
+
+  attribute :signing_key, nil
+
+  ##
+  # :attr_accessor: cert_chain
+  #
+  # The certificate chain used to sign this gem.  See Gem::Security for
+  # details.
+
+  attribute :cert_chain, []
+
+  ##
+  # :attr_accessor: post_install_message
+  #
+  # A message that gets displayed after the gem is installed
+
+  attribute :post_install_message, nil
+
+  ##
+  # :attr_accessor: authors
+  #
+  # The list of authors who wrote this gem
+
+  array_attribute :authors
+
+  ##
+  # :attr_accessor: licenses
+  #
+  # The license(s) for the library.  Each license must be a short name, no
+  # more than 64 characters.
+
+  array_attribute :licenses
+
+  ##
+  # :attr_accessor: files
+  #
+  # Files included in this gem.  You cannot append to this accessor, you must
+  # assign to it.
+  #
+  # Only add files you can require to this list, not directories, etc.
+  #
+  # Directories are automatically stripped from this list when building a gem,
+  # other non-files cause an error.
+
+  array_attribute :files
+
+  ##
+  # :attr_accessor: test_files
+  #
+  # Test files included in this gem.  You cannot append to this accessor, you
+  # must assign to it.
+
+  array_attribute :test_files
+
+  ##
+  # :attr_accessor: rdoc_options
+  #
+  # An ARGV-style array of options to RDoc
+
+  array_attribute :rdoc_options
+
+  ##
+  # :attr_accessor: extra_rdoc_files
+  #
+  # Extra files to add to RDoc
+
+  array_attribute :extra_rdoc_files
+
+  ##
+  # :attr_accessor: executables
+  #
+  # Executables included in the gem
+
+  array_attribute :executables
+
+  ##
+  # :attr_accessor: extensions
+  #
+  # Extensions to build when installing the gem.  See
+  # Gem::Installer#build_extensions for valid values.
+
+  array_attribute :extensions
+
+  ##
+  # :attr_accessor: requirements
+  #
+  # An array or things required by this gem.  Not used by anything
+  # presently.
+
+  array_attribute :requirements
+
+  ##
+  # :attr_reader: dependencies
+  #
+  # A list of Gem::Dependency objects this gem depends on.
+
+  array_attribute :dependencies
+
+  read_only :dependencies
+
+  # :section: Aliased gemspec attributes
+
+  ##
+  # Singular accessor for #executables
+
+  attribute_alias_singular :executable, :executables
+
+  ##
+  # Singular accessor for #authors
+
+  attribute_alias_singular :author, :authors
+
+  ##
+  # Singular accessor for #licenses
+
+  attribute_alias_singular :license, :licenses
+
+  ##
+  # Singular accessor for #require_paths
+
+  attribute_alias_singular :require_path, :require_paths
+
+  ##
+  # Singular accessor for #test_files
+
+  attribute_alias_singular :test_file, :test_files
+
+  ##
+  # has_rdoc is now ignored
+
+  overwrite_accessor :has_rdoc do
+    true
+  end
+
+  ##
+  # has_rdoc is now ignored
+
+  overwrite_accessor :has_rdoc= do |value|
+    @has_rdoc = true
+  end
+
+  overwrite_accessor :version= do |version|
+    @version = Gem::Version.create(version)
+    self.required_rubygems_version = '> 1.3.1' if @version.prerelease?
+    return @version
+  end
+
+  overwrite_accessor :platform do
+    @new_platform
+  end
+
+  overwrite_accessor :platform= do |platform|
+    if @original_platform.nil? or
+       @original_platform == Gem::Platform::RUBY then
+      @original_platform = platform
+    end
+
+    case platform
+    when Gem::Platform::CURRENT then
+      @new_platform = Gem::Platform.local
+      @original_platform = @new_platform.to_s
+
+    when Gem::Platform then
+      @new_platform = platform
+
+    # legacy constants
+    when nil, Gem::Platform::RUBY then
+      @new_platform = Gem::Platform::RUBY
+    when 'mswin32' then # was Gem::Platform::WIN32
+      @new_platform = Gem::Platform.new 'x86-mswin32'
+    when 'i586-linux' then # was Gem::Platform::LINUX_586
+      @new_platform = Gem::Platform.new 'x86-linux'
+    when 'powerpc-darwin' then # was Gem::Platform::DARWIN
+      @new_platform = Gem::Platform.new 'ppc-darwin'
+    else
+      @new_platform = Gem::Platform.new platform
+    end
+
+    @platform = @new_platform.to_s
+
+    @new_platform
+  end
+
+  overwrite_accessor :required_ruby_version= do |value|
+    @required_ruby_version = Gem::Requirement.create(value)
+  end
+
+  overwrite_accessor :required_rubygems_version= do |value|
+    @required_rubygems_version = Gem::Requirement.create(value)
+  end
+
+  overwrite_accessor :date= do |date|
+    # We want to end up with a Time object with one-day resolution.
+    # This is the cleanest, most-readable, faster-than-using-Date
+    # way to do it.
+    case date
+    when String then
+      @date = if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
+                Time.local($1.to_i, $2.to_i, $3.to_i)
+              else
+                require 'time'
+                Time.parse date
+              end
+    when Time then
+      @date = Time.local(date.year, date.month, date.day)
+    when Date then
+      @date = Time.local(date.year, date.month, date.day)
+    else
+      @date = TODAY
+    end
+  end
+
+  overwrite_accessor :date do
+    self.date = nil if @date.nil?  # HACK Sets the default value for date
+    @date
+  end
+
+  overwrite_accessor :summary= do |str|
+    @summary = if str then
+                 str.strip.
+                 gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
+                 gsub(/\n[ \t]*/, " ")
+               end
+  end
+
+  overwrite_accessor :description= do |str|
+    @description = str.to_s
+  end
+
+  overwrite_accessor :default_executable do
+    begin
+      if defined?(@default_executable) and @default_executable
+        result = @default_executable
+      elsif @executables and @executables.size == 1
+        result = Array(@executables).first
+      else
+        result = nil
+      end
+      result
+    rescue
+      nil
+    end
+  end
+
+  overwrite_accessor :test_files do
+    # Handle the possibility that we have @test_suite_file but not
+    # @test_files.  This will happen when an old gem is loaded via
+    # YAML.
+    if defined? @test_suite_file then
+      @test_files = [@test_suite_file].flatten
+      @test_suite_file = nil
+    end
+    if defined?(@test_files) and @test_files then
+      @test_files
+    else
+      @test_files = []
+    end
+  end
+
+  overwrite_accessor :files do
+    result = []
+    result.push(*@files) if defined?(@files)
+    result.push(*@test_files) if defined?(@test_files)
+    result.push(*(add_bindir(@executables)))
+    result.push(*@extra_rdoc_files) if defined?(@extra_rdoc_files)
+    result.push(*@extensions) if defined?(@extensions)
+    result.uniq.compact
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/test_utilities.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/test_utilities.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/test_utilities.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,131 @@
+require 'tempfile'
+require 'rubygems'
+require 'rubygems/remote_fetcher'
+
+##
+# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP
+# requests when testing code that uses RubyGems.
+#
+# Example:
+#
+#   @fetcher = Gem::FakeFetcher.new
+#   @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml
+#   Gem::RemoteFetcher.fetcher = @fetcher
+#   
+#   # invoke RubyGems code
+#   
+#   paths = @fetcher.paths
+#   assert_equal 'http://gems.example.com/yaml', paths.shift
+#   assert paths.empty?, paths.join(', ')
+#
+# See RubyGems' tests for more examples of FakeFetcher.
+
+class Gem::FakeFetcher
+
+  attr_reader :data
+  attr_accessor :paths
+
+  def initialize
+    @data = {}
+    @paths = []
+  end
+
+  def fetch_path path, mtime = nil
+    path = path.to_s
+    @paths << path
+    raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
+
+    unless @data.key? path then
+      raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
+    end
+
+    data = @data[path]
+
+    if data.respond_to?(:call) then
+      data.call
+    else
+      if path.to_s =~ /gz$/ and not data.nil? and not data.empty? then
+        data = Gem.gunzip data
+      end
+
+      data
+    end
+  end
+
+  def fetch_size(path)
+    path = path.to_s
+    @paths << path
+
+    raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
+
+    unless @data.key? path then
+      raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
+    end
+
+    data = @data[path]
+
+    data.respond_to?(:call) ? data.call : data.length
+  end
+
+  def download spec, source_uri, install_dir = Gem.dir
+    name = spec.file_name
+    path = File.join(install_dir, 'cache', name)
+
+    Gem.ensure_gem_subdirectories install_dir
+
+    if source_uri =~ /^http/ then
+      File.open(path, "wb") do |f|
+        f.write fetch_path(File.join(source_uri, "gems", name))
+      end
+    else
+      FileUtils.cp source_uri, path
+    end
+
+    path
+  end
+
+end
+
+# :stopdoc:
+class Gem::RemoteFetcher
+
+  def self.fetcher=(fetcher)
+    @fetcher = fetcher
+  end
+
+end
+# :startdoc:
+
+##
+# A StringIO duck-typed class that uses Tempfile instead of String as the
+# backing store.
+#--
+# This class was added to flush out problems in Rubinius' IO implementation.
+
+class TempIO
+
+  @@count = 0
+
+  def initialize(string = '')
+    @tempfile = Tempfile.new "TempIO-#{@@count += 1}"
+    @tempfile.binmode
+    @tempfile.write string
+    @tempfile.rewind
+  end
+
+  def method_missing(meth, *args, &block)
+    @tempfile.send(meth, *args, &block)
+  end
+
+  def respond_to?(meth)
+    @tempfile.respond_to? meth
+  end
+
+  def string
+    @tempfile.flush
+
+    Gem.read_binary @tempfile.path
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/text.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/text.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/text.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,30 @@
+require 'rubygems'
+
+##
+# A collection of text-wrangling methods
+
+module Gem::Text
+
+  ##
+  # Wraps +text+ to +wrap+ characters and optionally indents by +indent+
+  # characters
+
+  def format_text(text, wrap, indent=0)
+    result = []
+    work = text.dup
+
+    while work.length > wrap do
+      if work =~ /^(.{0,#{wrap}})[ \n]/ then
+        result << $1
+        work.slice!(0, $&.length)
+      else
+        result << work.slice!(0, wrap)
+      end
+    end
+
+    result << work if work.length.nonzero?
+    result.join("\n").gsub(/^/, " " * indent)
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/timer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/timer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/timer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,28 @@
+#
+# This file defines a $log variable for logging, and a time() method for
+# recording timing information.
+#
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+
+file, lineno = Gem.location_of_caller
+
+warn "#{file}:#{lineno}:Warning: RubyGems' lib/rubygems/timer.rb deprecated and will be removed on or after June 2009."
+
+$log = Object.new
+
+# :stopdoc:
+def $log.debug(message)
+  Gem.debug message
+end
+
+def time(msg, width=25, &block)
+  Gem.time(msg, width, &block)
+end
+# :startdoc:
+


Property changes on: MacRuby/trunk/test/libs/rubygems/lib/rubygems/timer.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/uninstaller.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/uninstaller.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/uninstaller.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,262 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'fileutils'
+require 'rubygems'
+require 'rubygems/dependency_list'
+require 'rubygems/doc_manager'
+require 'rubygems/user_interaction'
+
+##
+# An Uninstaller.
+#
+# The uninstaller fires pre and post uninstall hooks.  Hooks can be added
+# either through a rubygems_plugin.rb file in an installed gem or via a
+# rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb
+# file.  See Gem.pre_uninstall and Gem.post_uninstall for details.
+
+class Gem::Uninstaller
+
+  include Gem::UserInteraction
+
+  ##
+  # The directory a gem's executables will be installed into
+
+  attr_reader :bin_dir
+
+  ##
+  # The gem repository the gem will be installed into
+
+  attr_reader :gem_home
+
+  ##
+  # The Gem::Specification for the gem being uninstalled, only set during
+  # #uninstall_gem
+
+  attr_reader :spec
+
+  ##
+  # Constructs an uninstaller that will uninstall +gem+
+
+  def initialize(gem, options = {})
+    @gem = gem
+    @version = options[:version] || Gem::Requirement.default
+    gem_home = options[:install_dir] || Gem.dir
+    @gem_home = File.expand_path gem_home
+    @force_executables = options[:executables]
+    @force_all = options[:all]
+    @force_ignore = options[:ignore]
+    @bin_dir = options[:bin_dir]
+
+    # only add user directory if install_dir is not set
+    @user_install = false
+    @user_install = options[:user_install] unless options[:install_dir]
+
+    spec_dir = File.join @gem_home, 'specifications'
+    @source_index = Gem::SourceIndex.from_gems_in spec_dir
+
+    if @user_install then
+      user_dir = File.join Gem.user_dir, 'specifications'
+      @user_index = Gem::SourceIndex.from_gems_in user_dir
+    end
+  end
+
+  ##
+  # Performs the uninstall of the gem.  This removes the spec, the Gem
+  # directory, and the cached .gem file.
+
+  def uninstall
+    list = @source_index.find_name @gem, @version
+    list += @user_index.find_name @gem, @version if @user_install
+
+    if list.empty? then
+      raise Gem::InstallError, "cannot uninstall, check `gem list -d #{@gem}`"
+
+    elsif list.size > 1 and @force_all then
+      remove_all list.dup
+
+    elsif list.size > 1 then
+      gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
+
+      say
+      gem_name, index = choose_from_list "Select gem to uninstall:", gem_names
+
+      if index == list.size then
+        remove_all list.dup
+      elsif index >= 0 && index < list.size then
+        uninstall_gem list[index], list.dup
+      else
+        say "Error: must enter a number [1-#{list.size+1}]"
+      end
+    else
+      uninstall_gem list.first, list.dup
+    end
+  end
+
+  ##
+  # Uninstalls gem +spec+
+
+  def uninstall_gem(spec, specs)
+    @spec = spec
+
+    Gem.pre_uninstall_hooks.each do |hook|
+      hook.call self
+    end
+
+    remove_executables @spec
+    remove @spec, specs
+
+    Gem.post_uninstall_hooks.each do |hook|
+      hook.call self
+    end
+
+    @spec = nil
+  end
+
+  ##
+  # Removes installed executables and batch files (windows only) for
+  # +gemspec+.
+
+  def remove_executables(spec)
+    return if spec.nil?
+
+    unless spec.executables.empty? then
+      bindir = @bin_dir ? @bin_dir : Gem.bindir(spec.installation_path)
+
+      list = @source_index.find_name(spec.name).delete_if { |s|
+        s.version == spec.version
+      }
+
+      executables = spec.executables.clone
+
+      list.each do |s|
+        s.executables.each do |exe_name|
+          executables.delete exe_name
+        end
+      end
+
+      return if executables.empty?
+
+      answer = if @force_executables.nil? then
+                 ask_yes_no("Remove executables:\n" \
+                            "\t#{spec.executables.join(", ")}\n\nin addition to the gem?",
+                            true) # " # appease ruby-mode - don't ask
+               else
+                 @force_executables
+               end
+
+      unless answer then
+        say "Executables and scripts will remain installed."
+      else
+        raise Gem::FilePermissionError, bindir unless File.writable? bindir
+
+        spec.executables.each do |exe_name|
+          say "Removing #{exe_name}"
+          FileUtils.rm_f File.join(bindir, exe_name)
+          FileUtils.rm_f File.join(bindir, "#{exe_name}.bat")
+        end
+      end
+    end
+  end
+
+  ##
+  # Removes all gems in +list+.
+  #
+  # NOTE: removes uninstalled gems from +list+.
+
+  def remove_all(list)
+    list.dup.each { |spec| uninstall_gem spec, list }
+  end
+
+  ##
+  # spec:: the spec of the gem to be uninstalled
+  # list:: the list of all such gems
+  #
+  # Warning: this method modifies the +list+ parameter.  Once it has
+  # uninstalled a gem, it is removed from that list.
+
+  def remove(spec, list)
+    unless dependencies_ok? spec then
+      raise Gem::DependencyRemovalException,
+            "Uninstallation aborted due to dependent gem(s)"
+    end
+
+    unless path_ok?(@gem_home, spec) or
+           (@user_install and path_ok?(Gem.user_dir, spec)) then
+      e = Gem::GemNotInHomeException.new \
+            "Gem is not installed in directory #{@gem_home}"
+      e.spec = spec
+
+      raise e
+    end
+
+    raise Gem::FilePermissionError, spec.installation_path unless
+      File.writable?(spec.installation_path)
+
+    FileUtils.rm_rf spec.full_gem_path
+
+    original_platform_name = [
+      spec.name, spec.version, spec.original_platform].join '-'
+
+    spec_dir = File.join spec.installation_path, 'specifications'
+    gemspec = File.join spec_dir, spec.spec_name
+
+    unless File.exist? gemspec then
+      gemspec = File.join spec_dir, "#{original_platform_name}.gemspec"
+    end
+
+    FileUtils.rm_rf gemspec
+
+    cache_dir = File.join spec.installation_path, 'cache'
+    gem = File.join cache_dir, spec.file_name
+
+    unless File.exist? gem then
+      gem = File.join cache_dir, "#{original_platform_name}.gem"
+    end
+
+    FileUtils.rm_rf gem
+
+    Gem::DocManager.new(spec).uninstall_doc
+
+    say "Successfully uninstalled #{spec.full_name}"
+
+    list.delete spec
+  end
+
+  ##
+  # Is +spec+ in +gem_dir+?
+
+  def path_ok?(gem_dir, spec)
+    full_path = File.join gem_dir, 'gems', spec.full_name
+    original_path = File.join gem_dir, 'gems', spec.original_name
+
+    full_path == spec.full_gem_path || original_path == spec.full_gem_path
+  end
+
+  def dependencies_ok?(spec)
+    return true if @force_ignore
+
+    deplist = Gem::DependencyList.from_source_index @source_index
+    deplist.add(*@user_index.gems.values) if @user_install
+    deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec)
+  end
+
+  def ask_if_ok(spec)
+    msg = ['']
+    msg << 'You have requested to uninstall the gem:'
+    msg << "\t#{spec.full_name}"
+    spec.dependent_gems.each do |gem,dep,satlist|
+      msg <<
+        ("#{gem.name}-#{gem.version} depends on " +
+        "[#{dep.name} (#{dep.version_requirements})]")
+    end
+    msg << 'If you remove this gems, one or more dependencies will not be met.'
+    msg << 'Continue with Uninstall?'
+    return ask_yes_no(msg.join("\n"), true)
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/user_interaction.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/user_interaction.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/user_interaction.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,390 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+##
+# Module that defines the default UserInteraction.  Any class including this
+# module will have access to the +ui+ method that returns the default UI.
+
+module Gem::DefaultUserInteraction
+
+  ##
+  # The default UI is a class variable of the singleton class for this
+  # module.
+
+  @ui = nil
+
+  ##
+  # Return the default UI.
+
+  def self.ui
+    @ui ||= Gem::ConsoleUI.new
+  end
+
+  ##
+  # Set the default UI.  If the default UI is never explicitly set, a simple
+  # console based UserInteraction will be used automatically.
+
+  def self.ui=(new_ui)
+    @ui = new_ui
+  end
+
+  ##
+  # Use +new_ui+ for the duration of +block+.
+
+  def self.use_ui(new_ui)
+    old_ui = @ui
+    @ui = new_ui
+    yield
+  ensure
+    @ui = old_ui
+  end
+
+  ##
+  # See DefaultUserInteraction::ui
+
+  def ui
+    Gem::DefaultUserInteraction.ui
+  end
+
+  ##
+  # See DefaultUserInteraction::ui=
+
+  def ui=(new_ui)
+    Gem::DefaultUserInteraction.ui = new_ui
+  end
+
+  ##
+  # See DefaultUserInteraction::use_ui
+
+  def use_ui(new_ui, &block)
+    Gem::DefaultUserInteraction.use_ui(new_ui, &block)
+  end
+
+end
+
+##
+# Make the default UI accessable without the "ui." prefix.  Classes
+# including this module may use the interaction methods on the default UI
+# directly.  Classes may also reference the ui and ui= methods.
+#
+# Example:
+#
+#   class X
+#     include Gem::UserInteraction
+#
+#     def get_answer
+#       n = ask("What is the meaning of life?")
+#     end
+#   end
+
+module Gem::UserInteraction
+
+  include Gem::DefaultUserInteraction
+
+  ##
+  # :method: alert
+
+  ##
+  # :method: alert_error
+
+  ##
+  # :method: alert_warning
+
+  ##
+  # :method: ask
+
+  ##
+  # :method: ask_yes_no
+
+  ##
+  # :method: choose_from_list
+
+  ##
+  # :method: say
+
+  ##
+  # :method: terminate_interaction
+
+  [:alert,
+   :alert_error,
+   :alert_warning,
+   :ask,
+   :ask_yes_no,
+   :choose_from_list,
+   :say,
+   :terminate_interaction ].each do |methname|
+    class_eval %{
+      def #{methname}(*args)
+        ui.#{methname}(*args)
+      end
+    }, __FILE__, __LINE__
+  end
+end
+
+##
+# Gem::StreamUI implements a simple stream based user interface.
+
+class Gem::StreamUI
+
+  attr_reader :ins, :outs, :errs
+
+  def initialize(in_stream, out_stream, err_stream=STDERR)
+    @ins = in_stream
+    @outs = out_stream
+    @errs = err_stream
+  end
+
+  ##
+  # Choose from a list of options.  +question+ is a prompt displayed above
+  # the list.  +list+ is a list of option strings.  Returns the pair
+  # [option_name, option_index].
+
+  def choose_from_list(question, list)
+    @outs.puts question
+
+    list.each_with_index do |item, index|
+      @outs.puts " #{index+1}. #{item}"
+    end
+
+    @outs.print "> "
+    @outs.flush
+
+    result = @ins.gets
+
+    return nil, nil unless result
+
+    result = result.strip.to_i - 1
+    return list[result], result
+  end
+
+  ##
+  # Ask a question.  Returns a true for yes, false for no.  If not connected
+  # to a tty, raises an exception if default is nil, otherwise returns
+  # default.
+
+  def ask_yes_no(question, default=nil)
+    unless @ins.tty? then
+      if default.nil? then
+        raise Gem::OperationNotSupportedError,
+              "Not connected to a tty and no default specified"
+      else
+        return default
+      end
+    end
+
+    qstr = case default
+           when nil
+             'yn'
+           when true
+             'Yn'
+           else
+             'yN'
+           end
+
+    result = nil
+
+    while result.nil?
+      result = ask("#{question} [#{qstr}]")
+      result = case result
+      when /^[Yy].*/
+        true
+      when /^[Nn].*/
+        false
+      when /^$/
+        default
+      else
+        nil
+      end
+    end
+
+    return result
+  end
+
+  ##
+  # Ask a question.  Returns an answer if connected to a tty, nil otherwise.
+
+  def ask(question)
+    return nil if not @ins.tty?
+
+    @outs.print(question + "  ")
+    @outs.flush
+
+    result = @ins.gets
+    result.chomp! if result
+    result
+  end
+
+  ##
+  # Display a statement.
+
+  def say(statement="")
+    @outs.puts statement
+  end
+
+  ##
+  # Display an informational alert.  Will ask +question+ if it is not nil.
+
+  def alert(statement, question=nil)
+    @outs.puts "INFO:  #{statement}"
+    ask(question) if question
+  end
+
+  ##
+  # Display a warning in a location expected to get error messages.  Will
+  # ask +question+ if it is not nil.
+
+  def alert_warning(statement, question=nil)
+    @errs.puts "WARNING:  #{statement}"
+    ask(question) if question
+  end
+
+  ##
+  # Display an error message in a location expected to get error messages.
+  # Will ask +question+ if it is not nil.
+
+  def alert_error(statement, question=nil)
+    @errs.puts "ERROR:  #{statement}"
+    ask(question) if question
+  end
+
+  ##
+  # Display a debug message on the same location as error messages.
+
+  def debug(statement)
+    @errs.puts statement
+  end
+
+  ##
+  # Terminate the application with exit code +status+, running any exit
+  # handlers that might have been defined.
+
+  def terminate_interaction(status = 0)
+    raise Gem::SystemExitException, status
+  end
+
+  ##
+  # Return a progress reporter object chosen from the current verbosity.
+
+  def progress_reporter(*args)
+    case Gem.configuration.verbose
+    when nil, false
+      SilentProgressReporter.new(@outs, *args)
+    when true
+      SimpleProgressReporter.new(@outs, *args)
+    else
+      VerboseProgressReporter.new(@outs, *args)
+    end
+  end
+
+  ##
+  # An absolutely silent progress reporter.
+
+  class SilentProgressReporter
+    attr_reader :count
+
+    def initialize(out_stream, size, initial_message, terminal_message = nil)
+    end
+
+    def updated(message)
+    end
+
+    def done
+    end
+  end
+
+  ##
+  # A basic dotted progress reporter.
+
+  class SimpleProgressReporter
+
+    include Gem::DefaultUserInteraction
+
+    attr_reader :count
+
+    def initialize(out_stream, size, initial_message,
+                   terminal_message = "complete")
+      @out = out_stream
+      @total = size
+      @count = 0
+      @terminal_message = terminal_message
+
+      @out.puts initial_message
+    end
+
+    ##
+    # Prints out a dot and ignores +message+.
+
+    def updated(message)
+      @count += 1
+      @out.print "."
+      @out.flush
+    end
+
+    ##
+    # Prints out the terminal message.
+
+    def done
+      @out.puts "\n#{@terminal_message}"
+    end
+
+  end
+
+  ##
+  # A progress reporter that prints out messages about the current progress.
+
+  class VerboseProgressReporter
+
+    include Gem::DefaultUserInteraction
+
+    attr_reader :count
+
+    def initialize(out_stream, size, initial_message,
+                   terminal_message = 'complete')
+      @out = out_stream
+      @total = size
+      @count = 0
+      @terminal_message = terminal_message
+
+      @out.puts initial_message
+    end
+
+    ##
+    # Prints out the position relative to the total and the +message+.
+
+    def updated(message)
+      @count += 1
+      @out.puts "#{@count}/#{@total}: #{message}"
+    end
+
+    ##
+    # Prints out the terminal message.
+
+    def done
+      @out.puts @terminal_message
+    end
+  end
+
+end
+
+##
+# Subclass of StreamUI that instantiates the user interaction using STDIN,
+# STDOUT, and STDERR.
+
+class Gem::ConsoleUI < Gem::StreamUI
+  def initialize
+    super STDIN, STDOUT, STDERR
+  end
+end
+
+##
+# SilentUI is a UI choice that is absolutely silent.
+
+class Gem::SilentUI
+  def method_missing(sym, *args, &block)
+    self
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/validator.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/validator.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/validator.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,241 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'find'
+
+require 'digest'
+require 'rubygems/format'
+require 'rubygems/installer'
+
+# Load test-unit 2.x if it's a gem
+begin
+   Gem.activate('test-unit')
+rescue Gem::LoadError
+   # Ignore - use the test-unit library that's part of the standard library
+end   
+
+##
+# Validator performs various gem file and gem database validation
+
+class Gem::Validator
+
+  include Gem::UserInteraction
+
+  ##
+  # Given a gem file's contents, validates against its own MD5 checksum
+  # gem_data:: [String] Contents of the gem file
+
+  def verify_gem(gem_data)
+    raise Gem::VerificationError, 'empty gem file' if gem_data.size == 0
+
+    unless gem_data =~ /MD5SUM/ then
+      return # Don't worry about it...this sucks.  Need to fix MD5 stuff for
+      # new format
+      # FIXME
+    end
+
+    sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/,
+                             "MD5SUM = \"#{"F" * 32}\"")
+
+    unless Digest::MD5.hexdigest(sum_data) == $1.to_s then
+      raise Gem::VerificationError, 'invalid checksum for gem file'
+    end
+  end
+
+  ##
+  # Given the path to a gem file, validates against its own MD5 checksum
+  #
+  # gem_path:: [String] Path to gem file
+
+  def verify_gem_file(gem_path)
+    open gem_path, Gem.binary_mode do |file|
+      gem_data = file.read
+      verify_gem gem_data
+    end
+  rescue Errno::ENOENT, Errno::EINVAL
+    raise Gem::VerificationError, "missing gem file #{gem_path}"
+  end
+
+  private
+
+  def find_files_for_gem(gem_directory)
+    installed_files = []
+    Find.find gem_directory do |file_name|
+      fn = file_name[gem_directory.size..file_name.size-1].sub(/^\//, "")
+      installed_files << fn unless
+        fn =~ /CVS/ || fn.empty? || File.directory?(file_name)
+    end
+    installed_files
+  end
+
+  public
+
+  ErrorData = Struct.new :path, :problem
+
+  ##
+  # Checks the gem directory for the following potential
+  # inconsistencies/problems:
+  #
+  # * Checksum gem itself
+  # * For each file in each gem, check consistency of installed versions
+  # * Check for files that aren't part of the gem but are in the gems directory
+  # * 1 cache - 1 spec - 1 directory.
+  #
+  # returns a hash of ErrorData objects, keyed on the problem gem's name.
+
+  def alien(gems=[])
+    errors = Hash.new { |h,k| h[k] = {} }
+
+    Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
+      next unless gems.include? gem_spec.name unless gems.empty?
+
+      install_dir = gem_spec.installation_path
+      gem_path = File.join install_dir, "cache", gem_spec.file_name
+      spec_path = File.join install_dir, "specifications", gem_spec.spec_name
+      gem_directory = gem_spec.full_gem_path
+
+      unless File.directory? gem_directory then
+        errors[gem_name][gem_spec.full_name] =
+          "Gem registered but doesn't exist at #{gem_directory}"
+        next
+      end
+
+      unless File.exist? spec_path then
+        errors[gem_name][spec_path] = "Spec file missing for installed gem"
+      end
+
+      begin
+        verify_gem_file(gem_path)
+
+        good, gone, unreadable = nil, nil, nil, nil
+
+        open gem_path, Gem.binary_mode do |file|
+          format = Gem::Format.from_file_by_path(gem_path)
+
+          good, gone = format.file_entries.partition { |entry, _|
+            File.exist? File.join(gem_directory, entry['path'])
+          }
+
+          gone.map! { |entry, _| entry['path'] }
+          gone.sort.each do |path|
+            errors[gem_name][path] = "Missing file"
+          end
+
+          good, unreadable = good.partition { |entry, _|
+            File.readable? File.join(gem_directory, entry['path'])
+          }
+
+          unreadable.map! { |entry, _| entry['path'] }
+          unreadable.sort.each do |path|
+            errors[gem_name][path] = "Unreadable file"
+          end
+
+          good.each do |entry, data|
+            begin
+              next unless data # HACK `gem check -a mkrf`
+
+              open File.join(gem_directory, entry['path']), Gem.binary_mode do |f|
+                unless Digest::MD5.hexdigest(f.read).to_s ==
+                    Digest::MD5.hexdigest(data).to_s then
+                  errors[gem_name][entry['path']] = "Modified from original"
+                end
+              end
+            end
+          end
+        end
+
+        installed_files = find_files_for_gem(gem_directory)
+        good.map! { |entry, _| entry['path'] }
+        extras = installed_files - good - unreadable
+
+        extras.each do |extra|
+          errors[gem_name][extra] = "Extra file"
+        end
+      rescue Gem::VerificationError => e
+        errors[gem_name][gem_path] = e.message
+      end
+    end
+
+    errors.each do |name, subhash|
+      errors[name] = subhash.map { |path, msg| ErrorData.new(path, msg) }
+    end
+
+    errors
+  end
+
+  if RUBY_VERSION < '1.9' then
+    class TestRunner
+      def initialize(suite, ui)
+        @suite = suite
+        @ui = ui
+      end
+
+      def self.run(suite, ui)
+        require 'test/unit/ui/testrunnermediator'
+        return new(suite, ui).start
+      end
+
+      def start
+        @mediator = Test::Unit::UI::TestRunnerMediator.new(@suite)
+        @mediator.add_listener(Test::Unit::TestResult::FAULT, &method(:add_fault))
+        return @mediator.run_suite
+      end
+
+      def add_fault(fault)
+        if Gem.configuration.verbose then
+          @ui.say fault.long_display
+        end
+      end
+    end
+
+    autoload :TestRunner, 'test/unit/ui/testrunnerutilities'
+  end
+
+  ##
+  # Runs unit tests for a given gem specification
+
+  def unit_test(gem_spec)
+    start_dir = Dir.pwd
+    Dir.chdir(gem_spec.full_gem_path)
+    $: << gem_spec.full_gem_path
+    # XXX: why do we need this gem_spec when we've already got 'spec'?
+    test_files = gem_spec.test_files
+
+    if test_files.empty? then
+      say "There are no unit tests to run for #{gem_spec.full_name}"
+      return nil
+    end
+
+    gem gem_spec.name, "= #{gem_spec.version.version}"
+
+    test_files.each do |f| require f end
+
+    if RUBY_VERSION < '1.9' then
+      suite = Test::Unit::TestSuite.new("#{gem_spec.name}-#{gem_spec.version}")
+
+      ObjectSpace.each_object(Class) do |klass|
+        suite << klass.suite if (klass < Test::Unit::TestCase)
+      end
+
+      result = TestRunner.run suite, ui
+
+      alert_error result.to_s unless result.passed?
+    else
+      result = MiniTest::Unit.new
+      result.run
+    end
+
+    result
+  ensure
+    Dir.chdir(start_dir)
+  end
+
+  def remove_leading_dot_dir(path)
+    path.sub(/^\.\//, "")
+  end
+
+end
+


Property changes on: MacRuby/trunk/test/libs/rubygems/lib/rubygems/validator.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/version.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/version.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/version.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,208 @@
+module Gem
+
+  ##
+  # The Version class processes string versions into comparable
+  # values. A version string should normally be a series of numbers
+  # separated by periods. Each part (digits separated by periods) is
+  # considered its own number, and these are used for sorting. So for
+  # instance, 3.10 sorts higher than 3.2 because ten is greater than
+  # two.
+  #
+  # If any part contains letters (currently only a-z are supported) then
+  # that version is considered prerelease. Versions with a prerelease
+  # part in the Nth part sort less than versions with N-1 parts. Prerelease
+  # parts are sorted alphabetically using the normal Ruby string sorting
+  # rules.
+  #
+  # Prereleases sort between real releases (newest to oldest):
+  #
+  # 1. 1.0
+  # 2. 1.0.b
+  # 3. 1.0.a
+  # 4. 0.9
+  #
+  # == Preventing Version Catastrophe:
+  #
+  # From: http://blog.zenspider.com/2008/10/rubygems-howto-preventing-cata.html
+  #
+  # Let's say you're depending on the fnord gem version 2.y.z. If you
+  # specify your dependency as ">= 2.0.0" then, you're good, right? What
+  # happens if fnord 3.0 comes out and it isn't backwards compatible
+  # with 2.y.z? Your stuff will break as a result of using ">=". The
+  # better route is to specify your dependency with a "spermy" version
+  # specifier. They're a tad confusing, so here is how the dependency
+  # specifiers work:
+  #
+  #   Specification From  ... To (exclusive)
+  #   ">= 3.0"      3.0   ... &infin;
+  #   "~> 3.0"      3.0   ... 4.0
+  #   "~> 3.0.0"    3.0.0 ... 3.1
+  #   "~> 3.5"      3.5   ... 4.0
+  #   "~> 3.5.0"    3.5.0 ... 3.6
+
+  class Version
+    include Comparable
+
+    VERSION_PATTERN = '[0-9]+(\.[0-9a-z]+)*' # :nodoc:
+    ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc:
+
+    attr_reader :segments
+
+    ##
+    # A string representation of this Version.
+
+    attr_reader :version
+    alias to_s version
+
+    ##
+    # True if the +version+ string matches RubyGems' requirements.
+
+    def self.correct? version
+      version.to_s =~ ANCHORED_VERSION_PATTERN
+    end
+
+    ##
+    # Factory method to create a Version object. Input may be a Version
+    # or a String. Intended to simplify client code.
+    #
+    #   ver1 = Version.create('1.3.17')   # -> (Version object)
+    #   ver2 = Version.create(ver1)       # -> (ver1)
+    #   ver3 = Version.create(nil)        # -> nil
+
+    def self.create input
+      if input.respond_to? :version then
+        input
+      elsif input.nil? then
+        nil
+      else
+        new input
+      end
+    end
+
+    ##
+    # Constructs a Version from the +version+ string.  A version string is a
+    # series of digits or ASCII letters separated by dots.
+
+    def initialize version
+      raise ArgumentError, "Malformed version number string #{version}" unless
+        self.class.correct?(version)
+
+      @version = version.to_s
+      @version.strip!
+
+      @segments = @version.scan(/[0-9a-z]+/i).map do |s|
+        /^\d+$/ =~ s ? s.to_i : s
+      end
+    end
+
+    ##
+    # Return a new version object where the next to the last revision
+    # number is one greater (e.g., 5.3.1 => 5.4).
+    #
+    # Pre-release (alpha) parts, e.g, 5.3.1.b2 => 5.4, are ignored.
+
+    def bump
+      segments = self.segments.dup
+      segments.pop while segments.any? { |s| String === s }
+      segments.pop if segments.size > 1
+
+      segments[-1] = segments[-1].succ
+      self.class.new segments.join(".")
+    end
+
+    ##
+    # A Version is only eql? to another version if it's specified to the
+    # same precision. Version "1.0" is not the same as version "1".
+
+    def eql? other
+      self.class === other and segments == other.segments
+    end
+
+    def hash # :nodoc:
+      segments.hash
+    end
+
+    def inspect # :nodoc:
+      "#<#{self.class} #{version.inspect}>"
+    end
+
+    ##
+    # Dump only the raw version string, not the complete object. It's a
+    # string for backwards (RubyGems 1.3.5 and earlier) compatibility.
+
+    def marshal_dump
+      [version]
+    end
+
+    ##
+    # Load custom marshal format. It's a string for backwards (RubyGems
+    # 1.3.5 and earlier) compatibility.
+
+    def marshal_load array
+      initialize array[0]
+    end
+
+    ##
+    # A version is considered a prerelease if it contains a letter.
+
+    def prerelease?
+      @prerelease ||= segments.any? { |s| String === s }
+    end
+
+    def pretty_print q # :nodoc:
+      q.text "Gem::Version.new(#{version.inspect})"
+    end
+
+    ##
+    # The release for this version (e.g. 1.2.0.a -> 1.2.0).
+    # Non-prerelease versions return themselves.
+
+    def release
+      return self unless prerelease?
+
+      segments = self.segments.dup
+      segments.pop while segments.any? { |s| String === s }
+      self.class.new segments.join('.')
+    end
+
+    ##
+    # A recommended version for use with a ~> Requirement.
+
+    def spermy_recommendation
+      segments = self.segments.dup
+
+      segments.pop    while segments.any? { |s| String === s }
+      segments.pop    while segments.size > 2
+      segments.push 0 while segments.size < 2
+
+      "~> #{segments.join(".")}"
+    end
+
+    ##
+    # Compares this version with +other+ returning -1, 0, or 1 if the other
+    # version is larger, the same, or smaller than this one.
+
+    def <=> other
+      return   1 unless other # HACK: comparable with nil? why?
+      return nil unless self.class === other
+
+      # This method's motto: Object allocation is for suckers. This
+      # method is used often enough that avoiding extra object creation
+      # makes a real difference.
+
+      lhsize = segments.size
+      rhsize = other.segments.size
+      limit  = (lhsize > rhsize ? lhsize : rhsize) - 1
+
+      0.upto(limit) do |i|
+        lhs, rhs = segments[i] || 0, other.segments[i] || 0
+
+        return  -1         if String  === lhs && Numeric === rhs
+        return   1         if Numeric === lhs && String  === rhs
+        return lhs <=> rhs if lhs != rhs
+      end
+
+      return 0
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems/version_option.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems/version_option.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems/version_option.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,49 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+
+# Mixin methods for --version and --platform Gem::Command options.
+module Gem::VersionOption
+
+  # Add the --platform option to the option parser.
+  def add_platform_option(task = command, *wrap)
+    OptionParser.accept Gem::Platform do |value|
+      if value == Gem::Platform::RUBY then
+        value
+      else
+        Gem::Platform.new value
+      end
+    end
+
+    add_option('--platform PLATFORM', Gem::Platform,
+               "Specify the platform of gem to #{task}", *wrap) do
+                 |value, options|
+      unless options[:added_platform] then
+        Gem.platforms = [Gem::Platform::RUBY]
+        options[:added_platform] = true
+      end
+
+      Gem.platforms << value unless Gem.platforms.include? value
+    end
+  end
+
+  # Add the --version option to the option parser.
+  def add_version_option(task = command, *wrap)
+    OptionParser.accept Gem::Requirement do |value|
+      Gem::Requirement.new value
+    end
+
+    add_option('-v', '--version VERSION', Gem::Requirement,
+               "Specify version of gem to #{task}", *wrap) do
+                 |value, options|
+      options[:version] = value
+      options[:prerelease] = true if value.prerelease?
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/rubygems.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/rubygems.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/rubygems.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,1112 @@
+# -*- ruby -*-
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems/defaults'
+require 'thread'
+require 'etc'
+
+##
+# RubyGems is the Ruby standard for publishing and managing third party
+# libraries.
+#
+# For user documentation, see:
+#
+# * <tt>gem help</tt> and <tt>gem help [command]</tt>
+# * {RubyGems User Guide}[http://docs.rubygems.org/read/book/1]
+# * {Frequently Asked Questions}[http://docs.rubygems.org/read/book/3]
+#
+# For gem developer documentation see:
+#
+# * {Creating Gems}[http://docs.rubygems.org/read/chapter/5]
+# * Gem::Specification
+# * Gem::Version for version dependency notes
+#
+# Further RubyGems documentation can be found at:
+#
+# * {RubyGems API}[http://rubygems.rubyforge.org/rdoc] (also available from
+#   <tt>gem server</tt>)
+# * {RubyGems Bookshelf}[http://rubygem.org]
+#
+# == RubyGems Plugins
+#
+# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or
+# $LOAD_PATH.  Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and
+# placed at the root of your gem's #require_path.  Plugins are discovered via
+# Gem::find_files then loaded.  Take care when implementing a plugin as your
+# plugin file may be loaded multiple times if multiple versions of your gem
+# are installed.
+#
+# For an example plugin, see the graph gem which adds a `gem graph` command.
+#
+# == RubyGems Defaults, Packaging
+#
+# RubyGems defaults are stored in rubygems/defaults.rb.  If you're packaging
+# RubyGems or implementing Ruby you can change RubyGems' defaults.
+#
+# For RubyGems packagers, provide lib/rubygems/operating_system.rb and
+# override any defaults from lib/rubygems/defaults.rb.
+#
+# For Ruby implementers, provide lib/rubygems/#{RUBY_ENGINE}.rb and override
+# any defaults from lib/rubygems/defaults.rb.
+#
+# If you need RubyGems to perform extra work on install or uninstall, your
+# defaults override file can set pre and post install and uninstall hooks.
+# See Gem::pre_install, Gem::pre_uninstall, Gem::post_install,
+# Gem::post_uninstall.
+#
+# == Bugs
+#
+# You can submit bugs to the
+# {RubyGems bug tracker}[http://rubyforge.org/tracker/?atid=575&group_id=126]
+# on RubyForge
+#
+# == Credits
+#
+# RubyGems is currently maintained by Eric Hodel.
+#
+# RubyGems was originally developed at RubyConf 2003 by:
+#
+# * Rich Kilmer  -- rich(at)infoether.com
+# * Chad Fowler  -- chad(at)chadfowler.com
+# * David Black  -- dblack(at)wobblini.net
+# * Paul Brannan -- paul(at)atdesk.com
+# * Jim Weirch   -- jim(at)weirichhouse.org
+#
+# Contributors:
+#
+# * Gavin Sinclair     -- gsinclair(at)soyabean.com.au
+# * George Marrows     -- george.marrows(at)ntlworld.com
+# * Dick Davies        -- rasputnik(at)hellooperator.net
+# * Mauricio Fernandez -- batsman.geo(at)yahoo.com
+# * Simon Strandgaard  -- neoneye(at)adslhome.dk
+# * Dave Glasser       -- glasser(at)mit.edu
+# * Paul Duncan        -- pabs(at)pablotron.org
+# * Ville Aine         -- vaine(at)cs.helsinki.fi
+# * Eric Hodel         -- drbrain(at)segment7.net
+# * Daniel Berger      -- djberg96(at)gmail.com
+# * Phil Hagelberg     -- technomancy(at)gmail.com
+# * Ryan Davis         -- ryand-ruby(at)zenspider.com
+#
+# (If your name is missing, PLEASE let us know!)
+#
+# Thanks!
+#
+# -The RubyGems Team
+
+module Gem
+  RubyGemsVersion = VERSION = '1.3.5'
+
+  ##
+  # Raised when RubyGems is unable to load or activate a gem.  Contains the
+  # name and version requirements of the gem that either conflicts with
+  # already activated gems or that RubyGems is otherwise unable to activate.
+
+  class LoadError < ::LoadError
+    # Name of gem
+    attr_accessor :name
+
+    # Version requirement of gem
+    attr_accessor :version_requirement
+  end
+
+  ##
+  # Configuration settings from ::RbConfig
+
+  ConfigMap = {} unless defined?(ConfigMap)
+
+  require 'rbconfig'
+
+  ConfigMap.merge!(
+    :EXEEXT            => RbConfig::CONFIG["EXEEXT"],
+    :RUBY_SO_NAME      => RbConfig::CONFIG["RUBY_SO_NAME"],
+    :arch              => RbConfig::CONFIG["arch"],
+    :bindir            => RbConfig::CONFIG["bindir"],
+    :datadir           => RbConfig::CONFIG["datadir"],
+    :libdir            => RbConfig::CONFIG["libdir"],
+    :ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
+    :ruby_version      => RbConfig::CONFIG["ruby_version"],
+    :sitedir           => RbConfig::CONFIG["sitedir"],
+    :sitelibdir        => RbConfig::CONFIG["sitelibdir"],
+    :vendordir         => RbConfig::CONFIG["vendordir"] ,
+    :vendorlibdir      => RbConfig::CONFIG["vendorlibdir"]
+  )
+
+  ##
+  # Default directories in a gem repository
+
+  DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES)
+
+  # :stopdoc:
+  MUTEX = Mutex.new
+
+  RubyGemsPackageVersion = RubyGemsVersion
+  # :startdoc:
+
+  ##
+  # An Array of Regexps that match windows ruby platforms.
+
+  WIN_PATTERNS = [
+    /bccwin/i,
+    /cygwin/i,
+    /djgpp/i,
+    /mingw/i,
+    /mswin/i,
+    /wince/i,
+  ]
+
+  @@source_index = nil
+  @@win_platform = nil
+
+  @configuration = nil
+  @loaded_specs = {}
+  @loaded_stacks = {}
+  @platforms = []
+  @ruby = nil
+  @sources = []
+
+  @post_install_hooks   ||= []
+  @post_uninstall_hooks ||= []
+  @pre_uninstall_hooks  ||= []
+  @pre_install_hooks    ||= []
+
+  ##
+  # Activates an installed gem matching +gem+.  The gem must satisfy
+  # +version_requirements+.
+  #
+  # Returns true if the gem is activated, false if it is already
+  # loaded, or an exception otherwise.
+  #
+  # Gem#activate adds the library paths in +gem+ to $LOAD_PATH.  Before a Gem
+  # is activated its required Gems are activated.  If the version information
+  # is omitted, the highest version Gem of the supplied name is loaded.  If a
+  # Gem is not found that meets the version requirements or a required Gem is
+  # not found, a Gem::LoadError is raised.
+  #
+  # More information on version requirements can be found in the
+  # Gem::Requirement and Gem::Version documentation.
+
+  def self.activate(gem, *version_requirements)
+    if version_requirements.last.is_a?(Hash)
+      options = version_requirements.pop
+    else
+      options = {}
+    end
+
+    sources = options[:sources] || []
+
+    if version_requirements.empty? then
+      version_requirements = Gem::Requirement.default
+    end
+
+    unless gem.respond_to?(:name) and
+           gem.respond_to?(:version_requirements) then
+      gem = Gem::Dependency.new(gem, version_requirements)
+    end
+
+    matches = Gem.source_index.find_name(gem.name, gem.version_requirements)
+    report_activate_error(gem) if matches.empty?
+
+    if @loaded_specs[gem.name] then
+      # This gem is already loaded.  If the currently loaded gem is not in the
+      # list of candidate gems, then we have a version conflict.
+      existing_spec = @loaded_specs[gem.name]
+
+      unless matches.any? { |spec| spec.version == existing_spec.version } then
+         sources_message = sources.map { |spec| spec.full_name }
+         stack_message = @loaded_stacks[gem.name].map { |spec| spec.full_name }
+
+         msg = "can't activate #{gem} for #{sources_message.inspect}, "
+         msg << "already activated #{existing_spec.full_name} for "
+         msg << "#{stack_message.inspect}"
+
+         e = Gem::LoadError.new msg
+         e.name = gem.name
+         e.version_requirement = gem.version_requirements
+
+         raise e
+      end
+
+      return false
+    end
+
+    # new load
+    spec = matches.last
+    return false if spec.loaded?
+
+    spec.loaded = true
+    @loaded_specs[spec.name] = spec
+    @loaded_stacks[spec.name] = sources.dup
+
+    # Load dependent gems first
+    spec.runtime_dependencies.each do |dep_gem|
+      activate dep_gem, :sources => [spec, *sources]
+    end
+
+    # bin directory must come before library directories
+    spec.require_paths.unshift spec.bindir if spec.bindir
+
+    require_paths = spec.require_paths.map do |path|
+      File.join spec.full_gem_path, path
+    end
+
+    sitelibdir = ConfigMap[:sitelibdir]
+
+    # gem directories must come after -I and ENV['RUBYLIB']
+    insert_index = load_path_insert_index
+
+    if insert_index then
+      # gem directories must come after -I and ENV['RUBYLIB']
+      $LOAD_PATH.insert(insert_index, *require_paths)
+    else
+      # we are probably testing in core, -I and RUBYLIB don't apply
+      $LOAD_PATH.unshift(*require_paths)
+    end
+
+    return true
+  end
+
+  ##
+  # An Array of all possible load paths for all versions of all gems in the
+  # Gem installation.
+
+  def self.all_load_paths
+    result = []
+
+    Gem.path.each do |gemdir|
+      each_load_path all_partials(gemdir) do |load_path|
+        result << load_path
+      end
+    end
+
+    result
+  end
+
+  ##
+  # Return all the partial paths in +gemdir+.
+
+  def self.all_partials(gemdir)
+    Dir[File.join(gemdir, 'gems/*')]
+  end
+
+  private_class_method :all_partials
+
+  ##
+  # See if a given gem is available.
+
+  def self.available?(gem, *requirements)
+    requirements = Gem::Requirement.default if requirements.empty?
+
+    unless gem.respond_to?(:name) and
+           gem.respond_to?(:version_requirements) then
+      gem = Gem::Dependency.new gem, requirements
+    end
+
+    !Gem.source_index.search(gem).empty?
+  end
+
+  ##
+  # Find the full path to the executable for gem +name+.  If the +exec_name+
+  # is not given, the gem's default_executable is chosen, otherwise the
+  # specifed executable's path is returned.  +version_requirements+ allows you
+  # to specify specific gem versions.
+
+  def self.bin_path(name, exec_name = nil, *version_requirements)
+    version_requirements = Gem::Requirement.default if
+      version_requirements.empty?
+    spec = Gem.source_index.find_name(name, version_requirements).last
+
+    raise Gem::GemNotFoundException,
+          "can't find gem #{name} (#{version_requirements})" unless spec
+
+    exec_name ||= spec.default_executable
+
+    unless exec_name
+      msg = "no default executable for #{spec.full_name}"
+      raise Gem::Exception, msg
+    end
+
+    unless spec.executables.include? exec_name
+      msg = "can't find executable #{exec_name} for #{spec.full_name}"
+      raise Gem::Exception, msg
+    end
+
+    File.join(spec.full_gem_path, spec.bindir, exec_name)
+  end
+
+  ##
+  # The mode needed to read a file as straight binary.
+
+  def self.binary_mode
+    @binary_mode ||= RUBY_VERSION > '1.9' ? 'rb:ascii-8bit' : 'rb'
+  end
+
+  ##
+  # The path where gem executables are to be installed.
+
+  def self.bindir(install_dir=Gem.dir)
+    return File.join(install_dir, 'bin') unless
+      install_dir.to_s == Gem.default_dir
+    Gem.default_bindir
+  end
+
+  ##
+  # Reset the +dir+ and +path+ values.  The next time +dir+ or +path+
+  # is requested, the values will be calculated from scratch.  This is
+  # mainly used by the unit tests to provide test isolation.
+
+  def self.clear_paths
+    @gem_home = nil
+    @gem_path = nil
+    @user_home = nil
+
+    @@source_index = nil
+
+    MUTEX.synchronize do
+      @searcher = nil
+    end
+  end
+
+  ##
+  # The path to standard location of the user's .gemrc file.
+
+  def self.config_file
+    File.join Gem.user_home, '.gemrc'
+  end
+
+  ##
+  # The standard configuration object for gems.
+
+  def self.configuration
+    @configuration ||= Gem::ConfigFile.new []
+  end
+
+  ##
+  # Use the given configuration object (which implements the ConfigFile
+  # protocol) as the standard configuration object.
+
+  def self.configuration=(config)
+    @configuration = config
+  end
+
+  ##
+  # The path the the data directory specified by the gem name.  If the
+  # package is not available as a gem, return nil.
+
+  def self.datadir(gem_name)
+    spec = @loaded_specs[gem_name]
+    return nil if spec.nil?
+    File.join(spec.full_gem_path, 'data', gem_name)
+  end
+
+  ##
+  # A Zlib::Deflate.deflate wrapper
+
+  def self.deflate(data)
+    require 'zlib'
+    Zlib::Deflate.deflate data
+  end
+
+  ##
+  # The path where gems are to be installed.
+
+  def self.dir
+    @gem_home ||= nil
+    set_home(ENV['GEM_HOME'] || Gem.configuration.home || default_dir) unless @gem_home
+    @gem_home
+  end
+
+  ##
+  # Expand each partial gem path with each of the required paths specified
+  # in the Gem spec.  Each expanded path is yielded.
+
+  def self.each_load_path(partials)
+    partials.each do |gp|
+      base = File.basename(gp)
+      specfn = File.join(dir, "specifications", base + ".gemspec")
+      if File.exist?(specfn)
+        spec = eval(File.read(specfn))
+        spec.require_paths.each do |rp|
+          yield(File.join(gp, rp))
+        end
+      else
+        filename = File.join(gp, 'lib')
+        yield(filename) if File.exist?(filename)
+      end
+    end
+  end
+
+  private_class_method :each_load_path
+
+  ##
+  # Quietly ensure the named Gem directory contains all the proper
+  # subdirectories.  If we can't create a directory due to a permission
+  # problem, then we will silently continue.
+
+  def self.ensure_gem_subdirectories(gemdir)
+    require 'fileutils'
+
+    Gem::DIRECTORIES.each do |filename|
+      fn = File.join gemdir, filename
+      FileUtils.mkdir_p fn rescue nil unless File.exist? fn
+    end
+  end
+
+  ##
+  # Returns a list of paths matching +file+ that can be used by a gem to pick
+  # up features from other gems.  For example:
+  #
+  #   Gem.find_files('rdoc/discover').each do |path| load path end
+  #
+  # find_files search $LOAD_PATH for files as well as gems.
+  #
+  # Note that find_files will return all files even if they are from different
+  # versions of the same gem.
+
+  def self.find_files(path)
+    load_path_files = $LOAD_PATH.map do |load_path|
+      files = Dir["#{File.expand_path path, load_path}#{Gem.suffix_pattern}"]
+
+      files.select do |load_path_file|
+        File.file? load_path_file.untaint
+      end
+    end.flatten
+
+    specs = searcher.find_all path
+
+    specs_files = specs.map do |spec|
+      searcher.matching_files spec, path
+    end.flatten
+
+    (load_path_files + specs_files).flatten.uniq
+  end
+
+  ##
+  # Finds the user's home directory.
+  #--
+  # Some comments from the ruby-talk list regarding finding the home
+  # directory:
+  #
+  #   I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
+  #   to be depending on HOME in those code samples. I propose that
+  #   it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
+  #   least on Win32).
+
+  def self.find_home
+    unless RUBY_VERSION > '1.9' then
+      ['HOME', 'USERPROFILE'].each do |homekey|
+        return ENV[homekey] if ENV[homekey]
+      end
+
+      if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
+        return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
+      end
+    end
+
+    File.expand_path "~"
+  rescue
+    if File::ALT_SEPARATOR then
+      "C:/"
+    else
+      "/"
+    end
+  end
+
+  private_class_method :find_home
+
+  ##
+  # Zlib::GzipReader wrapper that unzips +data+.
+
+  def self.gunzip(data)
+    require 'stringio'
+    require 'zlib'
+    data = StringIO.new data
+
+    Zlib::GzipReader.new(data).read
+  end
+
+  ##
+  # Zlib::GzipWriter wrapper that zips +data+.
+
+  def self.gzip(data)
+    require 'stringio'
+    require 'zlib'
+    zipped = StringIO.new
+
+    Zlib::GzipWriter.wrap zipped do |io| io.write data end
+
+    zipped.string
+  end
+
+  ##
+  # A Zlib::Inflate#inflate wrapper
+
+  def self.inflate(data)
+    require 'zlib'
+    Zlib::Inflate.inflate data
+  end
+
+  ##
+  # Return a list of all possible load paths for the latest version for all
+  # gems in the Gem installation.
+
+  def self.latest_load_paths
+    result = []
+
+    Gem.path.each do |gemdir|
+      each_load_path(latest_partials(gemdir)) do |load_path|
+        result << load_path
+      end
+    end
+
+    result
+  end
+
+  ##
+  # Return only the latest partial paths in the given +gemdir+.
+
+  def self.latest_partials(gemdir)
+    latest = {}
+    all_partials(gemdir).each do |gp|
+      base = File.basename(gp)
+      if base =~ /(.*)-((\d+\.)*\d+)/ then
+        name, version = $1, $2
+        ver = Gem::Version.new(version)
+        if latest[name].nil? || ver > latest[name][0]
+          latest[name] = [ver, gp]
+        end
+      end
+    end
+    latest.collect { |k,v| v[1] }
+  end
+
+  private_class_method :latest_partials
+
+  ##
+  # The index to insert activated gem paths into the $LOAD_PATH.
+  #
+  # Defaults to the site lib directory unless gem_prelude.rb has loaded paths,
+  # then it inserts the activated gem's paths before the gem_prelude.rb paths
+  # so you can override the gem_prelude.rb default $LOAD_PATH paths.
+
+  def self.load_path_insert_index
+    index = $LOAD_PATH.index ConfigMap[:sitelibdir]
+
+    $LOAD_PATH.each_with_index do |path, i|
+      if path.instance_variables.include?(:@gem_prelude_index) or
+        path.instance_variables.include?('@gem_prelude_index') then
+        index = i
+        break
+      end
+    end
+
+    index
+  end
+
+  ##
+  # The file name and line number of the caller of the caller of this method.
+
+  def self.location_of_caller
+    caller[1] =~ /(.*?):(\d+).*?$/i
+    file = $1
+    lineno = $2.to_i
+
+    [file, lineno]
+  end
+
+  ##
+  # The version of the Marshal format for your Ruby.
+
+  def self.marshal_version
+    "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
+  end
+
+  ##
+  # Array of paths to search for Gems.
+
+  def self.path
+    @gem_path ||= nil
+
+    unless @gem_path then
+      paths = [ENV['GEM_PATH'] || Gem.configuration.path || default_path]
+
+      if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
+        paths << APPLE_GEM_HOME
+      end
+
+      set_paths paths.compact.join(File::PATH_SEPARATOR)
+    end
+
+    @gem_path
+  end
+
+  ##
+  # Set array of platforms this RubyGems supports (primarily for testing).
+
+  def self.platforms=(platforms)
+    @platforms = platforms
+  end
+
+  ##
+  # Array of platforms this RubyGems supports.
+
+  def self.platforms
+    @platforms ||= []
+    if @platforms.empty?
+      @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
+    end
+    @platforms
+  end
+
+  ##
+  # Adds a post-install hook that will be passed an Gem::Installer instance
+  # when Gem::Installer#install is called
+
+  def self.post_install(&hook)
+    @post_install_hooks << hook
+  end
+
+  ##
+  # Adds a post-uninstall hook that will be passed a Gem::Uninstaller instance
+  # and the spec that was uninstalled when Gem::Uninstaller#uninstall is
+  # called
+
+  def self.post_uninstall(&hook)
+    @post_uninstall_hooks << hook
+  end
+
+  ##
+  # Adds a pre-install hook that will be passed an Gem::Installer instance
+  # when Gem::Installer#install is called
+
+  def self.pre_install(&hook)
+    @pre_install_hooks << hook
+  end
+
+  ##
+  # Adds a pre-uninstall hook that will be passed an Gem::Uninstaller instance
+  # and the spec that will be uninstalled when Gem::Uninstaller#uninstall is
+  # called
+
+  def self.pre_uninstall(&hook)
+    @pre_uninstall_hooks << hook
+  end
+
+  ##
+  # The directory prefix this RubyGems was installed at.
+
+  def self.prefix
+    prefix = File.dirname File.expand_path(__FILE__)
+
+    if File.dirname(prefix) == File.expand_path(ConfigMap[:sitelibdir]) or
+       File.dirname(prefix) == File.expand_path(ConfigMap[:libdir]) or
+       'lib' != File.basename(prefix) then
+      nil
+    else
+      File.dirname prefix
+    end
+  end
+
+  ##
+  # Promotes the load paths of the +gem_name+ over the load paths of
+  # +over_name+.  Useful for allowing one gem to override features in another
+  # using #find_files.
+
+  def self.promote_load_path(gem_name, over_name)
+    gem = Gem.loaded_specs[gem_name]
+    over = Gem.loaded_specs[over_name]
+
+    raise ArgumentError, "gem #{gem_name} is not activated" if gem.nil?
+    raise ArgumentError, "gem #{over_name} is not activated" if over.nil?
+
+    last_gem_path = File.join gem.full_gem_path, gem.require_paths.last
+
+    over_paths = over.require_paths.map do |path|
+      File.join over.full_gem_path, path
+    end
+
+    over_paths.each do |path|
+      $LOAD_PATH.delete path
+    end
+
+    gem = $LOAD_PATH.index(last_gem_path) + 1
+
+    $LOAD_PATH.insert(gem, *over_paths)
+  end
+
+  ##
+  # Refresh source_index from disk and clear searcher.
+
+  def self.refresh
+    source_index.refresh!
+
+    MUTEX.synchronize do
+      @searcher = nil
+    end
+  end
+
+  ##
+  # Safely read a file in binary mode on all platforms.
+
+  def self.read_binary(path)
+    File.open path, binary_mode do |f| f.read end
+  end
+
+  ##
+  # Report a load error during activation.  The message of load error
+  # depends on whether it was a version mismatch or if there are not gems of
+  # any version by the requested name.
+
+  def self.report_activate_error(gem)
+    matches = Gem.source_index.find_name(gem.name)
+
+    if matches.empty? then
+      error = Gem::LoadError.new(
+          "Could not find RubyGem #{gem.name} (#{gem.version_requirements})\n")
+    else
+      error = Gem::LoadError.new(
+          "RubyGem version error: " +
+          "#{gem.name}(#{matches.first.version} not #{gem.version_requirements})\n")
+    end
+
+    error.name = gem.name
+    error.version_requirement = gem.version_requirements
+    raise error
+  end
+
+  private_class_method :report_activate_error
+
+  ##
+  # Full path to +libfile+ in +gemname+.  Searches for the latest gem unless
+  # +requirements+ is given.
+
+  def self.required_location(gemname, libfile, *requirements)
+    requirements = Gem::Requirement.default if requirements.empty?
+
+    matches = Gem.source_index.find_name gemname, requirements
+
+    return nil if matches.empty?
+
+    spec = matches.last
+    spec.require_paths.each do |path|
+      result = File.join spec.full_gem_path, path, libfile
+      return result if File.exist? result
+    end
+
+    nil
+  end
+
+  ##
+  # The path to the running Ruby interpreter.
+
+  def self.ruby
+    if @ruby.nil? then
+      @ruby = File.join(ConfigMap[:bindir],
+                        ConfigMap[:ruby_install_name])
+      @ruby << ConfigMap[:EXEEXT]
+
+      # escape string in case path to ruby executable contain spaces.
+      @ruby.sub!(/.*\s.*/m, '"\&"')
+    end
+
+    @ruby
+  end
+
+  ##
+  # A Gem::Version for the currently running ruby.
+
+  def self.ruby_version
+    return @ruby_version if defined? @ruby_version
+    version = RUBY_VERSION.dup
+
+    if defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1 then
+      version << ".#{RUBY_PATCHLEVEL}"
+    elsif defined?(RUBY_REVISION) then
+      version << ".dev.#{RUBY_REVISION}"
+    end
+
+    @ruby_version = Gem::Version.new version
+  end
+
+  ##
+  # The GemPathSearcher object used to search for matching installed gems.
+
+  def self.searcher
+    MUTEX.synchronize do
+      @searcher ||= Gem::GemPathSearcher.new
+    end
+  end
+
+  ##
+  # Set the Gem home directory (as reported by Gem.dir).
+
+  def self.set_home(home)
+    home = home.gsub File::ALT_SEPARATOR, File::SEPARATOR if File::ALT_SEPARATOR
+    @gem_home = home
+  end
+
+  private_class_method :set_home
+
+  ##
+  # Set the Gem search path (as reported by Gem.path).
+
+  def self.set_paths(gpaths)
+    if gpaths
+      @gem_path = gpaths.split(File::PATH_SEPARATOR)
+
+      if File::ALT_SEPARATOR then
+        @gem_path.map! do |path|
+          path.gsub File::ALT_SEPARATOR, File::SEPARATOR
+        end
+      end
+
+      @gem_path << Gem.dir
+    else
+      # TODO: should this be Gem.default_path instead?
+      @gem_path = [Gem.dir]
+    end
+
+    @gem_path.uniq!
+  end
+
+  private_class_method :set_paths
+
+  ##
+  # Returns the Gem::SourceIndex of specifications that are in the Gem.path
+
+  def self.source_index
+    @@source_index ||= SourceIndex.from_installed_gems
+  end
+
+  ##
+  # Returns an Array of sources to fetch remote gems from.  If the sources
+  # list is empty, attempts to load the "sources" gem, then uses
+  # default_sources if it is not installed.
+
+  def self.sources
+    if @sources.empty? then
+      begin
+        gem 'sources', '> 0.0.1'
+        require 'sources'
+      rescue LoadError
+        @sources = default_sources
+      end
+    end
+
+    @sources
+  end
+
+  ##
+  # Need to be able to set the sources without calling
+  # Gem.sources.replace since that would cause an infinite loop.
+
+  def self.sources=(new_sources)
+    @sources = new_sources
+  end
+
+  ##
+  # Glob pattern for require-able path suffixes.
+
+  def self.suffix_pattern
+    @suffix_pattern ||= "{#{suffixes.join(',')}}"
+  end
+
+  ##
+  # Suffixes for require-able paths.
+
+  def self.suffixes
+    ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
+  end
+
+  ##
+  # Prints the amount of time the supplied block takes to run using the debug
+  # UI output.
+
+  def self.time(msg, width = 0, display = Gem.configuration.verbose)
+    now = Time.now
+
+    value = yield
+
+    elapsed = Time.now - now
+
+    ui.say "%2$*1$s: %3$3.3fs" % [-width, msg, elapsed] if display
+
+    value
+  end
+
+  ##
+  # Lazily loads DefaultUserInteraction and returns the default UI.
+
+  def self.ui
+    require 'rubygems/user_interaction'
+
+    Gem::DefaultUserInteraction.ui
+  end
+
+  ##
+  # Use the +home+ and +paths+ values for Gem.dir and Gem.path.  Used mainly
+  # by the unit tests to provide environment isolation.
+
+  def self.use_paths(home, paths=[])
+    clear_paths
+    set_home(home) if home
+    set_paths(paths.join(File::PATH_SEPARATOR)) if paths
+  end
+
+  ##
+  # The home directory for the user.
+
+  def self.user_home
+    @user_home ||= find_home
+  end
+
+  ##
+  # Is this a windows platform?
+
+  def self.win_platform?
+    if @@win_platform.nil? then
+      @@win_platform = !!WIN_PATTERNS.find { |r| RUBY_PLATFORM =~ r }
+    end
+
+    @@win_platform
+  end
+
+  class << self
+
+    ##
+    # Hash of loaded Gem::Specification keyed by name
+
+    attr_reader :loaded_specs
+
+    ##
+    # The list of hooks to be run before Gem::Install#install does any work
+
+    attr_reader :post_install_hooks
+
+    ##
+    # The list of hooks to be run before Gem::Uninstall#uninstall does any
+    # work
+
+    attr_reader :post_uninstall_hooks
+
+    ##
+    # The list of hooks to be run after Gem::Install#install is finished
+
+    attr_reader :pre_install_hooks
+
+    ##
+    # The list of hooks to be run after Gem::Uninstall#uninstall is finished
+
+    attr_reader :pre_uninstall_hooks
+
+    # :stopdoc:
+
+    alias cache source_index # an alias for the old name
+
+    # :startdoc:
+
+  end
+
+  ##
+  # Location of Marshal quick gemspecs on remote repositories
+
+  MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
+
+  ##
+  # Location of legacy YAML quick gemspecs on remote repositories
+
+  YAML_SPEC_DIR = 'quick/'
+
+end
+
+module Kernel
+
+  ##
+  # Use Kernel#gem to activate a specific version of +gem_name+.
+  #
+  # +version_requirements+ is a list of version requirements that the
+  # specified gem must match, most commonly "= example.version.number".  See
+  # Gem::Requirement for how to specify a version requirement.
+  #
+  # If you will be activating the latest version of a gem, there is no need to
+  # call Kernel#gem, Kernel#require will do the right thing for you.
+  #
+  # Kernel#gem returns true if the gem was activated, otherwise false.  If the
+  # gem could not be found, didn't match the version requirements, or a
+  # different version was already activated, an exception will be raised.
+  #
+  # Kernel#gem should be called *before* any require statements (otherwise
+  # RubyGems may load a conflicting library version).
+  #
+  # In older RubyGems versions, the environment variable GEM_SKIP could be
+  # used to skip activation of specified gems, for example to test out changes
+  # that haven't been installed yet.  Now RubyGems defers to -I and the
+  # RUBYLIB environment variable to skip activation of a gem.
+  #
+  # Example:
+  #
+  #   GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
+
+  def gem(gem_name, *version_requirements) # :doc:
+    skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
+    raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
+    Gem.activate(gem_name, *version_requirements)
+  end
+
+  private :gem
+
+end
+
+##
+# Return the path to the data directory associated with the named package.  If
+# the package is loaded as a gem, return the gem specific data directory.
+# Otherwise return a path to the share area as define by
+# "#{ConfigMap[:datadir]}/#{package_name}".
+
+def RbConfig.datadir(package_name)
+  Gem.datadir(package_name) ||
+    File.join(Gem::ConfigMap[:datadir], package_name)
+end
+
+require 'rubygems/exceptions'
+require 'rubygems/version'
+require 'rubygems/requirement'
+require 'rubygems/dependency'
+require 'rubygems/gem_path_searcher'    # Needed for Kernel#gem
+require 'rubygems/source_index'         # Needed for Kernel#gem
+require 'rubygems/platform'
+require 'rubygems/builder'              # HACK: Needed for rake's package task.
+
+begin
+  require 'rubygems/defaults/operating_system'
+rescue LoadError
+end
+
+if defined?(RUBY_ENGINE) then
+  begin
+    require "rubygems/defaults/#{RUBY_ENGINE}"
+  rescue LoadError
+  end
+end
+
+require 'rubygems/config_file'
+
+if RUBY_VERSION < '1.9' then
+  require 'rubygems/custom_require'
+end
+
+Gem.clear_paths
+
+plugins = Gem.find_files 'rubygems_plugin'
+
+plugins.each do |plugin|
+  begin
+    load plugin
+  rescue => e
+    warn "error loading #{plugin.inspect}: #{e.message} (#{e.class})"
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/lib/ubygems.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/lib/ubygems.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/lib/ubygems.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,10 @@
+# This file allows for the running of rubygems with a nice
+# command line look-and-feel: ruby -rubygems foo.rb
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+
+require 'rubygems'

Added: MacRuby/trunk/test/libs/rubygems/pkgs/sources/lib/sources.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/pkgs/sources/lib/sources.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/pkgs/sources/lib/sources.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,3 @@
+module Gem
+  @sources = %w[http://gems.rubyforge.org]
+end

Added: MacRuby/trunk/test/libs/rubygems/pkgs/sources/sources.gemspec
===================================================================
--- MacRuby/trunk/test/libs/rubygems/pkgs/sources/sources.gemspec	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/pkgs/sources/sources.gemspec	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,14 @@
+module Gem
+  def self.sources_spec
+    @sources_spec ||= Gem::Specification.new do |s|
+      s.name = 'sources'
+      s.version = '0.0.2'
+      s.platform = Gem::Platform::RUBY
+      s.required_rubygems_version = '> 0.9.4.3'
+      s.summary = "This package provides download sources for remote gem installation"
+      s.files = %w[lib/sources.rb]
+      s.require_path = 'lib'
+    end
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/setup.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/setup.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/setup.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,39 @@
+#--
+# Copyright 2006, 2007 by Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel
+# and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+# Make sure rubygems isn't already loaded.
+if ENV['RUBYOPT'] and defined? Gem then
+  ENV.delete 'RUBYOPT'
+
+  require 'rbconfig'
+  config = defined?(RbConfig) ? RbConfig : Config
+
+  ruby = File.join config::CONFIG['bindir'], config::CONFIG['ruby_install_name']
+  ruby << config::CONFIG['EXEEXT']
+
+  exec(ruby, 'setup.rb', *ARGV)
+end
+
+Dir.chdir File.dirname(__FILE__)
+
+$:.unshift 'lib'
+require 'rubygems'
+require 'rubygems/gem_runner'
+require 'rubygems/exceptions'
+
+Gem::CommandManager.instance.register_command :setup
+
+args = ARGV.clone
+
+args.unshift 'setup'
+
+begin
+  Gem::GemRunner.new.run args
+rescue Gem::SystemExitException => e
+  exit e.exit_code
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/bogussources.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/bogussources.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/bogussources.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,8 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+Gem.use_paths("test/mock/gems")

Added: MacRuby/trunk/test/libs/rubygems/test/data/gem-private_key.pem
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/data/gem-private_key.pem	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/data/gem-private_key.pem	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAz0tTOtsJuHDKAEXrQx0f6DUEzBEUTSLR1fk0iEHsY9rDCQxm
+sw5Bf2UnVhdD03B4/XzIK+pat2CMQc37/vLIBuVgS7g/fzatGiM0m5rAHtycr0XU
+8Ek6zjx4iSv70OLjybY+/utHCEc838awGDMCFR21jYxgATPVwqAIyasvwbKh/Vhw
+uErFPqT9G8BKTHsaX+H+ADIRH001OmWkjB6EyjF05114kNMa0+2C7daV9hoBL3md
+hCt6zOGcapl/9LkGxhcNEUB/So16V1ZQldg9macGyWktyNTSfctlF+f8okAmicG3
+XIwaW8UTmjFCmvDs/h1R/uKpe2IOHz87n29d2QIDAQABAoIBAQCR6n/nyg+JmTtX
+/d+hGns/RTLfQpZ7xarXZ9gmoeD4WSE42VXhbIOGXXnXDAFecKl6Jb/xycGZm4if
+OZPM3rEWyZeDNWrc7WvkHiwF7GSYVMqmRg2iJqoSSla+mAtl+pBFiNfHMW6K0Tp0
+erOyFRW+L2+A9/MMZaRun6AP9URkn0jz2kwmMFf+6szmzVn6fPFzZDRI+hEeaDmi
+LBzSrfrddrIBX+xGEoBj6RmfnKBCSUVSSxOauYjd4mVjVYxvMH4SV1hXDUS5GPl5
+MbCiBb7bpNIg/8ljMoRrQiqk0XwwS7MaCqPtMhUtpSmC/zSjAfmoN7AOc/Xh69cQ
+OCMNZH9BAoGBAPBlsuuU6fg0gVTKDdR12jHx03uRRt8/nPxHnpJkZCIh9XKh1LtY
+bkumi9HZpp3mzDiaGg/rwfCwNckKx8NLhICLgkric6ClrKftxTu6C8tBAb5YDi6u
+74KYnV8lMY/unzBtIloPgM3uluS292POmrWZpKwhvHLD71MewzMor5HFAoGBANy/
+mwsBs8i3Gzk8Twjq8effhPpE7kpxhC7bhwmjX3q41EjQWDT8M6xb1P9dRSsCIebi
+kqP1yhl27dJpA8r5WqE/z89xhBvObAGRv41eXxOI0LaH2k5lJQrUeSC+51dy+BEB
+T3GXD4C5ezZHQ8Wz/oL73uikrfhD+AqOZT2YbMEFAoGBAJvWEWpOGm3f+4bvhI+Z
+5lxCG4oa3wqRvj58XvsfQRovUWGCLtlTtgwsZq8enLf3iaOXohV4Czzvva4Z4u1i
+4v5BcbEBo1scixRBOn5BWKvl9C9j/a2dkX3jWQD4p2xaj69gz8f6DNFyPTb+tNhq
+cjgO5YUASZ1MDrSfWIKteULRAoGAZkZv8x2KyofrmQ0UITGZerDYz4t4TA1kDMGx
+QwnqhtVzpXjCJWpkFotFmDsCfPaz9mErR8PtKvcrIL1/AF+fWe5Sve3+I1P0PpXk
+hf8fVdGhwbAXuRKrouTmagGI9b9Sp65PvHUcvasyJufFwqeuV8mScX87CzeSiHGI
+/ozMdnECgYEAq4+losrhe0DEmiC9zVPvwRXjbSixDsSJxHfOcqIsZqhUgBiZ4TJD
+SrkuukrMZib6BAD+PtCJS1TBbJyyvL3QecizhHSIh3ZnT0HnaRPatLEYmU65+3kE
+kTqL4ik92bJnnWowy677sydl1lzBJDVa9ZlTs7BFSd8y/0DZaUxGg2I=
+-----END RSA PRIVATE KEY-----

Added: MacRuby/trunk/test/libs/rubygems/test/data/gem-public_cert.pem
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/data/gem-public_cert.pem	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/data/gem-public_cert.pem	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMREwDwYDVQQDDAhydWJ5
+Z2VtczEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxEzARBgoJkiaJk/IsZAEZFgNj
+b20wHhcNMDcwODAyMDMyNTQyWhcNMDgwODAxMDMyNTQyWjBBMREwDwYDVQQDDAhy
+dWJ5Z2VtczEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxEzARBgoJkiaJk/IsZAEZ
+FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPS1M62wm4cMoA
+RetDHR/oNQTMERRNItHV+TSIQexj2sMJDGazDkF/ZSdWF0PTcHj9fMgr6lq3YIxB
+zfv+8sgG5WBLuD9/Nq0aIzSbmsAe3JyvRdTwSTrOPHiJK/vQ4uPJtj7+60cIRzzf
+xrAYMwIVHbWNjGABM9XCoAjJqy/BsqH9WHC4SsU+pP0bwEpMexpf4f4AMhEfTTU6
+ZaSMHoTKMXTnXXiQ0xrT7YLt1pX2GgEveZ2EK3rM4ZxqmX/0uQbGFw0RQH9KjXpX
+VlCV2D2ZpwbJaS3I1NJ9y2UX5/yiQCaJwbdcjBpbxROaMUKa8Oz+HVH+4ql7Yg4f
+Pzufb13ZAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
+BBRYTAoj4cn8CWZMHFnHGQgoO5jyFTANBgkqhkiG9w0BAQUFAAOCAQEATRrJC05l
+dOmx67Sy3bU+AVXkOr7B9nn2Myqo9uSIAncPoElN6aHr/Q8wOOjtok4r0JcHPe1e
+eotDCZUE1Jkl13Tpv26rOfOOUHtGlyAIAtpsUGOraaJkSut4WKLr1/KckyAAEtgP
+c13A0s0mEiWFRuYxIdEi54561pTT2qQBE/DUPGoYD5rUg9XYAlSovMMwG99Oca7L
+cI6vCymr1bzzddExoywBNOy0fbBT62I3ICBGbH5yOVVKVmlxeo2Zp10FCj0kDrnq
+OuMJSDr5I2XPYqoC+W4YSbwn55o2jGIUX1lOq2Hvj4tFgSxlnJZn0tUhBfR3gSOn
+IFnrqu8PlZsLFw==
+-----END CERTIFICATE-----

Added: MacRuby/trunk/test/libs/rubygems/test/fake_certlib/openssl.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/fake_certlib/openssl.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/fake_certlib/openssl.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,7 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+raise LoadError, "no such file to load -- openssl"

Added: MacRuby/trunk/test/libs/rubygems/test/functional.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/functional.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/functional.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,99 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+require 'minitest/unit'
+require 'test/insure_session'
+require 'rubygems/format'
+require 'rubygems/command_manager'
+
+class FunctionalTest < MiniTest::Unit::TestCase
+
+  def setup
+    @gem_path = File.expand_path("bin/gem")
+    lib_path = File.expand_path("lib")
+    @ruby_options = "-I#{lib_path} -I."
+    @verbose = false
+  end
+
+  def test_gem_help_options
+    gem_nossl 'help options'
+    assert_match(/Usage:/, @out, @err)
+    assert_status
+  end
+
+  def test_gem_help_commands
+    gem_nossl 'help commands'
+    assert_match(/gem install/, @out)
+    assert_status
+  end
+
+  def test_gem_no_args_shows_help
+    gem_nossl
+    assert_match(/Usage:/, @out)
+    assert_status 1
+  end
+
+  # This test is disabled because of the insanely long time it takes
+  # to time out.
+  def xtest_bogus_source_hoses_up_remote_install_but_gem_command_gives_decent_error_message
+    @ruby_options << " -rtest/bogussources"
+    gem_nossl "install asdf --remote"
+    assert_match(/error/im, @err)
+    assert_status 1
+  end
+
+  def test_all_command_helps
+    mgr = Gem::CommandManager.new
+    mgr.command_names.each do |cmdname|
+      gem_nossl "help #{cmdname}"
+      assert_match(/Usage: gem #{cmdname}/, @out,
+                   "should see help for #{cmdname}")
+    end
+  end
+
+  # :section: Help Methods
+
+  # Run a gem command without the SSL library.
+  def gem_nossl(options="")
+    old_options = @ruby_options.dup
+    @ruby_options << " -Itest/fake_certlib"
+    gem(options)
+  ensure
+    @ruby_options = old_options
+  end
+
+  # Run a gem command with the SSL library.
+  def gem_withssl(options="")
+    gem(options)
+  end
+
+  # Run a gem command for the functional test.
+  def gem(options="")
+    shell = Session::Shell.new
+    options = options + " --config-file missing_file" if options !~ /--config-file/
+    command = "#{Gem.ruby} #{@ruby_options} #{@gem_path} #{options}"
+    puts "\n\nCOMMAND: [#{command}]" if @verbose
+    @out, @err = shell.execute command
+    @status = shell.exit_status
+    puts "STATUS:  [#{@status}]" if @verbose
+    puts "OUTPUT:  [#{@out}]" if @verbose
+    puts "ERROR:   [#{@err}]" if @verbose
+    puts "PWD:     [#{Dir.pwd}]" if @verbose
+    shell.close
+  end
+
+  private
+
+  def assert_status(expected_status=0)
+    assert_equal expected_status, @status
+  end
+
+end
+
+MiniTest::Unit.autorun
+

Added: MacRuby/trunk/test/libs/rubygems/test/gem_installer_test_case.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/gem_installer_test_case.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/gem_installer_test_case.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,97 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/installer'
+
+class Gem::Installer
+  attr_accessor :gem_dir
+
+  attr_writer :format
+  attr_writer :gem_home
+  attr_writer :env_shebang
+  attr_writer :ignore_dependencies
+  attr_writer :format_executable
+  attr_writer :security_policy
+  attr_writer :spec
+  attr_writer :wrappers
+end
+
+class GemInstallerTestCase < RubyGemTestCase
+
+  def setup
+    super
+
+    @spec = quick_gem 'a'
+    @gem = File.join @tempdir, @spec.file_name
+
+    @installer = util_installer @spec, @gem, @gemhome
+
+    @user_spec = quick_gem 'b'
+    @user_gem = File.join @tempdir, @user_spec.file_name
+
+    @user_installer = util_installer @user_spec, @user_gem, Gem.user_dir
+    @user_installer.gem_dir = File.join(Gem.user_dir, 'gems',
+                                        @user_spec.full_name)
+  end
+
+  def util_gem_bindir(version = '2')
+    File.join util_gem_dir(version), "bin"
+  end
+
+  def util_gem_dir(version = '2')
+    File.join @gemhome, "gems", "a-#{version}" # HACK
+  end
+
+  def util_inst_bindir
+    File.join @gemhome, "bin"
+  end
+
+  def util_make_exec(version = '2', shebang = "#!/usr/bin/ruby")
+    @spec.executables = ["my_exec"]
+
+    FileUtils.mkdir_p util_gem_bindir(version)
+    exec_path = File.join util_gem_bindir(version), "my_exec"
+    File.open exec_path, 'w' do |f|
+      f.puts shebang
+    end
+  end
+
+  def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic
+    @spec.files = File.join('lib', 'code.rb')
+    @spec.executables << 'executable'
+    @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb')
+
+    Dir.chdir @tempdir do
+      FileUtils.mkdir_p 'bin'
+      FileUtils.mkdir_p 'lib'
+      FileUtils.mkdir_p File.join('ext', 'a')
+      File.open File.join('bin', 'executable'), 'w' do |f| f.puts '1' end
+      File.open File.join('lib', 'code.rb'), 'w' do |f| f.puts '1' end
+      File.open File.join('ext', 'a', 'mkrf_conf.rb'), 'w' do |f|
+        f << <<-EOF
+          File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end
+        EOF
+      end
+
+      use_ui ui do
+        FileUtils.rm @gem
+        Gem::Builder.new(@spec).build
+      end
+    end
+
+    @installer = Gem::Installer.new @gem
+  end
+
+  def util_installer(spec, gem_path, gem_home)
+    util_build_gem spec
+    FileUtils.mv File.join(@gemhome, 'cache', spec.file_name),
+                 @tempdir
+
+    installer = Gem::Installer.new gem_path
+    installer.gem_dir = util_gem_dir
+    installer.gem_home = gem_home
+    installer.spec = spec
+
+    installer
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/gem_package_tar_test_case.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/gem_package_tar_test_case.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/gem_package_tar_test_case.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,132 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/package'
+
+class TarTestCase < RubyGemTestCase
+
+  def ASCIIZ(str, length)
+    str + "\0" * (length - str.length)
+  end
+
+  def SP(s)
+    s + " "
+  end
+
+  def SP_Z(s)
+    s + " \0"
+  end
+
+  def Z(s)
+    s + "\0"
+  end
+
+  def assert_headers_equal(expected, actual)
+    expected = expected.to_s unless String === expected
+    actual = actual.to_s unless String === actual
+
+    fields = %w[
+      name 100
+      mode 8
+      uid 8
+      gid 8
+      size 12
+      mtime 12
+      checksum 8
+      typeflag 1
+      linkname 100
+      magic 6
+      version 2
+      uname 32 
+      gname 32
+      devmajor 8
+      devminor 8
+      prefix 155
+    ]
+
+    offset = 0
+
+    until fields.empty? do
+      name = fields.shift
+      length = fields.shift.to_i
+
+      if name == "checksum" then
+        chksum_off = offset
+        offset += length
+        next
+      end
+
+      assert_equal expected[offset, length], actual[offset, length], 
+                   "Field #{name} of the tar header differs."
+
+      offset += length
+    end
+
+    assert_equal expected[chksum_off, 8], actual[chksum_off, 8]
+  end
+
+  def calc_checksum(header)
+    sum = header.unpack("C*").inject{|s,a| s + a}
+    SP(Z(to_oct(sum, 6)))
+  end
+
+  def header(type, fname, dname, length, mode, checksum = nil)
+    checksum ||= " " * 8
+
+    arr = [                  # struct tarfile_entry_posix
+      ASCIIZ(fname, 100),    # char name[100];     ASCII + (Z unless filled)
+      Z(to_oct(mode, 7)),    # char mode[8];       0 padded, octal null
+      Z(to_oct(0, 7)),       # char uid[8];        ditto
+      Z(to_oct(0, 7)),       # char gid[8];        ditto
+      Z(to_oct(length, 11)), # char size[12];      0 padded, octal, null
+      Z(to_oct(0, 11)),      # char mtime[12];     0 padded, octal, null
+      checksum,              # char checksum[8];   0 padded, octal, null, space
+      type,                  # char typeflag[1];   file: "0"  dir: "5"
+      "\0" * 100,            # char linkname[100]; ASCII + (Z unless filled)
+      "ustar\0",             # char magic[6];      "ustar\0"
+      "00",                  # char version[2];    "00"
+      ASCIIZ("wheel", 32),   # char uname[32];     ASCIIZ
+      ASCIIZ("wheel", 32),   # char gname[32];     ASCIIZ
+      Z(to_oct(0, 7)),       # char devmajor[8];   0 padded, octal, null
+      Z(to_oct(0, 7)),       # char devminor[8];   0 padded, octal, null
+      ASCIIZ(dname, 155)     # char prefix[155];   ASCII + (Z unless filled)
+    ]
+
+    format = "C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155"
+    h = if RUBY_VERSION >= "1.9" then
+          arr.join
+        else
+          arr = arr.join("").split(//).map{|x| x[0]}
+          arr.pack format
+        end
+    ret = h + "\0" * (512 - h.size)
+    assert_equal(512, ret.size)
+    ret
+  end
+
+  def tar_dir_header(name, prefix, mode)
+    h = header("5", name, prefix, 0, mode)
+    checksum = calc_checksum(h)
+    header("5", name, prefix, 0, mode, checksum)
+  end
+
+  def tar_file_header(fname, dname, mode, length)
+    h = header("0", fname, dname, length, mode)
+    checksum = calc_checksum(h)
+    header("0", fname, dname, length, mode, checksum)
+  end
+
+  def to_oct(n, pad_size)
+    "%0#{pad_size}o" % n
+  end
+
+  def util_entry(tar)
+    io = TempIO.new tar
+    header = Gem::Package::TarHeader.from io
+    entry = Gem::Package::TarReader::Entry.new header, io
+  end
+
+  def util_dir_entry
+    util_entry tar_dir_header("foo", "bar", 0)
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/gemutilities.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/gemutilities.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/gemutilities.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,559 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+at_exit { $SAFE = 1 }
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+
+if RUBY_VERSION > '1.9' then
+  Gem::QuickLoader.load_full_rubygems_library
+else
+  require 'rubygems'
+end
+require 'fileutils'
+begin
+  gem 'minitest', '>= 1.3.1'
+  require 'minitest/unit'
+rescue Gem::LoadError
+  warn "Install minitest gem >= 1.3.1"
+  raise
+end
+require 'tmpdir'
+require 'uri'
+require 'rubygems/package'
+require 'rubygems/test_utilities'
+require 'pp'
+
+begin
+  gem 'rdoc'
+rescue Gem::LoadError
+end
+
+require 'rdoc/rdoc'
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
+
+module Gem
+  def self.searcher=(searcher)
+    MUTEX.synchronize do @searcher = searcher end
+  end
+
+  def self.source_index=(si)
+    @@source_index = si
+  end
+
+  def self.win_platform=(val)
+    @@win_platform = val
+  end
+
+  module DefaultUserInteraction
+    @ui = MockGemUi.new
+  end
+end
+
+class RubyGemTestCase < MiniTest::Unit::TestCase
+
+  include Gem::DefaultUserInteraction
+
+  undef_method :default_test if instance_methods.include? 'default_test' or
+                                instance_methods.include? :default_test
+
+  def setup
+    super
+
+    @ui = MockGemUi.new
+    tmpdir = nil
+    Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp
+    @tempdir = File.join tmpdir, "test_rubygems_#{$$}"
+    @tempdir.untaint
+    @gemhome = File.join @tempdir, "gemhome"
+    @gemcache = File.join(@gemhome, "source_cache")
+    @usrcache = File.join(@gemhome, ".gem", "user_cache")
+    @latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
+    @userhome = File.join @tempdir, 'userhome'
+
+    Gem.ensure_gem_subdirectories @gemhome
+
+    @orig_ENV_HOME = ENV['HOME']
+    ENV['HOME'] = @userhome
+    Gem.instance_variable_set :@user_home, nil
+
+    FileUtils.mkdir_p @gemhome
+    FileUtils.mkdir_p @userhome
+
+    ENV['GEMCACHE'] = @usrcache
+    Gem.use_paths(@gemhome)
+    Gem.loaded_specs.clear
+
+    Gem.configuration.verbose = true
+    Gem.configuration.update_sources = true
+
+    @gem_repo = "http://gems.example.com/"
+    @uri = URI.parse @gem_repo
+    Gem.sources.replace [@gem_repo]
+
+    Gem::SpecFetcher.fetcher = nil
+
+    @orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
+    Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:ruby_install_name]
+
+    @orig_arch = Gem::ConfigMap[:arch]
+
+    if win_platform?
+      util_set_arch 'i386-mswin32'
+    else
+      util_set_arch 'i686-darwin8.10.1'
+    end
+
+    @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
+
+    @private_key = File.expand_path File.join(File.dirname(__FILE__),
+                                              'private_key.pem')
+    @public_cert = File.expand_path File.join(File.dirname(__FILE__),
+                                              'public_cert.pem')
+
+    Gem.post_install_hooks.clear
+    Gem.post_uninstall_hooks.clear
+    Gem.pre_install_hooks.clear
+    Gem.pre_uninstall_hooks.clear
+
+    Gem.post_install do |installer|
+      @post_install_hook_arg = installer
+    end
+
+    Gem.post_uninstall do |uninstaller|
+      @post_uninstall_hook_arg = uninstaller
+    end
+
+    Gem.pre_install do |installer|
+      @pre_install_hook_arg = installer
+    end
+
+    Gem.pre_uninstall do |uninstaller|
+      @pre_uninstall_hook_arg = uninstaller
+    end
+  end
+
+  def teardown
+    Gem::ConfigMap[:BASERUBY] = @orig_BASERUBY
+    Gem::ConfigMap[:arch] = @orig_arch
+
+    if defined? Gem::RemoteFetcher then
+      Gem::RemoteFetcher.fetcher = nil
+    end
+
+    FileUtils.rm_rf @tempdir
+
+    ENV.delete 'GEMCACHE'
+    ENV.delete 'GEM_HOME'
+    ENV.delete 'GEM_PATH'
+
+    Gem.clear_paths
+
+    if @orig_ENV_HOME then
+      ENV['HOME'] = @orig_ENV_HOME
+    else
+      ENV.delete 'HOME'
+    end
+  end
+
+  def install_gem gem
+    require 'rubygems/installer'
+
+    use_ui MockGemUi.new do
+      Dir.chdir @tempdir do
+        Gem::Builder.new(gem).build
+      end
+    end
+
+    gem = File.join(@tempdir, gem.file_name).untaint
+    Gem::Installer.new(gem, :wrappers => true).install
+  end
+
+  def mu_pp(obj)
+    s = ''
+    s = PP.pp obj, s
+    s = s.force_encoding(Encoding.default_external) if defined? Encoding
+    s.chomp
+  end
+
+  def prep_cache_files(lc)
+    @usr_si ||= Gem::SourceIndex.new
+    @usr_sice ||= Gem::SourceInfoCacheEntry.new @usr_si, 0
+
+    @sys_si ||= Gem::SourceIndex.new
+    @sys_sice ||= Gem::SourceInfoCacheEntry.new @sys_si, 0
+
+    latest_si = Gem::SourceIndex.new
+    latest_si.add_specs(*@sys_si.latest_specs)
+    latest_sys_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
+
+    latest_si = Gem::SourceIndex.new
+    latest_si.add_specs(*@usr_si.latest_specs)
+    latest_usr_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
+
+    [ [lc.system_cache_file, @sys_sice],
+      [lc.latest_system_cache_file, latest_sys_sice],
+      [lc.user_cache_file, @usr_sice],
+      [lc.latest_user_cache_file, latest_usr_sice],
+    ].each do |filename, data|
+      FileUtils.mkdir_p File.dirname(filename).untaint
+
+      open filename.dup.untaint, 'wb' do |f|
+        f.write Marshal.dump({ @gem_repo => data })
+      end
+    end
+  end
+
+  def read_cache(path)
+    open path.dup.untaint, 'rb' do |io|
+      Marshal.load io.read
+    end
+  end
+
+  def read_binary(path)
+    Gem.read_binary path
+  end
+
+  def write_file(path)
+    path = File.join(@gemhome, path)
+    dir = File.dirname path
+    FileUtils.mkdir_p dir
+
+    open path, 'wb' do |io|
+      yield io
+    end
+
+    path
+  end
+
+  def quick_gem(gemname, version='2')
+    require 'rubygems/specification'
+
+    spec = Gem::Specification.new do |s|
+      s.platform = Gem::Platform::RUBY
+      s.name = gemname
+      s.version = version
+      s.author = 'A User'
+      s.email = 'example at example.com'
+      s.homepage = 'http://example.com'
+      s.has_rdoc = true
+      s.summary = "this is a summary"
+      s.description = "This is a test description"
+
+      yield(s) if block_given?
+    end
+
+    path = File.join "specifications", spec.spec_name
+    written_path = write_file path do |io|
+      io.write(spec.to_ruby)
+    end
+
+    spec.loaded_from = written_path
+
+    Gem.source_index.add_spec spec
+
+    return spec
+  end
+
+  def util_build_gem(spec)
+    dir = File.join(@gemhome, 'gems', spec.full_name)
+    FileUtils.mkdir_p dir
+
+    Dir.chdir dir do
+      spec.files.each do |file|
+        next if File.exist? file
+        FileUtils.mkdir_p File.dirname(file)
+        File.open file, 'w' do |fp| fp.puts "# #{file}" end
+      end
+
+      use_ui MockGemUi.new do
+        Gem::Builder.new(spec).build
+      end
+
+      FileUtils.mv spec.file_name,
+                   File.join(@gemhome, 'cache', "#{spec.original_name}.gem")
+    end
+  end
+
+  def util_clear_gems
+    FileUtils.rm_r File.join(@gemhome, 'gems')
+    FileUtils.rm_r File.join(@gemhome, 'specifications')
+    Gem.source_index.refresh!
+  end
+
+  def util_gem(name, version, &block)
+    spec = quick_gem(name, version, &block)
+
+    util_build_gem spec
+
+    cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+    FileUtils.mv File.join(@gemhome, 'cache', "#{spec.original_name}.gem"),
+                 cache_file
+    FileUtils.rm File.join(@gemhome, 'specifications', spec.spec_name)
+
+    spec.loaded_from = nil
+    spec.loaded = false
+
+    [spec, cache_file]
+  end
+
+  def util_gzip(data)
+    out = StringIO.new
+
+    Zlib::GzipWriter.wrap out do |io|
+      io.write data
+    end
+
+    out.string
+  end
+
+  def util_make_gems(prerelease = false)
+    @a1 = quick_gem 'a', '1' do |s|
+      s.files = %w[lib/code.rb]
+      s.require_paths = %w[lib]
+      s.date = Gem::Specification::TODAY - 86400
+      s.homepage = 'http://a.example.com'
+      s.email = %w[example at example.com example2 at example.com]
+      s.authors = %w[Example Example2]
+      s.description = <<-DESC
+This line is really, really long.  So long, in fact, that it is more than eighty characters long!  The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters.  Without the wrapping, the text might not look good in the RSS feed.
+
+Also, a list:
+  * An entry that's actually kind of sort
+  * an entry that's really long, which will probably get wrapped funny.  That's ok, somebody wasn't thinking straight when they made it more than eighty characters.
+      DESC
+    end
+
+    init = proc do |s|
+      s.files = %w[lib/code.rb]
+      s.require_paths = %w[lib]
+    end
+
+    @a2 = quick_gem('a', '2', &init)
+    @a3a = quick_gem('a', '3.a', &init)
+    @a_evil9 = quick_gem('a_evil', '9', &init)
+    @b2 = quick_gem('b', '2', &init)
+    @c1_2   = quick_gem('c', '1.2',   &init)
+    @pl1     = quick_gem 'pl', '1' do |s| # l for legacy
+      s.files = %w[lib/code.rb]
+      s.require_paths = %w[lib]
+      s.platform = Gem::Platform.new 'i386-linux'
+      s.instance_variable_set :@original_platform, 'i386-linux'
+    end
+
+    if prerelease
+      @a2_pre = quick_gem('a', '2.a', &init)
+      write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) do
+      end
+      util_build_gem @a2_pre
+    end
+
+    write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) do end
+    write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) do end
+    write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) do end
+    write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) do end
+    write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) do end
+    write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) do end
+
+    [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].each do |spec|
+      util_build_gem spec
+    end
+
+    FileUtils.rm_r File.join(@gemhome, 'gems', @pl1.original_name)
+
+    Gem.source_index = nil
+  end
+
+  ##
+  # Set the platform to +arch+
+
+  def util_set_arch(arch)
+    Gem::ConfigMap[:arch] = arch
+    platform = Gem::Platform.new arch
+
+    Gem.instance_variable_set :@platforms, nil
+    Gem::Platform.instance_variable_set :@local, nil
+
+    platform
+  end
+
+  def util_setup_fake_fetcher(prerelease = false)
+    require 'zlib'
+    require 'socket'
+    require 'rubygems/remote_fetcher'
+
+    @fetcher = Gem::FakeFetcher.new
+
+    util_make_gems(prerelease)
+
+    @all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort
+    @all_gem_names = @all_gems.map { |gem| gem.full_name }
+
+    gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name]
+    @gem_names = gem_names.sort.join("\n")
+
+    @source_index = Gem::SourceIndex.new
+    @source_index.add_spec @a1
+    @source_index.add_spec @a2
+    @source_index.add_spec @a3a
+    @source_index.add_spec @a_evil9
+    @source_index.add_spec @c1_2
+    @source_index.add_spec @a2_pre if prerelease
+
+    Gem::RemoteFetcher.fetcher = @fetcher
+  end
+
+  def util_setup_spec_fetcher(*specs)
+    specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
+    si = Gem::SourceIndex.new specs
+
+    spec_fetcher = Gem::SpecFetcher.fetcher
+
+    spec_fetcher.specs[@uri] = []
+    si.gems.sort_by { |_, spec| spec }.each do |_, spec|
+      spec_tuple = [spec.name, spec.version, spec.original_platform]
+      spec_fetcher.specs[@uri] << spec_tuple
+    end
+
+    spec_fetcher.latest_specs[@uri] = []
+    si.latest_specs.sort.each do |spec|
+      spec_tuple = [spec.name, spec.version, spec.original_platform]
+      spec_fetcher.latest_specs[@uri] << spec_tuple
+    end
+
+    spec_fetcher.prerelease_specs[@uri] = []
+    si.prerelease_specs.sort.each do |spec|
+      spec_tuple = [spec.name, spec.version, spec.original_platform]
+      spec_fetcher.prerelease_specs[@uri] << spec_tuple
+    end
+
+    (si.gems.merge si.prerelease_gems).sort_by { |_,spec| spec }.each do |_, spec|
+      path = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{spec.original_name}.gemspec.rz"
+      data = Marshal.dump spec
+      data_deflate = Zlib::Deflate.deflate data
+      @fetcher.data[path] = data_deflate
+    end
+
+    si
+  end
+
+  def util_zip(data)
+    Zlib::Deflate.deflate data
+  end
+
+  def self.win_platform?
+    Gem.win_platform?
+  end
+
+  def win_platform?
+    Gem.win_platform?
+  end
+
+  # Returns whether or not we're on a version of Ruby built with VC++ (or
+  # Borland) versus Cygwin, Mingw, etc.
+  #
+  def self.vc_windows?
+    RUBY_PLATFORM.match('mswin')
+  end
+
+  # Returns whether or not we're on a version of Ruby built with VC++ (or
+  # Borland) versus Cygwin, Mingw, etc.
+  #
+  def vc_windows?
+    RUBY_PLATFORM.match('mswin')
+  end
+
+  # Returns the make command for the current platform. For versions of Ruby
+  # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
+  # other platforms, including Cygwin, it will return 'make'.
+  #
+  def self.make_command
+    vc_windows? ? 'nmake' : 'make'
+  end
+
+  # Returns the make command for the current platform. For versions of Ruby
+  # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
+  # other platforms, including Cygwin, it will return 'make'.
+  #
+  def make_command
+    vc_windows? ? 'nmake' : 'make'
+  end
+
+  # Returns whether or not the nmake command could be found.
+  #
+  def nmake_found?
+    system('nmake /? 1>NUL 2>&1')
+  end
+
+  # NOTE Allow tests to use a random (but controlled) port number instead of
+  # a hardcoded one. This helps CI tools when running parallels builds on
+  # the same builder slave.
+  def self.process_based_port
+    @@process_based_port ||= 8000 + $$ % 1000
+  end
+
+  def process_based_port
+    self.class.process_based_port
+  end
+
+  def build_rake_in
+    gem_ruby = Gem.ruby
+    ruby = @@ruby
+    Gem.module_eval {@ruby = ruby}
+    env_rake = ENV["rake"]
+    ENV["rake"] = @@rake
+    yield @@rake
+  ensure
+    Gem.module_eval {@ruby = gem_ruby}
+    if env_rake
+      ENV["rake"] = env_rake
+    else
+      ENV.delete("rake")
+    end
+  end
+
+  def self.rubybin
+    if ruby = ENV["RUBY"]
+      return ruby
+    end
+    ruby = "ruby"
+    rubyexe = ruby+".exe"
+    3.times do
+      if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+        return File.expand_path(ruby)
+      end
+      if File.exist? rubyexe and File.executable? rubyexe
+        return File.expand_path(rubyexe)
+      end
+      ruby = File.join("..", ruby)
+    end
+    begin
+      require "rbconfig"
+      File.join(
+        RbConfig::CONFIG["bindir"],
+	RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
+      )
+    rescue LoadError
+      "ruby"
+    end
+  end
+
+  @@ruby = rubybin
+  env_rake = ENV['rake']
+  ruby19_rake = File.expand_path("../../../bin/rake", __FILE__)
+  @@rake = if env_rake then
+             ENV["rake"]
+           elsif File.exist? ruby19_rake then
+             @@ruby + " " + ruby19_rake
+           else
+             'rake'
+           end
+
+end
+
+MiniTest::Unit.autorun
+

Added: MacRuby/trunk/test/libs/rubygems/test/insure_session.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/insure_session.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/insure_session.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,51 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+
+require 'rubygems'
+
+def install_session
+  path_to_gem = File.join("redist", "session.gem")
+  begin
+    Gem::Installer.new(path_to_gem).install
+  rescue Errno::EACCES => ex
+    puts
+    puts "*****************************************************************"
+    puts "Unable to install Gem 'Session'."
+    puts "Reason:  #{ex.message}"
+    puts "Try running:"
+    puts
+    puts "   gem -Li #{path_to_gem}"
+    puts
+    puts "with the appropriate admin privileges."
+    puts "*****************************************************************"
+    puts 
+    exit
+  end
+  gem 'session'
+end
+
+begin
+  require 'session'
+rescue LoadError => e
+  puts
+  puts "Required Gem 'Session' missing."
+  puts "We can attempt to install from the RubyGems Distribution,"
+  puts "but installation may require admin privileges on your system."
+  puts
+  print "Install now from RubyGems distribution? [Yn]"
+  answer = gets
+  if(answer =~ /^y/i || answer =~ /^[^a-zA-Z0-9]$/) then
+    install_session
+    puts
+    puts "Retry running the functional tests."
+    exit(0)
+  else
+    puts "Test cancelled...quitting"
+    exit(1)
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/test/mockgemui.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/mockgemui.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/mockgemui.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,64 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+
+require 'stringio'
+require 'rubygems/user_interaction'
+
+class MockGemUi < Gem::StreamUI
+  class TermError < RuntimeError; end
+
+  module TTY
+
+    attr_accessor :tty
+
+    def tty?()
+      @tty = true unless defined?(@tty)
+      @tty
+    end
+
+  end
+
+  def initialize(input = "")
+    ins = StringIO.new input
+    outs = StringIO.new
+    errs = StringIO.new
+
+    ins.extend TTY
+    outs.extend TTY
+    errs.extend TTY
+
+    super ins, outs, errs
+
+    @terminated = false
+  end
+
+  def input
+    @ins.string
+  end
+
+  def output
+    @outs.string
+  end
+
+  def error
+    @errs.string
+  end
+
+  def terminated?
+    @terminated
+  end
+
+  def terminate_interaction(status=0)
+    @terminated = true
+
+    raise TermError unless status == 0
+    raise Gem::SystemExitException, status
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/private_key.pem
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/private_key.pem	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/private_key.pem	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAm24C6xixiAxO+i1f3L8XRMwrmLkt6BvT60mZ7g8HsklH3af7
+KNHA6vo/G6sujs2UsNO4HY8BTEneiVOXXWQlcsJ+Z5wEPlIu4zFueAmLefx+n9lE
+ulNIUDoyUenKX4spoMRnX8k4lXL05ho/6JFq0JdDY2DmAaQ4vvTz5mh9kZiybtHQ
+fzcpbA51uY+sjdQRCPDHyUUfh0SmWJlLYMwcBdVeCiGUPBLi+iP5x1btO4uiJK6Q
+IMaV1H3SUCYtKGQKl7qwFd8k8ZBcHYOtmK61tupg3vqWQc0em6SxPj5lws8+1MVK
+twBNIDx24jF4ntxBRNKMZ7FN5SHbobAgDYkPAQIDAQABAoIBAGQilgK8X/PUajVH
+clEXU3hhSV0VQHwfIYKeYms6h6zXBVPKW0dLC0zXeDztJgueasMZQ67XaPCrTpGO
+px/l2zJ6F1HM8/bqn4aDXDY9f/xRLYryQRMBgL8fHzgitNylHWaT4j2Vt7yg2SI9
+mxrMRNKqASJPVR+Nm3l6+n9gpjVb99wEucWplPPHI6KhXLYPZOqSwt+zaH5roz3k
+UQmMs0Bs4hF1SzVl0n+KNoXHOwswVrmBWXgWvm2OhnwY2e26jfejc8toJc/ShAJ7
+C9exnrdimcgEKbd22Sum4G00CDYhcrG5LHHqkgwifcAEVctrvBZBZHGgpxlO8a8U
+eF2Vr7kCgYEAykdrBlzp7Fn9xzUInBQ3NXTTYAq51lpuJdmHQmPuTSY0buoHkd9f
+xbUCZ2qR9QAesrx4hI0qGLetc8IOKDoWx2rPepCCvO3Kx61o1SB5fAvBue03qVoq
+HqACX3Uk24Em8zAz9xuP13ETH/wU7sUbUxRHMCre6ZDmlxn4g5l+Nl8CgYEAxLVl
+22yBx0dfRr3UsHY9rxll2gIlnfnYfiJzq8wetzt/TfztRV5ILz7FyWqL5d7IoqkA
+fT2V4HAasRJASnKohwJe7z5M/H2ExwkGNFvY+jefb2CoUl5WouK9AlhbqBk3zmHi
+sY5GqQkAp/kHMntEin+sErJw6mkgAGdser3a9p8CgYEAqi31w++tunRnxw4+RRnY
+7Pdx0k6T1NxV6TAe1ONAHNY0rM/mOHqml65W7GzDiU1lhlh8SIB/VzZJDqfHw15D
+xdh94A7uf0bMILwrA4wDyTIW9Xa3Kpq57vQNqwPiU25QN69pOM+Ob+IpBfLOJafc
++kOINOUMj5Kh/aQS6Zzci58CgYEAk24dlFKEBjbRCvU2FrfYTYcsljPru7ZJc2gg
+588J6m0WYf5CWy5pzbcviGFpzvSlzXv7GOLylQ+QgcxbETFUbDPzsT4xd0AgJwj1
+dIKuYgMUZOa94VZBer2TydEtiRS1heJJhKhM/1329u4nXceTvHYqIq1JAfeee48I
+eAoZtaMCgYBz1FjWFQnMTD5nmyPEEZneoBPAR5+9jwOps+IYOoHtazoMFszzd0qo
+JZW3Ihn9KRrVSxfFApKS/ZwjiZ+tJUk7DE/v/0l0sszefY7s8b0pL1lpeZSoL71e
+QoG1WLXUiDV3BRlmyOAF1h3p12KRTLgwubN51ajECwcs3QwE+ZT8Gg==
+-----END RSA PRIVATE KEY-----

Added: MacRuby/trunk/test/libs/rubygems/test/public_cert.pem
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/public_cert.pem	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/public_cert.pem	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
+YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
+ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
+cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
+FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
+LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
+U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
+Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
+mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
+g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
+sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
+BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
+kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
+bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
+DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
+UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
+14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
+x52qPcexcYZR7w==
+-----END CERTIFICATE-----

Added: MacRuby/trunk/test/libs/rubygems/test/rubygems_plugin.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/rubygems_plugin.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/rubygems_plugin.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,16 @@
+require 'rubygems/command_manager'
+
+class Gem::Commands::InterruptCommand < Gem::Command
+
+  def initialize
+    super('interrupt', 'Raises an Interrupt Exception', {})
+  end
+
+  def execute
+    raise Interrupt, "Interrupt exception"
+  end
+
+end
+
+Gem::CommandManager.instance.register_command :interrupt
+

Added: MacRuby/trunk/test/libs/rubygems/test/simple_gem.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/simple_gem.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/simple_gem.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,72 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+    SIMPLE_GEM = <<-GEMDATA
+        MD5SUM = "e3701f9db765a2358aef94c40ded71c8"
+        if $0 == __FILE__
+          require 'optparse'
+        
+          options = {}
+          ARGV.options do |opts|
+            opts.on_tail("--help", "show this message") {puts opts; exit}
+            opts.on('--dir=DIRNAME', "Installation directory for the Gem") {|options[:directory]|}
+            opts.on('--force', "Force Gem to intall, bypassing dependency checks") {|options[:force]|}
+            opts.on('--gen-rdoc', "Generate RDoc documentation for the Gem") {|options[:gen_rdoc]|}
+            opts.parse!
+          end
+
+          require 'rubygems'
+          @directory = options[:directory] || Gem.dir  
+          @force = options[:force]
+  
+          gem = Gem::Installer.new(__FILE__).install(@force, @directory)      
+          if options[:gen_rdoc]
+            Gem::DocManager.new(gem).generate_rdoc
+          end
+end
+
+__END__
+--- !ruby/object:Gem::Specification 
+rubygems_version: "1.0"
+name: testing
+version: !ruby/object:Gem::Version 
+  version: 1.2.3
+date: 2004-03-18 22:01:52.859121 -05:00
+platform: 
+summary: This exercise the gem testing stuff.
+require_paths: 
+  - lib
+files: 
+  - lib/foo.rb
+  - lib/test
+  - lib/test.rb
+  - lib/test/wow.rb
+autorequire: test
+test_suite_file: foo
+requirements: 
+  - a computer processor
+--- 
+- 
+  size: 109
+  mode: 420
+  path: lib/foo.rb
+- 
+  size: 0
+  mode: 420
+  path: lib/test.rb
+- 
+  size: 15
+  mode: 420
+  path: lib/test/wow.rb
+---
+eJwVjDEKgDAUQ/eeIpsKguhY3ARPoHMp9quF0mL7e39/h5DwQpLpqz4TOqbC
+U42eO6WuYEvBntIhECuaaX1KqXXLmy2kAEc32szExK+PjyBAlpTZyK0N/Twu
+g1CKTjX9BGAj1w==
+---
+eJwDAAAAAAE=
+---
+eJwrKC0pVlAvzy9XyE3MU+cCACwiBP4=
+    GEMDATA

Added: MacRuby/trunk/test/libs/rubygems/test/test_config.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_config.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_config.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,19 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rbconfig'
+require 'rubygems'
+
+class TestConfig < RubyGemTestCase
+
+  def test_datadir
+    datadir = RbConfig::CONFIG['datadir']
+    assert_equal "#{datadir}/xyz", RbConfig.datadir('xyz')
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,665 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems'
+require 'rubygems/gem_openssl'
+require 'rubygems/installer'
+require 'pathname'
+require 'tmpdir'
+
+class TestGem < RubyGemTestCase
+
+  def setup
+    super
+
+    @additional = %w[a b].map { |d| File.join @tempdir, d }
+    @default_dir_re = if RUBY_VERSION > '1.9' then
+                        %r|/.*?[Rr]uby.*?/[Gg]ems/[0-9.]+|
+                      else
+                        %r|/[Rr]uby/[Gg]ems/[0-9.]+|
+                      end
+  end
+
+  def test_self_all_load_paths
+    util_make_gems
+
+    expected = [
+      File.join(@gemhome, *%W[gems #{@a1.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@a2.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@b2.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]),
+    ]
+
+    assert_equal expected, Gem.all_load_paths.sort
+  end
+
+  def test_self_available?
+    util_make_gems
+    assert(Gem.available?("a"))
+    assert(Gem.available?("a", "1"))
+    assert(Gem.available?("a", ">1"))
+    assert(!Gem.available?("monkeys"))
+  end
+
+  def test_self_bin_path_bin_name
+    util_exec_gem
+    assert_equal @abin_path, Gem.bin_path('a', 'abin')
+  end
+
+  def test_self_bin_path_bin_name_version
+    util_exec_gem
+    assert_equal @abin_path, Gem.bin_path('a', 'abin', '4')
+  end
+
+  def test_self_bin_path_name
+    util_exec_gem
+    assert_equal @exec_path, Gem.bin_path('a')
+  end
+
+  def test_self_bin_path_name_version
+    util_exec_gem
+    assert_equal @exec_path, Gem.bin_path('a', nil, '4')
+  end
+
+  def test_self_bin_path_no_default_bin
+    quick_gem 'a', '2' do |s|
+      s.executables = ['exec']
+    end
+    assert_raises(Gem::Exception) do
+      Gem.bin_path('a', '2')
+    end
+  end
+
+  def test_self_bin_path_no_bin_file
+    quick_gem 'a', '1'
+    assert_raises(Gem::Exception) do
+      Gem.bin_path('a', '1')
+    end
+  end
+
+  def test_self_bin_path_not_found
+    assert_raises(Gem::GemNotFoundException) do
+      Gem.bin_path('non-existent')
+    end
+  end
+
+  def test_self_bindir
+    assert_equal File.join(@gemhome, 'bin'), Gem.bindir
+    assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Gem.dir)
+    assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Pathname.new(Gem.dir))
+  end
+
+  def test_self_bindir_default_dir
+    default = Gem.default_dir
+    bindir = if defined?(RUBY_FRAMEWORK_VERSION) then
+               '/usr/bin'
+             else
+               RbConfig::CONFIG['bindir']
+             end
+
+    assert_equal bindir, Gem.bindir(default)
+    assert_equal bindir, Gem.bindir(Pathname.new(default))
+  end
+
+  def test_self_clear_paths
+    Gem.dir
+    Gem.path
+    searcher = Gem.searcher
+    source_index = Gem.source_index
+
+    Gem.clear_paths
+
+    assert_equal nil, Gem.instance_variable_get(:@gem_home)
+    assert_equal nil, Gem.instance_variable_get(:@gem_path)
+    refute_equal searcher, Gem.searcher
+    refute_equal source_index.object_id, Gem.source_index.object_id
+  end
+
+  def test_self_configuration
+    expected = Gem::ConfigFile.new []
+    Gem.configuration = nil
+
+    assert_equal expected, Gem.configuration
+  end
+
+  def test_self_datadir
+    foo = nil
+
+    Dir.chdir @tempdir do
+      FileUtils.mkdir_p 'data'
+      File.open File.join('data', 'foo.txt'), 'w' do |fp|
+        fp.puts 'blah'
+      end
+
+      foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end
+      install_gem foo
+    end
+
+    Gem.source_index = nil
+
+    gem 'foo'
+
+    expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo'
+
+    assert_equal expected, Gem.datadir('foo')
+  end
+
+  def test_self_datadir_nonexistent_package
+    assert_nil Gem.datadir('xyzzy')
+  end
+
+  def test_self_default_dir
+    assert_match @default_dir_re, Gem.default_dir
+  end
+
+  def test_self_default_exec_format
+    orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name]
+    Gem::ConfigMap[:ruby_install_name] = 'ruby'
+
+    assert_equal '%s', Gem.default_exec_format
+  ensure
+    Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME
+  end
+
+  def test_self_default_exec_format_18
+    orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name]
+    Gem::ConfigMap[:ruby_install_name] = 'ruby18'
+
+    assert_equal '%s18', Gem.default_exec_format
+  ensure
+    Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME
+  end
+
+  def test_self_default_exec_format_jruby
+    orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name]
+    Gem::ConfigMap[:ruby_install_name] = 'jruby'
+
+    assert_equal 'j%s', Gem.default_exec_format
+  ensure
+    Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME
+  end
+
+  def test_self_default_sources
+    assert_equal %w[http://gems.rubyforge.org/], Gem.default_sources
+  end
+
+  def test_self_dir
+    assert_equal @gemhome, Gem.dir
+  end
+
+  def test_self_ensure_gem_directories
+    FileUtils.rm_r @gemhome
+    Gem.use_paths @gemhome
+
+    Gem.ensure_gem_subdirectories @gemhome
+
+    assert File.directory?(File.join(@gemhome, "cache"))
+  end
+
+  def test_self_ensure_gem_directories_missing_parents
+    gemdir = File.join @tempdir, 'a/b/c/gemdir'
+    FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil
+    refute File.exist?(File.join(@tempdir, 'a')),
+           "manually remove #{File.join @tempdir, 'a'}, tests are broken"
+    Gem.use_paths gemdir
+
+    Gem.ensure_gem_subdirectories gemdir
+
+    assert File.directory?("#{gemdir}/cache")
+  end
+
+  unless win_platform? then # only for FS that support write protection
+    def test_self_ensure_gem_directories_write_protected
+      gemdir = File.join @tempdir, "egd"
+      FileUtils.rm_r gemdir rescue nil
+      refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken"
+      FileUtils.mkdir_p gemdir
+      FileUtils.chmod 0400, gemdir
+      Gem.use_paths gemdir
+
+      Gem.ensure_gem_subdirectories gemdir
+
+      refute File.exist?("#{gemdir}/cache")
+    ensure
+      FileUtils.chmod 0600, gemdir
+    end
+
+    def test_self_ensure_gem_directories_write_protected_parents
+      parent = File.join(@tempdir, "egd")
+      gemdir = "#{parent}/a/b/c"
+
+      FileUtils.rm_r parent rescue nil
+      refute File.exist?(parent), "manually remove #{parent}, tests are broken"
+      FileUtils.mkdir_p parent
+      FileUtils.chmod 0400, parent
+      Gem.use_paths(gemdir)
+
+      Gem.ensure_gem_subdirectories gemdir
+
+      refute File.exist?("#{gemdir}/cache")
+    ensure
+      FileUtils.chmod 0600, parent
+    end
+  end
+
+  def test_ensure_ssl_available
+    orig_Gem_ssl_available = Gem.ssl_available?
+
+    Gem.ssl_available = true
+    Gem.ensure_ssl_available
+
+    Gem.ssl_available = false
+    e = assert_raises Gem::Exception do Gem.ensure_ssl_available end
+    assert_equal 'SSL is not installed on this system', e.message
+  ensure
+    Gem.ssl_available = orig_Gem_ssl_available
+  end
+
+  def test_self_find_files
+    discover_path = File.join 'lib', 'foo', 'discover.rb'
+
+    foo1 = quick_gem 'foo', '1' do |s|
+      s.files << discover_path
+    end
+
+    foo2 = quick_gem 'foo', '2' do |s|
+      s.files << discover_path
+    end
+
+    path = File.join 'gems', foo1.full_name, discover_path
+    write_file(path) { |fp| fp.puts "# #{path}" }
+
+    path = File.join 'gems', foo2.full_name, discover_path
+    write_file(path) { |fp| fp.puts "# #{path}" }
+
+    @fetcher = Gem::FakeFetcher.new
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    Gem.source_index = util_setup_spec_fetcher foo1, foo2
+
+    Gem.searcher = nil
+
+    expected = [
+      File.expand_path('foo/discover.rb', File.dirname(__FILE__)),
+      File.join(foo2.full_gem_path, discover_path),
+      File.join(foo1.full_gem_path, discover_path),
+    ]
+
+    assert_equal expected, Gem.find_files('foo/discover')
+  end
+
+  def test_self_latest_load_paths
+    util_make_gems
+
+    expected = [
+      File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@b2.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]),
+      File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]),
+    ]
+
+    assert_equal expected, Gem.latest_load_paths.sort
+  end
+
+  def test_self_loaded_specs
+    foo = quick_gem 'foo'
+    install_gem foo
+    Gem.source_index = nil
+
+    Gem.activate 'foo'
+
+    assert_equal true, Gem.loaded_specs.keys.include?('foo')
+  end
+
+  def test_self_path
+    assert_equal [Gem.dir], Gem.path
+  end
+
+  def test_self_path_default
+    if defined? APPLE_GEM_HOME
+      orig_APPLE_GEM_HOME = APPLE_GEM_HOME
+      Object.send :remove_const, :APPLE_GEM_HOME
+    end
+    Gem.instance_variable_set :@gem_path, nil
+
+    assert_equal [Gem.default_path, Gem.dir].flatten, Gem.path
+  ensure
+    Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME
+  end
+
+  unless win_platform?
+    def test_self_path_APPLE_GEM_HOME
+      Gem.clear_paths
+      apple_gem_home = File.join @tempdir, 'apple_gem_home'
+      Gem.const_set :APPLE_GEM_HOME, apple_gem_home
+
+      assert_includes Gem.path, apple_gem_home
+    ensure
+      Gem.send :remove_const, :APPLE_GEM_HOME
+    end
+
+    def test_self_path_APPLE_GEM_HOME_GEM_PATH
+      Gem.clear_paths
+      ENV['GEM_PATH'] = @gemhome
+      apple_gem_home = File.join @tempdir, 'apple_gem_home'
+      Gem.const_set :APPLE_GEM_HOME, apple_gem_home
+
+      refute Gem.path.include?(apple_gem_home)
+    ensure
+      Gem.send :remove_const, :APPLE_GEM_HOME
+    end
+  end
+
+  def test_self_path_ENV_PATH
+    Gem.send :set_paths, nil
+    path_count = Gem.path.size
+    Gem.clear_paths
+
+    ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR)
+
+    assert_equal @additional, Gem.path[0,2]
+
+    assert_equal path_count + @additional.size, Gem.path.size,
+                 "extra path components: #{Gem.path[2..-1].inspect}"
+    assert_equal Gem.dir, Gem.path.last
+  end
+
+  def test_self_path_duplicate
+    Gem.clear_paths
+    util_ensure_gem_dirs
+    dirs = @additional + [@gemhome] + [File.join(@tempdir, 'a')]
+
+    ENV['GEM_HOME'] = @gemhome
+    ENV['GEM_PATH'] = dirs.join File::PATH_SEPARATOR
+
+    assert_equal @gemhome, Gem.dir
+
+    paths = [Gem.dir]
+    assert_equal @additional + paths, Gem.path
+  end
+
+  def test_self_path_overlap
+    Gem.clear_paths
+
+    util_ensure_gem_dirs
+    ENV['GEM_HOME'] = @gemhome
+    ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR)
+
+    assert_equal @gemhome, Gem.dir
+
+    paths = [Gem.dir]
+    assert_equal @additional + paths, Gem.path
+  end
+
+  def test_self_platforms
+    assert_equal [Gem::Platform::RUBY, Gem::Platform.local], Gem.platforms
+  end
+
+  def test_self_prefix
+    file_name = File.expand_path __FILE__
+
+    prefix = File.dirname File.dirname(file_name)
+    prefix = File.dirname prefix if File.basename(prefix) == 'test'
+
+    assert_equal prefix, Gem.prefix
+  end
+
+  def test_self_prefix_libdir
+    orig_libdir = Gem::ConfigMap[:libdir]
+
+    file_name = File.expand_path __FILE__
+    prefix = File.dirname File.dirname(file_name)
+    prefix = File.dirname prefix if File.basename(prefix) == 'test'
+
+    Gem::ConfigMap[:libdir] = prefix
+
+    assert_nil Gem.prefix
+  ensure
+    Gem::ConfigMap[:libdir] = orig_libdir
+  end
+
+  def test_self_prefix_sitelibdir
+    orig_sitelibdir = Gem::ConfigMap[:sitelibdir]
+
+    file_name = File.expand_path __FILE__
+    prefix = File.dirname File.dirname(file_name)
+    prefix = File.dirname prefix if File.basename(prefix) == 'test'
+
+    Gem::ConfigMap[:sitelibdir] = prefix
+
+    assert_nil Gem.prefix
+  ensure
+    Gem::ConfigMap[:sitelibdir] = orig_sitelibdir
+  end
+
+  def test_self_refresh
+    util_make_gems
+
+    a1_spec = File.join @gemhome, "specifications", @a1.spec_name 
+
+    FileUtils.mv a1_spec, @tempdir
+
+    refute Gem.source_index.gems.include?(@a1.full_name)
+
+    FileUtils.mv File.join(@tempdir, @a1.spec_name), a1_spec
+
+    Gem.refresh
+
+    assert_includes Gem.source_index.gems, @a1.full_name
+    assert_equal nil, Gem.instance_variable_get(:@searcher)
+  end
+
+  def test_self_required_location
+    util_make_gems
+
+    assert_equal File.join(@tempdir, *%w[gemhome gems c-1.2 lib code.rb]),
+                 Gem.required_location("c", "code.rb")
+    assert_equal File.join(@tempdir, *%w[gemhome gems a-1 lib code.rb]),
+                 Gem.required_location("a", "code.rb", "< 2")
+    assert_equal File.join(@tempdir, *%w[gemhome gems a-2 lib code.rb]),
+                 Gem.required_location("a", "code.rb", "= 2")
+  end
+
+  def test_self_ruby_escaping_spaces_in_path
+    orig_ruby = Gem.ruby
+    orig_bindir = Gem::ConfigMap[:bindir]
+    orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name]
+    orig_exe_ext = Gem::ConfigMap[:EXEEXT]
+
+    Gem::ConfigMap[:bindir] = "C:/Ruby 1.8/bin"
+    Gem::ConfigMap[:ruby_install_name] = "ruby"
+    Gem::ConfigMap[:EXEEXT] = ".exe"
+    Gem.instance_variable_set("@ruby", nil)
+
+    assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby
+  ensure
+    Gem.instance_variable_set("@ruby", orig_ruby)
+    Gem::ConfigMap[:bindir] = orig_bindir
+    Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name
+    Gem::ConfigMap[:EXEEXT] = orig_exe_ext
+  end
+
+  def test_self_ruby_path_without_spaces
+    orig_ruby = Gem.ruby
+    orig_bindir = Gem::ConfigMap[:bindir]
+    orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name]
+    orig_exe_ext = Gem::ConfigMap[:EXEEXT]
+
+    Gem::ConfigMap[:bindir] = "C:/Ruby18/bin"
+    Gem::ConfigMap[:ruby_install_name] = "ruby"
+    Gem::ConfigMap[:EXEEXT] = ".exe"
+    Gem.instance_variable_set("@ruby", nil)
+
+    assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby
+  ensure
+    Gem.instance_variable_set("@ruby", orig_ruby)
+    Gem::ConfigMap[:bindir] = orig_bindir
+    Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name
+    Gem::ConfigMap[:EXEEXT] = orig_exe_ext
+  end
+
+  def test_self_ruby_version_1_8_5
+    util_set_RUBY_VERSION '1.8.5'
+
+    assert_equal Gem::Version.new('1.8.5'), Gem.ruby_version
+  ensure
+    util_restore_RUBY_VERSION
+  end
+
+  def test_self_ruby_version_1_8_6p287
+    util_set_RUBY_VERSION '1.8.6', 287
+
+    assert_equal Gem::Version.new('1.8.6.287'), Gem.ruby_version
+  ensure
+    util_restore_RUBY_VERSION
+  end
+
+  def test_self_ruby_version_1_9_2dev_r23493
+    util_set_RUBY_VERSION '1.9.2', -1, 23493
+
+    assert_equal Gem::Version.new('1.9.2.dev.23493'), Gem.ruby_version
+  ensure
+    util_restore_RUBY_VERSION
+  end
+
+  def test_self_searcher
+    assert_kind_of Gem::GemPathSearcher, Gem.searcher
+  end
+
+  def test_self_set_paths
+    other = File.join @tempdir, 'other'
+    path = [@userhome, other].join File::PATH_SEPARATOR
+    Gem.send :set_paths, path
+
+    assert_equal [@userhome, other, @gemhome], Gem.path
+  end
+
+  def test_self_set_paths_nonexistent_home
+    ENV['GEM_HOME'] = @gemhome
+    Gem.clear_paths
+
+    other = File.join @tempdir, 'other'
+
+    ENV['HOME'] = other
+
+    Gem.send :set_paths, other
+
+    assert_equal [other, @gemhome], Gem.path
+  end
+
+  def test_self_source_index
+    assert_kind_of Gem::SourceIndex, Gem.source_index
+  end
+
+  def test_self_sources
+    assert_equal %w[http://gems.example.com/], Gem.sources
+  end
+
+  def test_ssl_available_eh
+    orig_Gem_ssl_available = Gem.ssl_available?
+
+    Gem.ssl_available = true
+    assert_equal true, Gem.ssl_available?
+
+    Gem.ssl_available = false
+    assert_equal false, Gem.ssl_available?
+  ensure
+    Gem.ssl_available = orig_Gem_ssl_available
+  end
+
+  def test_self_use_paths
+    util_ensure_gem_dirs
+
+    Gem.use_paths @gemhome, @additional
+
+    assert_equal @gemhome, Gem.dir
+    assert_equal @additional + [Gem.dir], Gem.path
+  end
+
+  def test_self_user_dir
+    assert_equal File.join(@userhome, '.gem', Gem.ruby_engine,
+                           Gem::ConfigMap[:ruby_version]), Gem.user_dir
+  end
+
+  def test_self_user_home
+    if ENV['HOME'] then
+      assert_equal ENV['HOME'], Gem.user_home
+    else
+      assert true, 'count this test'
+    end
+  end
+
+  def test_self_user_home_user_drive_and_path
+    Gem.clear_paths
+
+    # safe-keep env variables
+    orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE']
+    orig_user_drive, orig_user_path = ENV['HOMEDRIVE'], ENV['HOMEPATH']
+
+    # prepare the environment
+    ENV.delete('HOME')
+    ENV.delete('USERPROFILE')
+    ENV['HOMEDRIVE'] = 'Z:'
+    ENV['HOMEPATH'] = '\\Users\\RubyUser'
+
+    assert_equal "Z:\\Users\\RubyUser", Gem.user_home
+
+  ensure
+    ENV['HOME'] = orig_home
+    ENV['USERPROFILE'] = orig_user_profile
+    ENV['USERDRIVE'] = orig_user_drive
+    ENV['USERPATH'] = orig_user_path
+  end if '1.9' > RUBY_VERSION
+
+  def util_ensure_gem_dirs
+    Gem.ensure_gem_subdirectories @gemhome
+    @additional.each do |dir|
+      Gem.ensure_gem_subdirectories @gemhome
+    end
+  end
+
+  def util_exec_gem
+    spec, _ = quick_gem 'a', '4' do |s|
+      s.default_executable = 'exec'
+      s.executables = ['exec', 'abin']
+    end
+
+    @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec'
+    @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin'
+  end
+
+  def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil)
+    if Gem.instance_variables.include? :@ruby_version or
+       Gem.instance_variables.include? '@ruby_version' then
+      Gem.send :remove_instance_variable, :@ruby_version
+    end
+
+    @RUBY_VERSION    = RUBY_VERSION
+    @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
+    @RUBY_REVISION   = RUBY_REVISION   if defined?(RUBY_REVISION)
+
+    Object.send :remove_const, :RUBY_VERSION
+    Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
+    Object.send :remove_const, :RUBY_REVISION   if defined?(RUBY_REVISION)
+
+    Object.const_set :RUBY_VERSION,    version
+    Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel
+    Object.const_set :RUBY_REVISION,   revision   if revision
+  end
+
+  def util_restore_RUBY_VERSION
+    Object.send :remove_const, :RUBY_VERSION
+    Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
+    Object.send :remove_const, :RUBY_REVISION   if defined?(RUBY_REVISION)
+
+    Object.const_set :RUBY_VERSION,    @RUBY_VERSION
+    Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if
+      defined?(@RUBY_PATCHLEVEL)
+    Object.const_set :RUBY_REVISION,   @RUBY_REVISION   if
+      defined?(@RUBY_REVISION)
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,33 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/builder'
+
+class TestGemBuilder < RubyGemTestCase
+
+  def test_build
+    builder = Gem::Builder.new quick_gem('a')
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        builder.build
+      end
+    end
+
+    assert_match %r|Successfully built RubyGem\n  Name: a|, @ui.output
+  end
+
+  def test_build_validates
+    builder = Gem::Builder.new Gem::Specification.new
+
+    assert_raises Gem::InvalidSpecificationException do
+      builder.build
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,185 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/command'
+
+class Gem::Command
+  public :parser
+end
+
+class TestGemCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @xopt = nil
+
+    Gem::Command.common_options.clear
+    Gem::Command.common_options <<  [
+      ['-x', '--exe', 'Execute'], lambda do |*a|
+        @xopt = true
+      end
+    ]
+
+    @cmd_name = 'doit'
+    @cmd = Gem::Command.new @cmd_name, 'summary'
+  end
+
+  def test_self_add_specific_extra_args
+    added_args = %w[--all]
+    @cmd.add_option '--all' do |v,o| end
+
+    Gem::Command.add_specific_extra_args @cmd_name, added_args
+
+    assert_equal added_args, Gem::Command.specific_extra_args(@cmd_name)
+
+    h = @cmd.add_extra_args []
+
+    assert_equal added_args, h
+  end
+
+  def test_self_add_specific_extra_args_unknown
+    added_args = %w[--definitely_not_there]
+
+    Gem::Command.add_specific_extra_args @cmd_name, added_args
+
+    assert_equal added_args, Gem::Command.specific_extra_args(@cmd_name)
+
+    h = @cmd.add_extra_args []
+
+    assert_equal [], h
+  end
+
+  def test_basic_accessors
+    assert_equal "doit", @cmd.command
+    assert_equal "gem doit", @cmd.program_name
+    assert_equal "summary", @cmd.summary
+  end
+
+  def test_common_option_in_class
+    assert Array === Gem::Command.common_options
+  end
+
+  def test_defaults
+    @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+      options[:help] = value
+    end
+
+    @cmd.defaults = { :help => true }
+
+    @cmd.when_invoked do |options|
+      assert options[:help], "Help options should default true"
+    end
+
+    use_ui @ui do
+      @cmd.invoke
+    end
+
+    assert_match %r|Usage: gem doit|, @ui.output
+  end
+
+  def test_invoke
+    done = false
+    @cmd.when_invoked { done = true }
+
+    use_ui @ui do
+      @cmd.invoke
+    end
+
+    assert done
+  end
+
+  def test_invode_with_bad_options
+    use_ui @ui do
+      @cmd.when_invoked do true end
+
+      ex = assert_raises OptionParser::InvalidOption do
+        @cmd.invoke('-zzz')
+      end
+
+      assert_match(/invalid option:/, ex.message)
+    end
+  end
+
+  def test_invoke_with_common_options
+    @cmd.when_invoked do true end
+
+    use_ui @ui do
+      @cmd.invoke "-x"
+    end
+
+    assert @xopt, "Should have done xopt"
+  end
+
+  # Returning false from the command handler invokes the usage output.
+  def test_invoke_with_help
+    done = false
+
+    use_ui @ui do
+      @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+        options[:help] = true
+        done = true
+      end
+
+      @cmd.invoke('--help')
+
+      assert done
+    end
+
+    assert_match(/Usage/, @ui.output)
+    assert_match(/gem doit/, @ui.output)
+    assert_match(/\[options\]/, @ui.output)
+    assert_match(/-h/, @ui.output)
+    assert_match(/--help \[COMMAND\]/, @ui.output)
+    assert_match(/Get help on COMMAND/, @ui.output)
+    assert_match(/-x/, @ui.output)
+    assert_match(/--exe/, @ui.output)
+    assert_match(/Execute/, @ui.output)
+    assert_match(/Common Options:/, @ui.output)
+  end
+
+  def test_invoke_with_options
+    @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+      options[:help] = true
+    end
+
+    @cmd.when_invoked do |opts|
+      assert opts[:help]
+    end
+
+    use_ui @ui do
+      @cmd.invoke '-h'
+    end
+
+    assert_match %r|Usage: gem doit|, @ui.output
+  end
+
+  def test_option_recognition
+    @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+      options[:help] = true
+    end
+    @cmd.add_option('-f', '--file FILE', 'File option') do |value, options|
+      options[:help] = true
+    end
+    assert @cmd.handles?(['-x'])
+    assert @cmd.handles?(['-h'])
+    assert @cmd.handles?(['-h', 'command'])
+    assert @cmd.handles?(['--help', 'command'])
+    assert @cmd.handles?(['-f', 'filename'])
+    assert @cmd.handles?(['--file=filename'])
+    refute @cmd.handles?(['-z'])
+    refute @cmd.handles?(['-f'])
+    refute @cmd.handles?(['--toothpaste'])
+
+    args = ['-h', 'command']
+    @cmd.handles?(args)
+    assert_equal ['-h', 'command'], args
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_command_manager.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_command_manager.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_command_manager.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,199 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/command_manager'
+
+class TestGemCommandManager < RubyGemTestCase
+
+  def setup
+    super
+
+    @command_manager = Gem::CommandManager.instance
+  end
+
+  def test_run_interrupt
+    use_ui @ui do
+      assert_raises MockGemUi::TermError do
+        @command_manager.run 'interrupt'
+      end
+      assert_equal '', ui.output
+      assert_equal "ERROR:  Interrupted\n", ui.error
+    end
+  end
+
+  def test_process_args_bad_arg
+    use_ui @ui do
+      assert_raises(MockGemUi::TermError) {
+        @command_manager.process_args("--bad-arg")
+      }
+    end
+
+    assert_match(/invalid option: --bad-arg/i, @ui.error)
+  end
+
+  def test_process_args_install
+    #capture all install options
+    use_ui @ui do
+      check_options = nil
+      @command_manager['install'].when_invoked do |options|
+        check_options = options
+        true
+      end
+
+      #check defaults
+      @command_manager.process_args("install")
+      assert_equal false, check_options[:test]
+      assert_equal true, check_options[:generate_rdoc]
+      assert_equal false, check_options[:force]
+      assert_equal :both, check_options[:domain]
+      assert_equal true, check_options[:wrappers]
+      assert_equal Gem::Requirement.default, check_options[:version]
+      assert_equal nil, check_options[:install_dir]
+      assert_equal nil, check_options[:bin_dir]
+
+      #check settings
+      check_options = nil
+      @command_manager.process_args(
+        "install --force --test --local --rdoc --install-dir . --version 3.0 --no-wrapper --bindir . ")
+      assert_equal true, check_options[:test]
+      assert_equal true, check_options[:generate_rdoc]
+      assert_equal true, check_options[:force]
+      assert_equal :local, check_options[:domain]
+      assert_equal false, check_options[:wrappers]
+      assert_equal Gem::Requirement.new('3.0'), check_options[:version]
+      assert_equal Dir.pwd, check_options[:install_dir]
+      assert_equal Dir.pwd, check_options[:bin_dir]
+
+      #check remote domain
+      check_options = nil
+      @command_manager.process_args("install --remote")
+      assert_equal :remote, check_options[:domain]
+
+      #check both domain
+      check_options = nil
+      @command_manager.process_args("install --both")
+      assert_equal :both, check_options[:domain]
+
+      #check both domain
+      check_options = nil
+      @command_manager.process_args("install --both")
+      assert_equal :both, check_options[:domain]
+    end
+  end
+
+  def test_process_args_uninstall
+    #capture all uninstall options
+    check_options = nil
+    @command_manager['uninstall'].when_invoked do |options|
+      check_options = options
+      true
+    end
+
+    #check defaults
+    @command_manager.process_args("uninstall")
+    assert_equal Gem::Requirement.default, check_options[:version]
+
+    #check settings
+    check_options = nil
+    @command_manager.process_args("uninstall foobar --version 3.0")
+    assert_equal "foobar", check_options[:args].first
+    assert_equal Gem::Requirement.new('3.0'), check_options[:version]
+  end
+
+  def test_process_args_check
+    #capture all check options
+    check_options = nil
+    @command_manager['check'].when_invoked do |options|
+      check_options = options
+      true
+    end
+
+    #check defaults
+    @command_manager.process_args("check")
+    assert_equal false, check_options[:verify]
+    assert_equal false, check_options[:alien]
+
+    #check settings
+    check_options = nil
+    @command_manager.process_args("check --verify foobar --alien")
+    assert_equal "foobar", check_options[:verify]
+    assert_equal true, check_options[:alien]
+  end
+
+  def test_process_args_build
+    #capture all build options
+    check_options = nil
+    @command_manager['build'].when_invoked do |options|
+      check_options = options
+      true
+    end
+
+    #check defaults
+    @command_manager.process_args("build")
+    #NOTE: Currently no defaults
+
+    #check settings
+    check_options = nil
+    @command_manager.process_args("build foobar.rb")
+    assert_equal 'foobar.rb', check_options[:args].first
+  end
+
+  def test_process_args_query
+    #capture all query options
+    check_options = nil
+    @command_manager['query'].when_invoked do |options|
+      check_options = options
+      true
+    end
+
+    #check defaults
+    @command_manager.process_args("query")
+    assert_equal(//, check_options[:name])
+    assert_equal :local, check_options[:domain]
+    assert_equal false, check_options[:details]
+
+    #check settings
+    check_options = nil
+    @command_manager.process_args("query --name foobar --local --details")
+    assert_equal(/foobar/i, check_options[:name])
+    assert_equal :local, check_options[:domain]
+    assert_equal true, check_options[:details]
+
+    #remote domain
+    check_options = nil
+    @command_manager.process_args("query --remote")
+    assert_equal :remote, check_options[:domain]
+
+    #both (local/remote) domains
+    check_options = nil
+    @command_manager.process_args("query --both")
+    assert_equal :both, check_options[:domain]
+  end
+
+  def test_process_args_update
+    #capture all update options
+    check_options = nil
+    @command_manager['update'].when_invoked do |options|
+      check_options = options
+      true
+    end
+
+    #check defaults
+    @command_manager.process_args("update")
+    assert_equal true, check_options[:generate_rdoc]
+
+    #check settings
+    check_options = nil
+    @command_manager.process_args("update --force --test --rdoc --install-dir .")
+    assert_equal true, check_options[:test]
+    assert_equal true, check_options[:generate_rdoc]
+    assert_equal true, check_options[:force]
+    assert_equal Dir.pwd, check_options[:install_dir]
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_build_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_build_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_build_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,74 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/build_command'
+require 'rubygems/format'
+
+class TestGemCommandsBuildCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @gem = quick_gem 'some_gem' do |s|
+      s.rubyforge_project = 'example'
+    end
+
+    @cmd = Gem::Commands::BuildCommand.new
+  end
+
+  def test_execute
+    gemspec_file = File.join(@tempdir, @gem.spec_name)
+
+    File.open gemspec_file, 'w' do |gs|
+      gs.write @gem.to_ruby
+    end
+
+    util_test_build_gem @gem, gemspec_file
+  end
+
+  def test_execute_yaml
+    gemspec_file = File.join(@tempdir, @gem.spec_name)
+
+    File.open gemspec_file, 'w' do |gs|
+      gs.write @gem.to_yaml
+    end
+
+    util_test_build_gem @gem, gemspec_file
+  end
+
+  def test_execute_bad_gem
+    @cmd.options[:args] = %w[some_gem]
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal '', @ui.output
+    assert_equal "ERROR:  Gemspec file not found: some_gem\n", @ui.error
+  end
+
+  def util_test_build_gem(gem, gemspec_file)
+    @cmd.options[:args] = [gemspec_file]
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    output = @ui.output.split "\n"
+    assert_equal "  Successfully built RubyGem", output.shift
+    assert_equal "  Name: some_gem", output.shift
+    assert_equal "  Version: 2", output.shift
+    assert_equal "  File: some_gem-2.gem", output.shift
+    assert_equal [], output
+    assert_equal '', @ui.error
+
+    gem_file = File.join @tempdir, gem.file_name
+    assert File.exist?(gem_file)
+
+    spec = Gem::Format.from_file_by_path(gem_file).spec
+
+    assert_equal "some_gem", spec.name
+    assert_equal "this is a summary", spec.summary
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_cert_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_cert_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_cert_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,125 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+
+require 'rubygems/commands/cert_command'
+
+unless defined? OpenSSL then
+  warn "`gem cert` tests are being skipped, module OpenSSL not found"
+end
+
+class TestGemCommandsCertCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @orig_security_trust_dir = Gem::Security::OPT[:trust_dir]
+    Gem::Security::OPT[:trust_dir] = @tempdir
+
+    @cmd = Gem::Commands::CertCommand.new
+
+    root = File.expand_path(File.dirname(__FILE__))
+
+    FileUtils.cp File.join(root, 'data', 'gem-private_key.pem'), @tempdir
+    FileUtils.cp File.join(root, 'data', 'gem-public_cert.pem'), @tempdir
+
+    @cert_file_name = File.join @tempdir, 'gem-public_cert.pem'
+    @pkey_file_name = File.join @tempdir, 'gem-private_key.pem'
+  end
+
+  def teardown
+    Gem::Security::OPT[:trust_dir] = @orig_security_trust_dir
+
+    super
+  end
+
+  def test_execute_add
+    use_ui @ui do
+      @cmd.send :handle_options, %W[--add #{@cert_file_name}]
+    end
+
+    assert_equal "Added '/CN=rubygems/DC=example/DC=com'\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_build
+    FileUtils.rm @cert_file_name
+    FileUtils.rm @pkey_file_name
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.send :handle_options, %W[--build nobody at example.com]
+      end
+    end
+
+    output = @ui.output.split "\n"
+
+    assert_equal 'Public Cert: gem-public_cert.pem', output.shift
+    assert_equal 'Private Key: gem-private_key.pem', output.shift
+    assert_equal 'Don\'t forget to move the key file to somewhere private...',
+                 output.shift
+    assert_equal [], output
+
+    assert_equal '', @ui.error
+
+    assert File.exist?(File.join(@tempdir, 'gem-private_key.pem'))
+    assert File.exist?(File.join(@tempdir, 'gem-public_cert.pem'))
+  end
+
+  def test_execute_certificate
+    use_ui @ui do
+      @cmd.send :handle_options, %W[--certificate #{@cert_file_name}]
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+
+    assert_equal File.read(@cert_file_name),
+                 Gem::Security::OPT[:issuer_cert].to_s
+  end
+
+  def test_execute_list
+    use_ui @ui do
+      @cmd.send :handle_options, %W[--list]
+    end
+
+    assert_equal "/CN=rubygems/DC=example/DC=com\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_private_key
+    use_ui @ui do
+      @cmd.send :handle_options, %W[--private-key #{@pkey_file_name}]
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+
+    assert_equal File.read(@pkey_file_name),
+                 Gem::Security::OPT[:issuer_key].to_s
+  end
+
+  def test_execute_remove
+    use_ui @ui do
+      @cmd.send :handle_options, %W[--remove rubygems]
+    end
+
+    assert_equal "Removed '/CN=rubygems/DC=example/DC=com'\n", @ui.output
+    assert_equal '', @ui.error
+
+    refute File.exist?(@cert_file_name)
+  end
+
+  def test_execute_sign
+    use_ui @ui do
+      @cmd.send :handle_options, %W[
+        -K #{@pkey_file_name} -C #{@cert_file_name} --sign #{@cert_file_name}
+      ]
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+
+    # HACK this test sucks
+  end
+
+end if defined? OpenSSL
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_check_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_check_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_check_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,24 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/check_command'
+
+class TestGemCommandsCheckCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::CheckCommand.new
+  end
+
+  def test_initialize
+    assert_equal "check", @cmd.command
+    assert_equal "gem check", @cmd.program_name
+    assert_match(/Check/, @cmd.summary)
+  end
+
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_contents_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_contents_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_contents_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,154 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/contents_command'
+
+class TestGemCommandsContentsCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::ContentsCommand.new
+  end
+
+  def test_execute
+    @cmd.options[:args] = %w[foo]
+    quick_gem 'foo' do |gem|
+      gem.files = %w[lib/foo.rb Rakefile]
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|lib/foo\.rb|, @ui.output
+    assert_match %r|Rakefile|, @ui.output
+    assert_equal "", @ui.error
+  end
+
+  def test_execute_all
+    @cmd.options[:all] = true
+
+    quick_gem 'foo' do |gem|
+      gem.files = %w[lib/foo.rb Rakefile]
+    end
+
+    quick_gem 'bar' do |gem|
+      gem.files = %w[lib/bar.rb Rakefile]
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|lib/foo\.rb|, @ui.output
+    assert_match %r|lib/bar\.rb|, @ui.output
+    assert_match %r|Rakefile|, @ui.output
+    assert_equal "", @ui.error
+  end
+
+  def test_execute_bad_gem
+    @cmd.options[:args] = %w[foo]
+
+    assert_raises MockGemUi::TermError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_match %r|Unable to find gem 'foo' in default gem paths|, @ui.output
+    assert_match %r|Directories searched:|, @ui.output
+    assert_equal "", @ui.error
+  end
+
+  def test_execute_exact_match
+    @cmd.options[:args] = %w[foo]
+    quick_gem 'foo' do |gem|
+      gem.files = %w[lib/foo.rb Rakefile]
+    end
+
+    quick_gem 'foo_bar' do |gem|
+      gem.files = %w[lib/foo_bar.rb Rakefile]
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|lib/foo\.rb|, @ui.output
+    assert_match %r|Rakefile|, @ui.output
+    assert_equal "", @ui.error
+  end
+
+  def test_execute_lib_only
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:lib_only] = true
+
+    quick_gem 'foo' do |gem|
+      gem.files = %w[lib/foo.rb Rakefile]
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|lib/foo\.rb|, @ui.output
+    refute_match %r|Rakefile|, @ui.output
+
+    assert_equal "", @ui.error
+  end
+
+  def test_execute_multiple
+    @cmd.options[:args] = %w[foo bar]
+    quick_gem 'foo' do |gem|
+      gem.files = %w[lib/foo.rb Rakefile]
+    end
+
+    quick_gem 'bar' do |gem|
+      gem.files = %w[lib/bar.rb Rakefile]
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|lib/foo\.rb|, @ui.output
+    assert_match %r|lib/bar\.rb|, @ui.output
+    assert_match %r|Rakefile|, @ui.output
+    assert_equal "", @ui.error
+  end
+
+  def test_execute_no_prefix
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:prefix] = false
+
+    quick_gem 'foo' do |gem|
+      gem.files = %w[lib/foo.rb Rakefile]
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+lib/foo.rb
+Rakefile
+    EOF
+
+    assert_equal expected, @ui.output
+
+    assert_equal "", @ui.error
+  end
+
+  def test_handle_options
+    assert_equal false, @cmd.options[:lib_only]
+    assert_equal [], @cmd.options[:specdirs]
+    assert_equal nil, @cmd.options[:version]
+
+    @cmd.send :handle_options, %w[-l -s foo --version 0.0.2]
+
+    assert_equal true, @cmd.options[:lib_only]
+    assert_equal %w[foo], @cmd.options[:specdirs]
+    assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version]
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_dependency_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_dependency_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_dependency_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,190 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/dependency_command'
+
+class TestGemCommandsDependencyCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::DependencyCommand.new
+    @cmd.options[:domain] = :local
+
+    util_setup_fake_fetcher
+  end
+
+  def test_execute
+    quick_gem 'foo' do |gem|
+      gem.add_dependency 'bar', '> 1'
+    end
+
+    Gem.source_index = nil
+
+    @cmd.options[:args] = %w[foo]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "Gem foo-2\n  bar (> 1, runtime)\n\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_no_args
+    Gem.source_index = nil
+
+    @cmd.options[:args] = []
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+Gem a-1
+
+Gem a-2
+
+Gem a-3.a
+
+Gem a_evil-9
+
+Gem b-2
+
+Gem c-1.2
+
+Gem pl-1-x86-linux
+
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_no_match
+    @cmd.options[:args] = %w[foo]
+
+    assert_raises MockGemUi::TermError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal "No gems found matching foo (>= 0)\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_pipe_format
+    quick_gem 'foo' do |gem|
+      gem.add_dependency 'bar', '> 1'
+    end
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:pipe_format] = true
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "bar --version '> 1'\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_regexp
+    Gem.source_index = nil
+
+    @cmd.options[:args] = %w[/[ab]/]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+Gem a-1
+
+Gem a-2
+
+Gem a-3.a
+
+Gem a_evil-9
+
+Gem b-2
+
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_reverse
+    quick_gem 'foo' do |gem|
+      gem.add_dependency 'bar', '> 1'
+    end
+
+    quick_gem 'baz' do |gem|
+      gem.add_dependency 'foo'
+    end
+
+    Gem.source_index = nil
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:reverse_dependencies] = true
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+Gem foo-2
+  bar (> 1, runtime)
+  Used by
+    baz-2 (foo (>= 0, runtime))
+
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_reverse_remote
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:reverse_dependencies] = true
+    @cmd.options[:domain] = :remote
+
+    assert_raises MockGemUi::TermError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    expected = <<-EOF
+ERROR:  Only reverse dependencies for local gems are supported.
+    EOF
+
+    assert_equal '', @ui.output
+    assert_equal expected, @ui.error
+  end
+
+  def test_execute_remote
+    foo = quick_gem 'foo' do |gem|
+      gem.add_dependency 'bar', '> 1'
+    end
+
+    @fetcher = Gem::FakeFetcher.new
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    util_setup_spec_fetcher foo
+
+    FileUtils.rm File.join(@gemhome, 'specifications', foo.spec_name)
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:domain] = :remote
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "Gem foo-2\n  bar (> 1, runtime)\n\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_environment_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_environment_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_environment_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,133 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/environment_command'
+
+class TestGemCommandsEnvironmentCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::EnvironmentCommand.new
+  end
+
+  def test_execute
+    orig_sources = Gem.sources.dup
+    Gem.sources.replace %w[http://gems.example.com]
+
+    @cmd.send :handle_options, %w[]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|RUBYGEMS VERSION: (\d\.)+\d|, @ui.output
+    assert_match %r|RUBY VERSION: \d\.\d\.\d \(.*\) \[.*\]|, @ui.output
+    assert_match %r|INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}|,
+                 @ui.output
+    assert_match %r|RUBYGEMS PREFIX: |, @ui.output
+    assert_match %r|RUBY EXECUTABLE:.*#{Gem::ConfigMap[:ruby_install_name]}|,
+                 @ui.output
+    assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
+    assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
+    assert_match %r|- #{Gem::Platform.local}|, @ui.output
+    assert_match %r|GEM PATHS:|, @ui.output
+    assert_match %r|- #{Regexp.escape @gemhome}|, @ui.output
+    assert_match %r|GEM CONFIGURATION:|, @ui.output
+    assert_match %r|:verbose => |, @ui.output
+    assert_match %r|REMOTE SOURCES:|, @ui.output
+    assert_equal '', @ui.error
+
+  ensure
+    Gem.sources.replace orig_sources
+  end
+
+  def test_execute_gemdir
+    @cmd.send :handle_options, %w[gemdir]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "#{@gemhome}\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_gempath
+    @cmd.send :handle_options, %w[gempath]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "#{@gemhome}\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_gempath_multiple
+    Gem.clear_paths
+    path = [@gemhome, "#{@gemhome}2"].join File::PATH_SEPARATOR
+    ENV['GEM_PATH'] = path
+
+    @cmd.send :handle_options, %w[gempath]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "#{Gem.path.join File::PATH_SEPARATOR}\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_packageversion
+    @cmd.send :handle_options, %w[packageversion]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "#{Gem::RubyGemsPackageVersion}\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_remotesources
+    orig_sources = Gem.sources.dup
+    Gem.sources.replace %w[http://gems.example.com]
+
+    @cmd.send :handle_options, %w[remotesources]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "http://gems.example.com\n", @ui.output
+    assert_equal '', @ui.error
+
+  ensure
+    Gem.sources.replace orig_sources
+  end
+
+  def test_execute_unknown
+    @cmd.send :handle_options, %w[unknown]
+
+    assert_raises Gem::CommandLineError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_version
+    @cmd.send :handle_options, %w[version]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "#{Gem::RubyGemsVersion}\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_fetch_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_fetch_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_fetch_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,34 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/package'
+require 'rubygems/security'
+require 'rubygems/commands/fetch_command'
+
+class TestGemCommandsFetchCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::FetchCommand.new
+  end
+
+  def test_execute
+    util_setup_fake_fetcher
+    util_setup_spec_fetcher @a2
+
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] =
+      File.read(File.join(@gemhome, 'cache', @a2.file_name))
+
+    @cmd.options[:args] = [@a2.name]
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    assert File.exist?(File.join(@tempdir, @a2.file_name)),
+           "#{@a2.full_name} fetched"
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_generate_index_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_generate_index_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_generate_index_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,135 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/indexer'
+require 'rubygems/commands/generate_index_command'
+
+class TestGemCommandsGenerateIndexCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::GenerateIndexCommand.new
+    @cmd.options[:directory] = @gemhome
+  end
+
+  def test_execute
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    yaml = File.join @gemhome, 'yaml'
+    yaml_z = File.join @gemhome, 'yaml.Z'
+    quick_index = File.join @gemhome, 'quick', 'index'
+    quick_index_rz = File.join @gemhome, 'quick', 'index.rz'
+
+    assert File.exist?(yaml), yaml
+    assert File.exist?(yaml_z), yaml_z
+    assert File.exist?(quick_index), quick_index
+    assert File.exist?(quick_index_rz), quick_index_rz
+  end
+
+  def test_execute_rss_update
+    @cmd.options[:update] = true
+    @cmd.options[:rss_host] = 'example.com'
+    @cmd.options[:rss_gems_host] = 'gems.example.com'
+
+    use_ui @ui do
+      assert_raises MockGemUi::TermError do
+        @cmd.execute
+      end
+    end
+
+    assert_equal "ERROR:  --update not compatible with RSS generation\n",
+                 @ui.error
+    assert_empty @ui.output
+  end
+
+  def test_handle_options_directory
+    return if win_platform?
+    refute_equal '/nonexistent', @cmd.options[:directory]
+
+    @cmd.handle_options %w[--directory /nonexistent]
+
+    assert_equal '/nonexistent', @cmd.options[:directory]
+  end
+
+  def test_handle_options_directory_windows
+    return unless win_platform?
+
+    refute_equal '/nonexistent', @cmd.options[:directory]
+
+    @cmd.handle_options %w[--directory C:/nonexistent]
+
+    assert_equal 'C:/nonexistent', @cmd.options[:directory]
+  end
+
+  def test_handle_options_invalid
+    e = assert_raises OptionParser::InvalidOption do
+      @cmd.handle_options %w[--no-modern --no-legacy]
+    end
+
+    assert_equal 'invalid option: --no-legacy no indicies will be built',
+                 e.message
+
+    @cmd = Gem::Commands::GenerateIndexCommand.new
+    e = assert_raises OptionParser::InvalidOption do
+      @cmd.handle_options %w[--no-legacy --no-modern]
+    end
+
+    assert_equal 'invalid option: --no-modern no indicies will be built',
+                 e.message
+  end
+
+  def test_handle_options_legacy
+    @cmd.handle_options %w[--legacy]
+
+    assert @cmd.options[:build_legacy]
+    assert @cmd.options[:build_modern], ':build_modern not set'
+  end
+
+  def test_handle_options_modern
+    @cmd.handle_options %w[--modern]
+
+    assert @cmd.options[:build_legacy]
+    assert @cmd.options[:build_modern], ':build_modern not set'
+  end
+
+  def test_handle_options_no_legacy
+    @cmd.handle_options %w[--no-legacy]
+
+    refute @cmd.options[:build_legacy]
+    assert @cmd.options[:build_modern]
+  end
+
+  def test_handle_options_no_modern
+    @cmd.handle_options %w[--no-modern]
+
+    assert @cmd.options[:build_legacy]
+    refute @cmd.options[:build_modern]
+  end
+
+  def test_handle_options_rss_gems_host
+    @cmd.handle_options %w[--rss-gems-host gems.example.com]
+
+    assert_equal 'gems.example.com', @cmd.options[:rss_gems_host]
+  end
+
+  def test_handle_options_rss_host
+    @cmd.handle_options %w[--rss-host example.com]
+
+    assert_equal 'example.com', @cmd.options[:rss_host]
+  end
+
+  def test_handle_options_rss_title
+    @cmd.handle_options %w[--rss-title Example\ Gems]
+
+    assert_equal 'Example Gems', @cmd.options[:rss_title]
+  end
+
+  def test_handle_options_update
+    @cmd.handle_options %w[--update]
+
+    assert @cmd.options[:update]
+  end
+
+end if ''.respond_to? :to_xs
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_install_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_install_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_install_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,264 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/install_command'
+
+class TestGemCommandsInstallCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::InstallCommand.new
+    @cmd.options[:generate_rdoc] = false
+    @cmd.options[:generate_ri] = false
+  end
+
+  def test_execute_exclude_prerelease
+    util_setup_fake_fetcher(:prerelease)
+    util_setup_spec_fetcher @a2, @a2_pre
+
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2.file_name))
+    @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2_pre.file_name))
+
+    @cmd.options[:args] = [@a2.name]
+
+    use_ui @ui do
+      e = assert_raises Gem::SystemExitException do
+        @cmd.execute
+      end
+      assert_equal 0, e.exit_code, @ui.error
+    end
+
+    assert_match(/Successfully installed #{@a2.full_name}$/, @ui.output)
+    refute_match(/Successfully installed #{@a2_pre.full_name}$/, @ui.output)
+  end
+
+  def test_execute_explicit_version_includes_prerelease
+    util_setup_fake_fetcher(:prerelease)
+    util_setup_spec_fetcher @a2, @a2_pre
+
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2.file_name))
+    @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2_pre.file_name))
+
+    @cmd.handle_options [@a2_pre.name, '--version', @a2_pre.version.to_s]
+    assert @cmd.options[:prerelease]
+    assert @cmd.options[:version].satisfied_by?(@a2_pre.version)
+
+    use_ui @ui do
+      e = assert_raises Gem::SystemExitException do
+        @cmd.execute
+      end
+      assert_equal 0, e.exit_code, @ui.error
+    end
+
+    refute_match(/Successfully installed #{@a2.full_name}$/, @ui.output)
+    assert_match(/Successfully installed #{@a2_pre.full_name}$/, @ui.output)
+  end
+
+  def test_execute_include_dependencies
+    @cmd.options[:include_dependencies] = true
+    @cmd.options[:args] = []
+
+    assert_raises Gem::CommandLineError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    output = @ui.output.split "\n"
+    assert_equal "INFO:  `gem install -y` is now default and will be removed",
+                 output.shift
+    assert_equal "INFO:  use --ignore-dependencies to install only the gems you list",
+                 output.shift
+    assert output.empty?, output.inspect
+  end
+
+  def test_execute_local
+    util_setup_fake_fetcher
+    @cmd.options[:domain] = :local
+
+    FileUtils.mv File.join(@gemhome, 'cache', @a2.file_name),
+                 File.join(@tempdir)
+
+    @cmd.options[:args] = [@a2.name]
+
+    use_ui @ui do
+      orig_dir = Dir.pwd
+      begin
+        Dir.chdir @tempdir
+        e = assert_raises Gem::SystemExitException do
+          @cmd.execute
+        end
+        assert_equal 0, e.exit_code
+      ensure
+        Dir.chdir orig_dir
+      end
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Successfully installed #{@a2.full_name}", out.shift
+    assert_equal "1 gem installed", out.shift
+    assert out.empty?, out.inspect
+  end
+
+  def test_no_user_install
+    skip 'skipped on MS Windows (chmod has no effect)' if win_platform?
+
+    util_setup_fake_fetcher
+    @cmd.options[:user_install] = false
+
+    FileUtils.mv File.join(@gemhome, 'cache', @a2.file_name),
+                 File.join(@tempdir)
+
+    @cmd.options[:args] = [@a2.name]
+
+    use_ui @ui do
+      orig_dir = Dir.pwd
+      begin
+        File.chmod 0755, @userhome
+        File.chmod 0555, @gemhome
+
+        Dir.chdir @tempdir
+        assert_raises Gem::FilePermissionError do
+          @cmd.execute
+        end
+      ensure
+        Dir.chdir orig_dir
+        File.chmod 0755, @gemhome
+      end
+    end
+  end
+
+  def test_execute_local_missing
+    util_setup_fake_fetcher
+    @cmd.options[:domain] = :local
+
+    @cmd.options[:args] = %w[no_such_gem]
+
+    use_ui @ui do
+      e = assert_raises Gem::SystemExitException do
+        @cmd.execute
+      end
+      assert_equal 2, e.exit_code
+    end
+
+    # HACK no repository was checked
+    assert_equal "ERROR:  could not find gem no_such_gem locally or in a repository\n",
+                 @ui.error
+  end
+
+  def test_execute_no_gem
+    @cmd.options[:args] = %w[]
+
+    assert_raises Gem::CommandLineError do
+      @cmd.execute
+    end
+  end
+
+  def test_execute_nonexistent
+    util_setup_fake_fetcher
+    util_setup_spec_fetcher
+
+    @cmd.options[:args] = %w[nonexistent]
+
+    use_ui @ui do
+      e = assert_raises Gem::SystemExitException do
+        @cmd.execute
+      end
+      assert_equal 2, e.exit_code
+    end
+
+    assert_equal "ERROR:  could not find gem nonexistent locally or in a repository\n",
+                 @ui.error
+  end
+
+  def test_execute_prerelease
+    util_setup_fake_fetcher(:prerelease)
+    util_setup_spec_fetcher @a2, @a2_pre
+
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2.file_name))
+    @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2_pre.file_name))
+
+    @cmd.options[:prerelease] = true
+    @cmd.options[:args] = [@a2_pre.name]
+
+    use_ui @ui do
+      e = assert_raises Gem::SystemExitException do
+        @cmd.execute
+      end
+      assert_equal 0, e.exit_code, @ui.error
+    end
+
+    refute_match(/Successfully installed #{@a2.full_name}$/, @ui.output)
+    assert_match(/Successfully installed #{@a2_pre.full_name}$/, @ui.output)
+  end
+
+  def test_execute_remote
+    @cmd.options[:generate_rdoc] = true
+    @cmd.options[:generate_ri] = true
+
+    util_setup_fake_fetcher
+    util_setup_spec_fetcher @a2
+
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] =
+      read_binary(File.join(@gemhome, 'cache', @a2.file_name))
+
+    @cmd.options[:args] = [@a2.name]
+
+    use_ui @ui do
+      e = assert_raises Gem::SystemExitException do
+        capture_io do
+          @cmd.execute
+        end
+      end
+      assert_equal 0, e.exit_code
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Successfully installed #{@a2.full_name}", out.shift
+    assert_equal "1 gem installed", out.shift
+    assert_equal "Installing ri documentation for #{@a2.full_name}...",
+                 out.shift
+    assert_equal "Installing RDoc documentation for #{@a2.full_name}...",
+                 out.shift
+    assert out.empty?, out.inspect
+  end
+
+  def test_execute_two
+    util_setup_fake_fetcher
+    @cmd.options[:domain] = :local
+
+    FileUtils.mv File.join(@gemhome, 'cache', @a2.file_name),
+                 File.join(@tempdir)
+
+    FileUtils.mv File.join(@gemhome, 'cache', @b2.file_name),
+                 File.join(@tempdir)
+
+    @cmd.options[:args] = [@a2.name, @b2.name]
+
+    use_ui @ui do
+      orig_dir = Dir.pwd
+      begin
+        Dir.chdir @tempdir
+        e = assert_raises Gem::SystemExitException do
+          @cmd.execute
+        end
+        assert_equal 0, e.exit_code
+      ensure
+        Dir.chdir orig_dir
+      end
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Successfully installed #{@a2.full_name}", out.shift
+    assert_equal "Successfully installed #{@b2.full_name}", out.shift
+    assert_equal "2 gems installed", out.shift
+    assert out.empty?, out.inspect
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_list_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_list_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_list_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,36 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/list_command'
+
+class TestGemCommandsListCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::ListCommand.new
+
+    util_setup_fake_fetcher
+
+    @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+    @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+      raise Gem::RemoteFetcher::FetchError
+    end
+  end
+
+  def test_execute_installed
+    @cmd.handle_options %w[c --installed]
+
+    e = assert_raises Gem::SystemExitException do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal 0, e.exit_code
+
+    assert_equal "true\n", @ui.output
+
+    assert_equal '', @ui.error
+  end
+
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_lock_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_lock_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_lock_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,68 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/lock_command'
+
+class TestGemCommandsLockCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @a1 = quick_gem 'a', '1'
+    @b1 = quick_gem 'b', '1' do |s|
+      s.add_runtime_dependency 'a'
+    end
+
+    @d1 = quick_gem 'd', '1' do |s|
+      s.add_runtime_dependency 'z'
+    end
+
+    @cmd = Gem::Commands::LockCommand.new
+  end
+
+  def test_execute
+    @cmd.handle_options %w[b-1]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EXPECTED
+require 'rubygems'
+gem 'b', '= 1'
+gem 'a', '= 1'
+    EXPECTED
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_missing_dependency
+    @cmd.handle_options %w[d-1]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EXPECTED
+require 'rubygems'
+gem 'd', '= 1'
+# Unable to satisfy 'z (>= 0, runtime)' from currently installed gems
+    EXPECTED
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_strict
+    @cmd.handle_options %w[c-1 --strict]
+
+    e = assert_raises Gem::Exception do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal 'Could not find gem c-1, try using the full name', e.message
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_mirror_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_mirror_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_mirror_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,60 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/indexer'
+require 'rubygems/commands/mirror_command'
+
+class TestGemCommandsMirrorCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::MirrorCommand.new
+  end
+
+  def test_execute
+    util_make_gems
+
+    gems_dir = File.join @tempdir, 'gems'
+    mirror = File.join @tempdir, 'mirror'
+
+    FileUtils.mkdir_p gems_dir
+    FileUtils.mkdir_p mirror
+
+    Dir[File.join(@gemhome, 'cache', '*.gem')].each do |gem|
+      FileUtils.mv gem, gems_dir
+    end
+
+    use_ui @ui do
+      Gem::Indexer.new(@tempdir).generate_index
+    end
+
+    orig_HOME = ENV['HOME']
+    ENV['HOME'] = @tempdir
+    Gem.instance_variable_set :@user_home, nil
+
+    File.open File.join(Gem.user_home, '.gemmirrorrc'), 'w' do |fp|
+      fp.puts "---"
+      # tempdir could be a drive+path (under windows)
+      if @tempdir.match(/[a-z]:/i)
+        fp.puts "- from: file:///#{@tempdir}"
+      else
+        fp.puts "- from: file://#{@tempdir}"
+      end
+      fp.puts "  to: #{mirror}"
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert File.exist?(File.join(mirror, 'gems', @a1.file_name))
+    assert File.exist?(File.join(mirror, 'gems', @a2.file_name))
+    assert File.exist?(File.join(mirror, 'gems', @b2.file_name))
+    assert File.exist?(File.join(mirror, 'gems', @c1_2.file_name))
+    assert File.exist?(File.join(mirror, "Marshal.#{@marshal_version}"))
+  ensure
+    orig_HOME.nil? ? ENV.delete('HOME') : ENV['HOME'] = orig_HOME
+    Gem.instance_variable_set :@user_home, nil
+  end
+
+end if ''.respond_to? :to_xs
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_outdated_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_outdated_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_outdated_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,40 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/outdated_command'
+
+class TestGemCommandsOutdatedCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::OutdatedCommand.new
+  end
+
+  def test_initialize
+    assert @cmd.handles?(%W[--platform #{Gem::Platform.local}])
+  end
+
+  def test_execute
+    local_01 = quick_gem 'foo', '0.1'
+    local_02 = quick_gem 'foo', '0.2'
+    remote_10 = quick_gem 'foo', '1.0'
+    remote_20 = quick_gem 'foo', '2.0'
+
+    remote_spec_file = File.join @gemhome, 'specifications', remote_10.spec_name
+    FileUtils.rm remote_spec_file
+
+    remote_spec_file = File.join @gemhome, 'specifications', remote_20.spec_name
+    FileUtils.rm remote_spec_file
+
+    @fetcher = Gem::FakeFetcher.new
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    util_setup_spec_fetcher remote_10, remote_20
+
+    use_ui @ui do @cmd.execute end
+
+    assert_equal "foo (0.2 < 2.0)\n", @ui.output
+    assert_equal "", @ui.error
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_pristine_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_pristine_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_pristine_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,108 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/pristine_command'
+
+class TestGemCommandsPristineCommand < RubyGemTestCase
+
+  def setup
+    super
+    @cmd = Gem::Commands::PristineCommand.new
+  end
+
+  def test_execute
+    a = quick_gem 'a' do |s| s.executables = %w[foo] end
+    FileUtils.mkdir_p File.join(@tempdir, 'bin')
+    File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp|
+      fp.puts "#!/usr/bin/ruby"
+    end
+
+    install_gem a
+
+    foo_path = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
+
+    File.open foo_path, 'w' do |io|
+      io.puts 'I changed it!'
+    end
+
+    @cmd.options[:args] = %w[a]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "#!/usr/bin/ruby\n", File.read(foo_path), foo_path
+
+    out = @ui.output.split "\n"
+
+    assert_equal "Restoring gem(s) to pristine condition...", out.shift
+    assert_equal "Restored #{a.full_name}", out.shift
+    assert_empty out, out.inspect
+  end
+
+  def test_execute_all
+    a = quick_gem 'a' do |s| s.executables = %w[foo] end
+    FileUtils.mkdir_p File.join(@tempdir, 'bin')
+    File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp|
+      fp.puts "#!/usr/bin/ruby"
+    end
+
+    install_gem a
+
+    gem_bin = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
+
+    FileUtils.rm gem_bin
+
+    @cmd.handle_options %w[--all]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert File.exist?(gem_bin)
+
+    out = @ui.output.split "\n"
+
+    assert_equal "Restoring gem(s) to pristine condition...", out.shift
+    assert_equal "Restored #{a.full_name}", out.shift
+    assert_empty out, out.inspect
+  end
+
+  def test_execute_missing_cache_gem
+    a = quick_gem 'a' do |s| s.executables = %w[foo] end
+    FileUtils.mkdir_p File.join(@tempdir, 'bin')
+    File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp|
+      fp.puts "#!/usr/bin/ruby"
+    end
+
+    install_gem a
+
+    FileUtils.rm File.join(@gemhome, 'cache', a.file_name)
+
+    @cmd.options[:args] = %w[a]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    out = @ui.output.split "\n"
+
+    assert_equal "Restoring gem\(s\) to pristine condition...", out.shift
+    assert_empty out, out.inspect
+
+    assert_equal "ERROR:  Cached gem for #{a.full_name} not found, use `gem install` to restore\n",
+                 @ui.error
+  end
+
+  def test_execute_no_gem
+    @cmd.options[:args] = %w[]
+
+    e = assert_raises Gem::CommandLineError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_match %r|specify a gem name|, e.message
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_query_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_query_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_query_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,377 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/query_command'
+
+class TestGemCommandsQueryCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::QueryCommand.new
+
+    util_setup_fake_fetcher
+
+    @si = util_setup_spec_fetcher @a1, @a2, @pl1, @a3a
+
+    @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+      raise Gem::RemoteFetcher::FetchError
+    end
+  end
+
+  def test_execute
+    @cmd.handle_options %w[-r]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2)
+pl (1)
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_all
+    a1_name = @a1.full_name
+    a2_name = @a2.full_name
+
+    @cmd.handle_options %w[-r --all]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2, 1)
+pl (1)
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_details
+    @a2.summary = 'This is a lot of text. ' * 4
+    @a2.authors = ['Abraham Lincoln', 'Hirohito']
+    @a2.homepage = 'http://a.example.com/'
+    @a2.rubyforge_project = 'rubygems'
+
+    @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+    @cmd.handle_options %w[-r -d]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2)
+    Authors: Abraham Lincoln, Hirohito
+    Rubyforge: http://rubyforge.org/projects/rubygems
+    Homepage: http://a.example.com/
+
+    This is a lot of text. This is a lot of text. This is a lot of text.
+    This is a lot of text.
+
+pl (1)
+    Platform: i386-linux
+    Author: A User
+    Homepage: http://example.com
+
+    this is a summary
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_details_platform
+    @a1.platform = 'x86-linux'
+
+    @a2.summary = 'This is a lot of text. ' * 4
+    @a2.authors = ['Abraham Lincoln', 'Hirohito']
+    @a2.homepage = 'http://a.example.com/'
+    @a2.rubyforge_project = 'rubygems'
+    @a2.platform = 'universal-darwin'
+
+    @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+    @cmd.handle_options %w[-r -d]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2, 1)
+    Platforms:
+        1: x86-linux
+        2: universal-darwin
+    Authors: Abraham Lincoln, Hirohito
+    Rubyforge: http://rubyforge.org/projects/rubygems
+    Homepage: http://a.example.com/
+
+    This is a lot of text. This is a lot of text. This is a lot of text.
+    This is a lot of text.
+
+pl (1)
+    Platform: i386-linux
+    Author: A User
+    Homepage: http://example.com
+
+    this is a summary
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_installed
+    @cmd.handle_options %w[-n c --installed]
+
+    e = assert_raises Gem::SystemExitException do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal 0, e.exit_code
+
+    assert_equal "true\n", @ui.output
+
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_installed_no_name
+    @cmd.handle_options %w[--installed]
+
+    e = assert_raises Gem::SystemExitException do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal '', @ui.output
+    assert_equal "ERROR:  You must specify a gem name\n", @ui.error
+
+    assert_equal 4, e.exit_code
+  end
+
+  def test_execute_installed_not_installed
+    @cmd.handle_options %w[-n not_installed --installed]
+
+    e = assert_raises Gem::SystemExitException do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal "false\n", @ui.output
+    assert_equal '', @ui.error
+
+    assert_equal 1, e.exit_code
+  end
+
+  def test_execute_installed_version
+    @cmd.handle_options %w[-n c --installed --version 1.2]
+
+    e = assert_raises Gem::SystemExitException do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal "true\n", @ui.output
+    assert_equal '', @ui.error
+
+    assert_equal 0, e.exit_code
+  end
+
+  def test_execute_installed_version_not_installed
+    @cmd.handle_options %w[-n c --installed --version 2]
+
+    e = assert_raises Gem::SystemExitException do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal "false\n", @ui.output
+    assert_equal '', @ui.error
+
+    assert_equal 1, e.exit_code
+  end
+
+  def test_execute_local_details
+    @a3a.summary = 'This is a lot of text. ' * 4
+    @a3a.authors = ['Abraham Lincoln', 'Hirohito']
+    @a3a.homepage = 'http://a.example.com/'
+    @a3a.rubyforge_project = 'rubygems'
+
+    @cmd.handle_options %w[--local --details]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** LOCAL GEMS ***
+
+a (3.a, 2, 1)
+    Author: A User
+    Homepage: http://example.com
+    Installed at (3.a): #{@gemhome}
+                 (2): #{@gemhome}
+                 (1): #{@gemhome}
+
+    this is a summary
+
+a_evil (9)
+    Author: A User
+    Homepage: http://example.com
+    Installed at: #{@gemhome}
+
+    this is a summary
+
+b (2)
+    Author: A User
+    Homepage: http://example.com
+    Installed at: #{@gemhome}
+
+    this is a summary
+
+c (1.2)
+    Author: A User
+    Homepage: http://example.com
+    Installed at: #{@gemhome}
+
+    this is a summary
+
+pl (1)
+    Platform: i386-linux
+    Author: A User
+    Homepage: http://example.com
+    Installed at: #{@gemhome}
+
+    this is a summary
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_local_notty
+    @cmd.handle_options %w[]
+
+    @ui.outs.tty = false
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+a (3.a, 2, 1)
+a_evil (9)
+b (2)
+c (1.2)
+pl (1)
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_no_versions
+    @cmd.handle_options %w[-r --no-versions]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a
+pl
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_notty
+    @cmd.handle_options %w[-r]
+
+    @ui.outs.tty = false
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+a (2)
+pl (1)
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_prerelease
+    @cmd.handle_options %w[-r --prerelease]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (3.a)
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_prerelease_local
+    @cmd.handle_options %w[-l --prerelease]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** LOCAL GEMS ***
+
+a (3.a, 2, 1)
+a_evil (9)
+b (2)
+c (1.2)
+pl (1)
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal "WARNING:  prereleases are always shown locally\n", @ui.error
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_server_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_server_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_server_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,52 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/server_command'
+
+class TestGemCommandsServerCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::ServerCommand.new
+  end
+
+  def test_handle_options
+    @cmd.send :handle_options, %w[-p 8808 --no-daemon]
+
+    assert_equal false, @cmd.options[:daemon]
+    assert_equal @gemhome, @cmd.options[:gemdir]
+    assert_equal 8808, @cmd.options[:port]
+
+    @cmd.send :handle_options, %w[-p 9999 -d /nonexistent --daemon]
+
+    assert_equal true, @cmd.options[:daemon]
+    assert_equal File.expand_path('/nonexistent'), @cmd.options[:gemdir]
+    assert_equal 9999, @cmd.options[:port]
+  end
+
+  def test_handle_options_port
+    @cmd.send :handle_options, %w[-p 0]
+    assert_equal 0, @cmd.options[:port]
+
+    @cmd.send :handle_options, %w[-p 65535]
+    assert_equal 65535, @cmd.options[:port]
+
+    @cmd.send :handle_options, %w[-p http]
+    assert_equal 80, @cmd.options[:port]
+
+    e = assert_raises OptionParser::InvalidArgument do
+      @cmd.send :handle_options, %w[-p nonexistent]
+    end
+
+    assert_equal 'invalid argument: -p nonexistent: no such named service',
+                 e.message
+
+    e = assert_raises OptionParser::InvalidArgument do
+      @cmd.send :handle_options, %w[-p 65536]
+    end
+
+    assert_equal 'invalid argument: -p 65536: not a port number',
+                 e.message
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_sources_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_sources_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_sources_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,209 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/sources_command'
+
+class TestGemCommandsSourcesCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::SourcesCommand.new
+
+    @new_repo = "http://beta-gems.example.com"
+  end
+
+  def test_initialize_proxy
+    assert @cmd.handles?(['--http-proxy', 'http://proxy.example.com'])
+  end
+
+  def test_execute
+    util_setup_spec_fetcher
+    @cmd.handle_options []
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+*** CURRENT SOURCES ***
+
+#{@gem_repo}
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_add
+    util_setup_fake_fetcher
+
+    si = Gem::SourceIndex.new
+    si.add_spec @a1
+
+    specs = si.map do |_, spec|
+      [spec.name, spec.version, spec.original_platform]
+    end
+
+    specs_dump_gz = StringIO.new
+    Zlib::GzipWriter.wrap specs_dump_gz do |io|
+      Marshal.dump specs, io
+    end
+
+    @fetcher.data["#{@new_repo}/specs.#{@marshal_version}.gz"] =
+      specs_dump_gz.string
+
+    @cmd.handle_options %W[--add #{@new_repo}]
+
+    util_setup_spec_fetcher
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal [@gem_repo, @new_repo], Gem.sources
+
+    expected = <<-EOF
+#{@new_repo} added to sources
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_add_nonexistent_source
+    util_setup_fake_fetcher
+
+    uri = "http://beta-gems.example.com/specs.#{@marshal_version}.gz"
+    @fetcher.data[uri] = proc do
+      raise Gem::RemoteFetcher::FetchError.new('it died', uri)
+    end
+
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    @cmd.handle_options %w[--add http://beta-gems.example.com]
+
+    util_setup_spec_fetcher
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+Error fetching http://beta-gems.example.com:
+\tit died (#{uri})
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_add_bad_uri
+    @cmd.handle_options %w[--add beta-gems.example.com]
+
+    util_setup_spec_fetcher
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal [@gem_repo], Gem.sources
+
+    expected = <<-EOF
+beta-gems.example.com is not a URI
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_clear_all
+    @cmd.handle_options %w[--clear-all]
+
+    util_setup_spec_fetcher
+
+    fetcher = Gem::SpecFetcher.fetcher
+
+    # HACK figure out how to force directory creation via fetcher
+    #assert File.directory?(fetcher.dir), 'cache dir exists'
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+*** Removed specs cache ***
+*** Removed user source cache ***
+*** Removed latest user source cache ***
+*** Removed system source cache ***
+*** Removed latest system source cache ***
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+
+    refute File.exist?(fetcher.dir), 'cache dir removed'
+  end
+
+  def test_execute_remove
+    @cmd.handle_options %W[--remove #{@gem_repo}]
+
+    util_setup_spec_fetcher
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = "#{@gem_repo} removed from sources\n"
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_remove_no_network
+    @cmd.handle_options %W[--remove #{@gem_repo}]
+
+    util_setup_fake_fetcher
+
+    @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+      raise Gem::RemoteFetcher::FetchError
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = "#{@gem_repo} removed from sources\n"
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_update
+    @cmd.handle_options %w[--update]
+
+    util_setup_fake_fetcher
+    source_index = util_setup_spec_fetcher @a1
+
+    specs = source_index.map do |name, spec|
+      [spec.name, spec.version, spec.original_platform]
+    end
+
+    @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] =
+      util_gzip Marshal.dump(specs)
+
+    latest_specs = source_index.latest_specs.map do |spec|
+      [spec.name, spec.version, spec.original_platform]
+    end
+
+    @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
+      util_gzip Marshal.dump(latest_specs)
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "source cache successfully updated\n", @ui.output
+    assert_equal '', @ui.error
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_specification_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_specification_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_specification_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,139 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/specification_command'
+
+class TestGemCommandsSpecificationCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::SpecificationCommand.new
+  end
+
+  def test_execute
+    foo = quick_gem 'foo'
+    Gem.source_index.add_spec foo
+
+    @cmd.options[:args] = %w[foo]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|Gem::Specification|, @ui.output
+    assert_match %r|name: foo|, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_all
+    foo1 = quick_gem 'foo', '0.0.1'
+    foo2 = quick_gem 'foo', '0.0.2'
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:all] = true
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|Gem::Specification|, @ui.output
+    assert_match %r|name: foo|, @ui.output
+    assert_match %r|version: 0.0.1|, @ui.output
+    assert_match %r|version: 0.0.2|, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_bad_name
+    @cmd.options[:args] = %w[foo]
+
+    assert_raises MockGemUi::TermError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_equal '', @ui.output
+    assert_equal "ERROR:  Unknown gem 'foo'\n", @ui.error
+  end
+
+  def test_execute_exact_match
+    foo = quick_gem 'foo'
+    foo_bar = quick_gem 'foo_bar'
+
+    @cmd.options[:args] = %w[foo]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|Gem::Specification|, @ui.output
+    assert_match %r|name: foo|, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_field
+    foo = quick_gem 'foo'
+    Gem.source_index.add_spec foo
+
+    @cmd.options[:args] = %w[foo name]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal "--- foo\n\n", @ui.output
+  end
+
+  def test_execute_marshal
+    foo = quick_gem 'foo'
+    Gem.source_index.add_spec foo
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:format] = :marshal
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_equal foo, Marshal.load(@ui.output)
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_remote
+    foo = quick_gem 'foo'
+
+    @fetcher = Gem::FakeFetcher.new
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    util_setup_spec_fetcher foo
+
+    FileUtils.rm File.join(@gemhome, 'specifications', foo.spec_name)
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:domain] = :remote
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output
+    assert_match %r|name: foo|, @ui.output
+  end
+
+  def test_execute_ruby
+    foo = quick_gem 'foo'
+    Gem.source_index.add_spec foo
+
+    @cmd.options[:args] = %w[foo]
+    @cmd.options[:format] = :ruby
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    assert_match %r|Gem::Specification.new|, @ui.output
+    assert_match %r|s.name = %q\{foo\}|, @ui.output
+    assert_equal '', @ui.error
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_stale_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_stale_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_stale_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,38 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/stale_command'
+
+class TestGemCommandsStaleCommand < RubyGemTestCase
+
+  def setup
+    super
+    @cmd = Gem::Commands::StaleCommand.new
+  end
+
+  def test_execute_sorts
+    files = %w[lib/foo_bar.rb Rakefile]
+    foo_bar = quick_gem 'foo_bar' do |gem|
+      gem.files = files
+    end
+    bar_baz = quick_gem 'bar_baz' do |gem|
+      gem.files = files
+    end
+
+    files.each do |file|
+      filename = bar_baz.full_gem_path + "/#{file}"
+      FileUtils.mkdir_p(File.dirname(filename))
+      FileUtils.touch(filename, :mtime => Time.now)
+
+      filename = foo_bar.full_gem_path + "/#{file}"
+      FileUtils.mkdir_p(File.dirname(filename))
+      FileUtils.touch(filename, :mtime => Time.now - 86400)
+    end
+
+    use_ui @ui do
+      @cmd.execute
+    end
+    lines = @ui.output.split("\n")
+    assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first)
+    assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first)
+  end
+
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_uninstall_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_uninstall_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_uninstall_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,82 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_installer_test_case')
+require 'rubygems/commands/uninstall_command'
+
+class TestGemCommandsUninstallCommand < GemInstallerTestCase
+
+  def setup
+    super
+
+    ui = MockGemUi.new
+    util_setup_gem ui
+
+    build_rake_in do
+      use_ui ui do
+        @installer.install
+      end
+    end
+
+    @cmd = Gem::Commands::UninstallCommand.new
+    @cmd.options[:executables] = true
+    @executable = File.join(@gemhome, 'bin', 'executable')
+  end
+
+  def test_execute_removes_executable
+    if win_platform?
+      assert_equal true, File.exist?(@executable)
+    else
+      assert_equal true, File.symlink?(@executable)
+    end
+
+    # Evil hack to prevent false removal success
+    FileUtils.rm_f @executable
+    File.open(@executable, "wb+") {|f| f.puts "binary"}
+
+    @cmd.options[:args] = Array(@spec.name)
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    output = @ui.output.split "\n"
+    assert_match(/Removing executable/, output.shift)
+    assert_match(/Successfully uninstalled/, output.shift)
+    assert_equal false, File.exist?(@executable)
+    assert_nil output.shift, "UI output should have contained only two lines"
+  end
+
+  def test_execute_not_installed
+    @cmd.options[:args] = ["foo"]
+    e = assert_raises Gem::InstallError do
+      use_ui @ui do
+        @cmd.execute
+      end
+    end
+
+    assert_match(/\Acannot uninstall, check `gem list -d foo`$/, e.message)
+    output = @ui.output.split "\n"
+    assert_empty output, "UI output should be empty after an uninstall error"
+  end
+
+  def test_execute_prerelease
+    @spec = quick_gem "pre", "2.b"
+    @gem = File.join @tempdir, @spec.file_name
+    FileUtils.touch @gem
+
+    util_setup_gem
+
+    use_ui @ui do
+      @installer.install
+    end
+
+    @cmd.options[:args] = ["pre"]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    output = @ui.output
+    assert_match(/Successfully uninstalled/, output)
+  end
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_unpack_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_unpack_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_unpack_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,115 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/unpack_command'
+
+class TestGemCommandsUnpackCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    Dir.chdir @tempdir do
+      @cmd = Gem::Commands::UnpackCommand.new
+    end
+  end
+
+  def test_execute
+    util_make_gems
+
+    @cmd.options[:args] = %w[a b]
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    assert File.exist?(File.join(@tempdir, 'a-3.a')), 'a should be installed'
+    assert File.exist?(File.join(@tempdir, 'b-2')),   'b should be installed'
+  end
+
+  def test_execute_gem_path
+    util_make_gems
+
+    Gem.clear_paths
+
+    gemhome2 = File.join @tempdir, 'gemhome2'
+
+    Gem.send :set_paths, [gemhome2, @gemhome].join(File::PATH_SEPARATOR)
+    Gem.send :set_home, gemhome2
+
+    @cmd.options[:args] = %w[a]
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    assert File.exist?(File.join(@tempdir, 'a-3.a'))
+  end
+
+  def test_execute_gem_path_missing
+    util_make_gems
+
+    Gem.clear_paths
+
+    gemhome2 = File.join @tempdir, 'gemhome2'
+
+    Gem.send :set_paths, [gemhome2, @gemhome].join(File::PATH_SEPARATOR)
+    Gem.send :set_home, gemhome2
+
+    @cmd.options[:args] = %w[z]
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    assert_equal '', @ui.output
+  end
+
+  def test_execute_with_target_option
+    util_make_gems
+
+    target = 'with_target'
+    @cmd.options[:args] = %w[a]
+    @cmd.options[:target] = target
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    assert File.exist?(File.join(@tempdir, target, 'a-3.a'))
+  end
+
+  def test_execute_exact_match
+    foo_spec = quick_gem 'foo'
+    foo_bar_spec = quick_gem 'foo_bar'
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        Gem::Builder.new(foo_spec).build
+        Gem::Builder.new(foo_bar_spec).build
+      end
+    end
+
+    foo_path = File.join(@tempdir, "#{foo_spec.full_name}.gem")
+    foo_bar_path = File.join(@tempdir, "#{foo_bar_spec.full_name}.gem")
+    Gem::Installer.new(foo_path).install
+    Gem::Installer.new(foo_bar_path).install
+
+    @cmd.options[:args] = %w[foo]
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        @cmd.execute
+      end
+    end
+
+    assert File.exist?(File.join(@tempdir, foo_spec.full_name))
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_update_command.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_update_command.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_commands_update_command.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,169 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/update_command'
+
+class TestGemCommandsUpdateCommand < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Commands::UpdateCommand.new
+
+    @cmd.options[:generate_rdoc] = false
+    @cmd.options[:generate_ri]   = false
+
+    util_setup_fake_fetcher
+
+    @a1_path = File.join @gemhome, 'cache', @a1.file_name
+    @a2_path = File.join @gemhome, 'cache', @a2.file_name
+
+    util_setup_spec_fetcher @a1, @a2
+
+    @fetcher.data["#{@gem_repo}gems/#{@a1.file_name}"] =
+      read_binary @a1_path
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] =
+      read_binary @a2_path
+  end
+
+  def test_execute
+    util_clear_gems
+
+    Gem::Installer.new(@a1_path).install
+
+    @cmd.options[:args] = []
+    @cmd.options[:generate_rdoc] = true
+    @cmd.options[:generate_ri]   = true
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Updating installed gems", out.shift
+    assert_equal "Updating #{@a2.name}", out.shift
+    assert_equal "Successfully installed #{@a2.full_name}", out.shift
+    assert_equal "Gems updated: #{@a2.name}", out.shift
+    assert_equal "Installing ri documentation for a-2...", out.shift
+    assert_equal "Installing RDoc documentation for a-2...", out.shift
+
+    assert_empty out
+  end
+
+  # before:
+  #   a1 -> c1.2
+  # after:
+  #   a2 -> b2 # new dependency
+  #   a2 -> c2
+
+  def test_execute_dependencies
+    @a1.add_dependency 'c', '1.2'
+
+    @c2 = quick_gem 'c', '2' do |s|
+      s.files = %w[lib/code.rb]
+      s.require_paths = %w[lib]
+    end
+
+    @a2.add_dependency 'c', '2'
+    @a2.add_dependency 'b', '2'
+
+    @b2_path = File.join @gemhome, 'cache', @b2.file_name
+    @c1_2_path = File.join @gemhome, 'cache', @c1_2.file_name
+    @c2_path = File.join @gemhome, 'cache', @c2.file_name
+
+    @source_index = Gem::SourceIndex.new
+    @source_index.add_spec @a1
+    @source_index.add_spec @a2
+    @source_index.add_spec @b2
+    @source_index.add_spec @c1_2
+    @source_index.add_spec @c2
+
+    util_build_gem @a1
+    util_build_gem @a2
+    util_build_gem @c2
+
+    @fetcher.data["#{@gem_repo}gems/#{@a1.file_name}"] = read_binary @a1_path
+    @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = read_binary @a2_path
+    @fetcher.data["#{@gem_repo}gems/#{@b2.file_name}"] = read_binary @b2_path
+    @fetcher.data["#{@gem_repo}gems/#{@c1_2.file_name}"] =
+      read_binary @c1_2_path
+    @fetcher.data["#{@gem_repo}gems/#{@c2.file_name}"] = read_binary @c2_path
+
+    util_setup_spec_fetcher @a1, @a2, @b2, @c1_2, @c2
+    util_clear_gems
+
+    Gem::Installer.new(@c1_2_path).install
+    Gem::Installer.new(@a1_path).install
+
+    @cmd.options[:args] = []
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Updating installed gems", out.shift
+    assert_equal "Updating #{@a2.name}", out.shift
+    assert_equal "Successfully installed #{@c2.full_name}", out.shift
+    assert_equal "Successfully installed #{@b2.full_name}", out.shift
+    assert_equal "Successfully installed #{@a2.full_name}", out.shift
+    assert_equal "Gems updated: #{@c2.name}, #{@b2.name}, #{@a2.name}",
+                 out.shift
+
+    assert_empty out
+  end
+
+  def test_execute_named
+    util_clear_gems
+
+    Gem::Installer.new(@a1_path).install
+
+    @cmd.options[:args] = [@a1.name]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Updating installed gems", out.shift
+    assert_equal "Updating #{@a2.name}", out.shift
+    assert_equal "Successfully installed #{@a2.full_name}", out.shift
+    assert_equal "Gems updated: #{@a2.name}", out.shift
+
+    assert_empty out
+  end
+
+  def test_execute_named_up_to_date
+    util_clear_gems
+
+    Gem::Installer.new(@a2_path).install
+
+    @cmd.options[:args] = [@a2.name]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Updating installed gems", out.shift
+    assert_equal "Nothing to update", out.shift
+
+    assert_empty out
+  end
+
+  def test_execute_up_to_date
+    util_clear_gems
+
+    Gem::Installer.new(@a2_path).install
+
+    @cmd.options[:args] = []
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    out = @ui.output.split "\n"
+    assert_equal "Updating installed gems", out.shift
+    assert_equal "Nothing to update", out.shift
+
+    assert_empty out
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_config_file.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_config_file.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_config_file.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,279 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/config_file'
+
+class TestGemConfigFile < RubyGemTestCase
+
+  def setup
+    super
+
+    @temp_conf = File.join @tempdir, '.gemrc'
+
+    @cfg_args = %W[--config-file #{@temp_conf}]
+
+    @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
+    Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
+    Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
+                         File.join(@tempdir, 'system-gemrc')
+    Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
+    Gem::ConfigFile::PLATFORM_DEFAULTS.clear
+
+    util_config_file
+  end
+
+  def teardown
+    Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
+    Gem::ConfigFile::PLATFORM_DEFAULTS.clear
+    Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
+    Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
+                         @orig_SYSTEM_WIDE_CONFIG_FILE
+
+    super
+  end
+
+  def test_initialize
+    assert_equal @temp_conf, @cfg.config_file_name
+
+    assert_equal false, @cfg.backtrace
+    assert_equal true, @cfg.update_sources
+    assert_equal false, @cfg.benchmark
+    assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold
+    assert_equal true, @cfg.verbose
+    assert_equal [@gem_repo], Gem.sources
+
+    File.open @temp_conf, 'w' do |fp|
+      fp.puts ":backtrace: true"
+      fp.puts ":update_sources: false"
+      fp.puts ":benchmark: true"
+      fp.puts ":bulk_threshold: 10"
+      fp.puts ":verbose: false"
+      fp.puts ":sources:"
+      fp.puts "  - http://more-gems.example.com"
+      fp.puts "install: --wrappers"
+      fp.puts ":gempath:"
+      fp.puts "- /usr/ruby/1.8/lib/ruby/gems/1.8"
+      fp.puts "- /var/ruby/1.8/gem_home"
+    end
+
+    util_config_file
+
+    assert_equal true, @cfg.backtrace
+    assert_equal true, @cfg.benchmark
+    assert_equal 10, @cfg.bulk_threshold
+    assert_equal false, @cfg.verbose
+    assert_equal false, @cfg.update_sources
+    assert_equal %w[http://more-gems.example.com], Gem.sources
+    assert_equal '--wrappers', @cfg[:install]
+    assert_equal(['/usr/ruby/1.8/lib/ruby/gems/1.8', '/var/ruby/1.8/gem_home'],
+                 @cfg.path)
+  end
+
+  def test_initialize_handle_arguments_config_file
+    util_config_file %W[--config-file #{@temp_conf}]
+
+    assert_equal @temp_conf, @cfg.config_file_name
+  end
+
+  def test_initialize_handle_arguments_config_file_with_other_params
+    util_config_file %W[--config-file #{@temp_conf} --backtrace]
+
+    assert_equal @temp_conf, @cfg.config_file_name
+  end
+
+  def test_initialize_handle_arguments_config_file_equals
+    util_config_file %W[--config-file=#{@temp_conf}]
+
+    assert_equal @temp_conf, @cfg.config_file_name
+  end
+
+  def test_initialize_operating_system_override
+    Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS[:bulk_threshold] = 1
+    Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS['install'] = '--no-env-shebang'
+
+    Gem::ConfigFile::PLATFORM_DEFAULTS[:bulk_threshold] = 2
+
+    util_config_file
+
+    assert_equal 2, @cfg.bulk_threshold
+    assert_equal '--no-env-shebang', @cfg[:install]
+  end
+
+  def test_initialize_platform_override
+    Gem::ConfigFile::PLATFORM_DEFAULTS[:bulk_threshold] = 2
+    Gem::ConfigFile::PLATFORM_DEFAULTS['install'] = '--no-env-shebang'
+
+    File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, 'w' do |fp|
+      fp.puts ":bulk_threshold: 3"
+    end
+
+    util_config_file
+
+    assert_equal 3, @cfg.bulk_threshold
+    assert_equal '--no-env-shebang', @cfg[:install]
+  end
+
+  def test_initialize_system_wide_override
+    File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, 'w' do |fp|
+      fp.puts ":backtrace: false"
+      fp.puts ":bulk_threshold: 2048"
+    end
+
+    File.open @temp_conf, 'w' do |fp|
+      fp.puts ":backtrace: true"
+    end
+
+    util_config_file
+
+    assert_equal 2048, @cfg.bulk_threshold
+    assert_equal true, @cfg.backtrace
+  end
+
+  def test_handle_arguments
+    args = %w[--backtrace --bunch --of --args here]
+
+    @cfg.handle_arguments args
+
+    assert_equal %w[--bunch --of --args here], @cfg.args
+  end
+
+  def test_handle_arguments_backtrace
+    assert_equal false, @cfg.backtrace
+
+    args = %w[--backtrace]
+
+    @cfg.handle_arguments args
+
+    assert_equal true, @cfg.backtrace
+  end
+
+  def test_handle_arguments_benchmark
+    assert_equal false, @cfg.benchmark
+
+    args = %w[--benchmark]
+
+    @cfg.handle_arguments args
+
+    assert_equal true, @cfg.benchmark
+  end
+
+  def test_handle_arguments_debug
+    old_dollar_DEBUG = $DEBUG
+    assert_equal false, $DEBUG
+
+    args = %w[--debug]
+
+    @cfg.handle_arguments args
+
+    assert_equal true, $DEBUG
+  ensure
+    $DEBUG = old_dollar_DEBUG
+  end
+
+  def test_handle_arguments_override
+    File.open @temp_conf, 'w' do |fp|
+      fp.puts ":benchmark: false"
+    end
+
+    util_config_file %W[--benchmark --config-file=#{@temp_conf}]
+
+    assert_equal true, @cfg.benchmark
+  end
+
+  def test_handle_arguments_traceback
+    assert_equal false, @cfg.backtrace
+
+    args = %w[--traceback]
+
+    @cfg.handle_arguments args
+
+    assert_equal true, @cfg.backtrace
+  end
+
+  def test_really_verbose
+    assert_equal false, @cfg.really_verbose
+
+    @cfg.verbose = true
+
+    assert_equal false, @cfg.really_verbose
+
+    @cfg.verbose = 1
+
+    assert_equal true, @cfg.really_verbose
+  end
+
+  def test_write
+    @cfg.backtrace = true
+    @cfg.benchmark = true
+    @cfg.update_sources = false
+    @cfg.bulk_threshold = 10
+    @cfg.verbose = false
+    Gem.sources.replace %w[http://more-gems.example.com]
+    @cfg[:install] = '--wrappers'
+
+    @cfg.write
+
+    util_config_file
+
+    # These should not be written out to the config file.
+    assert_equal false, @cfg.backtrace,     'backtrace'
+    assert_equal false, @cfg.benchmark,     'benchmark'
+    assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold,
+                 'bulk_threshold'
+    assert_equal true, @cfg.update_sources, 'update_sources'
+    assert_equal true, @cfg.verbose,        'verbose'
+
+    assert_equal '--wrappers', @cfg[:install], 'install'
+
+    # this should be written out to the config file.
+    assert_equal %w[http://more-gems.example.com], Gem.sources
+  end
+
+  def test_write_from_hash
+    File.open @temp_conf, 'w' do |fp|
+      fp.puts ":backtrace: true"
+      fp.puts ":benchmark: true"
+      fp.puts ":bulk_threshold: 10"
+      fp.puts ":update_sources: false"
+      fp.puts ":verbose: false"
+      fp.puts ":sources:"
+      fp.puts "  - http://more-gems.example.com"
+      fp.puts "install: --wrappers"
+    end
+
+    util_config_file
+
+    @cfg.backtrace = :junk
+    @cfg.benchmark = :junk
+    @cfg.update_sources = :junk
+    @cfg.bulk_threshold = 20
+    @cfg.verbose = :junk
+    Gem.sources.replace %w[http://even-more-gems.example.com]
+    @cfg[:install] = '--wrappers --no-rdoc'
+
+    @cfg.write
+
+    util_config_file
+
+    # These should not be written out to the config file
+    assert_equal true,  @cfg.backtrace,      'backtrace'
+    assert_equal true,  @cfg.benchmark,      'benchmark'
+    assert_equal 10,    @cfg.bulk_threshold, 'bulk_threshold'
+    assert_equal false, @cfg.update_sources, 'update_sources'
+    assert_equal false, @cfg.verbose,        'verbose'
+
+    assert_equal '--wrappers --no-rdoc', @cfg[:install], 'install'
+
+    assert_equal %w[http://even-more-gems.example.com], Gem.sources
+  end
+
+  def util_config_file(args = @cfg_args)
+    @cfg = Gem::ConfigFile.new args
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,315 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/version'
+
+class TestGemDependency < RubyGemTestCase
+
+  def setup
+    super
+
+    @pkg1_0 = Gem::Dependency.new 'pkg', ['> 1.0']
+    @pkg1_1 = Gem::Dependency.new 'pkg', ['> 1.1']
+
+    @oth1_0 = Gem::Dependency.new 'other', ['> 1.0']
+
+    @r1_0 = Gem::Requirement.new ['> 1.0']
+  end
+
+  def dep(name, version)
+    Gem::Dependency.new name, version
+  end
+
+  def test_initialize
+    assert_equal "pkg", @pkg1_0.name
+    assert_equal @r1_0, @pkg1_0.version_requirements
+  end
+
+  def test_initialize_double
+    dep = Gem::Dependency.new("pkg", ["> 1.0", "< 2.0"])
+
+    assert_equal Gem::Requirement.new(["> 1.0", "< 2.0"]),
+                 dep.version_requirements
+  end
+
+  def test_initialize_empty
+    dep = Gem::Dependency.new("pkg", [])
+    req = @r1_0
+
+    req.instance_eval do
+      @version = ">= 1.0"
+      @op = ">="
+      @nums = [1,0]
+      @requirements = nil
+    end
+
+    dep.instance_eval do
+      @version_requirement = req
+      @version_requirements = nil
+    end
+
+    assert_equal Gem::Requirement.new([">= 1.0"]), dep.version_requirements
+  end
+
+  def test_initialize_version
+    dep = Gem::Dependency.new 'pkg', Gem::Version.new('2')
+
+    assert_equal 'pkg', dep.name
+
+    assert_equal Gem::Requirement.new('= 2'), dep.version_requirements
+  end
+
+  def test_initialize_with_type
+    dep = Gem::Dependency.new("pkg", [], :development)
+    assert_equal(:development, dep.type)
+  end
+
+  def test_type_is_runtime_by_default
+    assert_equal(:runtime, Gem::Dependency.new("pkg", []).type)
+  end
+
+  def test_type_is_restricted
+    assert_raises ArgumentError do
+      Gem::Dependency.new("pkg", [:sometimes])
+    end
+  end
+
+  def test_equals2
+    assert_equal @pkg1_0, @pkg1_0.dup
+    assert_equal @pkg1_0.dup, @pkg1_0
+
+    refute_equal @pkg1_0, @pkg1_1, "requirements different"
+    refute_equal @pkg1_1, @pkg1_0, "requirements different"
+
+    refute_equal @pkg1_0, @oth1_0, "names different"
+    refute_equal @oth1_0, @pkg1_0, "names different"
+
+    refute_equal @pkg1_0, Object.new
+    refute_equal Object.new, @pkg1_0
+  end
+
+  def test_equals2_type
+    runtime = Gem::Dependency.new("pkg", [])
+    development = Gem::Dependency.new("pkg", [], :development)
+
+    refute_equal(runtime, development)
+  end
+
+  def test_equals_tilde
+    a0   = dep 'a', '0'
+    a1   = dep 'a', '1'
+    b0   = dep 'b', '0'
+
+    pa0  = dep 'a', '>= 0'
+    pa0r = dep(/a/, '>= 0')
+    pab0r = dep(/a|b/, '>= 0')
+
+    assert_match a0,    a0, 'match self'
+    assert_match pa0,   a0, 'match version exact'
+    assert_match pa0,   a1, 'match version'
+    assert_match pa0r,  a0, 'match regex simple'
+    assert_match pab0r, a0, 'match regex complex'
+
+    refute_match pa0r, b0,         'fail match regex'
+    refute_match pa0r, Object.new, 'fail match Object'
+  end
+
+  def test_equals_tilde_escape
+    a1 = Gem::Dependency.new 'a', '1'
+
+    pab1  = Gem::Dependency.new 'a|b', '>= 1'
+    pab1r = Gem::Dependency.new(/a|b/, '>= 1')
+
+    refute_match pab1,  a1, 'escaped'
+    assert_match pab1r, a1, 'exact regexp'
+  end
+
+  def test_equals_tilde_object
+    a0 = Object.new
+
+    def a0.name() 'a' end
+    def a0.version() '0' end
+
+    pa0  = Gem::Dependency.new 'a', '>= 0'
+
+    assert_match pa0, a0, 'match version exact'
+  end
+
+  def test_equals_tilde_spec
+    def spec(name, version)
+      Gem::Specification.new do |spec|
+        spec.name = name
+        spec.version = version
+      end
+    end
+
+    a0   = spec 'a', '0'
+    a1   = spec 'a', '1'
+    b0   = spec 'b', '0'
+
+    pa0  = dep 'a', '>= 0'
+    pa0r = dep(/a/, '>= 0')
+    pab0r = dep(/a|b/, '>= 0')
+
+    assert_match pa0, a0,   'match version exact'
+    assert_match pa0, a1,   'match version'
+
+    assert_match pa0r, a0,  'match regex simple'
+    assert_match pa0r, a1,  'match regex simple'
+
+    assert_match pab0r, a0, 'match regex complex'
+    assert_match pab0r, b0, 'match regex complex'
+
+    refute_match pa0r, b0,         'fail match regex'
+    refute_match pa0r, Object.new, 'fail match Object'
+  end
+
+  def test_hash
+    assert_equal @pkg1_0.hash, @pkg1_0.dup.hash
+    assert_equal @pkg1_0.dup.hash, @pkg1_0.hash
+
+    refute_equal @pkg1_0.hash, @pkg1_1.hash, "requirements different"
+    refute_equal @pkg1_1.hash, @pkg1_0.hash, "requirements different"
+
+    refute_equal @pkg1_0.hash, @oth1_0.hash, "names different"
+    refute_equal @oth1_0.hash, @pkg1_0.hash, "names different"
+  end
+
+  def test_hash_type
+    runtime = Gem::Dependency.new("pkg", [])
+    development = Gem::Dependency.new("pkg", [], :development)
+
+    refute_equal(runtime.hash, development.hash)
+  end
+
+  # FIX: Below this line are tests that used to be in TestGemVersion,
+  # but belong here. I'll be refactoring them along with Dependency.
+
+  def test_ok
+    assert_adequate( "0.2.33",      "= 0.2.33")
+    assert_adequate( "0.2.34",      "> 0.2.33")
+    assert_adequate( "1.0",         "= 1.0")
+    assert_adequate( "1.0",         "1.0")
+    assert_adequate( "1.8.2",       "> 1.8.0")
+    assert_adequate( "1.112",       "> 1.111")
+    assert_adequate( "0.2",         "> 0.0.0")
+    assert_adequate( "0.0.0.0.0.2", "> 0.0.0")
+    assert_adequate( "0.0.1.0",     "> 0.0.0.1")
+    assert_adequate( "10.3.2",      "> 9.3.2")
+    assert_adequate( "1.0.0.0",     "= 1.0")
+    assert_adequate( "10.3.2",      "!= 9.3.4")
+    assert_adequate( "10.3.2",      "> 9.3.2")
+    assert_adequate( "10.3.2",      "> 9.3.2")
+    assert_adequate( " 9.3.2",      ">= 9.3.2")
+    assert_adequate( "9.3.2 ",      ">= 9.3.2")
+    assert_adequate( "",            "= 0")
+    assert_adequate( "",            "< 0.1")
+    assert_adequate( "  ",          "< 0.1 ")
+    assert_adequate( "",            " <  0.1")
+    assert_adequate( "  ",          "> 0.a ")
+    assert_adequate( "",            " >  0.a")
+    assert_adequate( "0",           "=")
+    assert_adequate( "0",           ">=")
+    assert_adequate( "0",           "<=")
+    assert_adequate( "3.1",         "< 3.2.rc1")
+    assert_adequate( "3.2.0",       "> 3.2.0.rc1")
+    assert_adequate( "3.2.0.rc2",   "> 3.2.0.rc1")
+    assert_adequate( "3.0.rc2",     "< 3.0")
+    assert_adequate( "3.0.rc2",     "< 3.0.0")
+    assert_adequate( "3.0.rc2",     "< 3.0.1")
+  end
+
+  def test_illformed_requirements
+    [ ">>> 1.3.5", "> blah" ].each do |rq|
+      assert_raises ArgumentError, "req [#{rq}] should fail" do
+        Gem::Requirement.new rq
+      end
+    end
+  end
+
+  def test_satisfied_by_eh_boxed
+    assert_inadequate("1.3", "~> 1.4")
+    assert_adequate(  "1.4", "~> 1.4")
+    assert_adequate(  "1.5", "~> 1.4")
+    assert_inadequate("2.0", "~> 1.4")
+
+    assert_inadequate("1.3",   "~> 1.4.4")
+    assert_inadequate("1.4",   "~> 1.4.4")
+    assert_adequate(  "1.4.4", "~> 1.4.4")
+    assert_adequate(  "1.4.5", "~> 1.4.4")
+    assert_inadequate("1.5",   "~> 1.4.4")
+    assert_inadequate("2.0",   "~> 1.4.4")
+
+    assert_inadequate("1.1.pre", "~> 1.0.0")
+    assert_adequate(  "1.1.pre", "~> 1.1")
+    assert_inadequate("2.0.a",   "~> 1.0")
+    assert_adequate(  "2.0.a",   "~> 2.0")
+  end
+
+  def test_satisfied_by_eh_multiple
+    req = [">= 1.4", "<= 1.6", "!= 1.5"]
+    assert_inadequate("1.3", req)
+    assert_adequate(  "1.4", req)
+    assert_inadequate("1.5", req)
+    assert_adequate(  "1.6", req)
+    assert_inadequate("1.7", req)
+    assert_inadequate("2.0", req)
+  end
+
+  def test_boxed
+    assert_inadequate("1.3", "~> 1.4")
+    assert_adequate(  "1.4", "~> 1.4")
+    assert_adequate(  "1.5", "~> 1.4")
+    assert_inadequate("2.0", "~> 1.4")
+
+    assert_inadequate("1.3",   "~> 1.4.4")
+    assert_inadequate("1.4",   "~> 1.4.4")
+    assert_adequate(  "1.4.4", "~> 1.4.4")
+    assert_adequate(  "1.4.5", "~> 1.4.4")
+    assert_inadequate("1.5",   "~> 1.4.4")
+    assert_inadequate("2.0",   "~> 1.4.4")
+  end
+
+  def test_bad
+    assert_inadequate( "",            "> 0.1")
+    assert_inadequate( "1.2.3",       "!= 1.2.3")
+    assert_inadequate( "1.2.003.0.0", "!= 1.02.3")
+    assert_inadequate( "4.5.6",       "< 1.2.3")
+    assert_inadequate( "1.0",         "> 1.1")
+    assert_inadequate( "0",           ">")
+    assert_inadequate( "0",           "<")
+    assert_inadequate( "",            "= 0.1")
+    assert_inadequate( "1.1.1",       "> 1.1.1")
+    assert_inadequate( "1.2",         "= 1.1")
+    assert_inadequate( "1.40",        "= 1.1")
+    assert_inadequate( "1.3",         "= 1.40")
+    assert_inadequate( "9.3.3",       "<= 9.3.2")
+    assert_inadequate( "9.3.1",       ">= 9.3.2")
+    assert_inadequate( "9.3.03",      "<= 9.3.2")
+    assert_inadequate( "1.0.0.1",     "= 1.0")
+  end
+
+  # Assert that +version+ can fulfill +requirement+.
+
+  def assert_adequate version, requirement
+    ver = Gem::Version.create version
+    req = Gem::Requirement.new requirement
+
+    assert req.satisfied_by?(ver),
+      "Version #{version} should be adequate for Requirement #{requirement}"
+  end
+
+  # Assert that +version+ is unable to fulfill +requirement+.
+
+  def assert_inadequate version, requirement
+    ver = Gem::Version.create version
+    req = Gem::Requirement.new(requirement)
+
+    refute req.satisfied_by?(ver),
+      "Version #{version} should not be adequate for Requirement #{requirement}"
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_installer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_installer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_installer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,647 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/dependency_installer'
+
+class TestGemDependencyInstaller < RubyGemTestCase
+
+  def setup
+    super
+
+    @gems_dir = File.join @tempdir, 'gems'
+    @cache_dir = File.join @gemhome, 'cache'
+    FileUtils.mkdir @gems_dir
+
+    write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp|
+      fp.puts "#!/usr/bin/ruby"
+    end
+
+    @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
+    @aa1, @aa1_gem = util_gem 'aa', '1'
+    @a1_pre, @a1_pre_gem = util_gem 'a', '1.a'
+
+    @b1, @b1_gem = util_gem 'b', '1' do |s|
+      s.add_dependency 'a'
+      s.add_development_dependency 'aa'
+    end
+
+    @d1, @d1_gem = util_gem 'd', '1'
+    @d2, @d2_gem = util_gem 'd', '2'
+
+    @x1_m, @x1_m_gem = util_gem 'x', '1' do |s|
+      s.platform = Gem::Platform.new %w[cpu my_platform 1]
+    end
+
+    @x1_o, @x1_o_gem = util_gem 'x', '1' do |s|
+      s.platform = Gem::Platform.new %w[cpu other_platform 1]
+    end
+
+    @w1, @w1_gem = util_gem 'w', '1' do |s| s.add_dependency 'x' end
+
+    @y1, @y1_gem = util_gem 'y', '1'
+    @y1_1_p, @y1_1_p_gem = util_gem 'y', '1.1' do |s|
+      s.platform = Gem::Platform.new %w[cpu my_platform 1]
+    end
+
+    @z1, @z1_gem = util_gem 'z', '1'   do |s| s.add_dependency 'y' end
+
+    @fetcher = Gem::FakeFetcher.new
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    si = util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1, @d2, @x1_m, @x1_o, @w1, @y1,
+                                 @y1_1_p, @z1)
+
+    util_clear_gems
+  end
+
+  def test_install
+    FileUtils.mv @a1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'a'
+    end
+
+    assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
+                 Gem::SourceIndex.from_installed_gems
+
+    assert_equal [@a1], inst.installed_gems
+  end
+
+  def test_install_all_dependencies
+    e1, e1_gem = util_gem 'e', '1' do |s|
+      s.add_dependency 'b'
+    end
+
+    util_clear_gems
+
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    FileUtils.mv e1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :ignore_dependencies => true
+      inst.install 'b'
+    end
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'e'
+    end
+
+    assert_equal %w[e-1 a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_cache_dir
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
+      inst.install 'b'
+    end
+
+    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+
+    assert File.exist?(File.join(@tempdir, 'cache', @a1.file_name))
+    assert File.exist?(File.join(@tempdir, 'cache', @b1.file_name))
+  end
+
+  def test_install_dependencies_satisfied
+    a2, a2_gem = util_gem 'a', '2'
+
+    FileUtils.rm_rf File.join(@gemhome, 'gems')
+    Gem.source_index.refresh!
+
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv a2_gem, @tempdir # not in index
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'a-2'
+    end
+
+    FileUtils.rm File.join(@tempdir, a2.file_name)
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'b'
+    end
+
+    installed = Gem::SourceIndex.from_installed_gems.map { |n,s| s.full_name }
+
+    assert_equal %w[a-2 b-1], installed.sort
+
+    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_dependency
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'b'
+    end
+
+    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_dependency_development
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @aa1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new(:development => true)
+      inst.install 'b'
+    end
+
+    assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_dependency_existing
+    Gem::Installer.new(@a1_gem).install
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'b'
+    end
+
+    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_dependency_old
+    e1, e1_gem = util_gem 'e', '1'
+    f1, f1_gem = util_gem 'f', '1' do |s| s.add_dependency 'e' end
+    f2, f2_gem = util_gem 'f', '2'
+
+    FileUtils.mv e1_gem, @tempdir
+    FileUtils.mv f1_gem, @tempdir
+    FileUtils.mv f2_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'f'
+    end
+
+    assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_local
+    FileUtils.mv @a1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :domain => :local
+      inst.install 'a-1.gem'
+    end
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_local_dependency
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :domain => :local
+      inst.install 'b-1.gem'
+    end
+
+    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_local_dependency_installed
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+
+    inst = nil
+
+    Dir.chdir @tempdir do
+      Gem::Installer.new('a-1.gem').install
+
+      inst = Gem::DependencyInstaller.new :domain => :local
+      inst.install 'b-1.gem'
+    end
+
+    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_local_subdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :domain => :local
+      inst.install 'gems/a-1.gem'
+    end
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_env_shebang
+    FileUtils.mv @a1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true
+      inst.install 'a'
+    end
+
+    assert_match %r|\A#!/\S+/env #{Gem::ConfigMap[:ruby_install_name]}\n|,
+                 File.read(File.join(@gemhome, 'bin', 'a_bin'))
+  end
+
+  def test_install_force
+    FileUtils.mv @b1_gem, @tempdir
+    si = util_setup_spec_fetcher @b1
+    @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :force => true
+      inst.install 'b'
+    end
+
+    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_ignore_dependencies
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :ignore_dependencies => true
+      inst.install 'b'
+    end
+
+    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_install_dir
+    FileUtils.mv @a1_gem, @tempdir
+    gemhome2 = File.join @tempdir, 'gemhome2'
+    Dir.mkdir gemhome2
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :install_dir => gemhome2
+      inst.install 'a'
+    end
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+
+    assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name))
+    assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name))
+  end
+
+  def test_install_domain_both
+    a1_data = nil
+    File.open @a1_gem, 'rb' do |fp|
+      a1_data = fp.read
+    end
+
+    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :domain => :both
+      inst.install 'b'
+    end
+
+    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+    a1, b1 = inst.installed_gems
+
+    a1_expected = File.join(@gemhome, 'specifications', a1.spec_name)
+    b1_expected = File.join(@gemhome, 'specifications', b1.spec_name)
+
+    assert_equal a1_expected, a1.loaded_from
+    assert_equal b1_expected, b1.loaded_from
+  end
+
+  def test_install_domain_both_no_network
+    @fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
+      proc do
+        raise Gem::RemoteFetcher::FetchError
+      end
+
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :domain => :both
+      inst.install 'b'
+    end
+
+    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_domain_local
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    Gem.source_index.remove_spec @a1.full_name
+    Gem.source_index.remove_spec @a1_pre.full_name
+
+    Dir.chdir @tempdir do
+      e = assert_raises Gem::InstallError do
+        inst = Gem::DependencyInstaller.new :domain => :local
+        inst.install 'b'
+      end
+
+      assert_equal 'b requires a (>= 0, runtime)', e.message
+    end
+
+    assert_equal [], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_domain_remote
+    a1_data = nil
+    File.open @a1_gem, 'rb' do |fp|
+      a1_data = fp.read
+    end
+
+    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+    inst = Gem::DependencyInstaller.new :domain => :remote
+    inst.install 'a'
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_dual_repository
+    FileUtils.mv @a1_gem, @tempdir
+    FileUtils.mv @b1_gem, @tempdir
+    inst = nil
+
+    gemhome2 = "#{@gemhome}2"
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new :install_dir => gemhome2
+      inst.install 'a'
+    end
+
+    ENV['GEM_HOME'] = @gemhome
+    ENV['GEM_PATH'] = [@gemhome, gemhome2].join File::PATH_SEPARATOR
+    Gem.clear_paths
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'b'
+    end
+
+    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_remote
+    a1_data = nil
+    File.open @a1_gem, 'rb' do |fp|
+      a1_data = fp.read
+    end
+
+    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+    inst = Gem::DependencyInstaller.new
+
+    Dir.chdir @tempdir do
+      inst.install 'a'
+    end
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_remote_dep
+    a1_data = nil
+    File.open @a1_gem, 'rb' do |fp|
+      a1_data = fp.read
+    end
+
+    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+    inst = Gem::DependencyInstaller.new
+
+    Dir.chdir @tempdir do
+      dep = Gem::Dependency.new @a1.name, @a1.version
+      inst.install dep
+    end
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_domain_remote_platform_newer
+    a2_o, a2_o_gem = util_gem 'a', '2' do |s|
+      s.platform = Gem::Platform.new %w[cpu other_platform 1]
+    end
+
+    util_clear_gems
+
+    si = util_setup_spec_fetcher @a1, a2_o
+
+    @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
+
+    a1_data = nil
+    a2_o_data = nil
+
+    File.open @a1_gem, 'rb' do |fp| a1_data = fp.read end
+    File.open a2_o_gem, 'rb' do |fp| a2_o_data = fp.read end
+
+    @fetcher.data["http://gems.example.com/gems/#{@a1.file_name}"] =
+      a1_data
+    @fetcher.data["http://gems.example.com/gems/#{a2_o.file_name}"] =
+      a2_o_data
+
+    inst = Gem::DependencyInstaller.new :domain => :remote
+    inst.install 'a'
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_reinstall
+    Gem::Installer.new(@a1_gem).install
+    FileUtils.mv @a1_gem, @tempdir
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::DependencyInstaller.new
+      inst.install 'a'
+    end
+
+    assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
+                 Gem::SourceIndex.from_installed_gems
+
+    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  if defined? OpenSSL then
+    def test_install_security_policy
+      data = File.open(@a1_gem, 'rb') { |f| f.read }
+      @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
+
+      data = File.open(@b1_gem, 'rb') { |f| f.read }
+      @fetcher.data['http://gems.example.com/gems/b-1.gem'] = data
+
+      policy = Gem::Security::HighSecurity
+      inst = Gem::DependencyInstaller.new :security_policy => policy
+
+      e = assert_raises Gem::Exception do
+        inst.install 'b'
+      end
+
+      assert_equal 'Unsigned gem', e.message
+
+      assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
+    end
+  end
+
+  # Wrappers don't work on mswin
+  unless win_platform? then
+    def test_install_no_wrappers
+      @fetcher.data['http://gems.example.com/gems/a-1.gem'] = read_binary(@a1_gem)
+
+      inst = Gem::DependencyInstaller.new :wrappers => false
+      inst.install 'a'
+
+      refute_match(%r|This file was generated by RubyGems.|,
+                   File.read(File.join(@gemhome, 'bin', 'a_bin')))
+    end
+  end
+
+  def test_install_version
+    data = File.open(@d2_gem, 'rb') { |f| f.read }
+    @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
+
+    data = File.open(@d1_gem, 'rb') { |f| f.read }
+    @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
+
+    inst = Gem::DependencyInstaller.new
+
+    inst.install 'd', '= 1'
+
+    assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_install_version_default
+    data = File.open(@d2_gem, 'rb') { |f| f.read }
+    @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
+
+    data = File.open(@d1_gem, 'rb') { |f| f.read }
+    @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
+
+    inst = Gem::DependencyInstaller.new
+    inst.install 'd'
+
+    assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
+  end
+
+  def test_find_gems_gems_with_sources
+    inst = Gem::DependencyInstaller.new
+    dep = Gem::Dependency.new 'b', '>= 0'
+
+    assert_equal [[@b1, @gem_repo]],
+                 inst.find_gems_with_sources(dep)
+  end
+
+  def test_find_gems_with_sources_local
+    FileUtils.mv @a1_gem, @tempdir
+    inst = Gem::DependencyInstaller.new
+    dep = Gem::Dependency.new 'a', '>= 0'
+    gems = nil
+
+    Dir.chdir @tempdir do
+      gems = inst.find_gems_with_sources dep
+    end
+
+    assert_equal 2, gems.length
+    remote = gems.first
+    assert_equal 'a-1', remote.first.full_name, 'remote spec'
+    assert_equal @gem_repo, remote.last, 'remote path'
+
+    local = gems.last
+    assert_equal 'a-1', local.first.full_name, 'local spec'
+    assert_equal File.join(@tempdir, @a1.file_name),
+                 local.last, 'local path'
+  end
+
+  def test_gather_dependencies
+    inst = Gem::DependencyInstaller.new
+    inst.find_spec_by_name_and_version 'b'
+    inst.gather_dependencies
+
+    assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name }
+  end
+
+  def test_gather_dependencies_dropped
+    b2, = util_gem 'b', '2'
+    c1, = util_gem 'c', '1' do |s| s.add_dependency 'b' end
+
+    util_clear_gems
+
+    si = util_setup_spec_fetcher @a1, @b1, b2, c1
+
+    inst = Gem::DependencyInstaller.new
+    inst.find_spec_by_name_and_version 'c'
+    inst.gather_dependencies
+
+    assert_equal %w[b-2 c-1], inst.gems_to_install.map { |s| s.full_name }
+  end
+
+  def test_gather_dependencies_platform_alternate
+    util_set_arch 'cpu-my_platform1'
+
+    inst = Gem::DependencyInstaller.new
+    inst.find_spec_by_name_and_version 'w'
+    inst.gather_dependencies
+
+    assert_equal %w[x-1-cpu-my_platform-1 w-1],
+                 inst.gems_to_install.map { |s| s.full_name }
+  end
+
+  def test_gather_dependencies_platform_bump
+    inst = Gem::DependencyInstaller.new
+    inst.find_spec_by_name_and_version 'z'
+    inst.gather_dependencies
+
+    assert_equal %w[y-1 z-1], inst.gems_to_install.map { |s| s.full_name }
+  end
+
+  def test_gather_dependencies_old_required
+    e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end
+
+    util_clear_gems
+
+    si = util_setup_spec_fetcher @d1, @d2, e1
+
+    inst = Gem::DependencyInstaller.new
+    inst.find_spec_by_name_and_version 'e'
+    inst.gather_dependencies
+
+    assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name }
+  end
+
+  def test_prerelease_uses_pre_index
+    installer = Gem::DependencyInstaller.new
+    pre_installer = Gem::DependencyInstaller.new(:prerelease => true)
+    dependency = Gem::Dependency.new('a', Gem::Requirement.default)
+
+    releases = installer.find_gems_with_sources(dependency).map{ |gems, *| gems }
+    prereleases = pre_installer.find_gems_with_sources(dependency).map{ |gems, *| gems }
+
+    assert releases.select{ |s| s.name == 'a' and s.version.to_s == '1' }.first
+    assert releases.select{ |s| s.name == 'a' and s.version.to_s == '1.a' }.empty?
+    assert_equal [@a1_pre], prereleases
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_list.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_list.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_dependency_list.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,209 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/dependency_list'
+
+class TestGemDependencyList < RubyGemTestCase
+
+  def setup
+    super
+
+    @deplist = Gem::DependencyList.new
+
+    @a1 = quick_gem 'a', '1'
+    @a2 = quick_gem 'a', '2'
+    @a3 = quick_gem 'a', '3'
+
+    @b1 = quick_gem 'b', '1' do |s| s.add_dependency 'a', '>= 1' end
+    @b2 = quick_gem 'b', '2' do |s| s.add_dependency 'a', '>= 1' end
+
+    @c1 = quick_gem 'c', '1' do |s| s.add_dependency 'b', '>= 1' end
+    @c2 = quick_gem 'c', '2'
+
+    @d1 = quick_gem 'd', '1' do |s| s.add_dependency 'c', '>= 1' end
+  end
+
+  def test_self_from_source_index
+    hash = {
+      'a-1' => @a1,
+      'b-2' => @b2,
+    }
+
+    si = Gem::SourceIndex.new hash
+    deps = Gem::DependencyList.from_source_index si
+
+    assert_equal %w[b-2 a-1], deps.dependency_order.map { |s| s.full_name }
+  end
+
+  def test_active_count
+    assert_equal 0, @deplist.send(:active_count, [], {})
+    assert_equal 1, @deplist.send(:active_count, [@a1], {})
+    assert_equal 0, @deplist.send(:active_count, [@a1],
+                                  { @a1.full_name => true })
+  end
+
+  def test_add
+    assert_equal [], @deplist.dependency_order
+
+    @deplist.add @a1, @b2
+
+    assert_equal [@b2, @a1], @deplist.dependency_order
+  end
+
+  def test_dependency_order
+    @deplist.add @a1, @b1, @c1, @d1
+
+    order = @deplist.dependency_order
+
+    assert_equal %w[d-1 c-1 b-1 a-1], order.map { |s| s.full_name }
+  end
+
+  def test_dependency_order_circle
+    @a1.add_dependency 'c', '>= 1'
+    @deplist.add @a1, @b1, @c1
+
+    order = @deplist.dependency_order
+
+    assert_equal %w[b-1 c-1 a-1], order.map { |s| s.full_name }
+  end
+
+  def test_dependency_order_diamond
+    util_diamond
+    e1 = quick_gem 'e', '1'
+    @deplist.add e1
+    @a1.add_dependency 'e', '>= 1'
+
+    order = @deplist.dependency_order
+
+    assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map { |s| s.full_name },
+                 'deps of trimmed specs not included'
+  end
+
+  def test_dependency_order_no_dependendencies
+    @deplist.add @a1, @c2
+
+    order = @deplist.dependency_order
+
+    assert_equal %w[c-2 a-1], order.map { |s| s.full_name }
+  end
+
+  def test_find_name
+    @deplist.add @a1, @b2
+
+    assert_equal "a-1", @deplist.find_name("a-1").full_name
+    assert_equal "b-2", @deplist.find_name("b-2").full_name
+
+    assert_nil @deplist.find_name("c-2")
+  end
+
+  def test_ok_eh
+    assert @deplist.ok?, 'no dependencies'
+
+    @deplist.add @b2
+
+    refute @deplist.ok?, 'unsatisfied dependency'
+
+    @deplist.add @a1
+
+    assert @deplist.ok?, 'satisfied dependency'
+  end
+
+  def test_ok_eh_mismatch
+    a1 = quick_gem 'a', '1'
+    a2 = quick_gem 'a', '2'
+
+    b = quick_gem 'b', '1' do |s| s.add_dependency 'a', '= 1' end
+    c = quick_gem 'c', '1' do |s| s.add_dependency 'a', '= 2' end
+
+    d = quick_gem 'd', '1' do |s|
+      s.add_dependency 'b'
+      s.add_dependency 'c'
+    end
+
+    @deplist.add a1, a2, b, c, d
+
+    assert @deplist.ok?, 'this will break on require'
+  end
+
+  def test_ok_eh_redundant
+    @deplist.add @a1, @a3, @b2
+
+    @deplist.remove_by_name("a-1")
+
+    assert @deplist.ok?
+  end
+
+  def test_ok_to_remove_eh
+    @deplist.add @a1
+
+    assert @deplist.ok_to_remove?("a-1")
+
+    @deplist.add @b2
+
+    refute @deplist.ok_to_remove?("a-1")
+
+    @deplist.add @a2
+
+    assert @deplist.ok_to_remove?("a-1")
+    assert @deplist.ok_to_remove?("a-2")
+    assert @deplist.ok_to_remove?("b-2")
+  end
+
+  def test_ok_to_remove_eh_after_sibling_removed
+    @deplist.add @a1, @a2, @b2
+
+    assert @deplist.ok_to_remove?("a-1")
+    assert @deplist.ok_to_remove?("a-2")
+
+    @deplist.remove_by_name("a-1")
+
+    refute @deplist.ok_to_remove?("a-2")
+  end
+
+  def test_remove_by_name
+    @deplist.add @a1, @b2
+
+    @deplist.remove_by_name "a-1"
+
+    refute @deplist.ok?
+  end
+
+  def test_tsort_each_node
+    util_diamond
+
+    order = %w[a-1 a-2 b-1 c-2 d-1]
+
+    @deplist.tsort_each_node do |node|
+      assert_equal order.shift, node.full_name
+    end
+
+    assert_empty order
+  end
+
+  def test_tsort_each_child
+    util_diamond
+
+    order = %w[a-2]
+
+    @deplist.tsort_each_child(@b1) do |node|
+      assert_equal order.shift, node.full_name
+    end
+
+    assert_empty order
+  end
+
+  # d1 -> b1 -> a1
+  # d1 -> c2 -> a2
+  def util_diamond
+    @c2.add_dependency 'a', '>= 2'
+    @d1.add_dependency 'b'
+
+    @deplist.add @a1, @a2, @b1, @c2, @d1
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_doc_manager.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_doc_manager.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_doc_manager.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,37 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/doc_manager'
+
+class TestGemDocManager < RubyGemTestCase
+
+  def setup
+    super
+
+    @spec = quick_gem 'a'
+    @manager = Gem::DocManager.new(@spec)
+  end
+
+  def test_uninstall_doc_unwritable
+    orig_mode = File.stat(@spec.installation_path).mode
+    
+    # File.chmod has no effect on MS Windows directories (it needs ACL).
+    if win_platform?
+      skip("test_uninstall_doc_unwritable skipped on MS Windows")
+    else
+      File.chmod(0, @spec.installation_path)
+    end
+
+    assert_raises Gem::FilePermissionError do
+      @manager.uninstall_doc
+    end
+  ensure
+    File.chmod orig_mode, @spec.installation_path
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_configure_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_configure_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_configure_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,84 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/ext'
+
+class TestGemExtConfigureBuilder < RubyGemTestCase
+
+  def setup
+    super
+
+    @makefile_body =  "all:\n\t at echo ok\ninstall:\n\t at echo ok"
+
+    @ext = File.join @tempdir, 'ext'
+    @dest_path = File.join @tempdir, 'prefix'
+
+    FileUtils.mkdir_p @ext
+    FileUtils.mkdir_p @dest_path
+  end
+
+  def test_self_build
+    skip("test_self_build skipped on MS Windows (VC++)") if vc_windows?
+
+    File.open File.join(@ext, './configure'), 'w' do |configure|
+      configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile"
+    end
+
+    output = []
+
+    Dir.chdir @ext do
+      Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
+    end
+
+    assert_equal "sh ./configure --prefix=#{@dest_path}", output.shift
+    assert_equal "", output.shift
+    assert_equal "make", output.shift
+    assert_match(/^ok$/m, output.shift)
+    assert_equal "make install", output.shift
+    assert_match(/^ok$/m, output.shift)
+  end
+
+  def test_self_build_fail
+    skip("test_self_build_fail skipped on MS Windows (VC++)") if vc_windows?
+    output = []
+
+    error = assert_raises Gem::InstallError do
+      Dir.chdir @ext do
+        Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
+      end
+    end
+
+    shell_error_msg = %r{(\./configure: .*)|(Can't open \./configure(?:: No such file or directory)?)}
+    sh_prefix_configure = "sh ./configure --prefix="
+
+    expected = %r(configure failed:
+
+#{Regexp.escape sh_prefix_configure}#{Regexp.escape @dest_path}
+.*?: #{shell_error_msg}
+)
+
+    assert_match expected, error.message
+
+    assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift
+    assert_match %r(#{shell_error_msg}), output.shift
+    assert_equal true, output.empty?
+  end
+
+  def test_self_build_has_makefile
+    if vc_windows? && !nmake_found?
+      skip("test_self_build_has_makefile skipped - nmake not found")
+    end
+
+    File.open File.join(@ext, 'Makefile'), 'w' do |makefile|
+      makefile.puts @makefile_body
+    end
+
+    output = []
+    Dir.chdir @ext do
+      Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
+    end
+
+    assert_equal make_command, output[0]
+    assert_equal "#{make_command} install", output[2]
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_ext_conf_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_ext_conf_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_ext_conf_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,127 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/ext'
+
+class TestGemExtExtConfBuilder < RubyGemTestCase
+
+  def setup
+    super
+
+    @ext = File.join @tempdir, 'ext'
+    @dest_path = File.join @tempdir, 'prefix'
+
+    FileUtils.mkdir_p @ext
+    FileUtils.mkdir_p @dest_path
+  end
+
+  def test_class_build
+    if vc_windows? && !nmake_found?
+      skip("test_class_build skipped - nmake not found")
+    end
+
+    File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+      extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
+    end
+
+    output = []
+
+    Dir.chdir @ext do
+      Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output
+    end
+
+    expected = [
+      "ruby extconf.rb",
+      "creating Makefile\n",
+      "make",
+      "make: Nothing to be done for `all'.\n",
+      "make install",
+      "make: Nothing to be done for `install'.\n"
+    ]
+
+    assert_match(/^#{Gem.ruby} extconf.rb/, output[0])
+    assert_equal "creating Makefile\n", output[1]
+    case RUBY_PLATFORM
+    when /mswin/ then
+      assert_equal "nmake", output[2]
+      assert_equal "nmake install", output[4]
+    else
+      assert_equal "make", output[2]
+      assert_equal "make install", output[4]
+    end
+  end
+
+  def test_class_build_extconf_fail
+    if vc_windows? && !nmake_found?
+      skip("test_class_build_extconf_fail skipped - nmake not found")
+    end
+
+    File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+      extconf.puts "require 'mkmf'"
+      extconf.puts "have_library 'nonexistent' or abort 'need libnonexistent'"
+      extconf.puts "create_makefile 'foo'"
+    end
+
+    output = []
+
+    error = assert_raises Gem::InstallError do
+      Dir.chdir @ext do
+        Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output
+      end
+    end
+
+    assert_match(/\Aextconf failed:
+
+#{Gem.ruby} extconf.rb.*
+checking for main\(\) in .*?nonexistent/m, error.message)
+
+    assert_match(/^#{Gem.ruby} extconf.rb/, output[0])
+  end
+
+  def test_class_make
+    if vc_windows? && !nmake_found?
+      skip("test_class_make skipped - nmake not found")
+    end
+
+    output = []
+    makefile_path = File.join(@ext, 'Makefile')
+    File.open makefile_path, 'w' do |makefile|
+      makefile.puts "RUBYARCHDIR = $(foo)$(target_prefix)"
+      makefile.puts "RUBYLIBDIR = $(bar)$(target_prefix)"
+      makefile.puts "all:"
+      makefile.puts "install:"
+    end
+
+    Dir.chdir @ext do
+      Gem::Ext::ExtConfBuilder.make @ext, output
+    end
+
+    assert_equal make_command, output[0]
+    assert_equal "#{make_command} install", output[2]
+
+    edited_makefile = <<-EOF
+RUBYARCHDIR = #{@ext}$(target_prefix)
+RUBYLIBDIR = #{@ext}$(target_prefix)
+all:
+install:
+    EOF
+
+    assert_equal edited_makefile, File.read(makefile_path)
+  end
+
+  def test_class_make_no_Makefile
+    error = assert_raises Gem::InstallError do
+      Dir.chdir @ext do
+        Gem::Ext::ExtConfBuilder.make @ext, ['output']
+      end
+    end
+
+    expected = <<-EOF.strip
+Makefile not found:
+
+output
+    EOF
+
+    assert_equal expected, error.message
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_rake_builder.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_rake_builder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_ext_rake_builder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,81 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/ext'
+
+class TestGemExtRakeBuilder < RubyGemTestCase
+  def setup
+    super
+
+    @ext = File.join @tempdir, 'ext'
+    @dest_path = File.join @tempdir, 'prefix'
+
+    FileUtils.mkdir_p @ext
+    FileUtils.mkdir_p @dest_path
+  end
+
+  def test_class_build
+    File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf|
+      mkrf_conf.puts <<-EO_MKRF
+        File.open("Rakefile","w") do |f|
+          f.puts "task :default"
+        end
+      EO_MKRF
+    end
+
+    output = []
+    realdir = nil # HACK /tmp vs. /private/tmp
+
+    build_rake_in do
+      Dir.chdir @ext do
+        realdir = Dir.pwd
+        Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', nil, @dest_path, output
+      end
+    end
+
+    output = output.join "\n"
+
+    expected = [
+      "#{@@ruby} mkrf_conf.rb",
+      "",
+      "#{@@rake} RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}",
+      "(in #{realdir})\n"
+    ]
+
+    refute_match %r%^rake failed:%, output
+    assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output
+    assert_match %r%^#{Regexp.escape @@rake} RUBYARCHDIR=#{Regexp.escape @dest_path} RUBYLIBDIR=#{Regexp.escape @dest_path}%, output
+  end
+
+  def test_class_build_fail
+    File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf|
+      mkrf_conf.puts <<-EO_MKRF
+        File.open("Rakefile","w") do |f|
+          f.puts "task :default do abort 'fail' end"
+        end
+        EO_MKRF
+    end
+
+    output = []
+
+    error = assert_raises Gem::InstallError do
+      build_rake_in do
+        Dir.chdir @ext do
+          Gem::Ext::RakeBuilder.build "mkrf_conf.rb", nil, @dest_path, output
+        end
+      end
+    end
+
+    expected = <<-EOF.strip
+rake failed:
+
+#{@@ruby} mkrf_conf.rb
+
+#{@@rake} RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}
+    EOF
+
+    assert_match %r%^rake failed:%, error.message
+    assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, error.message
+    assert_match %r%^#{Regexp.escape @@rake} RUBYARCHDIR=#{Regexp.escape @dest_path} RUBYLIBDIR=#{Regexp.escape @dest_path}%, error.message
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_format.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_format.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_format.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,67 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem')
+require 'rubygems/format'
+
+class TestGemFormat < RubyGemTestCase
+
+  def setup
+    super
+
+    @simple_gem = SIMPLE_GEM
+  end
+
+  def test_from_file_by_path
+    util_make_gems
+
+    gems = Dir[File.join(@gemhome, 'cache', '*.gem')]
+
+    names = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].map do |spec|
+      spec.original_name
+    end
+
+    gems_n_names = gems.sort.zip names
+
+    gems_n_names.each do |gemfile, name|
+      spec = Gem::Format.from_file_by_path(gemfile).spec
+
+      assert_equal name, spec.original_name
+    end
+  end
+
+  def test_from_file_by_path_nonexistent
+    assert_raises Gem::Exception do
+      Gem::Format.from_file_by_path '/nonexistent'
+    end
+  end
+
+  def test_from_io_garbled
+    e = assert_raises Gem::Package::FormatError do
+      # subtly bogus input
+      Gem::Format.from_io(StringIO.new(@simple_gem.upcase))
+    end
+
+    assert_equal 'No metadata found!', e.message
+
+    e = assert_raises Gem::Package::FormatError do
+      # Totally bogus input
+      Gem::Format.from_io(StringIO.new(@simple_gem.reverse))
+    end
+
+    assert_equal 'No metadata found!', e.message
+
+    e = assert_raises Gem::Package::FormatError do
+      # This was intentionally screws up YAML parsing.
+      Gem::Format.from_io(StringIO.new(@simple_gem.gsub(/:/, "boom")))
+    end
+
+    assert_equal 'No metadata found!', e.message
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_path_searcher.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_path_searcher.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_path_searcher.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,67 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/gem_path_searcher'
+
+class Gem::GemPathSearcher
+  attr_accessor :gemspecs
+  attr_accessor :lib_dirs
+end
+
+class TestGemGemPathSearcher < RubyGemTestCase
+
+  def setup
+    super
+
+    @foo1 = quick_gem 'foo', '0.1' do |s|
+      s.require_paths << 'lib2'
+      s.files << 'lib/foo.rb'
+    end
+
+    path = File.join 'gems', @foo1.full_name, 'lib', 'foo.rb'
+    write_file(path) { |fp| fp.puts "# #{path}" }
+
+    @foo2 = quick_gem 'foo', '0.2'
+    @bar1 = quick_gem 'bar', '0.1'
+    @bar2 = quick_gem 'bar', '0.2'
+
+    @fetcher = Gem::FakeFetcher.new
+    Gem::RemoteFetcher.fetcher = @fetcher
+
+    Gem.source_index = util_setup_spec_fetcher @foo1, @foo2, @bar1, @bar2
+
+    @gps = Gem::GemPathSearcher.new
+  end
+
+  def test_find
+    assert_equal @foo1, @gps.find('foo')
+  end
+
+  def test_find_all
+    assert_equal [@foo1], @gps.find_all('foo')
+  end
+
+  def test_init_gemspecs
+    assert_equal [@bar2, @bar1, @foo2, @foo1], @gps.init_gemspecs
+  end
+
+  def test_lib_dirs_for
+    lib_dirs = @gps.lib_dirs_for(@foo1)
+    expected = File.join @gemhome, 'gems', @foo1.full_name, '{lib,lib2}'
+
+    assert_equal expected, lib_dirs
+  end
+
+  def test_matching_file_eh
+    refute @gps.matching_file?(@foo1, 'bar')
+    assert @gps.matching_file?(@foo1, 'foo')
+  end
+
+  def test_matching_files
+    assert_equal [], @gps.matching_files(@foo1, 'bar')
+
+    expected = File.join @foo1.full_gem_path, 'lib', 'foo.rb'
+
+    assert_equal [expected], @gps.matching_files(@foo1, 'foo')
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_runner.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_runner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_gem_runner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,45 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/gem_runner'
+
+class TestGemGemRunner < RubyGemTestCase
+
+  def test_do_configuration
+    Gem.clear_paths
+
+    temp_conf = File.join @tempdir, '.gemrc'
+
+    other_gem_path = File.join @tempdir, 'other_gem_path'
+    other_gem_home = File.join @tempdir, 'other_gem_home'
+
+    Gem.ensure_gem_subdirectories other_gem_path
+    Gem.ensure_gem_subdirectories other_gem_home
+
+    File.open temp_conf, 'w' do |fp|
+      fp.puts "gem: --commands"
+      fp.puts "gemhome: #{other_gem_home}"
+      fp.puts "gempath:"
+      fp.puts "  - #{other_gem_path}"
+      fp.puts "rdoc: --all"
+    end
+
+    gr = Gem::GemRunner.new
+    gr.send :do_configuration, %W[--config-file #{temp_conf}]
+
+    assert_equal [other_gem_path, other_gem_home], Gem.path
+    assert_equal %w[--commands], Gem::Command.extra_args
+    assert_equal %w[--all], Gem::DocManager.configured_args
+  end
+
+  def test_build_args__are_handled
+    Gem.clear_paths
+
+    gr = Gem::GemRunner.new
+    assert_raises(Gem::SystemExitException) do
+      gr.run(%W[--help -- --build_arg1 --build_arg2])
+    end
+
+    assert_equal %w[--build_arg1 --build_arg2], Gem::Command.build_args
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_indexer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_indexer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_indexer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,680 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+
+require 'rubygems/indexer'
+
+unless ''.respond_to? :to_xs then
+  warn "Gem::Indexer tests are being skipped.  Install builder gem."
+end
+
+class TestGemIndexer < RubyGemTestCase
+
+  def setup
+    super
+
+    util_make_gems
+
+    @d2_0 = quick_gem 'd', '2.0' do |s|
+      s.date = Gem::Specification::TODAY - 86400 * 3
+    end
+    util_build_gem @d2_0
+
+    @d2_0_a = quick_gem 'd', '2.0.a'
+    util_build_gem @d2_0_a
+
+    @d2_0_b = quick_gem 'd', '2.0.b'
+    util_build_gem @d2_0_b
+
+    gems = File.join(@tempdir, 'gems')
+    FileUtils.mkdir_p gems
+    cache_gems = File.join @gemhome, 'cache', '*.gem'
+    FileUtils.mv Dir[cache_gems], gems
+
+    @indexer = Gem::Indexer.new @tempdir, :rss_title => 'ExampleForge gems',
+                                :rss_host => 'example.com',
+                                :rss_gems_host => 'gems.example.com'
+  end
+
+  def test_initialize
+    assert_equal @tempdir, @indexer.dest_directory
+    assert_equal File.join(Dir.tmpdir, "gem_generate_index_#{$$}"),
+                 @indexer.directory
+
+    indexer = Gem::Indexer.new @tempdir
+    assert indexer.build_legacy
+    assert indexer.build_modern
+
+    indexer = Gem::Indexer.new @tempdir, :build_legacy => false,
+                               :build_modern => true
+    refute indexer.build_legacy
+    assert indexer.build_modern
+
+    indexer = Gem::Indexer.new @tempdir, :build_legacy => true,
+                               :build_modern => false
+    assert indexer.build_legacy
+    refute indexer.build_modern
+  end
+
+  def test_build_indicies
+    spec = quick_gem 'd', '2.0'
+    spec.instance_variable_set :@original_platform, ''
+
+    @indexer.make_temp_directories
+
+    index = Gem::SourceIndex.new
+    index.add_spec spec
+
+    use_ui @ui do
+      @indexer.build_indicies index
+    end
+
+    specs_path = File.join @indexer.directory, "specs.#{@marshal_version}"
+    specs_dump = Gem.read_binary specs_path
+    specs = Marshal.load specs_dump
+
+    expected = [
+      ['d',      Gem::Version.new('2.0'), 'ruby'],
+    ]
+
+    assert_equal expected, specs, 'specs'
+
+    latest_specs_path = File.join @indexer.directory,
+                                  "latest_specs.#{@marshal_version}"
+    latest_specs_dump = Gem.read_binary latest_specs_path
+    latest_specs = Marshal.load latest_specs_dump
+
+    expected = [
+      ['d',      Gem::Version.new('2.0'), 'ruby'],
+    ]
+
+    assert_equal expected, latest_specs, 'latest_specs'
+  end
+
+  def test_generate_index
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    assert_indexed @tempdir, 'yaml'
+    assert_indexed @tempdir, 'yaml.Z'
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}"
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
+
+    quickdir = File.join @tempdir, 'quick'
+    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+    assert File.directory?(quickdir)
+    assert File.directory?(marshal_quickdir)
+
+    assert_indexed quickdir, "index"
+    assert_indexed quickdir, "index.rz"
+
+    quick_index = File.read File.join(quickdir, 'index')
+    expected = <<-EOF
+a-1
+a-2
+a-3.a
+a_evil-9
+b-2
+c-1.2
+d-2.0
+d-2.0.a
+d-2.0.b
+pl-1-i386-linux
+    EOF
+
+    assert_equal expected, quick_index
+
+    assert_indexed quickdir, "latest_index"
+    assert_indexed quickdir, "latest_index.rz"
+
+    latest_quick_index = File.read File.join(quickdir, 'latest_index')
+    expected = <<-EOF
+a-2
+a_evil-9
+b-2
+c-1.2
+d-2.0
+pl-1-i386-linux
+    EOF
+
+    assert_equal expected, latest_quick_index
+
+    assert_indexed quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed quickdir, "#{@a2.spec_name}.rz"
+    assert_indexed quickdir, "#{@b2.spec_name}.rz"
+    assert_indexed quickdir, "#{@c1_2.spec_name}.rz"
+
+    assert_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
+    refute_indexed quickdir, "#{@pl1.spec_name}.rz"
+
+    assert_indexed marshal_quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed marshal_quickdir, "#{@a2.spec_name}.rz"
+
+    refute_indexed quickdir, @c1_2.spec_name
+    refute_indexed marshal_quickdir, @c1_2.spec_name
+
+    assert_indexed @tempdir, "specs.#{@marshal_version}"
+    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
+
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
+
+    expected = <<-EOF
+<?xml version=\"1.0\"?>
+<rss version=\"2.0\">
+  <channel>
+    <title>ExampleForge gems</title>
+    <link>http://example.com</link>
+    <description>Recently released gems from http://example.com</description>
+    <generator>RubyGems v#{Gem::RubyGemsVersion}</generator>
+    <docs>http://cyber.law.harvard.edu/rss/rss.html</docs>
+    <item>
+      <title>a-2</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>a-2</guid>
+      <enclosure url=\"http://gems.example.com/gems/a-2.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@a2.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>a-3.a</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>a-3.a</guid>
+      <enclosure url=\"http://gems.example.com/gems/a-3.a.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@a3a.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>a_evil-9</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>a_evil-9</guid>
+      <enclosure url=\"http://gems.example.com/gems/a_evil-9.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@a_evil9.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>b-2</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>b-2</guid>
+      <enclosure url=\"http://gems.example.com/gems/b-2.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@b2.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>c-1.2</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>c-1.2</guid>
+      <enclosure url=\"http://gems.example.com/gems/c-1.2.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@c1_2.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>d-2.0.a</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>d-2.0.a</guid>
+      <enclosure url=\"http://gems.example.com/gems/d-2.0.a.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@d2_0_a.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>d-2.0.b</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>d-2.0.b</guid>
+      <enclosure url=\"http://gems.example.com/gems/d-2.0.b.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@d2_0_b.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>pl-1-x86-linux</title>
+      <description>
+&lt;pre&gt;This is a test description&lt;/pre&gt;
+      </description>
+      <author>example at example.com (A User)</author>
+      <guid>pl-1-x86-linux</guid>
+      <enclosure url=\"http://gems.example.com/gems/pl-1-x86-linux.gem\"
+                 length=\"3072\" type=\"application/octet-stream\" />
+      <pubDate>#{@pl1.date.rfc2822}</pubDate>
+      <link>http://example.com</link>
+    </item>
+    <item>
+      <title>a-1</title>
+      <description>
+&lt;pre&gt;This line is really, really long.  So long, in fact, that it is more than
+eighty characters long!  The purpose of this line is for testing wrapping
+behavior because sometimes people don't wrap their text to eighty characters. 
+Without the wrapping, the text might not look good in the RSS feed.
+
+Also, a list:
+  * An entry that's actually kind of sort
+  * an entry that's really long, which will probably get wrapped funny. 
+That's ok, somebody wasn't thinking straight when they made it more than
+eighty characters.&lt;/pre&gt;
+      </description>
+      <author>example at example.com (Example), example2 at example.com (Example2)</author>
+      <guid>a-1</guid>
+      <enclosure url=\"http://gems.example.com/gems/a-1.gem\"
+                 length=\"3584\" type=\"application/octet-stream\" />
+      <pubDate>#{@a1.date.rfc2822}</pubDate>
+      <link>http://a.example.com</link>
+    </item>
+  </channel>
+</rss>
+    EOF
+
+    gems_rss = File.read File.join(@tempdir, 'index.rss')
+
+    assert_equal expected, gems_rss
+  end
+
+  def test_generate_index_legacy
+    @indexer.build_modern = false
+    @indexer.build_legacy = true
+
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    assert_indexed @tempdir, 'yaml'
+    assert_indexed @tempdir, 'yaml.Z'
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}"
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
+
+    quickdir = File.join @tempdir, 'quick'
+    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+    assert File.directory?(quickdir)
+    assert File.directory?(marshal_quickdir)
+
+    assert_indexed quickdir, "index"
+    assert_indexed quickdir, "index.rz"
+
+    assert_indexed quickdir, "latest_index"
+    assert_indexed quickdir, "latest_index.rz"
+
+    assert_indexed quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed quickdir, "#{@a2.spec_name}.rz"
+    assert_indexed quickdir, "#{@b2.spec_name}.rz"
+    assert_indexed quickdir, "#{@c1_2.spec_name}.rz"
+
+    assert_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
+    refute_indexed quickdir, "#{@pl1.spec_name}.rz"
+
+    assert_indexed marshal_quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed marshal_quickdir, "#{@a2.spec_name}.rz"
+
+    refute_indexed quickdir, "#{@c1_2.spec_name}"
+    refute_indexed marshal_quickdir, "#{@c1_2.spec_name}"
+
+    refute_indexed @tempdir, "specs.#{@marshal_version}"
+    refute_indexed @tempdir, "specs.#{@marshal_version}.gz"
+
+    refute_indexed @tempdir, "latest_specs.#{@marshal_version}"
+    refute_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
+  end
+
+  def test_generate_index_legacy_back_to_back
+    @indexer.build_modern = true
+    @indexer.build_legacy = true
+
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    @indexer = Gem::Indexer.new @tempdir
+    @indexer.build_modern = false
+    @indexer.build_legacy = true
+
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    assert_indexed @tempdir, 'yaml'
+    assert_indexed @tempdir, 'yaml.Z'
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}"
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
+
+    quickdir = File.join @tempdir, 'quick'
+    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+    assert File.directory?(quickdir)
+    assert File.directory?(marshal_quickdir)
+
+    assert_indexed quickdir, "index"
+    assert_indexed quickdir, "index.rz"
+
+    assert_indexed quickdir, "latest_index"
+    assert_indexed quickdir, "latest_index.rz"
+
+    assert_indexed quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed quickdir, "#{@a2.spec_name}.rz"
+    assert_indexed quickdir, "#{@b2.spec_name}.rz"
+    assert_indexed quickdir, "#{@c1_2.spec_name}.rz"
+
+    assert_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
+
+    assert_indexed marshal_quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed marshal_quickdir, "#{@a2.spec_name}.rz"
+
+    assert_indexed @tempdir, "specs.#{@marshal_version}"
+    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
+
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
+  end
+
+  def test_generate_index_modern
+    @indexer.build_modern = true
+    @indexer.build_legacy = false
+
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    refute_indexed @tempdir, 'yaml'
+    refute_indexed @tempdir, 'yaml.Z'
+    refute_indexed @tempdir, "Marshal.#{@marshal_version}"
+    refute_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
+
+    quickdir = File.join @tempdir, 'quick'
+    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+    assert File.directory?(quickdir), 'quickdir should be directory'
+    assert File.directory?(marshal_quickdir)
+
+    refute_indexed quickdir, "index"
+    refute_indexed quickdir, "index.rz"
+
+    refute_indexed quickdir, "latest_index"
+    refute_indexed quickdir, "latest_index.rz"
+
+    refute_indexed quickdir, "#{@a1.spec_name}.rz"
+    refute_indexed quickdir, "#{@a2.spec_name}.rz"
+    refute_indexed quickdir, "#{@b2.spec_name}.rz"
+    refute_indexed quickdir, "#{@c1_2.spec_name}.rz"
+
+    refute_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
+    refute_indexed quickdir, "#{@pl1.spec_name}.rz"
+
+    assert_indexed marshal_quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed marshal_quickdir, "#{@a2.spec_name}.rz"
+
+    refute_indexed quickdir, "#{@c1_2.spec_name}"
+    refute_indexed marshal_quickdir, "#{@c1_2.spec_name}"
+
+    assert_indexed @tempdir, "specs.#{@marshal_version}"
+    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
+
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
+  end
+
+  def test_generate_index_modern_back_to_back
+    @indexer.build_modern = true
+    @indexer.build_legacy = true
+
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    @indexer = Gem::Indexer.new @tempdir
+    @indexer.build_modern = true
+    @indexer.build_legacy = false
+
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    assert_indexed @tempdir, 'yaml'
+    assert_indexed @tempdir, 'yaml.Z'
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}"
+    assert_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
+
+    quickdir = File.join @tempdir, 'quick'
+    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+    assert File.directory?(quickdir)
+    assert File.directory?(marshal_quickdir)
+
+    assert_indexed quickdir, "index"
+    assert_indexed quickdir, "index.rz"
+
+    assert_indexed quickdir, "latest_index"
+    assert_indexed quickdir, "latest_index.rz"
+
+    assert_indexed quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed quickdir, "#{@a2.spec_name}.rz"
+    assert_indexed quickdir, "#{@b2.spec_name}.rz"
+    assert_indexed quickdir, "#{@c1_2.spec_name}.rz"
+
+    assert_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
+
+    assert_indexed marshal_quickdir, "#{@a1.spec_name}.rz"
+    assert_indexed marshal_quickdir, "#{@a2.spec_name}.rz"
+
+    assert_indexed @tempdir, "specs.#{@marshal_version}"
+    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
+
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
+    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
+  end
+
+  def test_generate_index_ui
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    assert_match %r%^Loading 10 gems from #{Regexp.escape @tempdir}$%,
+                 @ui.output
+    assert_match %r%^\.\.\.\.\.\.\.\.\.\.$%, @ui.output
+    assert_match %r%^Loaded all gems$%, @ui.output
+    assert_match %r%^Generating Marshal quick index gemspecs for 10 gems$%,
+                 @ui.output
+    assert_match %r%^Generating YAML quick index gemspecs for 10 gems$%,
+                 @ui.output
+    assert_match %r%^Complete$%, @ui.output
+    assert_match %r%^Generating specs index$%, @ui.output
+    assert_match %r%^Generating latest specs index$%, @ui.output
+    assert_match %r%^Generating quick index$%, @ui.output
+    assert_match %r%^Generating latest index$%, @ui.output
+    assert_match %r%^Generating prerelease specs index$%, @ui.output
+    assert_match %r%^Generating Marshal master index$%, @ui.output
+    assert_match %r%^Generating YAML master index for 10 gems \(this may take a while\)$%, @ui.output
+    assert_match %r%^Complete$%, @ui.output
+    assert_match %r%^Compressing indicies$%, @ui.output
+
+    assert_equal '', @ui.error
+  end
+
+  def test_generate_index_master
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    yaml_path = File.join @tempdir, 'yaml'
+    dump_path = File.join @tempdir, "Marshal.#{@marshal_version}"
+
+    yaml_index = YAML.load_file yaml_path
+    dump_index = Marshal.load Gem.read_binary(dump_path)
+
+    dump_index.each do |_,gem|
+      gem.send :remove_instance_variable, :@loaded
+    end
+
+    assert_equal yaml_index, dump_index,
+                 "expected YAML and Marshal to produce identical results"
+  end
+
+  def test_generate_index_specs
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    specs_path = File.join @tempdir, "specs.#{@marshal_version}"
+
+    specs_dump = Gem.read_binary specs_path
+    specs = Marshal.load specs_dump
+
+    expected = [
+      ['a',      Gem::Version.new(1),     'ruby'],
+      ['a',      Gem::Version.new(2),     'ruby'],
+      ['a_evil', Gem::Version.new(9),     'ruby'],
+      ['b',      Gem::Version.new(2),     'ruby'],
+      ['c',      Gem::Version.new('1.2'), 'ruby'],
+      ['d',      Gem::Version.new('2.0'), 'ruby'],
+      ['pl',     Gem::Version.new(1),     'i386-linux'],
+    ]
+
+    assert_equal expected, specs
+
+    assert_same specs[0].first, specs[1].first,
+                'identical names not identical'
+
+    assert_same specs[0][1],    specs[-1][1],
+                'identical versions not identical'
+
+    assert_same specs[0].last, specs[1].last,
+                'identical platforms not identical'
+
+    refute_same specs[1][1], specs[5][1],
+                'different versions not different'
+  end
+
+  def test_generate_index_latest_specs
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    latest_specs_path = File.join @tempdir, "latest_specs.#{@marshal_version}"
+
+    latest_specs_dump = Gem.read_binary latest_specs_path
+    latest_specs = Marshal.load latest_specs_dump
+
+    expected = [
+      ['a',      Gem::Version.new(2),     'ruby'],
+      ['a_evil', Gem::Version.new(9),     'ruby'],
+      ['b',      Gem::Version.new(2),     'ruby'],
+      ['c',      Gem::Version.new('1.2'), 'ruby'],
+      ['d',      Gem::Version.new('2.0'), 'ruby'],
+      ['pl',     Gem::Version.new(1),     'i386-linux'],
+    ]
+
+    assert_equal expected, latest_specs
+
+    assert_same latest_specs[0][1],   latest_specs[2][1],
+                'identical versions not identical'
+
+    assert_same latest_specs[0].last, latest_specs[1].last,
+                'identical platforms not identical'
+  end
+
+  def test_generate_index_prerelease_specs
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    prerelease_specs_path = File.join @tempdir, "prerelease_specs.#{@marshal_version}"
+
+    prerelease_specs_dump = Gem.read_binary prerelease_specs_path
+    prerelease_specs = Marshal.load prerelease_specs_dump
+
+    assert_equal [['a', Gem::Version.new('3.a'),   'ruby'],
+                  ['d', Gem::Version.new('2.0.a'), 'ruby'],
+                  ['d', Gem::Version.new('2.0.b'), 'ruby']],
+                 prerelease_specs
+  end
+
+  def test_update_index
+    use_ui @ui do
+      @indexer.generate_index
+    end
+
+    quickdir = File.join @tempdir, 'quick'
+    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+    assert File.directory?(quickdir)
+    assert File.directory?(marshal_quickdir)
+
+    @d2_1 = quick_gem 'd', '2.1'
+    util_build_gem @d2_1
+    @d2_1_tuple = [@d2_1.name, @d2_1.version, @d2_1.original_platform]
+
+    @d2_1_a = quick_gem 'd', '2.2.a'
+    util_build_gem @d2_1_a
+    @d2_1_a_tuple = [@d2_1_a.name, @d2_1_a.version, @d2_1_a.original_platform]
+
+    gems = File.join @tempdir, 'gems'
+    FileUtils.mv File.join(@gemhome, 'cache', @d2_1.file_name), gems
+    FileUtils.mv File.join(@gemhome, 'cache', @d2_1_a.file_name), gems
+
+    use_ui @ui do
+      @indexer.update_index
+    end
+
+    assert_indexed marshal_quickdir, "#{@d2_1.spec_name}.rz"
+
+    specs_index = Marshal.load Gem.read_binary(@indexer.dest_specs_index)
+
+    assert_includes specs_index, @d2_1_tuple
+    refute_includes specs_index, @d2_1_a_tuple
+
+    latest_specs_index = Marshal.load \
+      Gem.read_binary(@indexer.dest_latest_specs_index)
+
+    assert_includes latest_specs_index, @d2_1_tuple
+    assert_includes latest_specs_index,
+                    [@d2_0.name, @d2_0.version, @d2_0.original_platform]
+    refute_includes latest_specs_index, @d2_1_a_tuple
+
+    pre_specs_index = Marshal.load \
+      Gem.read_binary(@indexer.dest_prerelease_specs_index)
+
+    assert_includes pre_specs_index, @d2_1_a_tuple
+    refute_includes pre_specs_index, @d2_1_tuple
+  end
+
+  def assert_indexed(dir, name)
+    file = File.join dir, name
+    assert File.exist?(file), "#{file} does not exist"
+  end
+
+  def refute_indexed(dir, name)
+    file = File.join dir, name
+    refute File.exist?(file), "#{file} exists"
+  end
+
+end if ''.respond_to? :to_xs
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_install_update_options.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_install_update_options.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_install_update_options.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,74 @@
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_installer_test_case')
+require 'rubygems/install_update_options'
+require 'rubygems/command'
+
+class TestGemInstallUpdateOptions < GemInstallerTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Command.new 'dummy', 'dummy'
+    @cmd.extend Gem::InstallUpdateOptions
+    @cmd.add_install_update_options
+  end
+
+  def test_add_install_update_options
+    args = %w[-i /install_to --rdoc --ri -E -f -t -w -P HighSecurity
+              --ignore-dependencies --format-exec --include-dependencies]
+
+    assert @cmd.handles?(args)
+  end
+
+  def test_prerelease
+    @cmd.handle_options %w[--prerelease]
+    assert_equal true, @cmd.options[:prerelease]
+  end
+
+  def test_security_policy
+    @cmd.handle_options %w[-P HighSecurity]
+
+    assert_equal Gem::Security::HighSecurity, @cmd.options[:security_policy]
+  end
+
+  def test_security_policy_unknown
+    @cmd.add_install_update_options
+
+    assert_raises OptionParser::InvalidArgument do
+      @cmd.handle_options %w[-P UnknownSecurity]
+    end
+  end
+
+  def test_user_install_enabled
+    @cmd.handle_options %w[--user-install]
+
+    assert @cmd.options[:user_install]
+
+    @installer = Gem::Installer.new @gem, @cmd.options
+    @installer.install
+    assert File.exist?(File.join(Gem.user_dir, 'gems'))
+    assert File.exist?(File.join(Gem.user_dir, 'gems',
+                                 @spec.full_name))
+  end
+
+  def test_user_install_disabled_read_only
+    if win_platform?
+      skip('test_user_install_disabled_read_only test skipped on MS Windows')
+    else
+      @cmd.handle_options %w[--no-user-install]
+
+      refute @cmd.options[:user_install]
+
+      File.chmod 0755, @userhome
+      FileUtils.chmod 0000, @gemhome
+
+      assert_raises(Gem::FilePermissionError) do
+        @installer = Gem::Installer.new @gem, @cmd.options
+      end
+    end
+  ensure
+    FileUtils.chmod 0755, @gemhome
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_installer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_installer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_installer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,873 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_installer_test_case')
+
+class TestGemInstaller < GemInstallerTestCase
+
+  def test_app_script_text
+    util_make_exec '2', ''
+
+    expected = <<-EOF
+#!#{Gem.ruby}
+#
+# This file was generated by RubyGems.
+#
+# The application 'a' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = \">= 0\"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+  version = $1
+  ARGV.shift
+end
+
+gem 'a', version
+load Gem.bin_path('a', 'my_exec', version)
+    EOF
+
+    wrapper = @installer.app_script_text 'my_exec'
+    assert_equal expected, wrapper
+  end
+
+  def test_build_extensions_none
+    use_ui @ui do
+      @installer.build_extensions
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+
+    refute File.exist?('gem_make.out')
+  end
+
+  def test_build_extensions_extconf_bad
+    @spec.extensions << 'extconf.rb'
+
+    e = assert_raises Gem::Installer::ExtensionBuildError do
+      use_ui @ui do
+        @installer.build_extensions
+      end
+    end
+
+    assert_match(/\AERROR: Failed to build gem native extension.$/, e.message)
+
+    assert_equal "Building native extensions.  This could take a while...\n",
+                 @ui.output
+    assert_equal '', @ui.error
+
+    gem_make_out = File.join @gemhome, 'gems', @spec.full_name, 'gem_make.out'
+    expected = <<-EOF
+#{Gem.ruby} extconf.rb
+#{Gem.ruby}: No such file or directory -- extconf.rb (LoadError)
+    EOF
+
+    assert_match %r%#{Regexp.escape Gem.ruby} extconf.rb%,
+                 File.read(gem_make_out)
+    assert_match %r%#{Regexp.escape Gem.ruby}: No such file%,
+                 File.read(gem_make_out)
+  end
+
+  def test_build_extensions_unsupported
+    @spec.extensions << nil
+
+    e = assert_raises Gem::Installer::ExtensionBuildError do
+      use_ui @ui do
+        @installer.build_extensions
+      end
+    end
+
+    assert_match(/^No builder for extension ''$/, e.message)
+
+    assert_equal "Building native extensions.  This could take a while...\n",
+                 @ui.output
+    assert_equal '', @ui.error
+
+    assert_equal "No builder for extension ''\n", File.read('gem_make.out')
+  ensure
+    FileUtils.rm_f 'gem_make.out'
+  end
+
+  def test_ensure_dependency
+    dep = Gem::Dependency.new 'a', '>= 2'
+    assert @installer.ensure_dependency(@spec, dep)
+
+    dep = Gem::Dependency.new 'b', '> 2'
+    e = assert_raises Gem::InstallError do
+      @installer.ensure_dependency @spec, dep
+    end
+
+    assert_equal 'a requires b (> 2, runtime)', e.message
+  end
+
+  def test_expand_and_validate_gem_dir
+    @installer.gem_dir = '/nonexistent'
+    expanded_gem_dir = @installer.send(:expand_and_validate_gem_dir)
+    if win_platform?
+      expected = File.expand_path('/nonexistent').downcase
+      expanded_gem_dir = expanded_gem_dir.downcase
+    else
+      expected = '/nonexistent'
+    end
+
+    assert_equal expected, expanded_gem_dir
+  end
+
+  def test_extract_files
+    format = Object.new
+    def format.file_entries
+      [[{'size' => 7, 'mode' => 0400, 'path' => 'thefile'}, 'thefile']]
+    end
+
+    @installer.format = format
+
+    @installer.extract_files
+
+    thefile_path = File.join(util_gem_dir, 'thefile')
+    assert_equal 'thefile', File.read(thefile_path)
+
+    unless Gem.win_platform? then
+      assert_equal 0400, File.stat(thefile_path).mode & 0777
+    end
+  end
+
+  def test_extract_files_bad_dest
+    @installer.gem_dir = 'somedir'
+    @installer.format = nil
+    e = assert_raises ArgumentError do
+      @installer.extract_files
+    end
+
+    assert_equal 'format required to extract from', e.message
+  end
+
+  def test_extract_files_relative
+    format = Object.new
+    def format.file_entries
+      [[{'size' => 10, 'mode' => 0644, 'path' => '../thefile'}, '../thefile']]
+    end
+
+    @installer.format = format
+
+    e = assert_raises Gem::InstallError do
+      @installer.extract_files
+    end
+
+    assert_equal "attempt to install file into \"../thefile\" under #{util_gem_dir.inspect}",
+                 e.message
+    assert_equal false, File.file?(File.join(@tempdir, '../thefile')),
+                 "You may need to remove this file if you broke the test once"
+  end
+
+  def test_extract_files_absolute
+    format = Object.new
+    def format.file_entries
+      [[{'size' => 8, 'mode' => 0644, 'path' => '/thefile'}, '/thefile']]
+    end
+
+    @installer.format = format
+
+    e = assert_raises Gem::InstallError do
+      @installer.extract_files
+    end
+
+    assert_equal 'attempt to install file into "/thefile"', e.message
+    assert_equal false, File.file?(File.join('/thefile')),
+                 "You may need to remove this file if you broke the test once"
+  end
+
+  def test_generate_bin_bindir
+    @installer.wrappers = true
+
+    @spec.executables = ["my_exec"]
+    @spec.bindir = '.'
+
+    exec_file = @installer.formatted_program_filename "my_exec"
+    exec_path = File.join util_gem_dir(@spec.version), exec_file
+    File.open exec_path, 'w' do |f|
+      f.puts '#!/usr/bin/ruby'
+    end
+
+    @installer.gem_dir = util_gem_dir
+
+    @installer.generate_bin
+
+    assert_equal true, File.directory?(util_inst_bindir)
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal true, File.exist?(installed_exec)
+    assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+    wrapper = File.read installed_exec
+    assert_match %r|generated by RubyGems|, wrapper
+  end
+
+  def test_generate_bin_script
+    @installer.wrappers = true
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    @installer.generate_bin
+    assert_equal true, File.directory?(util_inst_bindir)
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal true, File.exist?(installed_exec)
+    assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+    wrapper = File.read installed_exec
+    assert_match %r|generated by RubyGems|, wrapper
+  end
+
+  def test_generate_bin_script_format
+    @installer.format_executable = true
+    @installer.wrappers = true
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    Gem::Installer.exec_format = 'foo-%s-bar'
+    @installer.generate_bin
+    assert_equal true, File.directory?(util_inst_bindir)
+    installed_exec = File.join util_inst_bindir, 'foo-my_exec-bar'
+    assert_equal true, File.exist?(installed_exec)
+  ensure
+    Gem::Installer.exec_format = nil
+  end
+
+  def test_generate_bin_script_format_disabled
+    @installer.wrappers = true
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    Gem::Installer.exec_format = 'foo-%s-bar'
+    @installer.generate_bin
+    assert_equal true, File.directory?(util_inst_bindir)
+    installed_exec = File.join util_inst_bindir, 'my_exec'
+    assert_equal true, File.exist?(installed_exec)
+  ensure
+    Gem::Installer.exec_format = nil
+  end
+
+  def test_generate_bin_script_install_dir
+    @installer.wrappers = true
+    @spec.executables = ["my_exec"]
+
+    gem_dir = File.join "#{@gemhome}2", 'gems', @spec.full_name
+    gem_bindir = File.join gem_dir, 'bin'
+    FileUtils.mkdir_p gem_bindir
+    File.open File.join(gem_bindir, "my_exec"), 'w' do |f|
+      f.puts "#!/bin/ruby"
+    end
+
+    @installer.gem_home = "#{@gemhome}2"
+    @installer.gem_dir = gem_dir
+
+    @installer.generate_bin
+
+    installed_exec = File.join("#{@gemhome}2", 'bin', 'my_exec')
+    assert_equal true, File.exist?(installed_exec)
+    assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+    wrapper = File.read installed_exec
+    assert_match %r|generated by RubyGems|, wrapper
+  end
+
+  def test_generate_bin_script_no_execs
+    @installer.wrappers = true
+    @installer.generate_bin
+    assert_equal false, File.exist?(util_inst_bindir)
+  end
+
+  def test_generate_bin_script_no_perms
+    @installer.wrappers = true
+    util_make_exec
+
+    Dir.mkdir util_inst_bindir
+
+    if win_platform?
+      skip('test_generate_bin_script_no_perms skipped on MS Windows')
+    else
+      File.chmod 0000, util_inst_bindir
+
+      assert_raises Gem::FilePermissionError do
+        @installer.generate_bin
+      end
+    end
+  ensure
+    File.chmod 0700, util_inst_bindir unless $DEBUG
+  end
+
+  def test_generate_bin_script_no_shebang
+    @installer.wrappers = true
+    @spec.executables = ["my_exec"]
+
+    gem_dir = File.join @gemhome, 'gems', @spec.full_name
+    gem_bindir = File.join gem_dir, 'bin'
+    FileUtils.mkdir_p gem_bindir
+    File.open File.join(gem_bindir, "my_exec"), 'w' do |f|
+      f.puts "blah blah blah"
+    end
+
+    @installer.generate_bin
+
+    installed_exec = File.join @gemhome, 'bin', 'my_exec'
+    assert_equal true, File.exist?(installed_exec)
+    assert_equal 0100755, File.stat(installed_exec).mode unless win_platform?
+
+    wrapper = File.read installed_exec
+    assert_match %r|generated by RubyGems|, wrapper
+    # HACK some gems don't have #! in their executables, restore 2008/06
+    #assert_no_match %r|generated by RubyGems|, wrapper
+  end
+
+  def test_generate_bin_script_wrappers
+    @installer.wrappers = true
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+
+    real_exec = File.join util_gem_dir, 'bin', 'my_exec'
+
+    # fake --no-wrappers for previous install
+    unless Gem.win_platform? then
+      FileUtils.mkdir_p File.dirname(installed_exec)
+      FileUtils.ln_s real_exec, installed_exec
+    end
+
+    @installer.generate_bin
+    assert_equal true, File.directory?(util_inst_bindir)
+    assert_equal true, File.exist?(installed_exec)
+    assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+    assert_match %r|generated by RubyGems|, File.read(installed_exec)
+
+    refute_match %r|generated by RubyGems|, File.read(real_exec),
+                 'real executable overwritten'
+  end
+
+  def test_generate_bin_symlink
+    return if win_platform? #Windows FS do not support symlinks
+
+    @installer.wrappers = false
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    @installer.generate_bin
+    assert_equal true, File.directory?(util_inst_bindir)
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal true, File.symlink?(installed_exec)
+    assert_equal(File.join(util_gem_dir, "bin", "my_exec"),
+                 File.readlink(installed_exec))
+  end
+
+  def test_generate_bin_symlink_no_execs
+    @installer.wrappers = false
+    @installer.generate_bin
+    assert_equal false, File.exist?(util_inst_bindir)
+  end
+
+  def test_generate_bin_symlink_no_perms
+    @installer.wrappers = false
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    Dir.mkdir util_inst_bindir
+
+    if win_platform?
+      skip('test_generate_bin_symlink_no_perms skipped on MS Windows')
+    else
+      File.chmod 0000, util_inst_bindir
+
+      assert_raises Gem::FilePermissionError do
+        @installer.generate_bin
+      end
+    end
+  ensure
+    File.chmod 0700, util_inst_bindir unless $DEBUG
+  end
+
+  def test_generate_bin_symlink_update_newer
+    return if win_platform? #Windows FS do not support symlinks
+
+    @installer.wrappers = false
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    @installer.generate_bin
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal(File.join(util_gem_dir, "bin", "my_exec"),
+                 File.readlink(installed_exec))
+
+    @spec = Gem::Specification.new do |s|
+      s.files = ['lib/code.rb']
+      s.name = "a"
+      s.version = "3"
+      s.summary = "summary"
+      s.description = "desc"
+      s.require_path = 'lib'
+    end
+
+    util_make_exec '3'
+    @installer.gem_dir = File.join util_gem_dir('3')
+    @installer.generate_bin
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal(File.join(util_gem_bindir('3'), "my_exec"),
+                 File.readlink(installed_exec),
+                 "Ensure symlink moved to latest version")
+  end
+
+  def test_generate_bin_symlink_update_older
+    return if win_platform? #Windows FS do not support symlinks
+
+    @installer.wrappers = false
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    @installer.generate_bin
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal(File.join(util_gem_dir, "bin", "my_exec"),
+                 File.readlink(installed_exec))
+
+    spec = Gem::Specification.new do |s|
+      s.files = ['lib/code.rb']
+      s.name = "a"
+      s.version = "1"
+      s.summary = "summary"
+      s.description = "desc"
+      s.require_path = 'lib'
+    end
+
+    util_make_exec '1'
+    @installer.gem_dir = util_gem_dir('1')
+    @installer.spec = spec
+
+    @installer.generate_bin
+
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal(File.join(util_gem_dir('2'), "bin", "my_exec"),
+                 File.readlink(installed_exec),
+                 "Ensure symlink not moved")
+  end
+
+  def test_generate_bin_symlink_update_remove_wrapper
+    return if win_platform? #Windows FS do not support symlinks
+
+    @installer.wrappers = true
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    @installer.generate_bin
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal true, File.exist?(installed_exec)
+
+    @spec = Gem::Specification.new do |s|
+      s.files = ['lib/code.rb']
+      s.name = "a"
+      s.version = "3"
+      s.summary = "summary"
+      s.description = "desc"
+      s.require_path = 'lib'
+    end
+
+    @installer.wrappers = false
+    util_make_exec '3'
+    @installer.gem_dir = util_gem_dir '3'
+    @installer.generate_bin
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal(File.join(util_gem_dir('3'), "bin", "my_exec"),
+                 File.readlink(installed_exec),
+                 "Ensure symlink moved to latest version")
+  end
+
+  def test_generate_bin_symlink_win32
+    old_win_platform = Gem.win_platform?
+    Gem.win_platform = true
+    @installer.wrappers = false
+    util_make_exec
+    @installer.gem_dir = util_gem_dir
+
+    use_ui @ui do
+      @installer.generate_bin
+    end
+
+    assert_equal true, File.directory?(util_inst_bindir)
+    installed_exec = File.join(util_inst_bindir, "my_exec")
+    assert_equal true, File.exist?(installed_exec)
+
+    assert_match(/Unable to use symlinks on Windows, installing wrapper/i,
+                 @ui.error)
+
+    wrapper = File.read installed_exec
+    assert_match(/generated by RubyGems/, wrapper)
+  ensure
+    Gem.win_platform = old_win_platform
+  end
+
+  def test_generate_bin_uses_default_shebang
+    return if win_platform? #Windows FS do not support symlinks
+
+    @installer.wrappers = true
+    util_make_exec
+
+    @installer.generate_bin
+
+    default_shebang = Gem.ruby
+    shebang_line = open("#{@gemhome}/bin/my_exec") { |f| f.readlines.first }
+    assert_match(/\A#!/, shebang_line)
+    assert_match(/#{default_shebang}/, shebang_line)
+  end
+
+  def test_initialize
+    spec = quick_gem 'a' do |s| s.platform = Gem::Platform.new 'mswin32' end
+    gem = File.join @tempdir, spec.file_name
+
+    Dir.mkdir util_inst_bindir
+    util_build_gem spec
+    FileUtils.mv File.join(@gemhome, 'cache', spec.file_name),
+                 @tempdir
+
+    installer = Gem::Installer.new gem
+
+    assert_equal File.join(@gemhome, 'gems', spec.full_name), installer.gem_dir
+  end
+
+  def test_install
+    Dir.mkdir util_inst_bindir
+    util_setup_gem
+
+    cache_file = File.join @gemhome, 'cache', @spec.file_name
+
+    Gem.pre_install do |installer|
+      refute File.exist?(cache_file), 'cache file should not exist yet'
+    end
+
+    Gem.post_install do |installer|
+      assert File.exist?(cache_file), 'cache file should exist'
+    end
+
+    build_rake_in do
+      use_ui @ui do
+        assert_equal @spec, @installer.install
+      end
+    end
+
+    gemdir = File.join @gemhome, 'gems', @spec.full_name
+    assert File.exist?(gemdir)
+
+    exe = File.join(gemdir, 'bin', 'executable')
+    assert File.exist?(exe)
+    exe_mode = File.stat(exe).mode & 0111
+    assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform?
+
+    assert File.exist?(File.join(gemdir, 'lib', 'code.rb'))
+
+    assert File.exist?(File.join(gemdir, 'ext', 'a', 'Rakefile'))
+
+    spec_file = File.join(@gemhome, 'specifications', @spec.spec_name)
+
+    assert_equal spec_file, @spec.loaded_from
+    assert File.exist?(spec_file)
+
+    assert_same @installer, @pre_install_hook_arg
+    assert_same @installer, @post_install_hook_arg
+  end
+
+  def test_install_bad_gem
+    gem = nil
+
+    use_ui @ui do
+      Dir.chdir @tempdir do Gem::Builder.new(@spec).build end
+      gem = File.join @tempdir, @spec.file_name
+    end
+
+    gem_data = File.open gem, 'rb' do |fp| fp.read 1024 end
+    File.open gem, 'wb' do |fp| fp.write gem_data end
+
+    e = assert_raises Gem::InstallError do
+      use_ui @ui do
+        @installer = Gem::Installer.new gem
+        @installer.install
+      end
+    end
+
+    assert_equal "invalid gem format for #{gem}", e.message
+  end
+
+  def test_install_check_dependencies
+    @spec.add_dependency 'b', '> 5'
+    util_setup_gem
+
+    use_ui @ui do
+      assert_raises Gem::InstallError do
+        @installer.install
+      end
+    end
+  end
+
+  def test_install_check_dependencies_install_dir
+    gemhome2 = "#{@gemhome}2"
+    @spec.add_dependency 'b'
+
+    b2 = quick_gem 'b', 2
+
+    FileUtils.mv @gemhome, gemhome2
+    Gem.source_index.gems.delete b2.full_name
+    source_index = Gem::SourceIndex.from_gems_in File.join(gemhome2,
+                                                           'specifications')
+
+    util_setup_gem
+
+    @installer = Gem::Installer.new @gem, :install_dir => gemhome2,
+                                    :source_index => source_index
+
+    build_rake_in do
+      use_ui @ui do
+        @installer.install
+      end
+    end
+
+    assert File.exist?(File.join(gemhome2, 'gems', @spec.full_name))
+  end
+
+  def test_install_force
+    use_ui @ui do
+      installer = Gem::Installer.new old_ruby_required, :force => true
+      installer.install
+    end
+
+    gem_dir = File.join(@gemhome, 'gems', 'old_ruby_required-1')
+    assert File.exist?(gem_dir)
+  end
+
+  def test_install_ignore_dependencies
+    Dir.mkdir util_inst_bindir
+    @spec.add_dependency 'b', '> 5'
+    util_setup_gem
+    @installer.ignore_dependencies = true
+
+    build_rake_in do
+      use_ui @ui do
+        assert_equal @spec, @installer.install
+      end
+    end
+
+    gemdir = File.join @gemhome, 'gems', @spec.full_name
+    assert File.exist?(gemdir)
+
+    exe = File.join(gemdir, 'bin', 'executable')
+    assert File.exist?(exe)
+    exe_mode = File.stat(exe).mode & 0111
+    assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform?
+    assert File.exist?(File.join(gemdir, 'lib', 'code.rb'))
+
+    assert File.exist?(File.join(@gemhome, 'specifications', @spec.spec_name))
+  end
+
+  def test_install_missing_dirs
+    FileUtils.rm_f File.join(Gem.dir, 'cache')
+    FileUtils.rm_f File.join(Gem.dir, 'docs')
+    FileUtils.rm_f File.join(Gem.dir, 'specifications')
+
+    use_ui @ui do
+      Dir.chdir @tempdir do Gem::Builder.new(@spec).build end
+      gem = File.join @tempdir, @spec.file_name
+
+      @installer.install
+    end
+
+    File.directory? File.join(Gem.dir, 'cache')
+    File.directory? File.join(Gem.dir, 'docs')
+    File.directory? File.join(Gem.dir, 'specifications')
+
+    assert File.exist?(File.join(@gemhome, 'cache', @spec.file_name))
+    assert File.exist?(File.join(@gemhome, 'specifications', @spec.spec_name))
+  end
+
+  def test_install_with_message
+    @spec.post_install_message = 'I am a shiny gem!'
+
+    use_ui @ui do
+      Dir.chdir @tempdir do Gem::Builder.new(@spec).build end
+
+      @installer.install
+    end
+
+    assert_match %r|I am a shiny gem!|, @ui.output
+  end
+
+  def test_install_wrong_ruby_version
+    use_ui @ui do
+      installer = Gem::Installer.new old_ruby_required
+      e = assert_raises Gem::InstallError do
+        installer.install
+      end
+      assert_equal 'old_ruby_required requires Ruby version = 1.4.6',
+                   e.message
+    end
+  end
+
+  def test_install_wrong_rubygems_version
+    spec = quick_gem 'old_rubygems_required', '1' do |s|
+      s.required_rubygems_version = '< 0'
+    end
+
+    util_build_gem spec
+
+    gem = File.join @gemhome, 'cache', spec.file_name
+
+    use_ui @ui do
+      @installer = Gem::Installer.new gem
+      e = assert_raises Gem::InstallError do
+        @installer.install
+      end
+      assert_equal 'old_rubygems_required requires RubyGems version < 0',
+                   e.message
+    end
+  end
+
+  def test_installation_satisfies_dependency_eh
+    dep = Gem::Dependency.new 'a', '>= 2'
+    assert @installer.installation_satisfies_dependency?(dep)
+
+    dep = Gem::Dependency.new 'a', '> 2'
+    refute @installer.installation_satisfies_dependency?(dep)
+  end
+
+  def test_shebang
+    util_make_exec '2', "#!/usr/bin/ruby"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby}", shebang
+  end
+
+  def test_shebang_arguments
+    util_make_exec '2', "#!/usr/bin/ruby -ws"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby} -ws", shebang
+  end
+
+  def test_shebang_empty
+    util_make_exec '2', ''
+
+    shebang = @installer.shebang 'my_exec'
+    assert_equal "#!#{Gem.ruby}", shebang
+  end
+
+  def test_shebang_env
+    util_make_exec '2', "#!/usr/bin/env ruby"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby}", shebang
+  end
+
+  def test_shebang_env_arguments
+    util_make_exec '2', "#!/usr/bin/env ruby -ws"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby} -ws", shebang
+  end
+
+  def test_shebang_env_shebang
+    util_make_exec '2', ''
+    @installer.env_shebang = true
+
+    shebang = @installer.shebang 'my_exec'
+    assert_equal "#!/usr/bin/env #{Gem::ConfigMap[:ruby_install_name]}", shebang
+  end
+
+  def test_shebang_nested
+    util_make_exec '2', "#!/opt/local/ruby/bin/ruby"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby}", shebang
+  end
+
+  def test_shebang_nested_arguments
+    util_make_exec '2', "#!/opt/local/ruby/bin/ruby -ws"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby} -ws", shebang
+  end
+
+  def test_shebang_version
+    util_make_exec '2', "#!/usr/bin/ruby18"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby}", shebang
+  end
+
+  def test_shebang_version_arguments
+    util_make_exec '2', "#!/usr/bin/ruby18 -ws"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby} -ws", shebang
+  end
+
+  def test_shebang_version_env
+    util_make_exec '2', "#!/usr/bin/env ruby18"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby}", shebang
+  end
+
+  def test_shebang_version_env_arguments
+    util_make_exec '2', "#!/usr/bin/env ruby18 -ws"
+
+    shebang = @installer.shebang 'my_exec'
+
+    assert_equal "#!#{Gem.ruby} -ws", shebang
+  end
+
+  def test_unpack
+    util_setup_gem
+
+    dest = File.join @gemhome, 'gems', @spec.full_name
+
+    @installer.unpack dest
+
+    assert File.exist?(File.join(dest, 'lib', 'code.rb'))
+    assert File.exist?(File.join(dest, 'bin', 'executable'))
+  end
+
+  def test_write_spec
+    spec_dir = File.join @gemhome, 'specifications'
+    spec_file = File.join spec_dir, @spec.spec_name
+    FileUtils.rm spec_file
+    refute File.exist?(spec_file)
+
+    @installer.spec = @spec
+    @installer.gem_home = @gemhome
+
+    @installer.write_spec
+
+    assert File.exist?(spec_file)
+    assert_equal @spec, eval(File.read(spec_file))
+  end
+
+  def old_ruby_required
+    spec = quick_gem 'old_ruby_required', '1' do |s|
+      s.required_ruby_version = '= 1.4.6'
+    end
+
+    util_build_gem spec
+
+    File.join @gemhome, 'cache', spec.file_name
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_local_remote_options.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_local_remote_options.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_local_remote_options.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,97 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/local_remote_options'
+require 'rubygems/command'
+
+class TestGemLocalRemoteOptions < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Command.new 'dummy', 'dummy'
+    @cmd.extend Gem::LocalRemoteOptions
+  end
+
+  def test_add_local_remote_options
+    @cmd.add_local_remote_options
+
+    args = %w[-l -r -b -B 10 --source http://gems.example.com -p --update-sources]
+    assert @cmd.handles?(args)
+  end
+
+  def test_both_eh
+    assert_equal false, @cmd.both?
+
+    @cmd.options[:domain] = :local
+
+    assert_equal false, @cmd.both?
+
+    @cmd.options[:domain] = :both
+
+    assert_equal true, @cmd.both?
+  end
+
+  def test_local_eh
+    assert_equal false, @cmd.local?
+
+    @cmd.options[:domain] = :local
+
+    assert_equal true, @cmd.local?
+
+    @cmd.options[:domain] = :both
+
+    assert_equal true, @cmd.local?
+  end
+
+  def test_remote_eh
+    assert_equal false, @cmd.remote?
+
+    @cmd.options[:domain] = :remote
+
+    assert_equal true, @cmd.remote?
+
+    @cmd.options[:domain] = :both
+
+    assert_equal true, @cmd.remote?
+  end
+
+  def test_source_option
+    @cmd.add_source_option
+
+    s1 = URI.parse 'http://more-gems.example.com/'
+    s2 = URI.parse 'http://even-more-gems.example.com/'
+    s3 = URI.parse 'http://other-gems.example.com/some_subdir'
+    s4 = URI.parse 'http://more-gems.example.com/' # Intentional duplicate
+
+    @cmd.handle_options %W[--source #{s1} --source #{s2} --source #{s3} --source #{s4}]
+
+    assert_equal [s1.to_s, s2.to_s, "#{s3}/"], Gem.sources
+  end
+
+  def test_update_sources_option
+    @cmd.add_update_sources_option
+
+    Gem.configuration.update_sources = false
+
+    @cmd.handle_options %W[--update-sources]
+
+    assert_equal true, Gem.configuration.update_sources
+
+    @cmd.handle_options %W[--no-update-sources]
+
+    assert_equal false, Gem.configuration.update_sources
+  end
+
+  def test_source_option_bad
+    @cmd.add_source_option
+
+    s1 = 'htp://more-gems.example.com'
+
+    assert_raises OptionParser::InvalidArgument do
+      @cmd.handle_options %W[--source #{s1}]
+    end
+
+    assert_equal [@gem_repo], Gem.sources
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_header.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_header.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_header.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,137 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_package_tar_test_case')
+require 'rubygems/package'
+
+class TestGemPackageTarHeader < TarTestCase
+
+  def setup
+    super
+
+    header = {
+      :name     => 'x',
+      :mode     => 0644,
+      :uid      => 1000,
+      :gid      => 10000,
+      :size     => 100,
+      :mtime    => 12345,
+      :typeflag => '0',
+      :linkname => 'link',
+      :uname    => 'user',
+      :gname    => 'group',
+      :devmajor => 1,
+      :devminor => 2,
+      :prefix   => 'y',
+    }
+
+    @tar_header = Gem::Package::TarHeader.new header
+  end
+
+  def test_self_from
+    io = TempIO.new @tar_header.to_s
+
+    new_header = Gem::Package::TarHeader.from io
+
+    assert_headers_equal @tar_header, new_header
+  end
+
+  def test_initialize
+    assert_equal '',      @tar_header.checksum, 'checksum'
+    assert_equal 1,       @tar_header.devmajor, 'devmajor'
+    assert_equal 2,       @tar_header.devminor, 'devminor'
+    assert_equal 10000,   @tar_header.gid,      'gid'
+    assert_equal 'group', @tar_header.gname,    'gname'
+    assert_equal 'link',  @tar_header.linkname, 'linkname'
+    assert_equal 'ustar', @tar_header.magic,    'magic'
+    assert_equal 0644,    @tar_header.mode,     'mode'
+    assert_equal 12345,   @tar_header.mtime,    'mtime'
+    assert_equal 'x',     @tar_header.name,     'name'
+    assert_equal 'y',     @tar_header.prefix,   'prefix'
+    assert_equal 100,     @tar_header.size,     'size'
+    assert_equal '0',     @tar_header.typeflag, 'typeflag'
+    assert_equal 1000,    @tar_header.uid,      'uid'
+    assert_equal 'user',  @tar_header.uname,    'uname'
+    assert_equal '00',    @tar_header.version,  'version'
+
+    refute_empty @tar_header, 'empty'
+  end
+
+  def test_initialize_bad
+    assert_raises ArgumentError do
+      Gem::Package::TarHeader.new :name => '', :size => '', :mode => ''
+    end
+
+    assert_raises ArgumentError do
+      Gem::Package::TarHeader.new :name => '', :size => '', :prefix => ''
+    end
+
+    assert_raises ArgumentError do
+      Gem::Package::TarHeader.new :name => '', :prefix => '', :mode => ''
+    end
+
+    assert_raises ArgumentError do
+      Gem::Package::TarHeader.new :prefix => '', :size => '', :mode => ''
+    end
+  end
+
+  def test_empty_eh
+    refute_empty @tar_header
+
+    @tar_header = Gem::Package::TarHeader.new :name => 'x', :prefix => '',
+                                              :mode => 0, :size => 0,
+                                              :empty => true
+
+    assert_empty @tar_header
+  end
+
+  def test_equals2
+    assert_equal @tar_header, @tar_header
+    assert_equal @tar_header, @tar_header.dup
+  end
+
+  def test_to_s
+    expected = <<-EOF.split("\n").join
+x\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\0000000644\0000001750\0000023420\00000000000144\00000000030071
+\000012467\000 0link\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000ustar\00000user\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\0000000001\0000000002\000y\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000
+    EOF
+
+    assert_headers_equal expected, @tar_header
+  end
+
+  def test_update_checksum
+    assert_equal '', @tar_header.checksum
+
+    @tar_header.update_checksum
+
+    assert_equal '012467', @tar_header.checksum
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_input.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_input.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_input.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,119 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_package_tar_test_case')
+require 'rubygems/package/tar_input'
+
+class TestGemPackageTarInput < TarTestCase
+
+  # Sometimes the setgid bit doesn't take.  Don't know if this is a problem on
+  # all systems, or just some.  But for now, we will ignore it in the tests.
+  SETGID_BIT = 02000
+
+  def setup
+    super
+
+    inner_tar = tar_file_header("bla", "", 0612, 10)
+    inner_tar += "0123456789" + "\0" * 502
+    inner_tar += tar_file_header("foo", "", 0636, 5)
+    inner_tar += "01234" + "\0" * 507
+    inner_tar += tar_dir_header("__dir__", "", 0600)
+    inner_tar += "\0" * 1024
+    str = TempIO.new
+
+    begin
+      os = Zlib::GzipWriter.new str
+      os.write inner_tar
+    ensure
+      os.finish
+    end
+
+    str.rewind
+
+    @file = File.join @tempdir, 'bla.tar'
+
+    File.open @file, 'wb' do |f|
+      f.write tar_file_header("data.tar.gz", "", 0644, str.string.size)
+      f.write str.string
+      f.write "\0" * ((512 - (str.string.size % 512)) % 512 )
+
+      @spec = Gem::Specification.new do |spec|
+        spec.author = "Mauricio :)"
+      end
+
+      meta = @spec.to_yaml
+
+      f.write tar_file_header("metadata", "", 0644, meta.size)
+      f.write meta + "\0" * (1024 - meta.size) 
+      f.write "\0" * 1024
+    end
+
+    @entry_names = %w{bla foo __dir__}
+    @entry_sizes = [10, 5, 0]
+    #FIXME: are these modes system dependent?
+    @entry_modes = [0100612, 0100636, 040600]
+    @entry_files = %W[#{@tempdir}/bla #{@tempdir}/foo]
+    @entry_contents = %w[0123456789 01234]
+  end
+
+  def test_each_works
+    open @file, 'rb' do |io|
+      Gem::Package::TarInput.open io do |tar_input|
+        count = 0
+
+        tar_input.each_with_index do |entry, i|
+          count = i
+
+          assert_kind_of Gem::Package::TarReader::Entry, entry
+          assert_equal @entry_names[i], entry.header.name
+          assert_equal @entry_sizes[i], entry.header.size
+        end
+
+        assert_equal 2, count
+
+        assert_equal @spec, tar_input.metadata
+      end
+    end
+  end
+
+  def test_extract_entry_works
+    open @file, 'rb' do |io|
+      Gem::Package::TarInput.open io do |tar_input|
+        assert_equal @spec, tar_input.metadata
+
+        count = 0
+
+        tar_input.each_with_index do |entry, i|
+          count = i
+          tar_input.extract_entry @tempdir, entry
+          name = File.join @tempdir, entry.header.name
+
+          if entry.directory? then
+            assert File.directory?(name)
+          else
+            assert File.file?(name)
+            assert_equal @entry_sizes[i], File.stat(name).size
+            #FIXME: win32? !!
+          end
+
+          unless Gem.win_platform? then
+            assert_equal @entry_modes[i], File.stat(name).mode & (~SETGID_BIT)
+          end
+        end
+
+        assert_equal 2, count
+      end
+    end
+
+    @entry_files.each_with_index do |x, i|
+      assert File.file?(x)
+      assert_equal @entry_contents[i], Gem.read_binary(x)
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_output.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_output.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_output.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,104 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_package_tar_test_case')
+require 'rubygems/package/tar_output'
+
+class TestGemPackageTarOutput < TarTestCase
+
+  def setup
+    super
+
+    @file = File.join @tempdir, 'bla2.tar'
+  end
+
+  def test_self_open
+    open @file, 'wb' do |tar_io|
+      Gem::Package::TarOutput.open tar_io do |tar_writer|
+        tar_writer.add_file_simple 'README', 0, 17 do |io|
+          io.write "This is a README\n"
+        end
+
+        tar_writer.metadata = "This is some metadata\n"
+      end
+    end
+
+    files = util_extract
+
+    name, data = files.shift
+    assert_equal 'data.tar.gz', name
+
+    gz = Zlib::GzipReader.new StringIO.new(data)
+
+    Gem::Package::TarReader.new gz do |tar_reader|
+      tar_reader.each do |entry|
+        assert_equal 'README', entry.full_name
+        assert_equal "This is a README\n", entry.read
+      end
+    end
+
+    gz.close
+
+    name, data = files.shift
+    assert_equal 'metadata.gz', name
+
+    gz = Zlib::GzipReader.new StringIO.new(data)
+    assert_equal "This is some metadata\n", gz.read
+
+    assert_empty files
+  ensure
+    gz.close if gz
+  end
+
+  if defined? OpenSSL then
+    def test_self_open_signed
+      signer = Gem::Security::Signer.new @private_key, [@public_cert]
+
+      open @file, 'wb' do |tar_io|
+        Gem::Package::TarOutput.open tar_io, signer do |tar_writer|
+          tar_writer.add_file_simple 'README', 0, 17 do |io|
+            io.write "This is a README\n"
+          end
+
+          tar_writer.metadata = "This is some metadata\n"
+        end
+      end
+
+      files = util_extract
+
+      name, data = files.shift
+      assert_equal 'data.tar.gz', name
+
+      name, data = files.shift
+      assert_equal 'metadata.gz', name
+
+      name, data = files.shift
+      assert_equal 'data.tar.gz.sig', name
+
+      name, data = files.shift
+      assert_equal 'metadata.gz.sig', name
+
+      assert_empty files
+    end
+  end
+
+  def util_extract
+    files = []
+
+    open @file, 'rb' do |io|
+      Gem::Package::TarReader.new io do |tar_reader|
+        tar_reader.each do |entry|
+          files << [entry.full_name, entry.read]
+        end
+      end
+    end
+
+    files
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,53 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_package_tar_test_case')
+require 'rubygems/package'
+
+class TestGemPackageTarReader < TarTestCase
+
+  def test_each_entry
+    tar = tar_dir_header "foo", "bar", 0
+    tar << tar_file_header("bar", "baz", 0, 0)
+
+    io = TempIO.new tar
+
+    entries = 0
+
+    Gem::Package::TarReader.new io do |tar_reader|
+      tar_reader.each_entry do |entry|
+        assert_kind_of Gem::Package::TarReader::Entry, entry
+
+        entries += 1
+      end
+    end
+
+    assert_equal 2, entries
+  end
+
+  def test_rewind
+    content = ('a'..'z').to_a.join(" ")
+
+    str = tar_file_header("lib/foo", "", 010644, content.size) + content +
+            "\0" * (512 - content.size)
+    str << "\0" * 1024
+
+    Gem::Package::TarReader.new(TempIO.new(str)) do |tar_reader|
+      3.times do
+        tar_reader.rewind
+        i = 0
+        tar_reader.each_entry do |entry|
+          assert_equal(content, entry.read)
+          i += 1
+        end
+        assert_equal(1, i)
+      end
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader_entry.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader_entry.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_reader_entry.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,116 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_package_tar_test_case')
+require 'rubygems/package'
+
+class TestGemPackageTarReaderEntry < TarTestCase
+
+  def setup
+    super
+
+    @contents = ('a'..'z').to_a.join * 100
+
+    @tar = ''
+    @tar << tar_file_header("lib/foo", "", 0, @contents.size)
+    @tar << @contents
+    @tar << "\0" * (512 - (@tar.size % 512))
+
+    @entry = util_entry @tar
+  end
+
+  def test_bytes_read
+    assert_equal 0, @entry.bytes_read
+
+    @entry.getc
+
+    assert_equal 1, @entry.bytes_read
+  end
+
+  def test_close
+    @entry.close
+
+    assert @entry.bytes_read
+
+    e = assert_raises IOError do @entry.eof? end
+    assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+    e = assert_raises IOError do @entry.getc end
+    assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+    e = assert_raises IOError do @entry.pos end
+    assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+    e = assert_raises IOError do @entry.read end
+    assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+    e = assert_raises IOError do @entry.rewind end
+    assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+  end
+
+  def test_closed_eh
+    @entry.close
+
+    assert @entry.closed?
+  end
+
+  def test_eof_eh
+    @entry.read
+
+    assert @entry.eof?
+  end
+
+  def test_full_name
+    assert_equal 'lib/foo', @entry.full_name
+  end
+
+  def test_getc
+    assert_equal ?a, @entry.getc
+  end
+
+  def test_directory_eh
+    assert_equal false, @entry.directory?
+    assert_equal true, util_dir_entry.directory?
+  end
+
+  def test_file_eh
+    assert_equal true, @entry.file?
+    assert_equal false, util_dir_entry.file?
+  end
+
+  def test_pos
+    assert_equal 0, @entry.pos
+
+    @entry.getc
+
+    assert_equal 1, @entry.pos
+  end
+
+  def test_read
+    assert_equal @contents, @entry.read
+  end
+
+  def test_read_big
+    assert_equal @contents, @entry.read(@contents.size * 2)
+  end
+
+  def test_read_small
+    assert_equal @contents[0...100], @entry.read(100)
+  end
+
+  def test_rewind
+    char = @entry.getc
+
+    @entry.rewind
+
+    assert_equal 0, @entry.pos
+
+    assert_equal char, @entry.getc
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_writer.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_writer.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_tar_writer.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,151 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_package_tar_test_case')
+require 'rubygems/package/tar_writer'
+
+class TestTarWriter < TarTestCase
+
+  def setup
+    super
+
+    @data = 'abcde12345'
+    @io = TempIO.new
+    @tar_writer = Gem::Package::TarWriter.new @io
+  end
+
+  def teardown
+    @tar_writer.close unless @tar_writer.closed?
+
+    super
+  end
+
+  def test_add_file
+    @tar_writer.add_file 'x', 0644 do |f| f.write 'a' * 10 end
+
+    assert_headers_equal(tar_file_header('x', '', 0644, 10),
+                         @io.string[0, 512])
+    assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
+    assert_equal 1024, @io.pos
+  end
+
+  def test_add_file_simple
+    @tar_writer.add_file_simple 'x', 0644, 10 do |io| io.write "a" * 10 end
+
+    assert_headers_equal(tar_file_header('x', '', 0644, 10),
+                         @io.string[0, 512])
+
+    assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
+    assert_equal 1024, @io.pos
+  end
+
+  def test_add_file_simple_padding
+    @tar_writer.add_file_simple 'x', 0, 100
+
+    assert_headers_equal tar_file_header('x', '', 0, 100), 
+                         @io.string[0, 512]
+
+    assert_equal "\0" * 512, @io.string[512, 512]
+  end
+
+  def test_add_file_simple_data
+    @tar_writer.add_file_simple("lib/foo/bar", 0, 10) { |f| f.write @data }
+    @tar_writer.flush
+
+    assert_equal @data + ("\0" * (512- at data.size)),
+                 @io.string[512, 512]
+  end
+
+  def test_add_file_simple_size
+    assert_raises Gem::Package::TarWriter::FileOverflow do 
+      @tar_writer.add_file_simple("lib/foo/bar", 0, 10) do |io|
+        io.write "1" * 11
+      end
+    end
+  end
+
+  def test_add_file_unseekable
+    assert_raises Gem::Package::NonSeekableIO do 
+      Gem::Package::TarWriter.new(Object.new).add_file 'x', 0
+    end
+  end
+
+  def test_close
+    @tar_writer.close
+
+    assert_equal "\0" * 1024, @io.string
+
+    e = assert_raises IOError do
+      @tar_writer.close
+    end
+    assert_equal 'closed Gem::Package::TarWriter', e.message
+
+    e = assert_raises IOError do
+      @tar_writer.flush
+    end
+    assert_equal 'closed Gem::Package::TarWriter', e.message
+
+    e = assert_raises IOError do
+      @tar_writer.add_file 'x', 0
+    end
+    assert_equal 'closed Gem::Package::TarWriter', e.message
+
+    e = assert_raises IOError do
+      @tar_writer.add_file_simple 'x', 0, 0
+    end
+    assert_equal 'closed Gem::Package::TarWriter', e.message
+
+    e = assert_raises IOError do
+      @tar_writer.mkdir 'x', 0
+    end
+    assert_equal 'closed Gem::Package::TarWriter', e.message
+  end
+
+  def test_mkdir
+    @tar_writer.mkdir 'foo', 0644
+
+    assert_headers_equal tar_dir_header('foo', '', 0644),
+                         @io.string[0, 512]
+    assert_equal 512, @io.pos
+  end
+
+  def test_split_name
+    assert_equal ['b' * 100, 'a' * 155],
+                 @tar_writer.split_name("#{'a' * 155}/#{'b' * 100}")
+
+    assert_equal ["#{'qwer/' * 19}bla", 'a' * 151],
+                 @tar_writer.split_name("#{'a' * 151}/#{'qwer/' * 19}bla")
+  end
+
+  def test_split_name_too_long_name
+    name = File.join 'a', 'b' * 100
+    assert_equal ['b' * 100, 'a'], @tar_writer.split_name(name)
+
+    assert_raises Gem::Package::TooLongFileName do
+      name = File.join 'a', 'b' * 101
+      @tar_writer.split_name name
+    end
+  end
+
+  def test_split_name_too_long_prefix
+    name = File.join 'a' * 155, 'b'
+    assert_equal ['b', 'a' * 155], @tar_writer.split_name(name)
+
+    assert_raises Gem::Package::TooLongFileName do
+      name = File.join 'a' * 156, 'b'
+      @tar_writer.split_name name
+    end
+  end
+
+  def test_split_name_too_long_total
+    assert_raises Gem::Package::TooLongFileName do
+      @tar_writer.split_name 'a' * 257
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_package_task.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_package_task.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_package_task.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,67 @@
+# Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems'
+require 'rubygems/package_task'
+
+class TestGemPackageTask < MiniTest::Unit::TestCase
+
+  def test_gem_package
+    gem = Gem::Specification.new do |g|
+      g.name = "pkgr"
+      g.version = "1.2.3"
+      g.files = Rake::FileList["x"].resolve
+    end
+    pkg = Gem::PackageTask.new(gem)  do |p|
+      p.package_files << "y"
+    end
+    assert_equal ["x", "y"], pkg.package_files
+  end
+
+  def test_gem_package_with_current_platform
+    gem = Gem::Specification.new do |g|
+      g.name = "pkgr"
+      g.version = "1.2.3"
+      g.files = Rake::FileList["x"].resolve
+      g.platform = Gem::Platform::CURRENT
+    end
+    pkg = Gem::PackageTask.new(gem)  do |p|
+      p.package_files << "y"
+    end
+    assert_equal ["x", "y"], pkg.package_files
+  end
+
+  def test_gem_package_with_ruby_platform
+    gem = Gem::Specification.new do |g|
+      g.name = "pkgr"
+      g.version = "1.2.3"
+      g.files = Rake::FileList["x"].resolve
+      g.platform = Gem::Platform::RUBY
+    end
+    pkg = Gem::PackageTask.new(gem)  do |p|
+      p.package_files << "y"
+    end
+    assert_equal ["x", "y"], pkg.package_files
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_platform.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_platform.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_platform.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,245 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/platform'
+require 'rbconfig'
+
+class TestGemPlatform < RubyGemTestCase
+
+  def test_self_local
+    util_set_arch 'i686-darwin8.10.1'
+
+    assert_equal Gem::Platform.new(%w[x86 darwin 8]), Gem::Platform.local
+  end
+
+  def test_self_match
+    assert Gem::Platform.match(nil), 'nil == ruby'
+    assert Gem::Platform.match(Gem::Platform.local), 'exact match'
+    assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match'
+    assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby'
+  end
+
+  def test_self_new
+    assert_equal Gem::Platform.local, Gem::Platform.new(Gem::Platform::CURRENT)
+    assert_equal Gem::Platform::RUBY, Gem::Platform.new(Gem::Platform::RUBY)
+    assert_equal Gem::Platform::RUBY, Gem::Platform.new(nil)
+    assert_equal Gem::Platform::RUBY, Gem::Platform.new('')
+  end
+
+  def test_initialize
+    test_cases = {
+      'amd64-freebsd6'         => ['amd64',     'freebsd',   '6'],
+      'hppa2.0w-hpux11.31'     => ['hppa2.0w',  'hpux',      '11'],
+      'java'                   => [nil,         'java',      nil],
+      'jruby'                  => [nil,         'java',      nil],
+      'powerpc-aix5.3.0.0'     => ['powerpc',   'aix',       '5'],
+      'powerpc-darwin7'        => ['powerpc',   'darwin',    '7'],
+      'powerpc-darwin8'        => ['powerpc',   'darwin',    '8'],
+      'powerpc-linux'          => ['powerpc',   'linux',     nil],
+      'powerpc64-linux'        => ['powerpc64', 'linux',     nil],
+      'sparc-solaris2.10'      => ['sparc',     'solaris',   '2.10'],
+      'sparc-solaris2.8'       => ['sparc',     'solaris',   '2.8'],
+      'sparc-solaris2.9'       => ['sparc',     'solaris',   '2.9'],
+      'universal-darwin8'      => ['universal', 'darwin',    '8'],
+      'universal-darwin9'      => ['universal', 'darwin',    '9'],
+      'i386-cygwin'            => ['x86',       'cygwin',    nil],
+      'i686-darwin'            => ['x86',       'darwin',    nil],
+      'i686-darwin8.4.1'       => ['x86',       'darwin',    '8'],
+      'i386-freebsd4.11'       => ['x86',       'freebsd',   '4'],
+      'i386-freebsd5'          => ['x86',       'freebsd',   '5'],
+      'i386-freebsd6'          => ['x86',       'freebsd',   '6'],
+      'i386-freebsd7'          => ['x86',       'freebsd',   '7'],
+      'i386-java1.5'           => ['x86',       'java',      '1.5'],
+      'x86-java1.6'            => ['x86',       'java',      '1.6'],
+      'i386-java1.6'           => ['x86',       'java',      '1.6'],
+      'i686-linux'             => ['x86',       'linux',     nil],
+      'i586-linux'             => ['x86',       'linux',     nil],
+      'i486-linux'             => ['x86',       'linux',     nil],
+      'i386-linux'             => ['x86',       'linux',     nil],
+      'i586-linux-gnu'         => ['x86',       'linux',     nil],
+      'i386-linux-gnu'         => ['x86',       'linux',     nil],
+      'i386-mingw32'           => ['x86',       'mingw32',   nil],
+      'i386-mswin32'           => ['x86',       'mswin32',   nil],
+      'i386-mswin32_80'        => ['x86',       'mswin32',   '80'],
+      'i386-mswin32-80'        => ['x86',       'mswin32',   '80'],
+      'x86-mswin32'            => ['x86',       'mswin32',   nil],
+      'x86-mswin32_60'         => ['x86',       'mswin32',   '60'],
+      'x86-mswin32-60'         => ['x86',       'mswin32',   '60'],
+      'i386-netbsdelf'         => ['x86',       'netbsdelf', nil],
+      'i386-openbsd4.0'        => ['x86',       'openbsd',   '4.0'],
+      'i386-solaris2.10'       => ['x86',       'solaris',   '2.10'],
+      'i386-solaris2.8'        => ['x86',       'solaris',   '2.8'],
+      'mswin32'                => ['x86',       'mswin32',   nil],
+      'x86_64-linux'           => ['x86_64',    'linux',     nil],
+      'x86_64-openbsd3.9'      => ['x86_64',    'openbsd',   '3.9'],
+      'x86_64-openbsd4.0'      => ['x86_64',    'openbsd',   '4.0'],
+    }
+
+    test_cases.each do |arch, expected|
+      platform = Gem::Platform.new arch
+      assert_equal expected, platform.to_a, arch.inspect
+    end
+  end
+
+  def test_initialize_command_line
+    expected = ['x86', 'mswin32', nil]
+
+    platform = Gem::Platform.new 'i386-mswin32'
+
+    assert_equal expected, platform.to_a, 'i386-mswin32'
+
+    expected = ['x86', 'mswin32', '80']
+
+    platform = Gem::Platform.new 'i386-mswin32-80'
+
+    assert_equal expected, platform.to_a, 'i386-mswin32-80'
+
+    expected = ['x86', 'solaris', '2.10']
+
+    platform = Gem::Platform.new 'i386-solaris-2.10'
+
+    assert_equal expected, platform.to_a, 'i386-solaris-2.10'
+  end
+
+  def test_initialize_mswin32_vc6
+    orig_RUBY_SO_NAME = RbConfig::CONFIG['RUBY_SO_NAME']
+    RbConfig::CONFIG['RUBY_SO_NAME'] = 'msvcrt-ruby18'
+
+    expected = ['x86', 'mswin32', nil]
+
+    platform = Gem::Platform.new 'i386-mswin32'
+
+    assert_equal expected, platform.to_a, 'i386-mswin32 VC6'
+  ensure
+    RbConfig::CONFIG['RUBY_SO_NAME'] = orig_RUBY_SO_NAME
+  end
+
+  def test_initialize_platform
+    platform = Gem::Platform.new 'cpu-my_platform1'
+    expected = Gem::Platform.new platform
+
+    assert_equal 'cpu', platform.cpu
+    assert_equal 'my_platform', platform.os
+    assert_equal '1', platform.version
+  end
+
+  def test_initialize_test
+    platform = Gem::Platform.new 'cpu-my_platform1'
+    assert_equal 'cpu', platform.cpu
+    assert_equal 'my_platform', platform.os
+    assert_equal '1', platform.version
+
+    platform = Gem::Platform.new 'cpu-other_platform1'
+    assert_equal 'cpu', platform.cpu
+    assert_equal 'other_platform', platform.os
+    assert_equal '1', platform.version
+  end
+
+  def test_empty
+    platform = Gem::Platform.new 'cpu-other_platform1'
+    assert_respond_to platform, :empty?
+    assert_equal false, platform.empty?
+  end
+
+  def test_to_s
+    if win_platform? then
+      assert_equal 'x86-mswin32-60', Gem::Platform.local.to_s
+    else
+      assert_equal 'x86-darwin-8', Gem::Platform.local.to_s
+    end
+  end
+
+  def test_equals2
+    my = Gem::Platform.new %w[cpu my_platform 1]
+    other = Gem::Platform.new %w[cpu other_platform 1]
+
+    assert_equal my, my
+    refute_equal my, other
+    refute_equal other, my
+  end
+
+  def test_equals3
+    my = Gem::Platform.new %w[cpu my_platform 1]
+    other = Gem::Platform.new %w[cpu other_platform 1]
+
+    assert(my === my)
+    refute(other === my)
+    refute(my === other)
+  end
+
+  def test_equals3_cpu
+    ppc_darwin8 = Gem::Platform.new 'powerpc-darwin8.0'
+    uni_darwin8 = Gem::Platform.new 'universal-darwin8.0'
+    x86_darwin8 = Gem::Platform.new 'i686-darwin8.0'
+
+    util_set_arch 'powerpc-darwin8'
+    assert((ppc_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+    assert((uni_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+    refute((x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+
+    util_set_arch 'i686-darwin8'
+    refute((ppc_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+    assert((uni_darwin8 === Gem::Platform.local), 'x86 =~ universal')
+    assert((x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+
+    util_set_arch 'universal-darwin8'
+    assert((ppc_darwin8 === Gem::Platform.local), 'universal =~ ppc')
+    assert((uni_darwin8 === Gem::Platform.local), 'universal =~ universal')
+    assert((x86_darwin8 === Gem::Platform.local), 'universal =~ x86')
+  end
+
+  def test_equals3_version
+    util_set_arch 'i686-darwin8'
+
+    x86_darwin = Gem::Platform.new ['x86', 'darwin', nil]
+    x86_darwin7 = Gem::Platform.new ['x86', 'darwin', '7']
+    x86_darwin8 = Gem::Platform.new ['x86', 'darwin', '8']
+    x86_darwin9 = Gem::Platform.new ['x86', 'darwin', '9']
+
+    assert((x86_darwin  === Gem::Platform.local), 'x86_darwin === x86_darwin8')
+    assert((x86_darwin8 === Gem::Platform.local), 'x86_darwin8 === x86_darwin8')
+
+    refute((x86_darwin7 === Gem::Platform.local), 'x86_darwin7 === x86_darwin8')
+    refute((x86_darwin9 === Gem::Platform.local), 'x86_darwin9 === x86_darwin8')
+  end
+
+  def test_equals_tilde
+    util_set_arch 'i386-mswin32'
+
+    assert_match 'mswin32',      Gem::Platform.local
+    assert_match 'i386-mswin32', Gem::Platform.local
+
+    # oddballs
+    assert_match 'i386-mswin32-mq5.3', Gem::Platform.local
+    assert_match 'i386-mswin32-mq6',   Gem::Platform.local
+    refute_match 'win32-1.8.2-VC7',    Gem::Platform.local
+    refute_match 'win32-1.8.4-VC6',    Gem::Platform.local
+    refute_match 'win32-source',       Gem::Platform.local
+    refute_match 'windows',            Gem::Platform.local
+
+    util_set_arch 'i686-linux'
+    assert_match 'i486-linux', Gem::Platform.local
+    assert_match 'i586-linux', Gem::Platform.local
+    assert_match 'i686-linux', Gem::Platform.local
+
+    util_set_arch 'i686-darwin8'
+    assert_match 'i686-darwin8.4.1', Gem::Platform.local
+    assert_match 'i686-darwin8.8.2', Gem::Platform.local
+
+    util_set_arch 'java'
+    assert_match 'java',  Gem::Platform.local
+    assert_match 'jruby', Gem::Platform.local
+
+    util_set_arch 'powerpc-darwin'
+    assert_match 'powerpc-darwin', Gem::Platform.local
+
+    util_set_arch 'powerpc-darwin7'
+    assert_match 'powerpc-darwin7.9.0', Gem::Platform.local
+
+    util_set_arch 'powerpc-darwin8'
+    assert_match 'powerpc-darwin8.10.0', Gem::Platform.local
+
+    util_set_arch 'sparc-solaris2.8'
+    assert_match 'sparc-solaris2.8-mq5.3', Gem::Platform.local
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_remote_fetcher.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_remote_fetcher.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_remote_fetcher.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,729 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'webrick'
+require 'zlib'
+require 'rubygems/remote_fetcher'
+require 'ostruct'
+
+# = Testing Proxy Settings
+#
+# These tests check the proper proxy server settings by running two
+# web servers.  The web server at http://localhost:#{SERVER_PORT}
+# represents the normal gem server and returns a gemspec with a rake
+# version of 0.4.11.  The web server at http://localhost:#{PROXY_PORT}
+# represents the proxy server and returns a different dataset where
+# rake has version 0.4.2.  This allows us to detect which server is
+# returning the data.
+#
+# Note that the proxy server is not a *real* proxy server.  But our
+# software doesn't really care, as long as we hit the proxy URL when a
+# proxy is configured.
+
+class TestGemRemoteFetcher < RubyGemTestCase
+
+  include Gem::DefaultUserInteraction
+
+  SERVER_DATA = <<-EOY
+--- !ruby/object:Gem::Cache
+gems:
+  rake-0.4.11: !ruby/object:Gem::Specification
+    rubygems_version: "0.7"
+    specification_version: 1
+    name: rake
+    version: !ruby/object:Gem::Version
+      version: 0.4.11
+    date: 2004-11-12
+    summary: Ruby based make-like utility.
+    require_paths:
+      - lib
+    author: Jim Weirich
+    email: jim at weirichhouse.org
+    homepage: http://rake.rubyforge.org
+    rubyforge_project: rake
+    description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
+    autorequire:
+    default_executable: rake
+    bindir: bin
+    has_rdoc: true
+    required_ruby_version: !ruby/object:Gem::Version::Requirement
+      requirements:
+        -
+          - ">"
+          - !ruby/object:Gem::Version
+            version: 0.0.0
+      version:
+    platform: ruby
+    files:
+      - README
+    test_files: []
+    library_stubs:
+    rdoc_options:
+    extra_rdoc_files:
+    executables:
+      - rake
+    extensions: []
+    requirements: []
+    dependencies: []
+  EOY
+
+  PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2')
+
+  # don't let 1.8 and 1.9 autotest collide
+  RUBY_VERSION =~ /(\d+)\.(\d+)\.(\d+)/
+  # don't let parallel runners collide
+  PROXY_PORT = process_based_port + 100 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
+  SERVER_PORT = process_based_port + 200 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
+
+  def setup
+    super
+    self.class.start_servers
+    self.class.enable_yaml = true
+    self.class.enable_zip = false
+    ENV.delete 'http_proxy'
+    ENV.delete 'HTTP_PROXY'
+    ENV.delete 'http_proxy_user'
+    ENV.delete 'HTTP_PROXY_USER'
+    ENV.delete 'http_proxy_pass'
+    ENV.delete 'HTTP_PROXY_PASS'
+
+    base_server_uri = "http://localhost:#{SERVER_PORT}"
+    @proxy_uri = "http://localhost:#{PROXY_PORT}"
+
+    @server_uri = base_server_uri + "/yaml"
+    @server_z_uri = base_server_uri + "/yaml.Z"
+
+    # REFACTOR: copied from test_gem_dependency_installer.rb
+    @gems_dir = File.join @tempdir, 'gems'
+    @cache_dir = File.join @gemhome, 'cache'
+    FileUtils.mkdir @gems_dir
+
+    @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
+
+    Gem::RemoteFetcher.fetcher = nil
+
+    @fetcher = Gem::RemoteFetcher.fetcher
+  end
+
+  def teardown
+    super
+    Gem.configuration[:http_proxy] = nil
+  end
+
+  def test_self_fetcher
+    fetcher = Gem::RemoteFetcher.fetcher
+    refute_nil fetcher
+    assert_kind_of Gem::RemoteFetcher, fetcher
+  end
+
+  def test_self_fetcher_with_proxy
+    proxy_uri = 'http://proxy.example.com'
+    Gem.configuration[:http_proxy] = proxy_uri
+    Gem::RemoteFetcher.fetcher = nil
+
+    fetcher = Gem::RemoteFetcher.fetcher
+
+    refute_nil fetcher
+    assert_kind_of Gem::RemoteFetcher, fetcher
+    assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri).to_s
+  end
+
+  def test_self_fetcher_with_proxy_URI
+    proxy_uri = URI.parse 'http://proxy.example.com'
+    Gem.configuration[:http_proxy] = proxy_uri
+    Gem::RemoteFetcher.fetcher = nil
+
+    fetcher = Gem::RemoteFetcher.fetcher
+    refute_nil fetcher
+
+    assert_kind_of Gem::RemoteFetcher, fetcher
+    assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri)
+  end
+
+  def test_fetch_size_bad_uri
+    fetcher = Gem::RemoteFetcher.new nil
+
+    e = assert_raises ArgumentError do
+      fetcher.fetch_size 'gems.example.com/yaml'
+    end
+
+    assert_equal 'uri scheme is invalid', e.message
+  end
+
+  def test_fetch_size_socket_error
+    fetcher = Gem::RemoteFetcher.new nil
+    def fetcher.connection_for(uri)
+      raise SocketError, "tarded"
+    end
+
+    uri = 'http://gems.example.com/yaml'
+    e = assert_raises Gem::RemoteFetcher::FetchError do
+      fetcher.fetch_size uri
+    end
+
+    assert_equal "SocketError: tarded (#{uri})", e.message
+  end
+
+  def test_no_proxy
+    use_ui @ui do
+      assert_data_from_server @fetcher.fetch_path(@server_uri)
+      assert_equal SERVER_DATA.size, @fetcher.fetch_size(@server_uri)
+    end
+  end
+
+  def util_fuck_with_fetcher data, blow = false
+    fetcher = Gem::RemoteFetcher.fetcher
+    fetcher.instance_variable_set :@test_data, data
+
+    unless blow then
+      def fetcher.fetch_path arg
+        @test_arg = arg
+        @test_data
+      end
+    else
+      def fetcher.fetch_path arg
+        # OMG I'm such an ass
+        class << self; remove_method :fetch_path; end
+        def self.fetch_path arg
+          @test_arg = arg
+          @test_data
+        end
+
+        raise Gem::RemoteFetcher::FetchError.new("haha!", nil)
+      end
+    end
+
+    fetcher
+  end
+
+  def test_download
+    a1_data = nil
+    File.open @a1_gem, 'rb' do |fp|
+      a1_data = fp.read
+    end
+
+    fetcher = util_fuck_with_fetcher a1_data
+
+    a1_cache_gem = File.join(@gemhome, 'cache', @a1.file_name)
+    assert_equal a1_cache_gem, fetcher.download(@a1, 'http://gems.example.com')
+    assert_equal("http://gems.example.com/gems/a-1.gem",
+                 fetcher.instance_variable_get(:@test_arg).to_s)
+    assert File.exist?(a1_cache_gem)
+  end
+
+  def test_download_cached
+    FileUtils.mv @a1_gem, @cache_dir
+
+    inst = Gem::RemoteFetcher.fetcher
+
+    assert_equal File.join(@gemhome, 'cache', @a1.file_name),
+                 inst.download(@a1, 'http://gems.example.com')
+  end
+
+  def test_download_local
+    FileUtils.mv @a1_gem, @tempdir
+    local_path = File.join @tempdir, @a1.file_name
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::RemoteFetcher.fetcher
+    end
+
+    assert_equal File.join(@gemhome, 'cache', @a1.file_name),
+                 inst.download(@a1, local_path)
+  end
+
+  def test_download_local_space
+    space_path = File.join @tempdir, 'space path'
+    FileUtils.mkdir space_path
+    FileUtils.mv @a1_gem, space_path
+    local_path = File.join space_path, @a1.file_name
+    inst = nil
+
+    Dir.chdir @tempdir do
+      inst = Gem::RemoteFetcher.fetcher
+    end
+
+    assert_equal File.join(@gemhome, 'cache', @a1.file_name),
+                 inst.download(@a1, local_path)
+  end
+
+  def test_download_install_dir
+    a1_data = nil
+    File.open @a1_gem, 'rb' do |fp|
+      a1_data = fp.read
+    end
+
+    fetcher = util_fuck_with_fetcher a1_data
+
+    install_dir = File.join @tempdir, 'more_gems'
+
+    a1_cache_gem = File.join install_dir, 'cache', @a1.file_name
+    FileUtils.mkdir_p(File.dirname(a1_cache_gem))
+    actual = fetcher.download(@a1, 'http://gems.example.com', install_dir)
+
+    assert_equal a1_cache_gem, actual
+    assert_equal("http://gems.example.com/gems/a-1.gem",
+                 fetcher.instance_variable_get(:@test_arg).to_s)
+
+    assert File.exist?(a1_cache_gem)
+  end
+
+  unless win_platform? # File.chmod doesn't work
+    def test_download_local_read_only
+      FileUtils.mv @a1_gem, @tempdir
+      local_path = File.join @tempdir, @a1.file_name
+      inst = nil
+      File.chmod 0555, File.join(@gemhome, 'cache')
+
+      Dir.chdir @tempdir do
+        inst = Gem::RemoteFetcher.fetcher
+      end
+
+      assert_equal File.join(@tempdir, @a1.file_name),
+        inst.download(@a1, local_path)
+    ensure
+      File.chmod 0755, File.join(@gemhome, 'cache')
+    end
+
+    def test_download_read_only
+      File.chmod 0555, File.join(@gemhome, 'cache')
+      File.chmod 0555, File.join(@gemhome)
+
+      fetcher = util_fuck_with_fetcher File.read(@a1_gem)
+      fetcher.download(@a1, 'http://gems.example.com')
+      assert File.exist?(File.join(Gem.user_dir, 'cache', @a1.file_name))
+    ensure
+      File.chmod 0755, File.join(@gemhome)
+      File.chmod 0755, File.join(@gemhome, 'cache')
+    end
+  end
+
+  def test_download_platform_legacy
+    original_platform = 'old-platform'
+
+    e1, e1_gem = util_gem 'e', '1' do |s|
+      s.platform = Gem::Platform::CURRENT
+      s.instance_variable_set :@original_platform, original_platform
+    end
+
+    e1_data = nil
+    File.open e1_gem, 'rb' do |fp|
+      e1_data = fp.read
+    end
+
+    fetcher = util_fuck_with_fetcher e1_data, :blow_chunks
+
+    e1_cache_gem = File.join(@gemhome, 'cache', e1.file_name)
+
+    assert_equal e1_cache_gem, fetcher.download(e1, 'http://gems.example.com')
+
+    assert_equal("http://gems.example.com/gems/#{e1.original_name}.gem",
+                 fetcher.instance_variable_get(:@test_arg).to_s)
+    assert File.exist?(e1_cache_gem)
+  end
+
+  def test_download_unsupported
+    inst = Gem::RemoteFetcher.fetcher
+
+    e = assert_raises Gem::InstallError do
+      inst.download @a1, 'ftp://gems.rubyforge.org'
+    end
+
+    assert_equal 'unsupported URI scheme ftp', e.message
+  end
+
+  def test_explicit_proxy
+    use_ui @ui do
+      fetcher = Gem::RemoteFetcher.new @proxy_uri
+      assert_equal PROXY_DATA.size, fetcher.fetch_size(@server_uri)
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_explicit_proxy_with_user_auth
+    use_ui @ui do
+      uri = URI.parse @proxy_uri
+      uri.user, uri.password = 'foo', 'bar'
+      fetcher = Gem::RemoteFetcher.new uri.to_s
+      proxy = fetcher.instance_variable_get("@proxy_uri")
+      assert_equal 'foo', proxy.user
+      assert_equal 'bar', proxy.password
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+
+    use_ui @ui do
+      uri = URI.parse @proxy_uri
+      uri.user, uri.password = 'domain%5Cuser', 'bar'
+      fetcher = Gem::RemoteFetcher.new uri.to_s
+      proxy = fetcher.instance_variable_get("@proxy_uri")
+      assert_equal 'domain\user', URI.unescape(proxy.user)
+      assert_equal 'bar', proxy.password
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+
+    use_ui @ui do
+      uri = URI.parse @proxy_uri
+      uri.user, uri.password = 'user', 'my%20pass'
+      fetcher = Gem::RemoteFetcher.new uri.to_s
+      proxy = fetcher.instance_variable_get("@proxy_uri")
+      assert_equal 'user', proxy.user
+      assert_equal 'my pass', URI.unescape(proxy.password)
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_explicit_proxy_with_user_auth_in_env
+    use_ui @ui do
+      ENV['http_proxy'] = @proxy_uri
+      ENV['http_proxy_user'] = 'foo'
+      ENV['http_proxy_pass'] = 'bar'
+      fetcher = Gem::RemoteFetcher.new nil
+      proxy = fetcher.instance_variable_get("@proxy_uri")
+      assert_equal 'foo', proxy.user
+      assert_equal 'bar', proxy.password
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+
+    use_ui @ui do
+      ENV['http_proxy'] = @proxy_uri
+      ENV['http_proxy_user'] = 'foo\user'
+      ENV['http_proxy_pass'] = 'my bar'
+      fetcher = Gem::RemoteFetcher.new nil
+      proxy = fetcher.instance_variable_get("@proxy_uri")
+      assert_equal 'foo\user', URI.unescape(proxy.user)
+      assert_equal 'my bar', URI.unescape(proxy.password)
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_fetch_path_gzip
+    fetcher = Gem::RemoteFetcher.new nil
+
+    def fetcher.open_uri_or_path(uri, mtime, head = nil)
+      Gem.gzip 'foo'
+    end
+
+    assert_equal 'foo', fetcher.fetch_path(@uri + 'foo.gz')
+  end
+
+  def test_fetch_path_gzip_unmodified
+    fetcher = Gem::RemoteFetcher.new nil
+
+    def fetcher.open_uri_or_path(uri, mtime, head = nil)
+      nil
+    end
+
+    assert_equal nil, fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
+  end
+
+  def test_fetch_path_io_error
+    fetcher = Gem::RemoteFetcher.new nil
+
+    def fetcher.open_uri_or_path(uri, mtime, head = nil)
+      raise EOFError
+    end
+
+    e = assert_raises Gem::RemoteFetcher::FetchError do
+      fetcher.fetch_path 'uri'
+    end
+
+    assert_equal 'EOFError: EOFError (uri)', e.message
+    assert_equal 'uri', e.uri
+  end
+
+  def test_fetch_path_socket_error
+    fetcher = Gem::RemoteFetcher.new nil
+
+    def fetcher.open_uri_or_path(uri, mtime, head = nil)
+      raise SocketError
+    end
+
+    e = assert_raises Gem::RemoteFetcher::FetchError do
+      fetcher.fetch_path 'uri'
+    end
+
+    assert_equal 'SocketError: SocketError (uri)', e.message
+    assert_equal 'uri', e.uri
+  end
+
+  def test_fetch_path_system_call_error
+    fetcher = Gem::RemoteFetcher.new nil
+
+    def fetcher.open_uri_or_path(uri, mtime = nil, head = nil)
+      raise Errno::ECONNREFUSED, 'connect(2)'
+    end
+
+    e = assert_raises Gem::RemoteFetcher::FetchError do
+      fetcher.fetch_path 'uri'
+    end
+
+    assert_match %r|ECONNREFUSED:.*connect\(2\) \(uri\)\z|,
+                 e.message
+    assert_equal 'uri', e.uri
+  end
+
+  def test_fetch_path_unmodified
+    fetcher = Gem::RemoteFetcher.new nil
+
+    def fetcher.open_uri_or_path(uri, mtime, head = nil)
+      nil
+    end
+
+    assert_equal nil, fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
+  end
+
+  def test_get_proxy_from_env_auto_normalizes
+    fetcher = Gem::RemoteFetcher.new(nil)
+    ENV['HTTP_PROXY'] = 'fakeurl:12345'
+
+    assert_equal('http://fakeurl:12345', fetcher.get_proxy_from_env.to_s)
+  end
+
+  def test_get_proxy_from_env_empty
+    orig_env_HTTP_PROXY = ENV['HTTP_PROXY']
+    orig_env_http_proxy = ENV['http_proxy']
+
+    ENV['HTTP_PROXY'] = ''
+    ENV.delete 'http_proxy'
+
+    fetcher = Gem::RemoteFetcher.new nil
+
+    assert_equal nil, fetcher.send(:get_proxy_from_env)
+
+  ensure
+    orig_env_HTTP_PROXY.nil? ? ENV.delete('HTTP_PROXY') :
+                               ENV['HTTP_PROXY'] = orig_env_HTTP_PROXY
+    orig_env_http_proxy.nil? ? ENV.delete('http_proxy') :
+                               ENV['http_proxy'] = orig_env_http_proxy
+  end
+
+  def test_implicit_no_proxy
+    use_ui @ui do
+      ENV['http_proxy'] = 'http://fakeurl:12345'
+      fetcher = Gem::RemoteFetcher.new :no_proxy
+      assert_data_from_server fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_implicit_proxy
+    use_ui @ui do
+      ENV['http_proxy'] = @proxy_uri
+      fetcher = Gem::RemoteFetcher.new nil
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_implicit_upper_case_proxy
+    use_ui @ui do
+      ENV['HTTP_PROXY'] = @proxy_uri
+      fetcher = Gem::RemoteFetcher.new nil
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_implicit_proxy_no_env
+    use_ui @ui do
+      fetcher = Gem::RemoteFetcher.new nil
+      assert_data_from_server fetcher.fetch_path(@server_uri)
+    end
+  end
+
+  def test_open_uri_or_path
+    fetcher = Gem::RemoteFetcher.new nil
+
+    conn = Object.new
+    def conn.started?() true end
+    def conn.request(req)
+      unless defined? @requested then
+        @requested = true
+        res = Net::HTTPMovedPermanently.new nil, 301, nil
+        res.add_field 'Location', 'http://gems.example.com/real_path'
+        res
+      else
+        res = Net::HTTPOK.new nil, 200, nil
+        def res.body() 'real_path' end
+        res
+      end
+    end
+
+    conn = { 'gems.example.com:80' => conn }
+    fetcher.instance_variable_set :@connections, conn
+
+    data = fetcher.open_uri_or_path 'http://gems.example.com/redirect'
+
+    assert_equal 'real_path', data
+  end
+
+  def test_open_uri_or_path_limited_redirects
+    fetcher = Gem::RemoteFetcher.new nil
+
+    conn = Object.new
+    def conn.started?() true end
+    def conn.request(req)
+      res = Net::HTTPMovedPermanently.new nil, 301, nil
+      res.add_field 'Location', 'http://gems.example.com/redirect'
+      res
+    end
+
+    conn = { 'gems.example.com:80' => conn }
+    fetcher.instance_variable_set :@connections, conn
+
+    e = assert_raises Gem::RemoteFetcher::FetchError do
+      fetcher.open_uri_or_path 'http://gems.example.com/redirect'
+    end
+
+    assert_equal 'too many redirects (http://gems.example.com/redirect)',
+                 e.message
+  end
+
+  def test_request
+    uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+    util_stub_connection_for :body => :junk, :code => 200
+
+    response = @fetcher.request uri, Net::HTTP::Get
+
+    assert_equal 200, response.code
+    assert_equal :junk, response.body
+  end
+
+  def test_request_head
+    uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+    util_stub_connection_for :body => '', :code => 200
+    response = @fetcher.request uri, Net::HTTP::Head
+
+    assert_equal 200, response.code
+    assert_equal '', response.body
+  end
+
+  def test_request_unmodifed
+    uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+    conn = util_stub_connection_for :body => '', :code => 304
+
+    t = Time.now
+    response = @fetcher.request uri, Net::HTTP::Head, t
+
+    assert_equal 304, response.code
+    assert_equal '', response.body
+
+    assert_equal t.rfc2822, conn.payload['if-modified-since']
+  end
+
+  def test_yaml_error_on_size
+    use_ui @ui do
+      self.class.enable_yaml = false
+      fetcher = Gem::RemoteFetcher.new nil
+      assert_error { fetcher.size }
+    end
+  end
+
+  def util_stub_connection_for hash
+    def @fetcher.connection= conn
+      @conn = conn
+    end
+
+    def @fetcher.connection_for uri
+      @conn
+    end
+
+    @fetcher.connection = Conn.new OpenStruct.new(hash)
+  end
+
+  def assert_error(exception_class=Exception)
+    got_exception = false
+    begin
+      yield
+    rescue exception_class => ex
+      got_exception = true
+    end
+    assert got_exception, "Expected exception conforming to #{exception_class}"
+  end
+
+  def assert_data_from_server(data)
+    assert_block("Data is not from server") { data =~ /0\.4\.11/ }
+  end
+
+  def assert_data_from_proxy(data)
+    assert_block("Data is not from proxy") { data =~ /0\.4\.2/ }
+  end
+
+  class Conn
+    attr_accessor :payload
+
+    def initialize(response)
+      @response = response
+      self.payload = nil
+    end
+
+    def request(req)
+      self.payload = req
+      @response
+    end
+  end
+
+  class NilLog < WEBrick::Log
+    def log(level, data) #Do nothing
+    end
+  end
+
+  class << self
+    attr_reader :normal_server, :proxy_server
+    attr_accessor :enable_zip, :enable_yaml
+
+    def start_servers
+      @normal_server ||= start_server(SERVER_PORT, SERVER_DATA)
+      @proxy_server  ||= start_server(PROXY_PORT, PROXY_DATA)
+      @enable_yaml = true
+      @enable_zip = false
+    end
+
+    private
+
+    def start_server(port, data)
+      Thread.new do
+        begin
+          null_logger = NilLog.new
+          s = WEBrick::HTTPServer.new(
+            :Port            => port,
+            :DocumentRoot    => nil,
+            :Logger          => null_logger,
+            :AccessLog       => null_logger
+            )
+          s.mount_proc("/kill") { |req, res| s.shutdown }
+          s.mount_proc("/yaml") { |req, res|
+            if @enable_yaml
+              res.body = data
+              res['Content-Type'] = 'text/plain'
+              res['content-length'] = data.size
+            else
+              res.status = "404"
+              res.body = "<h1>NOT FOUND</h1>"
+              res['Content-Type'] = 'text/html'
+            end
+          }
+          s.mount_proc("/yaml.Z") { |req, res|
+            if @enable_zip
+              res.body = Zlib::Deflate.deflate(data)
+              res['Content-Type'] = 'text/plain'
+            else
+              res.status = "404"
+              res.body = "<h1>NOT FOUND</h1>"
+              res['Content-Type'] = 'text/html'
+            end
+          }
+          s.start
+        rescue Exception => ex
+          abort ex.message
+          puts "ERROR during server thread: #{ex.message}"
+        end
+      end
+      sleep 0.2                 # Give the servers time to startup
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_requirement.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_requirement.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_requirement.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,222 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/version'
+
+class TestGemRequirement < RubyGemTestCase
+
+  def setup
+    super
+
+    @r1_2 = Gem::Requirement.new '= 1.2'
+    @r1_3 = Gem::Requirement.new '= 1.3'
+  end
+
+  def test_initialize
+    r = Gem::Requirement.new '2'
+    assert_equal '= 2', r.to_s, 'String'
+
+    r = Gem::Requirement.new %w[2]
+    assert_equal '= 2', r.to_s, 'Array of Strings'
+
+    r = Gem::Requirement.new Gem::Version.new('2')
+    assert_equal '= 2', r.to_s, 'Gem::Version'
+  end
+
+  def test_equals2
+    assert_equal @r1_2, @r1_2.dup
+    assert_equal @r1_2.dup, @r1_2
+
+    refute_equal @r1_3, @r1_2
+    refute_equal @r1_2, @r1_3
+
+    refute_equal Object.new, @r1_2
+    refute_equal @r1_2, Object.new
+  end
+
+  def test_hash
+    assert_equal @r1_2.hash, @r1_2.dup.hash
+    assert_equal @r1_2.dup.hash, @r1_2.hash
+
+    refute_equal @r1_2.hash, @r1_3.hash
+    refute_equal @r1_3.hash, @r1_2.hash
+  end
+
+  # We may get some old gems that have requirements in old formats.
+  # We need to be able to handle those old requirements by normalizing
+  # them to the latest format.
+  def test_normalization
+    require 'yaml'
+    yamldep = %{--- !ruby/object:Gem::Requirement
+      nums:
+        - 1
+        - 0
+        - 4
+      op: ">="
+      version: ">= 1.0.4"}
+    dep = YAML.load(yamldep)
+    dep.normalize
+    assert_equal ">= 1.0.4", dep.to_s
+  end
+
+  def test_parse
+    assert_equal ['=', Gem::Version.new(1)], @r1_2.parse('  1')
+
+    assert_equal ['=', Gem::Version.new(1)], @r1_2.parse('= 1')
+    assert_equal ['>', Gem::Version.new(1)], @r1_2.parse('> 1')
+
+    assert_equal ['=', Gem::Version.new(0)], @r1_2.parse('=')
+    assert_equal ['>', Gem::Version.new(0)], @r1_2.parse('>')
+
+    assert_equal ['=', Gem::Version.new(1)], @r1_2.parse("=\n1")
+    assert_equal ['=', Gem::Version.new(0)], @r1_2.parse("=\njunk")
+
+    assert_equal ['=', Gem::Version.new(2)], @r1_2.parse(Gem::Version.new('2'))
+  end
+
+  def test_parse_illformed
+    e = assert_raises ArgumentError do
+      @r1_2.parse(nil)
+    end
+
+    assert_equal 'Illformed requirement [nil]', e.message
+
+    e = assert_raises ArgumentError do
+      @r1_2.parse('')
+    end
+
+    assert_equal 'Illformed requirement [""]', e.message
+  end
+
+  def test_satisfied_by_eh_bang_equal
+    r1_2 = Gem::Requirement.new '!= 1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal true,  r1_2.satisfied_by?(nil)
+    assert_equal true,  r1_2.satisfied_by?(v1_1)
+    assert_equal false, r1_2.satisfied_by?(v1_2)
+    assert_equal true,  r1_2.satisfied_by?(v1_3)
+  end
+
+  def test_satisfied_by_eh_blank
+    r1_2 = Gem::Requirement.new '1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal false, r1_2.satisfied_by?(nil)
+    assert_equal false, r1_2.satisfied_by?(v1_1)
+    assert_equal true,  r1_2.satisfied_by?(v1_2)
+    assert_equal false, r1_2.satisfied_by?(v1_3)
+  end
+
+  def test_satisfied_by_eh_equal
+    r1_2 = @r1_2
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal false, r1_2.satisfied_by?(nil)
+    assert_equal false, r1_2.satisfied_by?(v1_1)
+    assert_equal true,  r1_2.satisfied_by?(v1_2)
+    assert_equal false, r1_2.satisfied_by?(v1_3)
+  end
+
+  def test_satisfied_by_eh_gt
+    r1_2 = Gem::Requirement.new '> 1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal false, r1_2.satisfied_by?(v1_1)
+    assert_equal false, r1_2.satisfied_by?(v1_2)
+    assert_equal true,  r1_2.satisfied_by?(v1_3)
+
+    assert_raises NoMethodError do
+      assert_equal true,  r1_2.satisfied_by?(nil)
+    end
+  end
+
+  def test_satisfied_by_eh_gte
+    r1_2 = Gem::Requirement.new '>= 1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal false, r1_2.satisfied_by?(v1_1)
+    assert_equal true,  r1_2.satisfied_by?(v1_2)
+    assert_equal true,  r1_2.satisfied_by?(v1_3)
+
+    assert_raises NoMethodError do
+      assert_equal true,  r1_2.satisfied_by?(nil)
+    end
+  end
+
+  def test_satisfied_by_eh_list
+    r = Gem::Requirement.create(['> 1.1', '< 1.3'])
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal false, r.satisfied_by?(v1_1)
+    assert_equal true,  r.satisfied_by?(v1_2)
+    assert_equal false, r.satisfied_by?(v1_3)
+
+    assert_raises NoMethodError do
+      assert_equal true,  r.satisfied_by?(nil)
+    end
+  end
+
+  def test_satisfied_by_eh_lt
+    r1_2 = Gem::Requirement.new '< 1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal true,  r1_2.satisfied_by?(v1_1)
+    assert_equal false, r1_2.satisfied_by?(v1_2)
+    assert_equal false, r1_2.satisfied_by?(v1_3)
+
+    assert_raises NoMethodError do
+      assert_equal true,  r1_2.satisfied_by?(nil)
+    end
+  end
+
+  def test_satisfied_by_eh_lte
+    r1_2 = Gem::Requirement.new '<= 1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal true,  r1_2.satisfied_by?(v1_1)
+    assert_equal true,  r1_2.satisfied_by?(v1_2)
+    assert_equal false, r1_2.satisfied_by?(v1_3)
+
+    assert_raises NoMethodError do
+      assert_equal true,  r1_2.satisfied_by?(nil)
+    end
+  end
+
+  def test_satisfied_by_eh_tilde_gt
+    r1_2 = Gem::Requirement.new '~> 1.2'
+    v1_1 = Gem::Version.new '1.1'
+    v1_2 = Gem::Version.new '1.2'
+    v1_3 = Gem::Version.new '1.3'
+
+    assert_equal false, r1_2.satisfied_by?(v1_1)
+    assert_equal true,  r1_2.satisfied_by?(v1_2)
+    assert_equal true,  r1_2.satisfied_by?(v1_3)
+
+    assert_raises NoMethodError do
+      assert_equal true,  r1_2.satisfied_by?(nil)
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_server.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_server.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_server.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,310 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/server'
+require 'stringio'
+
+class Gem::Server
+  attr_accessor :source_index
+  attr_reader :server
+end
+
+class TestGemServer < RubyGemTestCase
+
+  def setup
+    super
+
+    @a1 = quick_gem 'a', '1'
+    @a2 = quick_gem 'a', '2'
+
+    @server = Gem::Server.new Gem.dir, process_based_port, false
+    @req = WEBrick::HTTPRequest.new :Logger => nil
+    @res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
+  end
+
+  def test_Marshal
+    data = StringIO.new "GET /Marshal.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.Marshal @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/octet-stream', @res['content-type']
+
+    si = Gem::SourceIndex.new
+    si.add_specs @a1, @a2
+
+    assert_equal si, Marshal.load(@res.body)
+  end
+
+  def test_Marshal_Z
+    data = StringIO.new "GET /Marshal.#{Gem.marshal_version}.Z HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.Marshal @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    si = Gem::SourceIndex.new
+    si.add_specs @a1, @a2
+
+    assert_equal si, Marshal.load(Gem.inflate(@res.body))
+  end
+
+  def test_latest_specs
+    data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.latest_specs @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/octet-stream', @res['content-type']
+    assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+                 Marshal.load(@res.body)
+  end
+
+  def test_latest_specs_gz
+    data = StringIO.new "GET /latest_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.latest_specs @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/x-gzip', @res['content-type']
+    assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+                 Marshal.load(Gem.gunzip(@res.body))
+  end
+
+  def test_quick_a_1_gemspec_rz
+    data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    spec = YAML.load Gem.inflate(@res.body)
+    assert_equal 'a', spec.name
+    assert_equal Gem::Version.new(1), spec.version
+  end
+
+  def test_quick_a_1_mswin32_gemspec_rz
+    a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
+
+    data = StringIO.new "GET /quick/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    spec = YAML.load Gem.inflate(@res.body)
+    assert_equal 'a', spec.name
+    assert_equal Gem::Version.new(1), spec.version
+    assert_equal Gem::Platform.local, spec.platform
+  end
+
+  def test_quick_common_substrings
+    ab1 = quick_gem 'ab', '1'
+
+    data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    spec = YAML.load Gem.inflate(@res.body)
+    assert_equal 'a', spec.name
+    assert_equal Gem::Version.new(1), spec.version
+  end
+
+  def test_quick_index
+    data = StringIO.new "GET /quick/index HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'text/plain', @res['content-type']
+    assert_equal "a-1\na-2", @res.body
+  end
+
+  def test_quick_index_rz
+    data = StringIO.new "GET /quick/index.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+    assert_equal "a-1\na-2", Gem.inflate(@res.body)
+  end
+
+  def test_quick_latest_index
+    data = StringIO.new "GET /quick/latest_index HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'text/plain', @res['content-type']
+    assert_equal 'a-2', @res.body
+  end
+
+  def test_quick_latest_index_rz
+    data = StringIO.new "GET /quick/latest_index.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+    assert_equal 'a-2', Gem.inflate(@res.body)
+  end
+
+  def test_quick_missing
+    data = StringIO.new "GET /quick/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 404, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'text/plain', @res['content-type']
+    assert_equal 'No gems found matching "z" "9" nil', @res.body
+    assert_equal 404, @res.status
+  end
+
+  def test_quick_marshal_a_1_gemspec_rz
+    data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    spec = Marshal.load Gem.inflate(@res.body)
+    assert_equal 'a', spec.name
+    assert_equal Gem::Version.new(1), spec.version
+  end
+
+  def test_quick_marshal_a_1_mswin32_gemspec_rz
+    a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
+
+    data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.quick @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    spec = Marshal.load Gem.inflate(@res.body)
+    assert_equal 'a', spec.name
+    assert_equal Gem::Version.new(1), spec.version
+    assert_equal Gem::Platform.local, spec.platform
+  end
+
+  def test_rdoc
+    data = StringIO.new "GET /rdoc?q=a HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.rdoc @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r|No documentation found|, @res.body
+    assert_equal 'text/html', @res['content-type']
+  end
+
+  def test_root
+    data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.root @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'text/html', @res['content-type']
+  end
+
+  def test_specs
+    data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.specs @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/octet-stream', @res['content-type']
+
+    assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
+                  ['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+                 Marshal.load(@res.body)
+  end
+
+  def test_specs_gz
+    data = StringIO.new "GET /specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.specs @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/x-gzip', @res['content-type']
+
+    assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
+                  ['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+                 Marshal.load(Gem.gunzip(@res.body))
+  end
+
+  def test_yaml
+    data = StringIO.new "GET /yaml.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.yaml @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'text/plain', @res['content-type']
+
+    si = Gem::SourceIndex.new
+    si.add_specs @a1, @a2
+
+    assert_equal si, YAML.load(@res.body)
+  end
+
+  def test_yaml_Z
+    data = StringIO.new "GET /yaml.#{Gem.marshal_version}.Z HTTP/1.0\r\n\r\n"
+    @req.parse data
+
+    @server.yaml @req, @res
+
+    assert_equal 200, @res.status, @res.body
+    assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+    assert_equal 'application/x-deflate', @res['content-type']
+
+    si = Gem::SourceIndex.new
+    si.add_specs @a1, @a2
+
+    assert_equal si, YAML.load(Gem.inflate(@res.body))
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_source_index.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_source_index.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_source_index.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,467 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/source_index'
+require 'rubygems/config_file'
+
+class Gem::SourceIndex
+  public :fetcher, :fetch_bulk_index, :fetch_quick_index,
+         :find_missing, :gems, :remove_extra,
+         :update_with_missing, :unzip
+end
+
+class TestGemSourceIndex < RubyGemTestCase
+
+  def setup
+    super
+
+    util_setup_fake_fetcher
+  end
+
+  def test_self_from_gems_in
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.rm_r spec_dir
+
+    FileUtils.mkdir_p spec_dir
+
+    a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
+
+    spec_file = File.join spec_dir, a1.spec_name
+
+    File.open spec_file, 'w' do |fp|
+      fp.write a1.to_ruby
+    end
+
+    si = Gem::SourceIndex.from_gems_in spec_dir
+
+    assert_equal [spec_dir], si.spec_dirs
+    assert_equal [a1.full_name], si.gems.keys
+  end
+
+  def test_self_load_specification
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.rm_r spec_dir
+
+    FileUtils.mkdir_p spec_dir
+
+    a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
+
+    spec_file = File.join spec_dir, a1.spec_name
+
+    File.open spec_file, 'w' do |fp|
+      fp.write a1.to_ruby
+    end
+
+    spec = Gem::SourceIndex.load_specification spec_file
+
+    assert_equal a1.author, spec.author
+  end
+
+  def test_self_load_specification_utf_8
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.rm_r spec_dir
+
+    FileUtils.mkdir_p spec_dir
+
+    spec_file = File.join spec_dir, "utf-8.gemspec"
+    spec_data = <<-SPEC
+Gem::Specification.new do |s|
+  s.name = %q{utf}
+  s.version = "8"
+
+  s.required_rubygems_version = Gem::Requirement.new(">= 0")
+  s.authors = ["\317\200"]
+  s.date = %q{2008-09-10}
+  s.description = %q{This is a test description}
+  s.email = %q{example at example.com}
+  s.has_rdoc = true
+  s.homepage = %q{http://example.com}
+  s.require_paths = ["lib"]
+  s.rubygems_version = %q{1.2.0}
+  s.summary = %q{this is a summary}
+
+  if s.respond_to? :specification_version then
+    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+    s.specification_version = 2
+
+    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+    else
+    end
+  else
+  end
+end
+    SPEC
+
+    spec_data.force_encoding 'UTF-8'
+
+    File.open spec_file, 'w' do |io| io.write spec_data end
+
+    spec = Gem::SourceIndex.load_specification spec_file
+
+    pi = "\317\200"
+    pi.force_encoding 'UTF-8' if pi.respond_to? :force_encoding
+
+    assert_equal pi, spec.author
+  end if Gem.ruby_version > Gem::Version.new('1.9')
+
+  def test_self_load_specification_exception
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.mkdir_p spec_dir
+
+    spec_file = File.join spec_dir, 'a-1.gemspec'
+
+    File.open spec_file, 'w' do |fp|
+      fp.write 'raise Exception, "epic fail"'
+    end
+
+    use_ui @ui do
+      assert_equal nil, Gem::SourceIndex.load_specification(spec_file)
+    end
+
+    assert_equal '', @ui.output
+
+    expected = <<-EOF
+WARNING:  #<Exception: epic fail>
+raise Exception, "epic fail"
+WARNING:  Invalid .gemspec format in '#{spec_file}'
+    EOF
+
+    assert_equal expected, @ui.error
+  end
+
+  def test_self_load_specification_interrupt
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.mkdir_p spec_dir
+
+    spec_file = File.join spec_dir, 'a-1.gemspec'
+
+    File.open spec_file, 'w' do |fp|
+      fp.write 'raise Interrupt, "^C"'
+    end
+
+    use_ui @ui do
+      assert_raises Interrupt do
+        Gem::SourceIndex.load_specification(spec_file)
+      end
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_self_load_specification_syntax_error
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.mkdir_p spec_dir
+
+    spec_file = File.join spec_dir, 'a-1.gemspec'
+
+    File.open spec_file, 'w' do |fp|
+      fp.write '1 +'
+    end
+
+    use_ui @ui do
+      assert_equal nil, Gem::SourceIndex.load_specification(spec_file)
+    end
+
+    assert_equal '', @ui.output
+
+    assert_match(/syntax error/, @ui.error)
+    assert_match(/1 \+/, @ui.error)
+  end
+
+  def test_self_load_specification_system_exit
+    spec_dir = File.join @gemhome, 'specifications'
+
+    FileUtils.mkdir_p spec_dir
+
+    spec_file = File.join spec_dir, 'a-1.gemspec'
+
+    File.open spec_file, 'w' do |fp|
+      fp.write 'raise SystemExit, "bye-bye"'
+    end
+
+    use_ui @ui do
+      assert_raises SystemExit do
+        Gem::SourceIndex.load_specification(spec_file)
+      end
+    end
+
+    assert_equal '', @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_create_from_directory
+    # TODO
+  end
+
+  def test_fetcher
+    assert_equal @fetcher, @source_index.fetcher
+  end
+
+  def test_find_missing
+    missing = @source_index.find_missing [@b2.full_name]
+    assert_equal [@b2.full_name], missing
+  end
+
+  def test_find_missing_none_missing
+    missing = @source_index.find_missing [
+      @a1.full_name, @a2.full_name, @c1_2.full_name
+    ]
+
+    assert_equal [], missing
+  end
+
+  def test_find_name
+    assert_equal [@a1, @a2, @a3a], @source_index.find_name('a')
+    assert_equal [@a2], @source_index.find_name('a', '= 2')
+    assert_equal [], @source_index.find_name('bogusstring')
+    assert_equal [], @source_index.find_name('a', '= 3')
+
+    source_index = Gem::SourceIndex.new
+    source_index.add_spec @a1
+    source_index.add_spec @a2
+
+    assert_equal [@a1], source_index.find_name(@a1.name, '= 1')
+
+    r1 = Gem::Requirement.create '= 1'
+    assert_equal [@a1], source_index.find_name(@a1.name, r1)
+  end
+
+  def test_find_name_empty_cache
+    empty_source_index = Gem::SourceIndex.new({})
+    assert_equal [], empty_source_index.find_name("foo")
+  end
+
+  def test_latest_specs
+    p1_ruby = quick_gem 'p', '1'
+    p1_platform = quick_gem 'p', '1' do |spec|
+      spec.platform = Gem::Platform::CURRENT
+    end
+
+    a1_platform = quick_gem @a1.name, (@a1.version) do |s|
+      s.platform = Gem::Platform.new 'x86-my_platform1'
+    end
+
+    a2_platform = quick_gem @a2.name, (@a2.version) do |s|
+      s.platform = Gem::Platform.new 'x86-my_platform1'
+    end
+
+    a2_platform_other = quick_gem @a2.name, (@a2.version) do |s|
+      s.platform = Gem::Platform.new 'x86-other_platform1'
+    end
+
+    a3_platform_other = quick_gem @a2.name, (@a2.version.bump) do |s|
+      s.platform = Gem::Platform.new 'x86-other_platform1'
+    end
+
+    @source_index.add_spec p1_ruby
+    @source_index.add_spec p1_platform
+    @source_index.add_spec a1_platform
+    @source_index.add_spec a2_platform
+    @source_index.add_spec a2_platform_other
+    @source_index.add_spec a3_platform_other
+
+    expected = [
+      @a2.full_name,
+      a2_platform.full_name,
+      a3_platform_other.full_name,
+      @c1_2.full_name,
+      @a_evil9.full_name,
+      p1_ruby.full_name,
+      p1_platform.full_name,
+    ].sort
+
+    latest_specs = @source_index.latest_specs.map { |s| s.full_name }.sort
+
+    assert_equal expected, latest_specs
+  end
+
+  def test_load_gems_in
+    spec_dir1 = File.join @gemhome, 'specifications'
+    spec_dir2 = File.join @tempdir, 'gemhome2', 'specifications'
+
+    FileUtils.rm_r spec_dir1
+
+    FileUtils.mkdir_p spec_dir1
+    FileUtils.mkdir_p spec_dir2
+
+    a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
+    a2 = quick_gem 'a', '1' do |spec| spec.author = 'author 2' end
+
+    File.open File.join(spec_dir1, a1.spec_name), 'w' do |fp|
+      fp.write a1.to_ruby
+    end
+
+    File.open File.join(spec_dir2, a2.spec_name), 'w' do |fp|
+      fp.write a2.to_ruby
+    end
+
+    @source_index.load_gems_in spec_dir1, spec_dir2
+
+    assert_equal a1.author, @source_index.specification(a1.full_name).author
+  end
+
+  def test_outdated
+    util_setup_spec_fetcher
+
+    assert_equal [], @source_index.outdated
+
+    updated = quick_gem @a2.name, (@a2.version.bump)
+    util_setup_spec_fetcher updated
+
+    assert_equal [updated.name], @source_index.outdated
+
+    updated_platform = quick_gem @a2.name, (updated.version.bump) do |s|
+      s.platform = Gem::Platform.new 'x86-other_platform1'
+    end
+
+    util_setup_spec_fetcher updated, updated_platform
+
+    assert_equal [updated_platform.name], @source_index.outdated
+  end
+
+  def test_prerelease_specs_kept_in_right_place
+    gem_a1_alpha = quick_gem 'abba', '1.a'
+    @source_index.add_spec gem_a1_alpha
+
+    refute @source_index.latest_specs.include?(gem_a1_alpha)
+    assert @source_index.find_name(gem_a1_alpha.full_name).empty?
+    assert @source_index.prerelease_specs.include?(gem_a1_alpha)
+  end
+
+  def test_refresh_bang
+    a1_spec = File.join @gemhome, "specifications", @a1.spec_name 
+
+    FileUtils.mv a1_spec, @tempdir
+
+    source_index = Gem::SourceIndex.from_installed_gems
+
+    refute source_index.gems.include?(@a1.full_name)
+
+    FileUtils.mv File.join(@tempdir, @a1.spec_name), a1_spec
+
+    source_index.refresh!
+
+    assert source_index.gems.include?(@a1.full_name)
+  end
+
+  def test_refresh_bang_not_from_dir
+    source_index = Gem::SourceIndex.new
+
+    e = assert_raises RuntimeError do
+      source_index.refresh!
+    end
+
+    assert_equal 'source index not created from disk', e.message
+  end
+
+  def test_remove_extra
+    @source_index.add_spec @a1
+    @source_index.add_spec @a2
+    @source_index.add_spec @pl1
+
+    @source_index.remove_extra [@a1.full_name, @pl1.full_name]
+
+    assert_equal [@a1.full_name],
+                 @source_index.gems.map { |n,s| n }.sort
+  end
+
+  def test_remove_extra_no_changes
+    gems = [@a1.full_name, @a2.full_name]
+    @source_index.add_spec @a1
+    @source_index.add_spec @a2
+
+    @source_index.remove_extra gems
+
+    assert_equal gems, @source_index.gems.map { |n,s| n }.sort
+  end
+
+  def test_remove_spec
+    deleted = @source_index.remove_spec 'a-1'
+
+    assert_equal %w[a-2 a-3.a a_evil-9 c-1.2],
+                 @source_index.all_gems.values.map { |s| s.full_name }.sort
+
+    deleted = @source_index.remove_spec 'a-3.a'
+
+    assert_equal %w[a-2 a_evil-9 c-1.2],
+                 @source_index.all_gems.values.map { |s| s.full_name }.sort
+  end
+
+  def test_search
+    requirement = Gem::Requirement.create '= 9'
+    with_version = Gem::Dependency.new(/^a/, requirement)
+    assert_equal [@a_evil9], @source_index.search(with_version)
+
+    with_default = Gem::Dependency.new(/^a/, Gem::Requirement.default)
+    assert_equal [@a1, @a2, @a3a, @a_evil9], @source_index.search(with_default)
+
+    c1_1_dep = Gem::Dependency.new 'c', '~> 1.1'
+    assert_equal [@c1_2], @source_index.search(c1_1_dep)
+  end
+
+  def test_search_platform
+    util_set_arch 'x86-my_platform1'
+
+    a1 = quick_gem 'a', '1'
+    a1_mine = quick_gem 'a', '1' do |s|
+      s.platform = Gem::Platform.new 'x86-my_platform1'
+    end
+    a1_other = quick_gem 'a', '1' do |s|
+      s.platform = Gem::Platform.new 'x86-other_platform1'
+    end
+
+    si = Gem::SourceIndex.new(a1.full_name => a1, a1_mine.full_name => a1_mine,
+                              a1_other.full_name => a1_other)
+
+    dep = Gem::Dependency.new 'a', Gem::Requirement.new('1')
+
+    gems = si.search dep, true
+
+    assert_equal [a1, a1_mine], gems.sort
+  end
+
+  def test_signature
+    sig = @source_index.gem_signature('foo-1.2.3')
+    assert_equal 64, sig.length
+    assert_match(/^[a-f0-9]{64}$/, sig)
+  end
+
+  def test_specification
+    assert_equal @a1, @source_index.specification(@a1.full_name)
+
+    assert_nil @source_index.specification("foo-1.2.4")
+  end
+
+  def test_index_signature
+    sig = @source_index.index_signature
+    assert_match(/^[a-f0-9]{64}$/, sig)
+  end
+
+  def test_unzip
+    input = "x\234+\316\317MU(I\255(\001\000\021\350\003\232"
+    assert_equal 'some text', @source_index.unzip(input)
+  end
+
+  def util_setup_bulk_fetch(compressed)
+    source_index = @source_index.dump
+
+    if compressed then
+      @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] = util_zip source_index
+    else
+      @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = source_index
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_spec_fetcher.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_spec_fetcher.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_spec_fetcher.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,367 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/spec_fetcher'
+
+class TestGemSpecFetcher < RubyGemTestCase
+
+  def setup
+    super
+
+    @uri = URI.parse @gem_repo
+
+    util_setup_fake_fetcher
+
+    @a_pre = quick_gem 'a', '1.a'
+    @source_index.add_spec @pl1
+    @source_index.add_spec @a_pre
+
+    @specs = @source_index.gems.sort.map do |name, spec|
+      [spec.name, spec.version, spec.original_platform]
+    end.sort
+
+    @latest_specs = @source_index.latest_specs.sort.map do |spec|
+      [spec.name, spec.version, spec.original_platform]
+    end
+
+    @prerelease_specs = @source_index.prerelease_gems.sort.map do |name, spec|
+      [spec.name, spec.version, spec.original_platform]
+    end.sort
+
+    @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] =
+      util_gzip(Marshal.dump(@specs))
+
+    @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
+      util_gzip(Marshal.dump(@latest_specs))
+
+    @fetcher.data["#{@gem_repo}prerelease_specs.#{Gem.marshal_version}.gz"] =
+      util_gzip(Marshal.dump(@prerelease_specs))
+
+    @sf = Gem::SpecFetcher.new
+  end
+
+  def test_fetch_all
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a1))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a2))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a_pre.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a_pre))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a3a.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a3a))
+
+    dep = Gem::Dependency.new 'a', 1
+    specs_and_sources = @sf.fetch dep, true
+
+    spec_names = specs_and_sources.map do |spec, source_uri|
+      [spec.full_name, source_uri]
+    end
+
+    expected = [[@a1.full_name, @gem_repo], [@a2.full_name, @gem_repo]]
+
+    assert_equal expected, spec_names
+
+    assert_same specs_and_sources.first.last, specs_and_sources.last.last
+  end
+
+  def test_fetch_latest
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a1))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a2))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a_pre.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a_pre))
+
+    dep = Gem::Dependency.new 'a', 1
+    specs_and_sources = @sf.fetch dep
+
+    spec_names = specs_and_sources.map do |spec, source_uri|
+      [spec.full_name, source_uri]
+    end
+
+    assert_equal [[@a2.full_name, @gem_repo]], spec_names
+  end
+
+  def test_fetch_prerelease
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a1))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a2))
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a_pre.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a_pre))
+
+    dep = Gem::Dependency.new 'a', '1.a'
+    specs_and_sources = @sf.fetch dep, false, true, true
+
+    spec_names = specs_and_sources.map do |spec, source_uri|
+      [spec.full_name, source_uri]
+    end
+
+    assert_equal [[@a_pre.full_name, @gem_repo]], spec_names
+  end
+
+  def test_fetch_platform
+    util_set_arch 'i386-linux'
+
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@pl1.original_name}.gemspec.rz"] =
+      util_zip(Marshal.dump(@pl1))
+
+    dep = Gem::Dependency.new 'pl', 1
+    specs_and_sources = @sf.fetch dep
+
+    spec_names = specs_and_sources.map do |spec, source_uri|
+      [spec.full_name, source_uri]
+    end
+
+    assert_equal [[@pl1.full_name, @gem_repo]], spec_names
+  end
+
+  def test_fetch_spec
+    spec_uri = "#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}"
+    @fetcher.data["#{spec_uri}.rz"] = util_zip(Marshal.dump(@a1))
+
+    spec = @sf.fetch_spec ['a', Gem::Version.new(1), 'ruby'], @uri
+    assert_equal @a1.full_name, spec.full_name
+
+    cache_dir = @sf.cache_dir URI.parse(spec_uri)
+
+    cache_file = File.join cache_dir, @a1.spec_name
+
+    assert File.exist?(cache_file)
+  end
+
+  def test_fetch_spec_cached
+    spec_uri = "#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}"
+    @fetcher.data["#{spec_uri}.rz"] = nil
+
+    cache_dir = @sf.cache_dir URI.parse(spec_uri)
+    FileUtils.mkdir_p cache_dir
+
+    cache_file = File.join cache_dir, @a1.spec_name
+
+    open cache_file, 'wb' do |io|
+      Marshal.dump @a1, io
+    end
+
+    spec = @sf.fetch_spec ['a', Gem::Version.new(1), 'ruby'], @uri
+    assert_equal @a1.full_name, spec.full_name
+  end
+
+  def test_fetch_spec_platform
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@pl1.original_name}.gemspec.rz"] =
+      util_zip(Marshal.dump(@pl1))
+
+    spec = @sf.fetch_spec ['pl', Gem::Version.new(1), 'i386-linux'], @uri
+
+    assert_equal @pl1.full_name, spec.full_name
+  end
+
+  def test_fetch_spec_platform_ruby
+    @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] =
+      util_zip(Marshal.dump(@a1))
+
+    spec = @sf.fetch_spec ['a', Gem::Version.new(1), nil], @uri
+    assert_equal @a1.full_name, spec.full_name
+
+    spec = @sf.fetch_spec ['a', Gem::Version.new(1), ''], @uri
+    assert_equal @a1.full_name, spec.full_name
+  end
+
+  def test_find_matching_all
+    dep = Gem::Dependency.new 'a', 1
+    specs = @sf.find_matching dep, true
+
+    expected = [
+      [['a', Gem::Version.new(1), Gem::Platform::RUBY], @gem_repo],
+      [['a', Gem::Version.new(2), Gem::Platform::RUBY], @gem_repo],
+    ]
+
+    assert_equal expected, specs
+  end
+
+  def test_find_matching_latest
+    dep = Gem::Dependency.new 'a', 1
+    specs = @sf.find_matching dep
+
+    expected = [
+      [['a', Gem::Version.new(2), Gem::Platform::RUBY], @gem_repo],
+    ]
+
+    assert_equal expected, specs
+  end
+
+  def test_find_matching_prerelease
+    dep = Gem::Dependency.new 'a', '1.a'
+    specs = @sf.find_matching dep, false, true, true
+
+    expected = [
+      [['a', Gem::Version.new('1.a'), Gem::Platform::RUBY], @gem_repo],
+    ]
+
+    assert_equal expected, specs
+  end
+
+  def test_find_matching_platform
+    util_set_arch 'i386-linux'
+
+    dep = Gem::Dependency.new 'pl', 1
+    specs = @sf.find_matching dep
+
+    expected = [
+      [['pl', Gem::Version.new(1), 'i386-linux'], @gem_repo],
+    ]
+
+    assert_equal expected, specs
+
+    util_set_arch 'i386-freebsd6'
+
+    dep = Gem::Dependency.new 'pl', 1
+    specs = @sf.find_matching dep
+
+    assert_equal [], specs
+  end
+
+  def test_find_all_platforms
+    util_set_arch 'i386-freebsd6'
+
+    dep = Gem::Dependency.new 'pl', 1
+    specs = @sf.find_matching dep, false, false
+
+    expected = [
+      [['pl', Gem::Version.new(1), 'i386-linux'], @gem_repo],
+    ]
+
+    assert_equal expected, specs
+  end
+
+  def test_list
+    specs = @sf.list
+
+    assert_equal [@uri], specs.keys
+    assert_equal @latest_specs, specs[@uri].sort
+  end
+
+  def test_list_all
+    specs = @sf.list true
+
+    assert_equal [@uri], specs.keys
+
+    assert_equal([["a", Gem::Version.new("1"), "ruby"],
+                  ["a", Gem::Version.new("2"), "ruby"],
+                  ["a_evil", Gem::Version.new("9"), "ruby"],
+                  ["c", Gem::Version.new("1.2"), "ruby"],
+                  ["pl", Gem::Version.new("1"), "i386-linux"]],
+                 specs[@uri].sort)
+  end
+
+  def test_list_cache
+    specs = @sf.list
+
+    refute specs[@uri].empty?
+
+    @fetcher.data["#{@gem_repo}/latest_specs.#{Gem.marshal_version}.gz"] = nil
+
+    cached_specs = @sf.list
+
+    assert_equal specs, cached_specs
+  end
+
+  def test_list_cache_all
+    specs = @sf.list true
+
+    refute specs[@uri].empty?
+
+    @fetcher.data["#{@gem_repo}/specs.#{Gem.marshal_version}.gz"] = nil
+
+    cached_specs = @sf.list true
+
+    assert_equal specs, cached_specs
+  end
+
+  def test_list_latest_all
+    specs = @sf.list false
+
+    assert_equal [@latest_specs], specs.values
+
+    specs = @sf.list true
+
+    assert_equal([[["a", Gem::Version.new("1"), "ruby"],
+                   ["a", Gem::Version.new("2"), "ruby"],
+                   ["a_evil", Gem::Version.new("9"), "ruby"],
+                   ["c", Gem::Version.new("1.2"), "ruby"],
+                   ["pl", Gem::Version.new("1"), "i386-linux"]]],
+                 specs.values, 'specs file not loaded')
+  end
+
+  def test_list_prerelease
+    specs = @sf.list false, true
+
+    assert_equal @prerelease_specs, specs[@uri].sort
+  end
+
+  def test_load_specs
+    specs = @sf.load_specs @uri, 'specs'
+
+    expected = [
+      ['a',      Gem::Version.new('1.a'),     Gem::Platform::RUBY],
+      ['a',      Gem::Version.new(1),     Gem::Platform::RUBY],
+      ['a',      Gem::Version.new(2),     Gem::Platform::RUBY],
+      ['a',      Gem::Version.new('3.a'),     Gem::Platform::RUBY],
+      ['a_evil', Gem::Version.new(9),     Gem::Platform::RUBY],
+      ['c',      Gem::Version.new('1.2'), Gem::Platform::RUBY],
+      ['pl',     Gem::Version.new(1),     'i386-linux'],
+    ]
+
+    assert_equal expected, specs
+
+    cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com%80'
+    assert File.exist?(cache_dir), "#{cache_dir} does not exist"
+
+    cache_file = File.join cache_dir, "specs.#{Gem.marshal_version}"
+    assert File.exist?(cache_file)
+  end
+
+  def test_load_specs_cached
+    @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+    @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}"] =
+      ' ' * Marshal.dump(@latest_specs).length
+
+    cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com%80'
+
+    FileUtils.mkdir_p cache_dir
+
+    cache_file = File.join cache_dir, "latest_specs.#{Gem.marshal_version}"
+
+    open cache_file, 'wb' do |io|
+      Marshal.dump @latest_specs, io
+    end
+
+    latest_specs = @sf.load_specs @uri, 'latest_specs'
+
+    assert_equal @latest_specs, latest_specs
+  end
+
+  def test_load_specs_cached_empty
+    @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
+      proc do
+        @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
+          util_gzip(Marshal.dump(@latest_specs))
+
+        nil
+      end
+
+    cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com%80'
+
+    FileUtils.mkdir_p cache_dir
+
+    cache_file = File.join cache_dir, "latest_specs.#{Gem.marshal_version}"
+
+    open cache_file, 'wb' do |io|
+      io.write Marshal.dump(@latest_specs)[0, 10]
+    end
+
+    latest_specs = @sf.load_specs @uri, 'latest_specs'
+
+    assert_equal @latest_specs, latest_specs
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_specification.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_specification.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_specification.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,1250 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'stringio'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/specification'
+
+class TestGemSpecification < RubyGemTestCase
+
+  LEGACY_YAML_SPEC = <<-EOF
+--- !ruby/object:Gem::Specification
+rubygems_version: "1.0"
+name: keyedlist
+version: !ruby/object:Gem::Version
+  version: 0.4.0
+date: 2004-03-28 15:37:49.828000 +02:00
+platform:
+summary: A Hash which automatically computes keys.
+require_paths:
+  - lib
+files:
+  - lib/keyedlist.rb
+autorequire: keyedlist
+author: Florian Gross
+email: flgr at ccan.de
+has_rdoc: true
+  EOF
+
+  LEGACY_RUBY_SPEC = <<-EOF
+Gem::Specification.new do |s|
+  s.name = %q{keyedlist}
+  s.version = %q{0.4.0}
+  s.has_rdoc = true
+  s.summary = %q{A Hash which automatically computes keys.}
+  s.files = ["lib/keyedlist.rb"]
+  s.require_paths = ["lib"]
+  s.autorequire = %q{keyedlist}
+  s.author = %q{Florian Gross}
+  s.email = %q{flgr at ccan.de}
+end
+  EOF
+
+  def setup
+    super
+
+    @a1 = quick_gem 'a', '1' do |s|
+      s.executable = 'exec'
+      s.extensions << 'ext/a/extconf.rb'
+      s.has_rdoc = 'true'
+      s.test_file = 'test/suite.rb'
+      s.requirements << 'A working computer'
+      s.rubyforge_project = 'example'
+      s.license = 'MIT'
+
+      s.add_dependency 'rake', '> 0.4'
+      s.add_dependency 'jabber4r', '> 0.0.0'
+      s.add_dependency 'pqa', ['> 0.4', '<= 0.6']
+
+      s.mark_version
+      s.files = %w[lib/code.rb]
+    end
+
+    @a2 = quick_gem 'a', '2' do |s|
+      s.files = %w[lib/code.rb]
+    end
+
+    FileUtils.mkdir_p File.join(@tempdir, 'bin')
+    File.open File.join(@tempdir, 'bin', 'exec'), 'w' do |fp|
+      fp.puts "#!#{Gem.ruby}"
+    end
+
+    @current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+  end
+
+  def test_self_attribute_names
+    expected_value = %w[
+      authors
+      autorequire
+      bindir
+      cert_chain
+      date
+      default_executable
+      dependencies
+      description
+      email
+      executables
+      extensions
+      extra_rdoc_files
+      files
+      has_rdoc
+      homepage
+      licenses
+      name
+      platform
+      post_install_message
+      rdoc_options
+      require_paths
+      required_ruby_version
+      required_rubygems_version
+      requirements
+      rubyforge_project
+      rubygems_version
+      signing_key
+      specification_version
+      summary
+      test_files
+      version
+    ]
+
+    actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort
+
+    assert_equal expected_value, actual_value
+  end
+
+  def test_self__load_future
+    spec = Gem::Specification.new
+    spec.name = 'a'
+    spec.version = '1'
+    spec.specification_version = @current_version + 1
+
+    new_spec = Marshal.load Marshal.dump(spec)
+
+    assert_equal 'a', new_spec.name
+    assert_equal Gem::Version.new(1), new_spec.version
+    assert_equal @current_version, new_spec.specification_version
+  end
+
+  def test_self_load
+    spec = File.join @gemhome, 'specifications', @a2.spec_name
+    gs = Gem::Specification.load spec
+
+    assert_equal @a2, gs
+  end
+
+  def test_self_load_legacy_ruby
+    spec = eval LEGACY_RUBY_SPEC
+    assert_equal 'keyedlist', spec.name
+    assert_equal '0.4.0', spec.version.to_s
+    assert_equal true, spec.has_rdoc?
+    assert_equal Gem::Specification::TODAY, spec.date
+    assert spec.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
+    assert_equal false, spec.has_unit_tests?
+  end
+
+  def test_self_normalize_yaml_input_with_183_yaml
+    input = "!ruby/object:Gem::Specification "
+    assert_equal "--- #{input}", Gem::Specification.normalize_yaml_input(input)
+  end
+
+  def test_self_normalize_yaml_input_with_non_183_yaml
+    input = "--- !ruby/object:Gem::Specification "
+    assert_equal input, Gem::Specification.normalize_yaml_input(input)
+  end
+
+  def test_self_normalize_yaml_input_with_183_io
+    input = "!ruby/object:Gem::Specification "
+    assert_equal "--- #{input}",
+      Gem::Specification.normalize_yaml_input(StringIO.new(input))
+  end
+
+  def test_self_normalize_yaml_input_with_non_183_io
+    input = "--- !ruby/object:Gem::Specification "
+    assert_equal input,
+      Gem::Specification.normalize_yaml_input(StringIO.new(input))
+  end
+
+  def test_initialize
+    spec = Gem::Specification.new do |s|
+      s.name = "blah"
+      s.version = "1.3.5"
+    end
+
+    assert_equal "blah", spec.name
+    assert_equal "1.3.5", spec.version.to_s
+    assert_equal Gem::Platform::RUBY, spec.platform
+    assert_equal nil, spec.summary
+    assert_equal [], spec.files
+
+    assert_equal [], spec.test_files
+    assert_equal [], spec.rdoc_options
+    assert_equal [], spec.extra_rdoc_files
+    assert_equal [], spec.executables
+    assert_equal [], spec.extensions
+    assert_equal [], spec.requirements
+    assert_equal [], spec.dependencies
+    assert_equal 'bin', spec.bindir
+    assert_equal true, spec.has_rdoc
+    assert_equal true, spec.has_rdoc?
+    assert_equal '>= 0', spec.required_ruby_version.to_s
+    assert_equal '>= 0', spec.required_rubygems_version.to_s
+  end
+
+  def test_initialize_future
+    version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + 1
+    spec = Gem::Specification.new do |s|
+      s.name = "blah"
+      s.version = "1.3.5"
+
+      s.specification_version = version
+
+      s.new_unknown_attribute = "a value"
+    end
+
+    assert_equal "blah", spec.name
+    assert_equal "1.3.5", spec.version.to_s
+  end
+
+  def test_initialize_copy
+    spec = Gem::Specification.new do |s|
+      s.name = "blah"
+      s.version = "1.3.5"
+      s.summary = 'summary'
+      s.description = 'description'
+      s.authors = 'author a', 'author b'
+      s.licenses = 'BSD'
+      s.files = 'lib/file.rb'
+      s.test_files = 'test/file.rb'
+      s.rdoc_options = '--foo'
+      s.extra_rdoc_files = 'README.txt'
+      s.executables = 'exec'
+      s.extensions = 'ext/extconf.rb'
+      s.requirements = 'requirement'
+      s.add_dependency 'some_gem'
+    end
+
+    new_spec = spec.dup
+
+    assert_equal "blah", spec.name
+    assert_same  spec.name, new_spec.name
+
+    assert_equal "1.3.5", spec.version.to_s
+    assert_same spec.version, new_spec.version
+
+    assert_equal Gem::Platform::RUBY, spec.platform
+    assert_same spec.platform, new_spec.platform
+
+    assert_equal 'summary', spec.summary
+    assert_same spec.summary, new_spec.summary
+
+    assert_equal %w[lib/file.rb test/file.rb bin/exec README.txt
+                    ext/extconf.rb],
+                 spec.files
+    refute_same spec.files, new_spec.files, 'files'
+
+    assert_equal %w[test/file.rb], spec.test_files
+    refute_same spec.test_files, new_spec.test_files, 'test_files'
+
+    assert_equal %w[--foo], spec.rdoc_options
+    refute_same spec.rdoc_options, new_spec.rdoc_options, 'rdoc_options'
+
+    assert_equal %w[README.txt], spec.extra_rdoc_files
+    refute_same spec.extra_rdoc_files, new_spec.extra_rdoc_files,
+                'extra_rdoc_files'
+
+    assert_equal %w[exec], spec.executables
+    refute_same spec.executables, new_spec.executables, 'executables'
+
+    assert_equal %w[ext/extconf.rb], spec.extensions
+    refute_same spec.extensions, new_spec.extensions, 'extensions'
+
+    assert_equal %w[requirement], spec.requirements
+    refute_same spec.requirements, new_spec.requirements, 'requirements'
+
+    assert_equal [Gem::Dependency.new('some_gem', Gem::Requirement.default)],
+                 spec.dependencies
+    refute_same spec.dependencies, new_spec.dependencies, 'dependencies'
+
+    assert_equal 'bin', spec.bindir
+    assert_same spec.bindir, new_spec.bindir
+
+    assert_equal true, spec.has_rdoc
+    assert_same spec.has_rdoc, new_spec.has_rdoc
+
+    assert_equal '>= 0', spec.required_ruby_version.to_s
+    assert_same spec.required_ruby_version, new_spec.required_ruby_version
+
+    assert_equal '>= 0', spec.required_rubygems_version.to_s
+    assert_same spec.required_rubygems_version,
+                new_spec.required_rubygems_version
+  end
+
+  def test__dump
+    @a2.platform = Gem::Platform.local
+    @a2.instance_variable_set :@original_platform, 'old_platform'
+
+    data = Marshal.dump @a2
+
+    same_spec = Marshal.load data
+
+    assert_equal 'old_platform', same_spec.original_platform
+  end
+
+  def test_add_dependency_with_explicit_type
+    gem = quick_gem "awesome", "1.0" do |awesome|
+      awesome.add_development_dependency "monkey"
+    end
+
+    monkey = gem.dependencies.detect { |d| d.name == "monkey" }
+    assert_equal(:development, monkey.type)
+  end
+
+  def test_author
+    assert_equal 'A User', @a1.author
+  end
+
+  def test_authors
+    assert_equal ['A User'], @a1.authors
+  end
+
+  def test_bindir_equals
+    @a1.bindir = 'apps'
+
+    assert_equal 'apps', @a1.bindir
+  end
+
+  def test_bindir_equals_nil
+    @a2.bindir = nil
+    @a2.executable = 'app'
+
+    assert_equal nil, @a2.bindir
+    assert_equal %w[lib/code.rb app], @a2.files
+  end
+
+  def test_date
+    assert_equal Gem::Specification::TODAY, @a1.date
+  end
+
+  def test_date_equals_date
+    @a1.date = Date.new(2003, 9, 17)
+    assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+  end
+
+  def test_date_equals_string
+    @a1.date = '2003-09-17'
+    assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+  end
+
+  def test_date_equals_time
+    @a1.date = Time.local(2003, 9, 17, 0,0,0)
+    assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+  end
+
+  def test_date_equals_time_local
+    # HACK PDT
+    @a1.date = Time.local(2003, 9, 17, 19,50,0)
+    assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+  end
+
+  def test_date_equals_time_utc
+    # HACK PDT
+    @a1.date = Time.local(2003, 9, 17, 19,50,0)
+    assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+  end
+
+  def test_default_executable
+    assert_equal 'exec', @a1.default_executable
+
+    @a1.default_executable = nil
+    @a1.instance_variable_set :@executables, nil
+    assert_equal nil, @a1.default_executable
+  end
+
+  def test_dependencies
+    rake = Gem::Dependency.new 'rake', '> 0.4'
+    jabber = Gem::Dependency.new 'jabber4r', '> 0.0.0'
+    pqa = Gem::Dependency.new 'pqa', ['> 0.4', '<= 0.6']
+
+    assert_equal [rake, jabber, pqa], @a1.dependencies
+  end
+
+  def test_dependencies_scoped_by_type
+    gem = quick_gem "awesome", "1.0" do |awesome|
+      awesome.add_runtime_dependency "bonobo", []
+      awesome.add_development_dependency "monkey", []
+    end
+
+    bonobo = Gem::Dependency.new("bonobo", [])
+    monkey = Gem::Dependency.new("monkey", [], :development)
+
+    assert_equal([bonobo, monkey], gem.dependencies)
+    assert_equal([bonobo], gem.runtime_dependencies)
+    assert_equal([monkey], gem.development_dependencies)
+  end
+
+  def test_description
+    assert_equal 'This is a test description', @a1.description
+  end
+
+  def test_eql_eh
+    g1 = quick_gem 'gem'
+    g2 = quick_gem 'gem'
+
+    assert_equal g1, g2
+    assert_equal g1.hash, g2.hash
+    assert_equal true, g1.eql?(g2)
+  end
+
+  def test_equals2
+    assert_equal @a1, @a1
+    assert_equal @a1, @a1.dup
+    refute_equal @a1, @a2
+    refute_equal @a1, Object.new
+  end
+
+  # The cgikit specification was reported to be causing trouble in at least
+  # one version of RubyGems, so we test explicitly for it.
+  def test_equals2_cgikit
+    cgikit = Gem::Specification.new do |s|
+      s.name = %q{cgikit}
+      s.version = "1.1.0"
+      s.date = %q{2004-03-13}
+      s.summary = %q{CGIKit is a componented-oriented web application } +
+      %q{framework like Apple Computers WebObjects.  } +
+      %{This framework services Model-View-Controller architecture } +
+      %q{programming by components based on a HTML file, a definition } +
+      %q{file and a Ruby source.  }
+      s.email = %q{info at spice-of-life.net}
+      s.homepage = %q{http://www.spice-of-life.net/download/cgikit/}
+      s.autorequire = %q{cgikit}
+      s.bindir = nil
+      s.has_rdoc = true
+      s.required_ruby_version = nil
+      s.platform = nil
+      s.files = ["lib/cgikit", "lib/cgikit.rb", "lib/cgikit/components", "..."]
+    end
+
+    assert_equal cgikit, cgikit
+  end
+
+  def test_equals2_default_executable
+    spec = @a1.dup
+    spec.default_executable = 'xx'
+
+    refute_equal @a1, spec
+    refute_equal spec, @a1
+  end
+
+  def test_equals2_extensions
+    spec = @a1.dup
+    spec.extensions = 'xx'
+
+    refute_equal @a1, spec
+    refute_equal spec, @a1
+  end
+
+  def test_executables
+    @a1.executable = 'app'
+    assert_equal %w[app], @a1.executables
+  end
+
+  def test_executable_equals
+    @a2.executable = 'app'
+    assert_equal 'app', @a2.executable
+    assert_equal %w[lib/code.rb bin/app], @a2.files
+  end
+
+  def test_extensions
+    assert_equal ['ext/a/extconf.rb'], @a1.extensions
+  end
+
+  def test_files
+    @a1.files = %w(files bin/common)
+    @a1.test_files = %w(test_files bin/common)
+    @a1.executables = %w(executables common)
+    @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
+    @a1.extensions = %w(extensions bin/common)
+
+    expected = %w[
+      bin/common
+      bin/executables
+      extensions
+      extra_rdoc_files
+      files
+      test_files
+    ]
+    assert_equal expected, @a1.files.sort
+  end
+
+  def test_files_duplicate
+    @a2.files = %w[a b c d b]
+    @a2.extra_rdoc_files = %w[x y z x]
+    @a2.normalize
+
+    assert_equal %w[a b c d x y z], @a2.files
+    assert_equal %w[x y z], @a2.extra_rdoc_files
+  end
+
+  def test_files_extra_rdoc_files
+    @a2.files = %w[a b c d]
+    @a2.extra_rdoc_files = %w[x y z]
+    @a2.normalize
+    assert_equal %w[a b c d x y z], @a2.files
+  end
+
+  def test_files_non_array
+    @a1.files = "F"
+    @a1.test_files = "TF"
+    @a1.executables = "X"
+    @a1.extra_rdoc_files = "ERF"
+    @a1.extensions = "E"
+
+    assert_equal %w[E ERF F TF bin/X], @a1.files.sort
+  end
+
+  def test_files_non_array_pathological
+    @a1.instance_variable_set :@files, "F"
+    @a1.instance_variable_set :@test_files, "TF"
+    @a1.instance_variable_set :@extra_rdoc_files, "ERF"
+    @a1.instance_variable_set :@extensions, "E"
+    @a1.instance_variable_set :@executables, "X"
+
+    assert_equal %w[E ERF F TF bin/X], @a1.files.sort
+    assert_kind_of Integer, @a1.hash
+  end
+
+  def test_full_gem_path
+    assert_equal File.join(@gemhome, 'gems', @a1.full_name),
+                 @a1.full_gem_path
+
+    @a1.original_platform = 'mswin32'
+
+    assert_equal File.join(@gemhome, 'gems', @a1.original_name),
+                 @a1.full_gem_path
+  end
+
+  def test_full_gem_path_double_slash
+    gemhome = @gemhome.sub(/\w\//, '\&/')
+    @a1.loaded_from = File.join gemhome, 'specifications', @a1.spec_name
+
+    assert_equal File.join(@gemhome, 'gems', @a1.full_name),
+                 @a1.full_gem_path
+  end
+
+  def test_full_name
+    assert_equal 'a-1', @a1.full_name
+
+    @a1.platform = Gem::Platform.new ['universal', 'darwin', nil]
+    assert_equal 'a-1-universal-darwin', @a1.full_name
+
+    @a1.instance_variable_set :@new_platform, 'mswin32'
+    assert_equal 'a-1-mswin32', @a1.full_name, 'legacy'
+
+    return if win_platform?
+
+    @a1.platform = 'current'
+    assert_equal 'a-1-x86-darwin-8', @a1.full_name
+  end
+
+  def test_full_name_windows
+    test_cases = {
+      'i386-mswin32'      => 'a-1-x86-mswin32-60',
+      'i386-mswin32_80'   => 'a-1-x86-mswin32-80',
+      'i386-mingw32'      => 'a-1-x86-mingw32'
+    }
+    
+    test_cases.each do |arch, expected|
+      util_set_arch arch
+      @a1.platform = 'current'
+      assert_equal expected, @a1.full_name
+    end
+  end
+
+  def test_has_rdoc_eh
+    assert @a1.has_rdoc?
+  end
+
+  def test_has_rdoc_equals
+
+    use_ui @ui do
+      @a1.has_rdoc = false
+    end
+
+    assert_equal '', @ui.output
+
+    assert_equal true, @a1.has_rdoc
+  end
+
+  def test_hash
+    assert_equal @a1.hash, @a1.hash
+    assert_equal @a1.hash, @a1.dup.hash
+    refute_equal @a1.hash, @a2.hash
+  end
+
+  def test_installation_path
+    assert_equal @gemhome, @a1.installation_path
+
+    @a1.instance_variable_set :@loaded_from, nil
+
+    e = assert_raises Gem::Exception do
+      @a1.installation_path
+    end
+
+    assert_equal 'spec a-1 is not from an installed gem', e.message
+  end
+
+  def test_lib_files
+    @a1.files = %w[lib/foo.rb Rakefile]
+
+    assert_equal %w[lib/foo.rb], @a1.lib_files
+  end
+
+  def test_license
+    assert_equal 'MIT', @a1.license
+  end
+
+  def test_licenses
+    assert_equal ['MIT'], @a1.licenses
+  end
+
+  def test_name
+    assert_equal 'a', @a1.name
+  end
+
+  def test_original_name
+    assert_equal 'a-1', @a1.full_name
+
+    @a1.platform = 'i386-linux'
+    @a1.instance_variable_set :@original_platform, 'i386-linux'
+    assert_equal 'a-1-i386-linux', @a1.original_name
+  end
+
+  def test_platform
+    assert_equal Gem::Platform::RUBY, @a1.platform
+  end
+
+  def test_platform_equals
+    @a1.platform = nil
+    assert_equal Gem::Platform::RUBY, @a1.platform
+
+    @a1.platform = Gem::Platform::RUBY
+    assert_equal Gem::Platform::RUBY, @a1.platform
+
+    test_cases = {
+      'i386-mswin32'    => ['x86', 'mswin32', '60'],
+      'i386-mswin32_80' => ['x86', 'mswin32', '80'],
+      'i386-mingw32'    => ['x86', 'mingw32', nil ],
+      'x86-darwin8'     => ['x86', 'darwin',  '8' ],
+    }
+
+    test_cases.each do |arch, expected|
+      util_set_arch arch
+      @a1.platform = Gem::Platform::CURRENT
+      assert_equal Gem::Platform.new(expected), @a1.platform
+    end
+  end
+
+  def test_platform_equals_current
+    @a1.platform = Gem::Platform::CURRENT
+    assert_equal Gem::Platform.local, @a1.platform
+    assert_equal Gem::Platform.local.to_s, @a1.original_platform
+  end
+
+  def test_platform_equals_legacy
+    @a1.platform = 'mswin32'
+    assert_equal Gem::Platform.new('x86-mswin32'), @a1.platform
+
+    @a1.platform = 'i586-linux'
+    assert_equal Gem::Platform.new('x86-linux'), @a1.platform
+
+    @a1.platform = 'powerpc-darwin'
+    assert_equal Gem::Platform.new('ppc-darwin'), @a1.platform
+  end
+
+  def test_prerelease_spec_adds_required_rubygems_version
+    @prerelease = quick_gem('tardis', '2.2.0.a')
+    refute @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.3.1'))
+    assert @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.4.0'))
+  end
+
+  def test_require_paths
+    @a1.require_path = 'lib'
+    assert_equal %w[lib], @a1.require_paths
+  end
+
+  def test_requirements
+    assert_equal ['A working computer'], @a1.requirements
+  end
+
+  def test_runtime_dependencies_legacy
+    # legacy gems don't have a type
+    @a1.runtime_dependencies.each do |dep|
+      dep.instance_variable_set :@type, nil
+    end
+
+    expected = %w[rake jabber4r pqa]
+
+    assert_equal expected, @a1.runtime_dependencies.map { |d| d.name }
+  end
+
+  def test_spaceship_name
+    s1 = quick_gem 'a', '1'
+    s2 = quick_gem 'b', '1'
+
+    assert_equal(-1, (s1 <=> s2))
+    assert_equal( 0, (s1 <=> s1))
+    assert_equal( 1, (s2 <=> s1))
+  end
+
+  def test_spaceship_platform
+    s1 = quick_gem 'a', '1'
+    s2 = quick_gem 'a', '1' do |s|
+      s.platform = Gem::Platform.new 'x86-my_platform1'
+    end
+
+    assert_equal( -1, (s1 <=> s2))
+    assert_equal(  0, (s1 <=> s1))
+    assert_equal(  1, (s2 <=> s1))
+  end
+
+  def test_spaceship_version
+    s1 = quick_gem 'a', '1'
+    s2 = quick_gem 'a', '2'
+
+    assert_equal( -1, (s1 <=> s2))
+    assert_equal(  0, (s1 <=> s1))
+    assert_equal(  1, (s2 <=> s1))
+  end
+
+  def test_spec_name
+    assert_equal 'a-1.gemspec', @a1.spec_name
+  end
+
+  def test_summary
+    assert_equal 'this is a summary', @a1.summary
+  end
+
+  def test_test_files
+    @a1.test_file = 'test/suite.rb'
+    assert_equal ['test/suite.rb'], @a1.test_files
+  end
+
+  def test_to_ruby
+    @a2.add_runtime_dependency 'b', '1'
+    @a2.dependencies.first.instance_variable_set :@type, nil
+    @a2.required_rubygems_version = Gem::Requirement.new '> 0'
+
+    ruby_code = @a2.to_ruby
+
+    expected = <<-SPEC
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+  s.name = %q{a}
+  s.version = \"2\"
+
+  s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version=
+  s.authors = [\"A User\"]
+  s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
+  s.description = %q{This is a test description}
+  s.email = %q{example at example.com}
+  s.files = [\"lib/code.rb\"]
+  s.homepage = %q{http://example.com}
+  s.require_paths = [\"lib\"]
+  s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
+  s.summary = %q{this is a summary}
+
+  if s.respond_to? :specification_version then
+    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+    s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
+
+    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+      s.add_runtime_dependency(%q<b>, [\"= 1\"])
+    else
+      s.add_dependency(%q<b>, [\"= 1\"])
+    end
+  else
+    s.add_dependency(%q<b>, [\"= 1\"])
+  end
+end
+    SPEC
+
+    assert_equal expected, ruby_code
+
+    same_spec = eval ruby_code
+
+    assert_equal @a2, same_spec
+  end
+
+  def test_to_ruby_fancy
+    @a1.platform = Gem::Platform.local
+    ruby_code = @a1.to_ruby
+
+    local = Gem::Platform.local
+    expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
+
+    expected = <<-SPEC
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+  s.name = %q{a}
+  s.version = \"1\"
+  s.platform = Gem::Platform.new(#{expected_platform})
+
+  s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=
+  s.authors = [\"A User\"]
+  s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
+  s.default_executable = %q{exec}
+  s.description = %q{This is a test description}
+  s.email = %q{example at example.com}
+  s.executables = [\"exec\"]
+  s.extensions = [\"ext/a/extconf.rb\"]
+  s.files = [\"lib/code.rb\", \"test/suite.rb\", \"bin/exec\", \"ext/a/extconf.rb\"]
+  s.homepage = %q{http://example.com}
+  s.licenses = [\"MIT\"]
+  s.require_paths = [\"lib\"]
+  s.requirements = [\"A working computer\"]
+  s.rubyforge_project = %q{example}
+  s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
+  s.summary = %q{this is a summary}
+  s.test_files = [\"test/suite.rb\"]
+
+  if s.respond_to? :specification_version then
+    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+    s.specification_version = 3
+
+    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+      s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
+      s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
+      s.add_runtime_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
+    else
+      s.add_dependency(%q<rake>, [\"> 0.4\"])
+      s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
+      s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
+    end
+  else
+    s.add_dependency(%q<rake>, [\"> 0.4\"])
+    s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
+    s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
+  end
+end
+    SPEC
+
+    assert_equal expected, ruby_code
+
+    same_spec = eval ruby_code
+
+    assert_equal @a1, same_spec
+  end
+
+  def test_to_ruby_legacy
+    gemspec1 = eval LEGACY_RUBY_SPEC
+    ruby_code = gemspec1.to_ruby
+    gemspec2 = eval ruby_code
+
+    assert_equal gemspec1, gemspec2
+  end
+
+  def test_to_ruby_platform
+    @a2.platform = Gem::Platform.local
+    @a2.instance_variable_set :@original_platform, 'old_platform'
+
+    ruby_code = @a2.to_ruby
+
+    same_spec = eval ruby_code
+
+    assert_equal 'old_platform', same_spec.original_platform
+  end
+
+  def test_to_yaml
+    yaml_str = @a1.to_yaml
+    same_spec = YAML.load(yaml_str)
+
+    assert_equal @a1, same_spec
+  end
+
+  def test_to_yaml_fancy
+    @a1.platform = Gem::Platform.local
+    yaml_str = @a1.to_yaml
+
+    same_spec = YAML.load(yaml_str)
+
+    assert_equal Gem::Platform.local, same_spec.platform
+
+    assert_equal @a1, same_spec
+  end
+
+  def test_to_yaml_platform_empty_string
+    @a1.instance_variable_set :@original_platform, ''
+
+    assert_match %r|^platform: ruby$|, @a1.to_yaml
+  end
+
+  def test_to_yaml_platform_legacy
+    @a1.platform = 'powerpc-darwin7.9.0'
+    @a1.instance_variable_set :@original_platform, 'powerpc-darwin7.9.0'
+
+    yaml_str = @a1.to_yaml
+
+    same_spec = YAML.load(yaml_str)
+
+    assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform
+    assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform
+  end
+
+  def test_to_yaml_platform_nil
+    @a1.instance_variable_set :@original_platform, nil
+
+    assert_match %r|^platform: ruby$|, @a1.to_yaml
+  end
+
+  def test_validate
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      assert @a1.validate
+    end
+  end
+
+  def test_validate_authors
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.authors = []
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no author specified\n", @ui.error, 'error'
+
+      @a1.authors = [Object.new]
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal 'authors must be Array of Strings', e.message
+
+      @a1.authors = ['FIXME (who is writing this software)']
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not an author', e.message
+
+      @a1.authors = ['TODO (who is writing this software)']
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not an author', e.message
+    end
+  end
+
+  def test_validate_autorequire
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.autorequire = 'code'
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  deprecated autorequire specified\n",
+                   @ui.error, 'error'
+    end
+  end
+
+  def test_validate_description
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.description = ''
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no description specified\n", @ui.error, 'error'
+
+      @ui = MockGemUi.new
+      @a1.summary = 'this is my summary'
+      @a1.description = @a1.summary
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  description and summary are identical\n",
+                   @ui.error, 'error'
+
+      @a1.description = 'FIXME (describe your package)'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not a description', e.message
+
+      @a1.description = 'TODO (describe your package)'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not a description', e.message
+    end
+  end
+
+  def test_validate_email
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.email = ''
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no email specified\n", @ui.error, 'error'
+
+      @a1.email = 'FIXME (your e-mail)'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not an email address', e.message
+
+      @a1.email = 'TODO (your e-mail)'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not an email address', e.message
+    end
+  end
+
+  def test_validate_empty
+    util_setup_validate
+
+    e = assert_raises Gem::InvalidSpecificationException do
+      Gem::Specification.new.validate
+    end
+
+    assert_equal 'missing value for attribute name', e.message
+  end
+
+  def test_validate_executables
+    util_setup_validate
+
+    FileUtils.mkdir_p File.join(@tempdir, 'bin')
+    File.open File.join(@tempdir, 'bin', 'exec'), 'w' do end
+    FileUtils.mkdir_p File.join(@tempdir, 'exec')
+
+    use_ui @ui do
+      Dir.chdir @tempdir do
+        assert @a1.validate
+      end
+    end
+
+    assert_equal %w[exec], @a1.executables
+
+    assert_equal '', @ui.output, 'output'
+    assert_equal "WARNING:  bin/exec is missing #! line\n", @ui.error, 'error'
+  end
+
+  def test_validate_empty_require_paths
+    if win_platform? then
+      skip 'test_validate_empty_require_paths skipped on MS Windows (symlink)'
+    else
+      util_setup_validate
+
+      @a1.require_paths = []
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal 'specification must have at least one require_path',
+                   e.message
+    end
+  end
+
+  def test_validate_files
+    skip 'test_validate_files skipped on MS Windows (symlink)' if win_platform?
+    util_setup_validate
+
+    @a1.files += ['lib', 'lib2']
+
+    Dir.chdir @tempdir do
+      FileUtils.ln_s '/root/path', 'lib2' unless vc_windows?
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '["lib2"] are not files', e.message
+    end
+
+    assert_equal %w[lib/code.rb test/suite.rb bin/exec ext/a/extconf.rb lib2],
+                 @a1.files
+  end
+
+  def test_validate_homepage
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.homepage = nil
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no homepage specified\n", @ui.error, 'error'
+
+      @ui = MockGemUi.new
+
+      @a1.homepage = ''
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no homepage specified\n", @ui.error, 'error'
+
+      @a1.homepage = 'over at my cool site'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"over at my cool site" is not a URI', e.message
+    end
+  end
+
+  def test_validate_name
+    util_setup_validate
+
+    e = assert_raises Gem::InvalidSpecificationException do
+      @a1.name = :json
+      @a1.validate
+    end
+
+    assert_equal 'invalid value for attribute name: ":json"', e.message
+  end
+
+  def test_validate_platform_legacy
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.platform = 'mswin32'
+      assert @a1.validate
+
+      @a1.platform = 'i586-linux'
+      assert @a1.validate
+
+      @a1.platform = 'powerpc-darwin'
+      assert @a1.validate
+    end
+  end
+
+  def test_validate_rubyforge_project
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.rubyforge_project = ''
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no rubyforge_project specified\n",
+                   @ui.error, 'error'
+    end
+  end
+
+  def test_validate_rubygems_version
+    util_setup_validate
+
+    @a1.rubygems_version = "3"
+    e = assert_raises Gem::InvalidSpecificationException do
+      @a1.validate
+    end
+
+    assert_equal "expected RubyGems version #{Gem::RubyGemsVersion}, was 3",
+                 e.message
+  end
+
+  def test_validate_specification_version
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.specification_version = '1.0'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        use_ui @ui do
+          @a1.validate
+        end
+      end
+
+      err = 'specification_version must be a Fixnum (did you mean version?)'
+      assert_equal err, e.message
+    end
+  end
+
+  def test_validate_summary
+    util_setup_validate
+
+    Dir.chdir @tempdir do
+      @a1.summary = ''
+
+      use_ui @ui do
+        @a1.validate
+      end
+
+      assert_equal "WARNING:  no summary specified\n", @ui.error, 'error'
+
+      @a1.summary = 'FIXME (describe your package)'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not a summary', e.message
+
+      @a1.summary = 'TODO (describe your package)'
+
+      e = assert_raises Gem::InvalidSpecificationException do
+        @a1.validate
+      end
+
+      assert_equal '"FIXME" or "TODO" is not a summary', e.message
+    end
+  end
+
+  def test_version
+    assert_equal Gem::Version.new('1'), @a1.version
+  end
+
+  def util_setup_validate
+    Dir.chdir @tempdir do
+      FileUtils.mkdir_p File.join('ext', 'a')
+      FileUtils.mkdir_p 'lib'
+      FileUtils.mkdir_p 'test'
+
+      FileUtils.touch File.join('ext', 'a', 'extconf.rb')
+      FileUtils.touch File.join('lib', 'code.rb')
+      FileUtils.touch File.join('test', 'suite.rb')
+    end
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_stream_ui.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_stream_ui.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_stream_ui.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,116 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/user_interaction'
+
+class TestGemStreamUI < RubyGemTestCase
+
+  module IsTty
+    attr_accessor :tty
+
+    def tty?
+      @tty = true unless defined? @tty
+      return @tty
+    end
+
+    alias_method :isatty, :tty?
+  end
+
+  def setup
+    super
+
+    @cfg = Gem.configuration
+
+    @in = StringIO.new
+    @out = StringIO.new
+    @err = StringIO.new
+
+    @in.extend IsTty
+
+    @sui = Gem::StreamUI.new @in, @out, @err
+  end
+
+  def test_ask
+    timeout(1) do
+      expected_answer = "Arthur, King of the Britons"
+      @in.string = "#{expected_answer}\n"
+      actual_answer = @sui.ask("What is your name?")
+      assert_equal expected_answer, actual_answer
+    end
+  end
+
+  def test_ask_no_tty
+    @in.tty = false
+
+    timeout(0.1) do
+      answer = @sui.ask("what is your favorite color?")
+      assert_equal nil, answer
+    end
+  end
+
+  def test_ask_yes_no_no_tty_with_default
+    @in.tty = false
+
+    timeout(0.1) do
+      answer = @sui.ask_yes_no("do coconuts migrate?", false)
+      assert_equal false, answer
+
+      answer = @sui.ask_yes_no("do coconuts migrate?", true)
+      assert_equal true, answer
+    end
+  end
+
+  def test_ask_yes_no_no_tty_without_default
+    @in.tty = false
+
+    timeout(0.1) do
+      assert_raises(Gem::OperationNotSupportedError) do
+        @sui.ask_yes_no("do coconuts migrate?")
+      end
+    end
+  end
+
+  def test_choose_from_list
+    @in.puts "1"
+    @in.rewind
+
+    result = @sui.choose_from_list 'which one?', %w[foo bar]
+
+    assert_equal ['foo', 0], result
+    assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string
+  end
+
+  def test_choose_from_list_EOF
+    result = @sui.choose_from_list 'which one?', %w[foo bar]
+
+    assert_equal [nil, nil], result
+    assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string
+  end
+
+  def test_proress_reporter_silent_nil
+    @cfg.verbose = nil
+    reporter = @sui.progress_reporter 10, 'hi'
+    assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter
+  end
+
+  def test_proress_reporter_silent_false
+    @cfg.verbose = false
+    reporter = @sui.progress_reporter 10, 'hi'
+    assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter
+    assert_equal "", @out.string
+  end
+
+  def test_proress_reporter_simple
+    @cfg.verbose = true
+    reporter = @sui.progress_reporter 10, 'hi'
+    assert_kind_of Gem::StreamUI::SimpleProgressReporter, reporter
+    assert_equal "hi\n", @out.string
+  end
+
+  def test_proress_reporter_verbose
+    @cfg.verbose = 0
+    reporter = @sui.progress_reporter 10, 'hi'
+    assert_kind_of Gem::StreamUI::VerboseProgressReporter, reporter
+    assert_equal "hi\n", @out.string
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_uninstaller.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_uninstaller.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_uninstaller.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,147 @@
+require File.join(File.expand_path(File.dirname(__FILE__)),
+                  'gem_installer_test_case')
+require 'rubygems/uninstaller'
+
+class TestGemUninstaller < GemInstallerTestCase
+
+  def setup
+    super
+
+    ui = MockGemUi.new
+    util_setup_gem ui
+
+    @user_spec.executables = ["my_exec"]
+
+    # HACK util_make_exec
+    user_bin_dir = File.join Gem.user_dir, 'gems', @user_spec.full_name, 'bin'
+    FileUtils.mkdir_p user_bin_dir
+    exec_path = File.join user_bin_dir, "my_exec"
+    File.open exec_path, 'w' do |f|
+      f.puts "#!/usr/bin/ruby"
+    end
+
+    user_bin_dir = File.join Gem.user_dir, 'bin'
+    FileUtils.mkdir_p user_bin_dir
+    exec_path = File.join user_bin_dir, "my_exec"
+    File.open exec_path, 'w' do |f|
+      f.puts "#!/usr/bin/ruby"
+    end
+
+    build_rake_in do
+      use_ui ui do
+        @installer.install
+        @user_installer.install
+        Gem::Uninstaller.new(@user_spec.name, :executables => false).uninstall
+      end
+    end
+  end
+
+  def test_initialize_expand_path
+    uninstaller = Gem::Uninstaller.new nil, :install_dir => '/foo//bar'
+
+    assert_match %r|/foo/bar$|, uninstaller.instance_variable_get(:@gem_home)
+  end
+
+  def test_remove_executables_force_keep
+    uninstaller = Gem::Uninstaller.new nil, :executables => false
+
+    use_ui @ui do
+      uninstaller.remove_executables @spec
+    end
+
+    assert_equal true, File.exist?(File.join(@gemhome, 'bin', 'executable'))
+
+    assert_equal "Executables and scripts will remain installed.\n", @ui.output
+  end
+
+  def test_remove_executables_force_remove
+    uninstaller = Gem::Uninstaller.new nil, :executables => true
+
+    use_ui @ui do
+      uninstaller.remove_executables @spec
+    end
+
+    assert_equal "Removing executable\n", @ui.output
+
+    assert_equal false, File.exist?(File.join(@gemhome, 'bin', 'executable'))
+  end
+
+  def test_remove_executables_user
+    uninstaller = Gem::Uninstaller.new nil, :executables => true
+
+    use_ui @ui do
+      uninstaller.remove_executables @user_spec
+    end
+
+    exec_path = File.join Gem.user_dir, 'bin', 'my_exec'
+    assert_equal false, File.exist?(exec_path), 'removed exec from bin dir'
+
+    assert_equal "Removing my_exec\n", @ui.output
+  end
+
+  def test_path_ok_eh
+    uninstaller = Gem::Uninstaller.new nil
+
+    assert_equal true, uninstaller.path_ok?(@gemhome, @spec)
+  end
+
+  def test_path_ok_eh_legacy
+    uninstaller = Gem::Uninstaller.new nil
+
+    @spec.loaded_from.gsub! @spec.full_name, '\&-legacy'
+    @spec.platform = 'legacy'
+
+    assert_equal true, uninstaller.path_ok?(@gemhome, @spec)
+  end
+
+  def test_path_ok_eh_user
+    uninstaller = Gem::Uninstaller.new nil
+
+    assert_equal true, uninstaller.path_ok?(Gem.user_dir, @user_spec)
+  end
+
+  def test_uninstall
+    uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+
+    gem_dir = File.join @gemhome, 'gems', @spec.full_name
+
+    Gem.pre_uninstall do
+      assert File.exist?(gem_dir), 'gem_dir should exist'
+    end
+
+    Gem.post_uninstall do
+      refute File.exist?(gem_dir), 'gem_dir should not exist'
+    end
+
+    uninstaller.uninstall
+
+    refute File.exist?(gem_dir)
+
+    assert_same uninstaller, @pre_uninstall_hook_arg
+    assert_same uninstaller, @post_uninstall_hook_arg
+  end
+
+  def test_uninstall_user
+    uninstaller = Gem::Uninstaller.new @user_spec.name, :executables => true,
+                  :user_install => true
+
+    gem_dir = File.join Gem.user_dir, 'gems', @user_spec.full_name
+
+    Gem.pre_uninstall do
+      assert File.exist?(gem_dir), 'gem_dir should exist'
+    end
+
+    Gem.post_uninstall do
+      refute File.exist?(gem_dir), 'gem_dir should not exist'
+    end
+
+    uninstaller.uninstall
+
+    refute File.exist?(gem_dir)
+
+    assert_same uninstaller, @pre_uninstall_hook_arg
+    assert_same uninstaller, @post_uninstall_hook_arg
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_validator.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_validator.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_validator.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,69 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem')
+require 'rubygems/validator'
+
+class TestGemValidator < RubyGemTestCase
+
+  def setup
+    super
+
+    @simple_gem = SIMPLE_GEM
+    @validator = Gem::Validator.new
+  end
+
+  def test_verify_gem_file
+    gem_file = File.join @tempdir, 'simple_gem.gem'
+    File.open gem_file, 'wb' do |fp| fp.write @simple_gem end
+
+    assert_equal nil, @validator.verify_gem_file(gem_file)
+  end
+
+  def test_verify_gem_file_empty
+    e = assert_raises Gem::VerificationError do
+      @validator.verify_gem_file ''
+    end
+
+    assert_equal 'missing gem file ', e.message
+  end
+
+  def test_verify_gem_file_nonexistent
+    file = '/nonexistent/nonexistent.gem'
+    e = assert_raises Gem::VerificationError do
+      @validator.verify_gem_file file
+    end
+
+    assert_equal "missing gem file #{file}", e.message
+  end
+
+  def test_verify_gem
+    assert_equal nil, @validator.verify_gem(@simple_gem)
+  end
+
+  def test_verify_gem_empty
+    e = assert_raises Gem::VerificationError do
+      @validator.verify_gem ''
+    end
+
+    assert_equal 'empty gem file', e.message
+  end
+
+  def test_verify_gem_invalid_checksum
+    e = assert_raises Gem::VerificationError do
+      @validator.verify_gem @simple_gem.upcase
+    end
+
+    assert_equal 'invalid checksum for gem file', e.message
+  end
+
+  def test_verify_gem_no_sum
+    assert_equal nil, @validator.verify_gem('words')
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_version.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_version.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_version.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,175 @@
+require "minitest/autorun"
+require "rubygems/version"
+
+class TestGemVersion < MiniTest::Unit::TestCase
+  def test_bump
+    assert_bumped_version_equal "5.3", "5.2.4"
+  end
+
+  def test_bump_alpha
+    assert_bumped_version_equal "5.3", "5.2.4.a"
+  end
+
+  def test_bump_trailing_zeros
+    assert_bumped_version_equal "5.1", "5.0.0"
+  end
+
+  def test_bump_one_level
+    assert_bumped_version_equal "6", "5"
+  end
+
+  # FIX: For "legacy reasons," any object that responds to +version+
+  # is returned unchanged. I'm not certain why.
+
+  def test_class_create
+    fake = Object.new
+    def fake.version; "1.0" end
+
+    assert_same  fake, Gem::Version.create(fake)
+    assert_nil   Gem::Version.create(nil)
+    assert_equal v("5.1"), Gem::Version.create("5.1")
+  end
+
+  def test_eql_eh
+    assert_version_eql "1.2", "1.2"
+    refute_version_eql "1.2", "1.2.0"
+    refute_version_eql "1.2", "1.3"
+  end
+
+  def test_equals
+    assert_version_equal "1.2", "1.2"
+    refute_version_equal "1.2", "1.3"
+  end
+
+  # REVISIT: consider removing as too impl-bound
+  def test_hash
+    assert_equal v("1.2").hash, v("1.2").hash
+    refute_equal v("1.2").hash, v("1.3").hash
+    refute_equal v("1.2").hash, v("1.2.0").hash
+  end
+
+  def test_initialize
+    ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n"].each do |good|
+      assert_version_equal "1.0", good
+    end
+
+    assert_version_equal "1", 1
+  end
+
+  def test_initialize_bad
+    ["junk", "1.0\n2.0"].each do |bad|
+      e = assert_raises ArgumentError do
+        Gem::Version.new bad
+      end
+
+      assert_equal "Malformed version number string #{bad}", e.message
+    end
+  end
+
+  def test_prerelease
+    assert_prerelease "1.2.0.a"
+    assert_prerelease "2.9.b"
+    assert_prerelease "22.1.50.0.d"
+    assert_prerelease "1.2.d.42"
+
+    refute_prerelease "1.2.0"
+    refute_prerelease "2.9"
+    refute_prerelease "22.1.50.0"
+  end
+
+  def test_release
+    assert_release_equal "1.2.0", "1.2.0.a"
+    assert_release_equal "1.1",   "1.1.rc10"
+    assert_release_equal "1.9.3", "1.9.3.alpha.5"
+    assert_release_equal "1.9.3", "1.9.3"
+  end
+
+  def test_spaceship
+    assert_equal( 0, v("1.0")     <=> v("1.0.0"))
+    assert_equal( 1, v("1.0")     <=> v("1.0.a"))
+    assert_equal( 1, v("1.8.2")   <=> v("0.0.0"))
+    assert_equal( 1, v("1.8.2")   <=> v("1.8.2.a"))
+    assert_equal( 1, v("1.8.2.b") <=> v("1.8.2.a"))
+    assert_equal(-1, v("1.8.2.a") <=> v("1.8.2"))
+    assert_equal( 0, v("")        <=> v("0"))
+  end
+
+  def test_spermy_recommendation
+    assert_spermy_equal "~> 1.0", "1"
+    assert_spermy_equal "~> 1.0", "1.0"
+    assert_spermy_equal "~> 1.2", "1.2"
+    assert_spermy_equal "~> 1.2", "1.2.0"
+    assert_spermy_equal "~> 1.2", "1.2.3"
+    assert_spermy_equal "~> 1.2", "1.2.3.a.4"
+  end
+
+  def test_to_s
+    assert_equal "5.2.4", v("5.2.4").to_s
+  end
+
+  # Asserts that +version+ is a prerelease.
+
+  def assert_prerelease version
+    assert v(version).prerelease?, "#{version} is a prerelease"
+  end
+
+  # Assert that +expected+ is the "spermy" recommendation for +version".
+
+  def assert_spermy_equal expected, version
+    assert_equal expected, v(version).spermy_recommendation
+  end
+
+  # Assert that bumping the +unbumped+ version yields the +expected+.
+
+  def assert_bumped_version_equal expected, unbumped
+    assert_version_equal expected, v(unbumped).bump
+  end
+
+  # Assert that +release+ is the correct non-prerelease +version+.
+
+  def assert_release_equal release, version
+    assert_version_equal release, v(version).release
+  end
+
+  # Assert that two versions are equal. Handles strings or
+  # Gem::Version instances.
+
+  def assert_version_equal expected, actual
+    assert_equal v(expected), v(actual)
+  end
+
+  # Assert that two versions are eql?. Checks both directions.
+
+  def assert_version_eql first, second
+    first, second = v(first), v(second)
+    assert first.eql?(second), "#{first} is eql? #{second}"
+    assert second.eql?(first), "#{second} is eql? #{first}"
+  end
+
+  # Refute the assumption that +version+ is a prerelease.
+
+  def refute_prerelease version
+    refute v(version).prerelease?, "#{version} is NOT a prerelease"
+  end
+
+  # Refute the assumption that two versions are eql?. Checks both
+  # directions.
+
+  def refute_version_eql first, second
+    first, second = v(first), v(second)
+    refute first.eql?(second), "#{first} is NOT eql? #{second}"
+    refute second.eql?(first), "#{second} is NOT eql? #{first}"
+  end
+
+  # Refute the assumption that the two versions are equal?.
+
+  def refute_version_equal unexpected, actual
+    refute_equal v(unexpected), v(actual)
+  end
+
+  # Construct a new Gem::Version from +string+. Convenience method.
+
+  def v string
+    Gem::Version.create string
+  end
+end

Added: MacRuby/trunk/test/libs/rubygems/test/test_gem_version_option.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_gem_version_option.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_gem_version_option.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,89 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/command'
+require 'rubygems/version_option'
+
+class TestGemVersionOption < RubyGemTestCase
+
+  def setup
+    super
+
+    @cmd = Gem::Command.new 'dummy', 'dummy'
+    @cmd.extend Gem::VersionOption
+  end
+
+  def test_add_platform_option
+    @cmd.add_platform_option
+
+    assert @cmd.handles?(%w[--platform x86-darwin])
+  end
+
+  def test_add_version_option
+    @cmd.add_version_option
+
+    assert @cmd.handles?(%w[--version >1])
+  end
+
+  def test_enables_prerelease
+    @cmd.add_version_option
+
+    @cmd.handle_options %w[mygem -v 0.2.0.a]
+    assert @cmd.options[:prerelease]
+
+    @cmd.handle_options %w[mygem -v 0.2.0]
+    refute @cmd.options[:prerelease]
+
+    @cmd.handle_options %w[mygem]
+    refute @cmd.options[:prerelease]
+  end
+
+  def test_platform_option
+    @cmd.add_platform_option
+
+    @cmd.handle_options %w[--platform x86-freebsd6 --platform x86-freebsd7]
+
+    expected = [
+      Gem::Platform::RUBY,
+      Gem::Platform.new('x86-freebsd6'),
+      Gem::Platform.new('x86-freebsd7'),
+    ]
+
+    assert_equal expected, Gem.platforms
+  end
+
+  def test_platform_option_ruby
+    @cmd.add_platform_option
+
+    @cmd.handle_options %w[--platform ruby]
+
+    expected = [
+      Gem::Platform::RUBY
+    ]
+
+    assert_equal expected, Gem.platforms
+  end
+
+  def test_platform_option_twice
+    @cmd.add_platform_option
+
+    @cmd.handle_options %w[--platform x86-freebsd6 --platform x86-freebsd-6]
+
+    expected = [
+      Gem::Platform::RUBY,
+      Gem::Platform.new('x86-freebsd6'),
+    ]
+
+    assert_equal expected, Gem.platforms
+  end
+
+  def test_version_option
+    @cmd.add_version_option
+
+    @cmd.handle_options %w[--version >1]
+
+    expected = { :version => Gem::Requirement.new('> 1'), :args => [] }
+
+    assert_equal expected, @cmd.options
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/test/test_kernel.rb
===================================================================
--- MacRuby/trunk/test/libs/rubygems/test/test_kernel.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/test/test_kernel.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,65 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/package'
+
+class TestKernel < RubyGemTestCase
+
+  def setup
+    super
+
+    @old_path = $:.dup
+
+    util_make_gems
+  end
+
+  def teardown
+    super
+
+    $:.replace @old_path
+  end
+
+  def test_gem
+    assert gem('a', '= 1'), "Should load"
+    assert $:.any? { |p| %r{a-1/lib} =~ p }
+    assert $:.any? { |p| %r{a-1/bin} =~ p }
+  end
+
+  def test_gem_redundent
+    assert gem('a', '= 1'), "Should load"
+    refute gem('a', '= 1'), "Should not load"
+    assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size
+    assert_equal 1, $:.select { |p| %r{a-1/bin} =~ p }.size
+  end
+
+  def test_gem_overlapping
+    assert gem('a', '= 1'), "Should load"
+    refute gem('a', '>= 1'), "Should not load"
+    assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size
+    assert_equal 1, $:.select { |p| %r{a-1/bin} =~ p }.size
+  end
+
+  def test_gem_conflicting
+    assert gem('a', '= 1'), "Should load"
+
+    ex = assert_raises Gem::LoadError do
+      gem 'a', '= 2'
+    end
+
+    assert_match(/activate a \(= 2, runtime\)/, ex.message)
+    assert_match(/activated a-1/, ex.message)
+    assert_equal 'a', ex.name
+    assert_equal Gem::Requirement.new('= 2'), ex.version_requirement
+
+    assert $:.any? { |p| %r{a-1/lib} =~ p }
+    assert $:.any? { |p| %r{a-1/bin} =~ p }
+    refute $:.any? { |p| %r{a-2/lib} =~ p }
+    refute $:.any? { |p| %r{a-2/bin} =~ p }
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/rubygems/util/CL2notes
===================================================================
--- MacRuby/trunk/test/libs/rubygems/util/CL2notes	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/util/CL2notes	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,56 @@
+#!/usr/bin/env ruby
+
+$:.unshift 'lib'
+
+require 'rubygems'
+
+def format_text(text, wrap, indent=0)
+  result = []
+  work = text.dup
+
+  while work.length > wrap
+    if work =~ /^(.{0,#{wrap}})[ \n]/o then
+      result << $1
+      work.slice!(0, $&.length)
+    else
+      result << work.slice!(0, wrap)
+    end
+  end
+
+  result << work if work.length.nonzero?
+  result.join("\n").gsub(/^/, " " * indent)
+end
+
+version = ARGV.shift || Gem::RubyGemsVersion
+
+entries = Hash.new { |h,file| h[file] = [] }
+entry = []
+file = nil
+
+IO.foreach 'ChangeLog' do |line|
+  case line
+  when /^\s*$/,
+       /^#/,
+       /^\d{4}-\d{2}-\d{2}/ then
+    next
+  when /^\s+\*\s+([^:]+?):\s+#{version}/ then
+    entries[file] << entry.join(' ') unless entry.empty?
+    break
+  when /^\s+\*\s+([^:]+?):\s+/ then
+    entries[file] << entry.join(' ') unless entry.empty?
+    file = $1
+    entry = [$'.strip]
+  when /^\s+/ then
+    entry << $'.strip
+  end
+end
+
+entries.sort_by { |file, | file }.each do |file, file_entries|
+  puts "* #{file}"
+  file_entries.each do |file_entry|
+    file_entry = format_text file_entry, 74, 4
+    file_entry.sub! '    ', '  * '
+    puts file_entry
+  end
+end
+


Property changes on: MacRuby/trunk/test/libs/rubygems/util/CL2notes
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/rubygems/util/gem_prelude.rb.template
===================================================================
--- MacRuby/trunk/test/libs/rubygems/util/gem_prelude.rb.template	                        (rev 0)
+++ MacRuby/trunk/test/libs/rubygems/util/gem_prelude.rb.template	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,274 @@
+# depends on: array.rb dir.rb env.rb file.rb hash.rb module.rb regexp.rb
+# vim: filetype=ruby
+# WARN
+
+# NOTICE: Ruby is during initialization here.
+# * Encoding.default_external does not reflects -E.
+# * Should not expect Encoding.default_internal.
+# * Locale encoding is available.
+
+if defined?(Gem) then
+
+  # :stopdoc:
+
+  module Kernel
+
+    def gem(gem_name, *version_requirements)
+      Gem.push_gem_version_on_load_path(gem_name, *version_requirements)
+    end
+
+  end
+
+  module Gem
+
+    ConfigMap = {
+      :EXEEXT            => RbConfig::CONFIG["EXEEXT"],
+      :RUBY_SO_NAME      => RbConfig::CONFIG["RUBY_SO_NAME"],
+      :arch              => RbConfig::CONFIG["arch"],
+      :bindir            => RbConfig::CONFIG["bindir"],
+      :libdir            => RbConfig::CONFIG["libdir"],
+      :ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
+      :ruby_version      => RbConfig::CONFIG["ruby_version"],
+      :rubylibprefix     => RbConfig::CONFIG["rubylibprefix"],
+      :sitedir           => RbConfig::CONFIG["sitedir"],
+      :sitelibdir        => RbConfig::CONFIG["sitelibdir"],
+    }
+
+    def self.dir
+      @gem_home ||= nil
+      set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
+      @gem_home
+    end
+
+    def self.path
+      @gem_path ||= nil
+      unless @gem_path
+        paths = [ENV['GEM_PATH']]
+        paths << APPLE_GEM_HOME if defined? APPLE_GEM_HOME
+        set_paths(paths.compact.join(File::PATH_SEPARATOR))
+      end
+      @gem_path
+    end
+
+    def self.post_install(&hook)
+      @post_install_hooks << hook
+    end
+
+    def self.post_uninstall(&hook)
+      @post_uninstall_hooks << hook
+    end
+
+    def self.pre_install(&hook)
+      @pre_install_hooks << hook
+    end
+
+    def self.pre_uninstall(&hook)
+      @pre_uninstall_hooks << hook
+    end
+
+    def self.set_home(home)
+      home = home.gsub File::ALT_SEPARATOR, File::SEPARATOR if File::ALT_SEPARATOR
+      @gem_home = home
+    end
+
+    def self.set_paths(gpaths)
+      if gpaths
+        @gem_path = gpaths.split(File::PATH_SEPARATOR)
+
+        if File::ALT_SEPARATOR then
+          @gem_path.map! do |path|
+            path.gsub File::ALT_SEPARATOR, File::SEPARATOR
+          end
+        end
+
+        @gem_path << Gem.dir
+      else
+        # TODO: should this be Gem.default_path instead?
+        @gem_path = [Gem.dir]
+      end
+
+      @gem_path.uniq!
+    end
+
+    # INCLUDE rubygems/defaults
+
+    ##
+    # Methods before this line will be removed when QuickLoader is replaced
+    # with the real RubyGems
+
+    GEM_PRELUDE_METHODS = Gem.methods(false)
+
+    begin
+      verbose, debug = $VERBOSE, $DEBUG
+      $VERBOSE = $DEBUG = nil
+
+      begin
+        require 'rubygems/defaults/operating_system'
+      rescue ::LoadError
+      end
+
+      if defined?(RUBY_ENGINE) then
+        begin
+          require "rubygems/defaults/#{RUBY_ENGINE}"
+        rescue ::LoadError
+        end
+      end
+    ensure
+      $VERBOSE, $DEBUG = verbose, debug
+    end
+
+    module QuickLoader
+
+      @loaded_full_rubygems_library = false
+
+      def self.load_full_rubygems_library
+        return if @loaded_full_rubygems_library
+
+        @loaded_full_rubygems_library = true
+
+        class << Gem
+          Gem::GEM_PRELUDE_METHODS.each do |method_name|
+            undef_method method_name
+          end
+        end
+
+        Kernel.module_eval do
+          undef_method :gem if method_defined? :gem
+        end
+
+        $".delete File.join(Gem::ConfigMap[:rubylibprefix],
+                            Gem::ConfigMap[:ruby_version], 'rubygems.rb')
+
+        require 'rubygems'
+      end
+
+      GemPaths = {}
+      GemVersions = {}
+
+      def push_gem_version_on_load_path(gem_name, *version_requirements)
+        if version_requirements.empty?
+          unless GemPaths.has_key?(gem_name) then
+            raise Gem::LoadError, "Could not find RubyGem #{gem_name} (>= 0)\n"
+          end
+
+          # highest version gems already active
+          return false
+        else
+          if version_requirements.length > 1 then
+            QuickLoader.load_full_rubygems_library
+            return gem(gem_name, *version_requirements)
+          end
+
+          requirement, version = version_requirements[0].split
+          requirement.strip!
+
+          if loaded_version = GemVersions[gem_name] then
+            case requirement
+            when ">", ">=" then
+              return false if
+                (loaded_version <=> Gem.integers_for(version)) >= 0
+            when "~>" then
+              required_version = Gem.integers_for version
+
+              return false if loaded_version.first == required_version.first
+            end
+          end
+
+          QuickLoader.load_full_rubygems_library
+          gem gem_name, *version_requirements
+        end
+      end
+
+      def integers_for(gem_version)
+        numbers = gem_version.split(".").collect {|n| n.to_i}
+        numbers.pop while numbers.last == 0
+        numbers << 0 if numbers.empty?
+        numbers
+      end
+
+      def push_all_highest_version_gems_on_load_path
+        Gem.path.each do |path|
+          gems_directory = File.join(path, "gems")
+
+          if File.exist?(gems_directory) then
+            Dir.entries(gems_directory).each do |gem_directory_name|
+              next if gem_directory_name == "." || gem_directory_name == ".."
+
+              dash = gem_directory_name.rindex("-")
+              next if dash.nil?
+
+              gem_name = gem_directory_name[0...dash]
+              current_version = GemVersions[gem_name]
+              new_version = integers_for(gem_directory_name[dash+1..-1])
+
+              if current_version then
+                if (current_version <=> new_version) == -1 then
+                  GemVersions[gem_name] = new_version
+                  GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
+                end
+              else
+                GemVersions[gem_name] = new_version
+                GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
+              end
+            end
+          end
+        end
+
+        require_paths = []
+
+        GemPaths.each_value do |path|
+          if File.exist?(file = File.join(path, ".require_paths")) then
+            paths = File.read(file).split.map do |require_path|
+              File.join path, require_path
+            end
+
+            require_paths.concat paths
+          else
+            require_paths << file if File.exist?(file = File.join(path, "bin"))
+            require_paths << file if File.exist?(file = File.join(path, "lib"))
+          end
+        end
+
+        # "tag" the first require_path inserted into the $LOAD_PATH to enable
+        # indexing correctly with rubygems proper when it inserts an explicitly
+        # gem version
+        unless require_paths.empty? then
+          require_paths.first.instance_variable_set(:@gem_prelude_index, true)
+        end
+        # gem directories must come after -I and ENV['RUBYLIB']
+        $:[$:.index(ConfigMap[:sitelibdir]),0] = require_paths
+      end
+
+      def const_missing(constant)
+        QuickLoader.load_full_rubygems_library
+
+        if Gem.const_defined?(constant) then
+          Gem.const_get constant
+        else
+          super
+        end
+      end
+
+      def method_missing(method, *args, &block)
+        QuickLoader.load_full_rubygems_library
+        super unless Gem.respond_to?(method)
+        Gem.send(method, *args, &block)
+      end
+    end
+
+    extend QuickLoader
+
+  end
+
+  begin
+    Gem.push_all_highest_version_gems_on_load_path
+    $" << File.join(Gem::ConfigMap[:rubylibprefix],
+                    Gem::ConfigMap[:ruby_version], "rubygems.rb")
+  rescue Exception => e
+    puts "Error loading gem paths on load path in gem_prelude"
+    puts e
+    puts e.backtrace.join("\n")
+  end
+
+end
+

Added: MacRuby/trunk/test/libs/test-unit/History.txt
===================================================================
--- MacRuby/trunk/test/libs/test-unit/History.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/History.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,107 @@
+=== 2.0.3 / 2009-07-19
+
+* 6 major enhancements
+  * add assert_predicate.
+  * add assert_not_predicate.
+  * [#24210] assert_kind_of supports an array of classes or modules.
+    [Daniel Berger]
+  * assert_instance_of supports an array of classes or modules.
+  * add --default-priority option.
+  * [#26627] add --order option. [Daniel Berger]
+
+* 4 minor enhancements
+  * use yellow foreground + black background for error.
+  * don't show diff for long string.
+  * accept "*term-color" TERM environment as colorizable terminal.
+    (e.g. Apple's Terminal)
+  * [#26268] add a workaround for test-spec's after_all. [Angelo Lakra]
+
+* 1 bug fix
+  * [#23586] re-support ruby 1.9.1. [Diego Pettenò]
+
+* Thanks
+  * Diego Pettenò
+  * Daniel Berger
+  * Angelo Lakra
+
+=== 2.0.2 / 2008-12-21
+
+* 2 major enhancements
+
+  * re-support ruby 1.8.5.
+  * improve exception object comparison.
+
+* 3 bug fixes
+
+  * [#22723]: collector fails on anonymous classes
+  * [#22986]: Test names with '?' blow up on Windows
+  * [#22988]: don't create .test-result on non-priority mode.
+
+* Thanks
+
+  * Erik Hollensbe
+  * Daniel Berger
+  * Bill Lear
+
+=== 2.0.1 / 2008-11-09
+
+* 19 major enhancements
+
+  * support ruby 1.9.1.
+  * add run_test method to be extensible.
+  * improve priority-mode auto off.
+  * improve startup/shutdown RDoc. [Daniel Berger]
+  * add assert_compare. [#20851] [Designing Patterns]
+  * add assert_fail_assertion. [#20851] [Designing Patterns]
+  * add assert_raise_message. [#20851] [Designing Patterns]
+  * support folded diff.
+  * add assert_raise_kind_of. [Daniel Berger]
+  * ingore inherited test for nested test case.
+  * add assert_const_defined.
+  * add assert_not_const_defined.
+  * support assert_raise with an exception object.
+  * support assert_raise with no arguments that asserts any
+    exception is raised. [#22602] [Daniel Berger]
+  * support folded dot progress.
+  * add --progress-row-max option.
+  * support color scheme customize.
+  * support configuration file. (YAML)
+  * recognize test-XXX.rb files as test files not only test_XXX.rb
+
+* Thanks
+
+  * Daniel Berger
+  * Designing Patterns
+
+=== 2.0.0 / 2008-06-18
+
+* 15 major enhancements
+
+  * support startup/shutdown. (test case level setup/teardown)
+  * support multiple setup/teardown.
+  * support pending.
+  * support omission.
+  * support notification.
+  * support colorize.
+  * support diff.
+  * support test attribute.
+  * add assert_boolean.
+  * add assert_true.
+  * add assert_false.
+  * add --priority-mode option.
+  * don't use ObjectSpace to collect test cases.
+  * make more customizable. (additional options, exception handling and so on)
+  * improve Emacs integration.
+
+* 4 major changes
+
+  * remove GTK+1 support.
+  * split GTK+ runner as another gem.
+  * split FOX runner as another gem.
+  * split Tk runner as another gem.
+
+=== 1.2.3 / 2008-02-25
+
+* 1 major enhancement
+
+  * Birthday (as a gem)!

Added: MacRuby/trunk/test/libs/test-unit/Manifest.txt
===================================================================
--- MacRuby/trunk/test/libs/test-unit/Manifest.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/Manifest.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,82 @@
+History.txt
+Manifest.txt
+README.txt
+Rakefile
+TODO
+bin/testrb
+html/classic.html
+html/index.html
+html/index.html.ja
+html/test-unit-classic.png
+lib/test/unit.rb
+lib/test/unit/assertionfailederror.rb
+lib/test/unit/assertions.rb
+lib/test/unit/attribute.rb
+lib/test/unit/autorunner.rb
+lib/test/unit/collector.rb
+lib/test/unit/collector/descendant.rb
+lib/test/unit/collector/dir.rb
+lib/test/unit/collector/load.rb
+lib/test/unit/collector/objectspace.rb
+lib/test/unit/color-scheme.rb
+lib/test/unit/color.rb
+lib/test/unit/diff.rb
+lib/test/unit/error.rb
+lib/test/unit/exceptionhandler.rb
+lib/test/unit/failure.rb
+lib/test/unit/fixture.rb
+lib/test/unit/notification.rb
+lib/test/unit/omission.rb
+lib/test/unit/pending.rb
+lib/test/unit/priority.rb
+lib/test/unit/runner/console.rb
+lib/test/unit/runner/emacs.rb
+lib/test/unit/runner/tap.rb
+lib/test/unit/testcase.rb
+lib/test/unit/testresult.rb
+lib/test/unit/testsuite.rb
+lib/test/unit/ui/console/outputlevel.rb
+lib/test/unit/ui/console/testrunner.rb
+lib/test/unit/ui/emacs/testrunner.rb
+lib/test/unit/ui/tap/testrunner.rb
+lib/test/unit/ui/testrunner.rb
+lib/test/unit/ui/testrunnermediator.rb
+lib/test/unit/ui/testrunnerutilities.rb
+lib/test/unit/util/backtracefilter.rb
+lib/test/unit/util/method-owner-finder.rb
+lib/test/unit/util/observable.rb
+lib/test/unit/util/procwrapper.rb
+lib/test/unit/version.rb
+sample/adder.rb
+sample/subtracter.rb
+sample/tc_adder.rb
+sample/tc_subtracter.rb
+sample/test_user.rb
+sample/ts_examples.rb
+test/collector/test-descendant.rb
+test/collector/test-load.rb
+test/collector/test_dir.rb
+test/collector/test_objectspace.rb
+test/run-test.rb
+test/test-attribute.rb
+test/test-color-scheme.rb
+test/test-color.rb
+test/test-diff.rb
+test/test-emacs-runner.rb
+test/test-fixture.rb
+test/test-notification.rb
+test/test-omission.rb
+test/test-pending.rb
+test/test-priority.rb
+test/test-testcase.rb
+test/test_assertions.rb
+test/test_error.rb
+test/test_failure.rb
+test/test_testresult.rb
+test/test_testsuite.rb
+test/testunit-test-util.rb
+test/ui/test_testrunmediator.rb
+test/util/test-method-owner-finder.rb
+test/util/test_backtracefilter.rb
+test/util/test_observable.rb
+test/util/test_procwrapper.rb

Added: MacRuby/trunk/test/libs/test-unit/README.txt
===================================================================
--- MacRuby/trunk/test/libs/test-unit/README.txt	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/README.txt	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,52 @@
+= Test::Unit 2.x
+
+* http://rubyforge.org/projects/test-unit/
+
+== DESCRIPTION
+
+Test::Unit 2.x - Improved version of Test::Unit bundled in
+Ruby 1.8.x.
+
+Ruby 1.9.x bundles minitest not Test::Unit. Test::Unit
+bundled in Ruby 1.8.x had not been improved but unbundled
+Test::Unit (Test::Unit 2.x) will be improved actively.
+
+== FEATURES
+
+* Test::Unit 1.2.3 is the original Test::Unit, taken
+  straight from the ruby distribution. It is being
+  distributed as a gem to allow tool builders to use it as a
+  stand-alone package. (The test framework in ruby is going
+  to radically change very soon).
+
+* Test::Unit 2.x will be improved actively and may break
+  compatiblity with Test::Unit 1.2.3. (We will not hope it
+  if it isn't needed.)
+
+* Some features exist as separated gems like GUI test
+  runner. (Tk, GTK+ and Fox) test-unit-full gem package
+  provides for installing all Test::Unit related gems
+  easily.
+
+== INSTALL
+
+  % sudo gem install test-unit
+
+If you want to use full Test::Unit features:
+
+  % sudo gem install test-unit-full
+
+== LICENSE
+
+(The Ruby License)
+
+This software is distributed under the same terms as ruby.
+
+== Thanks
+
+* Daniel Berger: Suggestions and bug reports.
+* Designing Patterns: Suggestions.
+* Erik Hollensbe: Suggestions.
+* Bill Lear: A suggestion.
+* Diego Pettenò: A bug report.
+* Angelo Lakra: A bug report.

Added: MacRuby/trunk/test/libs/test-unit/Rakefile
===================================================================
--- MacRuby/trunk/test/libs/test-unit/Rakefile	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/Rakefile	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,40 @@
+# -*- ruby -*-
+
+require 'rubygems'
+gem 'rdoc'
+require 'hoe'
+require './lib/test/unit/version.rb'
+
+ENV["NODOT"] = "yes"
+
+version = Test::Unit::VERSION
+ENV["VERSION"] = version
+Hoe.spec('test-unit') do |p|
+  Hoe::Test::SUPPORTED_TEST_FRAMEWORKS[:testunit2] = "test/run-test.rb"
+  p.version = version
+  p.developer('Kouhei Sutou', 'kou at cozmixng.org')
+  p.developer('Ryan Davis', 'ryand-ruby at zenspider.com')
+
+  # Ex-Parrot:
+  # p.developer('Nathaniel Talbott', 'nathaniel at talbott.ws')
+end
+
+task :check_manifest => :clean_test_result
+task :check_manifest => :clean_coverage
+
+task :clean_test_result do
+  test_results = Dir.glob("**/.test-result")
+  sh("rm", "-rf", *test_results) unless test_results.empty?
+end
+
+task :clean_coverage do
+  sh("rm", "-rf", "coverage")
+end
+
+task :tag do
+  message = "Released Test::Unit #{version}!"
+  base = "svn+ssh://#{ENV['USER']}@rubyforge.org/var/svn/test-unit/"
+  sh 'svn', 'copy', '-m', message, "#{base}trunk", "#{base}tags/#{version}"
+end
+
+# vim: syntax=Ruby

Added: MacRuby/trunk/test/libs/test-unit/TODO
===================================================================
--- MacRuby/trunk/test/libs/test-unit/TODO	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/TODO	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,5 @@
+* mock.
+* data-driven test.
+* port ruby trunk's assert_equal's intelligent inspection
+  when inspected expected and actual are same content
+  string.

Added: MacRuby/trunk/test/libs/test-unit/bin/testrb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/bin/testrb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/bin/testrb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,5 @@
+#!/usr/bin/env ruby
+require 'test/unit'
+(r = Test::Unit::AutoRunner.new(true)).process_args(ARGV) or
+  abort r.options.banner + " tests..."
+exit r.run


Property changes on: MacRuby/trunk/test/libs/test-unit/bin/testrb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/test-unit/html/classic.html
===================================================================
--- MacRuby/trunk/test/libs/test-unit/html/classic.html	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/html/classic.html	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Test::Unit (Classic)</title>
+</head>
+<body bgcolor="red">
+<p style="text-align: center">
+  <img height="161" width="308" src="test-unit-classic.png">
+  <br>
+  <br>
+  <br>
+  Read the <a href="classic/test-unit/">rdoc</a>
+</p>
+</body>
+</html>

Added: MacRuby/trunk/test/libs/test-unit/html/index.html
===================================================================
--- MacRuby/trunk/test/libs/test-unit/html/index.html	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/html/index.html	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html
+  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+  <head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+    <title>Test::Unit - a Unit Testing Framework for Ruby</title>
+  </head>
+  <body>
+    <h1>Test::Unit - a Unit Testing Framework for Ruby</h1>
+    <p>[<a href="index.html.ja">Japanese</a>]</p>
+    <ul>
+      <li><a href="http://rubyforge.org/projects/test-unit/">Project Page</a></li>
+      <li>
+        <a href="test-unit/">RDoc</a>
+        <!--(<a href="ja/test-unit/">ja</a>)-->
+      </li>
+      <li>
+        <a href="classic.html">Classic</a>
+        <!--(<a href="ja/classic.html">ja</a>)-->
+      </li>
+    </ul>
+  </body>
+</html>

Added: MacRuby/trunk/test/libs/test-unit/html/index.html.ja
===================================================================
--- MacRuby/trunk/test/libs/test-unit/html/index.html.ja	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/html/index.html.ja	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html
+  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+    <title>Test::Unit - Ruby用単体テストフレームワーク</title>
+  </head>
+  <body>
+    <h1>Test::Unit - Ruby用単体テストフレームワーク</h1>
+    <p>[<a href="./">English</a>]</p>
+    <ul>
+      <li>
+        <a href="http://rubyforge.org/projects/test-unit/">プロジェクトページ</a>
+      </li>
+      <li>
+        <!--<a href="ja/test-unit/">RDoc</a>-->
+        RDoc(<a href="test-unit/">en</a>)
+      </li>
+      <li>
+        <!--<a href="classic.html.html">Classic</a>-->
+        Classic(<a href="classic.html">en</a>)
+      </li>
+    </ul>
+  </body>
+</html>

Added: MacRuby/trunk/test/libs/test-unit/html/test-unit-classic.png
===================================================================
--- MacRuby/trunk/test/libs/test-unit/html/test-unit-classic.png	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/html/test-unit-classic.png	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,77 @@
+\x89PNG
+
+   
+IHDR  4   \xA1   \xC6?Ԍ  
+piCCPICC Profile  x\x9C\xEDV\xE97|\xBEfF\xD6첍\xAC#4$I\xB2D\x96\xAC\x8D%{1cg\x8C1ִ)\x91B\xA9\xB4\x89Y*JTZh_,\xA94I\xF2\xA4-\x91=\xDEu\x9E\xCE\xFB\x9E\xF3\xBCA\xF7\xFD\xE5:\xD7\xEF\xDC\xD7\xFD\xFBp\x9Ds݀x\x8A\xB5\xBB\xBB3	@,\x8Bˡ\xDB/\xA3\xF8\xF8\xFAQ\x9F\x82YC\xAA\xC1\x8C\xB6\xB5\xBB\xBB3\xFE\xB5&\x9E\x80  \x9Dz\xF6\x9E.\xCBv{n\x9F\xB4\xD7
\xB6\xAB\x98\xFF\xC6$	\xFF> c\x86&0 \x82
\x80\x8E\x8F\xAF@\xD4 
\xFE\x9B\x90\xF9\x89\xDDHs<\xE96 \x91	E\xC2=\xE96 \x89
+EB<\xE96\x80@:@I油 9\x804\x83\xCD\xE1\xE4\xD3 \xB6\x86D\xB3\xB9 \xB9\x80t#\x9C\x99\x92\x8C\x88`& \xEE@\x8F\xCBb\x84\x9D \xE8\xCCX& \xF4\xB0\x8D\x8DId\xFC\xFA3\x80H(\xCB\xCB\x80
 %8 \xA1H\x85;8\x88F\xA0\x81S\xE8\x83#\xE8\xC3\x86\xA0@\xB60\xC1BP`#\xC0X\x83\xD0@\xF8\x97
& \x94\xE0}\xD0	.BA\x81#X`\xC0 \xE8 \xC9H\x86R\xC0\xF9\xF5n \xE2\xFB4u (\xC1,\xB0\x8CX\x84\x82	
+\"\xC1E
8\xA0\x80\xF6\xB3}|\xFD(?%\xC29\x80i  \xFF\x9B\x8B \xE5\xDD\xC0\x9C\x8Cߜv \xA0V\xD4\xEDd$r\x92~\xAF@ !\x8CِT\xC3\xAE\xB1U\xB8\x8A\xA7\xF8L%\xE8
	\x91\x84\xED\x84Z\xC2c\xC2Q\x83\xE8F\K\xAC"v\xF3\xCD\xE2[\xCA\xC7\xE1\xAB\xE2{ER"\xF9\x92\xF6\x91\xBA\xF8\xF8\xF9K\xF9\xDF,X/\xD0*8G0Z\xB0\x89,E\x8E"\xDFRJꞵxV\x910A8\\xF8\x81\x88\x99H\x85\xA8\xAC\xE8V\xD1I1\x96\xD8\xF1 \xF1n	o	\xDEl\xEF\xD9ݒA\x92RqRS\xD2\xDBdd\xAAe-eyr\xB1\xF2d\xF92\x85\xFE9Y\x8Az\x8A\x8F\x95\xD6+S\x95\xBBT\xB2T\xCDT\x87)\xE5jAs\xE6v\xA9j\xF8h*i\xBE\xD6:\xA1\x9D\xA4cC\x95\xA4\xF6랟\x97\xA7\xA6oe\xA0l0=\xFF/\xDA5\xC3
+\xA3\x9DҌ\xC3z\x9B8,275Z\xACk\xA6\xB9d\xAE\xB9\xDARumK+k\xEBen6\xABm\xE3\x97g\xDA\xD978<t\xFC\xE4$\xEEl\xE4\xB2\xCAu\x83[\x95;\x8FN\xF2X\xE8\xE1U\xEC\xDD\xE53\xDB\xD7\xD5/\xCF\xFFA\xA0t\x90\xFF\xEA\xB25#!\x8C|櫰E\xE1\xF9\xEF\xA2\xEC\xA2\xCBcY\xD1q\x8F\xE2\x97p*\xB82\x89\x99I\xDFRX\xA9kפ\xF7\xAE\xDC\xF0b#\xE3\xFD\x96\x84̙\xAC\xBCm\xAA9u;
r_\xE6\xA7\xEFR(h\xDCPH\xD8Wu\xC0\xE3\x8Aj\x8B\x83\x8F\xC8
m;\xB6\xB5|Y\xA1\xF2zu\xE6I\xE7\x99ھ35g74\xD0\xCF\xEB4\xE2b\xCF\xE5M\x{3BEEF7E}\xE6\xA6\xC3m\xA3\xBB\x94\xF16B\xFBD\xC7\xF0÷\x9Dox\xFD]\xDD\xEF{F{\xA7\xFAȯ\xE4\xFAu\x96\xBE\xF5|;\xB4m\xB8r\xA4\xE5\xF3\xF0\x99\xAF\x93QS~\xB4\xCC\xCC\xFC\xF1\xC2/\xFC\xF1\xC2/\xFC\xAF~\xE7\xC6\xEF\xD7-1\xEF77 \xF4\xFF\x93\xC1Q \x94`\x838\xB0\x91
+"\x8EpA\x81\xA0\x82\xF2_٩\xF7O>B\xFFZP`\x8DĀ\xFA?
+	\xA0\x80\x8EP$ 
$!L ?o\x87_\xC5G \x88 J\x84^b:\x9F"\xDFE\x92/\xE9\xFF>\x9E \x97,E\xAEZ9\xCBC\xD8Kd\x95\xA8\xAF\x98\xBFx\xA0\xC4\xEA\xD9\xC1\x92\xA9P\xE9\x99(\xD99\x96<[a\xE3\x9C|\xC5\xA5Z\xE5f\x95\xD5\x94a\xB5\xBF\xD5\xC54T4
+\xB4,\xB4]u\xA9\x99\xBA\xA7\xE6\xF1\xF4~h\xCEw\xA1%
6\xBA\xB5`h\xA1\xB4\x89\xF9"\xA6\xE9\x8E\xC5\xF5f\xBD\xE6Ki\xBE\x96V'\xACy\xCB\xFE\xB6\xD5^\xEEn\x97f̡\xCD��\xB3\xB3K\x9Ak\xA5o%\xDD\xD0#\xC8s\x87\xD7E\xEFA_\xBFx\xFF‶ \xC2\xEA\x85k\xA2\x82\x8BC:\x99\xE4P\xF3\xB0\xF8\xF0\xE3ϢģmcRbO\xB1^\xB1\xA5\xE3\xED8)	\xD5\xDC\xE7Ib\xC9V)\x9CԲ\xB4'\xE9\xE4uf\xEBc6
\xDEرih3y\x8BF\xA6\xF5\xD6\xC0\xAC\xD4\xEC\xC2mu9\xF7\xB7\xC8\xCCSϷ\xDC\xB0+\xA5 k\xF7\xDE=e{\xEB
+\xAF\xEE\xEB\xD8\xDF{`\xE8\xE0\xF7"\xA1\xC3r\xC5Z%\xC6Gl\x8E\xAE,
+>\xC6.\xDBX\x9E\xBC\xA4\xA2\xA6\xB2\xA9\xAA\xBD\xBA\xF7\xC4\xD0\xC9\xE9\xE1Z\xC5Ӻg\xCC\xEA,\xCF.\xAF_\xD1\xE0~\xCE\xEB\xBC\xFF\x855\x8Dac.\xC5_N\xBE\x92ޔќu5\xF7Z\xE6\xF5\xF4ܛѷ\xB7\xFD\xEE\xD0\xEF:޳n1m\xA5\xB5i\xB7\xABޗ\xED\xEB\xF8\xFA\xA0\xEF\xE1\xBDGu\x9D\x87
o\xE1\xC5>\xF1\xEE\xB2zJ\xED\x96\xEC\x9Ez\xD6\xDF\xD3\xFE\xFC\ﶿ^\xCC\xEF#\xF6\xF1^V\xBEZ\xFBڵ_\xAD\xFC͝\x81\x83\x83\xB1o\xAD\xDEI\xBDk}\xBF\xF9\x83\xF9\x87\xF1\xA1\x93C\x87\x95\x87y\x9F\xF2F\xECF\xFE
=\xFF9nL{\xACo<\xF9\x8Bؗ\xE3K'x_c\xBE\xF1};4i4\xD9\xF2=\xF8\xFB\xE4\xD4\xCEi\xED\xE9f uQ\x86x\x9B/\x85\xA4K\xEA\xE1\xCF\xB0,%{\xF1\x9D\x9B!\xEC)b%\xAA'\xA6 \xCE/>*\xD1;\xFB\x9Ed\x83\xD4Q\xE9<\x994\xD909\xBA\xBC\x85\xC2\xE29Ɗ4\xA5y\xCAZ*j\xAAJ95\xA9\xB9b\xEAB$\x8D\xCD\xEFZ:T9]\xEDy\xA6z\xFA\xBE\x91\xF3\xD3h9\x86\x87\x8CN,\xB8lܶ\xB0\xD7\xE4\xA3)\xFFb%3\xE3%N挥i\x96UVW\xAD\x9F.\xFBd+\xB8\\xC5\xCE\xC4\xDEŁ嘿\xE2\xB4\xD3\xE7QWI\xB7\xEE\x9E+\xE9{=\xCEyvy}[\xA5\xE0c\xE6\xEC\x97\xE5_\xC0\x9C^\xAD\xBEfEp|\xC8~F3s L4\xDC8\xC2?2#\xAA:\xFAa\xCC7\x96j\x9C=\x9B\xBF\x97s9\xA1?Q8\xC9(\xD97eSjeZ\xC7\xDA\xC1\xF4\xBF\xD7\xCBl\xD0\xDFh\xBB\xC9?#asΖ\xA3\x99\x8D[d
+f\xCF\xE4\xC8n\xD7\xDFa\x9C\xBB$\xCF:\xDFa\xA7\xDB.\xAF\x82\x80݌=\x91{م\xC9\xFB\xD6\xED\xDFr`\xFB\xC1]\x87
+\x8B
>R\^R}\xA4\xF6h}i㱦\xB2\xE5w\x8F\xB7W<\xAA\xEC\xAAz^\xFD\xF2\xC4\xC0\xC9\xA7Fk&j\xA7Π\x8E\xFF\xEC\xACz\xF1\xE9s
+\xE7U.\xA87\xEA\\xA4^\xA2^\xA6^\xA16Q\x9B\xA9W\xA9רש7\xA87\xA9\xB7\xA8\xB7\xA9wt\xEF\xEA\xDESjo%\xB4\x8E\xB7
+\xB4w\xDFo\xED\xB8\xF2\xE0\xF4\xC3\xD2G{;\xB3
\xA7\xF1b\x9E\xAC\xEEr|jܭ\xF2\x8C\xFCl\xAC\xA7\xF7\xF9\x9D޺\xBF\x8A^l\xED\x8B\xE9\xFFj\xF9kZ\xFF\x9C\xFE\x917\xB7&\xBCu|\xA7\xFAn\xE2}ۇҡ\x94\x8F\xAEÚ\xC3S\x9F
\x8ET\x8C\xFA\xFB|m\x8C;\xAE=\xDE\xF3%o\xC2zb\xFCk\xC57\xFFI\xB1\xC9k߹S\xDA b\xF1\x8C`O\xA8'\xAA\xF3\x89\xD3|\x91|OH6\xA4\xD3\xFC\xCA\xFC9\xFC_\x98\x82\x96d\xF2\x98P\xFB\xAC
+\xE1\x91 Q1	\xB1\xF7\xE2\xB7$Jf\xA7JzH\xE9KMH7\xC9dɺ\xCB\xC9˽\x94\xAFR\xE0\xCC1S\xE4SlSڣ
\xA8\xA2\xA92\xACz\x89\x92\xAD\xE65W}\xEE\x88\xFA\x8D
\xCDUZZ\xA3\xDA\xCD:;\xA8\xBE\xBAZ\xBAc\xF3:\xF5\xEA\xF4\xE2篤\xD1%?u,\xA81\xCE]k\xE2\xBCH\xCFT\xD8tt\xF1S\xB3\xA6%e\xE69K\xD9ޖ\xE6Vs\xAD\xC9\xD6\xC3\xCBx6\x97l\x8F.ϲK\xB6w\xF0qtXa\xEA\xA4\xE3,\xEF"\xE42\xE9\xFAέ۽e\xE5Ez\xB5\xC7A\xCF=^y\xDE٫2|\xD2}\x93\xFC\xD8\xFEQ\xCC\xC0\xA0 \x9F\xD5\xF45\xCE\xC1v!V[\xA6}\xA8S\x98[\xB8G\x84w\xA4_TPtpLhl$+&\x8E\xCD\xE6Ƨp\xD6%l\xE6f'\xE6&\xEDNޟR\x9Cz,\xADjmMz\xFD\xBA\xC6\xF5Mnn\xBC\xB7\xE9VƵ\xCDW\xB64f6l=\x93u*\xBBz\xDB\xF1\x9C\xD2\xED\xC5;\xE6\xE6\xE4\xE7\xED\xCC޵\xB9`\xDD\xEE\xE4=\x9C\xBD1\x85\xE1\xFB\x82\xF7
\xF0>\xB8\xF2\x90S\x91\xDDa\xAB\xE2%%\xD6G\xEC\x8E:\x97ҏ\xF9\x94\x953\x8FGU\xB0+\xAB\xD6Vo:\x91u2\xF7\xD4\xDA\xE6\xD3O\xCE\x9D%\xD6+4\xCC?\xB7\xFC|\xC0Nc\xF6ŒK
+\x97[\xAF\xBCj&]վ\xE6x=\xE6F\xDE\xCD3\xB7:oOܕ\xBF\xB7\xA4%\xB0uc[i\xFB\xAD\xFB\x83\xA8\xA3\x9D\xEA
\xE6ўp\xBA\xEA\x9FN<3\xEDI{~\xA9\xF7\xC7˾M/o\xBC\xBE\xF3\xA6u\xB0\xE3]燮\x8F=\x9F^\x8C\xBE
\xFC\xF2\xE1\xEB\xA7ɱ\xA9\xAF?\xA6ff\x80\x84\xB0F?\x93I\xB8
\xE0\xBF133\x9E \xD3_ff\xA6%ff~\x8C|N\xC0]\xEF\xFF F\xA8\xD2t\xE5\xCDMV   	pHYs     \x9A\x9C  \IDATx\x9C\xED]\x8C՝\xFF\xCE\xEC\x84IL\x9D\xE0\xA4FG\xCD\xE8R\x89[8\x94-eI*\xB1m\x8F+\xDBV\xB9
+W\x84\xA1j{\xB7T\xBAC\xC5\\x8F\xEA\xC0յ\xBA\xB6\x98\xABZ]+\x96\xEA\xE1\xB5:\x9DX\xAA^\xE9\xE2UU[\xA7\xB9\xC2%\xD0zK\xB2ؐu֛]{\xD7k\xEF\x8Fy\xF6\xFCz3\xF3ƞ\xF1\x9B\xDD}}\xC5\xDEyo\xBE\x9Ey\xDF\xF7\xE3\xFB\xBE\xEF\xFB\x95\xA2\x99\xB7 t\xE5\x88(\x84r
+DB9"
+\xA1\x9C\x85PN\x81\x88B(\xA7\x80 at D!\x94S@ \xA2\xCA) Q\xE5\x88(\x84r
+l>\xC4\xE305\xA5\x94J06\xC6[GH·V`\xB3\xE1\xF5r\xF9\x8A\xC1\xC1\xF6\xA75\xD8\xFAXY\xE1(\x8F\xC4\xC8)\xB0\xB9\x80\x92\xB4C\xD7L P`\xCFn^¸C(\xA7\xC0\xA6\x83b\xF9\xBC\xDA\xE4"\x86'\xACrґJ\xC1\x96-=\xDDgi	Μ驆\x88\xA1V(l;xΝ\x86ˮ\x82J\x85\xB78\xE1\x83\xDA.\xB8 \x96\x96\xE0\xF4ih\xB5L߫*\r	\xBD\x9E\x85\xBE\x8FKBl\x9C;]Hm\xE16\xF4\xE2\xF9\\xC1\xD8\xCF{\xAD6\x93I\xFDw\xBE\xC1]\x9E\xB0Y\xCD\xE7]_me\xFD\xE2V*\xE5\xD1F\xF6\xF1\xFD9sy\x89\xEE\xEA	\xBBxOk߾\xF3\xCE`\xBA\x81k\xDFL=\x80t\xC1\xFA\x87\xEB\xDF\xC7O\x90>\xA1z뭮\x8Fû;\xCE\xECc
\xD5ݲ\xBFw\x91zA\xF2\xEA\xABaz\x9A\xF0\x9E{\xBA
\xF1\xC2n\xDE\xD3ځ\x85\x85\xC0ﺡ\xB0\xB0\xC4[\x82б\xED\xE5\x97\xC1dD\xB1\xA0oLw>\\xF8\xCB_zT\xF7\xE2o\x83\xAA
;{\xF7\g̀m\xCDI\xB0\xF7\xFC=,/\xEB_,/7
x`\xCB5״?\x9F\x81O|b\xB1\xCE_\xE1\xBA\xEB\xE0\xF3\x9F'\x977v\xA8\xBC%
;?\xF9Ix\xE2	
\x85\x87
ҿ=t\x9E
Ξ\x85Ç\xC1\xB0䔏
\x83ݻ\xE1\x86 \x83X\xBE\xFD\xED\xF6_\xEAp\xD7\xDF\xC1o~ǎ\xF5S\xF8>!\x8Cf\xE09\xF1=Y*\xB5\xA7\xD5\xF3\xF6\xBF.f2\xFA\xB4{\xE2\xA0\xE5\xAF5Ӥ\xFC\xDF\xF9\xAE4\xA4iYU>\xCC]\x9E\xBEq޸TK%\xFD)=\xC7]\xFE`v3\xF0
9\xA5
;\xDA\xFFU@0\x9B\xE5\xB03N\xC0\x85\xDB-e\x95/\xD4?\\xFFL\xBD\xC5\xF00\xDCy'\x8C\x8D\xC1\x8E
\xB0\xB0@\xFE\xFD\xD9\xCF੧\xE0\x8F2\xD5a\x92P\x92\xA4\xF7\xBCn\xBF
\xF6\xED\x83\xEDۡZ \x98\x9D\x85\x9F\xFF
^x\x81ؐ\xD3i\xB8\xE9&x\xF9ex\xF2I\xDF7\xD84 at I2}\xDEr!\x80\x87\xDETd\xC7;\xE8\xA9*\xE8\x9B͎K at K\x96\xE5\xF7\xBF\xEE\xB8.\xBD\xB6o x\xEE9x\xF4QX\\xF4'\xBA\xE5\xB4{E\xEE\xBA۔媃QNcubB\xFF{\x{1B35BF}\xD6U\xB5\xC6޵LL4<\xCC|\x88\xEC
OCQЯ\xA9yp7K\xCD+\xFD9S)L\xA71\x93\xC1t\xBAk\x8Bb\x80ն$\xC94r\xFA+B{P5c\xFB\xE9`xHk\x8E\xAF)\x9Fg\xBBn\x9C\xDC\xD9Q|\xA6\xEB'v3\xF0\xF5>\xE6P\xB2^ஜ\x9E\xEF\x86phH\xD7aoTY\x9A\xFA\xA8\xB2\xA7\x9A3,\x95\xB0R\xC1J\xCBek'\xA2}\xEF\xC4\\xCE\xEF[i(\xCA|\xB9l\x95m\xEA\x87=\xBE\xEC
\xAB
+C9\xA7\xED\xF2 b\x{1556F98}r@帽5R\xB9P(\xB8\xD5\xE3K\xA9\xFA\xDB\xFC<\xDC\xD2O\xEC\xF8PNZq\xD7\xB2Rq
K\xC7?\xE2\xDE
+)\xDA^,b>\x8F\x85R\x84Z\x83kʲ\x9F\xBE\x83\x9F\xE3\xDEt\xA5B\xAFg\xEA	\xBF/8\xC0j\xC3P\xCE٩\xA9\xEE\x9F*\x9B\xE3̀\x94\xB3\xFF\xCD\xC0\xFB\xE1\xEA\xD3Z\xDA\xCF\xE8q\xE4\I\xA7m\xBF\xA0\x81\x99\xC6b\xFAe\xAA\x8Aԙ\xC9А\x93\xD8g-\xEF#\x9FGE1]#\xCB8>N\xD1\xFC(g\xC3m̧\xAC,\xFAVm\xCAْ$L\xA71\x97[6v
\xC6\xFF\xE7r88\x88\x89\x8E\x8EV\xAD\x9DK\xE3q\xEF߮(81\x81\xF9<\xE6rM\xC3\xF2\xFAUN\x98\xD1Ƌ\xF6\xBF\xFAP\xCEL\xC6\xF2ץX̪
\x85ǝ\xE6*MY^\xB0Nu(\xD3l\x8Do\xAF\xCCe
۫\xA2\xBCey\xDF
+\xAE>9\x89h\x98\xB7X\xE02\x99\xC1N~\xCB\xD7+\xF1\xF0\xB0a\x99҇Sm\xCA\xD9ᢽ\xFF->k\xEF2j_%[\x93c\xA1i\xC1ϴ\xB6\x9F\xCD Y\x94s\xBAs\xEF\xFCC\xF6\xBF\xBA+'6K\xBAuJ3\xF95Oa޲\xCCH'\xEE\xF6nC\xAAG\x9D3Ƨ\xCC\xD6\xF4M\xA3PЖ -J]ʫ\xDAP\x95\xB3jY\xDD
ejNk%\xF6G\xD1\xC3\xEB\xB5 \x8B\xFBޞ\x81\xB8\xF2Jػ\xEE\xFBR\xD6\xE0=\x97_N\x8A\xFF\xE5-\xC6\xEFWT5y\x8B\xE1\x9Bs\xAF\xC0g\xFFѳ\xB6]W_\xBDf\xFC\xFC\xED\xBD%ؾ\xCB\xFD\xEF\xEFڵk\xEE\xDC9\xF2\x81\xCD
j\xA0\xD1\xD0?,l\x8Bo\xB8\xFDqfg#Um8\xA8\xC0'\xFF\xD6\xE9o\xDDq\x87\xFE\x81\xABH\xA8\xCD \x98\x8E\x8C\xB5Zp\xE2LOwy\x87\xE2\xF2\x8D7\x9A\xF6X\xAF\xFD0Ke\x8B\x8B\xD5C\x87_\xEC\x81D\xC2r\x8D\x84\xB8z\xF4\xA8\xFEy\xEEUH\xA5\\xEA\x94[\xAD\x8B	\xB8\xF8bغ\xB57ˠ\xDB\xC733o
9B\xFF\xDB\xFD\xFF\xADjC\xC1\x97\xFEŲ\x9DnB\xB9\xDC?I\xD8B7\xE1\xCB}/H,\xDE}\xF7N\xE3\xE7\xE1k\xE1\x9D\xEF\xF2.V\xAD\xD6o\xBE\xD9\xF4͎
v\x8Dj\x9D<	\xBASaN\x9D \x98\x9E\x86矇\xD7_\x873g\x88\x8F\xE1ɓp\xEC\xBC\xF1\xB4Z\x91:\xD1\xF6\xAE \x9F\xD7=5\xDCuW\x8F>!U<\==\x95ӧ\xE2}\x86\xF8)\xE7\xF5כ\x94\xF3\xD9g^\xCAp\xCD\xCE\xDBn\xAB\xD7\xEB[-\xDF\xC2g>C/p\xE4|\xEEs\xD1\xF2\xF9\xBC\xEF>\xF8\xC2`\xF7n \x80Ffg\x82\xDCB\xAA\xB6\x8F\x90׼\xAF\xDAজ	\x8F\x83̸\x80▥\xAE\xAC\xC0޽>\xE6?\xFB\xF7\xC3\xEF\xE7ʐ\xBC\xA2\xF3\xE6\xD7ֺ_M\xF4\xBFZ\x9A\xDB\xFAs\xA7\x8DnaJ\xAE\xEB at VL\xFF^\xFB\xA3ß\xA6׶l\x81\xFB\xEF\xF7\xA1k\xED\x85\xD7^@*\x81v\xEF\xB6\xCE_\x98\xC1m\xE4\\xD3\xFD\xE9\xE0ϰ\xE5
+\xBAk\xB2\xA0^\xB7F\xC70CY[\x83\x87V
~R)\xF8\xE0\xE1C\x82T\x8A8\xBE\xC0\xF6\xED\xF5\xFD\xFBmS\xDF`\xEC \xFC\xAC\xE8C\x92M\x94$Ssi\xACz1\xD93\xF95\xB6u
+n\xCFK6\xD9lb\xB0\xB6k\x81M([\xB2,\xBF\xFB\xDDz\xB8\x9A\x99x\xF2I\xBB\xD9c+ \xC4b\x8D\xEF}o\xCB\xC1\x83\xFA\xB7׾7*\xCA94D\xA2\xAA./Ï~\x98ɪ\xDBj\xE5Vk\xF9\xE8\xD1x\xE7\xAD}\xF0\xFD\xF0\xE4}\xDC\xF7\xF9\x97|\x89)\xC0M9w<\xF6\xE8\xFB\x9CI\xDC
+ӧ\x82\xAA\xFC\xE4ٳ{\xB4N{\xF7z\xAC\xAF\x96\x97\xB7\xDC~\xFB\x9Fo\xBEyO'\xE2\xD3ߌ\xC3Ó>n\xC2׊\xAA.\xBF\xF9f\xC2\x84\xEA\xC8\xC3n\xEE\xC5~p\xB5\xFF\x90\xF1T\xCEʽ\xF7\xEAf\xBF\xD7\xFF\xE4\xFF
\xEB|\xF69\xC3\xC1\xC0\xE1æϿ{\xCE_yY\xE3QRZ\xB2\xBC\xB3\xD3\xFE~\xF7_,\x95\xED\xFC\xE2\xF5;|\xC6e\xBB\xE6Z\x90\xBC\xAF\xF2\x85\xB3v\x80\xFD\xCF>\xC1\xB7\xDA\xF8\xD3O\xEB\xAE\xF90\xC4鯠\x83\xBAq\xDB\xE6L\xD5\xF9\xC2\xF5\x8F\x9A?\xE5\\4\xED\x89_t
+\xE4
`*94SS\xD0l\xC2\xD2\xE0\x9C\xFD\x89\x98L\xED]\xB9\xACg\x95լ\xE1\x9A\xE7\xBD紸j\n%\xE1=\x97;^)I02SSP.C\xE5
+P\xBD\xB7\xAA\xD7/u
+\xDCx\xCB\xC1\xAE\xDFX \xD5n+\x9F\xF8\xFD.\xB7\xC6\xC7
+\xFB^u0y\x8Fl\x84\xDA zv\xFF\xF3\xF4\xADu\xE1j"a\xF5\xF0,\xFD\x8F\xE39I±\xB1e\xBB\xB7\xF1\xD0\xE5V\xCFI\x8B("\x9Er9uѰxuN\xDC\xC1"\xBC9\xBC\xE2\x9C\xE9\x8D\xC6x
\xB3Y\xAB\xB4\x8F(\xB2\x8E\xEF\xAD\xE7Ί\xCFҏ\x8C\x8F\x9B/\xF38\xD3\xCCސ<OJy2\xC0C\xD2\xE15\xF4\xAD\x9C\xE94\x96\xCBFZ\x8F\x95\x94J\xA6FF\xDC+\xA4\x84/ql\x93IL&qx3,
\xDAT
+\xCA˳*\xA7\x86\xC9I

FUEIB T
Y\xB6\x9E\xED\xACalˣ8\xA3
P\xB0\xD4?:\x8A\xE94NNR\x8E,hHܳf-J2E\xEE	\xAFڵ\xA1![\xE1f\xB3\x98L\xA2\xA2\xA0\xA2\xE0\xE0\xE0\xAA\xFD\xA8\xB4\x93c}"\x81\xC5"\xE5\x84m\xB9\x8CŢU\xAA|
\xCBe\xEB\xB3\xD5Z5D\x86v\xBD\x8D\xD6FK\xBB\xCBe\xCC\xDEDZ\xF8SNS\x8Fňʯ=\xAB]\xB5\xF7+\xACh\xE0\xF0\xB0\xBDBsh\x9F\xBB\x89\xF1i4e\x99\xDE\xB8\xA0r\x9C\xE5ؤ)T\xB1\xF3\x8C\xC7\xFFC\xAD\xD6w\x9Cq\xE7\xF3Fo8v\xBB\x88\x88\x98\xBB\xB7s\xE5\x8Ag\xAC\xEA\xB8i\xD4\xF2\x8Em퍚\xE7\xFB
+\xAFDB9 \x87\x86|\xD6\\xC3L\xC6\xE5\xE4g\x97\x87b\xC7\xC7\xFD\xB5\xF8D\xC2;葆\xF2	
c\xAFy\xCE)> \xED\x88
\x9Fj)\xA7\xE4
\x90\xFF\xB2K=\xA7\x99\x95\xD3[\xD9\xCC"\xD7\xC3\xE5\x8C\xF0V\xCEP\x9B\x81\xBFW\xB2\xE2\xB7\xCB\xF4#
+\xA6\xD3
JU\xA9`>ϲ:2\xAC\x8B\x98\xCF\xE3Ԕ\xEB\xE3k`6\xDBe\x84E\xC1l\xD6Q\xECR\xC9Ձ\x9D\xD6G\xDD\xC0t\xBA\x9Bz«6
o\xBA\xABVe\x96:\xB51\xD1%|T\xA5b,ޒ$\xDBi{ï\x98\xFC\x8E\xA5\xE6\x96$\xAD\xB8\x8B\xE7\x89\xC2\xE3|\x9BA\xF4\xF2s&\xB0o
+ ,/\xC3\xF22\xCC\xCEB\xB9o\xBD\xE5\xC3KAU\xE1\xC6\xA1^\x87\x97^4|\xF9\xCEw\xC2%\x97\xC0%\x97@\xA5W\\xA7N\xC1ѣ\xC1l\xEE\xC7bp\xF1\xC5\x8F ,.\xC2ٳp\xFE<`oOW\x96aW\xFB0j\x80\x87f\x82\xAD6
\x87[o5y_
?\xC5"
>\xEC;\x80\xE5@\xA0\xCD z\xCA)    "?\xA7\x80 at d!\x94S@ \xA2\xCA) Ql\xD0S<\x92۶A";w\x82\xAA\xC2֭P\xAFC\xB5
+\x95
+T\xAB\x91N\x8F! \xD0\xC6RNY\x86\xAB\xAE\x82;\xEFl|\xEAS[<\x93\x8A9\xCF<?\xF8A\xA4B	\xB1!\xAC\xB5CC\xF0\xC8#\xFA\xB4\xA3G\xE1\xE9\xA7\xE1嗡\\x86\xE5eP\xA8\xD7a\xEBVH$\xE0\xCA+\xE1\xC03
%]\x83G\xBE	_\xF9J\xD7\xE9\x8DB\xC2:W\xCE\xE1\xE1ڑ#۴q\xF2\xB1\xC7\xE0\x91G\xE0\xB5ט\xB6\x95$	.\xBD>\xFD\xE9\xFAC\x91`ӯ\xC2G?J\x8C/m\xEF\xEB\x8A+`\xE7N\x92O\xF6\xED\xB7ᥗ`f&\xF8{	l$\xE0t
\xAA\xDA\xF6\xFFh\xB8\xB8\xF211\x95\xC2Nn\x95\xCA]\xFB01
\xC7t\xDA\xD9_uɹ?I\xC1\xA8\x92\xBF\xDDpt\x944\xEF\xC9\xEF\xF4\xA4\x96Fj\xE9n\x88\xDF\xD6\xD3]z\xF3i\xE7\x83LgjX(`:\x8D\x83\x83\x8F\xA3\xA2\xA0\xAA\xA2,\xE3\xF00I\xCBS\xFE\xFF\xE7)I\xF2\x97\xC0/۩lj.Yƺ\xA7\xA2\xB4\xC8(J?\xF2\xE2\xC8\xD1\xD1US\x8F\x8E\x8F{\xBAS\x92\xC48\xBD\xB9\xB3nT\xF2\x97\xC0In\xBF\xCAq\xFB1\xCE 92Bt,\xF7\xA0Ǖ\x8AbN\xC8]\xC5tU\x95\xFD^s\x88\x88s\xDC\xAC`\xC9_v\x92\x93\xD9}\x99\xB6b1r\xC8}\xEA\xFDKN\xFBb\xB1\xBB\x91|!\x9B\xED%\xEB\xA6\xE0&	\xD9>\xCE7׷vܒ$\x92mΜg\xAE)˦\xC0SS~\x93\xA2Y\x9D\x98@\x9C\xCA)h'	I҄v\x9B\x9D\xB2k\x9E\xD5\xCEN}\x9F|c\xCC\xF1Z|\xA1\xB5\xD4X\xCFd\xC4\xC8)H%	XH\xD2
\xE7\xE0rw\xA2\x9F\xE5\xB2
\xAE!\xA8
\x9D@(\xA7 \x85\xFC%\xF0d;&\x90c\x92\xF9\xB0i
+iHD \xA8\xABj\x99\x83\xB9)\xCB\x8Bu
\xECKp]\x90\xBF\x9E\т,fn\xE3# ٹi#\xB9+\xC0\xCAI\xA4\xAC\xF13]?1\x81\xA5\x92uU\xB9\x97\xFC%\xF0䛥b
+վ\xDF\xDA\xDEf\x9Ehi\xE1Ѡ\xEA_\x8B\xC7\xCC\xFB(\xF4\xF0Vc\xB8\xBF
\xC1\xF0\xC8_w6\xA5f\xB3\x97\xF6\x81k\xC6x\xA4\x85\xA7\xB45\xE8F\xAF\xE43\xDAȦ`3\xF6\xA8\xA5縿
\xC1P\xC9_w6\x87\x87}ǒ\x83\xA68\x9D\xE6 \x82\xD3\xDA(\xDA\xF3d\xB2\xA2)\xFF\xD4,\xAFP\xE2P6\x83_\xAE_\xF2\x97\xC0\x9Dڎ\xE2\xF0U\xFD\xB9]\xCB\xE1z޾SB\xA6\x97\x93_\xE9\xE5.me\x9Bf\xB9\xB8\xAE\xAA\x94\x98\x8B\x99\x83\xDC_\x8D`\xD8\xE4/\x81;I
+\x8D��(\xF3F\xE7\xD8\xF2o\x9D\x86G2\xE8ukj\xAF\xFD*\xE3*\x9A	\xBAR\xE2\xFE^\xFB@\xFE\xB8\x93\x8C\x9C\x83\xBBý\xD1\xE0\xA0)괓\xCB
 \xF6\xB6n\x8D\x8D\x91I)\xDB.-1I\xC0c\xC1Ȓ\xBF\xEE\x9C\xD6F3\xC6͆\xAEش\xAC\xE8&\xFFͳ\xCFm	\xCE\xDC\xD9Ngƪ\x990c\xD7\xCC\\x96\xFBK\xEC\xF9K\xE0Nb 
+\xCD T\xB7d\x89rN\xB9c$IdV~\x91\xFDF\xAB\xE4$Z\x95\xDD\xE3o\x81\x92\xE2i\x86\xFB\xEC\xF9K\xE0N2F\x85\xB3\xCA:kɽ\xC10fvH\x8C:,\xBE\xBE\xF189\xE0⼎\xB5\xB3\xBDj\x86ϱZp]\x93\xBF\xEE\xD4x\xBA\xD0j\xCA\xF2\xBCe\xE7ЧwAK\x92\xE6+\xEF	j'\x87\xAC\xE7\xD1P3Oړ\xF6\xFE\x9D\xFB\xEB\xEC'\xF9K\xE0N\xDD"\\xD3l(ʜ\xA5݇\xE1\xE4`\x8Cr\xE4+\xA8\xC0J'\x8B\xE1
\xEFLI"	\x917\xF9K\xE0NS\x9A\xEA \x82\xD4UՖ\xEDt:x\xC9;~\xF1\xC7~\x836\xD03sO=곊\xC5\xF4P\xFE\xAB\xDC\xE5	\x96\xFC%\xF0䬾\xD1\xD7\xEB\xC1\x94\x86\xA2\xD8\xDA}\xD0^\xBB\xA3\xA3m\x9F\x81\x86\xBF\xF4\xA4m\x9E\xB5\xB8ڇ4\xB0\xAF6Śs\xB9\xEF\xC7}C%	<i\xF2\xF9.\xFEg\xD7\xF54e\xD9:\x9BE2J\xD8\xF0\xF0r\xA7\x9F\x9C\xECnJK/<\xF5\xE8l\xD9'\xFF
\xB2\x8D\xF9K\xC0BSrr?6\xD5[\x924m\xD7\xCC\xEC=\xC1H82\xA2\xABe\xE9׽
\xB3|\xCB襤Ax\xEA9\xB0n\x8CJ!\x94\x93\x97b1Ӿ{>\xF06ߴ?{\xA6(\x98\xC9莯\x95\xD9
\xC7ᕎiW\xAF\xF3\xDC~dY\xED,\xEC	6\xDA\xE9V\xFE0r\xD1\xD2MV\xFE\x84\xF18c٪}\xD7\xE3\qpP\xAF\xA9\xE5\xC8H\x8F?\xB0
\xF0\xC1\xE1\xA9\xE7L[\x84
+N\xC7\xF1C#	\xD8\xF9\xB6=\xBB\xC1Ąg\xA9V'\xAD\xE9E~\xBCR)\xCC\xE5Lcx\xF9\x84\xDFm'\x9E5j\xBBN1\x93\xD6\x87\x860\x97\xC3\S)\xFE\xC2M\xFE\xF8"eI\x865
w\xB2\xE2'u\xFC\xB8ݡ\xA2\xE0\xC8NNZ\xFDu\xA6\xA6\xE1\xD3
\xB4I)<\xF56;\xF9K\xE0\x97\x8B\xF6#Td\x9C\xC9ۻ\xCF\xD3\xD4TBq\x8F,	\x8B\xE1\xC8\xE6\xF3\xAB\xF6\xF8\x959\xCCdPQ\x82\xFDQcU\xC9&\xD7\xF9K\xD0
+\xAD\x96 3\x8AE\x9C\x98\xC0\xE1a\xB4[\xF3\xD0\xECC/I\xA8\xAA\x98H\xE0\xF00\xA6\xD389\x89v\xBBA\xF3\xF9\x90\xA2\xDD-\xD9
ܧ
\xE3\xFF\x90ys\xDD\xE6\xE7L&O\x9C\x88{f\xB0\xA6`
+Νւu\xF8\xD2\xD7\xE0\xBB\xDF
+1\x97f"\xF3\xF3\xE6\xAFa`;\xB4º\xA1\xC0\xBA\xF7\xEE\xA1'\x8E\x8DQ,\x9C\xBD\xA3X\xC4t\x9A\xDD\xDC)\x91\xBB\x84\xA7\x9E  \xAE{\xE5\xD4h\xD9\xD8\xE8\x95
+ɢ\x99L\xF63t5eB+<\xF5\xDB\\xB7\xD3Z*	ط\xAE\xBDv\xED\xEB_W\xA8LO\xC3\xC2\xBC\xF2
+\x9C8\xAF\xBC\xAF\xBE
+\xA7N\xC1\xC2\xB48L"1\x95\x92N\x9D2\xB7n\x87\xE5Z\xFF\x85\x88 6\x96r @K\x96\x97\x9A͸\xFD\xBBS03\xDBy\x9Cp1i\xF9\xEA\xAE\xDB\xE1\xC9C\\x84a\x85,"`\xB7\xAD\xA6\xC7\xE2\x9B2o\x82\xC7\xE2\x83R4\xF3\xE8\xF3h\xA6,\x83\xA2\x80\xAA\x82$\xF5XS\xB5P\xB0j\xE6\xB9W\xA2\xAC\x99-Y^.\x95\xA0لV\xC6n\xEAs\xF1M
+\xEE\xEB`Iw\x82Cđ\xAB\xBB\xAC3\x95\xC2|
\xED\xCE=\xA4\xE5\xA4\xF8\xD0"F<+\xD1)\xE3\xF0ҩ\xC7⛓\xFC%\x96\xF4vߝ\xB7\xCD\xE8(M\xCF\xA6TB]d
K$(\xB5F\xDBSo\x95D\xF4\xECR\xBBz,\xBEi\xC9_\x82`9mߙ@\xC4ܽ\xFE\xEA\x89ǭ\x86J\xBF\xC6\xE1a\x94er\x81,c'\xA0\xA6\x9F#]-I\xA2\x9C)\xED=\xBB\xA1\xE6M\x8Fc"\x811/\xFF'\x9F\xB4
\x9B,\xFE\xD4\xD7\xE1\x8F
\x8B\xEB\x94e\xF2{\xFCE\x8A\x82\xF18yV\xAA\xEC\xB3
+\x96\xFC%\x90\xAB\xD4A	\xD1\xDF\xFC\xD3z\x84w\xDEѩ:
\xAF"\xFA:\xE0B\xF1\xDD\xC7
\xE2\xD9'\x93\x98\xCDR\xA6\xDC\xC5[\xB5}l\xB3Y\xCC\xE50\x9F\xC7B\x8BE\xC6\xE0)\xD5j`6\xEBW\xF3{,\x8ECC\x94\x84]
\xDAT
é)Jm\x95
+f2]>\xFF\x90\xC9_\x82 I\xF4\xEA/\xACf\xD32+\xF6:8J
\xD6\xD9&\xA5t\xF1\xD8rْ$
\xB7N\xB9
\xC7\xD1\xD1eMWˇ;\xD7S➰\x940
\xE8\xF1\x9F
\xA6\xD7\xE2\xB1\xE5\xD0B\xF1\xF5$\x94=\xF0r\xB3Y

5$_\x9D\xF3\xEA\xA9\xE4/A\x80\xA4\xCFi'\xEE`,n\x9D\x80M|\x86\xA5ԩrq\xDEs^\xBAB=\xB9\x865\xDFmb|\xDC\xDA\xFD\xA7Ӗ\xBB\x93x\xBC\xC9]HO\xEC\xC96\x8B&e\xA6QU\xE7q\xE2nr\xF6V\x9C
S\xF3Qê]-mq*\xFE\xAF3\x97\xF1\xDFK\x86M\xFEEk\xB4\x84<Ϡ \xA0\xBD37\xA6\xEAĄg\xDCJz\x84h\xF4\x99f"\x95\xB2F'+
\xA1\xEA69\x85<q\xA9\x87\xECX"S'
+\xC4N\xB6\xA5*\xFA\xB4\xE2\xF4X
`\x9Er6\xD0G?\x8B\xC3ÔN\x8B\xB7fXhD.\xF8(	\x82"-\xD6+k\x98\x8F\xA6,\x9B\xDA}\xFE!\xF7\xD5f\xC2\xCE!&#\x90ql\xF7s\xAC\xB4\xA9\xA5\xA50	\xF9e\x97\x9FSE\xC4\xCCm$\xBB\xA9ϟVWU\xB2\x96N$\xF4ژ\xB5\xAB\xC7\xE2\xE8\xB42g\x8E`\xBAJY>\xCCS,I##\xE6is\xCFf\xB9\xA0\xC9_\x82\xA0xƒ\xF5D\x9B\x9D\xD6t\xECӧwk]S \xE7\xE1Ț\xF4\xA163U]U߲O\xD7]\xA7\xDC\xC40\x96\xCBYm\xCE[JzWҶ\xBB\xB4$\x89]\xBBz,\x8E\xA6\x88
+\xD3\xE8\xC7fZ\xA0xYS֓4ۡ9C#弲\xAB\xCE\xE84E!��$\x8Cpд\xF3Z\x97Q(,[\xF4\x84qwǒ\x9BP\x83W\xD0 at Z\\xAD}{gR$\xDE\xA37t\xBE!\xDA\xC5&p\x8F\xC5\xCF\xDB'\xD8\xB8V(\xF1\xE7\xA93\xCA#\xF2\xA3/\xE4/A tpb
+mr^\xF1o\xA6'kNڌ\x88\xE8m\xE1)\xB4N\xB4\x98\x9C"(qY\x91-C!%\xA0ӄ\x96\x8CZ\xE6\xF56{J\xB5
\x8B\x93P\x97Ţ- E\x95\xC5lF3N\x87V,f\xBD6zI\xA2\xF8K
\x94sڳ\xE0\x8A\xD1\xE4g\xA9\xD9\xE1\xC9R\x89:#"\xAAU\xFA\xA6R\xD6яac\xB3e\xF1\xAA\xD1\xC0Γ\x9E\xCD\xE7<ݰ)\xBBB\x8FY_\x8F\xC5\xC9B\xFB\xF2\x84\xC1lFr]}6
+\xCB\xF8\x8E\x8Ev\xF1\xEA\xC3&	!}"ǰ'fX\xE1\xF8\x9E\xD0"@]U\xD4u6dٺ\xC1\xC3`\xB2\xA7Gd\xCBTo\xF5\x95\xD3\xE0\xD5
\xD3m\xBD\xBD\xD4\xD9otNvL\xF1\xF2\xAF\xD0\xFE\xC3\xB6\xA9\xE9>\x9B,\xA9Ve9\xF0pP\x92\xBF\x81\x90\xB6\x9B\xE7\xBD
bo3\xDDD=%q\x8DG\xAF3}\xDF\xD9H\x90a\xDE
\xF8\xD8s\x86F\xC9Ȁ\x94\xBB8\x90\x92۳; O{<[\xA7G\xD4[\xF1v\x8A\x8C\xC5(\x86\xCFȽ\x96\xE8\xB5\xDDt\xB5Q#	!]9\xBD,\x84\x86A\xC6ۋ\x80\xCA9[\xD9V,F6\xE2\xB0d_\xD8x\xCD\xD0(\xC9y4\xB0y\xC6؂\xA0\xA3\xE7\x82m-
\xAFi\x979\xCB\xFA~M\x86
\x8B\xB7\xF7]j\xA8\xAAg(\xDBE

+\xC7
+\xE4\xEE\xE2G\x8C\xFC%\x84\xB4\xFC?\xDE.\xE9z\x82ڮ\xCEIw<\x83
R\xDFH\xBA
\xED 3\xB4\xC5\xC5e\x8D\xD1}\x97\xEE\x86\xE1\xDA
\xAC\xE4r\xD5Z
+\xB1\xE12@\x9E҅\x9D\xAB\xD7\x9B]'3\xFE\xE4\xAEj<n\xDD{㱺\xB2B{\݆\xFC

l\xE0Ltv;\xF9K\xE9Vׄp\x869m7Y \xDB݁\xA9\xCDi\xA6\xFC\xB1\x9B\x90\xBA\xF2JPW\xFF\xE8GiM\x8D\xD5w\x97\x92۵;XI\xA7\xB1\x81\xE8
\xB4޴	lތi\xEEߏ\x88\xF8ȿ\xF6T\xFC\x9B_Ej2\xAFi\xFC\xEA\xFD\xF7\xD3WW\xC3fەw\xBA\x8B\xB2!\x91\xBF\x81\x90~\xCBu_D\xB7!\xFF\xA3\x8B;\x92\xA5\x9D\xC5\xD02>\xAE%M\xA1\xCCN=3sk\xF2\xCC\xCE\xDA~\x93\xFF-\xDD(\xE2\xD2
hK5/\xAA\xBA\xAA֜*\xD4v\xAD\x81\xB18ŞWz\x8E\xE5\x{1F698F}\xDBVݬ6uW\xDE(e\xF8\xE4/AP\xA4\x8C\xAE{\xEEz9\xFF\xB1\xD5\xC9\xE9\xBC"\xB2Y\xF6=\xE7\xF6\xCAmf\xC1>0\x9B\xF4\xA5W\xE1\x8EE\x88	gγ
\xAFt\x8E\xADj\xE8\xACH
+
\x9A\xC0X\xDC\x98\xDFq\x92\x90\x81\xE6Z\xD6\x8B\x91\xD6F\xA0td_e\xC3#	\x82"\xE5@\x96\xAB\x9Ft{ŷG%\x89g\xE9<c\xA4l\xBA\xBA\xAEi\xEB\xAAJvU\xBBE\x87i\xB5I\xB1\xD0:\x8F\xB7K\xC4dUc\xAAٲ4v \xF5\xE1
+OD\x96\xE2k\xF6զ\xAB;Q\xDB\xF8W\xC5\xD86\xCAr\xC6\xFF\xE1X2\xA3\x8E\x9E
+\x89\xBFAq\xC5n\xB0uU	\xD2n|
j\x92\xA1\x80\xEEF$\xB1\xCE0\xDD\x{13FB59}\xA4\xA5Z\x87\#\xED9\xAA\x9B\xB8C\xC7\xD4VdI\xCBE\x99m\xA6\x92\xD8\xE9\xBCf
\x8C\xC5m\xBD\xAA\xDB\xE3j&\x93
+\xC3\xE3\xB2)'\x93/\x91\x91\xC4\xE3\x8F\xEDx`\x9F\xC9_\x82 i\xDD\xEEwVN}pK\x84\xBD\xFE֪\xEEc\x8Eն\xE1l/mk\xA6\xBEԱ&\xF42\x8A\x9C\xEF\xF8Ә~;\xDD\xA8)\xCB\xED\xA52S\xDAB\x9B\x91f\x85\xF8\xF1\x8F\xDDT\xF1S\x9B\xB6s\xC0\xFB\xF6\xE4_\xEFY\xAC\x93\x9F\xFE\xB1\xE4\xE9u\xE5\xD6\xF2\x97 @ZO\x8D9\xBF*\xBD\xC7e6 ,\xB5\x99\xF7\x9C
+\x9Awҧ
e \xD3K\x93\xE1ʜJ\xDD\xC3\xB4\xA2
+\xB3Ţի\x9E\xD6
\xE8\x9A\xD9Q\x8CD'&0\x93\xA1\xCEN)\xC7\xCD
+\x85\xA66Jkij{,ޖʤ]΋]3\xCDv>S\x8Fl\x88\xFF\xE0ɶf:\x9E\xBC\xE3N\xFEK\xB3b8.\xD8
>	\xE3\xF1\xAA\xD6J\xBF\xF0\\xA0Z[\x9BӰ\x99L\xD64	\xCDM\xADf\s\xBA65\xA2\x99\xA5\x9F\xA0ՠB\xD9\xE5\xA3k\xA66\x8C\xC9\xFAmT\x80\xCC
oӚ@\xD5\xC9\xFB\x9C<.\xCA\\xBAb\xF4\xC5\xF5:\xAF\xD3!I$a\xCDč\xA7\x9C\xD6T\xE4
|ļ\xC9r\xBBcodȢ\x8D\xD6U\x90\x83\xE3\xF1 \xADُh\x9B֫Α~H\xAF?\xF5}\xED\xA3ii\xEB\x8ABT\xC5\xE0\xDEm\xB5<\x99\xB5\xC2\xD4\xE2\xD1`	
\xA4\xB8\xCEDBWN\xA7\x99N\xC7ᖶ\xCA5\xF9!\xB3į蜏\x8D\xE4:\xD3H\xFEΆ\xA9\xDD\xD0-\xC4V\xE1~\xAE:\x95"&γG|6)'5\xAAo\x8E:\xAA\x9Bӊ\xB7$iASŜ\xBE\xC5bPN\xEBj\xB3\x8By\xCC\xEBL\xB3ժa\xE0\xFB\xB7a\xAC\xA1\xC7\xE2F\xF1tݥZ\xDBgG(
\xB9\xC08U\xC9e=^Pg\xE1\xC9c(\xF2\x97 \x9A\xF4\xB3r\xDC>|\xE5t\x9A7&\x93\xCD\xCED\xD1g\xDCDr\xB6X\x83\xC5BQ\x88^\xB9N\x8F\x{159E7D}\xEFH\xA5\xDAv,\x93\xB9\x9E\xAD\xCC\xE2\xEA at BKRZ\xF6y]\x85L\xBE{b\xE6,a>z,N{\\xB6\xBD\xCDD\x82Dr\xA8\xFC\xC9=\xC0\xACa-\xE0|2.\x91X"]\xD8\ס\xFA\xFBL\xFE\x84E\x93q\xA8j\x99\x91\xEE\xD6\xD2\xFAeGGW;\xC6\xC3\\xAE\xBB\xF3D\xFA
+\xB0\xB3\xA9\xAD(z6\xEE\xEC}\xEE\xC5
+q\xFAj\xBA\xBD*
ot\xAC\xD9=\x9Ft\xBF\xFF\x8E\xC7B<\xDE\xD2,X\x95\xE3\x{1390FE}\xD83L.\xA8)\xC3s\xB9\xC0\x8B9\xDB	_бӪ\xAA~\xAAs\xF2[,\xCF\\x8F3\xF5C\xD3[\x93$

ֻZ/a"E\xFE\x84HU]1YJj\x98\xCF\xE3\xE8(&m{\xC64\xC6b84\x84\x99LK\x9F\xD60\x93у\xBB\xFB\xA7iojJ\xFA\>\xC1\xB2\xBB\x88\x96\x91\xBFP\xD0#L~\xC7i\xC8Ճb\x95J\xFA
\xF3_u\xB9\x8B\xE1PN\x8D
p\xB9Pp\x89\xB0\xDEcq\xFD\xC7v\xB6^\xB1XD\xFDEX\xBBTw\x9Ab5MMa\xA1`
+\xB7\xCD&L\xA4\xC8_\x82\xD0\x8Ba&C	\x8BnAe\xB3\xD9\xC0\xB2	\xA5R\xFA\\x99\xC3|\xDEw \x94TJo\xF1\x95
+NNzO\xC62\x99Z\xE7\xFA|\x9E\xA9-\xA6RX,\x9Ac\x96\xB1P\xC0\xB11\xA6YC\x8F\xC5\xDBlI\xE6\xF3\xFA\x8F-wb\xAD
2uZU>\x85\x897`~NG\xC82\xEC\xDA{\xF6\xC0e\x97@mrr\xDBE[\xE1}7\xC2\xFF\xC8+\xAE\x80\x806\x93r\x9AQ\xCDf\xB7\xFD\x9FA\xDA\xCE[:6`\xF2\F\xA8g\xCE l\x83x\x8C\xB7 tl^\xE5\xBC\xE0\xA7?P`\xD7ż\xA0c\xF3*'\x9E>]\x80\\xCF[:6\xAFrʭ\xD6[\xE7\xCE\xC1\xAD\xE4-\x88\x80 
\x9BW9`\xE7\xE3\x8F\xC3-\x89\xB7
4lj\xE5\xBC\xF0\xA9\xA7 \xB0g7oA(\xD8\xD4\xCA	\xF8\xC3" \xFC\xF5\x87x\xCB! @\xC1\xA6VN\xB9\xD5Z>t\x88\xB7tl^'\x81\x88cS\x8F\x9CQ\x86PN\x81\x88B(\xA7\x80 at D!\x94S@ \xA2\xCA) Q\xE5\x88(\x84r
+DB9"
+\xA1\x9C\x85PN\x81\x88B(\xA7\x80 at D!\x94S@ \xA2\xCA) Q\xE5\x88(\x84r
+DB9"
+\xA1\x9C\x85PN\x81\x88B(\xA7\x80 at D!\x94S@ \xA2\xCA) Q\xE5\x88(\x84r
+DB9"
+\xA1\x9C\x85PN\x81\x88B(\xA7\x80 at D!\x94S@ \xA2\xCA) Q\xE5\x88(\xFE\xD0N\xC0o~\x97\x80I    IEND\xAEB`\x82
\ No newline at end of file

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertionfailederror.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertionfailederror.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertionfailederror.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,14 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+
+    # Thrown by Test::Unit::Assertions when an assertion fails.
+    class AssertionFailedError < StandardError
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertions.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertions.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/assertions.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,1149 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+#             Copyright (c) 2009 Kouhei Sutou.
+# License:: Ruby license.
+
+require 'test/unit/assertionfailederror'
+require 'test/unit/util/backtracefilter'
+require 'test/unit/util/method-owner-finder'
+require 'test/unit/diff'
+
+module Test
+  module Unit
+
+    ##
+    # Test::Unit::Assertions contains the standard Test::Unit assertions.
+    # Assertions is included in Test::Unit::TestCase.
+    #
+    # To include it in your own code and use its functionality, you simply
+    # need to rescue Test::Unit::AssertionFailedError. Additionally you may
+    # override add_assertion to get notified whenever an assertion is made.
+    #
+    # Notes:
+    # * The message to each assertion, if given, will be propagated with the
+    #   failure.
+    # * It is easy to add your own assertions based on assert_block().
+    #
+    # = Example Custom Assertion
+    #
+    #   def deny(boolean, message = nil)
+    #     message = build_message message, '<?> is not false or nil.', boolean
+    #     assert_block message do
+    #       not boolean
+    #     end
+    #   end
+
+    module Assertions
+
+      ##
+      # The assertion upon which all other assertions are based. Passes if the
+      # block yields true.
+      #
+      # Example:
+      #   assert_block "Couldn't do the thing" do
+      #     do_the_thing
+      #   end
+
+      public
+      def assert_block(message="assert_block failed.") # :yields: 
+        _wrap_assertion do
+          if (! yield)
+            raise AssertionFailedError.new(message.to_s)
+          end
+        end
+      end
+
+      ##
+      # Asserts that +boolean+ is not false or nil.
+      #
+      # Example:
+      #   assert [1, 2].include?(5)
+
+      public
+      def assert(boolean, message=nil)
+        _wrap_assertion do
+          assert_block("assert should not be called with a block.") { !block_given? }
+          assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
+        end
+      end
+
+      ##
+      # Passes if +expected+ == +actual.
+      #
+      # Note that the ordering of arguments is important, since a helpful
+      # error message is generated when this one fails that tells you the
+      # values of expected and actual.
+      #
+      # Example:
+      #   assert_equal 'MY STRING', 'my string'.upcase
+
+      public
+      def assert_equal(expected, actual, message=nil)
+        diff = AssertionMessage.delayed_diff(expected, actual)
+        full_message = build_message(message, <<EOT, expected, actual, diff)
+<?> expected but was
+<?>.?
+EOT
+        assert_block(full_message) { expected == actual }
+      end
+
+      ##
+      # Passes if the block raises one of the expected
+      # exceptions. When an expected exception is an Exception
+      # object, passes if expected_exception == actual_exception.
+      #
+      # Example:
+      #   assert_raise(RuntimeError, LoadError) do
+      #     raise 'Boom!!!'
+      #   end # -> pass
+      #
+      #   assert_raise do
+      #     raise Exception, 'Any exception should be raised!!!'
+      #   end # -> pass
+      #
+      #   assert_raise(RuntimeError.new("XXX")) {raise "XXX"} # -> pass
+      #   assert_raise(MyError.new("XXX"))      {raise "XXX"} # -> fail
+      #   assert_raise(RuntimeError.new("ZZZ")) {raise "XXX"} # -> fail
+      public
+      def assert_raise(*args, &block)
+        assert_expected_exception = Proc.new do |*_args|
+          message, assert_exception_helper, actual_exception = _args
+          expected = assert_exception_helper.expected_exceptions
+          full_message = build_message(message,
+                                       "<?> exception expected but was\n?",
+                                       expected, actual_exception)
+          assert_block(full_message) do
+            expected == [] or assert_exception_helper.expected?(actual_exception)
+          end
+        end
+        _assert_raise(assert_expected_exception, *args, &block)
+      end
+
+      ##
+      # Alias of assert_raise.
+      #
+      # Will be deprecated in 1.9, and removed in 2.0.
+
+      public
+      def assert_raises(*args, &block)
+        assert_raise(*args, &block)
+      end
+
+      ##
+      # Passes if the block raises one of the given
+      # exceptions or sub exceptions of the given exceptions.
+      #
+      # Example:
+      #   assert_raise_kind_of(SystemCallError) do
+      #     raise Errno::EACCES
+      #   end
+      def assert_raise_kind_of(*args, &block)
+        assert_expected_exception = Proc.new do |*_args|
+          message, assert_exception_helper, actual_exception = _args
+          expected = assert_exception_helper.expected_exceptions
+          full_message = build_message(message,
+                                       "<?> family exception expected " +
+                                       "but was\n?",
+                                       expected, actual_exception)
+          assert_block(full_message) do
+            assert_exception_helper.expected?(actual_exception, :kind_of?)
+          end
+        end
+        _assert_raise(assert_expected_exception, *args, &block)
+      end
+
+
+      ##
+      # Passes if +object+.instance_of?(+klass+). When +klass+ is
+      # an array of classes, it passes if any class
+      # satisfies +object.instance_of?(class).
+      #
+      # Example:
+      #   assert_instance_of(String, 'foo')            # -> pass
+      #   assert_instance_of([Fixnum, NilClass], 100)  # -> pass
+      #   assert_instance_of([Numeric, NilClass], 100) # -> fail
+
+      public
+      def assert_instance_of(klass, object, message="")
+        _wrap_assertion do
+          klasses = nil
+          klasses = klass if klass.is_a?(Array)
+          assert_block("The first parameter to assert_instance_of should be " +
+                       "a Class or an Array of Class.") do
+            if klasses
+              klasses.all? {|k| k.is_a?(Class)}
+            else
+              klass.is_a?(Class)
+            end
+          end
+          klass_message = AssertionMessage.maybe_container(klass) do |value|
+            "<#{value}>"
+          end
+          full_message = build_message(message, <<EOT, object, klass_message, object.class)
+<?> expected to be an instance of
+? but was
+<?>.
+EOT
+          assert_block(full_message) do
+            if klasses
+              klasses.any? {|k| object.instance_of?(k)}
+            else
+              object.instance_of?(klass)
+            end
+          end
+        end
+      end
+
+      ##
+      # Passes if +object+ is nil.
+      #
+      # Example:
+      #   assert_nil [1, 2].uniq!
+
+      public
+      def assert_nil(object, message="")
+        full_message = build_message(message, <<EOT, object)
+<?> expected to be nil.
+EOT
+        assert_block(full_message) { object.nil? }
+      end
+
+      ##
+      # Passes if +object+.kind_of?(+klass+). When +klass+ is
+      # an array of classes or modules, it passes if any
+      # class or module satisfies +object.kind_of?(class_or_module).
+      #
+      # Example:
+      #   assert_kind_of(Object, 'foo')                # -> pass
+      #   assert_kind_of([Fixnum, NilClass], 100)      # -> pass
+      #   assert_kind_of([Fixnum, NilClass], "string") # -> fail
+
+      public
+      def assert_kind_of(klass, object, message="")
+        _wrap_assertion do
+          klasses = nil
+          klasses = klass if klass.is_a?(Array)
+          assert_block("The first parameter to assert_kind_of should be " +
+                       "a kind_of Module or an Array of a kind_of Module.") do
+            if klasses
+              klasses.all? {|k| k.kind_of?(Module)}
+            else
+              klass.kind_of?(Module)
+            end
+          end
+          klass_message = AssertionMessage.maybe_container(klass) do |value|
+            "<#{value}>"
+          end
+          full_message = build_message(message,
+                                       "<?> expected to be kind_of\\?\n" +
+                                       "? but was\n" +
+                                       "<?>.",
+                                       object,
+                                       klass_message,
+                                       object.class)
+          assert_block(full_message) do
+            if klasses
+              klasses.any? {|k| object.kind_of?(k)}
+            else
+              object.kind_of?(klass)
+            end
+          end
+        end
+      end
+
+      ##
+      # Passes if +object+ .respond_to? +method+
+      #
+      # Example:
+      #   assert_respond_to 'bugbear', :slice
+
+      public
+      def assert_respond_to(object, method, message="")
+        _wrap_assertion do
+          full_message = build_message(message,
+                                       "<?>.kind_of\\?(Symbol) or\n" +
+                                       "<?>.respond_to\\?(:to_str) expected",
+                                       method, method)
+          assert_block(full_message) do
+            method.kind_of?(Symbol) or method.respond_to?(:to_str)
+          end
+          full_message = build_message(message,
+                                       "<?>.respond_to\\?(?) expected\n" +
+                                       "(Class: <?>)",
+                                       object, method, object.class)
+          assert_block(full_message) {object.respond_to?(method)}
+        end
+      end
+
+      ##
+      # Passes if +string+ =~ +pattern+.
+      #
+      # Example:
+      #   assert_match(/\d+/, 'five, 6, seven')
+
+      public
+      def assert_match(pattern, string, message="")
+        _wrap_assertion do
+          pattern = case(pattern)
+            when String
+              Regexp.new(Regexp.escape(pattern))
+            else
+              pattern
+          end
+          full_message = build_message(message, "<?> expected to be =~\n<?>.", string, pattern)
+          assert_block(full_message) { string =~ pattern }
+        end
+      end
+
+      ##
+      # Passes if +actual+ .equal? +expected+ (i.e. they are the same
+      # instance).
+      #
+      # Example:
+      #   o = Object.new
+      #   assert_same o, o
+
+      public
+      def assert_same(expected, actual, message="")
+        full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
+<?>
+with id <?> expected to be equal\\? to
+<?>
+with id <?>.
+EOT
+        assert_block(full_message) { actual.equal?(expected) }
+      end
+
+      ##
+      # Compares the +object1+ with +object2+ using +operator+.
+      #
+      # Passes if object1.__send__(operator, object2) is true.
+      #
+      # Example:
+      #   assert_operator 5, :>=, 4
+
+      public
+      def assert_operator(object1, operator, object2, message="")
+        _wrap_assertion do
+          full_message = build_message(nil, "<?>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator)
+          assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)}
+          full_message = build_message(message, <<EOT, object1, AssertionMessage.literal(operator), object2)
+<?> expected to be
+?
+<?>.
+EOT
+          assert_block(full_message) { object1.__send__(operator, object2) }
+        end
+      end
+
+      ##
+      # Passes if block does not raise an exception.
+      #
+      # Example:
+      #   assert_nothing_raised do
+      #     [1, 2].uniq
+      #   end
+
+      public
+      def assert_nothing_raised(*args)
+        _wrap_assertion do
+          if args.last.is_a?(String)
+            message = args.pop
+          else
+            message = ""
+          end
+
+          assert_exception_helper = AssertExceptionHelper.new(self, args)
+          begin
+            yield
+          rescue Exception => e
+            if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
+                assert_exception_helper.expected?(e))
+              failure_message = build_message(message, "Exception raised:\n?", e)
+              assert_block(failure_message) {false}
+            else
+              raise
+            end
+          end
+          nil
+        end
+      end
+
+      ##
+      # Flunk always fails.
+      #
+      # Example:
+      #   flunk 'Not done testing yet.'
+
+      public
+      def flunk(message="Flunked")
+        assert_block(build_message(message)){false}
+      end
+
+      ##
+      # Passes if ! +actual+ .equal? +expected+
+      #
+      # Example:
+      #   assert_not_same Object.new, Object.new
+
+      public
+      def assert_not_same(expected, actual, message="")
+        full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
+<?>
+with id <?> expected to not be equal\\? to
+<?>
+with id <?>.
+EOT
+        assert_block(full_message) { !actual.equal?(expected) }
+      end
+
+      ##
+      # Passes if +expected+ != +actual+
+      #
+      # Example:
+      #   assert_not_equal 'some string', 5
+
+      public
+      def assert_not_equal(expected, actual, message="")
+        full_message = build_message(message, "<?> expected to be != to\n<?>.", expected, actual)
+        assert_block(full_message) { expected != actual }
+      end
+
+      ##
+      # Passes if ! +object+ .nil?
+      #
+      # Example:
+      #   assert_not_nil '1 two 3'.sub!(/two/, '2')
+
+      public
+      def assert_not_nil(object, message="")
+        full_message = build_message(message, "<?> expected to not be nil.", object)
+        assert_block(full_message){!object.nil?}
+      end
+
+      ##
+      # Passes if +regexp+ !~ +string+ 
+      #
+      # Example:
+      #   assert_no_match(/two/, 'one 2 three')
+
+      public
+      def assert_no_match(regexp, string, message="")
+        _wrap_assertion do
+          assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
+          full_message = build_message(message, "<?> expected to not match\n<?>.", regexp, string)
+          assert_block(full_message) { regexp !~ string }
+        end
+      end
+
+      UncaughtThrow = {
+        NameError => /^uncaught throw \`(.+)\'$/,
+        ArgumentError => /^uncaught throw (.+)$/,
+        ThreadError => /^uncaught throw \`(.+)\' in thread /
+      } #`
+
+      ##
+      # Passes if the block throws +expected_object+
+      #
+      # Example:
+      #   assert_throw(:done) do
+      #     throw(:done)
+      #   end
+
+      public
+      def assert_throw(expected_object, message="", &proc)
+        _wrap_assertion do
+          begin
+            catch([]) {}
+          rescue TypeError
+            assert_instance_of(Symbol, expected_object,
+                               "assert_throws expects the symbol that should be thrown for its first argument")
+          end
+          assert_block("Should have passed a block to assert_throw.") do
+            block_given?
+          end
+          caught = true
+          begin
+            catch(expected_object) do
+              proc.call
+              caught = false
+            end
+            full_message = build_message(message,
+                                         "<?> should have been thrown.",
+                                         expected_object)
+            assert_block(full_message) {caught}
+          rescue NameError, ArgumentError, ThreadError => error
+            raise unless UncaughtThrow[error.class] =~ error.message
+            tag = $1
+            tag = tag[1..-1].intern if tag[0, 1] == ":"
+            full_message = build_message(message,
+                                         "<?> expected to be thrown but\n" +
+                                         "<?> was thrown.",
+                                         expected_object, tag)
+            flunk(full_message)
+          end
+        end
+      end
+
+      ##
+      # Alias of assert_throw.
+      #
+      # Will be deprecated in 1.9, and removed in 2.0.
+      def assert_throws(*args, &block)
+        assert_throw(*args, &block)
+      end
+
+      ##
+      # Passes if block does not throw anything.
+      #
+      # Example:
+      #  assert_nothing_thrown do
+      #    [1, 2].uniq
+      #  end
+
+      public
+      def assert_nothing_thrown(message="", &proc)
+        _wrap_assertion do
+          assert(block_given?, "Should have passed a block to assert_nothing_thrown")
+          begin
+            proc.call
+          rescue NameError, ArgumentError, ThreadError => error
+            raise unless UncaughtThrow[error.class] =~ error.message
+            tag = $1
+            tag = tag[1..-1].intern if tag[0, 1] == ":"
+            full_message = build_message(message,
+                                         "<?> was thrown when nothing was expected",
+                                         tag)
+            flunk(full_message)
+          end
+          assert(true, "Expected nothing to be thrown")
+        end
+      end
+
+      ##
+      # Passes if +expected_float+ and +actual_float+ are equal
+      # within +delta+ tolerance.
+      #
+      # Example:
+      #   assert_in_delta 0.05, (50000.0 / 10**6), 0.00001
+
+      public
+      def assert_in_delta(expected_float, actual_float, delta, message="")
+        _wrap_assertion do
+          {expected_float => "first float", actual_float => "second float", delta => "delta"}.each do |float, name|
+            assert_respond_to(float, :to_f, "The arguments must respond to to_f; the #{name} did not")
+          end
+          assert_operator(delta, :>=, 0.0, "The delta should not be negative")
+          full_message = build_message(message, <<EOT, expected_float, actual_float, delta)
+<?> and
+<?> expected to be within
+<?> of each other.
+EOT
+          assert_block(full_message) { (expected_float.to_f - actual_float.to_f).abs <= delta.to_f }
+        end
+      end
+
+      ##
+      # Passes if the method send returns a true value.
+      #
+      # +send_array+ is composed of:
+      # * A receiver
+      # * A method
+      # * Arguments to the method
+      #
+      # Example:
+      #   assert_send [[1, 2], :include?, 4]
+
+      public
+      def assert_send(send_array, message="")
+        _wrap_assertion do
+          assert_instance_of(Array, send_array, "assert_send requires an array of send information")
+          assert(send_array.size >= 2, "assert_send requires at least a receiver and a message name")
+          full_message = build_message(message, <<EOT, send_array[0], AssertionMessage.literal(send_array[1].to_s), send_array[2..-1])
+<?> expected to respond to
+<?(?)> with a true value.
+EOT
+          assert_block(full_message) { send_array[0].__send__(send_array[1], *send_array[2..-1]) }
+        end
+      end
+
+      ##
+      # Passes if +actual+ is a boolean value.
+      #
+      # Example:
+      #   assert_boolean(true) # -> pass
+      #   assert_boolean(nil)  # -> fail
+      def assert_boolean(actual, message=nil)
+        _wrap_assertion do
+          assert_block(build_message(message,
+                                     "<true> or <false> expected but was\n<?>",
+                                     actual)) do
+            [true, false].include?(actual)
+          end
+        end
+      end
+
+      ##
+      # Passes if +actual+ is true.
+      #
+      # Example:
+      #   assert_true(true)  # -> pass
+      #   assert_true(:true) # -> fail
+      def assert_true(actual, message=nil)
+        _wrap_assertion do
+          assert_block(build_message(message,
+                                     "<true> expected but was\n<?>",
+                                     actual)) do
+            actual == true
+          end
+        end
+      end
+
+      ##
+      # Passes if +actual+ is false.
+      #
+      # Example:
+      #   assert_false(false)  # -> pass
+      #   assert_false(nil)    # -> fail
+      def assert_false(actual, message=nil)
+        _wrap_assertion do
+          assert_block(build_message(message,
+                                     "<false> expected but was\n<?>",
+                                     actual)) do
+            actual == false
+          end
+        end
+      end
+
+      ##
+      # Passes if expression "+expected+ +operator+
+      # +actual+" is true.
+      #
+      # Example:
+      #   assert_compare(1, "<", 10)  # -> pass
+      #   assert_compare(1, ">=", 10) # -> fail
+      def assert_compare(expected, operator, actual, message=nil)
+        _wrap_assertion do
+          assert_send([["<", "<=", ">", ">="], :include?, operator.to_s])
+          case operator.to_s
+          when "<"
+            operator_description = "less than"
+          when "<="
+            operator_description = "less than or equal to"
+          when ">"
+            operator_description = "greater than"
+          when ">="
+            operator_description = "greater than or equal to"
+          end
+          template = <<-EOT
+<?> #{operator} <?> should be true
+<?> expected #{operator_description}
+<?>.
+EOT
+          full_message = build_message(message, template,
+                                       expected, actual,
+                                       expected, actual)
+          assert_block(full_message) do
+            expected.send(operator, actual)
+          end
+        end
+      end
+
+      ##
+      # Passes if assertion is failed in block.
+      #
+      # Example:
+      #   assert_fail_assertion {assert_equal("A", "B")}  # -> pass
+      #   assert_fail_assertion {assert_equal("A", "A")}  # -> fail
+      def assert_fail_assertion(message=nil)
+        _wrap_assertion do
+          full_message = build_message(message,
+                                       "Failed assertion was expected.")
+          assert_block(full_message) do
+            begin
+              yield
+              false
+            rescue AssertionFailedError
+              true
+            end
+          end
+        end
+      end
+
+      ##
+      # Passes if an exception is raised in block and its
+      # message is +expected+.
+      #
+      # Example:
+      #   assert_raise_message("exception") {raise "exception"}  # -> pass
+      #   assert_raise_message(/exc/i) {raise "exception"}       # -> pass
+      #   assert_raise_message("exception") {raise "EXCEPTION"}  # -> fail
+      #   assert_raise_message("exception") {}                   # -> fail
+      def assert_raise_message(expected, message=nil)
+        _wrap_assertion do
+          full_message = build_message(message,
+                                       "<?> exception message expected " +
+                                       "but none was thrown.",
+                                       expected)
+          exception = nil
+          assert_block(full_message) do
+            begin
+              yield
+              false
+            rescue Exception => exception
+              true
+            end
+          end
+
+          actual = exception.message
+          diff = AssertionMessage.delayed_diff(expected, actual)
+          full_message =
+            build_message(message,
+                          "<?> exception message expected but was\n" +
+                          "<?>.?", expected, actual, diff)
+          assert_block(full_message) do
+            if expected.is_a?(Regexp)
+              expected =~ actual
+            else
+              expected == actual
+            end
+          end
+        end
+      end
+
+      ##
+      # Passes if +object+.const_defined?(+constant_name+)
+      #
+      # Example:
+      #   assert_const_defined(Test, :Unit)          # -> pass
+      #   assert_const_defined(Object, :Nonexistent) # -> fail
+      def assert_const_defined(object, constant_name, message=nil)
+        _wrap_assertion do
+          full_message = build_message(message,
+                                       "<?>.const_defined\\?(<?>) expected.",
+                                       object, constant_name)
+          assert_block(full_message) do
+            object.const_defined?(constant_name)
+          end
+        end
+      end
+
+      ##
+      # Passes if !+object+.const_defined?(+constant_name+)
+      #
+      # Example:
+      #   assert_not_const_defined(Object, :Nonexistent) # -> pass
+      #   assert_not_const_defined(Test, :Unit)          # -> fail
+      def assert_not_const_defined(object, constant_name, message=nil)
+        _wrap_assertion do
+          full_message = build_message(message,
+                                       "!<?>.const_defined\\?(<?>) expected.",
+                                       object, constant_name)
+          assert_block(full_message) do
+            !object.const_defined?(constant_name)
+          end
+        end
+      end
+
+      ##
+      # Passes if +object+.+predicate+
+      #
+      # Example:
+      #   assert_predicate([], :empty?)  # -> pass
+      #   assert_predicate([1], :empty?) # -> fail
+      def assert_predicate(object, predicate, message=nil)
+        _wrap_assertion do
+          assert_respond_to(object, predicate, message)
+          actual = object.send(predicate)
+          full_message = build_message(message,
+                                       "<?>.? is true value expected but was\n" +
+                                       "<?>",
+                                       object,
+                                       AssertionMessage.literal(predicate),
+                                       actual)
+          assert_block(full_message) do
+            actual
+          end
+        end
+      end
+
+      ##
+      # Passes if +object+.+predicate+
+      #
+      # Example:
+      #   assert_not_predicate([1], :empty?) # -> pass
+      #   assert_not_predicate([], :empty?)  # -> fail
+      def assert_not_predicate(object, predicate, message=nil)
+        _wrap_assertion do
+          assert_respond_to(object, predicate, message)
+          actual = object.send(predicate)
+          full_message = build_message(message,
+                                       "<?>.? is false value expected but was\n" +
+                                       "<?>",
+                                       object,
+                                       AssertionMessage.literal(predicate),
+                                       actual)
+          assert_block(full_message) do
+            not actual
+          end
+        end
+      end
+
+      ##
+      # Builds a failure message.  +head+ is added before the +template+ and
+      # +arguments+ replaces the '?'s positionally in the template.
+
+      public
+      def build_message(head, template=nil, *arguments)
+        template &&= template.chomp
+        return AssertionMessage.new(head, template, arguments)
+      end
+
+      private
+      def _wrap_assertion
+        @_assertion_wrapped ||= false
+        unless (@_assertion_wrapped)
+          @_assertion_wrapped = true
+          begin
+            add_assertion
+            return yield
+          ensure
+            @_assertion_wrapped = false
+          end
+        else
+          return yield
+        end
+      end
+      
+      ##
+      # Called whenever an assertion is made.  Define this in classes that
+      # include Test::Unit::Assertions to record assertion counts.
+
+      private
+      def add_assertion
+      end
+
+      ##
+      # Select whether or not to use the pretty-printer. If this option is set
+      # to false before any assertions are made, pp.rb will not be required.
+
+      public
+      def self.use_pp=(value)
+        AssertionMessage.use_pp = value
+      end
+
+      # :stopdoc:
+      private
+      def _assert_raise(assert_expected_exception, *args, &block)
+        _wrap_assertion do
+          if args.last.is_a?(String)
+            message = args.pop
+          else
+            message = ""
+          end
+
+          assert_exception_helper = AssertExceptionHelper.new(self, args)
+          expected = assert_exception_helper.expected_exceptions
+          actual_exception = nil
+          full_message = build_message(message,
+                                       "<?> exception expected " +
+                                       "but none was thrown.",
+                                       expected)
+          assert_block(full_message) do
+            begin
+              yield
+              false
+            rescue Exception => actual_exception
+              true
+            end
+          end
+          assert_expected_exception.call(message, assert_exception_helper,
+                                         actual_exception)
+          actual_exception
+        end
+      end
+
+      class AssertionMessage
+        @use_pp = true
+        class << self
+          attr_accessor :use_pp
+
+          def literal(value)
+            Literal.new(value)
+          end
+
+          def delayed_literal(&block)
+            DelayedLiteral.new(block)
+          end
+
+          def maybe_container(value, &formatter)
+            MaybeContainer.new(value, &formatter)
+          end
+
+          MAX_DIFF_TARGET_STRING_SIZE = 300
+          def diff_target_string?(string)
+            if string.respond_to?(:bytesize)
+              string.bytesize < MAX_DIFF_TARGET_STRING_SIZE
+            else
+              string.size < MAX_DIFF_TARGET_STRING_SIZE
+            end
+          end
+
+          def delayed_diff(from, to)
+            delayed_literal do
+              if !from.is_a?(String) or !to.is_a?(String)
+                from = convert(from)
+                to = convert(to)
+              end
+
+              diff = nil
+              diff = "" if !diff_target_string?(from) or !diff_target_string?(to)
+              diff ||= Diff.readable(from, to)
+              if /^[-+]/ !~ diff
+                diff = ""
+              elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff
+                diff = "\n\ndiff:\n#{diff}"
+              else
+                diff = ""
+              end
+
+              if Diff.need_fold?(diff)
+                folded_diff = Diff.folded_readable(from, to)
+                diff << "\n\nfolded diff:\n#{folded_diff}"
+              end
+
+              diff
+            end
+          end
+
+          def convert(object)
+            case object
+            when Exception
+              <<EOM.chop
+Class: <#{convert(object.class)}>
+Message: <#{convert(object.message)}>
+---Backtrace---
+#{Util::BacktraceFilter.filter_backtrace(object.backtrace).join("\n")}
+---------------
+EOM
+            else
+              if use_pp
+                begin
+                  require 'pp' unless defined?(PP)
+                  return PP.pp(object, '').chomp
+                rescue LoadError
+                  self.use_pp = false
+                end
+              end
+              object.inspect
+            end
+          end
+        end
+
+        class Literal
+          def initialize(value)
+            @value = value
+          end
+
+          def inspect
+            @value.to_s
+          end
+        end
+
+        class DelayedLiteral
+          def initialize(value)
+            @value = value
+          end
+
+          def inspect
+            @value.call.to_s
+          end
+        end
+
+        class MaybeContainer
+          def initialize(value, &formatter)
+            @value = value
+            @formatter = formatter
+          end
+
+          def inspect
+            if @value.is_a?(Array)
+              values = @value.collect do |value|
+                @formatter.call(AssertionMessage.convert(value))
+              end
+              "[#{values.join(', ')}]"
+            else
+              @formatter.call(AssertionMessage.convert(@value))
+            end
+          end
+        end
+
+        class Template
+          def self.create(string)
+            parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : [])
+            self.new(parts)
+          end
+
+          attr_reader :count
+
+          def initialize(parts)
+            @parts = parts
+            @count = parts.find_all{|e| e == '?'}.size
+          end
+
+          def result(parameters)
+            raise "The number of parameters does not match the number of substitutions." if(parameters.size != count)
+            params = parameters.dup
+            @parts.collect{|e| e == '?' ? params.shift : e.gsub(/\\\?/m, '?')}.join('')
+          end
+        end
+
+        include Util::BacktraceFilter
+
+        def initialize(head, template_string, parameters)
+          @head = head
+          @template_string = template_string
+          @parameters = parameters
+        end
+
+        def convert(object)
+          self.class.convert(object)
+        end
+
+        def template
+          @template ||= Template.create(@template_string)
+        end
+
+        def add_period(string)
+          (string =~ /\.\Z/ ? string : string + '.')
+        end
+
+        def to_s
+          message_parts = []
+          if (@head)
+            head = @head.to_s 
+            unless(head.empty?)
+              message_parts << add_period(head)
+            end
+          end
+          tail = template.result(@parameters.collect{|e| convert(e)})
+          message_parts << tail unless(tail.empty?)
+          message_parts.join("\n")
+        end
+      end
+
+      class AssertExceptionHelper
+        class WrappedException
+          def initialize(exception)
+            @exception = exception
+          end
+
+          def inspect
+            if default_inspect?
+              "#{@exception.class.inspect}(#{@exception.message.inspect})"
+            else
+              @exception.inspect
+            end
+          end
+
+          def method_missing(name, *args, &block)
+            @exception.send(name, *args, &block)
+          end
+
+          private
+          def default_inspect?
+            inspect_method = @exception.method(:inspect)
+            if inspect_method.respond_to?(:owner) and
+                inspect_method.owner == Exception
+              true
+            else
+              default_inspect_method = Exception.instance_method(:inspect)
+              default_inspect_method.bind(@exception).call == @exception.inspect
+            end
+          end
+        end
+
+        def initialize(test_case, expected_exceptions)
+          @test_case = test_case
+          @expected_exceptions = expected_exceptions
+          @expected_classes, @expected_modules, @expected_objects =
+            split_expected_exceptions(expected_exceptions)
+        end
+
+        def expected_exceptions
+          exceptions = @expected_exceptions.collect do |exception|
+            if exception.is_a?(Exception)
+              WrappedException.new(exception)
+            else
+              exception
+            end
+          end
+          if exceptions.size == 1
+            exceptions[0]
+          else
+            exceptions
+          end
+        end
+
+        def expected?(actual_exception, equality=nil)
+          equality ||= :instance_of?
+          expected_class?(actual_exception, equality) or
+            expected_module?(actual_exception) or
+            expected_object?(actual_exception)
+        end
+
+        private
+        def split_expected_exceptions(expected_exceptions)
+          exception_modules = []
+          exception_objects = []
+          exception_classes = []
+          expected_exceptions.each do |exception_type|
+            if exception_type.instance_of?(Module)
+              exception_modules << exception_type
+            elsif exception_type.is_a?(Exception)
+              exception_objects << exception_type
+            else
+              @test_case.send(:assert,
+                              Exception >= exception_type,
+                              "Should expect a class of exception, " +
+                              "#{exception_type}")
+              exception_classes << exception_type
+            end
+          end
+          [exception_classes, exception_modules, exception_objects]
+        end
+
+        def expected_class?(actual_exception, equality)
+          @expected_classes.any? do |expected_class|
+            actual_exception.send(equality, expected_class)
+          end
+        end
+
+        def expected_module?(actual_exception)
+          @expected_modules.any? do |expected_module|
+            actual_exception.is_a?(expected_module)
+          end
+        end
+
+        def expected_object?(actual_exception)
+          @expected_objects.any? do |expected_object|
+            expected_object == actual_exception or
+              fallback_exception_object_equal(expected_object, actual_exception)
+          end
+        end
+
+        def fallback_exception_object_equal(expected_object, actual_exception)
+          owner = Util::MethodOwnerFinder.find(expected_object, :==)
+          if owner == Kernel or owner == Exception
+            expected_object.class == actual_exception.class and
+              expected_object.message == actual_exception.message
+          else
+            false
+          end
+        end
+      end
+
+      # :startdoc:
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/attribute.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/attribute.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/attribute.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,125 @@
+module Test
+  module Unit
+    module Attribute
+      class << self
+        def included(base)
+          base.extend(BaseClassMethods)
+          base.extend(ClassMethods)
+        end
+      end
+
+      module BaseClassMethods
+        def attributes_table
+          {}
+        end
+      end
+
+      module ClassMethods
+        def method_added(name)
+          super
+          return unless defined?(@current_attributes)
+
+          attributes = {}
+          kept_attributes = {}
+          @current_attributes.each do |attribute_name, attribute|
+            attributes[attribute_name] = attribute[:value]
+            kept_attributes[attribute_name] = attribute if attribute[:keep]
+          end
+          set_attributes(name, attributes)
+          @current_attributes = kept_attributes
+        end
+
+        def attribute(name, value, options={}, *method_names)
+          unless options.is_a?(Hash)
+            method_names << options
+            options = {}
+          end
+          @current_attributes ||= {}
+          if method_names.empty?
+            @current_attributes[name] = options.merge(:value => value)
+          else
+            method_names.each do |method_name|
+              set_attributes(method_name, {name => value})
+            end
+          end
+        end
+
+        def attributes_table
+          @attributes_table ||= {}
+          super.merge(@attributes_table)
+        end
+
+        def set_attributes(method_name, new_attributes)
+          return if new_attributes.empty?
+          method_name = normalize_method_name(method_name)
+          @attributes_table ||= {}
+          @attributes_table[method_name] ||= {}
+          current_attributes = @attributes_table[method_name]
+          new_attributes.each do |key, value|
+            key = normalize_attribute_name(key)
+            observers = attribute_observers(key) || []
+            observers.each do |observer|
+              observer.call(self,
+                            key,
+                            (attributes(method_name) || {})[key],
+                            value,
+                            method_name)
+            end
+            current_attributes[key] = value
+          end
+        end
+
+        def attributes(method_name)
+          method_name = normalize_method_name(method_name)
+          attributes = attributes_table[method_name]
+          ancestors[1..-1].each do |ancestor|
+            if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute
+              parent_attributes = ancestor.attributes(method_name)
+              if attributes
+                attributes = (parent_attributes || {}).merge(attributes)
+              else
+                attributes = parent_attributes
+              end
+              break
+            end
+          end
+          attributes
+        end
+
+        def get_attribute(method_name, attribute_name)
+          attribute_name = normalize_attribute_name(attribute_name)
+          (attributes(method_name) || {})[attribute_name]
+        end
+
+        @@attribute_observers = {}
+        def register_attribute_observer(attribute_name, observer=Proc.new)
+          attribute_name = normalize_attribute_name(attribute_name)
+          @@attribute_observers[attribute_name] ||= []
+          @@attribute_observers[attribute_name] << observer
+        end
+
+        def attribute_observers(attribute_name)
+          attribute_name = normalize_attribute_name(attribute_name)
+          @@attribute_observers[attribute_name]
+        end
+
+        private
+        def normalize_attribute_name(name)
+          name.to_s
+        end
+
+        def normalize_method_name(name)
+          name.to_s
+        end
+      end
+
+      def attributes
+        self.class.attributes(@method_name) || {}
+      end
+
+      def [](name)
+        self.class.get_attribute(@method_name, name)
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/autorunner.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/autorunner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/autorunner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,344 @@
+require 'test/unit/color-scheme'
+require 'optparse'
+
+module Test
+  module Unit
+    class AutoRunner
+      RUNNERS = {}
+      COLLECTORS = {}
+      ADDITIONAL_OPTIONS = []
+
+      class << self
+        def register_runner(id, runner_builder=Proc.new)
+          RUNNERS[id] = runner_builder
+          RUNNERS[id.to_s] = runner_builder
+        end
+
+        def runner(id)
+          RUNNERS[id.to_s]
+        end
+
+        def register_collector(id, collector_builder=Proc.new)
+          COLLECTORS[id] = collector_builder
+          COLLECTORS[id.to_s] = collector_builder
+        end
+
+        def collector(id)
+          COLLECTORS[id.to_s]
+        end
+
+        def register_color_scheme(id, scheme)
+          ColorScheme[id] = scheme
+        end
+
+        def setup_option(option_builder=Proc.new)
+          ADDITIONAL_OPTIONS << option_builder
+        end
+      end
+
+      def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
+        r = new(force_standalone || standalone?, &block)
+        r.base = default_dir
+        r.process_args(argv)
+        r.run
+      end
+      
+      def self.standalone?
+        return false unless("-e" == $0)
+        ObjectSpace.each_object(Class) do |klass|
+          return false if(klass < TestCase)
+        end
+        true
+      end
+
+      register_collector(:descendant) do |auto_runner|
+        require 'test/unit/collector/descendant'
+        collector = Collector::Descendant.new
+        collector.filter = auto_runner.filters
+        collector.collect($0.sub(/\.rb\Z/, ''))
+      end
+
+      register_collector(:load) do |auto_runner|
+        require 'test/unit/collector/load'
+        collector = Collector::Load.new
+        collector.patterns.concat(auto_runner.pattern) if auto_runner.pattern
+        collector.excludes.concat(auto_runner.exclude) if auto_runner.exclude
+        collector.base = auto_runner.base
+        collector.filter = auto_runner.filters
+        collector.collect(*auto_runner.to_run)
+      end
+
+      # deprecated
+      register_collector(:object_space) do |auto_runner|
+        require 'test/unit/collector/objectspace'
+        c = Collector::ObjectSpace.new
+        c.filter = auto_runner.filters
+        c.collect($0.sub(/\.rb\Z/, ''))
+      end
+
+      # deprecated
+      register_collector(:dir) do |auto_runner|
+        require 'test/unit/collector/dir'
+        c = Collector::Dir.new
+        c.filter = auto_runner.filters
+        c.pattern.concat(auto_runner.pattern) if auto_runner.pattern
+        c.exclude.concat(auto_runner.exclude) if auto_runner.exclude
+        c.base = auto_runner.base
+        $:.push(auto_runner.base) if auto_runner.base
+        c.collect(*(auto_runner.to_run.empty? ? ['.'] : auto_runner.to_run))
+      end
+
+      attr_reader :suite, :runner_options
+      attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
+      attr_accessor :color_scheme
+      attr_writer :runner, :collector
+
+      def initialize(standalone)
+        Unit.run = true
+        @standalone = standalone
+        @runner = default_runner
+        @collector = default_collector
+        @filters = []
+        @to_run = []
+        @color_scheme = ColorScheme.default
+        @runner_options = {}
+        @default_arguments = []
+        @workdir = nil
+        config_file = "test-unit.yml"
+        if File.exist?(config_file)
+          load_config(config_file)
+        else
+          global_config_file = File.expand_path("~/.test-unit.xml")
+          load_config(global_config_file) if File.exist?(global_config_file)
+        end
+        yield(self) if block_given?
+      end
+
+      def process_args(args = ARGV)
+        default_arguments = @default_arguments.dup
+        begin
+          @default_arguments.concat(args)
+          options.order!(@default_arguments) {|arg| @to_run << arg}
+        rescue OptionParser::ParseError => e
+          puts e
+          puts options
+          exit(false)
+        else
+          @filters << proc{false} unless(@filters.empty?)
+        end
+        not @to_run.empty?
+      ensure
+        @default_arguments = default_arguments
+      end
+
+      def options
+        @options ||= OptionParser.new do |o|
+          o.banner = "Test::Unit automatic runner."
+          o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
+
+          o.on
+          o.on('-r', '--runner=RUNNER', RUNNERS,
+               "Use the given RUNNER.",
+               "(" + keyword_display(RUNNERS) + ")") do |r|
+            @runner = r
+          end
+
+          if (@standalone)
+            o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
+              @base = b
+            end
+
+            o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
+              @workdir = w
+            end
+
+            o.on('-a', '--add=TORUN', Array,
+                 "Add TORUN to the list of things to run;",
+                 "can be a file or a directory.") do |a|
+              @to_run.concat(a)
+            end
+
+            @pattern = []
+            o.on('-p', '--pattern=PATTERN', Regexp,
+                 "Match files to collect against PATTERN.") do |e|
+              @pattern << e
+            end
+
+            @exclude = []
+            o.on('-x', '--exclude=PATTERN', Regexp,
+                 "Ignore files to collect against PATTERN.") do |e|
+              @exclude << e
+            end
+          end
+
+          o.on('-n', '--name=NAME', String,
+               "Runs tests matching NAME.",
+               "(patterns may be used).") do |n|
+            n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
+            case n
+            when Regexp
+              @filters << proc{|t| n =~ t.method_name ? true : nil}
+            else
+              @filters << proc{|t| n == t.method_name ? true : nil}
+            end
+          end
+
+          o.on('-t', '--testcase=TESTCASE', String,
+               "Runs tests in TestCases matching TESTCASE.",
+               "(patterns may be used).") do |n|
+            n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
+            case n
+            when Regexp
+              @filters << proc{|t| n =~ t.class.name ? true : nil}
+            else
+              @filters << proc{|t| n == t.class.name ? true : nil}
+            end
+          end
+
+          priority_filter = Proc.new do |test|
+            if @filters.size > 2
+              nil
+            else
+              Priority::Checker.new(test).need_to_run? or nil
+            end
+          end
+          o.on("--[no-]priority-mode",
+               "Runs some tests based on their priority.") do |priority_mode|
+            if priority_mode
+              Priority.enable
+              @filters |= [priority_filter]
+            else
+              Priority.disable
+              @filters -= [priority_filter]
+            end
+          end
+
+          o.on("--default-priority=PRIORITY",
+               Priority.available_values,
+               "Uses PRIORITY as default priority",
+               "(#{keyword_display(Priority.available_values)})") do |priority|
+            Priority.default = priority
+          end
+
+          o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
+               "Appends directory list to $LOAD_PATH.") do |dirs|
+            $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
+          end
+
+          color_schemes = ColorScheme.all
+          o.on("--color-scheme=SCHEME", color_schemes,
+               "Use SCHEME as color scheme.",
+               "(#{keyword_display(color_schemes)})") do |scheme|
+            @color_scheme = scheme
+          end
+
+          o.on("--config=FILE",
+               "Use YAML fomat FILE content as configuration file.") do |file|
+            load_config(file)
+          end
+
+          o.on("--order=ORDER", TestCase::AVAILABLE_ORDERS,
+               "Run tests in a test case in ORDER order.",
+               "(#{keyword_display(TestCase::AVAILABLE_ORDERS)})") do |order|
+            TestCase.test_order = order
+          end
+
+          ADDITIONAL_OPTIONS.each do |option_builder|
+            option_builder.call(self, o)
+          end
+
+          o.on('--',
+               "Stop processing options so that the",
+               "remaining options will be passed to the",
+               "test."){o.terminate}
+
+          o.on('-h', '--help', 'Display this help.'){puts o; exit}
+
+          o.on_tail
+          o.on_tail('Deprecated options:')
+
+          o.on_tail('--console', 'Console runner (use --runner).') do
+            warn("Deprecated option (--console).")
+            @runner = self.class.runner(:console)
+          end
+
+          if RUNNERS[:fox]
+            o.on_tail('--fox', 'Fox runner (use --runner).') do
+              warn("Deprecated option (--fox).")
+              @runner = self.class.runner(:fox)
+            end
+          end
+
+          o.on_tail
+        end
+      end
+
+      def keyword_display(keywords)
+        keywords = keywords.collect do |keyword, _|
+          keyword.to_s
+        end.uniq.sort
+
+        i = 0
+        keywords.collect do |keyword|
+          if (i > 0 and keyword[0] == keywords[i - 1][0]) or
+              ((i < keywords.size - 1) and (keyword[0] == keywords[i + 1][0]))
+            n = 2
+          else
+            n = 1
+          end
+          i += 1
+          keyword.sub(/^(.{#{n}})([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')
+        end.join(", ")
+      end
+
+      def run
+        suite = @collector[self]
+        return false if suite.nil?
+        runner = @runner[self]
+        return false if runner.nil?
+        @runner_options[:color_scheme] ||= @color_scheme
+        Dir.chdir(@workdir) if @workdir
+        runner.run(suite, @runner_options).passed?
+      end
+
+      def load_config(file)
+        require 'yaml'
+        config = YAML.load(File.read(file))
+        runner_name = config["runner"]
+        @runner = self.class.runner(runner_name) || @runner
+        @collector = self.class.collector(config["collector"]) || @collector
+        (config["color_schemes"] || {}).each do |name, options|
+          ColorScheme[name] = options
+        end
+        runner_options = {}
+        (config["#{runner_name}_options"] || {}).each do |key, value|
+          key = key.to_sym
+          value = ColorScheme[value] if key == :color_scheme
+          if key == :arguments
+            @default_arguments.concat(value.split)
+          else
+            runner_options[key.to_sym] = value
+          end
+        end
+        @runner_options = @runner_options.merge(runner_options)
+      end
+
+      private
+      def default_runner
+        if ENV["EMACS"] == "t"
+          self.class.runner(:emacs)
+        else
+          self.class.runner(:console)
+        end
+      end
+
+      def default_collector
+        self.class.collector(@standalone ? :load : :descendant)
+      end
+    end
+  end
+end
+
+require 'test/unit/runner/console'
+require 'test/unit/runner/emacs'
+require 'test/unit/runner/tap'

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/descendant.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/descendant.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/descendant.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,23 @@
+require 'test/unit/collector'
+
+module Test
+  module Unit
+    module Collector
+      class Descendant
+        include Collector
+
+        NAME = 'collected from the subclasses of TestCase'
+
+        def collect(name=NAME)
+          suite = TestSuite.new(name)
+          sub_suites = []
+          TestCase::DESCENDANTS.each do |descendant_test_case|
+            add_suite(sub_suites, descendant_test_case.suite)
+          end
+          sort(sub_suites).each {|s| suite << s}
+          suite
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/dir.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/dir.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/dir.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,108 @@
+require 'test/unit/testsuite'
+require 'test/unit/collector'
+
+module Test
+  module Unit
+    module Collector
+      class Dir
+        include Collector
+
+        attr_reader :pattern, :exclude
+        attr_accessor :base
+
+        def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil)
+          super()
+          @dir = dir
+          @file = file
+          @object_space = object_space
+          @req = req
+          @pattern = [/\btest_.*\.rb\Z/m]
+          @exclude = []
+          @base = nil
+        end
+
+        def collect(*from)
+          basedir = @base
+          $:.push(basedir) if basedir
+          if(from.empty?)
+            recursive_collect('.', find_test_cases)
+          elsif(from.size == 1)
+            recursive_collect(from.first, find_test_cases)
+          else
+            suites = []
+            from.each do |f|
+              suite = recursive_collect(f, find_test_cases)
+              suites << suite unless(suite.tests.empty?)
+            end
+            suite = TestSuite.new("[#{from.join(', ')}]")
+            sort(suites).each{|s| suite << s}
+            suite
+          end
+        ensure
+          $:.delete_at($:.rindex(basedir)) if basedir
+        end
+
+        def find_test_cases(ignore=[])
+          cases = []
+          @object_space.each_object(Class) do |c|
+            cases << c if(c < TestCase && !ignore.include?(c))
+          end
+          ignore.concat(cases)
+          cases
+        end
+
+        def recursive_collect(name, already_gathered)
+          sub_suites = []
+          path = realdir(name)
+          if @file.directory?(path)
+	    dir_name = name unless name == '.'
+            @dir.entries(path).each do |e|
+              next if(e == '.' || e == '..')
+              e_name = dir_name ? @file.join(dir_name, e) : e
+              if @file.directory?(realdir(e_name))
+                next if /\A(?:CVS|\.svn)\z/ =~ e
+                sub_suite = recursive_collect(e_name, already_gathered)
+                sub_suites << sub_suite unless(sub_suite.empty?)
+              else
+                next if /~\z/ =~ e_name or /\A\.\#/ =~ e
+                if @pattern and !@pattern.empty?
+                  next unless @pattern.any? {|pat| pat =~ e_name}
+                end
+                if @exclude and !@exclude.empty?
+                  next if @exclude.any? {|pat| pat =~ e_name}
+                end
+                collect_file(e_name, sub_suites, already_gathered)
+              end
+            end
+          else
+            collect_file(name, sub_suites, already_gathered)
+          end
+          suite = TestSuite.new(@file.basename(name))
+          sort(sub_suites).each{|s| suite << s}
+          suite
+        end
+
+        def collect_file(name, suites, already_gathered)
+          dir = @file.dirname(@file.expand_path(name, @base))
+          $:.unshift(dir)
+          if(@req)
+            @req.require(name)
+          else
+            require(name)
+          end
+          find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)}
+        ensure
+          $:.delete_at($:.rindex(dir)) if(dir)
+        end
+
+	def realdir(path)
+	  if @base
+	    @file.join(@base, path)
+	  else
+	    path
+	  end
+	end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/load.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/load.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/load.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,137 @@
+require 'pathname'
+
+require 'test/unit/testsuite'
+require 'test/unit/collector'
+
+module Test
+  module Unit
+    module Collector
+      class Load
+        include Collector
+
+        attr_reader :patterns, :excludes, :base
+
+        def initialize
+          super
+          @system_excludes = [/~\z/, /\A\.\#/]
+          @system_directory_excludes = [/\A(?:CVS|\.svn)\z/]
+          @patterns = [/\Atest[_\-].+\.rb\z/m]
+          @excludes = []
+          @base = nil
+        end
+
+        def base=(base)
+          base = Pathname(base) unless base.nil?
+          @base = base
+        end
+
+        def collect(*froms)
+          add_load_path(@base) do
+            froms = ["."] if froms.empty?
+            test_suites = froms.collect do |from|
+              test_suite = collect_recursive(from, find_test_cases)
+              test_suite = nil if test_suite.tests.empty?
+              test_suite
+            end.compact
+
+            if test_suites.size > 1
+              test_suite = TestSuite.new("[#{froms.join(', ')}]")
+              sort(test_suites).each do |sub_test_suite|
+                test_suite << sub_test_suite
+              end
+              test_suite
+            else
+              test_suites.first
+            end
+          end
+        end
+
+        def find_test_cases(ignore=[])
+          test_cases = []
+          TestCase::DESCENDANTS.each do |test_case|
+            test_cases << test_case unless ignore.include?(test_case)
+          end
+          ignore.concat(test_cases)
+          test_cases
+        end
+
+        private
+        def collect_recursive(name, already_gathered)
+          sub_test_suites = []
+
+          path = resolve_path(name)
+          if path.directory?
+            directories, files = path.children.partition do |child|
+              child.directory?
+            end
+
+            files.each do |child|
+              next if excluded_file?(child.basename.to_s)
+              collect_file(child, sub_test_suites, already_gathered)
+            end
+
+            directories.each do |child|
+              next if excluded_directory?(child.basename.to_s)
+              sub_test_suite = collect_recursive(child, already_gathered)
+              sub_test_suites << sub_test_suite unless sub_test_suite.empty?
+            end
+          else
+            unless excluded_file?(path.basename.to_s)
+              collect_file(path, sub_test_suites, already_gathered)
+            end
+          end
+
+          test_suite = TestSuite.new(path.basename.to_s)
+          sort(sub_test_suites).each do |sub_test_suite|
+            test_suite << sub_test_suite
+          end
+          test_suite
+        end
+
+        def collect_file(path, test_suites, already_gathered)
+          add_load_path(path.expand_path.dirname) do
+            require(path.to_s)
+            find_test_cases(already_gathered).each do |test_case|
+              add_suite(test_suites, test_case.suite)
+            end
+          end
+        end
+
+        def resolve_path(path)
+          if @base
+            @base + path
+          else
+            Pathname(path)
+          end
+        end
+
+        def add_load_path(path)
+          $LOAD_PATH.push(path.to_s) if path
+          yield
+        ensure
+          $LOAD_PATH.delete_at($LOAD_PATH.rindex(path.to_s)) if path
+        end
+
+        def excluded_directory?(base)
+          @system_directory_excludes.any? {|pattern| pattern =~ base}
+        end
+
+        def excluded_file?(base)
+          return true if @system_excludes.any? {|pattern| pattern =~ base}
+
+          patterns = @patterns || []
+          unless patterns.empty?
+            return true unless patterns.any? {|pattern| pattern =~ base}
+          end
+
+          excludes = @excludes || []
+          unless excludes.empty?
+            return true if excludes.any? {|pattern| pattern =~ base}
+          end
+
+          false
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/objectspace.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/objectspace.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector/objectspace.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,34 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/collector'
+
+module Test
+  module Unit
+    module Collector
+      class ObjectSpace
+        include Collector
+        
+        NAME = 'collected from the ObjectSpace'
+        
+        def initialize(source=::ObjectSpace)
+          super()
+          @source = source
+        end
+        
+        def collect(name=NAME)
+          suite = TestSuite.new(name)
+          sub_suites = []
+          @source.each_object(Class) do |klass|
+            if(Test::Unit::TestCase > klass)
+              add_suite(sub_suites, klass.suite)
+            end
+          end
+          sort(sub_suites).each{|s| suite << s}
+          suite
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/collector.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,43 @@
+module Test
+  module Unit
+    module Collector
+      def initialize
+        @filters = []
+      end
+
+      def filter=(filters)
+        @filters = case(filters)
+          when Proc
+            [filters]
+          when Array
+            filters
+        end
+      end
+
+      def add_suite(destination, suite)
+        to_delete = suite.tests.find_all{|t| !include?(t)}
+        to_delete.each{|t| suite.delete(t)}
+        destination << suite unless(suite.size == 0)
+      end
+
+      def include?(test)
+        return true if(@filters.empty?)
+        @filters.each do |filter|
+          result = filter[test]
+          if(result.nil?)
+            next
+          elsif(!result)
+            return false
+          else
+            return true
+          end
+        end
+        true
+      end
+
+      def sort(suites)
+        suites.sort_by {|suite| suite.name || suite.to_s}
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/color-scheme.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/color-scheme.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/color-scheme.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,90 @@
+require 'test/unit/color'
+
+module Test
+  module Unit
+    class ColorScheme
+      include Enumerable
+
+      class << self
+        @@default = nil
+        def default
+          @@default ||= new("success" => Color.new("green", :bold => true),
+                            "failure" => Color.new("red", :bold => true),
+                            "pending" => Color.new("magenta", :bold => true),
+                            "omission" => Color.new("blue", :bold => true),
+                            "notification" => Color.new("cyan", :bold => true),
+                            "error" => Color.new("yellow", :bold => true) +
+                                       Color.new("black", :foreground => false),
+                            "case" => Color.new("white", :bold => true) +
+                                       Color.new("blue", :foreground => false),
+                            "suite" => Color.new("white", :bold => true) +
+                                       Color.new("green", :foreground => false))
+        end
+
+        @@schemes = {}
+        def all
+          @@schemes.merge("default" => default)
+        end
+
+        def [](id)
+          @@schemes[id.to_s]
+        end
+
+        def []=(id, scheme_or_spec)
+          if scheme_or_spec.is_a?(self)
+            scheme = scheme_or_spec
+          else
+            scheme = new(scheme_or_spec)
+          end
+          @@schemes[id.to_s] = scheme
+        end
+      end
+
+      def initialize(scheme_spec)
+        @scheme = {}
+        scheme_spec.each do |key, color_spec|
+          self[key] = color_spec
+        end
+      end
+
+      def [](name)
+        @scheme[name.to_s]
+      end
+
+      def []=(name, color_spec)
+        @scheme[name.to_s] = make_color(color_spec)
+      end
+
+      def each(&block)
+        @scheme.each(&block)
+      end
+
+      def to_hash
+        hash = {}
+        @scheme.each do |key, color|
+          hash[key] = color
+        end
+        hash
+      end
+
+      private
+      def make_color(color_spec)
+        if color_spec.is_a?(Color) or color_spec.is_a?(MixColor)
+          color_spec
+        else
+          color_name = nil
+          normalized_color_spec = {}
+          color_spec.each do |key, value|
+            key = key.to_sym
+            if key == :name
+              color_name = value
+            else
+              normalized_color_spec[key] = value
+            end
+          end
+          Color.new(color_name, normalized_color_spec)
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/color.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/color.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/color.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,96 @@
+module Test
+  module Unit
+    class Color
+      NAMES = ["black", "red", "green", "yellow",
+               "blue", "magenta", "cyan", "white"]
+
+      attr_reader :name
+      def initialize(name, options={})
+        @name = name
+        @foreground = options[:foreground]
+        @foreground = true if @foreground.nil?
+        @intensity = options[:intensity]
+        @bold = options[:bold]
+        @italic = options[:italic]
+        @underline = options[:underline]
+      end
+
+      def foreground?
+        @foreground
+      end
+
+      def intensity?
+        @intensity
+      end
+
+      def bold?
+        @bold
+      end
+
+      def italic?
+        @italic
+      end
+
+      def underline?
+        @underline
+      end
+
+      def ==(other)
+        self.class === other and
+          [name, foreground?, intensity?,
+           bold?, italic?, underline?] ==
+          [other.name, other.foreground?, other.intensity?,
+           other.bold?, other.italic?, other.underline?]
+      end
+
+      def sequence
+        sequence = []
+        if @name == "none"
+        elsif @name == "reset"
+          sequence << "0"
+        else
+          foreground_parameter = foreground? ? 3 : 4
+          foreground_parameter += 6 if intensity?
+          sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
+        end
+        sequence << "1" if bold?
+        sequence << "3" if italic?
+        sequence << "4" if underline?
+        sequence
+      end
+
+      def escape_sequence
+        "\e[#{sequence.join(';')}m"
+      end
+
+      def +(other)
+        MixColor.new([self, other])
+      end
+    end
+
+    class MixColor
+      attr_reader :colors
+      def initialize(colors)
+        @colors = colors
+      end
+
+      def sequence
+        @colors.inject([]) do |result, color|
+          result + color.sequence
+        end
+      end
+
+      def escape_sequence
+        "\e[#{sequence.join(';')}m"
+      end
+
+      def +(other)
+        self.class.new([self, other])
+      end
+
+      def ==(other)
+        self.class === other and colors == other.colors
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/diff.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/diff.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/diff.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,538 @@
+# port of Python's difflib.
+
+module Test
+  module Unit
+    module Diff
+      class SequenceMatcher
+        def initialize(from, to, &junk_predicate)
+          @from = from
+          @to = to
+          @junk_predicate = junk_predicate
+          update_to_indexes
+        end
+
+        def longest_match(from_start, from_end, to_start, to_end)
+          best_info = find_best_match_position(from_start, from_end,
+                                               to_start, to_end)
+          unless @junks.empty?
+            args = [from_start, from_end, to_start, to_end]
+            best_info = adjust_best_info_with_junk_predicate(false, best_info,
+                                                             *args)
+            best_info = adjust_best_info_with_junk_predicate(true, best_info,
+                                                             *args)
+          end
+
+          best_info
+        end
+
+        def blocks
+          @blocks ||= compute_blocks
+        end
+
+        def operations
+          @operations ||= compute_operations
+        end
+
+        def grouped_operations(context_size=nil)
+          context_size ||= 3
+          _operations = operations
+          _operations = [[:equal, 0, 0, 0, 0]] if _operations.empty?
+          expand_edge_equal_operations!(_operations, context_size)
+
+          group_window = context_size * 2
+          groups = []
+          group = []
+          _operations.each do |tag, from_start, from_end, to_start, to_end|
+            if tag == :equal and from_end - from_start > group_window
+              group << [tag,
+                        from_start,
+                        [from_end, from_start + context_size].min,
+                        to_start,
+                        [to_end, to_start + context_size].min]
+              groups << group
+              group = []
+              from_start = [from_start, from_end - context_size].max
+              to_start = [to_start, to_end - context_size].max
+            end
+            group << [tag, from_start, from_end, to_start, to_end]
+          end
+          groups << group unless group.empty?
+          groups
+        end
+
+        def ratio
+          @ratio ||= compute_ratio
+        end
+
+        private
+        def update_to_indexes
+          @to_indexes = {}
+          @junks = {}
+          if @to.is_a?(String)
+            each = " "[0].is_a?(Integer) ? :each_byte : :each_char
+          else
+            each = :each
+          end
+          i = 0
+          @to.send(each) do |item|
+            @to_indexes[item] ||= []
+            @to_indexes[item] << i
+            i += 1
+          end
+
+          return if @junk_predicate.nil?
+          @to_indexes = @to_indexes.reject do |key, value|
+            junk = @junk_predicate.call(key)
+            @junks[key] = true if junk
+            junk
+          end
+        end
+
+        def find_best_match_position(from_start, from_end, to_start, to_end)
+          best_from, best_to, best_size = from_start, to_start, 0
+          sizes = {}
+          from_start.upto(from_end) do |from_index|
+            _sizes = {}
+            (@to_indexes[@from[from_index]] || []).each do |to_index|
+              next if to_index < to_start
+              break if to_index > to_end
+              size = _sizes[to_index] = (sizes[to_index - 1] || 0) + 1
+              if size > best_size
+                best_from = from_index - size + 1
+                best_to = to_index - size + 1
+                best_size = size
+              end
+            end
+            sizes = _sizes
+          end
+          [best_from, best_to, best_size]
+        end
+
+        def adjust_best_info_with_junk_predicate(should_junk, best_info,
+                                                 from_start, from_end,
+                                                 to_start, to_end)
+          best_from, best_to, best_size = best_info
+          while best_from > from_start and best_to > to_start and
+              (should_junk ?
+               @junks.has_key?(@to[best_to - 1]) :
+               !@junks.has_key?(@to[best_to - 1])) and
+              @from[best_from - 1] == @to[best_to - 1]
+            best_from -= 1
+            best_to -= 1
+            best_size += 1
+          end
+
+          while best_from + best_size < from_end and
+              best_to + best_size < to_end and
+              (should_junk ?
+               @junks.has_key?(@to[best_to + best_size]) :
+               !@junks.has_key?(@to[best_to + best_size])) and
+              @from[best_from + best_size] == @to[best_to + best_size]
+            best_size += 1
+          end
+
+          [best_from, best_to, best_size]
+        end
+
+        def matches
+          @matches ||= compute_matches
+        end
+
+        def compute_matches
+          matches = []
+          queue = [[0, @from.size, 0, @to.size]]
+          until queue.empty?
+            from_start, from_end, to_start, to_end = queue.pop
+            match = longest_match(from_start, from_end - 1, to_start, to_end - 1)
+            match_from_index, match_to_index, size = match
+            unless size.zero?
+              if from_start < match_from_index and
+                  to_start < match_to_index
+                queue.push([from_start, match_from_index,
+                            to_start, match_to_index])
+              end
+              matches << match
+              if match_from_index + size < from_end and
+                  match_to_index + size < to_end
+                queue.push([match_from_index + size, from_end,
+                            match_to_index + size, to_end])
+              end
+            end
+          end
+          matches.sort_by do |(from_index, to_index, match_size)|
+            from_index
+          end
+        end
+
+        def compute_blocks
+          blocks = []
+          current_from_index = current_to_index = current_size = 0
+          matches.each do |from_index, to_index, size|
+            if current_from_index + current_size == from_index and
+                current_to_index + current_size == to_index
+              current_size += size
+            else
+              unless current_size.zero?
+                blocks << [current_from_index, current_to_index, current_size]
+              end
+              current_from_index = from_index
+              current_to_index = to_index
+              current_size = size
+            end
+          end
+          unless current_size.zero?
+            blocks << [current_from_index, current_to_index, current_size]
+          end
+
+          blocks << [@from.size, @to.size, 0]
+          blocks
+        end
+
+        def compute_operations
+          from_index = to_index = 0
+          operations = []
+          blocks.each do |match_from_index, match_to_index, size|
+            tag = determine_tag(from_index, to_index,
+                                match_from_index, match_to_index)
+            if tag != :equal
+              operations << [tag,
+                             from_index, match_from_index,
+                             to_index, match_to_index]
+            end
+
+            from_index, to_index = match_from_index + size, match_to_index + size
+            if size > 0
+              operations << [:equal,
+                             match_from_index, from_index,
+                             match_to_index, to_index]
+            end
+          end
+          operations
+        end
+
+        def compute_ratio
+          matches = blocks.inject(0) {|result, block| result + block[-1]}
+          length = @from.length + @to.length
+          if length.zero?
+            1.0
+          else
+            2.0 * matches / length
+          end
+        end
+
+        def determine_tag(from_index, to_index,
+                          match_from_index, match_to_index)
+          if from_index < match_from_index and to_index < match_to_index
+            :replace
+          elsif from_index < match_from_index
+            :delete
+          elsif to_index < match_to_index
+            :insert
+          else
+            :equal
+          end
+        end
+
+        def expand_edge_equal_operations!(_operations, context_size)
+          tag, from_start, from_end, to_start, to_end = _operations[0]
+          if tag == :equal
+            _operations[0] = [tag,
+                              [from_start, from_end - context_size].max,
+                              from_end,
+                              [to_start, to_end - context_size].max,
+                              to_end]
+          end
+
+          tag, from_start, from_end, to_start, to_end = _operations[-1]
+          if tag == :equal
+            _operations[-1] = [tag,
+                               from_start,
+                               [from_end, from_start + context_size].min,
+                               to_start,
+                               [to_end, to_start + context_size].min]
+          end
+        end
+      end
+
+      class Differ
+        def initialize(from, to)
+          @from = from
+          @to = to
+        end
+
+        private
+        def tag(mark, contents)
+          contents.collect {|content| "#{mark}#{content}"}
+        end
+      end
+
+      class ReadableDiffer < Differ
+        def diff(options={})
+          result = []
+          matcher = SequenceMatcher.new(@from, @to)
+          matcher.operations.each do |args|
+            tag, from_start, from_end, to_start, to_end = args
+            case tag
+            when :replace
+              result.concat(diff_lines(from_start, from_end, to_start, to_end))
+            when :delete
+              result.concat(tag_deleted(@from[from_start...from_end]))
+            when :insert
+              result.concat(tag_inserted(@to[to_start...to_end]))
+            when :equal
+              result.concat(tag_equal(@from[from_start...from_end]))
+            else
+              raise "unknown tag: #{tag}"
+            end
+          end
+          result
+        end
+
+        private
+        def tag_deleted(contents)
+          tag("- ", contents)
+        end
+
+        def tag_inserted(contents)
+          tag("+ ", contents)
+        end
+
+        def tag_equal(contents)
+          tag("  ", contents)
+        end
+
+        def tag_difference(contents)
+          tag("? ", contents)
+        end
+
+        def find_diff_line_info(from_start, from_end, to_start, to_end)
+          best_ratio = 0.74
+          from_equal_index = to_equal_index = nil
+          from_best_index = to_best_index = nil
+
+          to_start.upto(to_end - 1) do |to_index|
+            from_start.upto(from_end - 1) do |from_index|
+              if @from[from_index] == @to[to_index]
+                from_equal_index ||= from_index
+                to_equal_index ||= to_index
+                next
+              end
+
+              matcher = SequenceMatcher.new(@from[from_index], @to[to_index],
+                                            &method(:space_character?))
+              if matcher.ratio > best_ratio
+                best_ratio = matcher.ratio
+                from_best_index = from_index
+                to_best_index = to_index
+              end
+            end
+          end
+
+          [best_ratio,
+           from_equal_index, to_equal_index,
+           from_best_index,  to_best_index]
+        end
+
+        def diff_lines(from_start, from_end, to_start, to_end)
+          cut_off = 0.75
+
+          info = find_diff_line_info(from_start, from_end, to_start, to_end)
+          best_ratio, from_equal_index, to_equal_index, *info = info
+          from_best_index, to_best_index = info
+
+          if best_ratio < cut_off
+            if from_equal_index.nil?
+              tagged_from = tag_deleted(@from[from_start...from_end])
+              tagged_to = tag_inserted(@to[to_start...to_end])
+              if to_end - to_start < from_end - from_start
+                return tagged_to + tagged_from
+              else
+                return tagged_from + tagged_to
+              end
+            end
+            from_best_index = from_equal_index
+            to_best_index = to_equal_index
+            best_ratio = 1.0
+          end
+
+          _diff_lines(from_start, from_best_index, to_start, to_best_index) +
+            diff_line(@from[from_best_index], @to[to_best_index]) +
+            _diff_lines(from_best_index + 1, from_end, to_best_index + 1, to_end)
+        end
+
+        def _diff_lines(from_start, from_end, to_start, to_end)
+          if from_start < from_end
+            if to_start < to_end
+              diff_lines(from_start, from_end, to_start, to_end)
+            else
+              tag_deleted(@from[from_start...from_end])
+            end
+          else
+            tag_inserted(@to[to_start...to_end])
+          end
+        end
+
+        def diff_line(from_line, to_line)
+          from_tags = ""
+          to_tags = ""
+          matcher = SequenceMatcher.new(from_line, to_line,
+                                        &method(:space_character?))
+          operations = matcher.operations
+          operations.each do |tag, from_start, from_end, to_start, to_end|
+            from_length = from_end - from_start
+            to_length = to_end - to_start
+            case tag
+            when :replace
+              from_tags << "^" * from_length
+              to_tags << "^" * to_length
+            when :delete
+              from_tags << "-" * from_length
+            when :insert
+              to_tags << "+" * to_length
+            when :equal
+              from_tags << " " * from_length
+              to_tags << " " * to_length
+            else
+              raise "unknown tag: #{tag}"
+            end
+          end
+          format_diff_point(from_line, to_line, from_tags, to_tags)
+        end
+
+        def format_diff_point(from_line, to_line, from_tags, to_tags)
+          common = [n_leading_characters(from_line, ?\t),
+                    n_leading_characters(to_line, ?\t)].min
+          common = [common,
+                    n_leading_characters(from_tags[0, common], " "[0])].min
+          from_tags = from_tags[common..-1].rstrip
+          to_tags = to_tags[common..-1].rstrip
+
+          result = tag_deleted([from_line])
+          unless from_tags.empty?
+            result.concat(tag_difference(["#{"\t" * common}#{from_tags}"]))
+          end
+          result.concat(tag_inserted([to_line]))
+          unless to_tags.empty?
+            result.concat(tag_difference(["#{"\t" * common}#{to_tags}"]))
+          end
+          result
+        end
+
+        def n_leading_characters(string, character)
+          n = 0
+          while string[n] == character
+            n += 1
+          end
+          n
+        end
+
+        def space_character?(character)
+          [" "[0], "\t"[0]].include?(character)
+        end
+      end
+
+      class UnifiedDiffer < Differ
+        def diff(options={})
+          groups = SequenceMatcher.new(@from, @to).grouped_operations
+          return [] if groups.empty?
+          return [] if same_content?(groups)
+
+          show_context = options[:show_context]
+          show_context = true if show_context.nil?
+          result = ["--- #{options[:from_label]}".rstrip,
+                    "+++ #{options[:to_label]}".rstrip]
+          groups.each do |operations|
+            result << format_summary(operations, show_context)
+            operations.each do |args|
+              operation_tag, from_start, from_end, to_start, to_end = args
+              case operation_tag
+              when :replace
+                result.concat(tag("-", @from[from_start...from_end]))
+                result.concat(tag("+", @to[to_start...to_end]))
+              when :delete
+                result.concat(tag("-", @from[from_start...from_end]))
+              when :insert
+                result.concat(tag("+", @to[to_start...to_end]))
+              when :equal
+                result.concat(tag(" ", @from[from_start...from_end]))
+              end
+            end
+          end
+          result
+        end
+
+        private
+        def same_content?(groups)
+          return false if groups.size != 1
+          group = groups[0]
+          return false if group.size != 1
+          tag, from_start, from_end, to_start, to_end = group[0]
+
+          tag == :equal and [from_start, from_end] == [to_start, to_end]
+        end
+
+        def format_summary(operations, show_context)
+          _, first_from_start, _, first_to_start, _ = operations[0]
+          _, _, last_from_end, _, last_to_end = operations[-1]
+          summary = "@@ -%d,%d +%d,%d @@" % [first_from_start + 1,
+                                             last_from_end - first_from_start,
+                                             first_to_start + 1,
+                                             last_to_end - first_to_start,]
+          if show_context
+            interesting_line = find_interesting_line(first_from_start,
+                                                     first_to_start,
+                                                     :define_line?)
+            summary << " #{interesting_line}" if interesting_line
+          end
+          summary
+        end
+
+        def find_interesting_line(from_start, to_start, predicate)
+          from_index = from_start
+          to_index = to_start
+          while from_index >= 0 or to_index >= 0
+            [@from[from_index], @to[to_index]].each do |line|
+              return line if line and send(predicate, line)
+            end
+
+            from_index -= 1
+            to_index -= 1
+          end
+          nil
+        end
+
+        def define_line?(line)
+          /\A(?:[_a-zA-Z$]|\s*(?:class|module|def)\b)/ =~ line
+        end
+      end
+
+      module_function
+      def need_fold?(diff)
+        /^[-+].{79}/ =~ diff
+      end
+
+      def fold(string)
+        string.split(/\r?\n/).collect do |line|
+          line.gsub(/(.{78})/, "\\1\n")
+        end.join("\n")
+      end
+
+      def folded_readable(from, to, options={})
+        readable(fold(from), fold(to), options)
+      end
+
+      def readable(from, to, options={})
+        diff(ReadableDiffer, from, to, options)
+      end
+
+      def unified(from, to, options={})
+        diff(UnifiedDiffer, from, to, options)
+      end
+
+      def diff(differ_class, from, to, options={})
+        differ = differ_class.new(from.split(/\r?\n/), to.split(/\r?\n/))
+        differ.diff(options).join("\n")
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/error.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/error.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/error.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,126 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+
+    # Encapsulates an error in a test. Created by
+    # Test::Unit::TestCase when it rescues an exception thrown
+    # during the processing of a test.
+    class Error
+      include Util::BacktraceFilter
+
+      attr_reader(:test_name, :exception)
+
+      SINGLE_CHARACTER = 'E'
+      LABEL = "Error"
+
+      # Creates a new Error with the given test_name and
+      # exception.
+      def initialize(test_name, exception)
+        @test_name = test_name
+        @exception = exception
+      end
+
+      # Returns a single character representation of an error.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      def label
+        LABEL
+      end
+
+      # Returns the message associated with the error.
+      def message
+        "#{@exception.class.name}: #{@exception.message}"
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#@test_name: #{message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        backtrace_display = backtrace.join("\n    ")
+        "#{label}:\n#@test_name:\n#{message}\n    #{backtrace_display}"
+      end
+
+      def backtrace
+        filter_backtrace(@exception.backtrace)
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+
+    module ErrorHandler
+      class << self
+        def included(base)
+          base.exception_handler(:handle_all_exception)
+        end
+      end
+
+      NOT_PASS_THROUGH_EXCEPTIONS = []
+      PASS_THROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
+                                 SystemExit]
+      private
+      def handle_all_exception(exception)
+        case exception
+        when *NOT_PASS_THROUGH_EXCEPTIONS
+        when *PASS_THROUGH_EXCEPTIONS
+          return false
+        end
+
+        problem_occurred
+        add_error(exception)
+        true
+      end
+
+      def add_error(exception)
+        current_result.add_error(Error.new(name, exception))
+      end
+    end
+
+    module TestResultErrorSupport
+      attr_reader :errors
+
+      # Records a Test::Unit::Error.
+      def add_error(error)
+        @errors << error
+        notify_fault(error)
+        notify_changed
+      end
+
+      # Returns the number of errors this TestResult has
+      # recorded.
+      def error_count
+        @errors.size
+      end
+
+      def error_occurred?
+        not @errors.empty?
+      end
+
+      private
+      def initialize_containers
+        super
+        @errors = []
+        @summary_generators << :error_summary
+        @problem_checkers << :error_occurred?
+      end
+
+      def error_summary
+        "#{error_count} errors"
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/exceptionhandler.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/exceptionhandler.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/exceptionhandler.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,39 @@
+module Test
+  module Unit
+    module ExceptionHandler
+      @@exception_handlers = []
+      class << self
+        def exception_handlers
+          @@exception_handlers
+	end
+
+        def included(base)
+          base.extend(ClassMethods)
+
+          observer = Proc.new do |test_case, _, _, value, method_name|
+            if value
+              @@exception_handlers.unshift(method_name)
+            else
+              @@exception_handlers -= [method_name]
+            end
+          end
+          base.register_attribute_observer(:exception_handler, &observer)
+        end
+      end
+
+      module ClassMethods
+        def exception_handlers
+          ExceptionHandler.exception_handlers
+        end
+
+        def exception_handler(*method_names)
+          attribute(:exception_handler, true, *method_names)
+        end
+
+        def unregister_exception_handler(*method_names)
+          attribute(:exception_handler, false, *method_names)
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/failure.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/failure.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/failure.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,110 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+
+    # Encapsulates a test failure. Created by Test::Unit::TestCase
+    # when an assertion fails.
+    class Failure
+      attr_reader :test_name, :location, :message
+      
+      SINGLE_CHARACTER = 'F'
+      LABEL = "Failure"
+
+      # Creates a new Failure with the given location and
+      # message.
+      def initialize(test_name, location, message)
+        @test_name = test_name
+        @location = location
+        @message = message
+      end
+      
+      # Returns a single character representation of a failure.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      def label
+        LABEL
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#@test_name: #{@message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        if location.size == 1
+          location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
+        else
+          location_display = "\n    [#{location.join("\n     ")}]"
+        end
+        "#{label}:\n#@test_name#{location_display}:\n#@message"
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+
+    module FailureHandler
+      class << self
+        def included(base)
+          base.exception_handler(:handle_assertion_failed_error)
+        end
+      end
+
+      private
+      def handle_assertion_failed_error(exception)
+        return false unless exception.is_a?(AssertionFailedError)
+        problem_occurred
+        add_failure(exception.message, exception.backtrace)
+        true
+      end
+
+      def add_failure(message, backtrace)
+        failure = Failure.new(name, filter_backtrace(backtrace), message)
+        current_result.add_failure(failure)
+      end
+    end
+
+    module TestResultFailureSupport
+      attr_reader :failures
+
+      # Records a Test::Unit::Failure.
+      def add_failure(failure)
+        @failures << failure
+        notify_fault(failure)
+        notify_changed
+      end
+
+      # Returns the number of failures this TestResult has
+      # recorded.
+      def failure_count
+        @failures.size
+      end
+
+      def failure_occurred?
+        not @failures.empty?
+      end
+
+      private
+      def initialize_containers
+        super
+        @failures = []
+        @summary_generators << :failure_summary
+        @problem_checkers << :failure_occurred?
+      end
+
+      def failure_summary
+        "#{failure_count} failures"
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/fixture.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/fixture.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/fixture.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,176 @@
+module Test
+  module Unit
+    module Fixture
+      class << self
+        def included(base)
+          base.extend(ClassMethods)
+
+          [:setup, :teardown].each do |fixture|
+            observer = Proc.new do |test_case, _, _, value, method_name|
+              if value.nil?
+                test_case.send("unregister_#{fixture}_method", method_name)
+              else
+                test_case.send("register_#{fixture}_method", method_name,
+                               value)
+              end
+            end
+            base.register_attribute_observer(fixture, &observer)
+          end
+        end
+      end
+
+      module ClassMethods
+        def setup(*method_names)
+          register_fixture(:setup, *method_names)
+        end
+
+        def unregister_setup(*method_names)
+          unregister_fixture(:setup, *method_names)
+        end
+
+        def teardown(*method_names)
+          register_fixture(:teardown, *method_names)
+        end
+
+        def unregister_teardown(*method_names)
+          unregister_fixture(:teardown, *method_names)
+        end
+
+        def register_setup_method(method_name, options)
+          register_fixture_method(:setup, method_name, options, :after, :append)
+        end
+
+        def unregister_setup_method(method_name)
+          unregister_fixture_method(:setup, method_name)
+        end
+
+        def register_teardown_method(method_name, options)
+          register_fixture_method(:teardown, method_name, options,
+                                  :before, :prepend)
+        end
+
+        def unregister_teardown_method(method_name)
+          unregister_fixture_method(:teardown, method_name)
+        end
+
+        def before_setup_methods
+          collect_fixture_methods(:setup, :before)
+        end
+
+        def after_setup_methods
+          collect_fixture_methods(:setup, :after)
+        end
+
+        def before_teardown_methods
+          collect_fixture_methods(:teardown, :before)
+        end
+
+        def after_teardown_methods
+          collect_fixture_methods(:teardown, :after)
+        end
+
+        private
+        def register_fixture(fixture, *method_names)
+          options = {}
+          options = method_names.pop if method_names.last.is_a?(Hash)
+          attribute(fixture, options, *method_names)
+        end
+
+        def unregister_fixture(fixture, *method_names)
+          attribute(fixture, nil, *method_names)
+        end
+
+        def valid_register_fixture_options?(options)
+          return true if options.empty?
+          return false if options.size > 1
+
+          key = options.keys.first
+          [:before, :after].include?(key) and
+            [:prepend, :append].include?(options[key])
+        end
+
+        def add_fixture_method_name(how, variable_name, method_name)
+          methods = instance_eval("#{variable_name} ||= []")
+
+          if how == :prepend
+            methods = [method_name] | methods
+          else
+            methods = methods | [method_name]
+          end
+          instance_variable_set(variable_name, methods)
+        end
+
+        def registered_methods_variable_name(fixture, order)
+          "@#{order}_#{fixture}_methods"
+        end
+
+        def unregistered_methods_variable_name(fixture)
+          "@unregistered_#{fixture}_methods"
+        end
+
+        def register_fixture_method(fixture, method_name, options,
+                                    default_order, default_how)
+          unless valid_register_fixture_options?(options)
+            message = "must be {:before => :prepend}, " +
+              "{:before => :append}, {:after => :prepend} or " +
+              "{:after => :append}: #{options.inspect}"
+            raise ArgumentError, message
+          end
+
+          if options.empty?
+            order, how = default_order, default_how
+          else
+            order, how = options.to_a.first
+          end
+          variable_name = registered_methods_variable_name(fixture, order)
+          add_fixture_method_name(how, variable_name, method_name)
+        end
+
+        def unregister_fixture_method(fixture, method_name)
+          variable_name = unregistered_methods_variable_name(fixture)
+          add_fixture_method_name(:append, variable_name, method_name)
+        end
+
+        def collect_fixture_methods(fixture, order)
+          methods_variable = registered_methods_variable_name(fixture, order)
+          unregistered_methods_variable =
+            unregistered_methods_variable_name(fixture)
+
+          base_index = ancestors.index(Fixture)
+          interested_ancestors = ancestors[0, base_index].reverse
+          interested_ancestors.inject([]) do |result, ancestor|
+            if ancestor.is_a?(Class)
+              ancestor.class_eval do
+                methods = instance_eval("#{methods_variable} ||= []")
+                unregistered_methods =
+                  instance_eval("#{unregistered_methods_variable} ||= []")
+                (result | methods) - unregistered_methods
+              end
+            else
+              result
+            end
+          end
+        end
+      end
+
+      private
+      def run_fixture(fixture)
+        [
+         self.class.send("before_#{fixture}_methods"),
+         fixture,
+         self.class.send("after_#{fixture}_methods")
+        ].flatten.each do |method_name|
+          send(method_name) if respond_to?(method_name, true)
+        end
+      end
+
+      def run_setup
+        run_fixture(:setup)
+      end
+
+      def run_teardown
+        run_fixture(:teardown)
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/notification.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/notification.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/notification.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,125 @@
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+    class Notification
+      include Util::BacktraceFilter
+      attr_reader :test_name, :location, :message
+
+      SINGLE_CHARACTER = 'N'
+      LABEL = "Notification"
+
+      # Creates a new Notification with the given location and
+      # message.
+      def initialize(test_name, location, message)
+        @test_name = test_name
+        @location = location
+        @message = message
+      end
+
+      # Returns a single character representation of a notification.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      def label
+        LABEL
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#{@test_name}: #{@message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        backtrace = filter_backtrace(location).join("\n")
+        "#{label}: #{@message}\n#{@test_name}\n#{backtrace}"
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+
+    class NotifiedError < StandardError
+    end
+
+
+    module TestCaseNotificationSupport
+      class << self
+        def included(base)
+          base.class_eval do
+            include NotificationHandler
+          end
+        end
+      end
+
+      # Notify some information.
+      #
+      # Example:
+      #   def test_notification
+      #     notify("I'm here!")
+      #     # Reached here
+      #     notify("Special!") if special_case?
+      #     # Reached here too
+      #   end
+      def notify(message, &block)
+        notification = Notification.new(name, filter_backtrace(caller), message)
+        add_notification(notification)
+      end
+
+      private
+      def add_notification(notification)
+        current_result.add_notification(notification)
+      end
+    end
+
+    module NotificationHandler
+      class << self
+        def included(base)
+          base.exception_handler(:handle_Notified_error)
+        end
+      end
+
+      private
+      def handle_Notified_error(exception)
+        return false unless exception.is_a?(NotifiedError)
+        notification = Notification.new(name,
+                                filter_backtrace(exception.backtrace),
+                                exception.message)
+        add_notification(notification)
+        true
+      end
+    end
+
+    module TestResultNotificationSupport
+      attr_reader :notifications
+
+      # Records a Test::Unit::Notification.
+      def add_notification(notification)
+        @notifications << notification
+        notify_fault(notification)
+        notify_changed
+      end
+
+      # Returns the number of notifications this TestResult has
+      # recorded.
+      def notification_count
+        @notifications.size
+      end
+
+      private
+      def initialize_containers
+        super
+        @notifications = []
+        @summary_generators << :notification_summary
+      end
+
+      def notification_summary
+        "#{notification_count} notifications"
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/omission.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/omission.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/omission.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,143 @@
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+    class Omission
+      include Util::BacktraceFilter
+      attr_reader :test_name, :location, :message
+
+      SINGLE_CHARACTER = 'O'
+      LABEL = "Omission"
+
+      # Creates a new Omission with the given location and
+      # message.
+      def initialize(test_name, location, message)
+        @test_name = test_name
+        @location = location
+        @message = message
+      end
+
+      # Returns a single character representation of a omission.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      def label
+        LABEL
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#{@test_name}: #{@message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        backtrace = filter_backtrace(location).join("\n")
+        "#{label}: #{@message}\n#{@test_name}\n#{backtrace}"
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+
+    class OmittedError < StandardError
+    end
+
+
+    module TestCaseOmissionSupport
+      class << self
+        def included(base)
+          base.class_eval do
+            include OmissionHandler
+          end
+        end
+      end
+
+      # Omit the test of part of the test.
+      #
+      # Example:
+      #   def test_omission
+      #     omit
+      #     # Not reached here
+      #   end
+      #
+      #   def test_omission_with_here
+      #     omit do
+      #       # Not ran here
+      #     end
+      #     # Reached here
+      #   end
+      def omit(message=nil, &block)
+        message ||= "omitted."
+        if block_given?
+          omission = Omission.new(name, filter_backtrace(caller), message)
+          add_omission(omission)
+        else
+          raise OmittedError.new(message)
+        end
+      end
+
+      def omit_if(condition, *args, &block)
+        omit(*args, &block) if condition
+      end
+
+      def omit_unless(condition, *args, &block)
+        omit(*args, &block) unless condition
+      end
+
+      private
+      def add_omission(omission)
+        current_result.add_omission(omission)
+      end
+    end
+
+    module OmissionHandler
+      class << self
+        def included(base)
+          base.exception_handler(:handle_omitted_error)
+        end
+      end
+
+      private
+      def handle_omitted_error(exception)
+        return false unless exception.is_a?(OmittedError)
+        omission = Omission.new(name,
+                                filter_backtrace(exception.backtrace),
+                                exception.message)
+        add_omission(omission)
+        true
+      end
+    end
+
+    module TestResultOmissionSupport
+      attr_reader :omissions
+
+      # Records a Test::Unit::Omission.
+      def add_omission(omission)
+        @omissions << omission
+        notify_fault(omission)
+        notify_changed
+      end
+
+      # Returns the number of omissions this TestResult has
+      # recorded.
+      def omission_count
+        @omissions.size
+      end
+
+      private
+      def initialize_containers
+        super
+        @omissions = []
+        @summary_generators << :omission_summary
+      end
+
+      def omission_summary
+        "#{omission_count} omissions"
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/pending.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/pending.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/pending.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,146 @@
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+    class Pending
+      include Util::BacktraceFilter
+      attr_reader :test_name, :location, :message
+
+      SINGLE_CHARACTER = 'P'
+      LABEL = "Pending"
+
+      # Creates a new Pending with the given location and
+      # message.
+      def initialize(test_name, location, message)
+        @test_name = test_name
+        @location = location
+        @message = message
+      end
+
+      # Returns a single character representation of a pending.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      def label
+        LABEL
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#{@test_name}: #{@message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        backtrace = filter_backtrace(location).join("\n")
+        "#{label}: #{@message}\n#{@test_name}\n#{backtrace}"
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+
+    class PendedError < StandardError
+    end
+
+
+    module TestCasePendingSupport
+      class << self
+        def included(base)
+          base.class_eval do
+            include PendingHandler
+          end
+        end
+      end
+
+      # Marks the test or part of the test is pending.
+      #
+      # Example:
+      #   def test_pending
+      #     pend
+      #     # Not reached here
+      #   end
+      #
+      #   def test_pending_with_here
+      #     pend do
+      #       # Ran here
+      #       # Fails if the block doesn't raise any error.
+      #       # Because it means the block is passed unexpectedly.
+      #     end
+      #     # Reached here
+      #   end
+      def pend(message=nil, &block)
+        message ||= "pended."
+        if block_given?
+          pending = nil
+          begin
+            yield
+          rescue Exception
+            pending = Pending.new(name, filter_backtrace(caller), message)
+            add_pending(pending)
+          end
+          unless pending
+            flunk("Pending block should not be passed: #{message}")
+          end
+        else
+          raise PendedError.new(message)
+        end
+      end
+
+      private
+      def add_pending(pending)
+        problem_occurred
+        current_result.add_pending(pending)
+      end
+    end
+
+    module PendingHandler
+      class << self
+        def included(base)
+          base.exception_handler(:handle_pended_error)
+        end
+      end
+
+      private
+      def handle_pended_error(exception)
+        return false unless exception.is_a?(PendedError)
+        pending = Pending.new(name,
+                                filter_backtrace(exception.backtrace),
+                                exception.message)
+        add_pending(pending)
+        true
+      end
+    end
+
+    module TestResultPendingSupport
+      attr_reader :pendings
+
+      # Records a Test::Unit::Pending.
+      def add_pending(pending)
+        @pendings << pending
+        notify_fault(pending)
+        notify_changed
+      end
+
+      # Returns the number of pendings this TestResult has
+      # recorded.
+      def pending_count
+        @pendings.size
+      end
+
+      private
+      def initialize_containers
+        super
+        @pendings = []
+        @summary_generators << :pending_summary
+      end
+
+      def pending_summary
+        "#{pending_count} pendings"
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/priority.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/priority.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/priority.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,181 @@
+require "fileutils"
+require "tmpdir"
+
+module Test
+  module Unit
+    module Priority
+      class << self
+        def included(base)
+          base.extend(ClassMethods)
+
+          base.class_eval do
+            setup :priority_setup, :before => :prepend
+            teardown :priority_teardown, :after => :append
+          end
+        end
+
+        @@enabled = false
+        def enabled?
+          @@enabled
+        end
+
+        def enable
+          @@enabled = true
+        end
+
+        def disable
+          @@enabled = false
+        end
+
+        @@default = :normal
+        def default
+          @@default || :normal
+        end
+
+        def default=(default)
+          @@default = default
+        end
+
+        def available_values
+          Checker.available_priorities
+        end
+      end
+
+      class Checker
+        class << self
+          def have_priority?(name)
+            singleton_class = (class << self; self; end)
+            singleton_class.method_defined?(priority_check_method_name(name))
+          end
+
+          def need_to_run?(test)
+            priority = test[:priority] || Priority.default
+            if have_priority?(priority)
+              send(priority_check_method_name(priority), test)
+            else
+              true
+            end
+          end
+
+          def available_priorities
+            methods(false).collect do |name|
+              /\Arun_priority_(.+)\?\z/ =~ name.to_s
+              $1
+            end.compact
+          end
+
+          def run_priority_must?(test)
+            true
+          end
+
+          def run_priority_important?(test)
+            rand > 0.1
+          end
+
+          def run_priority_high?(test)
+            rand > 0.3
+          end
+
+          def run_priority_normal?(test)
+            rand > 0.5
+          end
+
+          def run_priority_low?(test)
+            rand > 0.75
+          end
+
+          def run_priority_never?(test)
+            false
+          end
+
+          private
+          def priority_check_method_name(priority_name)
+            "run_priority_#{priority_name}?"
+          end
+        end
+
+        attr_reader :test
+        def initialize(test)
+          @test = test
+        end
+
+        def setup
+          FileUtils.rm_f(passed_file)
+        end
+
+        def teardown
+          if @test.send(:passed?)
+            FileUtils.touch(passed_file)
+          else
+            FileUtils.rm_f(passed_file)
+          end
+        end
+
+        def need_to_run?
+          !previous_test_success? or self.class.need_to_run?(@test)
+        end
+
+        private
+        def previous_test_success?
+          File.exist?(passed_file)
+        end
+
+        def result_dir
+          components = [".test-result",
+                        @test.class.name || "AnonymousTestCase",
+                        escaped_method_name]
+          parent_directories = [File.dirname($0), Dir.pwd]
+          if Process.respond_to?(:uid)
+            parent_directories << File.join(Dir.tmpdir, Process.uid.to_s)
+          end
+          parent_directories.each do |parent_directory|
+            dir = File.expand_path(File.join(parent_directory, *components))
+            begin
+              FileUtils.mkdir_p(dir)
+              return dir
+            rescue Errno::EACCES
+            end
+          end
+
+          raise Errno::EACCES, parent_directories.join(", ")
+        end
+
+        def passed_file
+          File.join(result_dir, "passed")
+        end
+
+        def escaped_method_name
+          @test.method_name.to_s.gsub(/[!?=]$/) do |matched|
+            case matched
+            when "!"
+              ".destructive"
+            when "?"
+              ".predicate"
+            when "="
+              ".equal"
+            end
+          end
+        end
+      end
+
+      module ClassMethods
+        def priority(name, *tests)
+          unless Checker.have_priority?(name)
+            raise ArgumentError, "unknown priority: #{name}"
+          end
+          attribute(:priority, name, {:keep => true}, *tests)
+        end
+      end
+
+      def priority_setup
+        return unless Priority.enabled?
+        Checker.new(self).setup
+      end
+
+      def priority_teardown
+        return unless Priority.enabled?
+        Checker.new(self).teardown
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/console.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/console.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/console.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,52 @@
+module Test
+  module Unit
+    AutoRunner.register_runner(:console) do |auto_runner|
+      require 'test/unit/ui/console/testrunner'
+      Test::Unit::UI::Console::TestRunner
+    end
+
+    AutoRunner.setup_option do |auto_runner, opts|
+      require 'test/unit/ui/console/outputlevel'
+
+      output_levels = [
+        [:silent, UI::Console::OutputLevel::SILENT],
+        [:progress, UI::Console::OutputLevel::PROGRESS_ONLY],
+        [:normal, UI::Console::OutputLevel::NORMAL],
+        [:verbose, UI::Console::OutputLevel::VERBOSE],
+      ]
+      opts.on('-v', '--verbose=[LEVEL]', output_levels,
+              "Set the output level (default is verbose).",
+              "(#{auto_runner.keyword_display(output_levels)})") do |level|
+        level ||= output_levels.assoc(:verbose)[1]
+        auto_runner.runner_options[:output_level] = level
+      end
+
+      use_color_options = [
+        [:auto, :auto],
+        ["-", false],
+        ["no", false],
+        ["false", false],
+        ["+", true],
+        ["yes", true],
+        ["true", true],
+      ]
+      opts.on("--[no-]use-color=[auto]", use_color_options,
+              "Uses color output",
+              "(default is auto)") do |use_color|
+        case use_color
+        when nil
+          use_color = true
+        when :auto
+          use_color = nil
+        end
+        auto_runner.runner_options[:use_color] = use_color
+      end
+
+      opts.on("--progress-row-max=MAX", Integer,
+              "Uses MAX as max terminal width for progress mark",
+              "(default is auto)") do |max|
+        auto_runner.runner_options[:progress_row_max] = max
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/emacs.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/emacs.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/emacs.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,8 @@
+module Test
+  module Unit
+    AutoRunner.register_runner(:emacs) do |auto_runner|
+      require 'test/unit/ui/emacs/testrunner'
+      Test::Unit::UI::Emacs::TestRunner
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/tap.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/tap.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/runner/tap.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,8 @@
+module Test
+  module Unit
+    AutoRunner.register_runner(:tap) do |auto_runner|
+      require 'test/unit/ui/tap/testrunner'
+      Test::Unit::UI::Tap::TestRunner
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/testcase.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/testcase.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/testcase.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,425 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright::
+#   * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+#   * Copyright (c) 2008-2009 Kouhei Sutou <tt><kou at clear-code.com></tt>
+# License:: Ruby license.
+
+require 'test/unit/attribute'
+require 'test/unit/fixture'
+require 'test/unit/exceptionhandler'
+require 'test/unit/assertions'
+require 'test/unit/failure'
+require 'test/unit/error'
+require 'test/unit/pending'
+require 'test/unit/omission'
+require 'test/unit/notification'
+require 'test/unit/priority'
+require 'test/unit/testsuite'
+require 'test/unit/assertionfailederror'
+require 'test/unit/util/backtracefilter'
+require 'test/unit/util/method-owner-finder'
+
+module Test
+  module Unit
+
+    # Ties everything together. If you subclass and add your own
+    # test methods, it takes care of making them into tests and
+    # wrapping those tests into a suite. It also does the
+    # nitty-gritty of actually running an individual test and
+    # collecting its results into a Test::Unit::TestResult object.
+    #
+    # You can run two hooks before/after a TestCase run.
+    #
+    # Example:
+    #   class TestMyClass < Test::Unit::TestCase
+    #     class << self
+    #       def startup
+    #         ...
+    #       end
+    #
+    #       def shutdown
+    #         ...
+    #       end
+    #     end
+    #
+    #     def setup
+    #       ...
+    #     end
+    #
+    #     def teardown
+    #       ...
+    #     end
+    #
+    #     def test_my_method1
+    #       ...
+    #     end
+    #
+    #     def test_my_method2
+    #       ...
+    #     end
+    #   end
+    #
+    # Here is a call order:
+    # * startup
+    # * setup
+    # * test_my_method1
+    # * teardown
+    # * setup
+    # * test_my_method2
+    # * teardown
+    # * shutdown
+    class TestCase
+      include Attribute
+      include Fixture
+      include ExceptionHandler
+      include ErrorHandler
+      include FailureHandler
+      include TestCasePendingSupport
+      include TestCaseOmissionSupport
+      include TestCaseNotificationSupport
+      include Priority
+      include Assertions
+      include Util::BacktraceFilter
+
+      STARTED = name + "::STARTED" # :nodoc:
+      FINISHED = name + "::FINISHED" # :nodoc:
+
+      DESCENDANTS = [] # :nodoc:
+      AVAILABLE_ORDERS = [:alphabetic, :random, :defined] # :nodoc:
+
+      class << self
+        def inherited(sub_class) # :nodoc:
+          DESCENDANTS << sub_class
+        end
+
+        @@added_methods = []
+        def method_added(name) # :nodoc:
+          super
+          @@added_methods << name.to_s
+        end
+
+        # Rolls up all of the test* methods in the fixture into
+        # one suite, creating a new instance of the fixture for
+        # each method.
+        def suite
+          suite = TestSuite.new(name, self)
+          collect_test_names.each do |test|
+            catch(:invalid_test) do
+              suite << new(test)
+            end
+          end
+          if suite.empty?
+            catch(:invalid_test) do
+              suite << new("default_test")
+            end
+          end
+          suite
+        end
+
+        # Called before every test case runs. Can be used
+        # to set up fixture information used in test case
+        # scope.
+        #
+        # Here is an example test case:
+        #   class TestMyClass < Test::Unit::TestCase
+        #     class << self
+        #       def startup
+        #         ...
+        #       end
+        #     end
+        #
+        #     def setup
+        #       ...
+        #     end
+        #
+        #     def test_my_class1
+        #       ...
+        #     end
+        #
+        #     def test_my_class2
+        #       ...
+        #     end
+        #   end
+        #
+        # Here is a call order:
+        # * startup
+        # * setup
+        # * test_my_class1 (or test_my_class2)
+        # * setup
+        # * test_my_class2 (or test_my_class1)
+        #
+        # Note that you should not assume test order. Tests
+        # should be worked in any order.
+        def startup
+        end
+
+        # Called after every test case runs. Can be used to tear
+        # down fixture information used in test case scope.
+        #
+        # Here is an example test case:
+        #   class TestMyClass < Test::Unit::TestCase
+        #     class << self
+        #       def shutdown
+        #         ...
+        #       end
+        #     end
+        #
+        #     def teardown
+        #       ...
+        #     end
+        #
+        #     def test_my_class1
+        #       ...
+        #     end
+        #
+        #     def test_my_class2
+        #       ...
+        #     end
+        #   end
+        #
+        # Here is a call order:
+        # * test_my_class1 (or test_my_class2)
+        # * teardown
+        # * test_my_class2 (or test_my_class1)
+        # * teardown
+        # * shutdown
+        #
+        # Note that you should not assume test order. Tests
+        # should be worked in any order.
+        def shutdown
+        end
+
+        @@test_order = AVAILABLE_ORDERS.first
+
+        # Returns the current test order. This returns
+        # +:alphabetic+ by default.
+        def test_order
+          @@test_order
+        end
+
+        # Sets the current test order.
+        #
+        # Here are the available _order_:
+        # [:alphabetic]
+        #   Default. Tests are sorted in alphabetic order.
+        # [:random]
+        #   Tests are sorted in random order.
+        # [:defined]
+        #   Tests are sorted in defined order.
+        def test_order=(order)
+          @@test_order = order
+        end
+
+        # :stopdoc:
+        private
+        def collect_test_names
+          method_names = public_instance_methods(true).collect do |name|
+            name.to_s
+          end
+          test_names = method_names.find_all do |method_name|
+            method_name =~ /^test./
+          end
+          send("sort_test_names_in_#{test_order}_order", test_names)
+        end
+
+        def sort_test_names_in_alphabetic_order(test_names)
+          test_names.sort
+        end
+
+        def sort_test_names_in_random_order(test_names)
+          test_names.sort_by {rand(test_names.size)}
+        end
+
+        def sort_test_names_in_defined_order(test_names)
+          test_names.sort do |test1, test2|
+            test1_defined_order = @@added_methods.index(test1)
+            test2_defined_order = @@added_methods.index(test2)
+            if test1_defined_order and test2_defined_order
+              test1_defined_order <=> test2_defined_order
+            elsif test1_defined_order
+              1
+            elsif test2_defined_order
+              -1
+            else
+              test1 <=> test2
+            end
+          end
+        end
+        # :startdoc:
+      end
+
+      attr_reader :method_name
+
+      # Creates a new instance of the fixture for running the
+      # test represented by test_method_name.
+      def initialize(test_method_name)
+        throw :invalid_test unless respond_to?(test_method_name)
+        test_method = method(test_method_name)
+        throw :invalid_test if test_method.arity > 0
+        owner = Util::MethodOwnerFinder.find(self, test_method_name)
+        if owner.class != Module and self.class != owner
+          throw :invalid_test
+        end
+        @method_name = test_method_name
+        @test_passed = true
+        @interrupted = false
+      end
+
+      # Runs the individual test method represented by this
+      # instance of the fixture, collecting statistics, failures
+      # and errors in result.
+      def run(result)
+        begin
+          @_result = result
+          yield(STARTED, name)
+          begin
+            run_setup
+            run_test
+          rescue Exception
+            @interrupted = true
+            raise unless handle_exception($!)
+          ensure
+            begin
+              run_teardown
+            rescue Exception
+              raise unless handle_exception($!)
+            end
+          end
+          result.add_run
+          yield(FINISHED, name)
+        ensure
+          # @_result = nil # For test-spec's after_all :<
+        end
+      end
+
+      # Called before every test method runs. Can be used
+      # to set up fixture information.
+      #
+      # You can add additional setup tasks by the following
+      # code:
+      #   class TestMyClass < Test::Unit::TestCase
+      #     def setup
+      #       ...
+      #     end
+      #
+      #     setup
+      #     def my_setup1
+      #       ...
+      #     end
+      #
+      #     setup
+      #     def my_setup2
+      #       ...
+      #     end
+      #
+      #     def test_my_class
+      #       ...
+      #     end
+      #   end
+      #
+      # Here is a call order:
+      # * setup
+      # * my_setup1
+      # * my_setup2
+      # * test_my_class
+      def setup
+      end
+
+      # Called after every test method runs. Can be used to tear
+      # down fixture information.
+      #
+      # You can add additional teardown tasks by the following
+      # code:
+      #   class TestMyClass < Test::Unit::TestCase
+      #     def teardown
+      #       ...
+      #     end
+      #
+      #     teardown
+      #     def my_teardown1
+      #       ...
+      #     end
+      #
+      #     teardown
+      #     def my_teardown2
+      #       ...
+      #     end
+      #
+      #     def test_my_class
+      #       ...
+      #     end
+      #   end
+      #
+      # Here is a call order:
+      # * test_my_class
+      # * my_teardown2
+      # * my_teardown1
+      # * teardown
+      def teardown
+      end
+
+      def default_test
+        flunk("No tests were specified")
+      end
+
+      def size
+        1
+      end
+
+      # Returns a human-readable name for the specific test that
+      # this instance of TestCase represents.
+      def name
+        "#{@method_name}(#{self.class.name})"
+      end
+
+      # Overridden to return #name.
+      def to_s
+        name
+      end
+
+      # It's handy to be able to compare TestCase instances.
+      def ==(other)
+        return false unless(other.kind_of?(self.class))
+        return false unless(@method_name == other.method_name)
+        self.class == other.class
+      end
+
+      def interrupted?
+        @interrupted
+      end
+
+      private
+      def current_result
+        @_result
+      end
+
+      def run_test
+        __send__(@method_name)
+      end
+
+      def handle_exception(exception)
+        self.class.exception_handlers.each do |handler|
+          return true if send(handler, exception)
+        end
+        false
+      end
+
+      # Returns whether this individual test passed or
+      # not. Primarily for use in teardown so that artifacts
+      # can be left behind if the test fails.
+      def passed?
+        @test_passed
+      end
+
+      def problem_occurred
+        @test_passed = false
+      end
+
+      def add_assertion
+        current_result.add_assertion
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/testresult.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/testresult.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/testresult.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,89 @@
+#--
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/observable'
+require 'test/unit/failure'
+require 'test/unit/error'
+require 'test/unit/omission'
+require 'test/unit/pending'
+require 'test/unit/notification'
+
+module Test
+  module Unit
+    module NullResultContainerInitializer
+      private
+      def initialize_containers
+      end
+    end
+
+    # Collects Test::Unit::Failure and Test::Unit::Error so that
+    # they can be displayed to the user. To this end, observers
+    # can be added to it, allowing the dynamic updating of, say, a
+    # UI.
+    class TestResult
+      include Util::Observable
+      include NullResultContainerInitializer
+      include TestResultFailureSupport
+      include TestResultErrorSupport
+      include TestResultPendingSupport
+      include TestResultOmissionSupport
+      include TestResultNotificationSupport
+
+      CHANGED = "CHANGED"
+      FAULT = "FAULT"
+
+      attr_reader :run_count, :assertion_count, :faults
+
+      # Constructs a new, empty TestResult.
+      def initialize
+        @run_count, @assertion_count = 0, 0
+        @summary_generators = []
+        @problem_checkers = []
+        @faults = []
+        initialize_containers
+      end
+
+      # Records a test run.
+      def add_run
+        @run_count += 1
+        notify_changed
+      end
+
+      # Records an individual assertion.
+      def add_assertion
+        @assertion_count += 1
+        notify_changed
+      end
+
+      # Returns a string contain the recorded runs, assertions,
+      # failures and errors in this TestResult.
+      def summary
+        ["#{run_count} tests",
+         "#{assertion_count} assertions",
+         *@summary_generators.collect {|generator| send(generator)}].join(", ")
+      end
+
+      def to_s
+        summary
+      end
+
+      # Returns whether or not this TestResult represents
+      # successful completion.
+      def passed?
+        @problem_checkers.all? {|checker| not send(checker)}
+      end
+
+      private
+      def notify_changed
+        notify_listeners(CHANGED, self)
+      end
+
+      def notify_fault(fault)
+        @faults << fault
+        notify_listeners(FAULT, fault)
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/testsuite.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/testsuite.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/testsuite.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,110 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/error'
+
+module Test
+  module Unit
+
+    # A collection of tests which can be #run.
+    #
+    # Note: It is easy to confuse a TestSuite instance with
+    # something that has a static suite method; I know because _I_
+    # have trouble keeping them straight. Think of something that
+    # has a suite method as simply providing a way to get a
+    # meaningful TestSuite instance.
+    class TestSuite
+      attr_reader :name, :tests
+      
+      STARTED = name + "::STARTED"
+      FINISHED = name + "::FINISHED"
+
+      # Creates a new TestSuite with the given name.
+      def initialize(name="Unnamed TestSuite", test_case=nil)
+        @name = name
+        @tests = []
+        @test_case = test_case
+      end
+
+      # Runs the tests and/or suites contained in this
+      # TestSuite.
+      def run(result, &progress_block)
+        yield(STARTED, name)
+        run_startup(result)
+        @tests.each do |test|
+          test.run(result, &progress_block)
+        end
+        run_shutdown(result)
+        yield(FINISHED, name)
+      end
+
+      # Adds the test to the suite.
+      def <<(test)
+        @tests << test
+        self
+      end
+
+      def delete(test)
+        @tests.delete(test)
+      end
+
+      # Retuns the rolled up number of tests in this suite;
+      # i.e. if the suite contains other suites, it counts the
+      # tests within those suites, not the suites themselves.
+      def size
+        total_size = 0
+        @tests.each { |test| total_size += test.size }
+        total_size
+      end
+      
+      def empty?
+        tests.empty?
+      end
+
+      # Overridden to return the name given the suite at
+      # creation.
+      def to_s
+        @name
+      end
+      
+      # It's handy to be able to compare TestSuite instances.
+      def ==(other)
+        return false unless(other.kind_of?(self.class))
+        return false unless(@name == other.name)
+        @tests == other.tests
+      end
+
+      private
+      def run_startup(result)
+        return if @test_case.nil? or !@test_case.respond_to?(:startup)
+        begin
+          @test_case.startup
+        rescue Exception
+          raise unless handle_exception($!, result)
+        end
+      end
+
+      def run_shutdown(result)
+        return if @test_case.nil? or !@test_case.respond_to?(:shutdown)
+        begin
+          @test_case.shutdown
+        rescue Exception
+          raise unless handle_exception($!, result)
+        end
+      end
+
+      def handle_exception(exception, result)
+        case exception
+        when *ErrorHandler::PASS_THROUGH_EXCEPTIONS
+          false
+        else
+          result.add_error(Error.new(@test_case.name, exception))
+          true
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/outputlevel.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/outputlevel.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/outputlevel.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,14 @@
+module Test
+  module Unit
+    module UI
+      module Console
+        module OutputLevel
+          SILENT = 0
+          PROGRESS_ONLY = 1
+          NORMAL = 2
+          VERBOSE = 3
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/testrunner.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/testrunner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/console/testrunner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,278 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright::
+#   * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+#   * Copyright (c) 2008-2009 Kouhei Sutou <kou at clear-code.com>
+# License:: Ruby license.
+
+require 'test/unit/color-scheme'
+require 'test/unit/ui/testrunner'
+require 'test/unit/ui/testrunnermediator'
+require 'test/unit/ui/console/outputlevel'
+
+module Test
+  module Unit
+    module UI
+      module Console
+
+        # Runs a Test::Unit::TestSuite on the console.
+        class TestRunner < UI::TestRunner
+          include OutputLevel
+
+          # Creates a new TestRunner for running the passed
+          # suite. If quiet_mode is true, the output while
+          # running is limited to progress dots, errors and
+          # failures, and the final result. io specifies
+          # where runner output should go to; defaults to
+          # STDOUT.
+          def initialize(suite, options={})
+            super
+            @output_level = @options[:output_level] || NORMAL
+            @output = @options[:output] || STDOUT
+            @use_color = @options[:use_color]
+            @use_color = guess_color_availability if @use_color.nil?
+            @color_scheme = @options[:color_scheme] || ColorScheme.default
+            @reset_color = Color.new("reset")
+            @progress_row = 0
+            @progress_row_max = @options[:progress_row_max]
+            @progress_row_max ||= guess_progress_row_max
+            @already_outputted = false
+            @n_successes = 0
+            @indent = 0
+            @top_level = true
+            @faults = []
+          end
+
+          # Begins the test run.
+          def start
+            setup_mediator
+            attach_to_mediator
+            return start_mediator
+          end
+
+          private
+          def setup_mediator
+            @mediator = create_mediator(@suite)
+            output_setup_end
+          end
+
+          def output_setup_end
+            suite_name = @suite.to_s
+            suite_name = @suite.name if @suite.kind_of?(Module)
+            output("Loaded suite #{suite_name}")
+          end
+
+          def create_mediator(suite)
+            return TestRunnerMediator.new(suite)
+          end
+          
+          def attach_to_mediator
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
+            @mediator.add_listener(TestSuite::STARTED, &method(:test_suite_started))
+            @mediator.add_listener(TestSuite::FINISHED, &method(:test_suite_finished))
+          end
+          
+          def start_mediator
+            return @mediator.run_suite
+          end
+          
+          def add_fault(fault)
+            @faults << fault
+            output_progress(fault.single_character_display, fault_color(fault))
+            @already_outputted = true
+          end
+          
+          def started(result)
+            @result = result
+            output_started
+          end
+
+          def output_started
+            output("Started")
+          end
+
+          def finished(elapsed_time)
+            nl if output?(NORMAL) and !output?(VERBOSE)
+            @faults.each_with_index do |fault, index|
+              nl
+              output_single("%3d) " % (index + 1))
+              label, detail = format_fault(fault).split(/\r?\n/, 2)
+              output(label, fault_color(fault))
+              output(detail)
+            end
+            nl
+            output("Finished in #{elapsed_time} seconds.")
+            nl
+            output(@result, result_color)
+            n_tests = @result.run_count
+            if n_tests.zero?
+              pass_percentage = 0
+            else
+              pass_percentage = 100.0 * (@n_successes / n_tests.to_f)
+            end
+            output("%g%% passed" % pass_percentage, result_color)
+          end
+
+          def format_fault(fault)
+            fault.long_display
+          end
+
+          def test_started(name)
+            return unless output?(VERBOSE)
+
+            name = name.sub(/\(.+?\)\z/, '')
+            right_space = 8 * 2
+            left_space = @progress_row_max - right_space
+            left_space = left_space - indent.size - name.size
+            tab_stop = "\t" * ((left_space - 1) / 8)
+            output_single("#{indent}#{name}:#{tab_stop}", nil, VERBOSE)
+            @test_start = Time.now
+          end
+
+          def test_finished(name)
+            unless @already_outputted
+              @n_successes += 1
+              output_progress(".", color("success"))
+            end
+            @already_outputted = false
+
+            return unless output?(VERBOSE)
+
+            output(": (%f)" % (Time.now - @test_start), nil, VERBOSE)
+          end
+
+          def test_suite_started(name)
+            if @top_level
+              @top_level = false
+              return
+            end
+
+            output_single(indent, nil, VERBOSE)
+            if /\A[A-Z]/ =~ name
+              _color = color("case")
+            else
+              _color = color("suite")
+            end
+            output_single(name, _color, VERBOSE)
+            output(": ", nil, VERBOSE)
+            @indent += 2
+          end
+
+          def test_suite_finished(name)
+            @indent -= 2
+          end
+
+          def indent
+            if output?(VERBOSE)
+              " " * @indent
+            else
+              ""
+            end
+          end
+
+          def nl(level=NORMAL)
+            output("", nil, level)
+          end
+          
+          def output(something, color=nil, level=NORMAL)
+            return unless output?(level)
+            output_single(something, color, level)
+            @output.puts
+          end
+          
+          def output_single(something, color=nil, level=NORMAL)
+            return false unless output?(level)
+            if @use_color and color
+              something = "%s%s%s" % [color.escape_sequence,
+                                      something,
+                                      @reset_color.escape_sequence]
+            end
+            @output.write(something)
+            @output.flush
+            true
+          end
+
+          def output_progress(mark, color=nil)
+            if output_single(mark, color, PROGRESS_ONLY)
+              return unless @progress_row_max > 0
+              @progress_row += mark.size
+              if @progress_row >= @progress_row_max
+                nl unless @output_level == VERBOSE
+                @progress_row = 0
+              end
+            end
+          end
+
+          def output?(level)
+            level <= @output_level
+          end
+
+          def color(name)
+            @color_scheme[name] || ColorScheme.default[name]
+          end
+
+          def fault_color(fault)
+            color(fault.class.name.split(/::/).last.downcase)
+          end
+
+          def result_color
+            if @result.passed?
+              if @result.pending_count > 0
+                color("pending")
+              elsif @result.omission_count > 0
+                color("omission")
+              elsif @result.notification_count > 0
+                color("notification")
+              else
+                color("success")
+              end
+            elsif @result.error_count > 0
+              color("error")
+            elsif @result.failure_count > 0
+              color("failure")
+            end
+          end
+
+          def guess_color_availability
+            return false unless @output.tty?
+            case ENV["TERM"]
+            when /term(?:-color)?\z/, "screen"
+              true
+            else
+              return true if ENV["EMACS"] == "t"
+              false
+            end
+          end
+
+          def guess_progress_row_max
+            term_width = guess_term_width
+            if term_width.zero?
+              if ENV["EMACS"] == "t"
+                -1
+              else
+                79
+              end
+            else
+              term_width
+            end
+          end
+
+          def guess_term_width
+            Integer(ENV["TERM_WIDTH"] || 0)
+          rescue ArgumentError
+            0
+          end
+        end
+      end
+    end
+  end
+end
+
+if __FILE__ == $0
+  Test::Unit::UI::Console::TestRunner.start_command_line_test
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/emacs/testrunner.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/emacs/testrunner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/emacs/testrunner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,49 @@
+require 'test/unit/ui/console/testrunner'
+
+module Test
+  module Unit
+    module UI
+      module Emacs
+        class TestRunner < Console::TestRunner
+          private
+          def output_setup_end
+          end
+
+          def output_started
+          end
+
+          def format_fault(fault)
+            return super unless fault.respond_to?(:label)
+            format_method_name = "format_fault_#{fault.label.downcase}"
+            if respond_to?(format_method_name, true)
+              send(format_method_name, fault)
+            else
+              super
+            end
+          end
+
+          def format_fault_failure(failure)
+            if failure.location.size == 1
+              location = failure.location[0]
+              location_display = location.sub(/\A(.+:\d+).*/, ' [\\1]')
+            else
+              location_display = "\n" + failure.location.join("\n")
+            end
+            result = "#{failure.label}:\n"
+            result << "#{failure.test_name}#{location_display}:\n"
+            result << failure.message
+            result
+          end
+
+          def format_fault_error(error)
+            result = "#{error.label}:\n"
+            result << "#{error.test_name}:\n"
+            result << "#{error.message}\n"
+            result << error.backtrace.join("\n")
+            result
+          end
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/tap/testrunner.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/tap/testrunner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/tap/testrunner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,92 @@
+#--
+#
+# Author:: Kouhei Sutou.
+# Copyright:: Copyright (c) 2009 Kouhei Sutou <kou at clear-code.com>.
+# License:: Ruby license.
+
+require 'test/unit/ui/testrunner'
+require 'test/unit/ui/testrunnermediator'
+
+module Test
+  module Unit
+    module UI
+      module Tap
+
+        # Runs a Test::Unit::TestSuite and outputs result
+        # as TAP format.
+        class TestRunner < UI::TestRunner
+          def initialize(suite, options={})
+            super
+            @output = @options[:output] || STDOUT
+            @n_tests = 0
+            @already_outputted = false
+          end
+
+          # Begins the test run.
+          def start
+            setup_mediator
+            result = start_mediator
+            def result.passed?
+              true # for prove commend :<
+            end
+            result
+          end
+
+          private
+          def setup_mediator
+            @mediator = TestRunnerMediator.new(@suite)
+            attach_to_mediator
+          end
+
+          def attach_to_mediator
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
+          end
+
+          def start_mediator
+            @mediator.run_suite
+          end
+
+          def add_fault(fault)
+            puts("not ok #{@n_tests} - #{fault.short_display}")
+            fault.long_display.each_line do |line|
+              puts("# #{line}")
+            end
+            @already_outputted = true
+          end
+
+          def started(result)
+            @result = result
+            puts("1..#{@suite.size}")
+          end
+
+          def finished(elapsed_time)
+            puts("# Finished in #{elapsed_time} seconds.")
+            @result.to_s.each_line do |line|
+              puts("# #{line}")
+            end
+          end
+
+          def test_started(name)
+            @n_tests += 1
+          end
+
+          def test_finished(name)
+            unless @already_outputted
+              puts("ok #{@n_tests} - #{name}")
+            end
+            @already_outputted = false
+          end
+
+          def puts(*args)
+            @output.puts(*args)
+            @output.flush
+          end
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunner.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,20 @@
+require 'test/unit/ui/testrunnerutilities'
+
+module Test
+  module Unit
+    module UI
+      class TestRunner
+        extend TestRunnerUtilities
+
+        def initialize(suite, options={})
+          if suite.respond_to?(:suite)
+            @suite = suite.suite
+          else
+            @suite = suite
+          end
+          @options = options
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnermediator.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnermediator.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnermediator.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,77 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/util/observable'
+require 'test/unit/testresult'
+
+module Test
+  module Unit
+    module UI
+
+      # Provides an interface to write any given UI against,
+      # hopefully making it easy to write new UIs.
+      class TestRunnerMediator
+        RESET = name + "::RESET"
+        STARTED = name + "::STARTED"
+        FINISHED = name + "::FINISHED"
+        
+        include Util::Observable
+        
+        # Creates a new TestRunnerMediator initialized to run
+        # the passed suite.
+        def initialize(suite)
+          @suite = suite
+        end
+
+        # Runs the suite the TestRunnerMediator was created
+        # with.
+        def run_suite
+          Unit.run = true
+
+          result = create_result
+          result_listener = result.add_listener(TestResult::CHANGED) do |*args|
+            notify_listeners(TestResult::CHANGED, *args)
+          end
+          fault_listener = result.add_listener(TestResult::FAULT) do |*args|
+            notify_listeners(TestResult::FAULT, *args)
+          end
+
+          start_time = Time.now
+          begin
+            notify_listeners(RESET, @suite.size)
+            notify_listeners(STARTED, result)
+
+            @suite.run(result) do |channel, value|
+              notify_listeners(channel, value)
+            end
+          ensure
+            elapsed_time = Time.now - start_time
+            result.remove_listener(TestResult::FAULT, fault_listener)
+            result.remove_listener(TestResult::CHANGED, result_listener)
+            notify_listeners(FINISHED, elapsed_time)
+          end
+
+          result
+        end
+
+        private
+        # A factory method to create the result the mediator
+        # should run with. Can be overridden by subclasses if
+        # one wants to use a different result.
+        def create_result
+          TestResult.new
+        end
+
+        def measure_time
+          begin_time = Time.now
+          yield
+          Time.now - begin_time
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnerutilities.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnerutilities.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/ui/testrunnerutilities.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,41 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+    module UI
+
+      # Provides some utilities common to most, if not all,
+      # TestRunners.
+      #
+      #--
+      #
+      # Perhaps there ought to be a TestRunner superclass? There
+      # seems to be a decent amount of shared code between test
+      # runners.
+
+      module TestRunnerUtilities
+
+        # Creates a new TestRunner and runs the suite.
+        def run(suite, options={})
+          return new(suite, options).start
+        end
+
+        # Takes care of the ARGV parsing and suite
+        # determination necessary for running one of the
+        # TestRunners from the command line.
+        def start_command_line_test
+          if ARGV.empty?
+            puts "You should supply the name of a test suite file to the runner"
+            exit
+          end
+          require ARGV[0].gsub(/.+::/, '')
+          new(eval(ARGV[0])).start
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/backtracefilter.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/backtracefilter.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/backtracefilter.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,41 @@
+module Test
+  module Unit
+    module Util
+      module BacktraceFilter
+        TESTUNIT_FILE_SEPARATORS = %r{[\\/:]}
+        TESTUNIT_PREFIX = __FILE__.split(TESTUNIT_FILE_SEPARATORS)[0..-3]
+        TESTUNIT_RB_FILE = /\.rb\Z/
+
+        module_function
+        def filter_backtrace(backtrace, prefix=nil)
+          return ["No backtrace"] unless(backtrace)
+          split_p = if(prefix)
+            prefix.split(TESTUNIT_FILE_SEPARATORS)
+          else
+            TESTUNIT_PREFIX
+          end
+          match = proc do |e|
+            split_e = e.split(TESTUNIT_FILE_SEPARATORS)[0, split_p.size]
+            next false unless(split_e[0..-2] == split_p[0..-2])
+            split_e[-1].sub(TESTUNIT_RB_FILE, '') == split_p[-1]
+          end
+          return backtrace unless(backtrace.detect(&match))
+          found_prefix = false
+          new_backtrace = backtrace.reverse.reject do |e|
+            if(match[e])
+              found_prefix = true
+              true
+            elsif(found_prefix)
+              false
+            else
+              true
+            end
+          end.reverse
+          new_backtrace = (new_backtrace.empty? ? backtrace : new_backtrace)
+          new_backtrace = new_backtrace.reject(&match)
+          new_backtrace.empty? ? backtrace : new_backtrace
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/method-owner-finder.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/method-owner-finder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/method-owner-finder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,28 @@
+module Test
+  module Unit
+    module Util
+      module MethodOwnerFinder
+        module_function
+        def find(object, method_name)
+          method = object.method(method_name)
+          return method.owner if method.respond_to?(:owner)
+
+          if /\((.+?)\)\#/ =~ method.to_s
+            owner_name = $1
+            if /\A#</ =~ owner_name
+              ObjectSpace.each_object(Module) do |mod|
+                return mod if mod.to_s == owner_name
+              end
+            else
+              owner_name.split(/::/).inject(Object) do |parent, name|
+                parent.const_get(name)
+              end
+            end
+          else
+            object.class
+          end
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/observable.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/observable.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/observable.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,90 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/procwrapper'
+
+module Test
+  module Unit
+    module Util
+
+      # This is a utility class that allows anything mixing
+      # it in to notify a set of listeners about interesting
+      # events.
+      module Observable
+        # We use this for defaults since nil might mean something
+        NOTHING = "NOTHING/#{__id__}"
+
+        # Adds the passed proc as a listener on the
+        # channel indicated by channel_name. listener_key
+        # is used to remove the listener later; if none is
+        # specified, the proc itself is used.
+        #
+        # Whatever is used as the listener_key is
+        # returned, making it very easy to use the proc
+        # itself as the listener_key:
+        #
+        #  listener = add_listener("Channel") { ... }
+        #  remove_listener("Channel", listener)
+        def add_listener(channel_name, listener_key=NOTHING, &listener) # :yields: value
+          unless(block_given?)
+            raise ArgumentError.new("No callback was passed as a listener")
+          end
+      
+          key = listener_key
+          if (listener_key == NOTHING)
+            listener_key = listener
+            key = ProcWrapper.new(listener)
+          end
+      
+          channels[channel_name] ||= {}
+          channels[channel_name][key] = listener
+          return listener_key
+        end
+
+        # Removes the listener indicated by listener_key
+        # from the channel indicated by
+        # channel_name. Returns the registered proc, or
+        # nil if none was found.
+        def remove_listener(channel_name, listener_key)
+          channel = channels[channel_name]
+          return nil unless (channel)
+          key = listener_key
+          if (listener_key.instance_of?(Proc))
+            key = ProcWrapper.new(listener_key)
+          end
+          if (channel.has_key?(key))
+            return channel.delete(key)
+          end
+          return nil
+        end
+
+        # Calls all the procs registered on the channel
+        # indicated by channel_name. If value is
+        # specified, it is passed in to the procs,
+        # otherwise they are called with no arguments.
+        #
+        #--
+        #
+        # Perhaps this should be private? Would it ever
+        # make sense for an external class to call this
+        # method directly?
+        def notify_listeners(channel_name, *arguments)
+          channel = channels[channel_name]
+          return 0 unless (channel)
+          listeners = channel.values
+          listeners.each { |listener| listener.call(*arguments) }
+          return listeners.size
+        end
+
+        private
+        def channels
+          @channels ||= {}
+          return @channels
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/procwrapper.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/procwrapper.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/util/procwrapper.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,48 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+    module Util
+
+      # Allows the storage of a Proc passed through '&' in a
+      # hash.
+      #
+      # Note: this may be inefficient, since the hash being
+      # used is not necessarily very good. In Observable,
+      # efficiency is not too important, since the hash is
+      # only accessed when adding and removing listeners,
+      # not when notifying.
+
+      class ProcWrapper
+
+        # Creates a new wrapper for a_proc.
+        def initialize(a_proc)
+          @a_proc = a_proc
+          @hash = a_proc.inspect.sub(/^(#<#{a_proc.class}:)/){''}.sub(/(>)$/){''}.hex
+        end
+
+        def hash
+          return @hash
+        end
+
+        def ==(other)
+          case(other)
+            when ProcWrapper
+              return @a_proc == other.to_proc
+            else
+              return super
+          end
+        end
+        alias :eql? :==
+
+        def to_proc
+          return @a_proc
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit/version.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit/version.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit/version.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,7 @@
+
+# HACK: quick and dirty to get integrated into the new project - ryan
+module Test
+  module Unit
+    VERSION = '2.0.3'
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/lib/test/unit.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/lib/test/unit.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/lib/test/unit.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,342 @@
+require 'test/unit/testcase'
+require 'test/unit/autorunner'
+
+module Test # :nodoc:
+  #
+  # = Test::Unit - Ruby Unit Testing Framework
+  # 
+  # == Introduction
+  # 
+  # Unit testing is making waves all over the place, largely due to the
+  # fact that it is a core practice of XP. While XP is great, unit testing
+  # has been around for a long time and has always been a good idea. One
+  # of the keys to good unit testing, though, is not just writing tests,
+  # but having tests. What's the difference? Well, if you just _write_ a
+  # test and throw it away, you have no guarantee that something won't
+  # change later which breaks your code. If, on the other hand, you _have_
+  # tests (obviously you have to write them first), and run them as often
+  # as possible, you slowly build up a wall of things that cannot break
+  # without you immediately knowing about it. This is when unit testing
+  # hits its peak usefulness.
+  # 
+  # Enter Test::Unit, a framework for unit testing in Ruby, helping you to
+  # design, debug and evaluate your code by making it easy to write and
+  # have tests for it.
+  # 
+  # 
+  # == Notes
+  # 
+  # Test::Unit has grown out of and superceded Lapidary.
+  # 
+  # 
+  # == Feedback
+  # 
+  # I like (and do my best to practice) XP, so I value early releases,
+  # user feedback, and clean, simple, expressive code. There is always
+  # room for improvement in everything I do, and Test::Unit is no
+  # exception. Please, let me know what you think of Test::Unit as it
+  # stands, and what you'd like to see expanded/changed/improved/etc. If
+  # you find a bug, let me know ASAP; one good way to let me know what the
+  # bug is is to submit a new test that catches it :-) Also, I'd love to
+  # hear about any successes you have with Test::Unit, and any
+  # documentation you might add will be greatly appreciated. My contact
+  # info is below.
+  # 
+  # 
+  # == Contact Information
+  # 
+  # A lot of discussion happens about Ruby in general on the ruby-talk
+  # mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask
+  # any questions you might have there. I monitor the list, as do many
+  # other helpful Rubyists, and you're sure to get a quick answer. Of
+  # course, you're also welcome to email me (Nathaniel Talbott) directly
+  # at mailto:testunit at talbott.ws, and I'll do my best to help you out.
+  # 
+  # 
+  # == Credits
+  # 
+  # I'd like to thank...
+  # 
+  # Matz, for a great language!
+  # 
+  # Masaki Suketa, for his work on RubyUnit, which filled a vital need in
+  # the Ruby world for a very long time. I'm also grateful for his help in
+  # polishing Test::Unit and getting the RubyUnit compatibility layer
+  # right. His graciousness in allowing Test::Unit to supercede RubyUnit
+  # continues to be a challenge to me to be more willing to defer my own
+  # rights.
+  # 
+  # Ken McKinlay, for his interest and work on unit testing, and for his
+  # willingness to dialog about it. He was also a great help in pointing
+  # out some of the holes in the RubyUnit compatibility layer.
+  # 
+  # Dave Thomas, for the original idea that led to the extremely simple
+  # "require 'test/unit'", plus his code to improve it even more by
+  # allowing the selection of tests from the command-line. Also, without
+  # RDoc, the documentation for Test::Unit would stink a lot more than it
+  # does now.
+  # 
+  # Everyone who's helped out with bug reports, feature ideas,
+  # encouragement to continue, etc. It's a real privilege to be a part of
+  # the Ruby community.
+  # 
+  # The guys at RoleModel Software, for putting up with me repeating, "But
+  # this would be so much easier in Ruby!" whenever we're coding in Java.
+  # 
+  # My Creator, for giving me life, and giving it more abundantly.
+  # 
+  # 
+  # == License
+  # 
+  # Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free
+  # software, and is distributed under the Ruby license. See the COPYING
+  # file in the standard Ruby distribution for details.
+  # 
+  # 
+  # == Warranty
+  # 
+  # This software is provided "as is" and without any express or
+  # implied warranties, including, without limitation, the implied
+  # warranties of merchantibility and fitness for a particular
+  # purpose.
+  # 
+  # 
+  # == Author
+  # 
+  # Nathaniel Talbott.
+  # Copyright (c) 2000-2003, Nathaniel Talbott
+  #
+  # ----
+  #
+  # = Usage
+  #
+  # The general idea behind unit testing is that you write a _test_
+  # _method_ that makes certain _assertions_ about your code, working
+  # against a _test_ _fixture_. A bunch of these _test_ _methods_ are
+  # bundled up into a _test_ _suite_ and can be run any time the
+  # developer wants. The results of a run are gathered in a _test_
+  # _result_ and displayed to the user through some UI. So, lets break
+  # this down and see how Test::Unit provides each of these necessary
+  # pieces.
+  #
+  #
+  # == Assertions
+  #
+  # These are the heart of the framework. Think of an assertion as a
+  # statement of expected outcome, i.e. "I assert that x should be equal
+  # to y". If, when the assertion is executed, it turns out to be
+  # correct, nothing happens, and life is good. If, on the other hand,
+  # your assertion turns out to be false, an error is propagated with
+  # pertinent information so that you can go back and make your
+  # assertion succeed, and, once again, life is good. For an explanation
+  # of the current assertions, see Test::Unit::Assertions.
+  #
+  #
+  # == Test Method & Test Fixture
+  #
+  # Obviously, these assertions have to be called within a context that
+  # knows about them and can do something meaningful with their
+  # pass/fail value. Also, it's handy to collect a bunch of related
+  # tests, each test represented by a method, into a common test class
+  # that knows how to run them. The tests will be in a separate class
+  # from the code they're testing for a couple of reasons. First of all,
+  # it allows your code to stay uncluttered with test code, making it
+  # easier to maintain. Second, it allows the tests to be stripped out
+  # for deployment, since they're really there for you, the developer,
+  # and your users don't need them. Third, and most importantly, it
+  # allows you to set up a common test fixture for your tests to run
+  # against.
+  #
+  # What's a test fixture? Well, tests do not live in a vacuum; rather,
+  # they're run against the code they are testing. Often, a collection
+  # of tests will run against a common set of data, also called a
+  # fixture. If they're all bundled into the same test class, they can
+  # all share the setting up and tearing down of that data, eliminating
+  # unnecessary duplication and making it much easier to add related
+  # tests.
+  #
+  # Test::Unit::TestCase wraps up a collection of test methods together
+  # and allows you to easily set up and tear down the same test fixture
+  # for each test. This is done by overriding #setup and/or #teardown,
+  # which will be called before and after each test method that is
+  # run. The TestCase also knows how to collect the results of your
+  # assertions into a Test::Unit::TestResult, which can then be reported
+  # back to you... but I'm getting ahead of myself. To write a test,
+  # follow these steps:
+  #
+  # * Make sure Test::Unit is in your library path.
+  # * require 'test/unit' in your test script.
+  # * Create a class that subclasses Test::Unit::TestCase.
+  # * Add a method that begins with "test" to your class.
+  # * Make assertions in your test method.
+  # * Optionally define #setup and/or #teardown to set up and/or tear
+  #   down your common test fixture.
+  # * You can now run your test as you would any other Ruby
+  #   script... try it and see!
+  #
+  # A really simple test might look like this (#setup and #teardown are
+  # commented out to indicate that they are completely optional):
+  #
+  #     require 'test/unit'
+  #     
+  #     class TC_MyTest < Test::Unit::TestCase
+  #       # def setup
+  #       # end
+  #     
+  #       # def teardown
+  #       # end
+  #     
+  #       def test_fail
+  #         assert(false, 'Assertion was false.')
+  #       end
+  #     end
+  #
+  #
+  # == Test Runners
+  #
+  # So, now you have this great test class, but you still need a way to
+  # run it and view any failures that occur during the run. This is
+  # where Test::Unit::UI::Console::TestRunner (and others, such as
+  # Test::Unit::UI::GTK::TestRunner) comes into play. The console test
+  # runner is automatically invoked for you if you require 'test/unit'
+  # and simply run the file. To use another runner, or to manually
+  # invoke a runner, simply call its run class method and pass in an
+  # object that responds to the suite message with a
+  # Test::Unit::TestSuite. This can be as simple as passing in your
+  # TestCase class (which has a class suite method). It might look
+  # something like this:
+  #
+  #    require 'test/unit/ui/console/testrunner'
+  #    Test::Unit::UI::Console::TestRunner.run(TC_MyTest)
+  #
+  #
+  # == Test Suite
+  #
+  # As more and more unit tests accumulate for a given project, it
+  # becomes a real drag running them one at a time, and it also
+  # introduces the potential to overlook a failing test because you
+  # forget to run it. Suddenly it becomes very handy that the
+  # TestRunners can take any object that returns a Test::Unit::TestSuite
+  # in response to a suite method. The TestSuite can, in turn, contain
+  # other TestSuites or individual tests (typically created by a
+  # TestCase). In other words, you can easily wrap up a group of
+  # TestCases and TestSuites like this:
+  #
+  #  require 'test/unit/testsuite'
+  #  require 'tc_myfirsttests'
+  #  require 'tc_moretestsbyme'
+  #  require 'ts_anothersetoftests'
+  #
+  #  class TS_MyTests
+  #    def self.suite
+  #      suite = Test::Unit::TestSuite.new
+  #      suite << TC_MyFirstTests.suite
+  #      suite << TC_MoreTestsByMe.suite
+  #      suite << TS_AnotherSetOfTests.suite
+  #      return suite
+  #    end
+  #  end
+  #  Test::Unit::UI::Console::TestRunner.run(TS_MyTests)
+  #
+  # Now, this is a bit cumbersome, so Test::Unit does a little bit more
+  # for you, by wrapping these up automatically when you require
+  # 'test/unit'. What does this mean? It means you could write the above
+  # test case like this instead:
+  #
+  #  require 'test/unit'
+  #  require 'tc_myfirsttests'
+  #  require 'tc_moretestsbyme'
+  #  require 'ts_anothersetoftests'
+  #
+  # Test::Unit is smart enough to find all the test cases existing in
+  # the ObjectSpace and wrap them up into a suite for you. It then runs
+  # the dynamic suite using the console TestRunner.
+  #
+  #
+  # == Configuration file
+  #
+  # Test::Unit reads 'test-unit.yml' in the current working
+  # directory as Test::Unit's configuration file. It can
+  # contain the following configurations:
+  #
+  # * color scheme definitions
+  # * test runner to be used
+  # * test runner options
+  # * test collector to be used
+  #
+  # Except color scheme definitions, all of them are
+  # specified by command line option.
+  #
+  # Here are sample color scheme definitions:
+  #
+  #   color_schemes:
+  #     inverted:
+  #       success:
+  #         name: red
+  #         bold: true
+  #       failure:
+  #         name: green
+  #         bold: true
+  #     other_scheme:
+  #       ...
+  #
+  # Here are the syntax of color scheme definitions:
+  #
+  #  color_schemes:
+  #    SCHEME_NAME:
+  #      EVENT_NAME:
+  #        name: COLOR_NAME
+  #        intensity: BOOLEAN
+  #        bold: BOOLEAN
+  #        italic: BOOLEAN
+  #        underline: BOOLEAN
+  #      ...
+  #    ...
+  #
+  # SCHEME_NAME:: the name of the color scheme
+  # EVENT_NAME:: one of [success, failure, pending,
+  #              omission, notification, error]
+  # COLOR_NAME:: one of [black, red, green, yellow, blue,
+  #              magenta, cyan, white]
+  # BOOLEAN:: true or false
+  #
+  # You can use the above 'inverted' color scheme with the
+  # following configuration:
+  #
+  #   runner: console
+  #   console_options:
+  #     color_scheme: inverted
+  #   color_schemes:
+  #     inverted:
+  #       success:
+  #         name: red
+  #         bold: true
+  #       failure:
+  #         name: green
+  #         bold: true
+  #
+  # == Questions?
+  #
+  # I'd really like to get feedback from all levels of Ruby
+  # practitioners about typos, grammatical errors, unclear statements,
+  # missing points, etc., in this document (or any other).
+  #
+
+  module Unit
+    # If set to false Test::Unit will not automatically run at exit.
+    def self.run=(flag)
+      @run = flag
+    end
+
+    # Automatically run tests at exit?
+    def self.run?
+      @run ||= false
+    end
+  end
+end
+
+at_exit do
+  unless $! || Test::Unit.run?
+    exit Test::Unit::AutoRunner.run
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/sample/adder.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/sample/adder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/sample/adder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,13 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+class Adder
+  def initialize(number)
+    @number = number
+  end
+  def add(number)
+    return @number + number
+  end
+end
+

Added: MacRuby/trunk/test/libs/test-unit/sample/subtracter.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/sample/subtracter.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/sample/subtracter.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,12 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+class Subtracter
+  def initialize(number)
+    @number = number
+  end
+  def subtract(number)
+    return @number - number
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/sample/tc_adder.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/sample/tc_adder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/sample/tc_adder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,18 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'adder'
+
+class TC_Adder < Test::Unit::TestCase
+  def setup
+    @adder = Adder.new(5)
+  end
+  def test_add
+    assert_equal(7, @adder.add(2), "Should have added correctly")
+  end
+  def teardown
+    @adder = nil
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/sample/tc_subtracter.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/sample/tc_subtracter.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/sample/tc_subtracter.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,18 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'subtracter'
+
+class TC_Subtracter < Test::Unit::TestCase
+  def setup
+    @subtracter = Subtracter.new(5)
+  end
+  def test_subtract
+    assert_equal(3, @subtracter.subtract(2), "Should have subtracted correctly")
+  end
+  def teardown
+    @subtracter = nil
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/sample/test_user.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/sample/test_user.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/sample/test_user.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,22 @@
+# nested test case example.
+
+class UserTest < Test::Unit::TestCase
+  def setup
+    @user = "me"
+  end
+
+  def test_full_name
+    assert_equal("me", @user)
+  end
+
+  class ProfileTest < UserTest
+    setup
+    def setup_profile
+      @user += ": profile"
+    end
+
+    def test_has_profile
+      assert_match(/: profile/, @user)
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/sample/ts_examples.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/sample/ts_examples.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/sample/ts_examples.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,7 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'tc_adder'
+require 'tc_subtracter'

Added: MacRuby/trunk/test/libs/test-unit/test/collector/test-descendant.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/collector/test-descendant.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/collector/test-descendant.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,135 @@
+require 'test/unit'
+require 'test/unit/collector/descendant'
+
+class TestUnitCollectorDescendant < Test::Unit::TestCase
+  def setup
+    @previous_descendants = Test::Unit::TestCase::DESCENDANTS.dup
+    Test::Unit::TestCase::DESCENDANTS.clear
+
+    @test_case1 = Class.new(Test::Unit::TestCase) do
+      def self.name
+        "test-case1"
+      end
+
+      def test_1
+      end
+
+      def test_2
+      end
+    end
+
+    @test_case2 = Class.new(Test::Unit::TestCase) do
+      def self.name
+        "test-case2"
+      end
+
+      def test_0
+      end
+    end
+
+    @no_test_case = Class.new do
+      def self.name
+        "no-test-case"
+      end
+
+      def test_4
+      end
+    end
+  end
+
+  def teardown
+    Test::Unit::TestCase::DESCENDANTS.replace(@previous_descendants)
+  end
+
+  def test_basic_collection
+    assert_collect(full_suite("name"), "name")
+
+    assert_collect(full_suite("name"), "name") do |collector|
+      collector.filter = []
+    end
+  end
+
+  def test_filtered_collection
+    assert_collect(empty_suite) do |collector|
+      collector.filter = Proc.new {false}
+    end
+
+    assert_collect(full_suite) do |collector|
+      collector.filter = Proc.new {true}
+    end
+
+    assert_collect(full_suite) do |collector|
+      collector.filter = Proc.new {nil}
+    end
+
+    assert_collect(empty_suite) do |collector|
+      collector.filter = [Proc.new {false}, Proc.new {true}]
+    end
+
+    assert_collect(full_suite) do |collector|
+      collector.filter = [Proc.new {true}, Proc.new {false}]
+    end
+
+    assert_collect(empty_suite) do |collector|
+      collector.filter = [Proc.new {nil}, Proc.new {false}]
+    end
+
+    assert_collect(full_suite) do |collector|
+      collector.filter = [Proc.new {nil}, Proc.new {true}]
+    end
+
+    expected = empty_suite
+    suite1 = Test::Unit::TestSuite.new(@test_case1.name)
+    suite1 << @test_case1.new("test_1")
+    suite2 = Test::Unit::TestSuite.new(@test_case2.name)
+    suite2 << @test_case2.new("test_0")
+    expected << suite1 << suite2
+    assert_collect(expected) do |collector|
+      collector.filter = Proc.new do |test|
+        ['test_1', 'test_0'].include?(test.method_name)
+      end
+    end
+
+    expected = empty_suite
+    suite1 = Test::Unit::TestSuite.new(@test_case1.name)
+    suite1 << @test_case1.new("test_1")
+    suite2 = Test::Unit::TestSuite.new(@test_case2.name)
+    suite2 << @test_case2.new("test_0")
+    expected << suite1 << suite2
+    assert_collect(expected) do |collector|
+      filters = [Proc.new {|test| test.method_name == 'test_1' ? true : nil},
+                 Proc.new {|test| test.method_name == 'test_0' ? true : nil},
+                 Proc.new {false}]
+      collector.filter = filters
+    end
+  end
+
+  private
+  def assert_collect(expected, *collect_args)
+    collector = Test::Unit::Collector::Descendant.new
+    yield(collector) if block_given?
+    assert_equal(expected, collector.send(:collect, *collect_args))
+  end
+
+  def default_name
+    Test::Unit::Collector::Descendant::NAME
+  end
+
+  def empty_suite(name=nil)
+    Test::Unit::TestSuite.new(name || default_name)
+  end
+
+  def full_suite(name=nil)
+    sub_suite1 = Test::Unit::TestSuite.new(@test_case1.name)
+    sub_suite1 << @test_case1.new('test_1')
+    sub_suite1 << @test_case1.new('test_2')
+
+    sub_suite2 = Test::Unit::TestSuite.new(@test_case2.name)
+    sub_suite2 << @test_case2.new('test_0')
+
+    suite = empty_suite(name)
+    suite << sub_suite1
+    suite << sub_suite2
+    suite
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/collector/test-load.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/collector/test-load.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/collector/test-load.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,329 @@
+require 'tmpdir'
+require 'pathname'
+
+require 'test/unit'
+require 'test/unit/collector/load'
+
+class TestUnitCollectorLoad < Test::Unit::TestCase
+  def setup
+    @previous_descendants = Test::Unit::TestCase::DESCENDANTS.dup
+    Test::Unit::TestCase::DESCENDANTS.clear
+
+    @temporary_test_cases_module_name = "TempTestCases"
+    ::Object.const_set(@temporary_test_cases_module_name, Module.new)
+
+    @test_dir = Pathname(Dir.tmpdir) + "test-unit"
+    @test_dir.rmtree if @test_dir.exist?
+    @test_dir.mkpath
+  end
+
+  setup
+  def setup_top_level_test_cases
+    @test_case1 = @test_dir + "test_case1.rb"
+    @test_case2 = @test_dir + "test_case2.rb"
+    @no_load_test_case3 = @test_dir + "case3.rb"
+
+    @test_case1.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class TestCase1 < Test::Unit::TestCase
+    def test1_1
+    end
+
+    def test1_2
+    end
+  end
+end
+EOT
+    end
+
+    @test_case2.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class TestCase2 < Test::Unit::TestCase
+    def test2
+    end
+  end
+end
+EOT
+    end
+
+    @no_load_test_case3.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class NoLoadTestCase3 < Test::Unit::TestCase
+    def test3
+    end
+  end
+end
+EOT
+    end
+  end
+
+  setup
+  def setup_sub_level_test_cases
+    @sub_test_dir = @test_dir + "sub"
+    @sub_test_dir.mkpath
+
+    @sub_test_case4 = @sub_test_dir + "test_case4.rb"
+    @no_load_sub_test_case5 = @sub_test_dir + "case5.rb"
+    @sub_test_case6 = @sub_test_dir + "test_case6.rb"
+
+    @sub_test_case4.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class SubTestCase4 < Test::Unit::TestCase
+    def test4_1
+    end
+
+    def test4_2
+    end
+  end
+end
+EOT
+    end
+
+    @no_load_sub_test_case5.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class NoLoadSubTestCase5 < Test::Unit::TestCase
+    def test5_1
+    end
+
+    def test5_2
+    end
+  end
+end
+EOT
+    end
+
+    @sub_test_case6.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class SubTestCase6 < Test::Unit::TestCase
+    def test6
+    end
+  end
+end
+EOT
+    end
+  end
+
+  setup
+  def setup_sub_level_test_cases2
+    @sub2_test_dir = @test_dir + "sub2"
+    @sub2_test_dir.mkpath
+
+    @no_load_sub2_test_case7 = @sub2_test_dir + "case7.rb"
+    @sub2_test_case8 = @sub2_test_dir + "test_case8.rb"
+    @sub2_test_case9 = @sub2_test_dir + "test_case9.rb"
+
+    @no_load_sub2_test_case7.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class NoLoadSub2TestCase7 < Test::Unit::TestCase
+    def test7_1
+    end
+
+    def test7_2
+    end
+  end
+end
+EOT
+    end
+
+    @sub2_test_case8.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class Sub2TestCase8 < Test::Unit::TestCase
+    def test8_1
+    end
+
+    def test8_2
+    end
+  end
+end
+EOT
+    end
+
+    @sub2_test_case9.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class Sub2TestCase9 < Test::Unit::TestCase
+    def test9
+    end
+  end
+end
+EOT
+    end
+  end
+
+  setup
+  def setup_svn_test_cases
+    @svn_test_dir = @test_dir + ".svn"
+    @svn_test_dir.mkpath
+
+    @svn_test_case10 = @svn_test_dir + "test_case10.rb"
+
+    @svn_test_case10.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class SvnTestCase10 < Test::Unit::TestCase
+    def test7
+    end
+  end
+end
+EOT
+    end
+  end
+
+  setup
+  def setup_sub_cvs_test_cases
+    @sub_cvs_test_dir = @sub_test_dir + "CVS"
+    @sub_cvs_test_dir.mkpath
+
+    @sub_cvs_test_case11 = @sub_cvs_test_dir + "test_case11.rb"
+
+    @sub_cvs_test_case11.open("w") do |test_case|
+      test_case.puts(<<-EOT)
+module #{@temporary_test_cases_module_name}
+  class SubCVSTestCase11 < Test::Unit::TestCase
+    def test11
+    end
+  end
+end
+EOT
+    end
+  end
+
+  def teardown
+    @test_dir.rmtree if @test_dir.exist?
+    ::Object.send(:remove_const, @temporary_test_cases_module_name)
+    Test::Unit::TestCase::DESCENDANTS.replace(@previous_descendants)
+  end
+
+  def test_simple_collect
+    assert_collect([:suite, {:name => @sub_test_dir.basename.to_s},
+                    [:suite, {:name => _test_case_name("SubTestCase4")},
+                     [:test, {:name => "test4_1"}],
+                     [:test, {:name => "test4_2"}]],
+                    [:suite, {:name => _test_case_name("SubTestCase6")},
+                     [:test, {:name => "test6"}]]],
+                   @sub_test_dir.to_s)
+  end
+
+  def test_multilevel_collect
+    assert_collect([:suite, {:name => "."},
+                    [:suite, {:name => _test_case_name("TestCase1")},
+                     [:test, {:name => "test1_1"}],
+                     [:test, {:name => "test1_2"}]],
+                    [:suite, {:name => _test_case_name("TestCase2")},
+                     [:test, {:name => "test2"}]],
+                    [:suite, {:name => @sub_test_dir.basename.to_s},
+                     [:suite, {:name => _test_case_name("SubTestCase4")},
+                      [:test, {:name => "test4_1"}],
+                      [:test, {:name => "test4_2"}]],
+                     [:suite, {:name => _test_case_name("SubTestCase6")},
+                      [:test, {:name => "test6"}]]],
+                   [:suite, {:name => @sub2_test_dir.basename.to_s},
+                     [:suite, {:name => _test_case_name("Sub2TestCase8")},
+                      [:test, {:name => "test8_1"}],
+                      [:test, {:name => "test8_2"}]],
+                     [:suite, {:name => _test_case_name("Sub2TestCase9")},
+                      [:test, {:name => "test9"}]]]])
+  end
+
+  def test_collect_file
+    assert_collect([:suite, {:name => @test_case1.basename.to_s},
+                    [:suite, {:name => _test_case_name("TestCase1")},
+                     [:test, {:name => "test1_1"}],
+                     [:test, {:name => "test1_2"}]]],
+                   @test_case1.to_s)
+
+    assert_collect(nil, @no_load_sub_test_case5.to_s)
+  end
+
+  def test_nil_pattern
+    assert_collect([:suite, {:name => @sub_test_dir.basename.to_s},
+                    [:suite, {:name => _test_case_name("NoLoadSubTestCase5")},
+                     [:test, {:name => "test5_1"}],
+                     [:test, {:name => "test5_2"}]],
+                    [:suite, {:name => _test_case_name("SubTestCase4")},
+                     [:test, {:name => "test4_1"}],
+                     [:test, {:name => "test4_2"}]],
+                    [:suite, {:name => _test_case_name("SubTestCase6")},
+                     [:test, {:name => "test6"}]]],
+                   @sub_test_dir.to_s) do |collector|
+      collector.patterns.clear
+    end
+  end
+
+  def test_filtering
+    assert_collect([:suite, {:name => "."},
+                    [:suite, {:name => _test_case_name("TestCase1")},
+                     [:test, {:name => "test1_1"}],
+                     [:test, {:name => "test1_2"}]]]) do |collector|
+      collector.filter = Proc.new do |test|
+        !/\Atest1/.match(test.method_name).nil?
+      end
+    end
+  end
+
+  def test_collect_multi
+    test_dirs = [@sub_test_dir.to_s, @sub2_test_dir.to_s]
+    assert_collect([:suite, {:name => "[#{test_dirs.join(', ')}]"},
+                    [:suite, {:name => @sub_test_dir.basename.to_s},
+                     [:suite, {:name => _test_case_name("SubTestCase4")},
+                      [:test, {:name => "test4_1"}],
+                      [:test, {:name => "test4_2"}]],
+                     [:suite, {:name => _test_case_name("SubTestCase6")},
+                      [:test, {:name => "test6"}]]],
+                   [:suite, {:name => @sub2_test_dir.basename.to_s},
+                     [:suite, {:name => _test_case_name("Sub2TestCase8")},
+                      [:test, {:name => "test8_1"}],
+                      [:test, {:name => "test8_2"}]],
+                     [:suite, {:name => _test_case_name("Sub2TestCase9")},
+                      [:test, {:name => "test9"}]]]],
+                   *test_dirs)
+  end
+
+  private
+  def assert_collect(expected, *collect_args)
+    keep_required_files do
+      Dir.chdir(@test_dir.to_s) do
+        collector = Test::Unit::Collector::Load.new
+        yield(collector) if block_given?
+        actual = inspect_test_object(collector.send(:collect, *collect_args))
+        assert_equal(expected, actual)
+      end
+    end
+  end
+
+  def keep_required_files
+    required_files = $".dup
+    yield
+  ensure
+    $".replace(required_files)
+  end
+
+  def _test_case_name(test_case_class_name)
+    "#{@temporary_test_cases_module_name}::#{test_case_class_name}"
+  end
+
+  def inspect_test_object(test_object)
+    return nil if test_object.nil?
+    case test_object
+    when Test::Unit::TestSuite
+      sub_tests = test_object.tests.collect do |test|
+        inspect_test_object(test)
+      end.sort_by do |type, attributes, *children|
+        attributes[:name]
+      end
+      [:suite, {:name => test_object.name}, *sub_tests]
+    when Test::Unit::TestCase
+      [:test, {:name => test_object.method_name}]
+    else
+      raise "unexpected test object: #{test_object.inspect}"
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/collector/test_dir.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/collector/test_dir.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/collector/test_dir.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,406 @@
+require 'test/unit'
+require 'test/unit/collector/dir'
+require 'pp'
+
+module Test
+  module Unit
+    module Collector
+      class TestDir < TestCase
+        class FileSystem
+          class Directory
+            def initialize(name, fs, parent=self, &block)
+              @name = name
+              @fs = fs
+              @parent = parent
+              @contents = {'.' => self, '..' => parent}
+              instance_eval(&block) if(block)
+            end
+            
+            def file(name, contents)
+              @contents[name] = contents
+            end
+
+            def dir(name, &block)
+              @contents[name] = self.class.new(name, @fs, self, &block)
+            end
+
+            def entries
+              @contents.keys
+            end
+
+            def directory?(name)
+              return true if(name.nil? || name.empty?)
+              return false unless(@contents.include?(name))
+              @contents[name].kind_of?(self.class)
+            end
+
+            def file?(name)
+              return false unless(@contents.include?(name))
+              !directory?(name)
+            end
+
+            def exist?(name)
+              @contents.include?(name)
+            end
+
+            def [](name)
+              raise Errno::ENOENT, name unless(@contents.include?(name))
+              @contents[name]
+            end
+
+            def path_to(name=nil)
+              if(!name)
+                @parent.path_to(@name)
+              elsif(@parent == self)
+                @fs.join('/', name)
+              else
+                @fs.join(@parent.path_to(@name), name)
+              end
+            end
+          end
+
+          class ObjectSpace
+            def initialize
+              @objects = []
+            end
+
+            def each_object(klass, &block)
+              @objects.find_all{|o| o.kind_of?(klass)}.each(&block)
+            end
+
+            def <<(object)
+              @objects << object
+            end
+          end
+
+          attr_reader :object_space
+          
+          def initialize(&block)
+            @root = Directory.new('/', self, &block)
+            @pwd = @root
+            @object_space = ObjectSpace.new
+            @required = []
+          end
+
+          def entries(dir)
+            e = find(dir)
+            require_directory(dir)
+            e.entries
+          end
+
+          def directory?(name)
+            return true if (base = basename(name)) == '/'
+            e = find(dirname(name))
+            return false unless(e)
+            e.directory?(base)
+          end
+
+          def find(path)
+            if(/\A\// =~ path)
+              thing = @root
+            else
+              thing = @pwd
+            end
+            path.scan(/[^\/]+/) do |e|
+              break thing = false unless(thing.kind_of?(Directory))
+              thing = thing[e]
+            end
+            thing
+          end
+
+          def dirname(name)
+            if (name = name.tr_s('/', '/')) == '/'
+              name
+            else
+              name[%r"\A.+(?=/[^/]+/?\z)|\A/"] || "."
+            end
+          end
+
+          def basename(name)
+            name[%r"(\A/|[^/]+)/*\z", 1]
+          end
+
+          def split(name)
+            [dirname(name), basename(name)]
+          end
+
+          def join(*parts)
+            parts.join('/').gsub(%r{/+}, '/')
+          end
+
+          def file?(name)
+            e = find(dirname(name))
+            return false unless(e)
+            e.file?(basename(name))
+          end
+
+          def pwd
+            @pwd.path_to
+          end
+
+          def chdir(to)
+            e = find(to)
+            require_directory(to)
+            @pwd = e
+          end
+
+          def expand_path(path, base = nil)
+            until /\A\// =~ path
+              base ||= pwd
+              path = join(base, path)
+              base = nil
+            end
+            path.gsub!(%r"(?:/\.)+(?=/)", '')
+            nil while path.sub!(%r"/(?!\.\./)[^/]+/\.\.(?=/)", '')
+            path.sub!(%r"\A(?:/\.\.)+(?=/)", '')
+            path.sub!(%r"(?:\A(/)|/)\.\.?\z", '\1')
+            path
+          end
+
+          def require_directory(path)
+            raise Errno::ENOTDIR, path unless(directory?(path))
+          end
+
+          def require(file)
+            return false if(@required.include?(file))
+            begin
+              e = find(file)
+            rescue Errno::ENOENT => e
+              if(/\.rb\Z/ =~ file)
+                raise LoadError, file
+              end
+              e = find(file + '.rb')
+            end
+            @required << file
+            @object_space << e
+            true
+          rescue Errno::ENOENT
+            raise LoadError, file
+          end
+        end
+
+        def test_dir
+          inner_dir = nil
+          dirs = FileSystem::Directory.new('/', nil) do
+            file 'a', nil
+            inner_dir = dir 'b'
+          end
+          assert_equal(inner_dir, dirs['b'])
+        end
+
+        def test_fs
+          fs = FileSystem.new do
+            file 'a', nil
+            dir 'b'
+          end
+          assert_equal(['.', '..', 'a', 'b'].sort, fs.entries('/').sort)
+          assert(fs.directory?('/'))
+          assert(!fs.directory?('/a'))
+          assert(!fs.directory?('/bogus'))
+          assert(fs.file?('/a'))
+          assert(!fs.file?('/'))
+          assert(!fs.file?('/bogus'))
+          assert(fs.directory?('/b'))
+          assert(fs.file?('a'))
+          assert(fs.directory?('b'))
+        end
+
+        def test_fs_sub
+          fs = FileSystem.new do
+            dir 'a' do
+              file 'b', nil
+              dir 'c' do
+                file 'd', nil
+              end
+            end
+          end
+          assert(fs.file?('/a/b'))
+          assert(!fs.file?('/a/b/c/d'))
+          assert(fs.file?('/a/c/d'))
+        end
+
+        def test_fs_pwd
+          fs = FileSystem.new do
+            file 'a', nil
+            dir 'b' do
+              file 'c', nil
+              dir 'd' do
+                file 'e', nil
+              end
+            end
+          end
+          assert_equal('/', fs.pwd)
+          assert_raises(Errno::ENOENT) do
+            fs.chdir('bogus')
+          end
+          assert_raises(Errno::ENOTDIR) do
+            fs.chdir('a')
+          end
+          fs.chdir('b')
+          assert_equal('/b', fs.pwd)
+          fs.chdir('d')
+          assert_equal('/b/d', fs.pwd)
+          fs.chdir('..')
+          assert_equal('/b', fs.pwd)
+          fs.chdir('..')
+          assert_equal('/', fs.pwd)
+        end
+
+        def test_fs_entries
+          fs = FileSystem.new do
+            file 'a', nil
+            dir 'b' do
+              file 'c', nil
+              file 'd', nil
+            end
+            file 'e', nil
+            dir 'f' do
+              file 'g', nil
+              dir 'h' do
+                file 'i', nil
+              end
+            end
+          end
+          assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('/').sort)
+          assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('.').sort)
+          assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('b/..').sort)
+          assert_equal(['.', '..', 'c', 'd'], fs.entries('b').sort)
+          assert_raises(Errno::ENOENT) do
+            fs.entries('z')
+          end
+          assert_raises(Errno::ENOTDIR) do
+            fs.entries('a')
+          end
+          fs.chdir('f')
+          assert_equal(['.', '..', 'i'], fs.entries('h').sort)
+        end
+
+        class TestClass1
+        end
+        class TestClass2
+        end
+        def test_fs_require
+          fs = FileSystem.new do
+            file 'test_class1.rb', TestClass1
+            dir 'dir' do
+              file 'test_class2.rb', TestClass2
+            end
+          end
+          c = []
+          fs.object_space.each_object(Class) do |o|
+            c << o
+          end
+          assert_equal([], c)
+
+          assert_raises(LoadError) do
+            fs.require('bogus')
+          end
+          
+          assert(fs.require('test_class1.rb'))
+          assert(!fs.require('test_class1.rb'))
+          c = []
+          fs.object_space.each_object(Class) do |o|
+            c << o
+          end
+          assert_equal([TestClass1], c)
+
+          fs.require('dir/test_class2')
+          c = []
+          fs.object_space.each_object(Class) do |o|
+            c << o
+          end
+          assert_equal([TestClass1, TestClass2], c)
+
+          c = []
+          fs.object_space.each_object(Time) do |o|
+            c << o
+          end
+          assert_equal([], c)
+        end
+
+        def setup
+          @t1 = t1 = create_test(1)
+          @t2 = t2 = create_test(2)
+          @t3 = t3 = create_test(3)
+          @t4 = t4 = create_test(4)
+          @t5 = t5 = create_test(5)
+          @t6 = t6 = create_test(6)
+          fs = FileSystem.new do
+            file 'test_1.rb', t1
+            file 'test_2.rb', t2
+            dir 'd1' do
+              file 'test_3.rb', t3
+            end
+            file 't4.rb', t4
+            dir 'd2' do
+              file 'test_5', t5
+              file 'test_6.rb', Time
+            end
+            file 't6.rb', t6
+          end
+          fs.require('t6')
+          @c = Dir.new(fs, fs, fs.object_space, fs)
+        end
+
+        def create_test(name)
+          t = Class.new(TestCase)
+          t.class_eval <<-EOC
+            def self.name
+              "T\#{#{name}}"
+            end
+            def test_#{name}a
+            end
+            def test_#{name}b
+            end
+          EOC
+          t
+        end
+
+        def test_simple_collect
+          expected = TestSuite.new('d1')
+          expected << (@t3.suite)
+          assert_equal(expected, @c.collect('d1'))
+        end
+
+        def test_multilevel_collect
+          expected = TestSuite.new('.')
+          expected << @t1.suite << @t2.suite
+          expected << (TestSuite.new('d1') << @t3.suite)
+          assert_equal(expected, @c.collect)
+        end
+
+        def test_collect_file
+          expected = TestSuite.new('test_1.rb')
+          expected << @t1.suite
+          assert_equal(expected, @c.collect('test_1.rb'))
+          
+          expected = TestSuite.new('t4.rb')
+          expected << @t4.suite
+          assert_equal(expected, @c.collect('t4.rb'))
+        end
+
+        def test_nil_pattern
+          expected = TestSuite.new('d2')
+          expected << @t5.suite
+          @c.pattern.clear
+          assert_equal(expected, @c.collect('d2'))
+        end
+
+        def test_filtering
+          expected = TestSuite.new('.')
+          expected << @t1.suite
+          @c.filter = proc{|t| t.method_name == 'test_1a' || t.method_name == 'test_1b'}
+          assert_equal(expected, @c.collect)
+        end
+
+        def test_collect_multi
+          expected = TestSuite.new('[d1, d2]')
+          expected << (TestSuite.new('d1') << @t3.suite)
+          expected << (TestSuite.new('d2') << @t5.suite)
+          @c.pattern.replace([/\btest_/])
+          assert_equal(expected, @c.collect('d1', 'd2'))
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/collector/test_objectspace.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/collector/test_objectspace.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/collector/test_objectspace.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,98 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/collector/objectspace'
+
+module Test
+  module Unit
+    module Collector
+      class TC_ObjectSpace < TestCase
+        def setup
+          @tc1 = Class.new(TestCase) do
+            def self.name
+              "tc_1"
+            end
+            def test_1
+            end
+            def test_2
+            end
+          end
+
+          @tc2 = Class.new(TestCase) do
+            def self.name
+              "tc_2"
+            end
+            def test_0
+            end
+          end
+
+          @no_tc = Class.new do
+            def test_4
+            end
+          end
+ 
+          @object_space = {Class => [@tc1, @tc2, @no_tc], String => ['']}
+          def @object_space.each_object(type)
+            self[type].each{|item| yield(item) }
+          end
+
+          @c = ObjectSpace.new(@object_space)
+        end
+
+        def full_suite(name=ObjectSpace::NAME)
+          expected = TestSuite.new(name)
+          expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1') << @tc1.new('test_2'))
+          expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
+        end
+
+        def empty_suite
+          TestSuite.new(ObjectSpace::NAME)
+        end
+        
+        def test_basic_collection
+          assert_equal(full_suite("name"), @c.collect("name"))
+
+          @c.filter = []
+          assert_equal(full_suite("name"), @c.collect("name"))
+        end
+        
+        def test_filtered_collection
+          @c.filter = proc{false}
+          assert_equal(empty_suite, @c.collect)
+
+          @c.filter = proc{true}
+          assert_equal(full_suite, @c.collect)
+
+          @c.filter = proc{nil}
+          assert_equal(full_suite, @c.collect)
+
+          @c.filter = [proc{false}, proc{true}]
+          assert_equal(empty_suite, @c.collect)
+
+          @c.filter = [proc{true}, proc{false}]
+          assert_equal(full_suite, @c.collect)
+
+          @c.filter = [proc{nil}, proc{false}]
+          assert_equal(empty_suite, @c.collect)
+          
+          @c.filter = [proc{nil}, proc{true}]
+          assert_equal(full_suite, @c.collect)
+          
+          expected = TestSuite.new(ObjectSpace::NAME)
+          expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1'))
+          expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
+          @c.filter = proc{|test| ['test_1', 'test_0'].include?(test.method_name)}
+          assert_equal(expected, @c.collect)
+
+          expected = TestSuite.new(ObjectSpace::NAME)
+          expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1'))
+          expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
+          @c.filter = [proc{|t| t.method_name == 'test_1' ? true : nil}, proc{|t| t.method_name == 'test_0' ? true : nil}, proc{false}]
+          assert_equal(expected, @c.collect)
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/run-test.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/run-test.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/run-test.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,13 @@
+#!/usr/bin/env ruby
+
+$VERBOSE = true
+
+base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
+lib_dir = File.join(base_dir, "lib")
+test_dir = File.join(base_dir, "test")
+
+$LOAD_PATH.unshift(lib_dir)
+
+require 'test/unit'
+
+exit Test::Unit::AutoRunner.run(true, test_dir)


Property changes on: MacRuby/trunk/test/libs/test-unit/test/run-test.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: MacRuby/trunk/test/libs/test-unit/test/test-attribute.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-attribute.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-attribute.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,86 @@
+class TestUnitAttribute < Test::Unit::TestCase
+  class TestStack < Test::Unit::TestCase
+    class << self
+      def suite
+        Test::Unit::TestSuite.new(name)
+      end
+    end
+
+    class Stack
+      def initialize
+        @data = []
+      end
+
+      def push(data)
+        @data.push(data)
+      end
+
+      def peek
+        @data[-2]
+      end
+
+      def empty?
+        @data.empty?
+      end
+
+      def size
+        @data.size + 11
+      end
+    end
+
+    def setup
+      @stack = Stack.new
+    end
+
+    attribute :category, :accessor
+    def test_peek
+      @stack.push(1)
+      @stack.push(2)
+      assert_equal(2, @stack.peek)
+    end
+
+    attribute :bug, 1234
+    def test_bug_1234
+      assert_equal(0, @stack.size)
+    end
+
+    def test_no_attributes
+      assert(@stack.empty?)
+      @stack.push(1)
+      assert(!@stack.empty?)
+      assert_equal(1, @stack.size)
+    end
+  end
+
+  def test_set_attributes
+    test_for_accessor_category = TestStack.new("test_peek")
+    assert_equal({"category" => :accessor},
+                 test_for_accessor_category.attributes)
+
+    test_for_bug_1234 = TestStack.new("test_bug_1234")
+    assert_equal({"bug" => 1234}, test_for_bug_1234.attributes)
+
+    test_no_attributes = TestStack.new("test_no_attributes")
+    assert_equal({}, test_no_attributes.attributes)
+  end
+
+  def test_callback
+    changed_attributes = []
+    observer = Proc.new do |test_case, key, old_value, value, method_name|
+      changed_attributes << [test_case, key, old_value, value, method_name]
+    end
+
+    test_case = Class.new(TestStack) do
+      register_attribute_observer(:bug, &observer)
+      attribute("bug", 9876, "test_bug_1234")
+      attribute(:description, "Test for peek", "test_peek")
+      attribute(:bug, 29, "test_peek")
+    end
+
+    assert_equal([
+                  [test_case, "bug", 1234, 9876, "test_bug_1234"],
+                  [test_case, "bug", nil, 29, "test_peek"],
+                 ],
+                 changed_attributes)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-color-scheme.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-color-scheme.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-color-scheme.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,60 @@
+class TestUnitColorScheme < Test::Unit::TestCase
+  def test_default
+    assert_equal({
+                   "success" => color("green", :bold => true),
+                   "failure" => color("red", :bold => true),
+                   "pending" => color("magenta", :bold => true),
+                   "omission" => color("blue", :bold => true),
+                   "notification" => color("cyan", :bold => true),
+                   "error" => color("yellow", :bold => true) +
+                              color("black", :foreground => false),
+                   "case" => color("white", :bold => true) +
+                             color("blue", :foreground => false),
+                   "suite" => color("white", :bold => true) +
+                              color("green", :foreground => false),
+                 },
+                 Test::Unit::ColorScheme.default.to_hash)
+  end
+
+  def test_register
+    inverted_scheme_spec = {
+      "success" => {:name => "red"},
+      "failure" => {:name => "green"},
+    }
+    Test::Unit::ColorScheme["inverted"] = inverted_scheme_spec
+    assert_equal({
+                   "success" => color("red"),
+                   "failure" => color("green"),
+                 },
+                 Test::Unit::ColorScheme["inverted"].to_hash)
+  end
+
+  def test_new_with_colors
+    scheme = Test::Unit::ColorScheme.new(:success => color("blue"),
+                                         "failure" => color("green",
+                                                            :underline => true))
+    assert_equal({
+                   "success" => color("blue"),
+                   "failure" => color("green", :underline => true),
+                 },
+                 scheme.to_hash)
+  end
+
+  def test_new_with_spec
+    scheme = Test::Unit::ColorScheme.new(:success => {
+                                           :name => "blue",
+                                           :bold => true
+                                         },
+                                         "failure" => {:name => "green"})
+    assert_equal({
+                   "success" => color("blue", :bold => true),
+                   "failure" => color("green"),
+                 },
+                 scheme.to_hash)
+  end
+
+  private
+  def color(name, options={})
+    Test::Unit::Color.new(name, options)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-color.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-color.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-color.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,47 @@
+class TestUnitColor < Test::Unit::TestCase
+  def test_color_escape_sequence
+    assert_escape_sequence(["31"], color("red"))
+    assert_escape_sequence(["32", "1"], color("green", :bold => true))
+    assert_escape_sequence(["0"], color("reset"))
+    assert_escape_sequence(["45"], color("magenta", :foreground => false))
+  end
+
+  def test_mix_color_escape_sequence
+    assert_escape_sequence(["34", "1"],
+                           mix_color([color("blue"),
+                                      color("none", :bold => true)]))
+    assert_escape_sequence(["34", "1", "4"],
+                           mix_color([color("blue"),
+                                      color("none", :bold => true)]) +
+                           color("none", :underline => true))
+    assert_escape_sequence(["34", "1", "4"],
+                           color("blue") +
+                           color("none", :bold => true) +
+                           color("none", :underline => true))
+  end
+
+  def test_equal
+    red = color("red")
+    red_bold = color("red", :bold => true)
+
+    assert_operator(red, :==, red)
+    assert_not_equal(red, nil)
+    assert_equal(red, color("red"))
+    assert_not_equal(red, red_bold)
+  end
+
+  private
+  def color(name, options={})
+    Test::Unit::Color.new(name, options)
+  end
+
+  def mix_color(colors)
+    Test::Unit::MixColor.new(colors)
+  end
+
+  def assert_escape_sequence(expected, color)
+    assert_equal(expected, color.sequence)
+    assert_match(/\e\[(?:\d+;)*\d+m/, color.escape_sequence)
+    assert_equal(expected, color.escape_sequence[2..-2].split(";"))
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-diff.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-diff.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-diff.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,477 @@
+class TestUnitDiff < Test::Unit::TestCase
+  def test_to_indexes
+    assert_to_indexes({"abc def" => [0, 2], "abc" => [1]},
+                      ["abc def", "abc", "abc def"])
+
+    assert_to_indexes({?a => [0, 3], ?b => [1], ?c => [2], ?d => [4]},
+                      "abcad")
+
+    assert_to_indexes({
+                        ?1 => [0, 35],
+                        ?t => [2, 5, 16],
+                        ?e => [3, 14, 31, 38],
+                        ?s => [4, 6, 12, 13, 20, 32, 44],
+                        ?, => [7, 21, 33],
+                        ?0 => [9, 23],
+                        ?a => [11, 26],
+                        ?r => [15, 30],
+                        ?i => [17, 27, 41],
+                        ?o => [18],
+                        ?n => [19, 39, 42],
+                        ?f => [25],
+                        ?l => [28],
+                        ?u => [29],
+                        ?p => [37],
+                        ?d => [40],
+                        ?g => [43],
+                      },
+                      "1 tests, 0 assertions, 0 failures, 1 pendings") do |x|
+      x == " "[0]
+    end
+  end
+
+  def test_longest_match
+    assert_longest_match([0, 1, 3],
+                         %w(b c d), %w(a b c d x y z),
+                         0, 2, 0, 7)
+    assert_longest_match([1, 2, 2],
+                         %w(b c d), %w(a b c d x y z),
+                         1, 2, 0, 6)
+    assert_longest_match([0, 0, 0],
+                         %w(a b), %w(c),
+                         0, 1, 0, 0)
+    assert_longest_match([1, 0, 2],
+                         %w(q a b x c d), %w(a b y c d f),
+                         0, 5, 0, 5)
+    assert_longest_match([4, 3, 2],
+                         %w(q a b x c d), %w(a b y c d f),
+                         3, 5, 2, 5)
+
+    assert_longest_match([1, 0, 2], "qabxcd", "abycdf", 0, 5, 0, 5)
+    assert_longest_match([0, 0, 1], "efg", "eg", 0, 2, 0, 1)
+    assert_longest_match([2, 1, 1], "efg", "eg", 1, 2, 1, 1)
+  end
+
+  def test_longest_match_with_junk_predicate
+    assert_longest_match([0, 4, 5], " abcd", "abcd abcd", 0, 4, 0, 8)
+    assert_longest_match([1, 0, 4], " abcd", "abcd abcd", 0, 4, 0, 8) do |x|
+      x == ' '[0]
+    end
+  end
+
+  def test_matches
+    assert_matches([[0, 0, 2],
+                    [3, 2, 2]],
+                   %w(a b x c d), %w(a b c d))
+    assert_matches([[1, 0, 2],
+                    [4, 3, 2]],
+                   %w(q a b x c d), %w(a b y c d f))
+
+    assert_matches([[1, 0, 2],
+                    [4, 3, 2]],
+                   "qabxcd", "abycdf")
+    assert_matches([[0, 0, 1],
+                    [2, 1, 1]],
+                   "efg", "eg")
+  end
+
+  def test_matches_with_junk_predicate
+    assert_matches([[0, 0, 23],
+                    [24, 24, 11],
+                    [36, 36, 9]],
+                  "1 tests, 0 assertions, 1 failures, 0 pendings",
+                  "1 tests, 0 assertions, 0 failures, 1 pendings")
+
+    assert_matches([[0, 0, 1],
+                    [1, 1, 8],
+                    [9, 9, 1],
+                    [10, 10, 13],
+                    [24, 24, 11],
+                    [36, 36, 9]],
+                  "1 tests, 0 assertions, 1 failures, 0 pendings",
+                  "1 tests, 0 assertions, 0 failures, 1 pendings") do |x|
+      x == " "[0]
+    end
+  end
+
+  def test_blocks
+    assert_blocks([[0, 0, 2],
+                   [3, 2, 2],
+                   [5, 4, 0]],
+                  %w(a b x c d), %w(a b c d))
+    assert_blocks([[1, 0, 2],
+                   [4, 3, 2],
+                   [6, 6, 0]],
+                  %w(q a b x c d), %w(a b y c d f))
+
+    assert_blocks([[1, 0, 2],
+                   [4, 3, 2],
+                   [6, 6, 0]],
+                  "qabxcd", "abycdf")
+    assert_blocks([[0, 0, 1],
+                   [2, 1, 1],
+                   [3, 2, 0]],
+                  "efg", "eg")
+  end
+
+  def test_blocks_with_junk_predicate
+    assert_blocks([[0, 0, 23],
+                   [24, 24, 11],
+                   [36, 36, 9],
+                   [45, 45, 0]],
+                  "1 tests, 0 assertions, 1 failures, 0 pendings",
+                  "1 tests, 0 assertions, 0 failures, 1 pendings") do |x|
+      x == " "[0]
+    end
+  end
+
+  def test_operations
+    assert_operations([], %w(), %w())
+
+    assert_operations([[:delete, 0, 1, 0, 0],
+                       [:equal, 1, 3, 0, 2],
+                       [:replace, 3, 4, 2, 3],
+                       [:equal, 4, 6, 3, 5],
+                       [:insert, 6, 6, 5, 6]],
+                      %w(q a b x c d), %w(a b y c d f))
+
+    assert_operations([[:delete, 0, 1, 0, 0],
+                       [:equal, 1, 3, 0, 2],
+                       [:replace, 3, 4, 2, 3],
+                       [:equal, 4, 6, 3, 5],
+                       [:insert, 6, 6, 5, 6]],
+                      "qabxcd", "abycdf")
+
+    assert_operations([[:equal, 0, 23, 0, 23],
+                       [:replace, 23, 24, 23, 24],
+                       [:equal, 24, 35, 24, 35],
+                       [:replace, 35, 36, 35, 36],
+                       [:equal, 36, 45, 36, 45]],
+                      "1 tests, 0 assertions, 1 failures, 0 pendings",
+                      "1 tests, 0 assertions, 0 failures, 1 pendings")
+
+    assert_operations([[:equal, 0, 23, 0, 23],
+                       [:replace, 23, 24, 23, 24],
+                       [:equal, 24, 35, 24, 35],
+                       [:replace, 35, 36, 35, 36],
+                       [:equal, 36, 45, 36, 45]],
+                      "1 tests, 0 assertions, 1 failures, 0 pendings",
+                      "1 tests, 0 assertions, 0 failures, 1 pendings") do |x|
+      x == " "[0]
+    end
+  end
+
+  def test_grouped_operations
+    assert_grouped_operations([[[:equal, 0, 0, 0, 0]]],
+                              %w(),
+                              %w())
+
+    assert_grouped_operations([[[:equal, 0, 3, 0, 3]]],
+                              %w(a b c),
+                              %w(a b c))
+
+    assert_grouped_operations([[[:equal, 0, 1, 0, 1],
+                                [:replace, 1, 2, 1, 2],
+                                [:equal, 2, 5, 2, 5]],
+                               [[:equal, 8, 11, 8, 11],
+                                [:replace, 11, 12, 11, 12],
+                                [:equal, 12, 13, 12, 13],
+                                [:delete, 13, 16, 13, 13],
+                                [:equal, 16, 17, 13, 14],
+                                [:replace, 17, 18, 14, 15],
+                                [:equal, 18, 20, 15, 17]]],
+                              %w(1 2 3 4 5 6 7 8 9 a b c d e f g h i j k),
+                              %w(1 i 3 4 5 6 7 8 9 a b cX d h iX j k))
+  end
+
+  def test_ratio
+    assert_ratio(0.75, "abcd", "bcde")
+    assert_ratio(0.80, "efg", "eg")
+  end
+
+  def test_same_contents_readable_diff
+    assert_readable_diff("  aaa", ["aaa"], ["aaa"])
+    assert_readable_diff("  aaa\n" \
+                         "  bbb",
+                         ["aaa", "bbb"], ["aaa", "bbb"])
+  end
+
+  def test_deleted_readable_diff
+    assert_readable_diff("  aaa\n" \
+                         "- bbb",
+                         ["aaa", "bbb"], ["aaa"])
+    assert_readable_diff("  aaa\n" \
+                         "- bbb\n" \
+                         "- ccc\n" \
+                         "- ddd",
+                         ["aaa", "bbb", "ccc", "ddd"], ["aaa"])
+  end
+
+  def test_inserted_readable_diff
+    assert_readable_diff("  aaa\n" \
+                         "+ bbb\n" \
+                         "+ ccc\n" \
+                         "+ ddd",
+                         ["aaa"], ["aaa", "bbb", "ccc", "ddd"])
+  end
+
+  def test_replace_readable_diff
+    assert_readable_diff("  aaa\n" \
+                         "- bbb\n" \
+                         "+ BbB\n" \
+                         "  ccc\n" \
+                         "- ddd\n" \
+                         "- efg\n" \
+                         "?  -\n" \
+                         "+ eg",
+                         ["aaa", "bbb", "ccc", "ddd", "efg"],
+                         ["aaa", "BbB", "ccc", "eg"])
+
+    assert_readable_diff("-  abcd xyz abc\n" \
+                         "? -\n" \
+                         "+ abcd abcd xyz abc\n" \
+                         "?      +++++",
+                         [" abcd xyz abc"],
+                         ["abcd abcd xyz abc"])
+  end
+
+  def test_difference_readable_diff
+    assert_readable_diff("- 1 tests, 0 assertions, 1 failures, 0 pendings\n" \
+                         "?                        ^           ^\n" \
+                         "+ 1 tests, 0 assertions, 0 failures, 1 pendings\n" \
+                         "?                        ^           ^",
+                         ["1 tests, 0 assertions, 1 failures, 0 pendings"],
+                         ["1 tests, 0 assertions, 0 failures, 1 pendings"])
+  end
+
+  def test_complex_readable_diff
+    assert_readable_diff("  aaa\n" \
+                         "- bbb\n" \
+                         "- ccc\n" \
+                         "+ \n" \
+                         "+   # \n" \
+                         "  ddd",
+                         ["aaa", "bbb", "ccc", "ddd"],
+                         ["aaa", "", "  # ", "ddd"])
+
+    assert_readable_diff("- one1\n" \
+                         "?  ^\n" \
+                         "+ ore1\n" \
+                         "?  ^\n" \
+                         "- two2\n" \
+                         "- three3\n" \
+                         "?  -   -\n" \
+                         "+ tree\n" \
+                         "+ emu",
+                         ["one1", "two2", "three3"],
+                         ["ore1", "tree", "emu"])
+  end
+
+  def test_empty_readable_diff
+    assert_readable_diff("", [""], [""])
+  end
+
+  def test_unified_diff
+    assert_unified_diff("",
+                        ["one", "two", "three"],
+                        ["one", "two", "three"],
+                        "content 1",
+                        "content 2")
+
+    assert_unified_diff("--- Original Sat Jan 26 23:30:50 1991\n" \
+                        "+++ Current Fri Jun 06 10:20:52 2003\n" \
+                        "@@ -1,4 +1,4 @@\n" \
+                        "+zero\n" \
+                        " one\n" \
+                        "-two\n" \
+                        "-three\n" \
+                        "+tree\n" \
+                        " four",
+                        ["one", "two", "three", "four"],
+                        ["zero", "one", "tree", "four"],
+                        "Original Sat Jan 26 23:30:50 1991",
+                        "Current Fri Jun 06 10:20:52 2003",
+                        :show_context => false)
+
+    from = File.read(__FILE__).split(/\n/)
+    to = from.dup
+    target_line = __LINE__
+    to[target_line - 1, 1] = []
+    context = "  def test_unified_diff"
+    summary = "@@ -#{target_line - 3},7 +#{target_line - 3},6 @@ #{context}"
+    assert_unified_diff((["--- revision 10",
+                          "+++ revision 11",
+                          summary] +
+                         from[target_line - 4, 3].collect {|line| " #{line}"} +
+                         ["-#{from[target_line - 1]}"] +
+                         from[target_line, 3].collect {|line| " #{line}"}
+                         ).join("\n"),
+                        from, to,
+                        "revision 10",
+                        "revision 11")
+  end
+
+  def test_empty_unified_diff
+    assert_unified_diff("", [""], [""], "From", "To")
+    assert_unified_diff("", [], [], "From", "To")
+  end
+
+  def test_diff_lines
+    assert_diff_lines(["- ddd",
+                       "- efg",
+                       "?  -",
+                       "+ eg"],
+                      ["aaa", "bbb", "ccc", "ddd", "efg"],
+                      ["aaa", "BbB", "ccc", "eg"],
+                      3, 5, 3, 4)
+  end
+
+  def test_diff_line
+    assert_diff_line(["- abcDefghiJkl",
+                      "?    ^  ^  ^",
+                      "+ abcdefGhijkl",
+                      "?    ^  ^  ^"],
+                     "abcDefghiJkl",
+                     "abcdefGhijkl")
+
+    assert_diff_line(["- bcDefghiJklx",
+                      "?   ^  ^  ^  -",
+                      "+ abcdefGhijkl",
+                      "? +  ^  ^  ^"],
+                     "bcDefghiJklx",
+                     "abcdefGhijkl")
+  end
+
+  def test_empty_diff_line
+    assert_diff_line(["- ",
+                      "+ "],
+                     "", "")
+  end
+
+  def test_format_diff_point
+    assert_format_diff_point(["- \tabcDefghiJkl",
+                              "? \t ^ ^  ^",
+                              "+ \t\tabcdefGhijkl",
+                              "? \t  ^ ^  ^"],
+                             "\tabcDefghiJkl",
+                             "\t\tabcdefGhijkl",
+                             "  ^ ^  ^      ",
+                             "+  ^ ^  ^      ")
+    assert_format_diff_point(["- efg",
+                              "?  ^",
+                              "+ eg"],
+                             "efg",
+                             "eg",
+                             " ^",
+                             "")
+  end
+
+  def test_interesting_line
+    from = ["class X",
+            "  def find(x=0)",
+            "    body",
+            "  end",
+            "end"]
+    to = ["def xxx",
+          "  raise 'not call me'",
+          "end"]
+    assert_interesting_line("  def find(x=0)",
+                            from, to,
+                            2, 1)
+    assert_interesting_line("def xxx",
+                            from, to,
+                            2, 0)
+    assert_interesting_line("class X",
+                            from, to,
+                            0, 0)
+  end
+
+  private
+  def assert_to_indexes(expected, to, &junk_predicate)
+    matcher = Test::Unit::Diff::SequenceMatcher.new([""], to, &junk_predicate)
+    assert_equal(expected, matcher.instance_variable_get("@to_indexes"))
+  end
+
+  def assert_find_best_match_position(expected, from, to,
+                                      from_start, from_end,
+                                      to_start, to_end, &junk_predicate)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate)
+    assert_equal(expected, matcher.send(:find_best_match_position,
+                                        from_start, from_end,
+                                        to_start, to_end))
+  end
+
+  def assert_longest_match(expected, from, to,
+                           from_start, from_end,
+                           to_start, to_end, &junk_predicate)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate)
+    assert_equal(expected, matcher.longest_match(from_start, from_end,
+                                                 to_start, to_end))
+  end
+
+  def assert_matches(expected, from, to, &junk_predicate)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate)
+    assert_equal(expected, matcher.send(:matches))
+  end
+
+  def assert_blocks(expected, from, to, &junk_predicate)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate)
+    assert_equal(expected, matcher.blocks)
+  end
+
+  def assert_operations(expected, from, to, &junk_predicate)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate)
+    assert_equal(expected, matcher.operations)
+  end
+
+  def assert_grouped_operations(expected, from, to)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to)
+    assert_equal(expected, matcher.grouped_operations)
+  end
+
+  def assert_ratio(expected, from, to)
+    matcher = Test::Unit::Diff::SequenceMatcher.new(from, to)
+    assert_in_delta(expected, 0.001, matcher.ratio)
+  end
+
+  def assert_readable_diff(expected, from, to)
+    assert_equal(expected,
+                 Test::Unit::Diff.readable(from.join("\n"), to.join("\n")))
+  end
+
+  def assert_unified_diff(expected, from, to, from_label, to_label, options={})
+    options = options.merge(:from_label => from_label,
+                            :to_label => to_label)
+    assert_equal(expected,
+                 Test::Unit::Diff.unified(from.join("\n"), to.join("\n"),
+                                          options))
+  end
+
+  def assert_diff_lines(expected, from, to,
+                        from_start, from_end,
+                        to_start, to_end)
+    differ = Test::Unit::Diff::ReadableDiffer.new(from, to)
+    assert_equal(expected, differ.send(:diff_lines,
+                                       from_start, from_end,
+                                       to_start, to_end))
+  end
+
+  def assert_diff_line(expected, from_line, to_line)
+    differ = Test::Unit::Diff::ReadableDiffer.new([""], [""])
+    assert_equal(expected, differ.send(:diff_line, from_line, to_line))
+  end
+
+  def assert_format_diff_point(expected, from_line, to_line, from_tags, to_tags)
+    differ = Test::Unit::Diff::ReadableDiffer.new([""], [""])
+    assert_equal(expected, differ.send(:format_diff_point,
+                                       from_line, to_line,
+                                       from_tags, to_tags))
+  end
+
+  def assert_interesting_line(expected, from, to, from_start, to_start)
+    differ = Test::Unit::Diff::UnifiedDiffer.new(from, to)
+    assert_equal(expected, differ.send(:find_interesting_line,
+                                       from_start, to_start,
+                                       :define_line?))
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-emacs-runner.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-emacs-runner.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-emacs-runner.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,60 @@
+require 'test/unit'
+require 'test/unit/ui/emacs/testrunner'
+
+class TestUnitEmacsRunner < Test::Unit::TestCase
+  def test_format_failure_with_a_location
+    runner = create_runner
+    test_name = "test_failure"
+    file = "/home/user/test_xxx.rb"
+    line = "3"
+    info = "in `xxx'"
+    location = "#{file}:#{line}: #{info}"
+    message = "FAIL!!!"
+    failure = Test::Unit::Failure.new(test_name, [location], message)
+    assert_equal(<<-EOM.chomp, runner.send(:format_fault, failure))
+Failure:
+#{test_name} [#{file}:#{line}]:
+#{message}
+EOM
+  end
+
+  def test_format_failure_with_locations
+    runner = create_runner
+    test_name = "test_failure"
+    locations = ["/home/user/test_xxx.rb:3: in `xxx'",
+                 "/home/user/yyy/test_yyy.rb:999: in `yyy'",
+                 "/home/user/xyz/zzz.rb:29: in `zzz'"]
+    message = "Many backtrace!!!"
+    failure = Test::Unit::Failure.new(test_name, locations, message)
+    assert_equal(<<-EOM.chomp, runner.send(:format_fault, failure))
+Failure:
+#{test_name}
+#{locations.join("\n")}:
+#{message}
+EOM
+  end
+
+  def test_format_error
+    runner = create_runner
+    test_name = "test_error"
+    message = "Error Message!!!"
+    backtrace = ["/home/user/test_xxx.rb:3: in `xxx'",
+                 "/home/user/yyy/test_yyy.rb:999: in `yyy'",
+                 "/home/user/xyz/zzz.rb:29: in `zzz'"]
+    exception = RuntimeError.new(message)
+    exception.set_backtrace(backtrace)
+    error = Test::Unit::Error.new(test_name, exception)
+    assert_equal(<<-EOM.chomp, runner.send(:format_fault, error))
+Error:
+#{test_name}:
+#{exception.class.name}: #{message}
+#{backtrace.join("\n")}
+EOM
+  end
+
+  private
+  def create_runner(suite=nil)
+    suite ||= Test::Unit::TestSuite.new
+    Test::Unit::UI::Emacs::TestRunner.new(suite)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-fixture.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-fixture.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-fixture.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,287 @@
+class TestUnitFixture < Test::Unit::TestCase
+  module EmptyModule
+  end
+
+  def test_setup_without_option
+    expected_setup_calls = [:setup,
+                            :custom_setup_method0,
+                            :custom_setup_method1,
+                            :custom_setup_method3]
+    test_case = assert_setup(expected_setup_calls, [])
+    assert_inherited_setup(expected_setup_calls, test_case)
+
+    assert_inherited_setup([:setup], nil)
+    assert_called_fixtures(expected_setup_calls, test_case)
+  end
+
+  def test_setup_with_before_option
+    expected_setup_calls = [:custom_setup_method3,
+                            :custom_setup_method0,
+                            :custom_setup_method1,
+                            :setup]
+    test_case = assert_setup(expected_setup_calls,
+                             [[{:before => :append}],
+                              [{:before => :append}],
+                              [{:before => :prepend}],
+                              [{:before => :prepend}]])
+    assert_inherited_setup(expected_setup_calls, test_case)
+
+    assert_inherited_setup([:setup], nil)
+    assert_called_fixtures(expected_setup_calls, test_case)
+  end
+
+  def test_setup_with_after_option
+    expected_setup_calls = [:setup,
+                            :custom_setup_method3,
+                            :custom_setup_method0,
+                            :custom_setup_method1]
+    test_case = assert_setup(expected_setup_calls,
+                             [[{:after => :append}],
+                              [{:after => :append}],
+                              [{:after => :prepend}],
+                              [{:after => :prepend}]])
+    assert_inherited_setup(expected_setup_calls, test_case)
+
+    assert_inherited_setup([:setup], nil)
+    assert_called_fixtures(expected_setup_calls, test_case)
+  end
+
+  def test_setup_with_invalid_option
+    assert_invalid_setup_option(:unknown => true)
+    assert_invalid_setup_option(:before => :unknown)
+    assert_invalid_setup_option(:after => :unknown)
+  end
+
+  def test_setup_with_option_to_inherited
+    expected_setup_calls = [:setup]
+    test_case = assert_setup(expected_setup_calls, nil)
+    assert_inherited_setup([:setup,
+                            :custom_setup_method0,
+                            :custom_setup_method1,
+                            :custom_setup_method3],
+                           test_case,
+                           [])
+
+    assert_inherited_setup([:setup], nil)
+    assert_called_fixtures(expected_setup_calls, test_case)
+  end
+
+  def test_teardown_without_option
+    expected_teardown_calls = [:custom_teardown_method3,
+                               :custom_teardown_method1,
+                               :custom_teardown_method0,
+                               :teardown]
+    test_case = assert_teardown(expected_teardown_calls, [])
+    assert_inherited_teardown(expected_teardown_calls, test_case)
+
+    assert_inherited_teardown([:teardown], nil)
+    assert_called_fixtures(expected_teardown_calls, test_case)
+  end
+
+  def test_teardown_with_before_option
+    expected_teardown_calls = [:custom_teardown_method3,
+                               :custom_teardown_method0,
+                               :custom_teardown_method1,
+                               :teardown]
+    test_case = assert_teardown(expected_teardown_calls,
+                                [[{:before => :append}],
+                                 [{:before => :append}],
+                                 [{:before => :prepend}],
+                                 [{:before => :prepend}]])
+    assert_inherited_teardown(expected_teardown_calls, test_case)
+
+    assert_inherited_teardown([:teardown], nil)
+    assert_called_fixtures(expected_teardown_calls, test_case)
+  end
+
+  def test_teardown_with_after_option
+    expected_teardown_calls = [:teardown,
+                               :custom_teardown_method3,
+                               :custom_teardown_method0,
+                               :custom_teardown_method1]
+    test_case = assert_teardown(expected_teardown_calls,
+                                [[{:after => :append}],
+                                 [{:after => :append}],
+                                 [{:after => :prepend}],
+                                 [{:after => :prepend}]])
+    assert_inherited_teardown(expected_teardown_calls, test_case)
+
+    assert_inherited_teardown([:teardown], nil)
+    assert_called_fixtures(expected_teardown_calls, test_case)
+  end
+
+  def test_teardown_with_invalid_option
+    assert_invalid_teardown_option(:unknown => true)
+    assert_invalid_teardown_option(:before => :unknown)
+    assert_invalid_teardown_option(:after => :unknown)
+  end
+
+  def test_teardown_with_option_to_inherited
+    expected_teardown_calls = [:teardown]
+    test_case = assert_teardown(expected_teardown_calls, nil)
+    assert_inherited_teardown([:custom_teardown_method3,
+                               :custom_teardown_method1,
+                               :custom_teardown_method0,
+                               :teardown],
+                              test_case, [])
+
+    assert_inherited_teardown([:teardown], nil)
+    assert_called_fixtures(expected_teardown_calls, test_case)
+  end
+
+  private
+  def assert_called_fixtures(expected, test_case)
+    test = test_case.new("test_nothing")
+    test.run(Test::Unit::TestResult.new) {}
+    assert_equal(expected, test.called_ids)
+  end
+
+  def assert_setup_customizable(expected, parent, options)
+    test_case = Class.new(parent || Test::Unit::TestCase) do
+      yield(self, :before) if block_given?
+
+      def called_ids
+        @called_ids ||= []
+      end
+
+      def called(id)
+        called_ids << id
+      end
+
+      def setup
+        called(:setup)
+      end
+
+      setup(*(options[0] || [])) if options
+      def custom_setup_method0
+        called(:custom_setup_method0)
+      end
+
+      def custom_setup_method1
+        called(:custom_setup_method1)
+      end
+      setup(*[:custom_setup_method1, *(options[1] || [])]) if options
+
+      setup(*(options[2] || [])) if options
+      def custom_setup_method2
+        called(:custom_setup_method2)
+      end
+      unregister_setup(:custom_setup_method2) if options
+
+      setup(*(options[3] || [])) if options
+      def custom_setup_method3
+        called(:custom_setup_method3)
+      end
+
+      def test_nothing
+      end
+
+      yield(self, :after) if block_given?
+    end
+
+    assert_called_fixtures(expected, test_case)
+    test_case
+  end
+
+  def assert_setup(expected, options)
+    _test_case = assert_setup_customizable(expected, nil, options)
+    assert_setup_customizable(expected, nil, options) do |test_case, tag|
+      test_case.send(:include, EmptyModule) if tag == :before
+    end
+    _test_case
+  end
+
+  def assert_inherited_setup(expected, parent, options=nil)
+    _test_case = assert_setup_customizable(expected, parent, options)
+    assert_setup_customizable(expected, parent, options) do |test_case, tag|
+      test_case.send(:include, EmptyModule) if tag == :before
+    end
+    _test_case
+  end
+
+  def assert_teardown_customizable(expected, parent, options)
+    test_case = Class.new(parent || Test::Unit::TestCase) do
+      yield(self, :before) if block_given?
+
+      def called_ids
+        @called_ids ||= []
+      end
+
+      def called(id)
+        called_ids << id
+      end
+
+      def teardown
+        called(:teardown)
+      end
+
+      teardown(*(options[0] || [])) if options
+      def custom_teardown_method0
+        called(:custom_teardown_method0)
+      end
+
+      def custom_teardown_method1
+        called(:custom_teardown_method1)
+      end
+      teardown(*[:custom_teardown_method1, *(options[1] || [])]) if options
+
+      teardown(*(options[2] || [])) if options
+      def custom_teardown_method2
+        called(:custom_teardown_method2)
+      end
+      unregister_teardown(:custom_teardown_method2) if options
+
+      teardown(*(options[3] || [])) if options
+      def custom_teardown_method3
+        called(:custom_teardown_method3)
+      end
+
+      def test_nothing
+      end
+
+      yield(self, :after) if block_given?
+    end
+
+    assert_called_fixtures(expected, test_case)
+    test_case
+  end
+
+  def assert_teardown(expected, options)
+    assert_teardown_customizable(expected, nil, options)
+    assert_teardown_customizable(expected, nil, options) do |test_case, tag|
+      test_case.send(:include, EmptyModule) if tag == :before
+    end
+  end
+
+  def assert_inherited_teardown(expected, parent, options=nil)
+    assert_teardown_customizable(expected, parent, options)
+    assert_teardown_customizable(expected, parent, options) do |test_case, tag|
+      test_case.send(:include, EmptyModule) if tag == :before
+    end
+  end
+
+  def assert_invalid_option(fixture_type, option)
+    exception = assert_raise(ArgumentError) do
+      Class.new(Test::Unit::TestCase) do
+        def test_nothing
+        end
+
+        send(fixture_type, option)
+        def fixture
+        end
+      end
+    end
+    assert_equal("must be {:before => :prepend}, {:before => :append}, " +
+                 "{:after => :prepend} or {:after => :append}" +
+                 ": #{option.inspect}",
+                 exception.message)
+  end
+
+  def assert_invalid_setup_option(option)
+    assert_invalid_option(:setup, option)
+  end
+
+  def assert_invalid_teardown_option(option)
+    assert_invalid_option(:teardown, option)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-notification.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-notification.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-notification.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,33 @@
+require 'test/unit'
+require 'testunit-test-util'
+
+class TestUnitNotification < Test::Unit::TestCase
+  include TestUnitTestUtil
+
+  class TestCase < Test::Unit::TestCase
+    class << self
+      def suite
+        Test::Unit::TestSuite.new(name)
+      end
+    end
+
+    def test_notify
+      notify("1st notify")
+      notify("2nd notify. Reach here.")
+    end
+  end
+
+  def test_notify
+    result = _run_test("test_notify")
+    assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \
+                 "0 omissions, 2 notifications",
+                 result.to_s)
+    assert_fault_messages(["1st notify", "2nd notify. Reach here."],
+                          result.notifications)
+  end
+
+  private
+  def _run_test(name)
+    super(TestCase, name)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-omission.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-omission.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-omission.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,81 @@
+require 'test/unit'
+require 'testunit-test-util'
+
+class TestUnitOmission < Test::Unit::TestCase
+  include TestUnitTestUtil
+
+  class TestCase < Test::Unit::TestCase
+    class << self
+      def suite
+        Test::Unit::TestSuite.new(name)
+      end
+    end
+
+    def test_omit
+      omit("1st omit")
+      omit("2nd omit. Should not be reached here.")
+      assert(true, "Should not be reached here too.")
+    end
+
+    def test_omit_with_condition
+      omit_if(false, "Never omit.")
+      omit_unless(true, "Never omit too.")
+      omit_if(true, "Should omit.")
+      omit("The last omit. Should not be reached here.")
+    end
+
+    def test_omit_with_block
+      omit("Omit block") do
+        flunk("Should not be reached here.")
+      end
+      assert(true, "Should be reached here.")
+    end
+
+    def test_omit_with_block_and_condition
+      omit_if(false, "Never omit.") do
+        assert(true, "Should be reached here.")
+      end
+      omit_if(true, "Should omit.") do
+        flunk("Never reached here.")
+      end
+      assert(true, "Should be reached here too.")
+    end
+  end
+
+  def test_omit
+    result = _run_test("test_omit")
+    assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \
+                 "1 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["1st omit"], result.omissions)
+  end
+
+  def test_omit_with_condition
+    result = _run_test("test_omit_with_condition")
+    assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \
+                 "1 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["Should omit."], result.omissions)
+  end
+
+  def test_omit_with_block
+    result = _run_test("test_omit_with_block")
+    assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, " \
+                 "1 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["Omit block"], result.omissions)
+  end
+
+  def test_omit_with_condition_and_block
+    result = _run_test("test_omit_with_block_and_condition")
+    assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, " \
+                 "1 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["Should omit."], result.omissions)
+  end
+
+  private
+  def _run_test(name)
+    super(TestCase, name)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-pending.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-pending.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-pending.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,70 @@
+require 'test/unit'
+require 'testunit-test-util'
+
+class TestUnitPending < Test::Unit::TestCase
+  include TestUnitTestUtil
+
+  class TestCase < Test::Unit::TestCase
+    class << self
+      def suite
+        Test::Unit::TestSuite.new(name)
+      end
+    end
+
+    def test_pend
+      pend("1st pend")
+      pend("2nd pend. Should not be reached here.")
+      assert(true, "Should not be reached here too.")
+    end
+
+    def test_pend_with_failure_in_block
+      pend("Wait a minute") do
+        raise "Not implemented yet"
+      end
+      assert(true, "Reached here.")
+    end
+
+    def test_pend_with_no_failure_in_block
+      pend("Wait a minute") do
+        "Nothing raised"
+      end
+      assert(true, "Not reached here.")
+    end
+  end
+
+  def test_pend
+    test = nil
+    result = _run_test("test_pend") {|t| test = t}
+    assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 1 pendings, " \
+                 "0 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["1st pend"], result.pendings)
+    assert_true(test.interrupted?)
+  end
+
+  def test_pend_with_failure_in_block
+    test = nil
+    result = _run_test("test_pend_with_failure_in_block") {|t| test = t}
+    assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 1 pendings, " \
+                 "0 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["Wait a minute"], result.pendings)
+    assert_false(test.interrupted?)
+  end
+
+  def test_pend_with_no_failure_in_block
+    test = nil
+    result = _run_test("test_pend_with_no_failure_in_block") {|t| test = t}
+    assert_equal("1 tests, 1 assertions, 1 failures, 0 errors, 0 pendings, " \
+                 "0 omissions, 0 notifications",
+                 result.to_s)
+    assert_fault_messages(["Pending block should not be passed: Wait a minute."],
+                          result.failures)
+    assert_true(test.interrupted?)
+  end
+
+  private
+  def _run_test(name, &block)
+    super(TestCase, name, &block)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-priority.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-priority.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-priority.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,119 @@
+require 'test/unit'
+
+class TestUnitPriority < Test::Unit::TestCase
+  class TestCase < Test::Unit::TestCase
+    class << self
+      def suite
+        Test::Unit::TestSuite.new(name)
+      end
+    end
+
+    priority :must
+    def test_must
+      assert(true)
+    end
+
+    def test_must_inherited
+      assert(true)
+    end
+
+    priority :important
+    def test_important
+      assert(true)
+    end
+
+    def test_important_inherited
+      assert(true)
+    end
+
+    priority :high
+    def test_high
+      assert(true)
+    end
+
+    def test_high_inherited
+      assert(true)
+    end
+
+    priority :normal
+    def test_normal
+      assert(true)
+    end
+
+    def test_normal_inherited
+      assert(true)
+    end
+
+    priority :low
+    def test_low
+      assert(true)
+    end
+
+    def test_low_inherited
+      assert(true)
+    end
+
+    priority :never
+    def test_never
+      assert(true)
+    end
+
+    def test_never_inherited
+      assert(true)
+    end
+  end
+
+  def test_priority
+    assert_priority("must", 1.0, 0.0001)
+    assert_priority("important", 0.9, 0.09)
+    assert_priority("high", 0.70, 0.1)
+    assert_priority("normal", 0.5, 0.1)
+    assert_priority("low", 0.25, 0.1)
+    assert_priority("never", 0.0, 0.0001)
+  end
+
+  def assert_priority(priority, expected, delta)
+    assert_need_to_run("test_#{priority}", expected, delta)
+    assert_need_to_run("test_#{priority}_inherited", expected, delta)
+  end
+
+  def assert_need_to_run(test_name, expected, delta)
+    test = TestCase.new(test_name)
+    n = 1000
+    n_need_to_run = 0
+    n.times do |i|
+      n_need_to_run +=1 if Test::Unit::Priority::Checker.need_to_run?(test)
+    end
+    assert_in_delta(expected, n_need_to_run.to_f / n, delta)
+  end
+
+  class SpecialNameTestCase < Test::Unit::TestCase
+    class << self
+      def suite
+        Test::Unit::TestSuite.new(name)
+      end
+    end
+
+    def test_question?
+    end
+
+    def test_exclamation!
+    end
+
+    def test_equal=
+    end
+  end
+
+  def test_escaped?
+    assert_escaped_name("test_question.predicate", "test_question?")
+    assert_escaped_name("test_exclamation.destructive", "test_exclamation!")
+    assert_escaped_name("test_equal.equal", "test_equal=")
+  end
+
+  def assert_escaped_name(expected, test_method_name)
+    checker = Checker.new(SpecialNameTestCase.new(test_method_name))
+    passed_file = checker.send(:passed_file)
+    method_name_component = File.basename(File.dirname(passed_file))
+    assert_equal(expected, method_name_component)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test-testcase.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test-testcase.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test-testcase.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,507 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+  module Unit
+    class TestTestCase < TestCase
+      def test_creation
+        tc = Class.new(TestCase) do
+          def test_with_arguments(arg1, arg2)
+          end
+        end
+      
+        caught = true
+        catch(:invalid_test) do
+          tc.new(:test_with_arguments)
+          caught = false
+        end
+        check("Should have caught an invalid test when there are arguments", caught)
+        
+        caught = true
+        catch(:invalid_test) do
+          tc.new(:non_existent_test)
+          caught = false
+        end
+        check("Should have caught an invalid test when the method does not exist", caught)
+      end
+      
+      def setup
+        @tc_failure_error = Class.new(TestCase) do
+          def test_failure
+            assert_block("failure") { false }
+          end
+          def test_error
+            1 / 0
+          end
+          def test_nested_failure
+            nested
+          end
+          def nested
+            assert_block("nested"){false}
+          end
+          def return_passed?
+            return passed?
+          end
+        end
+
+        def @tc_failure_error.name
+          "TC_FailureError"
+        end
+      end
+ 
+      def test_add_failed_assertion
+        test_case = @tc_failure_error.new(:test_failure)
+        check("passed? should start out true", test_case.return_passed?)
+        result = TestResult.new
+        called = false
+        result.add_listener(TestResult::FAULT) {
+          | fault |
+          check("Should have a Failure", fault.instance_of?(Failure))
+          check("The Failure should have the correct message", "failure" == fault.message)
+          check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_failure(TC_FailureError)")
+          r = /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_failure'\Z/
+
+          location = fault.location
+          check("The location should be an array", location.kind_of?(Array))
+          check("The location should have two lines (was: <#{location.inspect}>)", location.size == 2)
+          check("The Failure should have the correct location (was <#{location[0].inspect}>, expected <#{r.inspect}>)", r =~ location[0])
+          called = true
+        }
+        progress = []
+        test_case.run(result) { |*arguments| progress << arguments }
+        check("The failure should have triggered the listener", called)
+        check("The failure should have set passed?", !test_case.return_passed?)
+        check("The progress block should have been updated correctly", [[TestCase::STARTED, test_case.name], [TestCase::FINISHED, test_case.name]] == progress)
+      end
+
+      def test_add_failure_nested
+        test_case = @tc_failure_error.new(:test_nested_failure)
+        check("passed? should start out true", test_case.return_passed?)
+
+        result = TestResult.new
+        called = false
+        result.add_listener(TestResult::FAULT) {
+          | fault |
+          check("Should have a Failure", fault.instance_of?(Failure))
+          check("The Failure should have the correct message", "nested" == fault.message)
+          check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_nested_failure(TC_FailureError)")
+          r = 
+
+          location = fault.location
+          check("The location should be an array", location.kind_of?(Array))
+          check("The location should have the correct number of lines (was: <#{location.inspect}>)", location.size == 3)
+          check("The Failure should have the correct location (was <#{location[0].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `nested'\Z/ =~ location[0])
+          check("The Failure should have the correct location (was <#{location[1].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_nested_failure'\Z/ =~ location[1])
+          called = true
+        }
+        test_case.run(result){}
+        check("The failure should have triggered the listener", called)
+      end
+      
+      def test_add_error
+        test_case = @tc_failure_error.new(:test_error)
+        check("passed? should start out true", test_case.return_passed?)
+        result = TestResult.new
+        called = false
+        result.add_listener(TestResult::FAULT) {
+          | fault |
+          check("Should have a TestError", fault.instance_of?(Error))
+          check("The Error should have the correct message", "ZeroDivisionError: divided by 0" == fault.message)
+          check("The Error should have the correct test_name", "test_error(TC_FailureError)" == fault.test_name)
+          check("The Error should have the correct exception", fault.exception.instance_of?(ZeroDivisionError))
+          called = true
+        }
+        test_case.run(result) {}
+        check("The error should have triggered the listener", called)
+        check("The error should have set passed?", !test_case.return_passed?)
+      end
+
+      def test_no_tests      
+        suite = TestCase.suite
+        check("Should have a test suite", suite.instance_of?(TestSuite))
+        check("Should have one test", suite.size == 1)
+        check("Should have the default test", suite.tests.first.name == "default_test(Test::Unit::TestCase)")
+        
+        result = TestResult.new
+        suite.run(result) {}
+        check("Should have had one test run", result.run_count == 1)
+        check("Should have had one test failure", result.failure_count == 1)
+        check("Should have had no errors", result.error_count == 0)
+      end
+
+      def test_suite
+        tc = Class.new(TestCase) do
+          def test_succeed
+            assert_block {true}
+          end
+          def test_fail
+            assert_block {false}
+          end
+          def test_error
+            1/0
+          end
+          def dont_run
+            assert_block {true}
+          end
+          def test_dont_run(argument)
+            assert_block {true}
+          end
+          def test
+            assert_block {true}
+          end
+        end
+      
+        suite = tc.suite
+        check("Should have a test suite", suite.instance_of?(TestSuite))
+        check("Should have three tests", suite.size == 3)
+  
+        result = TestResult.new
+        suite.run(result) {}
+        check("Should have had three test runs", result.run_count == 3)
+        check("Should have had one test failure", result.failure_count == 1)
+        check("Should have had one test error", result.error_count == 1)
+      end
+      
+     
+      def test_setup_teardown
+        tc = Class.new(TestCase) do
+          attr_reader(:setup_called, :teardown_called)
+          def initialize(test)
+            super(test)
+            @setup_called = false
+            @teardown_called = false
+          end
+          def setup
+            @setup_called = true
+          end
+          def teardown
+            @teardown_called = true
+          end
+          def test_succeed
+            assert_block {true}
+          end
+          def test_fail
+            assert_block {false}
+          end
+          def test_error
+            raise "Error!"
+          end
+        end
+        result = TestResult.new
+  
+        test = tc.new(:test_succeed)
+        test.run(result) {}
+        check("Should have called setup the correct number of times", test.setup_called)
+        check("Should have called teardown the correct number of times", test.teardown_called)
+  
+        test = tc.new(:test_fail)
+        test.run(result) {}
+        check("Should have called setup the correct number of times", test.setup_called)
+        check("Should have called teardown the correct number of times", test.teardown_called)
+  
+        test = tc.new(:test_error)
+        test.run(result) {}
+        check("Should have called setup the correct number of times", test.setup_called)
+        check("Should have called teardown the correct number of times", test.teardown_called)
+  
+        check("Should have had two test runs", result.run_count == 3)
+        check("Should have had a test failure", result.failure_count == 1)
+        check("Should have had a test error", result.error_count == 1)
+      end
+      
+      def test_assertion_failed_not_called
+        tc = Class.new(TestCase) do
+          def test_thing
+            raise AssertionFailedError.new
+          end
+        end
+        
+        suite = tc.suite
+        check("Should have one test", suite.size == 1)
+        result = TestResult.new
+        suite.run(result) {}
+        check("Should have had one test run", result.run_count == 1)
+        check("Should have had one assertion failure", result.failure_count == 1)
+        check("Should not have any assertion errors but had #{result.error_count}", result.error_count == 0)
+      end
+      
+      def test_equality
+        tc1 = Class.new(TestCase) do
+          def test_1
+          end
+          def test_2
+          end
+        end
+        
+        tc2 = Class.new(TestCase) do
+          def test_1
+          end
+        end
+      
+        test1 = tc1.new('test_1')
+        test2 = tc1.new('test_1')
+        check("Should be equal", test1 == test2)
+        check("Should be equal", test2 == test1)
+        
+        test1 = tc1.new('test_2')
+        check("Should not be equal", test1 != test2)
+        check("Should not be equal", test2 != test1)
+        
+        test2 = tc1.new('test_2')
+        check("Should be equal", test1 == test2)
+        check("Should be equal", test2 == test1)
+        
+        test1 = tc1.new('test_1')
+        test2 = tc2.new('test_1')
+        check("Should not be equal", test1 != test2)
+        check("Should not be equal", test2 != test1)
+
+        
+        check("Should not be equal", test1 != Object.new)
+        check("Should not be equal", Object.new != test1)
+      end
+
+      def test_re_raise_exception
+        test_case = Class.new(TestCase) do
+          def test_raise_interrupt
+            raise Interrupt, "from test"
+          end
+        end
+
+        test = test_case.new("test_raise_interrupt")
+        begin
+          test.run(TestResult.new) {}
+          check("Should not be reached", false)
+        rescue Exception
+          check("Interrupt exception should be re-raised", $!.class == Interrupt)
+        end
+      end
+
+      def test_startup_shutdown
+        called = []
+        test_case = Class.new(TestCase) do
+          @@called = called
+          class << self
+            def startup
+              @@called << :startup
+            end
+
+            def shutdown
+              @@called << :shutdown
+            end
+          end
+
+          def setup
+            @@called << :setup
+          end
+
+          def teardown
+            @@called << :teardown
+          end
+
+          def test1
+          end
+
+          def test2
+          end
+        end
+
+        test_suite = test_case.suite
+        test_suite.run(TestResult.new) {}
+        check("startup/shutdown should be called once per test case" +
+              ": #{called.inspect}",
+              called == [:startup,
+                         :setup, :teardown,
+                         :setup, :teardown,
+                         :shutdown])
+      end
+
+      def test_error_on_startup
+        test_case = Class.new(TestCase) do
+          class << self
+            def startup
+              raise "from startup"
+            end
+          end
+
+          def test_nothing
+          end
+        end
+
+        test_suite = test_case.suite
+        result = TestResult.new
+        test_suite.run(result) {}
+        check("Should record an error on startup: #{result}",
+              result.error_count == 1)
+      end
+
+      def test_pass_through_error_on_startup
+        test_case = Class.new(TestCase) do
+          class << self
+            def startup
+              raise Interrupt, "from startup"
+            end
+          end
+
+          def test_nothing
+          end
+        end
+
+        test_suite = test_case.suite
+        begin
+          test_suite.run(TestResult.new) {}
+          check("Should not be reached", false)
+        rescue Exception
+          check("Interrupt should be passed through: #{$!}",
+                Interrupt === $!)
+        end
+      end
+
+      def test_error_on_shutdown
+        test_case = Class.new(TestCase) do
+          class << self
+            def shutdown
+              raise "from shutdown"
+            end
+          end
+
+          def test_nothing
+          end
+        end
+
+        test_suite = test_case.suite
+        result = TestResult.new
+        test_suite.run(result) {}
+        check("Should record an error on shutdown: #{result}",
+              result.error_count == 1)
+      end
+
+      def test_pass_through_error_on_shutdown
+        test_case = Class.new(TestCase) do
+          class << self
+            def shutdown
+              raise Interrupt, "from shutdown"
+            end
+          end
+
+          def test_nothing
+          end
+        end
+
+        test_suite = test_case.suite
+        begin
+          test_suite.run(TestResult.new) {}
+          check("Should not be reached", false)
+        rescue Exception
+          check("Interrupt should be passed through: #{$!}",
+                Interrupt === $!)
+        end
+      end
+
+      def test_interrupted
+        test_case = Class.new(TestCase) do
+          def test_fail
+            flunk
+          end
+
+          def test_nothing
+          end
+        end
+
+        failed_test = test_case.new(:test_fail)
+        failed_test.run(TestResult.new) {}
+        check("Should be interrupted", failed_test.interrupted?)
+
+        success_test = test_case.new(:test_nothing)
+        success_test.run(TestResult.new) {}
+        check("Should not be interrupted", !success_test.interrupted?)
+      end
+
+      def test_inherited_test_should_be_ignored
+        test_case = Class.new(TestCase) do
+          def test_nothing
+          end
+        end
+
+        sub_test_case = Class.new(test_case) do
+          def test_fail
+            flunk
+          end
+        end
+
+        assert_nothing_thrown do
+          test_case.new("test_nothing")
+        end
+
+        assert_nothing_thrown do
+          sub_test_case.new("test_fail")
+        end
+
+        assert_throw(:invalid_test) do
+          sub_test_case.new("test_nothing")
+        end
+      end
+
+      def test_mixin_test_should_not_be_ignored
+        test_module = Module.new do
+          def test_nothing
+          end
+        end
+
+        test_case = Class.new(Test::Unit::TestCase) do
+          include test_module
+
+          def test_fail
+            flunk
+          end
+        end
+
+        assert_nothing_thrown do
+          test_case.new("test_nothing")
+        end
+
+        assert_nothing_thrown do
+          test_case.new("test_fail")
+        end
+      end
+
+      def test_defined_order
+        keep_test_order do
+          test_case = Class.new(Test::Unit::TestCase) do
+            def test_z
+            end
+
+            def test_1
+            end
+
+            def test_a
+            end
+          end
+
+          assert_equal(["test_1", "test_a", "test_z"],
+                       test_case.suite.tests.collect {|test| test.method_name})
+
+          test_case.test_order = :defined
+          assert_equal(["test_z", "test_1", "test_a"],
+                       test_case.suite.tests.collect {|test| test.method_name})
+        end
+      end
+
+      private
+      def check(message, passed)
+        add_assertion
+        raise AssertionFailedError.new(message) unless passed
+      end
+
+      def keep_test_order
+        order = TestCase.test_order
+        yield
+      ensure
+        TestCase.test_order = order
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test_assertions.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test_assertions.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test_assertions.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,1082 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+#             Copyright (c) 2009 Kouhei Sutou.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+  module Unit
+    class TC_Assertions < TestCase
+      backtrace_pre  = "---Backtrace---"
+      backtrace_post = "---------------"
+      BACKTRACE_RE = /#{backtrace_pre}\n.+\n#{backtrace_post}/m
+
+      def check(value, message="")
+        add_assertion
+        raise AssertionFailedError.new(message) unless value
+      end
+
+      def check_assertions(expect_fail, expected_message="",
+                           return_value_expected=false)
+        @actual_assertion_count = 0
+        failed = true
+        actual_message = nil
+        @catch_assertions = true
+        return_value = nil
+        begin
+          return_value = yield
+          failed = false
+        rescue AssertionFailedError => error
+          actual_message = error.message
+        end
+        @catch_assertions = false
+
+        if expect_fail
+          message = "Should have failed, but didn't"
+        else
+          message = "Should not have failed, but did with message\n" +
+            "<#{actual_message}>"
+        end
+        check(expect_fail == failed, message)
+
+        message = "Should have made one assertion but made\n" +
+          "<#{@actual_assertion_count}>"
+        check(1 == @actual_assertion_count, message)
+
+        if expect_fail
+          case expected_message
+          when String
+            check(actual_message == expected_message,
+                  "Should have the correct message.\n" +
+                  "<#{expected_message.inspect}> expected but was\n" +
+                  "<#{actual_message.inspect}>")
+          when Regexp
+            check(actual_message =~ expected_message,
+                  "The message should match correctly.\n" +
+                  "</#{expected_message.source}/> expected to match\n" +
+                  "<#{actual_message.inspect}>")
+          else
+            check(false,
+                  "Incorrect expected message type in assert_nothing_failed")
+          end
+        else
+          if return_value_expected
+            check(!return_value.nil?, "Should return a value")
+          else
+            check(return_value.nil?,
+                  "Should not return a value but returned <#{return_value}>")
+          end
+        end
+
+        return_value
+      end
+
+      def check_nothing_fails(return_value_expected=false, &proc)
+        check_assertions(false, "", return_value_expected, &proc)
+      end
+
+      def check_fails(expected_message="", &proc)
+        check_assertions(true, expected_message, &proc)
+      end
+
+      def inspect_tag(tag)
+        begin
+          throw tag
+        rescue NameError
+          tag.to_s.inspect
+        rescue ArgumentError
+          tag.inspect
+        end
+      end
+
+      def test_assert_block
+        check_nothing_fails {
+          assert_block {true}
+        }
+        check_nothing_fails {
+          assert_block("successful assert_block") {true}
+        }
+        check_nothing_fails {
+          assert_block("successful assert_block") {true}
+        }
+        check_fails("assert_block failed.") {
+          assert_block {false}
+        }
+        check_fails("failed assert_block") {
+          assert_block("failed assert_block") {false}
+        }
+      end
+      
+      def test_assert
+        check_nothing_fails{assert("a")}
+        check_nothing_fails{assert(true)}
+        check_nothing_fails{assert(true, "successful assert")}
+        check_fails("<nil> is not true."){assert(nil)}
+        check_fails("<false> is not true."){assert(false)}
+        check_fails("failed assert.\n<false> is not true."){assert(false, "failed assert")}
+      end
+      
+      def test_assert_equal
+        check_nothing_fails {
+          assert_equal("string1", "string1")
+        }
+        check_nothing_fails {
+          assert_equal("string1", "string1", "successful assert_equal")
+        }
+
+        message = <<-EOM.chomp
+<"string1"> expected but was
+<"string2">.
+
+diff:
+- string1
+?       ^
++ string2
+?       ^
+EOM
+        check_fails(message) {
+          assert_equal("string1", "string2")
+        }
+
+        message = <<-EOM.chomp
+failed assert_equal.
+<"string1"> expected but was
+<"string2">.
+
+diff:
+- string1
+?       ^
++ string2
+?       ^
+EOM
+        check_fails(message) {
+          assert_equal("string1", "string2", "failed assert_equal")
+        }
+
+        message = <<-EOM.chomp
+<"111111"> expected but was
+<111111>.
+
+diff:
+- "111111"
+? -      -
++ 111111
+EOM
+        check_fails(message) do
+          assert_equal("111111", 111111)
+        end
+      end
+
+      def test_assert_equal_with_long_line
+        expected = ["0123456789",
+                    "1123456789",
+                    "2123456789",
+                    "3123456789",
+                    "4123456789",
+                    "5123456789",
+                    "6123456789",
+                    "7123456789",
+                    "8123456789"].join
+        actual =   ["0000000000",
+                    "1123456789",
+                    "2123456789",
+                    "3123456789",
+                    "4123456789",
+                    "5123456789",
+                    "6123456789",
+                    "7123456789",
+                    "8123456789"].join
+        message = <<-EOM.chomp
+<"#{expected}"> expected but was
+<"#{actual}">.
+
+diff:
+- #{expected}
+?  ^^^^^^^^^
++ #{actual}
+?  ^^^^^^^^^
+
+folded diff:
+- 012345678911234567892123456789312345678941234567895123456789612345678971234567
+?  ^^^^^^^^^
++ 000000000011234567892123456789312345678941234567895123456789612345678971234567
+?  ^^^^^^^^^
+  898123456789
+EOM
+        check_fails(message) do
+          assert_equal(expected, actual)
+        end
+      end
+
+      def test_assert_equal_for_too_small_difference
+        message = <<-EOM.chomp
+<1> expected but was
+<2>.
+EOM
+        check_fails(message) do
+          assert_equal(1, 2)
+        end
+      end
+
+      def test_assert_equal_for_same_inspected_objects
+        now = Time.now
+        now_without_usec = Time.at(now.to_i)
+        message = <<-EOM.chomp
+<#{now.inspect}> expected but was
+<#{now.inspect}>.
+EOM
+        check_fails(message) do
+          assert_equal(now, now_without_usec)
+        end
+      end
+
+      def test_assert_equal_with_multi_lines_result
+        message = <<-EOM.chomp
+<#{"a\nb".inspect}> expected but was
+<#{"x".inspect}>.
+
+diff:
++ x
+- a
+- b
+EOM
+        check_fails(message) do
+          assert_equal("a\nb", "x")
+        end
+      end
+
+      def test_assert_equal_with_large_string
+        message = <<-EOM.chomp
+<#{("a\n" + "x" * 297).inspect}> expected but was
+<#{"x".inspect}>.
+
+diff:
++ x
+- a
+- #{"x" * 297}
+
+folded diff:
++ x
+- a
+- #{"x" * 78}
+- #{"x" * 78}
+- #{"x" * 78}
+- #{"x" * 63}
+EOM
+        check_fails(message) do
+          assert_equal("a\n" + "x" * 297, "x")
+        end
+
+        message = <<-EOM.chomp
+<#{("a\n" + "x" * 298).inspect}> expected but was
+<#{"x".inspect}>.
+EOM
+        check_fails(message) do
+          assert_equal("a\n" + "x" * 298, "x")
+        end
+      end
+
+      def test_assert_raise_success
+        return_value = nil
+        check_nothing_fails(true) do
+          return_value = assert_raise(RuntimeError) do
+            raise "Error"
+          end
+        end
+        check(return_value.kind_of?(Exception),
+              "Should have returned the exception " +
+              "from a successful assert_raise")
+        check(return_value.message == "Error",
+              "Should have returned the correct exception " +
+              "from a successful assert_raise")
+
+        check_nothing_fails(true) do
+          assert_raise(ArgumentError, "successful assert_raise") do
+            raise ArgumentError.new("Error")
+          end
+        end
+
+        check_nothing_fails(true) do
+          assert_raise(RuntimeError) do
+            raise "Error"
+          end
+        end
+
+        check_nothing_fails(true) do
+          assert_raise(RuntimeError, "successful assert_raise") do
+            raise "Error"
+          end
+        end
+
+        check_nothing_fails(true) do
+          assert_raise do
+            raise Exception, "Any exception"
+          end
+        end
+      end
+
+      def test_assert_raise_fail
+        check_fails("<RuntimeError> exception expected but none was thrown.") do
+          assert_raise(RuntimeError) do
+            1 + 1
+          end
+        end
+
+        message = <<-EOM
+failed assert_raise.
+<ArgumentError> exception expected but was
+Class: <RuntimeError>
+Message: <"Error">
+EOM
+        check_fails(/\A#{message}#{BACKTRACE_RE}\Z/m) do
+          assert_raise(ArgumentError, "failed assert_raise") do
+            raise "Error"
+          end
+        end
+
+        message = <<-EOM
+Should expect a class of exception, Object.
+<false> is not true.
+EOM
+        check_fails(message.chomp) do
+          assert_nothing_raised(Object) do
+            1 + 1
+          end
+        end
+      end
+
+      def test_assert_raise_module
+        exceptions = [ArgumentError, TypeError]
+        modules = [Math, Comparable]
+        rescues = exceptions + modules
+
+        exceptions.each do |exc|
+          return_value = nil
+          check_nothing_fails(true) do
+            return_value = assert_raise(*rescues) do
+              raise exc, "Error"
+            end
+          end
+          check(return_value.instance_of?(exc),
+                "Should have returned #{exc} but was #{return_value.class}")
+          check(return_value.message == "Error",
+                "Should have returned the correct exception " +
+                "from a successful assert_raise")
+        end
+
+        modules.each do |mod|
+          return_value = nil
+          check_nothing_fails(true) do
+            return_value = assert_raise(*rescues) do
+              raise Exception.new("Error").extend(mod)
+            end
+          end
+          check(mod === return_value,
+                "Should have returned #{mod}")
+          check(return_value.message == "Error",
+                "Should have returned the correct exception " +
+                "from a successful assert_raise")
+        end
+
+        check_fails("<[ArgumentError, TypeError, Math, Comparable]> exception " +
+                    "expected but none was thrown.") do
+          assert_raise(*rescues) do
+            1 + 1
+          end
+        end
+
+        message = <<-EOM
+failed assert_raise.
+<[ArgumentError, TypeError]> exception expected but was
+Class: <RuntimeError>
+Message: <"Error">
+EOM
+        message = Regexp.escape(message)
+        check_fails(/\A#{message}#{BACKTRACE_RE}\z/m) do
+          assert_raise(ArgumentError, TypeError, "failed assert_raise") do
+            raise "Error"
+          end
+        end
+      end
+
+      def test_assert_raise_instance
+        return_value = nil
+        check_nothing_fails(true) do
+          return_value = assert_raise(RuntimeError.new("Error")) do
+            raise "Error"
+          end
+        end
+        check(return_value.kind_of?(Exception),
+              "Should have returned the exception " +
+              "from a successful assert_raise")
+        check(return_value.message == "Error",
+              "Should have returned the correct exception " +
+              "from a successful assert_raise")
+
+        message = <<-EOM
+<RuntimeError("XXX")> exception expected but was
+Class: <RuntimeError>
+Message: <"Error">
+EOM
+        message = Regexp.escape(message)
+        check_fails(/\A#{message}#{BACKTRACE_RE}\z/) do
+          return_value = assert_raise(RuntimeError.new("XXX")) do
+            raise "Error"
+          end
+        end
+
+        different_error_class = Class.new(StandardError)
+        message = <<-EOM
+<\#<Class:[xa-f\\d]+>\\("Error"\\)> exception expected but was
+Class: <RuntimeError>
+Message: <"Error">
+EOM
+        check_fails(/\A#{message}#{BACKTRACE_RE}\z/) do
+          assert_raise(different_error_class.new("Error")) do
+            raise "Error"
+          end
+        end
+
+        different_error = different_error_class.new("Error")
+        def different_error.inspect
+          "DifferentError: \"Error\""
+        end
+        message = <<-EOM
+<\DifferentError: \\"Error\\"> exception expected but was
+Class: <RuntimeError>
+Message: <"Error">
+EOM
+        check_fails(/\A#{message}#{BACKTRACE_RE}\z/) do
+          assert_raise(different_error) do
+            raise "Error"
+          end
+        end
+
+        check_nothing_fails(true) do
+          assert_raise(different_error_class.new("Error"),
+                       RuntimeError.new("Error"),
+                       RuntimeError.new("XXX")) do
+            raise "Error"
+          end
+        end
+      end
+
+      def test_assert_instance_of
+        check_nothing_fails {
+          assert_instance_of(String, "string")
+        }
+        check_nothing_fails {
+          assert_instance_of(String, "string", "successful assert_instance_of")
+        }
+        check_nothing_fails {
+          assert_instance_of(String, "string", "successful assert_instance_of")
+        }
+        check_fails(%Q{<"string"> expected to be an instance of\n<Hash> but was\n<String>.}) {
+          assert_instance_of(Hash, "string")
+        }
+        check_fails(%Q{failed assert_instance_of.\n<"string"> expected to be an instance of\n<Hash> but was\n<String>.}) {
+          assert_instance_of(Hash, "string", "failed assert_instance_of")
+        }
+
+        check_nothing_fails do
+          assert_instance_of([Fixnum, NilClass], 100)
+        end
+        check_fails(%Q{<"string"> expected to be an instance of\n[<Fixnum>, <NilClass>] but was\n<String>.}) do
+          assert_instance_of([Fixnum, NilClass], "string")
+        end
+        check_fails(%Q{<100> expected to be an instance of\n[<Numeric>, <NilClass>] but was\n<Fixnum>.}) do
+          assert_instance_of([Numeric, NilClass], 100)
+        end
+      end
+
+      def test_assert_nil
+        check_nothing_fails {
+          assert_nil(nil)
+        }
+        check_nothing_fails {
+          assert_nil(nil, "successful assert_nil")
+        }
+        check_nothing_fails {
+          assert_nil(nil, "successful assert_nil")
+        }
+        check_fails(%Q{<"string"> expected to be nil.}) {
+          assert_nil("string")
+        }
+        check_fails(%Q{failed assert_nil.\n<"string"> expected to be nil.}) {
+          assert_nil("string", "failed assert_nil")
+        }
+      end
+      
+      def test_assert_not_nil
+        check_nothing_fails{assert_not_nil(false)}
+        check_nothing_fails{assert_not_nil(false, "message")}
+        check_fails("<nil> expected to not be nil."){assert_not_nil(nil)}
+        check_fails("message.\n<nil> expected to not be nil.") {assert_not_nil(nil, "message")}
+      end
+        
+      def test_assert_kind_of
+        check_nothing_fails {
+          assert_kind_of(Module, Array)
+        }
+        check_nothing_fails {
+          assert_kind_of(Object, "string", "successful assert_kind_of")
+        }
+        check_nothing_fails {
+          assert_kind_of(Object, "string", "successful assert_kind_of")
+        }
+        check_nothing_fails {
+          assert_kind_of(Comparable, 1)
+        }
+        check_fails(%Q{<"string"> expected to be kind_of?\n<Class> but was\n<String>.}) {
+          assert_kind_of(Class, "string")
+        }
+        check_fails(%Q{failed assert_kind_of.\n<"string"> expected to be kind_of?\n<Class> but was\n<String>.}) {
+          assert_kind_of(Class, "string", "failed assert_kind_of")
+        }
+
+        check_nothing_fails do
+          assert_kind_of([Fixnum, NilClass], 100)
+        end
+        check_fails(%Q{<"string"> expected to be kind_of?\n[<Fixnum>, <NilClass>] but was\n<String>.}) do
+          assert_kind_of([Fixnum, NilClass], "string")
+        end
+      end
+
+      def test_assert_match
+        check_nothing_fails {
+          assert_match(/strin./, "string")
+        }
+        check_nothing_fails {
+          assert_match("strin", "string")
+        }
+        check_nothing_fails {
+          assert_match(/strin./, "string", "successful assert_match")
+        }
+        check_nothing_fails {
+          assert_match(/strin./, "string", "successful assert_match")
+        }
+        check_fails(%Q{<"string"> expected to be =~\n</slin./>.}) {
+          assert_match(/slin./, "string")
+        }
+        check_fails(%Q{<"string"> expected to be =~\n</strin\\./>.}) {
+          assert_match("strin.", "string")
+        }
+        check_fails(%Q{failed assert_match.\n<"string"> expected to be =~\n</slin./>.}) {
+          assert_match(/slin./, "string", "failed assert_match")
+        }
+      end
+      
+      def test_assert_same
+        thing = "thing"
+        check_nothing_fails {
+          assert_same(thing, thing)
+        }
+        check_nothing_fails {
+          assert_same(thing, thing, "successful assert_same")
+        }
+        check_nothing_fails {
+          assert_same(thing, thing, "successful assert_same")
+        }
+        thing2 = "thing"
+        check_fails(%Q{<"thing">\nwith id <#{thing.__id__}> expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) {
+          assert_same(thing, thing2)
+        }
+        check_fails(%Q{failed assert_same.\n<"thing">\nwith id <#{thing.__id__}> expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) {
+          assert_same(thing, thing2, "failed assert_same")
+        }
+      end
+      
+      def test_assert_nothing_raised
+        check_nothing_fails {
+          assert_nothing_raised {
+            1 + 1
+          }
+        }
+        check_nothing_fails {
+          assert_nothing_raised("successful assert_nothing_raised") {
+            1 + 1
+          }
+        }
+        check_nothing_fails {
+          assert_nothing_raised("successful assert_nothing_raised") {
+            1 + 1
+          }
+        }
+        check_nothing_fails {
+          begin
+            assert_nothing_raised(RuntimeError, StandardError, Comparable, "successful assert_nothing_raised") {
+              raise ZeroDivisionError.new("ArgumentError")
+            }
+          rescue ZeroDivisionError
+          end
+        }
+        check_fails("Should expect a class of exception, Object.\n<false> is not true.") {
+          assert_nothing_raised(Object) {
+            1 + 1
+          }
+        }
+        check_fails(%r{\AException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+          assert_nothing_raised {
+            raise "Error"
+          }
+        }
+        check_fails(%r{\Afailed assert_nothing_raised\.\nException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+          assert_nothing_raised("failed assert_nothing_raised") {
+            raise "Error"
+          }
+        }
+        check_fails(%r{\AException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+          assert_nothing_raised(StandardError, RuntimeError) {
+            raise "Error"
+          }
+        }
+        check_fails("Failure.") do
+          assert_nothing_raised do
+            flunk("Failure")
+          end
+        end
+      end
+      
+      def test_flunk
+        check_fails("Flunked.") {
+          flunk
+        }
+        check_fails("flunk message.") {
+          flunk("flunk message")
+        }
+      end
+      
+      def test_assert_not_same
+        thing = "thing"
+        thing2 = "thing"
+        check_nothing_fails {
+          assert_not_same(thing, thing2)
+        }
+        check_nothing_fails {
+          assert_not_same(thing, thing2, "message")
+        }
+        check_fails(%Q{<"thing">\nwith id <#{thing.__id__}> expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) {
+          assert_not_same(thing, thing)
+        }
+        check_fails(%Q{message.\n<"thing">\nwith id <#{thing.__id__}> expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) {
+          assert_not_same(thing, thing, "message")
+        }
+      end
+      
+      def test_assert_not_equal
+        check_nothing_fails {
+          assert_not_equal("string1", "string2")
+        }
+        check_nothing_fails {
+          assert_not_equal("string1", "string2", "message")
+        }
+        check_fails(%Q{<"string"> expected to be != to\n<"string">.}) {
+          assert_not_equal("string", "string")
+        }
+        check_fails(%Q{message.\n<"string"> expected to be != to\n<"string">.}) {
+          assert_not_equal("string", "string", "message")
+        }
+      end
+      
+      def test_assert_no_match
+        check_nothing_fails{assert_no_match(/sling/, "string")}
+        check_nothing_fails{assert_no_match(/sling/, "string", "message")}
+        check_fails(%Q{The first argument to assert_no_match should be a Regexp.\n<"asdf"> expected to be an instance of\n<Regexp> but was\n<String>.}) do
+          assert_no_match("asdf", "asdf")
+        end
+        check_fails(%Q{</string/> expected to not match\n<"string">.}) do
+          assert_no_match(/string/, "string")
+        end
+        check_fails(%Q{message.\n</string/> expected to not match\n<"string">.}) do
+          assert_no_match(/string/, "string", "message")
+        end
+      end
+      
+      def test_assert_throw
+        check_nothing_fails do
+          assert_throw(:thing, "message") do
+            throw :thing
+          end
+        end
+
+        tag = :thing2
+        check_fails("message.\n" +
+                    "<:thing> expected to be thrown but\n" +
+                    "<#{inspect_tag(tag)}> was thrown.") do
+          assert_throw(:thing, "message") do
+            throw :thing2
+          end
+        end
+        check_fails("message.\n" +
+                    "<:thing> should have been thrown.") do
+          assert_throw(:thing, "message") do
+            1 + 1
+          end
+        end
+      end
+      
+      def test_assert_nothing_thrown
+        check_nothing_fails do
+          assert_nothing_thrown("message") do
+            1 + 1
+          end
+        end
+
+        tag = :thing
+        inspected = inspect_tag(tag)
+        check_fails("message.\n" +
+                    "<#{inspected}> was thrown when nothing was expected.") do
+          assert_nothing_thrown("message") do
+            throw tag
+          end
+        end
+      end
+      
+      def test_assert_operator
+        check_nothing_fails {
+          assert_operator("thing", :==, "thing", "message")
+        }
+        check_fails(%Q{<0.15>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to?(:to_str).}) do
+          assert_operator("thing", 0.15, "thing")
+        end
+        check_fails(%Q{message.\n<"thing1"> expected to be\n==\n<"thing2">.}) {
+          assert_operator("thing1", :==, "thing2", "message")
+        }
+      end
+      
+      def test_assert_respond_to
+        check_nothing_fails {
+          assert_respond_to("thing", :to_s, "message")
+        }
+        check_nothing_fails {
+          assert_respond_to("thing", "to_s", "message")
+        }
+        check_fails("<0.15>.kind_of?(Symbol) or\n" +
+                    "<0.15>.respond_to?(:to_str) expected") {
+          assert_respond_to("thing", 0.15)
+        }
+        check_fails("message.\n" +
+                    "<:symbol>.respond_to?(:non_existent) expected\n" +
+                    "(Class: <Symbol>)") {
+          assert_respond_to(:symbol, :non_existent, "message")
+        }
+      end
+      
+      def test_assert_in_delta
+        check_nothing_fails {
+          assert_in_delta(1.4, 1.4, 0)
+        }
+        check_nothing_fails {
+          assert_in_delta(0.5, 0.4, 0.1, "message")
+        }
+        check_nothing_fails {
+          float_thing = Object.new
+          def float_thing.to_f
+            0.2
+          end
+          assert_in_delta(0.1, float_thing, 0.1)
+        }
+        check_fails("message.\n<0.5> and\n<0.4> expected to be within\n<0.05> of each other.") {
+          assert_in_delta(0.5, 0.4, 0.05, "message")
+        }
+        object = Object.new
+        check_fails("The arguments must respond to to_f; " +
+                    "the first float did not.\n" +
+                    "<#{object.inspect}>.respond_to?(:to_f) expected\n" +
+                    "(Class: <Object>)") {
+          assert_in_delta(object, 0.4, 0.1)
+        }
+        check_fails("The delta should not be negative.\n" +
+                    "<-0.1> expected to be\n>=\n<0.0>.") {
+          assert_in_delta(0.5, 0.4, -0.1, "message")
+        }
+      end
+      
+      def test_assert_send
+        object = Object.new
+        class << object
+          private
+          def return_argument(argument, bogus)
+            return argument
+          end
+        end
+        check_nothing_fails {
+          assert_send([object, :return_argument, true, "bogus"], "message")
+        }
+        check_fails(%r{\Amessage\.\n<.+> expected to respond to\n<return_argument\(\[false, "bogus"\]\)> with a true value.\Z}) {
+          assert_send([object, :return_argument, false, "bogus"], "message")
+        }
+      end
+      
+      def test_condition_invariant
+        object = Object.new
+        def object.inspect
+          @changed = true
+        end
+        def object.==(other)
+          @changed ||= false
+          return (!@changed)
+        end
+        check_nothing_fails do
+          assert_equal(object, object, "message")
+        end
+      end
+
+      def test_assert_boolean
+        check_nothing_fails do
+          assert_boolean(true)
+        end
+        check_nothing_fails do
+          assert_boolean(false)
+        end
+
+        check_fails("<true> or <false> expected but was\n<1>") do
+          assert_boolean(1)
+        end
+
+        check_fails("<true> or <false> expected but was\n<nil>") do
+          assert_boolean(nil)
+        end
+
+        check_fails("message.\n<true> or <false> expected but was\n<\"XXX\">") do
+          assert_boolean("XXX", "message")
+        end
+      end
+
+      def test_assert_true
+        check_nothing_fails do
+          assert_true(true)
+        end
+
+        check_fails("<true> expected but was\n<false>") do
+          assert_true(false)
+        end
+
+        check_fails("<true> expected but was\n<1>") do
+          assert_true(1)
+        end
+
+        check_fails("message.\n<true> expected but was\n<nil>") do
+          assert_true(nil, "message")
+        end
+      end
+
+      def test_assert_false
+        check_nothing_fails do
+          assert_false(false)
+        end
+
+        check_fails("<false> expected but was\n<true>") do
+          assert_false(true)
+        end
+
+        check_fails("<false> expected but was\n<nil>") do
+          assert_false(nil)
+        end
+
+        check_fails("message.\n<false> expected but was\n<:false>") do
+          assert_false(:false, "message")
+        end
+      end
+
+      def test_assert_compare
+        check_nothing_fails do
+          assert_compare(1.4, "<", 10.0)
+        end
+
+        check_nothing_fails do
+          assert_compare(2, "<=", 2)
+        end
+
+        check_nothing_fails do
+          assert_compare(14, ">=", 10.0)
+        end
+
+        check_nothing_fails do
+          assert_compare(14, ">", 13.9)
+        end
+
+        expected_message = <<-EOM
+<15> < <10> should be true
+<15> expected less than
+<10>.
+EOM
+        check_fails(expected_message.chomp) do
+          assert_compare(15, "<", 10)
+        end
+
+        expected_message = <<-EOM
+<15> <= <10> should be true
+<15> expected less than or equal to
+<10>.
+EOM
+        check_fails(expected_message.chomp) do
+          assert_compare(15, "<=", 10)
+        end
+
+        expected_message = <<-EOM
+<10> > <15> should be true
+<10> expected greater than
+<15>.
+EOM
+        check_fails(expected_message.chomp) do
+          assert_compare(10, ">", 15)
+        end
+
+        expected_message = <<-EOM
+<10> >= <15> should be true
+<10> expected greater than or equal to
+<15>.
+EOM
+        check_fails(expected_message.chomp) do
+          assert_compare(10, ">=", 15)
+        end
+      end
+
+      def test_assert_fail_assertion
+        check_nothing_fails do
+          assert_fail_assertion do
+            flunk
+          end
+        end
+
+        check_fails("Failed assertion was expected.") do
+          assert_fail_assertion do
+          end
+        end
+      end
+
+      def test_assert_raise_message
+        check_nothing_fails do
+          assert_raise_message("Raise!") do
+            raise "Raise!"
+          end
+        end
+
+        check_nothing_fails do
+          assert_raise_message("Raise!") do
+            raise Exception, "Raise!"
+          end
+        end
+
+        check_nothing_fails do
+          assert_raise_message(/raise/i) do
+            raise "Raise!"
+          end
+        end
+
+        expected_message = <<-EOM
+<"Expected message"> exception message expected but was
+<"Actual message">.
+EOM
+        check_fails(expected_message.chomp) do
+          assert_raise_message("Expected message") do
+            raise "Actual message"
+          end
+        end
+
+        expected_message = <<-EOM
+<"Expected message"> exception message expected but none was thrown.
+EOM
+        check_fails(expected_message.chomp) do
+          assert_raise_message("Expected message") do
+          end
+        end
+      end
+
+      def test_assert_raise_kind_of
+        check_nothing_fails(true) do
+          assert_raise_kind_of(SystemCallError) do
+            raise Errno::EACCES
+          end
+        end
+
+        expected_message = <<-EOM
+<SystemCallError> family exception expected but was
+Class: <RuntimeError>
+Message: <"XXX">
+---Backtrace---
+EOM
+        check_fails(/\A#{Regexp.escape(expected_message)}(?m).+\z/) do
+          assert_raise_kind_of(SystemCallError) do
+            raise RuntimeError, "XXX"
+          end
+        end
+      end
+
+      def test_assert_const_defined
+        check_nothing_fails do
+          assert_const_defined(Test, :Unit)
+        end
+
+        check_nothing_fails do
+          assert_const_defined(Test, "Unit")
+        end
+
+        check_fails("<Test>.const_defined?(<:Nonexistence>) expected.") do
+          assert_const_defined(Test, :Nonexistence)
+        end
+      end
+
+      def test_assert_not_const_defined
+        check_nothing_fails do
+          assert_not_const_defined(Test, :Nonexistence)
+        end
+
+        check_fails("!<Test>.const_defined?(<:Unit>) expected.") do
+          assert_not_const_defined(Test, :Unit)
+        end
+
+        check_fails("!<Test>.const_defined?(<\"Unit\">) expected.") do
+          assert_not_const_defined(Test, "Unit")
+        end
+      end
+
+      def test_assert_predicate
+        check_nothing_fails do
+          assert_predicate([], :empty?)
+        end
+
+        check_fails("<[1]>.empty? is true value expected but was\n<false>") do
+          assert_predicate([1], :empty?)
+        end
+
+        check_fails("<[1]>.respond_to?(:nonexistent?) expected\n" +
+                    "(Class: <Array>)") do
+          assert_predicate([1], :nonexistent?)
+        end
+      end
+
+      def test_assert_not_predicate
+        check_nothing_fails do
+          assert_not_predicate([1], :empty?)
+        end
+
+        check_fails("<[]>.empty? is false value expected but was\n<true>") do
+          assert_not_predicate([], :empty?)
+        end
+
+        check_fails("<[]>.respond_to?(:nonexistent?) expected\n" +
+                    "(Class: <Array>)") do
+          assert_not_predicate([], :nonexistent?)
+        end
+      end
+
+      private
+      def add_failure(message, location=caller)
+        unless @catch_assertions
+          super
+        end
+      end
+
+      def add_assertion
+        if @catch_assertions
+          @actual_assertion_count += 1
+        else
+          super
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test_error.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test_error.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test_error.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,26 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+  module Unit
+    class TC_Error < TestCase
+      TF_Exception = Struct.new('TF_Exception', :message, :backtrace)
+      def test_display
+        ex = TF_Exception.new("message1\nmessage2", ['line1', 'line2'])
+        e = Error.new("name", ex)
+        assert_equal("name: #{TF_Exception.name}: message1", e.short_display)
+        assert_equal(<<EOM.strip, e.long_display)
+Error:
+name:
+Struct::TF_Exception: message1
+message2
+    line1
+    line2
+EOM
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test_failure.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test_failure.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test_failure.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,33 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/failure'
+
+module Test::Unit
+  class TestFailure < TestCase
+    def test_display
+      f = Failure.new("name", [%q{location:1 in 'l'}], "message1\nmessage2")
+      assert_equal("name: message1", f.short_display)
+      assert_equal(<<EOM.strip, f.long_display)
+Failure:
+name [location:1]:
+message1
+message2
+EOM
+
+      f = Failure.new("name", [%q{location1:2 in 'l1'}, 'location2:1', %q{location3:3 in 'l3'}], "message1\nmessage2")
+      assert_equal("name: message1", f.short_display)
+      assert_equal(<<EOM.strip, f.long_display)
+Failure:
+name
+    [location1:2 in 'l1'
+     location2:1
+     location3:3 in 'l3']:
+message1
+message2
+EOM
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test_testresult.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test_testresult.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test_testresult.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,113 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/testcase'
+require 'test/unit/testresult'
+
+module Test
+  module Unit
+    class TC_TestResult < TestCase
+      def setup
+        @my_result = TestResult.new
+        @my_result.add_assertion()
+        @failure = "failure"
+        @my_result.add_failure(@failure)
+        @error = "error"
+        @my_result.add_error(@error)
+      end
+
+      def test_result_changed_notification
+        called1 = false
+        @my_result.add_listener(TestResult::CHANGED) do |result|
+          assert_equal(@my_result, result)
+          called1 = true
+        end
+        @my_result.add_assertion
+        assert_true(called1)
+
+        called1, called2 = false, false
+        @my_result.add_listener(TestResult::CHANGED) do |result|
+          assert_equal(@my_result, result)
+          called2 = true
+        end
+        @my_result.add_assertion
+        assert_equal([true, true], [called1, called2])
+
+        called1, called2 = false, false
+        @my_result.add_failure("")
+        assert_equal([true, true], [called1, called2])
+
+        called1, called2 = false, false
+        @my_result.add_error("")
+        assert_equal([true, true], [called1, called2])
+
+        called1, called2 = false, false
+        @my_result.add_run
+        assert_equal([true, true], [called1, called2])
+      end
+
+      def test_fault_notification
+        called1 = false
+        fault = "fault"
+        @my_result.add_listener(TestResult::FAULT) do |passed_fault|
+          assert_equal(fault, passed_fault)
+          called1 = true
+        end
+
+        @my_result.add_assertion
+        assert_false(called1)
+
+        @my_result.add_failure(fault)
+        assert_true(called1)
+
+        called1, called2 = false, false
+        @my_result.add_listener(TestResult::FAULT) do |passed_fault|
+          assert_equal(fault, passed_fault)
+          called2 = true
+        end
+
+        @my_result.add_assertion
+        assert_equal([false, false], [called1, called2])
+
+        called1, called2 = false, false
+        @my_result.add_failure(fault)
+        assert_equal([true, true], [called1, called2])
+
+        called1, called2 = false, false
+        @my_result.add_error(fault)
+        assert_equal([true, true], [called1, called2])
+
+        called1, called2 = false, false
+        @my_result.add_run
+        assert_equal([false, false], [called1, called2])
+      end
+
+      def test_passed?
+        result = TestResult.new
+        assert_true(result.passed?)
+
+        result.add_assertion
+        assert_true(result.passed?)
+
+        result.add_run
+        assert_true(result.passed?)
+
+        result.add_failure("")
+        assert_false(result.passed?)
+
+        result = TestResult.new
+        result.add_error("")
+        assert_false(result.passed?)
+      end
+
+      def test_faults
+        assert_equal([@failure, @error], @my_result.faults)
+
+        notification = "notification"
+        @my_result.add_notification(notification)
+        assert_equal([@failure, @error, notification], @my_result.faults)
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/test_testsuite.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/test_testsuite.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/test_testsuite.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,129 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+  module Unit
+    class TC_TestSuite < TestCase
+      def setup
+        @testcase1 = Class.new(TestCase) do
+          def test_succeed1
+            assert_block { true }
+          end
+          def test_fail
+            assert_block { false }
+          end
+        end
+
+        @testcase2 = Class.new(TestCase) do
+          def test_succeed2
+            assert_block { true }
+          end
+          def test_error
+            raise
+          end
+        end
+      end
+
+      def test_add
+        s = TestSuite.new
+        assert_equal(s, s << self.class.new("test_add"))
+      end
+
+      def test_delete
+        s = TestSuite.new
+        t1 = self.class.new("test_delete")
+        s << t1
+        t2 = self.class.new("test_add")
+        s << t2
+        assert_equal(t1, s.delete(t1))
+        assert_nil(s.delete(t1))
+        assert_equal(TestSuite.new << t2, s)
+      end
+
+      def test_size
+        suite = TestSuite.new
+        suite2 = TestSuite.new
+        suite2 << self.class.new("test_size")
+        suite << suite2
+        suite << self.class.new("test_size")
+        assert_equal(2, suite.size, "The count should be correct")
+      end
+      
+      def test_run
+        progress = []
+        suite = @testcase1.suite
+        result = TestResult.new
+        suite.run(result) { |*values| progress << values }
+  
+        assert_equal(2, result.run_count, "Should have had four test runs")
+        assert_equal(1, result.failure_count, "Should have had one test failure")
+        assert_equal(0, result.error_count, "Should have had one test error")
+        assert_equal([[TestSuite::STARTED, suite.name],
+                [TestCase::STARTED, "test_fail(#{suite.name})"],
+                [TestCase::FINISHED, "test_fail(#{suite.name})"],
+                [TestCase::STARTED, "test_succeed1(#{suite.name})"],
+                [TestCase::FINISHED, "test_succeed1(#{suite.name})"],
+                [TestSuite::FINISHED, suite.name]],
+                progress, "Should have had the correct progress")
+        
+        suite = TestSuite.new
+        suite << @testcase1.suite
+        suite << @testcase2.suite
+        result = TestResult.new
+        progress = []
+        suite.run(result) { |*values| progress << values }
+  
+        assert_equal(4, result.run_count, "Should have had four test runs")
+        assert_equal(1, result.failure_count, "Should have had one test failure")
+        assert_equal(1, result.error_count, "Should have had one test error")
+        assert_equal(14, progress.size, "Should have had the correct number of progress calls")
+      end
+      
+      def test_empty?
+        assert(TestSuite.new.empty?, "A new test suite should be empty?")
+        assert(!@testcase2.suite.empty?, "A test suite with tests should not be empty")
+      end
+      
+      def test_equality
+        suite1 = TestSuite.new
+        suite2 = TestSuite.new
+        assert_equal(suite1, suite2)
+        assert_equal(suite2, suite1)
+        
+        suite1 = TestSuite.new('name')
+        assert_not_equal(suite1, suite2)
+        assert_not_equal(suite2, suite1)
+        
+        suite2 = TestSuite.new('name')
+        assert_equal(suite1, suite2)
+        assert_equal(suite2, suite1)
+        
+        suite1 << 'test'
+        assert_not_equal(suite1, suite2)
+        assert_not_equal(suite2, suite1)
+        
+        suite2 << 'test'
+        assert_equal(suite1, suite2)
+        assert_equal(suite2, suite1)
+        
+        suite2 = Object.new
+        class << suite2
+          def name
+            'name'
+          end
+          def tests
+            ['test']
+          end
+        end
+        assert_not_equal(suite1, suite2)
+        assert_not_equal(suite2, suite1)
+
+        assert_not_equal(suite1, Object.new)
+        assert_not_equal(Object.new, suite1)
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/testunit-test-util.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/testunit-test-util.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/testunit-test-util.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,14 @@
+module TestUnitTestUtil
+  private
+  def assert_fault_messages(expected, faults)
+    assert_equal(expected, faults.collect {|fault| fault.message})
+  end
+
+  def _run_test(test_case, name)
+    result = Test::Unit::TestResult.new
+    test = test_case.new(name)
+    yield(test) if block_given?
+    test.run(result) {}
+    result
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/ui/test_testrunmediator.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/ui/test_testrunmediator.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/ui/test_testrunmediator.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,20 @@
+require 'test/unit/ui/testrunnermediator'
+
+class TestUnitUIMediator < Test::Unit::TestCase
+  def test_run_suite_with_interrupt_exception
+    test_case = Class.new(Test::Unit::TestCase) do
+      def test_raise_interrupt
+        raise Interrupt, "from test"
+      end
+    end
+    mediator = Test::Unit::UI::TestRunnerMediator.new(test_case.suite)
+    finished = false
+    mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED) do
+      finished = true
+    end
+    assert_raise(Interrupt) do
+      mediator.run_suite
+    end
+    assert(finished)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/util/test-method-owner-finder.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/util/test-method-owner-finder.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/util/test-method-owner-finder.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,38 @@
+require 'test/unit'
+
+require 'test/unit/util/method-owner-finder'
+
+class TestUnitMethodOwnerFinder < Test::Unit::TestCase
+  def test_find
+    assert_equal(Exception, find(RuntimeError.new, :inspect))
+    assert_equal(Exception, find(Exception.new, :inspect))
+
+    anonymous_class = Class.new do
+    end
+    assert_equal(Kernel, find(anonymous_class.new, :inspect))
+
+    anonymous_parent_class = Class.new do
+      def inspect
+        super + " by anonymous parent class"
+      end
+    end
+    anonymous_sub_class = Class.new(anonymous_parent_class) do
+    end
+    assert_equal(anonymous_parent_class, find(anonymous_sub_class.new, :inspect))
+
+    anonymous_module = Module.new do
+      def inspect
+        super + " by anonymous module"
+      end
+    end
+    anonymous_include_class = Class.new do
+      include anonymous_module
+    end
+    assert_equal(anonymous_module, find(anonymous_include_class.new, :inspect))
+  end
+
+  private
+  def find(object, method_name)
+    Test::Unit::Util::MethodOwnerFinder.find(object, method_name)
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/util/test_backtracefilter.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/util/test_backtracefilter.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/util/test_backtracefilter.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,41 @@
+require 'test/unit'
+
+require 'test/unit/util/backtracefilter'
+
+module Test::Unit::Util
+  class TestBacktraceFilter < Test::Unit::TestCase
+    include BacktraceFilter
+    
+    def test_filter_backtrace
+      backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
+        %q{tc_thing.rb:4:in 'a'},
+        %q{tc_thing.rb:4:in 'test_stuff'},
+        %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'},
+        %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'},
+        %q{C:\some\old\path\test\unit.rb:44:in 'run'},
+        %q{tc_thing.rb:3}]
+      assert_equal(backtrace[1..2], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
+
+backtrace = [%q{tc_thing.rb:4:in 'a'},
+        %q{tc_thing.rb:4:in 'test_stuff'},
+        %q{tc_thing.rb:3}]
+      assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Shouldn't filter too much")
+
+      backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
+        %q{tc_thing.rb:4:in 'a'},
+        %q{tc_thing.rb:4:in 'test_stuff'},
+        %q{tc_thing.rb:3}]
+      assert_equal(backtrace[1..3], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
+      
+      backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
+        %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'},
+        %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'},
+        %q{C:\some\old\path\test\unit.rb:44:in 'run'}]
+      assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
+    end
+
+    def test_nil_backtrace
+      assert_equal(["No backtrace"], filter_backtrace(nil))
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/util/test_observable.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/util/test_observable.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/util/test_observable.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,102 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/observable'
+
+module Test
+  module Unit
+    module Util
+      class TC_Observable < TestCase
+      
+        class TF_Observable
+          include Observable
+        end
+        
+        def setup
+          @observable = TF_Observable.new
+        end
+        
+        def test_simple_observation
+          assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do
+            @observable.add_listener(:property, "a")
+          end
+      
+          heard = false
+          callback = proc { heard = true }
+          assert_equal("a", @observable.add_listener(:property, "a", &callback), "add_listener should return the listener that was added")
+      
+          count = 0
+          @observable.instance_eval do
+            count = notify_listeners(:property)
+          end
+          assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified")
+          assert(heard, "Should have heard the property changed")
+      
+          heard = false
+          assert_equal(callback, @observable.remove_listener(:property, "a"), "remove_listener should return the callback")
+          
+          count = 1
+          @observable.instance_eval do
+            count = notify_listeners(:property)
+          end
+          assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified")
+          assert(!heard, "Should not have heard the property change")
+        end
+        
+        def test_value_observation
+          value = nil
+          @observable.add_listener(:property, "a") do |passed_value|
+            value = passed_value
+          end
+          count = 0
+          @observable.instance_eval do
+            count = notify_listeners(:property, "stuff")
+          end
+          assert_equal(1, count, "Should have update the correct number of listeners")
+          assert_equal("stuff", value, "Should have received the value as an argument to the listener")
+        end
+        
+        def test_multiple_value_observation
+          values = []
+          @observable.add_listener(:property, "a") do |first_value, second_value|
+            values = [first_value, second_value]
+          end
+          count = 0
+          @observable.instance_eval do
+            count = notify_listeners(:property, "stuff", "more stuff")
+          end
+          assert_equal(1, count, "Should have update the correct number of listeners")
+          assert_equal(["stuff", "more stuff"], values, "Should have received the value as an argument to the listener")
+        end
+        
+        def test_add_remove_with_default_listener
+          assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do
+            @observable.add_listener(:property)
+          end
+      
+          heard = false
+          callback = proc { heard = true }
+          assert_equal(callback, @observable.add_listener(:property, &callback), "add_listener should return the listener that was added")
+      
+          count = 0
+          @observable.instance_eval do
+            count = notify_listeners(:property)
+          end
+          assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified")
+          assert(heard, "Should have heard the property changed")
+      
+          heard = false
+          assert_equal(callback, @observable.remove_listener(:property, callback), "remove_listener should return the callback")
+      
+          count = 1
+          @observable.instance_eval do
+            count = notify_listeners(:property)
+          end
+          assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified")
+          assert(!heard, "Should not have heard the property change")
+        end
+      end
+    end
+  end
+end

Added: MacRuby/trunk/test/libs/test-unit/test/util/test_procwrapper.rb
===================================================================
--- MacRuby/trunk/test/libs/test-unit/test/util/test_procwrapper.rb	                        (rev 0)
+++ MacRuby/trunk/test/libs/test-unit/test/util/test_procwrapper.rb	2009-09-14 16:45:55 UTC (rev 2550)
@@ -0,0 +1,36 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/util/procwrapper'
+
+module Test
+  module Unit
+    module Util
+      class TC_ProcWrapper < TestCase
+        def munge_proc(&a_proc)
+          return a_proc
+        end
+        def setup
+          @original = proc {}
+          @munged = munge_proc(&@original)
+          @wrapped_original = ProcWrapper.new(@original)
+          @wrapped_munged = ProcWrapper.new(@munged)
+        end
+        def test_wrapping
+          assert_same(@original, @wrapped_original.to_proc, "The wrapper should return what was wrapped")
+        end
+        def test_hashing
+      
+          assert_equal(@wrapped_original.hash, @wrapped_munged.hash, "The original and munged should have the same hash when wrapped")
+          assert_equal(@wrapped_original, @wrapped_munged, "The wrappers should be equivalent")
+          
+          a_hash = {@wrapped_original => @original}
+          assert(a_hash[@wrapped_original], "Should be able to access the wrapper in the hash")
+          assert_equal(a_hash[@wrapped_original], @original, "Should be able to access the wrapper in the hash")
+        end
+      end
+    end
+  end
+end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090914/436d1247/attachment-0001.html>


More information about the macruby-changes mailing list