Skip to content

Commit

Permalink
Showing 448 changed files with 9,352 additions and 6,418 deletions.
72 changes: 38 additions & 34 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,54 +1,58 @@
language: cpp

compiler:
- gcc
- clang

- clang
before_install:
- echo $LANG
- echo $LC_ALL
- if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update && sudo apt-get install -y llvm-3.4 llvm-3.4-dev; fi
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install llvm && brew link --force llvm; fi
- rvm use $RVM --install --binary --fuzzy
- gem update --system
- gem --version

- echo $LANG
- echo $LC_ALL
- if [ $TRAVIS_OS_NAME == linux ]; then ./scripts/llvm.sh; fi
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install llvm35 && brew link --force llvm35; fi
- rvm use $RVM --install --binary --fuzzy
- gem update --system
- gem --version
before_script:
- travis_retry bundle
- if [ $TRAVIS_OS_NAME == linux ]; then travis_retry ./configure --llvm-config llvm-config-3.4; fi
- if [ $TRAVIS_OS_NAME == osx ]; then travis_retry ./configure --llvm-config /usr/local/opt/llvm/bin/llvm-config; fi

- travis_retry bundle
- if [ $TRAVIS_OS_NAME == linux ]; then travis_retry ./configure --llvm-config=./vendor/llvm/Release/bin/llvm-config; fi
- if [ $TRAVIS_OS_NAME == osx ]; then travis_retry ./configure; fi
script: rake ci

after_success:
- if [ $TRAVIS_BRANCH == $TRAVIS_TAG ]; then rake deploy; fi

- if [ $TRAVIS_BRANCH == $TRAVIS_TAG ]; then ./scripts/deploy.sh all; fi
branches:
only:
- master
- 1.8.7
- 2.2
- /^v\d+\./

- master
- 1.8.7
- 2.2
- "/^v\\d+\\./"
notifications:
email: false
irc:
channels:
- "chat.freenode.net#rubinius"
- chat.freenode.net#rubinius
template:
- "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}"
- "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}"
webhooks:
urls:
- https://webhooks.gitter.im/e/9502afd22ca6c8e85fb3
- https://webhooks.gitter.im/e/9502afd22ca6c8e85fb3
on_success: change
on_failure: always
on_start: always

matrix:
exclude:
- compiler: clang
- os: linux
- os: osx
include:
- env: RVM=rbx-2
os: osx
- env: RVM=2.2.0
os: linux
compiler: clang
env:
- RVM=2.0.0 LANG="en_US.UTF-8"

global:
- LANG="en_US.UTF-8"
- secure: olbok/GN6rOYvPnHBYWGz7giCoCdLFpT/7WSBHukYO3E0uNeqAUOOgW2BFOwCVWdSEJ/iTvJXZQ4qVZHX+6jRfvILZeGv+D2P93VdD8UFQRoTOfFC7esAo525s9fuKm9ehUGWZxlzGOBHHckky1jn6pEf8mlXAVM5e76dlH0fck=
- secure: aqG9eB/PrzQ7XJQN6YX/00sNVvwSB77saxXQzguL2WFjAXB74h6168Hzq+awHtNX/vfOb6ta7fpWLHrA0D+gmZnvTR29VlP6nd0vs1tkdX1/jWbiBHjamRffp+NWVdKbJKYn5iLOGXcuUMOzY/opLKOdvxKZfkxGMxR2tTNLZUE=
- secure: eElvNLjuFZAuixJdgom4Kv8RDziE4ArFcSEwYctvprMe/414CAaJcFkjQKg0RrJzAxZ51oGjdcZhEfmjNXcUU1gA5l++IdnlQm0x4kt8r7aql+q2geHzrrjhhwPujT9a8JNtXs6dHnbi+quNlxyVItWzeGJsjyhJzH8hxiFhCYI=
os:
- linux
# - osx

osx_image: xcode61
- linux
- osx
sudo: false
27 changes: 27 additions & 0 deletions BSD_LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
BSD 3-clause License

Copyright (c) 2007-2015, Evan Phoenix and contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Rubinius nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -27,6 +27,27 @@ Gist:
These two files contain the output of the compilation process and the various
configuration options used (e.g. compiler options).

### Version Managers

We can *not* help you with any issues that might be caused by a Ruby version
manager. In the event of any issues please try building from source instead to
see if the issue is caused by Rubinius itself or your version manager of choice.

Issues involving version managers will be closed if they can either not be
reproduced when building from source, or when the original report makes no
mention about the author having tried building from source.

Note that this only applies to the installation procedure. Problems with the
runtime can of course still be reported, even when using a version manager.

### Rubinius Versions

Rubinius releases quite often, at least more often than most other
implementations. As such we ask users to try out the latest version prior to
reporting an issue. This ensures we don't have to start digging through the
code, only to find out the problem has already been resolved in a more recent
release.

### Running Specs

MSpec provides several different scripts to run the specs under different
2 changes: 1 addition & 1 deletion Gemfile.installed
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ gem "racc", "~> 1.4"
gem "rake", "~> 10.1"
gem "json", "~> 1.8"
gem "rdoc", "~> 4.0"
gem "psych", "= 2.0.10"
gem "psych", "= 2.0.17"

gem "rb-readline", "~> 0.5"
gem "rubysl-readline", "~> 2.0"
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -27,3 +27,6 @@ DEPENDENCIES
redcard (~> 1.0)
rubinius-bridge (~> 1.0)
rubinius-build_tools (~> 2.0)

BUNDLED WITH
1.11.2
389 changes: 364 additions & 25 deletions LICENSE

Large diffs are not rendered by default.

32 changes: 19 additions & 13 deletions README
Original file line number Diff line number Diff line change
@@ -11,10 +11,15 @@ Rubinius runs on Mac OS X and many Unix/Linux operating systems. Microsoft
Windows is not yet supported.


2. The Ruby Programming Language
2. Code of Conduct

Participation in the Rubinius project is governed by the Rubinius Code of
Conduct. See http://rubinius.com/code-of-conduct/

3. The Ruby Programming Language

Many popular Ruby applications, like Rails, run on Rubinius, which aims to be
compatible with Ruby version 2.1.
compatible with Ruby version 2.2.

Rubinius includes a Ruby parser, Ruby bytecode compiler, Ruby core library,
and C-API compatibility for native C extensions. The Ruby core library is
@@ -33,12 +38,13 @@ The following Ruby features are not supported on Rubinius:
* $SAFE levels


3. License

Rubinius uses the BSD license. See LICENSE for details.
4. License

Rubinius uses the MPL-2.0 license. See LICENSE for details. Contributions made
prior to January 3rd, 2016 are licensed under the old BSD 3-clause license. A
copy of this license can be found in the file "BSD_LICENSE".

4. Installing Rubinius from Source
5. Installing Rubinius from Source

To install Rubinius, use the following steps:

@@ -51,25 +57,25 @@ To install Rubinius, use the following steps:

When the install process finishes, follow the directions printed to the
terminal to add the Rubinius executable (bin) directory to your PATH. For more
information see http://rubini.us/doc/en/getting-started/requirements/
and http://rubini.us/doc/en/getting-started/building/.
information see http://rubinius.com/doc/en/getting-started/requirements/
and http://rubinius.com/doc/en/getting-started/building/.


5. Using RubyGems
6. Using RubyGems

Rubinius comes with RubyGems built-in. To install a gem, run the following:

$ rbx -S gem install <gem_name>


6. Documentation
7. Documentation

The Rubinius documentation is available at the Rubinius website:

http://rubini.us
http://rubinius.com


7. Issues & Support
8. Issues & Support

Please file tickets for bugs or problems. The issue tracker is:

@@ -80,7 +86,7 @@ For additional help, visit the Rubinius Gitter chat room:
https://gitter.im/rubinius/rubinius


8. Contributing
9. Contributing

The Rubinius team welcomes contributions. For more information, read the
CONTRIBUTING file in the root directory of Rubinius.
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -9,10 +9,15 @@ Rubinius includes a bytecode virtual machine, generational garbage collector, an
Rubinius runs on Mac OS X and many Unix/Linux operating systems. Microsoft Windows is not yet supported.


### Code of Conduct

Participation in the Rubinius project is governed by the Rubinius [Code of
Conduct](http://rubinius.com/code-of-conduct/).

### The Ruby Programming Language

Many popular Ruby applications, like Rails, run on Rubinius, which aims to be
compatible with Ruby version 2.1.
compatible with Ruby version 2.2.

Rubinius includes a Ruby parser, Ruby bytecode compiler, Ruby core library,
and C-API compatibility for native C extensions. The Ruby core library is
@@ -33,8 +38,9 @@ The following Ruby features are not supported on Rubinius:

### License

Rubinius uses the BSD license. See LICENSE for details.

Rubinius uses the MPL-2.0 license. See LICENSE for details. Contributions made
prior to January 3rd, 2016 are licensed under the old BSD 3-clause license. A
copy of this license can be found in the file "BSD_LICENSE".

### Installing Rubinius from Source

@@ -47,7 +53,7 @@ To install Rubinius, use the following steps:
1. ./configure --prefix=/path/to/install/dir
1. rake

When the install process finishes, follow the directions printed to the terminal to add the Rubinius executable (bin) directory to your PATH. For more information see the documentation for [Build Requirements](http://rubini.us/doc/en/getting-started/requirements/) and [Building Rubinius](http://rubini.us/doc/en/getting-started/building/).
When the install process finishes, follow the directions printed to the terminal to add the Rubinius executable (bin) directory to your PATH. For more information see the documentation for [Build Requirements](http://rubinius.com/doc/en/getting-started/requirements/) and [Building Rubinius](http://rubinius.com/doc/en/getting-started/building/).


### Using RubyGems
@@ -59,7 +65,7 @@ Rubinius comes with RubyGems built-in. To install a gem, run the following:

### Documentation

The Rubinius documentation is available at the [Rubinius website](http://rubini.us).
The Rubinius documentation is available at the [Rubinius website](http://rubinius.com).


### Issues & Support
@@ -72,4 +78,4 @@ For additional help, visit the [Rubinius Gitter chat room](https://gitter.im/rub
### Contributing

The Rubinius team welcomes contributions. For more information, read the
[CONTRIBUTING](https://github.com/rubinius/rubinius/blob/master/CONTRIBUTING.md) file and see the documentation [about contributing](http://rubini.us/doc/en/contributing/).
[CONTRIBUTING](https://github.com/rubinius/rubinius/blob/master/CONTRIBUTING.md) file and see the documentation [about contributing](http://rubinius.com/doc/en/contributing/).
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -94,7 +94,7 @@ class SpecRunner
end

def self.set_at_exit_status(status)
@at_exit_status = status
@at_exit_status = status || 1
end

def self.flags
101 changes: 92 additions & 9 deletions configure
Original file line number Diff line number Diff line change
@@ -136,6 +136,7 @@ class Configure
"rubysl-etc",
"rubysl-fcntl",
"rubysl-fileutils",
"rubysl-io-nonblock",
"rubysl-monitor",
"rubysl-openssl",
"rubysl-optparse",
@@ -161,7 +162,7 @@ class Configure
@vendored_libdir = File.join(root, "/vendor")

# Ruby compatibility version
@ruby_version = "2.1.0"
@ruby_version = "2.2.0"
@ruby_libversion = @ruby_version.split(/\./)[0..1].join.to_i

# Configure settings
@@ -276,6 +277,11 @@ class Configure
@runtime_gems_dir ||= "#{@build_prefix}#{@runtimedir}/gems"
end

def add_opt_dir(dir)
@include_dirs << "#{dir}/include"
@lib_dirs << "#{dir}/lib" << "#{dir}/lib64"
end

def options
@options = Rubinius::Options.new "Usage: configure [options]", 30
o = @options
@@ -365,8 +371,7 @@ class Configure

o.on "--with-opt-dir", "DIR", "Add DIR/include and DIR/lib to include and library search paths" do |dir|
dir.split(File::PATH_SEPARATOR).each do |d|
@include_dirs << "#{d}/include"
@lib_dirs << "#{d}/lib" << "#{d}/lib64"
add_opt_dir(d)
end
end

@@ -577,8 +582,8 @@ class Configure
if macports?
config = macports_llvm_config
else
out = Bundler.with_clean_env { `brew list llvm | grep '/llvm-config$'` }
config = out.chomp if $?.success?
out = Bundler.with_clean_env { `brew --prefix llvm35` }.chomp
config = "#{out}/bin/llvm-config-3.5" if $?.success?
end
end
end
@@ -710,6 +715,14 @@ int main() { LLVMContext &Context = getGlobalContext(); }
check_tool_version @cc, '-dumpversion', [4, 1]
check_tool_version @cxx, '-dumpversion', [4, 1]

unless @cc == "clang" and @cxx == "clang++"
@log.deprecated <<-EOM
Support for compilers other than clang/clang++ is deprecated and will be
removed soon. If your platform does not have support for clang/clang++,
please notify us.
EOM
end

@make ||= ENV['MAKE'] || 'make'
@rake ||= ENV['RAKE'] || 'rake'
@tar ||= ENV['TAR'] || (@windows ? 'bsdtar' : 'tar')
@@ -1027,8 +1040,7 @@ int main() { return tgetnum(""); }

def detect_build_dirs
["/usr/local", "/opt/local", "/usr/pkg"].each do |dir|
@include_dirs << "#{dir}/include"
@lib_dirs << "#{dir}/lib" << "#{dir}/lib64"
add_opt_dir(dir)
end

@include_dirs = @include_dirs.select {|p| File.directory? p }
@@ -1165,7 +1177,7 @@ int main() { return tgetnum(""); }

def detect_features
# Default on *BSD is no execinfo
if RUBY_PLATFORM =~ /bsd/i and @features["execinfo"].configured.nil?
if @bsd and @features["execinfo"].configured.nil?
@features["execinfo"].configured = false
end

@@ -1230,6 +1242,46 @@ int main() { return tgetnum(""); }
@defines << "HAVE_GETTID"
end

if has_struct_member("stat", "st_atim", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_ATIM"
end

if has_struct_member("stat", "st_atimespec", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_ATIMESPEC"
end

if has_struct_member("stat", "st_atimensec", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_ATIMENSEC"
end

if has_struct_member("stat", "st_mtim", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_MTIM"
end

if has_struct_member("stat", "st_mtimespec", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_MTIMESPEC"
end

if has_struct_member("stat", "st_mtimensec", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_MTIMENSEC"
end

if has_struct_member("stat", "st_ctim", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_CTIM"
end

if has_struct_member("stat", "st_ctimespec", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_CTIMESPEC"
end

if has_struct_member("stat", "st_ctimensec", ["sys/stat.h"])
@defines << "HAVE_STRUCT_STAT_ST_CTIMENSEC"
end

if has_struct_member("stat", "st_birthtimespec", ["sys/stat.h"])
@defines << "HAVE_ST_BIRTHTIME"
end

# glibc has useless lchmod() so we don't try to use lchmod() on linux
if !@linux and has_function("lchmod", ["sys/stat.h", "unistd.h"])
@have_lchmod = true
@@ -1357,7 +1409,6 @@ int main() { return tgetnum(""); }
end

def process
set_host
set_system_commands

enable_features
@@ -1810,7 +1861,9 @@ int main() { return tgetnum(""); }
end

options
set_host
parse ARGV
detect_homebrew_openssl_lib
create_directories
check_tools
check_force_clean
@@ -1972,6 +2025,21 @@ Available commands are:
STDERR.puts message
end

DEPRECATION_HEADER =
"------------------------------ Deprecation notice ------------------------------"
DEPRECATION_FOOTER =
"--------------------------------------------------------------------------------"

def deprecated(message)
log DEPRECATION_HEADER, true
log message, true
log DEPRECATION_FOOTER, true

STDERR.puts DEPRECATION_HEADER
STDERR.puts message
STDERR.puts DEPRECATION_FOOTER
end

# Yields an IO for writing log messages.
def output
File.open @path, "a" do |f|
@@ -2009,6 +2077,21 @@ Available commands are:
fgrep llvm-config`.split
avail_binaries.reject { |fname| fname.include? 'libexec' }.last
end

# Returns true if the *brew* command is in the PATH and identifies
# itself with "Homebrew" when run interactively with -v argument.
def homebrew?
`echo quit | brew -v 2>&-`.start_with? 'Homebrew'
end

# Check if latest version of openssl is installed; if so, add to include
# and libs
def detect_homebrew_openssl_lib
if @darwin && homebrew? && (`brew list`.split("\n").include? 'openssl')
add_opt_dir(`brew --prefix openssl`.chomp)
end
end

end

STDOUT.sync = true
8 changes: 8 additions & 0 deletions dockerfiles/ubuntu/14.04/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM ubuntu:14.04

ADD https://rubinius-binaries-rubinius-com.s3-us-west-2.amazonaws.com/ubuntu/14.04/x86_64/rubinius-3.3.tar.bz2 /tmp/rubinius.tar.bz2
RUN apt-get -y install bzip2 && cd /opt && tar xvjf /tmp/rubinius.tar.bz2

ENV PATH /opt/rubinius/3.3/bin:/opt/rubinius/3.3/gems/bin:$PATH

CMD ["bash"]
8 changes: 8 additions & 0 deletions dockerfiles/ubuntu/15.10/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM ubuntu:15.10

ADD https://rubinius-binaries-rubinius-com.s3-us-west-2.amazonaws.com/ubuntu/15.10/x86_64/rubinius-3.3.tar.bz2 /tmp/rubinius.tar.bz2
RUN apt-get -y install bzip2 && cd /opt && tar xvjf /tmp/rubinius.tar.bz2

ENV PATH /opt/rubinius/3.3/bin:/opt/rubinius/3.3/gems/bin:$PATH

CMD ["bash"]
21 changes: 11 additions & 10 deletions gems_list.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
bundler-1.9.8.gem
bundler-1.11.2.gem
daedalus-core-0.5.0.gem
ffi2-generators-0.1.1.gem
json-1.8.2.gem
json-1.8.3.gem
minitest-4.7.5.gem
psych-2.0.10.gem
racc-1.4.12.gem
psych-2.0.17.gem
racc-1.4.14.gem
rake-10.4.2.gem
rb-readline-0.5.2.gem
rdoc-4.2.0.gem
rb-readline-0.5.3.gem
rdoc-4.2.1.gem
redcard-1.1.0.gem
rubinius-ast-2.3.2.gem
rubinius-bridge-1.1.0.gem
rubinius-build_tools-2.0.0.gem
rubinius-compiler-2.3.1.gem
rubinius-coverage-2.0.3.gem
@@ -25,7 +26,7 @@ rubysl-base64-2.0.0.gem
rubysl-benchmark-2.0.1.gem
rubysl-bigdecimal-2.0.2.gem
rubysl-cgi-2.0.1.gem
rubysl-cgi-session-2.0.1.gem
rubysl-cgi-session-2.1.0.gem
rubysl-cmath-2.0.0.gem
rubysl-complex-2.0.0.gem
rubysl-continuation-2.0.0.gem
@@ -71,9 +72,9 @@ rubysl-nkf-2.0.1.gem
rubysl-observer-2.0.0.gem
rubysl-open-uri-2.0.0.gem
rubysl-open3-2.0.0.gem
rubysl-openssl-2.3.0.gem
rubysl-openssl-2.8.0.gem
rubysl-optparse-2.0.1.gem
rubysl-ostruct-2.0.4.gem
rubysl-ostruct-2.1.0.gem
rubysl-pathname-2.1.0.gem
rubysl-prettyprint-2.0.3.gem
rubysl-prime-2.0.1.gem
@@ -92,7 +93,7 @@ rubysl-securerandom-2.0.0.gem
rubysl-set-2.0.1.gem
rubysl-shellwords-2.0.0.gem
rubysl-singleton-2.0.0.gem
rubysl-socket-2.0.1.gem
rubysl-socket-2.1.0.gem
rubysl-stringio-2.0.0.gem
rubysl-strscan-2.0.0.gem
rubysl-sync-2.0.0.gem
5 changes: 5 additions & 0 deletions kernel/bootstrap/stat.rb
Original file line number Diff line number Diff line change
@@ -87,6 +87,11 @@ def ctime
raise PrimitiveFailure, "Rubinius::Stat#ctime primitive failed"
end

def birthtime
Rubinius.primitive :stat_birthtime
raise NotImplementedError, "birthtime() function is unimplemented on this machine"
end

def inspect
"#<#{self.class.name} dev=0x#{self.dev.to_s(16)}, ino=#{self.ino}, " \
"mode=#{sprintf("%07d", self.mode.to_s(8).to_i)}, nlink=#{self.nlink}, " \
2 changes: 2 additions & 0 deletions kernel/bootstrap/thunk.rb
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ def self.new(value)
Rubinius.primitive :thunk_create
raise PrimitiveFailure, "Thunk.new primitive failed"
end

attr_accessor :value
end

class CallUnit
68 changes: 49 additions & 19 deletions kernel/common/array.rb
Original file line number Diff line number Diff line change
@@ -993,7 +993,7 @@ def pack(directives)

def permutation(num=undefined, &block)
unless block_given?
return to_enum(:permutation, num) do
return to_enum(:permutation, num) do
Rubinius::Mirror::Array.reflect(self).permutation_size(num)
end
end
@@ -1365,28 +1365,38 @@ def sample(count=undefined, options=undefined)
else
if size / count > 3
abandon = false
spin = 0

result = Array.new count
i = 1

result[0] = rng.rand(size)
while i < count
k = rng.rand(size)
j = 0

while j < i
while k == result[j]
spin += 1
if spin > 100
spin = false
spin_count = 0

while true
j = 0
while j < i
if k == result[j]
spin = true
break
end

j += 1
end

if spin
if (spin_count += 1) > 100
abandon = true
break
end

k = rng.rand(size)
else
break
end
break if abandon

j += 1
end

break if abandon
@@ -1858,20 +1868,29 @@ def values_at(*args)

def zip(*others)
out = Array.new(size) { [] }
others = others.map do |ary|
if ary.respond_to?(:to_ary)
ary.to_ary
others = others.map do |other|
if other.respond_to?(:to_ary)
other.to_ary
else
elements = []
ary.each { |e| elements << e }
elements
other.to_enum :each
end
end

size.times do |i|
slot = out.at(i)
slot << @tuple.at(@start + i)
others.each { |ary| slot << ary.at(i) }
others.each do |other|
slot << case other
when Array
other.at i
else
begin
other.next
rescue StopIteration
nil
end
end
end
end

if block_given?
@@ -1943,9 +1962,20 @@ def recursively_flatten(array, out, max_levels = -1)
while i < total
o = tuple.at i

if ary = Rubinius::Type.check_convert_type(o, Array, :to_ary)
if Rubinius::Type.object_kind_of? o, Array
modified = true
recursively_flatten o, out, max_levels
elsif Rubinius::Type.object_respond_to? o, :to_ary
ary = o.__send__ :to_ary
if nil.equal? ary
out << o
else
modified = true
recursively_flatten ary, out, max_levels
end
elsif ary = Rubinius::Type.execute_check_convert_type(o, Array, :to_ary)
modified = true
recursively_flatten(ary, out, max_levels)
recursively_flatten ary, out, max_levels
else
out << o
end
8 changes: 6 additions & 2 deletions kernel/common/binding.rb
Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@ class Binding
attr_accessor :compiled_code
attr_accessor :constant_scope
attr_accessor :proc_environment
attr_accessor :self
attr_accessor :location
attr_accessor :receiver

def from_proc?
@proc_environment
@@ -29,7 +29,7 @@ def self.self_context(recv, variables)
def self.setup(variables, code, constant_scope, recv=nil, location=nil)
bind = allocate()

bind.self = self_context(recv, variables)
bind.receiver = self_context(recv, variables)
bind.variables = variables
bind.compiled_code = code
bind.constant_scope = constant_scope
@@ -54,4 +54,8 @@ def eval(expr, filename=nil, lineno=nil)

Kernel.eval(expr, self, filename, lineno)
end

def local_variables
variables.local_variables
end
end
14 changes: 8 additions & 6 deletions kernel/common/comparable.rb
Original file line number Diff line number Diff line change
@@ -2,14 +2,16 @@ module Comparable
def ==(other)
return true if equal?(other)

begin
unless comp = (self <=> other)
return false if Thread.detect_recursion(self, other) do
begin
unless comp = (self <=> other)
return false
end

return Comparable.compare_int(comp) == 0
rescue StandardError
return false
end

return Comparable.compare_int(comp) == 0
rescue StandardError, SystemStackError
return false
end
end

2 changes: 1 addition & 1 deletion kernel/common/complex.rb
Original file line number Diff line number Diff line change
@@ -277,7 +277,7 @@ def rationalize(eps = nil)
def to_s
result = real.to_s

if imag.kind_of?(Float) ? !imag.nan? && imag.negative? : imag < 0
if imag.kind_of?(Float) ? !imag.nan? && imag.signbit? : imag < 0
result << "-"
else
result << "+"
5 changes: 5 additions & 0 deletions kernel/common/dir.rb
Original file line number Diff line number Diff line change
@@ -174,6 +174,11 @@ def each
self
end

def fileno
Rubinius.primitive :dir_fileno
raise PrimitiveFailure, "Dir#fileno primitive failed"
end

attr_reader :path

alias_method :to_path, :path
368 changes: 223 additions & 145 deletions kernel/common/enumerable.rb

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions kernel/common/enumerator.rb
Original file line number Diff line number Diff line change
@@ -149,7 +149,7 @@ def rewind
end

def size
@size.kind_of?(Proc) ? @size.call : @size
@size.respond_to?(:call) ? @size.call : @size
end

def with_index(offset=0)
@@ -258,17 +258,20 @@ def take(n)
raise ArgumentError, "attempt to take negative size" if n < 0

current_size = enumerator_size
set_size = if current_size.kind_of?(Integer)
set_size = if current_size.kind_of?(Numeric)
n < current_size ? n : current_size
else
current_size
end

return to_enum(:cycle, 0).lazy if n.zero?

taken = 0
Lazy.new(self, set_size) do |yielder, *args|
if taken < n
yielder.yield(*args)
taken += 1
raise StopLazyError unless taken < n
else
raise StopLazyError
end
27 changes: 5 additions & 22 deletions kernel/common/eval.rb
Original file line number Diff line number Diff line change
@@ -31,6 +31,9 @@ def instance_eval(string=nil, filename="(eval)", line=1, &prc)
if string
raise ::ArgumentError, 'cannot pass both a block and a string to evaluate'
end

return prc.ruby_method.call(self) if prc.ruby_method

# Return a copy of the BlockEnvironment with the receiver set to self
env = prc.block

@@ -107,28 +110,8 @@ module Kernel
# Names of local variables at point of call (including evaled)
#
def local_variables
locals = []

scope = Rubinius::VariableScope.of_sender

# Ascend up through all applicable blocks to get all vars.
while scope
if scope.method.local_names
scope.method.local_names.each do |name|
locals << name
end
end

if dyn = scope.dynamic_locals
dyn.keys.each do |name|
locals << name unless locals.include?(name)
end
end

scope = scope.parent
end

locals
scope.local_variables
end
module_function :local_variables

@@ -173,7 +156,7 @@ def eval(string, binding=nil, filename=nil, lineno=nil)
c = Rubinius::ToolSets::Runtime::Compiler
be = c.construct_block string, binding, filename, lineno

result = be.call_on_instance(binding.self)
result = be.call_on_instance(binding.receiver)
binding.constant_scope = existing_scope
result
end
3 changes: 3 additions & 0 deletions kernel/common/exception.rb
Original file line number Diff line number Diff line change
@@ -213,6 +213,9 @@ def to_s
end
end

class UncaughtThrowError < ArgumentError
end

class IndexError < StandardError
end

134 changes: 83 additions & 51 deletions kernel/common/file.rb
Original file line number Diff line number Diff line change
@@ -103,6 +103,69 @@ def self.atime(path)
Stat.new(path).atime
end

##
# Returns the change time for the named file (the
# time at which directory information about the
# file was changed, not the file itself).
#
# File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
def self.ctime(path)
Stat.new(path).ctime
end

##
# Returns the birthtime for the named file
#
# Note this is not supported on all platforms.
# See stat(2) for more information.
def self.birthtime(path)
Stat.new(path).birthtime
end

##
# Returns the modification time for the named file as a Time object.
#
# File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
def self.mtime(path)
Stat.new(path).mtime
end

##
# Sets the access and modification times of each named
# file to the first two arguments. Returns the number
# of file names in the argument list.
# #=> Integer
def self.utime(a_in, m_in, *paths)
a_in ||= Time.now
a_in_usec = if a_in.is_a?(Time) || a_in.is_a?(Float) || a_in.is_a?(Rational)
Time.at(a_in).usec
else
0
end
m_in ||= Time.now
m_in_usec = if m_in.is_a?(Time) || m_in.is_a?(Float) || m_in.is_a?(Rational)
Time.at(m_in).usec
else
0
end

FFI::MemoryPointer.new(POSIX::TimeVal, 2) do |ptr|
atime = POSIX::TimeVal.new ptr
mtime = POSIX::TimeVal.new ptr[1]
atime[:tv_sec] = a_in.to_i
atime[:tv_usec] = a_in_usec

mtime[:tv_sec] = m_in.to_i
mtime[:tv_usec] = m_in_usec

paths.each do |path|

n = POSIX.utimes(Rubinius::Type.coerce_to_path(path), ptr)
Errno.handle unless n == 0
end
end
end

##
# Returns the last component of the filename given
# in file_name, which must be formed using forward
@@ -304,16 +367,6 @@ def self.lchown(owner, group, *paths)
paths.size
end

##
# Returns the change time for the named file (the
# time at which directory information about the
# file was changed, not the file itself).
#
# File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
def self.ctime(path)
Stat.new(path).ctime
end

##
# Returns true if the named file is a directory, false otherwise.
#
@@ -816,14 +869,6 @@ def self.lstat(path)
Stat.lstat path
end

##
# Returns the modification time for the named file as a Time object.
#
# File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
def self.mtime(path)
Stat.new(path).mtime
end

def self.path(obj)
return obj.to_path if obj.respond_to? :to_path

@@ -1072,31 +1117,6 @@ def self.unlink(*paths)
paths.size
end

##
# Sets the access and modification times of each named
# file to the first two arguments. Returns the number
# of file names in the argument list.
# #=> Integer
def self.utime(a_in, m_in, *paths)
a_in ||= Time.now
m_in ||= Time.now
FFI::MemoryPointer.new(POSIX::TimeVal, 2) do |ptr|
atime = POSIX::TimeVal.new ptr
mtime = POSIX::TimeVal.new ptr[1]
atime[:tv_sec] = a_in.to_i
atime[:tv_usec] = 0

mtime[:tv_sec] = m_in.to_i
mtime[:tv_usec] = 0

paths.each do |path|

n = POSIX.utimes(Rubinius::Type.coerce_to_path(path), ptr)
Errno.handle unless n == 0
end
end
end

def self.world_readable?(path)
path = Rubinius::Type.coerce_to_path path
return nil unless exist? path
@@ -1222,10 +1242,30 @@ def initialize(path_or_fd, mode=undefined, perm=undefined, options=undefined)

private :initialize

##
# see File.atime
def atime
Stat.new(@path).atime
end

##
# see File.ctime
def ctime
Stat.new(@path).ctime
end

##
# see File.birthtime
def birthtime
Stat.new(@path).birthtime
end

##
# see File.mtime
def mtime
Stat.new(@path).mtime
end

def reopen(other, mode = 'r+')
rewind unless closed?
unless other.kind_of? IO
@@ -1234,10 +1274,6 @@ def reopen(other, mode = 'r+')
super(other, mode)
end

def ctime
Stat.new(@path).ctime
end

def flock(const)
const = Rubinius::Type.coerce_to const, Integer, :to_int

@@ -1251,10 +1287,6 @@ def lstat
Stat.lstat @path
end

def mtime
Stat.new(@path).mtime
end

def stat
Stat.fstat @descriptor
end
36 changes: 32 additions & 4 deletions kernel/common/float.rb
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ def to_r
def arg
if nan?
self
elsif negative?
elsif signbit?
Math::PI
else
0
@@ -118,9 +118,9 @@ def abs

alias_method :magnitude, :abs

def negative?
Rubinius.primitive :float_negative
raise PrimitiveFailure, "Float#negative primitive failed"
def signbit?
Rubinius.primitive :float_signbit_p
raise PrimitiveFailure, "Float#signbit? primitive failed"
end

def +(other)
@@ -285,4 +285,32 @@ def floor
return int if self > 0 or self == int
return int - 1
end

def next_float
return NAN if self.nan?
return -MAX if self == -INFINITY
return INFINITY if self == MAX
return Math.ldexp(0.5, MIN_EXP - MANT_DIG + 1) if self.zero?

frac, exp = Math.frexp self

if frac == -0.5
frac *= 2
exp -= 1
end

smallest_frac = EPSILON / 2
smallest_frac = Math.ldexp(smallest_frac, MIN_EXP - exp) if exp < MIN_EXP

result_frac = frac + smallest_frac

return -0.0 if result_frac.zero? && frac < 0
return 0.0 if result_frac.zero? && frac > 0

return Math.ldexp result_frac, exp
end

def prev_float
return -(-self).next_float
end
end
24 changes: 12 additions & 12 deletions kernel/common/gc.rb
Original file line number Diff line number Diff line change
@@ -6,9 +6,9 @@ def self.count

def self.time
data = stat
data[:"gc.young.total.ms"] +
data[:"gc.immix.stop.total.ms"] +
data[:"gc.large.sweep.total.ms"]
data[:"gc.young.ms"] +
data[:"gc.immix.stop.ms"] +
data[:"gc.large.sweep.us"] * 1_000
end

def self.stat
@@ -54,22 +54,22 @@ def self.result
===================================
Collections
Count Total time / concurrent (ms) Last time / concurrent (ms)
Young #{sprintf("% 22d", stats[:'gc.young.count'])} #{sprintf("% 16d ", stats[:'gc.young.total.ms'])} #{sprintf("% 16d ", stats[:'gc.young.last.ms'])}
Full #{sprintf("% 22d", stats[:'gc.immix.count'])} #{sprintf("% 16d / % 10d", stats[:'gc.immix.stop.total.ms'], stats[:'gc.immix.concurrent.total.ms'])} #{sprintf("% 16d / % 10d", stats[:'gc.immix.stop.last.ms'], stats[:'gc.immix.concurrent.last.ms'])}
Count Total time / concurrent (ms)
Young #{sprintf("% 22d", stats[:'gc.young.count'])} #{sprintf("% 16d ", stats[:'gc.young.ms'])}
Full #{sprintf("% 22d", stats[:'gc.immix.count'])} #{sprintf("% 16d / % 10d", stats[:'gc.immix.stop.ms'], stats[:'gc.immix.concurrent.ms'])}
Allocation
Objects allocated Bytes allocated
Young #{sprintf("% 22d", stats[:'memory.young.objects.total'])} #{sprintf("% 22d", stats[:'memory.young.bytes.total'])}
Promoted#{sprintf("% 22d", stats[:'memory.promoted.objects.total'])} #{sprintf("% 22d", stats[:'memory.promoted.bytes.total'])}
Mature #{sprintf("% 22d", stats[:'memory.immix.objects.total'])} #{sprintf("% 22d", stats[:'memory.immix.bytes.total'])}
Young #{sprintf("% 22d", stats[:'memory.young.objects'])} #{sprintf("% 22d", stats[:'memory.young.bytes'])}
Promoted#{sprintf("% 22d", stats[:'memory.promoted.objects'])} #{sprintf("% 22d", stats[:'memory.promoted.bytes'])}
Mature #{sprintf("% 22d", stats[:'memory.immix.objects'])} #{sprintf("% 22d", stats[:'memory.immix.bytes'])}
Usage
Bytes used
Young #{sprintf("% 22d", stats[:'memory.young.bytes.current'])}
Mature #{sprintf("% 22d", stats[:'memory.immix.bytes.current'])}
Large #{sprintf("% 22d", stats[:'memory.large.bytes.current'])}
Young #{sprintf("% 22d", stats[:'memory.young.bytes'])}
Mature #{sprintf("% 22d", stats[:'memory.immix.bytes'])}
Large #{sprintf("% 22d", stats[:'memory.large.bytes'])}
Code #{sprintf("% 22d", stats[:'memory.code.bytes'])}
Symbols #{sprintf("% 22d", stats[:'memory.symbols.bytes'])}
OUT
20 changes: 18 additions & 2 deletions kernel/common/io.rb
Original file line number Diff line number Diff line change
@@ -14,6 +14,22 @@ class EAGAINWaitWritable < Errno::EAGAIN
include ::IO::WaitWritable
end

class EWOULDBLOCKWaitReadable < Errno::EAGAIN
include WaitReadable
end

class EWOULDBLOCKWaitWritable < Errno::EAGAIN
include WaitWritable
end

class EINPROGRESSWaitReadable < Errno::EINPROGRESS
include WaitReadable
end

class EINPROGRESSWaitWritable < Errno::EINPROGRESS
include WaitWritable
end

# Import platform constants

SEEK_SET = Rubinius::Config['rbx.platform.io.SEEK_SET']
@@ -1778,9 +1794,9 @@ def puts(*args)
str = ""
elsif Thread.guarding? arg
str = "[...]"
elsif arg.kind_of?(Array)
elsif arg.respond_to?(:to_ary)
Thread.recursion_guard arg do
arg.each do |a|
arg.to_ary.each do |a|
puts a
end
end
6 changes: 5 additions & 1 deletion kernel/common/marshal.rb
Original file line number Diff line number Diff line change
@@ -627,7 +627,8 @@ def construct_bignum

obj = result * sign

store_unique_object obj
add_object obj
obj
end

def construct_data
@@ -674,8 +675,11 @@ def construct_hash
store_unique_object obj

construct_integer.times do
original_modules = @modules
@modules = nil
key = construct
val = construct
@modules = original_modules

# Use __store__ (an alias for []=) to get around subclass overrides
obj.__store__ key, val
34 changes: 34 additions & 0 deletions kernel/common/method.rb
Original file line number Diff line number Diff line change
@@ -141,6 +141,12 @@ def to_proc
Proc.from_method self
end

##
# Calls curry on the method in proc representation
def curry(n = nil)
to_proc.curry(n)
end

##
# Detach this Method from the receiver object it is bound to and create an
# UnboundMethod object. Populates the UnboundMethod with the method data as
@@ -152,6 +158,20 @@ def unbind
UnboundMethod.new(@defined_in, @executable, @receiver.class, @name)
end

def super_method
superclass = @defined_in.direct_superclass

if superclass
mod, entry = superclass.lookup_method(@name)

if entry && entry.visibility != :undef
return Method.new(@receiver, superclass, entry.method, @name)
end
end

return nil
end

end

##
@@ -282,4 +302,18 @@ def owner
@defined_in
end
end

def super_method
superclass = @defined_in.direct_superclass

if superclass
mod, entry = superclass.lookup_method(@name)

if entry && entry.visibility != :undef
return UnboundMethod.new(superclass, entry.method, @defined_in, @name)
end
end

return nil
end
end
2 changes: 2 additions & 0 deletions kernel/common/module.rb
Original file line number Diff line number Diff line change
@@ -130,6 +130,7 @@ def constants(all=undefined)
end

def private_constant(*names)
names = names.map(&:to_sym)
unknown_constants = names - @constant_table.keys
if unknown_constants.size > 0
raise NameError, "#{unknown_constants.size > 1 ? 'Constants' : 'Constant'} #{unknown_constants.map{|e| "#{name}::#{e}"}.join(', ')} undefined"
@@ -141,6 +142,7 @@ def private_constant(*names)
end

def public_constant(*names)
names = names.map(&:to_sym)
unknown_constants = names - @constant_table.keys
if unknown_constants.size > 0
raise NameError, "#{unknown_constants.size > 1 ? 'Constants' : 'Constant'} #{unknown_constants.map{|e| "#{name}::#{e}"}.join(', ')} undefined"
14 changes: 1 addition & 13 deletions kernel/common/proc.rb
Original file line number Diff line number Diff line change
@@ -99,19 +99,7 @@ def curry(curried_arity = nil)

def source_location
if @ruby_method
code = @ruby_method.executable
if code.respond_to? :file
file = code.file
if code.lines
line = code.first_line
else
line = -1
end
else
file = "(unknown)"
line = -1
end
[file.to_s, line]
@ruby_method.source_location
elsif @bound_method
if @bound_method.respond_to?(:source_location)
@bound_method.source_location
3 changes: 1 addition & 2 deletions kernel/common/process_mirror.rb
Original file line number Diff line number Diff line change
@@ -185,8 +185,7 @@ def convert_to_fd(obj, target)
[obj[0], File::RDONLY, 0644]
when 2
if obj[0] == :child
fd = convert_to_fd obj[1], target
fd.kind_of?(::Fixnum) ? -(fd + 1) : fd
convert_to_fd obj[1], target
else
[obj[0], convert_file_mode(obj[1]), 0644]
end
44 changes: 22 additions & 22 deletions kernel/common/range.rb
Original file line number Diff line number Diff line change
@@ -51,47 +51,47 @@ def bsearch

last_true = nil

if max < 0 and min < 0
value = min + (max - min) / 2
elsif min < -max
value = -((-1 - min - max) / 2 + 1)
else
value = (min + max) / 2
end

while min < max
x = yield value
seeker = Proc.new do |current|
x = yield current

return value if x == 0
return current if x == 0

case x
when Numeric
if x > 0
min = value + 1
min = current + 1
else
max = value
max = current
end
when true
last_true = value
max = value
last_true = current
max = current
when false, nil
min = value + 1
min = current + 1
else
raise TypeError, "Range#bsearch block must return Numeric or boolean"
end
end

while min < max
if max < 0 and min < 0
value = min + (max - min) / 2
mid = min + (max - min) / 2
elsif min < -max
value = -((-1 - min - max) / 2 + 1)
mid = -((-1 - min - max) / 2 + 1)
else
value = (min + max) / 2
end
mid = (min + max) / 2
end

seeker.call mid
end

if min == max
seeker.call min
end

if min < max
return @begin if value == start
return @begin.kind_of?(Float) ? value.to_f : value
return @begin if mid == start
return @begin.kind_of?(Float) ? mid.to_f : mid
end

if last_true
2 changes: 2 additions & 0 deletions kernel/common/range_mirror.rb
Original file line number Diff line number Diff line change
@@ -17,6 +17,8 @@ def step_float_iterations_size(first, last, step_size)
else
iterations = ((last - first) / step_size + err).floor + 1
end

iterations
end

def step_iterations_size(first, last, step_size)
18 changes: 8 additions & 10 deletions kernel/common/regexp.rb
Original file line number Diff line number Diff line change
@@ -375,20 +375,18 @@ def parts

# TODO: audit specs for this method when specs are running
def create_parts
return unless @index < @source.size
char = @source[@index].chr
case char
when '('
idx = @index + 1
if idx < @source.size and @source[idx].chr == '?'
process_group
while @index < @source.size
if @source[@index].chr == '('
idx = @index + 1
if idx < @source.size and @source[idx].chr == '?'
process_group
else
push_current_character!
end
else
push_current_character!
end
else
push_current_character!
end
create_parts
end

def process_group
4 changes: 3 additions & 1 deletion kernel/common/splitter.rb
Original file line number Diff line number Diff line change
@@ -32,7 +32,9 @@ def self.split(string, pattern, limit)
return [string.dup] if limit == 1
limited = true
else
tail_empty = true
if limit < 0
tail_empty = true
end
limited = false
end
end
2 changes: 1 addition & 1 deletion kernel/common/struct.rb
Original file line number Diff line number Diff line change
@@ -209,7 +209,7 @@ def each

def each_pair
return to_enum(:each_pair) { size } unless block_given?
_attrs.each { |var| yield var, instance_variable_get(:"@#{var}") }
_attrs.each { |var| yield [var, instance_variable_get(:"@#{var}")] }
self
end

3 changes: 3 additions & 0 deletions kernel/common/symbol.rb
Original file line number Diff line number Diff line change
@@ -7,6 +7,9 @@ def <=>(other)
to_s <=> other.to_s
end

# Use equal? for == (and not Comparable version)
alias_method :==, :equal?

def capitalize
to_s.capitalize.to_sym
end
2 changes: 1 addition & 1 deletion kernel/common/thread_group.rb
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ def add(thread)
tm = Rubinius::Mirror.reflect thread
tm.group = self

@threads << thread
Rubinius.synchronize(@threads) { @threads << thread }

self
end
3 changes: 1 addition & 2 deletions kernel/common/thread_group_mirror.rb
Original file line number Diff line number Diff line change
@@ -5,9 +5,8 @@ class ThreadGroup < Mirror

def remove(thread)
ary = Rubinius.invoke_primitive :object_get_ivar, @object, :@threads
ary.delete thread
Rubinius.synchronize(ary) { ary.delete thread }
end

end
end
end
2 changes: 1 addition & 1 deletion kernel/common/throw_catch.rb
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ def catch(obj = Object.new, &block)

def throw(obj, value=nil)
unless Rubinius::ThrownValue.available? obj
raise ArgumentError, "uncaught throw #{obj.inspect}"
raise UncaughtThrowError, "uncaught throw #{obj.inspect}"
end

Rubinius.throw obj, value
26 changes: 26 additions & 0 deletions kernel/common/variable_scope.rb
Original file line number Diff line number Diff line change
@@ -101,6 +101,32 @@ def local_layout
out
end

# Returns the names of local variables available in this scope
#
def local_variables
locals = []
scope = self

# Ascend up through all applicable blocks to get all vars.
while scope
if scope.method.local_names
scope.method.local_names.each do |name|
locals << name
end
end

if dyn = scope.dynamic_locals
dyn.keys.each do |name|
locals << name unless locals.include?(name)
end
end

scope = scope.parent
end

locals
end

def exitted?
@exitted
end
7 changes: 7 additions & 0 deletions kernel/delta/deprecations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Rubinius
DEPRECATIONS = {
# "Description" => "Alternative"
"Ruby 2.1 features that are incompatible with Ruby 2.2 are deprecated." =>
"Use Ruby 2.2 features if they are available."
}
end
1 change: 1 addition & 0 deletions kernel/delta/load_order.txt
Original file line number Diff line number Diff line change
@@ -21,3 +21,4 @@ ruby_constants.rbc
pack.rbc
metrics.rbc
code_db.rbc
deprecations.rbc
3 changes: 3 additions & 0 deletions kernel/delta/module.rb
Original file line number Diff line number Diff line change
@@ -202,6 +202,9 @@ def prepend_features(klass)
im.superclass = klass.direct_superclass
klass.superclass = im
klass.origin = im
klass.method_table.each do |meth, obj, vis|
Rubinius::VM.reset_method_cache klass, meth
end
end
Rubinius::Type.include_modules_from(self, klass)
Rubinius::Type.infect(klass, self)
90 changes: 62 additions & 28 deletions kernel/loader.rb
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ def initialize
@load_profiler = false
@enable_gems = true
@load_gemfile = false
@deprecations = false

version = RUBY_VERSION.split(".").first(2).join(".")
@gem_bins = ["#{version}/bin", "bin"].map do |dir|
@@ -394,6 +395,10 @@ def options(argv=ARGV)
end
end

options.on "--deprecated", "Display any deprecations" do
@deprecations = true
end

options.on "--version", "Display the version" do
@repl = false
puts Rubinius.version
@@ -531,6 +536,27 @@ def load_paths
end
end

def deprecations
@stage = "showing deprecations"

return unless @deprecations

if Rubinius::DEPRECATIONS.size > 0
Rubinius::DEPRECATIONS.each do |desc, alt|
STDERR.puts <<-EOM
Deprecation: #{desc}
Alternative: #{alt}
EOM
end

exit 1
else
STDERR.puts "Rubinius #{Rubinius::VERSION} has no deprecation notices"
exit 0
end
end

def run_compiled
return unless ENV["RBX_RUN_COMPILED"]

@@ -718,6 +744,11 @@ def flush_stdio
STDERR.flush unless STDERR.closed?
end

def exit_with_exception(e)
@exit_code = 1
Rubinius::Logger.log_exception "An exception occurred #{@stage}", e
end

# Cleanup and at_exit processing.
def epilogue
@stage = "running at_exit handlers"
@@ -737,8 +768,7 @@ def epilogue
flush_stdio

rescue Object => e
Rubinius::Logger.log_exception "An exception occurred #{@stage}", e
@exit_code = 1
exit_with_exception e
end

# Exit.
@@ -790,6 +820,34 @@ def done
Process.exit! @exit_code
end

def handle_exception(e)
case e
when SystemExit
@exit_code = e.status
when SyntaxError
@exit_code = 1

show_syntax_error(e)

STDERR.puts "\nBacktrace:"
STDERR.puts
STDERR.puts e.awesome_backtrace.show
when Interrupt
exit_with_exception e
when SignalException
Signal.trap(e.signo, "SIG_DFL")
Process.kill e.signo, Process.pid
when nil
# what?
else
exit_with_exception e
end
rescue Object => e
exit_with_exception e
ensure
epilogue
end

# Orchestrate everything.
def main
preamble
@@ -801,6 +859,7 @@ def main
detect_alias
options
load_paths
deprecations
rubygems
gemfile
debugger
@@ -810,33 +869,8 @@ def main
script
repl

rescue SystemExit => e
@exit_code = e.status

epilogue
rescue SyntaxError => e
@exit_code = 1

show_syntax_error(e)

STDERR.puts "\nBacktrace:"
STDERR.puts
STDERR.puts e.awesome_backtrace.show
epilogue
rescue Interrupt => e
@exit_code = 1

Rubinius::Logger.log_exception "An exception occurred #{@stage}:", e
epilogue
rescue SignalException => e
Signal.trap(e.signo, "SIG_DFL")
Process.kill e.signo, Process.pid
epilogue
rescue Object => e
@exit_code = 1

Rubinius::Logger.log_exception "An exception occurred #{@stage}:", e
epilogue
handle_exception e
else
# We do this, run epilogue both in the rescue blocks and also here,
# so that at_exit{} hooks can read $!.
31 changes: 15 additions & 16 deletions kernel/platform/pointer.rb
Original file line number Diff line number Diff line change
@@ -253,6 +253,21 @@ def primitive_write_pointer(obj)
raise PrimitiveFailure, "FFI::Pointer#primitive_write_pointer primitive failed"
end

##
# If +val+ is true, this Pointer object will call
# free() on it's address when it is garbage collected.
def autorelease=(val)
Rubinius.primitive :pointer_set_autorelease
raise PrimitiveFailure, "FFI::Pointer#autorelease= primitive failed"
end

##
# Returns true if autorelease is enabled, otherwise false.
def autorelease?
Rubinius.primitive :pointer_autorelease_p
raise PrimitiveFailure, "FFI::Pointer#pointer_autorelease_p primitive failed"
end

NULL = Pointer.new(0x0)
end

@@ -370,22 +385,6 @@ def free
Rubinius.primitive :pointer_free
raise PrimitiveFailure, "FFI::MemoryPointer#free primitive failed"
end

##
# If +val+ is true, this MemoryPointer object will call
# free() on it's address when it is garbage collected.
def autorelease=(val)
Rubinius.primitive :pointer_set_autorelease
raise PrimitiveFailure, "FFI::MemoryPointer#autorelease= primitive failed"
end

##
# Returns true if autorelease is enabled, otherwise false.
def autorelease?
Rubinius.primitive :pointer_autorelease_p
raise PrimitiveFailure, "FFI::MemoryPointer#pointer_autorelease_p primitive failed"
end

end

class DynamicLibrary::Symbol < Pointer
39 changes: 15 additions & 24 deletions library/rubinius/configuration.rb
Original file line number Diff line number Diff line change
@@ -11,33 +11,15 @@
end

c.section "gc" do |s|
s.vm_variable "young_initial_bytes", 3145728,
"The initial number of bytes the young generation of the GC should use"

s.vm_variable "young_max_bytes", 5 * 3145728,
"The maximum number of bytes the young generation of the GC should use"

s.vm_variable "young_autotune_size", true,
"Set whether or not the young GC should autotune the size"

s.vm_variable "young_autotune_factor", 8,
"Set the young GC size autotune factor. This is the denominator of the fraction of total memory used for young GC"
s.vm_variable "young_bytes", (30 * 1024 * 1024),
"The number of bytes the young generation of the GC should use"

s.vm_variable "young_lifetime", 2,
"How many young GC cycles an object lives before promotion"

s.vm_variable "young_autotune_lifetime", true,
"Set whether or not the young GC should adjust promotion age for performance"

s.vm_variable "large_object", (50 * 1024),
s.vm_variable "large_object", (1024 * 1024),
"The size (in bytes) of the large object threshold"

s.vm_variable "show", :bool,
"Display information whenever the GC runs"

s.vm_variable "noisy", :bool,
"Beep whenever the GC runs (once for young, twice for mature). Requires gc.show"

s.vm_variable "immix.concurrent", true,
"Set whether we want the Immix mark phase to run concurrently"

@@ -50,10 +32,10 @@
s.vm_variable "autopack", true,
"Set whether or not objects should be packed tightly in memory"

s.vm_variable "marksweep_threshold", (10 * 1024 * 1024),
s.vm_variable "marksweep_threshold", (25 * 1024 * 1024),
"The number of bytes allocated before the marksweep GC region is collected"

s.vm_variable "malloc_threshold", 104857600,
s.vm_variable "malloc_threshold", (25 * 1024 * 1024),
"How many bytes allocated by C extensions til the GC is run"
end

@@ -192,14 +174,23 @@
s.vm_variable "log", "$TMPDIR/$PROGRAM_NAME-$USER.log",
"Logging facility to use: 'syslog', 'console', or path"

s.vm_variable "log.limit", (10 * 1024 * 1024),
"The maximum size of the log file before log rotation is performed"

s.vm_variable "log.archives", 5,
"The number of prior logs that will be saved as '$(system.log).N.Z' zip files"

s.vm_variable "log.access", 0600,
"Permissions on the log file"

s.vm_variable "log.level", "warn",
"Logging level: fatal, error, warn, info, debug"

s.vm_variable "metrics.interval", 10000,
"Number of milliseconds between aggregation of VM metrics"

s.vm_variable "metrics.target", "none",
"Location to send metrics every interval: 'statsd', 'disk'"
"Location to send metrics every interval: 'statsd', path"

s.vm_variable "metrics.statsd.server", "localhost:8125",
"The [host:]port of the StatsD server"
51 changes: 34 additions & 17 deletions library/rubygems.rb
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
require 'thread'

module Gem
VERSION = '2.4.6'
VERSION = '2.5.1'
end

# Must be first since it unloads the prelude from 1.9.2
@@ -26,12 +26,12 @@ module Gem
# 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]
# * {RubyGems User Guide}[http://guides.rubygems.org/]
# * {Frequently Asked Questions}[http://guides.rubygems.org/faqs]
#
# For gem developer documentation see:
#
# * {Creating Gems}[http://docs.rubygems.org/read/chapter/5]
# * {Creating Gems}[http://guides.rubygems.org/make-your-own-gem]
# * Gem::Specification
# * Gem::Version for version dependency notes
#
@@ -156,6 +156,7 @@ module Gem
@@win_platform = nil

@configuration = nil
@gemdeps = nil
@loaded_specs = {}
LOADED_SPECS_MUTEX = Mutex.new
@path_to_default_spec_map = {}
@@ -184,13 +185,9 @@ def self.try_activate path
# or if it was ambiguous (and thus unresolved) the code in our custom
# require will try to activate the more specific version.

spec = Gem::Specification.find_inactive_by_path path

unless spec
spec = Gem::Specification.find_by_path path
return true if spec && spec.activated?
return false
end
spec = Gem::Specification.find_by_path path
return false unless spec
return true if spec.activated?

begin
spec.activate
@@ -310,11 +307,10 @@ def self.configuration=(config)
# package is not available as a gem, return nil.

def self.datadir(gem_name)
# TODO: deprecate and move to Gem::Specification
# and drop the extra ", gem_name" which is uselessly redundant
# TODO: deprecate
spec = @loaded_specs[gem_name]
return nil if spec.nil?
File.join spec.full_gem_path, "data", gem_name
spec.datadir
end

##
@@ -433,7 +429,7 @@ def self.find_files(glob, check_load_path=true)

files = find_files_from_load_path glob if check_load_path

files.concat Gem::Specification.map { |spec|
files.concat Gem::Specification.stubs.map { |spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
}.flatten

@@ -580,6 +576,10 @@ def self.host= host
# gem's paths are inserted before site lib directory by default.

def self.load_path_insert_index
$LOAD_PATH.each_with_index do |path, i|
return i if path.instance_variable_defined?(:@gem_prelude_index)
end

index = $LOAD_PATH.index RbConfig::CONFIG['sitelibdir']

index
@@ -596,6 +596,9 @@ def self.load_yaml

test_syck = ENV['TEST_SYCK']

# Only Ruby 1.8 and 1.9 have syck
test_syck = false unless /^1\./ =~ RUBY_VERSION

unless test_syck
begin
gem 'psych', '>= 1.2.1'
@@ -777,6 +780,14 @@ def self.read_binary(path)
open path, 'rb' do |f|
f.read
end
rescue Errno::ENOLCK # NFS
if Thread.main != Thread.current
raise
else
open path, 'rb' do |f|
f.read
end
end
end

##
@@ -1052,7 +1063,7 @@ def self.use_gemdeps path = nil
end

rs = Gem::RequestSet.new
rs.load_gemdeps path
@gemdeps = rs.load_gemdeps path

rs.resolve_current.map do |s|
sp = s.full_spec
@@ -1082,6 +1093,12 @@ class << self

attr_reader :loaded_specs

##
# GemDependencyAPI object, which is set when .use_gemdeps is called.
# This contains all the information from the Gemfile.

attr_reader :gemdeps

##
# Register a Gem::Specification for default gem.
#
@@ -1196,6 +1213,7 @@ def clear_default_specs
autoload :DependencyList, 'rubygems/dependency_list'
autoload :DependencyResolver, 'rubygems/resolver'
autoload :Installer, 'rubygems/installer'
autoload :Licenses, 'rubygems/util/licenses'
autoload :PathSupport, 'rubygems/path_support'
autoload :Platform, 'rubygems/platform'
autoload :RequestSet, 'rubygems/request_set'
@@ -1242,4 +1260,3 @@ def clear_default_specs
require 'rubygems/core_ext/kernel_require'

Gem.use_gemdeps

135 changes: 87 additions & 48 deletions library/rubygems/basic_specification.rb
Original file line number Diff line number Diff line change
@@ -22,17 +22,29 @@ class Gem::BasicSpecification
##
# The path this gemspec was loaded from. This attribute is not persisted.

attr_reader :loaded_from
attr_accessor :loaded_from

##
# Allows correct activation of git: and path: gems.

attr_writer :full_gem_path # :nodoc:

def initialize
internal_init
end

def self.default_specifications_dir
File.join(Gem.default_dir, "specifications", "default")
end

##
# The path to the gem.build_complete file within the extension install
# directory.

def gem_build_complete_path # :nodoc:
File.join extension_dir, 'gem.build_complete'
end

##
# True when the gem has been activated

@@ -46,39 +58,24 @@ def activated?
# eg: /usr/local/lib/ruby/gems/1.8

def base_dir
return Gem.dir unless loaded_from
@base_dir ||= if default_gem? then
File.dirname File.dirname File.dirname loaded_from
else
File.dirname File.dirname loaded_from
end
raise NotImplementedError
end

##
# Return true if this spec can require +file+.

def contains_requirable_file? file
@contains_requirable_file ||= {}
@contains_requirable_file[file] ||=
begin
if instance_variable_defined?(:@ignored) then
return false
elsif missing_extensions? then
@ignored = true

warn "Ignoring #{full_name} because its extensions are not built. " +
"Try: gem pristine #{name} --version #{version}"
return false
end

suffixes = Gem.suffixes
if @ignored then
return false
elsif missing_extensions? then
@ignored = true

warn "Ignoring #{full_name} because its extensions are not built. " +
"Try: gem pristine #{name} --version #{version}"
return false
end

full_require_paths.any? do |dir|
base = "#{dir}/#{file}"
suffixes.any? { |suf| File.file? "#{base}#{suf}" }
end
end ? :yes : :no
@contains_requirable_file[file] == :yes
have_file? file, Gem.suffixes
end

def default_gem?
@@ -90,7 +87,7 @@ def default_gem?
# Returns full path to the directory where gem's extensions are installed.

def extension_dir
@extension_dir ||= File.expand_path File.join(extensions_dir, full_name)
@extension_dir ||= File.expand_path(File.join(extensions_dir, full_name)).untaint
end

##
@@ -106,7 +103,7 @@ def find_full_gem_path # :nodoc:
# TODO: also, shouldn't it default to full_name if it hasn't been written?
path = File.expand_path File.join(gems_dir, full_name)
path.untaint
path if File.directory? path
path
end

private :find_full_gem_path
@@ -141,15 +138,23 @@ def full_require_paths
@full_require_paths ||=
begin
full_paths = raw_require_paths.map do |path|
File.join full_gem_path, path
File.join full_gem_path, path.untaint
end

full_paths << extension_dir unless @extensions.nil? || @extensions.empty?
full_paths << extension_dir if have_extensions?

full_paths
end
end

##
# The path to the data directory for this gem.

def datadir
# TODO: drop the extra ", gem_name" which is uselessly redundant
File.expand_path(File.join(gems_dir, full_name, "data", name)).untaint
end

##
# Full path of the target library file.
# If the file is not in this gem, return nil.
@@ -161,8 +166,8 @@ def to_fullpath path
begin
fullpath = nil
suffixes = Gem.suffixes
full_require_paths.find do |dir|
suffixes.find do |suf|
suffixes.find do |suf|
full_require_paths.find do |dir|
File.file?(fullpath = "#{dir}/#{path}#{suf}")
end
end ? fullpath : nil
@@ -185,23 +190,15 @@ def gem_dir
# gem directory. eg: /usr/local/lib/ruby/1.8/gems

def gems_dir
# TODO: this logic seems terribly broken, but tests fail if just base_dir
@gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems")
raise NotImplementedError
end

##
# Set the path the Specification was loaded from. +path+ is converted to a
# String.

def loaded_from= path
@loaded_from = path && path.to_s

def internal_init # :nodoc:
@extension_dir = nil
@extensions_dir = nil
@full_gem_path = nil
@gem_dir = nil
@gems_dir = nil
@base_dir = nil
@ignored = nil
end

##
@@ -219,7 +216,7 @@ def platform
end

def raw_require_paths # :nodoc:
Array(@require_paths)
raise NotImplementedError
end

##
@@ -240,7 +237,7 @@ def raw_require_paths # :nodoc:
# spec.require_path = '.'

def require_paths
return raw_require_paths if @extensions.nil? || @extensions.empty?
return raw_require_paths unless have_extensions?

[extension_dir].concat raw_require_paths
end
@@ -252,8 +249,8 @@ def require_paths
def source_paths
paths = raw_require_paths.dup

if @extensions then
ext_dirs = @extensions.map do |extension|
if have_extensions? then
ext_dirs = extensions.map do |extension|
extension.split(File::SEPARATOR, 2).first
end.uniq

@@ -263,6 +260,30 @@ def source_paths
paths.uniq
end

##
# Return all files in this gem that match for +glob+.

def matches_for_glob glob # TODO: rename?
# TODO: do we need these?? Kill it
glob = File.join(self.lib_dirs_glob, glob)

Dir[glob].map { |f| f.untaint } # FIX our tests are broken, run w/ SAFE=1
end

##
# Returns a string usable in Dir.glob to match all requirable paths
# for this spec.

def lib_dirs_glob
dirs = if self.require_paths.size > 1 then
"{#{self.require_paths.join(',')}}"
else
self.require_paths.first
end

"#{self.full_gem_path}/#{dirs}".untaint
end

##
# Return a Gem::Specification from this gem

@@ -285,5 +306,23 @@ def stubbed?
raise NotImplementedError
end

private

def have_extensions?; !extensions.empty?; end

def have_file? file, suffixes
return true if raw_require_paths.any? do |path|
base = File.join(gems_dir, full_name, path.untaint, file).untaint
suffixes.any? { |suf| File.file? base + suf }
end

if have_extensions?
base = File.join extension_dir, file
suffixes.any? { |suf| File.file? base + suf }
else
false
end
end

end

40 changes: 25 additions & 15 deletions library/rubygems/commands/dependency_command.rb
Original file line number Diff line number Diff line change
@@ -61,27 +61,24 @@ def fetch_remote_specs dependency # :nodoc:
ss.map { |spec, _| spec }
end

def fetch_specs dependency # :nodoc:
def fetch_specs name_pattern, dependency # :nodoc:
specs = []

specs.concat dependency.matching_specs if local?
if local?
specs.concat Gem::Specification.stubs.find_all { |spec|
name_pattern =~ spec.name and
dependency.requirement.satisfied_by? spec.version
}.map(&:to_spec)
end

specs.concat fetch_remote_specs dependency if remote?

ensure_specs specs

specs.uniq.sort
end

def gem_dependency args, version, prerelease # :nodoc:
args << '' if args.empty?

pattern = if args.length == 1 and args.first =~ /\A\/(.*)\/(i)?\z/m then
flags = $2 ? Regexp::IGNORECASE : nil
Regexp.new $1, flags
else
/\A#{Regexp.union(*args)}/
end

def gem_dependency pattern, version, prerelease # :nodoc:
dependency = Gem::Deprecate.skip_during {
Gem::Dependency.new pattern, version
}
@@ -121,10 +118,12 @@ def display_readable specs, reverse # :nodoc:
def execute
ensure_local_only_reverse_dependencies

pattern = name_pattern options[:args]

dependency =
gem_dependency options[:args], options[:version], options[:prerelease]
gem_dependency pattern, options[:version], options[:prerelease]

specs = fetch_specs dependency
specs = fetch_specs pattern, dependency

reverse = reverse_dependencies specs

@@ -203,5 +202,16 @@ def find_reverse_dependencies spec # :nodoc:
result
end

end
private

def name_pattern args
args << '' if args.empty?

if args.length == 1 and args.first =~ /\A\/(.*)\/(i)?\z/m then
flags = $2 ? Regexp::IGNORECASE : nil
Regexp.new $1, flags
else
/\A#{Regexp.union(*args)}/
end
end
end
2 changes: 2 additions & 0 deletions library/rubygems/commands/environment_command.rb
Original file line number Diff line number Diff line change
@@ -113,6 +113,8 @@ def show_environment # :nodoc:

out << " - INSTALLATION DIRECTORY: #{Gem.dir}\n"

out << " - USER INSTALLATION DIRECTORY: #{Gem.user_dir}\n"

out << " - RUBYGEMS PREFIX: #{Gem.prefix}\n" unless Gem.prefix.nil?

out << " - RUBY EXECUTABLE: #{Gem.ruby}\n"
10 changes: 0 additions & 10 deletions library/rubygems/commands/help_command.rb
Original file line number Diff line number Diff line change
@@ -370,15 +370,5 @@ def show_command_help command_name # :nodoc:
end
end

def show_help # :nodoc:
command = @command_manager[options[:help]]
if command then
# help with provided command
command.invoke("--help")
else
alert_error "Unknown command #{options[:help]}. Try 'gem help commands'"
end
end

end

2 changes: 1 addition & 1 deletion library/rubygems/commands/install_command.rb
Original file line number Diff line number Diff line change
@@ -275,7 +275,7 @@ def install_gem_without_dependencies name, req # :nodoc:
gem = fetcher.download_to_cache dependency
end

inst = Gem::Installer.new gem, options
inst = Gem::Installer.at gem, options
inst.install

require 'rubygems/dependency_installer'
4 changes: 2 additions & 2 deletions library/rubygems/commands/list_command.rb
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

##
# An alternate to Gem::Commands::QueryCommand that searches for gems starting
# with the the supplied argument.
# with the supplied argument.

class Gem::Commands::ListCommand < Gem::Commands::QueryCommand

@@ -33,7 +33,7 @@ def description # :nodoc:
end

def usage # :nodoc:
"#{program_name} [STRING ...]"
"#{program_name} [REGEXP ...]"
end

end
12 changes: 11 additions & 1 deletion library/rubygems/commands/pristine_command.rb
Original file line number Diff line number Diff line change
@@ -21,6 +21,11 @@ def initialize
options[:all] = value
end

add_option('--skip=gem_name',
'used on --all, skip if name == gem_name') do |value, options|
options[:skip] = value
end

add_option('--[no-]extensions',
'Restore gems with extensions',
'in addition to regular gems') do |value, options|
@@ -109,6 +114,11 @@ def execute
next
end

if spec.name == options[:skip]
say "Skipped #{spec.full_name}, it was given through options"
next
end

if spec.bundled_gem_in_old_ruby?
say "Skipped #{spec.full_name}, it is bundled with old Ruby"
next
@@ -146,7 +156,7 @@ def execute
install_defaults.to_s['--env-shebang']
end

installer = Gem::Installer.new(gem,
installer = Gem::Installer.at(gem,
:wrappers => true,
:force => true,
:install_dir => spec.base_dir,
2 changes: 1 addition & 1 deletion library/rubygems/commands/query_command.rb
Original file line number Diff line number Diff line change
@@ -227,7 +227,7 @@ def entry_details entry, detail_tuple, specs, platforms

name_tuple, spec = detail_tuple

spec = spec.fetch_spec name_tuple unless Gem::Specification === spec
spec = spec.fetch_spec name_tuple if spec.respond_to? :fetch_spec

entry << "\n"

2 changes: 1 addition & 1 deletion library/rubygems/commands/sources_command.rb
Original file line number Diff line number Diff line change
@@ -102,7 +102,7 @@ def description # :nodoc:
RubyGems fetches gems from the sources you have configured (stored in your
~/.gemrc).

The default source is https://rubygems.org, but you may have older sources
The default source is https://rubygems.org, but you may have other sources
configured. This guide will help you update your sources or configure
yourself to use your own gem server.

4 changes: 2 additions & 2 deletions library/rubygems/commands/update_command.rb
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ def initialize
end

def arguments # :nodoc:
"REGEXP regexp to search for in gem name"
"GEMNAME name of gem to update"
end

def defaults_str # :nodoc:
@@ -64,7 +64,7 @@ def description # :nodoc:
end

def usage # :nodoc:
"#{program_name} REGEXP [REGEXP ...]"
"#{program_name} GEMNAME [GEMNAME ...]"
end

def check_latest_rubygems version # :nodoc:
8 changes: 4 additions & 4 deletions library/rubygems/config_file.rb
Original file line number Diff line number Diff line change
@@ -321,12 +321,12 @@ def rubygems_api_key= api_key
@rubygems_api_key = api_key
end

YAMLErrors = [ArgumentError]
YAMLErrors << Psych::SyntaxError if defined?(Psych::SyntaxError)

def load_file(filename)
Gem.load_yaml

yaml_errors = [ArgumentError]
yaml_errors << Psych::SyntaxError if defined?(Psych::SyntaxError)

return {} unless filename and File.exist? filename

begin
@@ -336,7 +336,7 @@ def load_file(filename)
return {}
end
return content
rescue *YAMLErrors => e
rescue *yaml_errors => e
warn "Failed to load #{filename}, #{e}"
rescue Errno::EACCES
warn "Failed to load #{filename} due to permissions problem."
8 changes: 3 additions & 5 deletions library/rubygems/core_ext/kernel_require.rb
Original file line number Diff line number Diff line change
@@ -60,13 +60,11 @@ def require path
#--
# TODO request access to the C implementation of this to speed up RubyGems

spec = Gem::Specification.stubs.find { |s|
s.activated? and s.contains_requirable_file? path
}
spec = Gem::Specification.find_active_stub_by_path path

begin
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(spec.to_fullpath(path) || path)
return gem_original_require(path)
end if spec

# Attempt to find +path+ in any unresolved gems...
@@ -105,7 +103,7 @@ def require path

# Ok, now find a gem that has no conflicts, starting
# at the highest version.
valid = found_specs.select { |s| s.conflicts.empty? }.last
valid = found_specs.reject { |s| s.has_conflicts? }.last

unless valid then
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
15 changes: 9 additions & 6 deletions library/rubygems/dependency.rb
Original file line number Diff line number Diff line change
@@ -164,6 +164,10 @@ def type
@type ||= :runtime
end

def runtime?
@type == :runtime || !@type
end

def == other # :nodoc:
Gem::Dependency === other &&
self.name == other.name &&
@@ -270,14 +274,13 @@ def merge other
end

def matching_specs platform_only = false
matches = Gem::Specification.stubs.find_all { |spec|
self.name === spec.name and # TODO: == instead of ===
requirement.satisfied_by? spec.version
matches = Gem::Specification.stubs_for(name).find_all { |spec|
requirement.satisfied_by? spec.version
}.map(&:to_spec)

if platform_only
matches.reject! { |spec|
not Gem::Platform.match spec.platform
spec.nil? || !Gem::Platform.match(spec.platform)
}
end

@@ -323,11 +326,11 @@ def to_specs
def to_spec
matches = self.to_specs

active = matches.find { |spec| spec.activated? }
active = matches.find { |spec| spec && spec.activated? }

return active if active

matches.delete_if { |spec| spec.version.prerelease? } unless prerelease?
matches.delete_if { |spec| spec.nil? || spec.version.prerelease? } unless prerelease?

matches.last
end
3 changes: 3 additions & 0 deletions library/rubygems/dependency_list.rb
Original file line number Diff line number Diff line change
@@ -141,6 +141,9 @@ def why_not_ok? quick = false
def ok_to_remove?(full_name, check_dev=true)
gem_to_remove = find_name full_name

# If the state is inconsistent, at least don't crash
return true unless gem_to_remove

siblings = @specs.find_all { |s|
s.name == gem_to_remove.name &&
s.full_name != gem_to_remove.full_name
2 changes: 2 additions & 0 deletions library/rubygems/ext/builder.rb
Original file line number Diff line number Diff line change
@@ -66,9 +66,11 @@ def self.run(command, results, command_name = nil)
# TODO use Process.spawn when ruby 1.8 support is dropped.
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
if verbose
puts("current directory: #{Dir.pwd}")
puts(command)
system(command)
else
results << "current directory: #{Dir.pwd}"
results << command
results << `#{command} #{redirector}`
end
7 changes: 6 additions & 1 deletion library/rubygems/ext/ext_conf_builder.rb
Original file line number Diff line number Diff line change
@@ -35,7 +35,12 @@ def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil)
begin
run cmd, results
ensure
FileUtils.mv 'mkmf.log', dest_path if File.exist? 'mkmf.log'
if File.exist? 'mkmf.log'
results << "To see why this extension failed to compile, please check" \
" the mkmf.log which can be found here:\n"
results << " " + File.join(dest_path, 'mkmf.log') + "\n"
FileUtils.mv 'mkmf.log', dest_path
end
siteconf.unlink
end

117 changes: 26 additions & 91 deletions library/rubygems/indexer.rb
Original file line number Diff line number Diff line change
@@ -93,48 +93,30 @@ def initialize(directory, options = {})
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.
#--
# TODO move to Gem::Specification

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
Gem::Specification.dirs = []
Gem::Specification.add_specs(*map_gems_to_specs(gem_file_list))
# Build various indices

build_marshal_gemspecs
build_modern_indicies if @build_modern
def build_indices
specs = map_gems_to_specs gem_file_list
Gem::Specification._resort! specs
build_marshal_gemspecs specs
build_modern_indices specs if @build_modern

compress_indicies
compress_indices
end

##
# Builds Marshal quick index gemspecs.

def build_marshal_gemspecs
count = Gem::Specification.count { |s| not s.default_gem? }
def build_marshal_gemspecs specs
count = specs.count
progress = ui.progress_reporter count,
"Generating Marshal quick index gemspecs for #{count} gems",
"Complete"

files = []

Gem.time 'Generated Marshal quick index gemspecs' do
Gem::Specification.each do |spec|
specs.each do |spec|
next if spec.default_gem?
spec_file_name = "#{spec.original_name}.gemspec.rz"
marshal_name = File.join @quick_marshal_dir, spec_file_name
@@ -186,16 +168,14 @@ def build_modern_index(index, file, name)
end

##
# Builds indicies for RubyGems 1.2 and newer. Handles full, latest, prerelease

def build_modern_indicies
specs = Gem::Specification.reject { |s| s.default_gem? }
# Builds indices for RubyGems 1.2 and newer. Handles full, latest, prerelease

def build_modern_indices specs
prerelease, released = specs.partition { |s|
s.version.prerelease?
}
latest_specs =
Gem::Specification.latest_specs.reject { |s| s.default_gem? }
Gem::Specification._latest_specs specs

build_modern_index(released.sort, @specs_index, 'specs')
build_modern_index(latest_specs.sort, @latest_specs_index, 'latest specs')
@@ -221,18 +201,8 @@ def map_gems_to_specs gems
spec = Gem::Package.new(gemfile).spec
spec.loaded_from = gemfile

# HACK: fuck this shit - borks all tests that use pl1
# if File.basename(gemfile, ".gem") != spec.original_name then
# exp = spec.full_name
# exp << " (#{spec.original_name})" if
# spec.original_name != spec.full_name
# msg = "Skipping misnamed gem: #{gemfile} should be named #{exp}"
# alert_warning msg
# next
# end

abbreviate spec
sanitize spec
spec.abbreviate
spec.sanitize

spec
rescue SignalException
@@ -248,14 +218,14 @@ def map_gems_to_specs gems
end

##
# Compresses indicies on disk
# Compresses indices on disk
#--
# All future files should be compressed using gzip, not deflate

def compress_indicies
say "Compressing indicies"
def compress_indices
say "Compressing indices"

Gem.time 'Compressed indicies' do
Gem.time 'Compressed indices' do
if @build_modern then
gzip @specs_index
gzip @latest_specs_index
@@ -303,12 +273,12 @@ def gem_file_list
end

##
# Builds and installs indicies.
# Builds and installs indices.

def generate_index
make_temp_directories
build_indicies
install_indicies
build_indices
install_indices
rescue SignalException
ensure
FileUtils.rm_rf @directory
@@ -324,9 +294,9 @@ def gzip(filename)
end

##
# Install generated indicies into the destination directory.
# Install generated indices into the destination directory.

def install_indicies
def install_indices
verbose = Gem.configuration.really_verbose

say "Moving index into production dir #{@dest_directory}" if verbose
@@ -380,38 +350,6 @@ def paranoid(path, extension)
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)
return string unless 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 gemspec
# generation. (Probably won't happen.)
string = string.to_s

begin
Builder::XChar.encode string
rescue NameError, NoMethodError
string.to_xs
end
end

##
# Perform an in-place update of the repository from newly added gems.

@@ -435,10 +373,7 @@ def update_index
specs = map_gems_to_specs updated_gems
prerelease, released = specs.partition { |s| s.version.prerelease? }

Gem::Specification.dirs = []
Gem::Specification.add_specs(*specs)

files = build_marshal_gemspecs
files = build_marshal_gemspecs specs

Gem.time 'Updated indexes' do
update_specs_index released, @dest_specs_index, @specs_index
@@ -448,7 +383,7 @@ def update_index
@prerelease_specs_index)
end

compress_indicies
compress_indices

verbose = Gem.configuration.really_verbose

88 changes: 60 additions & 28 deletions library/rubygems/installer.rb
Original file line number Diff line number Diff line change
@@ -61,11 +61,6 @@ class Gem::Installer

attr_reader :options

##
# Sets the specification for .gem-less installs.

attr_writer :spec

@path_warning = false

@install_lock = Mutex.new
@@ -99,6 +94,46 @@ def exec_format

end

##
# Construct an installer object for the gem file located at +path+

def self.at path, options = {}
security_policy = options[:security_policy]
package = Gem::Package.new path, security_policy
new package, options
end

class FakePackage
attr_accessor :spec

def initialize(spec)
@spec = spec
end

def extract_files destination_dir, pattern = '*'
FileUtils.mkdir_p destination_dir

spec.files.each do |file|
file = File.join destination_dir, file
next if File.exist? file
FileUtils.mkdir_p File.dirname(file)
File.open file, 'w' do |fp| fp.puts "# #{file}" end
end
end

def copy_to path
end
end

##
# Construct an installer object for an ephemeral gem (one where we don't
# actually have a .gem file, just a spec)

def self.for_spec spec, options = {}
# FIXME: we should have a real Package class for this
new FakePackage.new(spec), options
end

##
# Constructs an Installer instance that will install the gem located at
# +gem+. +options+ is a Hash with the following keys:
@@ -122,17 +157,22 @@ def exec_format
# :build_args:: An Array of arguments to pass to the extension builder
# process. If not set, then Gem::Command.build_args is used

def initialize(gem, options={})
def initialize(package, options={})
require 'fileutils'

@gem = gem
@options = options
@package = Gem::Package.new @gem
if package.is_a? String
security_policy = options[:security_policy]
@package = Gem::Package.new package, security_policy
if $VERBOSE
warn "constructing an Installer object with a string is deprecated. Please use Gem::Installer.at (called from: #{caller.first})"
end
else
@package = package
end

process_options

@package.security_policy = @security_policy

if options[:user_install] and not options[:unpack] then
@gem_home = Gem.user_dir
@bin_dir = Gem.bindir gem_home unless options[:bin_dir]
@@ -211,7 +251,7 @@ def gem_dir
# Lazy accessor for the installer's spec.

def spec
@spec ||= @package.spec
@package.spec
rescue Gem::Package::Error => e
raise Gem::InstallError, "invalid gem: #{e.message}"
end
@@ -230,7 +270,7 @@ def spec
def install
pre_install_checks

FileUtils.rm_f File.join gem_home, 'specifications', @spec.spec_name
FileUtils.rm_f File.join gem_home, 'specifications', spec.spec_name

run_pre_install_hooks

@@ -239,12 +279,12 @@ def install

FileUtils.mkdir_p gem_dir

spec.loaded_from = spec_file

if @options[:install_as_default]
spec.loaded_from = default_spec_file
extract_bin
write_default_spec
else
spec.loaded_from = spec_file
extract_files

build_extensions
@@ -258,7 +298,7 @@ def install

say spec.post_install_message unless spec.post_install_message.nil?

Gem::Installer.install_lock.synchronize { Gem::Specification.add_spec spec }
Gem::Installer.install_lock.synchronize { Gem::Specification.reset }

run_post_install_hooks

@@ -351,19 +391,19 @@ def unpack(directory)
end

##
# The location of of the spec file that is installed.
# The location of the spec file that is installed.
#

def spec_file
File.join gem_home, "specifications", "#{spec.full_name}.gemspec"
end

##
# The location of of the default spec file for default gems.
# The location of the default spec file for default gems.
#

def default_spec_file
File.join gem_home, "specifications/default", "#{spec.full_name}.gemspec"
File.join Gem::Specification.default_specifications_dir, "#{spec.full_name}.gemspec"
end

##
@@ -595,7 +635,6 @@ def process_options # :nodoc:
@gem_home = options[:install_dir] || Gem.dir
@ignore_dependencies = options[:ignore_dependencies]
@format_executable = options[:format_executable]
@security_policy = options[:security_policy]
@wrappers = options[:wrappers]
@only_install_dir = options[:only_install_dir]

@@ -661,7 +700,7 @@ def app_script_text(bin_file_name)

require 'rubygems'

version = "#{Gem::Requirement.default}"
version = "#{Gem::Requirement.default}.a"

if ARGV.first
str = ARGV.first
@@ -764,11 +803,6 @@ def dir
def pre_install_checks
verify_gem_home options[:unpack]

# If we're forcing the install then disable security unless the security
# policy says that we only install signed gems.
@security_policy = nil if
@force and @security_policy and not @security_policy.only_signed

ensure_loadable_spec

if options[:install_as_default]
@@ -811,9 +845,7 @@ def write_build_info_file

def write_cache_file
cache_file = File.join gem_home, 'cache', spec.file_name

FileUtils.cp @gem, cache_file unless File.exist? cache_file
@package.copy_to cache_file
end

end

4 changes: 2 additions & 2 deletions library/rubygems/installer_test_case.rb
Original file line number Diff line number Diff line change
@@ -176,15 +176,15 @@ def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic
end
end

@installer = Gem::Installer.new @gem
@installer = Gem::Installer.at @gem
end

##
# Creates an installer for +spec+ that will install into +gem_home+. If
# +user+ is true a user-install will be performed.

def util_installer(spec, gem_home, user=false)
Gem::Installer.new(spec.cache_file,
Gem::Installer.at(spec.cache_file,
:install_dir => gem_home,
:user_install => user)
end
24 changes: 18 additions & 6 deletions library/rubygems/package.rb
Original file line number Diff line number Diff line change
@@ -123,7 +123,7 @@ def self.build spec, skip_validation=false
# If +gem+ is an existing file in the old format a Gem::Package::Old will be
# returned.

def self.new gem
def self.new gem, security_policy = nil
gem = if gem.is_a?(Gem::Package::Source)
gem
elsif gem.respond_to? :read
@@ -132,7 +132,7 @@ def self.new gem
Gem::Package::FileSource.new gem
end

return super(gem) unless Gem::Package == self
return super unless Gem::Package == self
return super unless gem.present?

return super unless gem.start
@@ -144,20 +144,27 @@ def self.new gem
##
# Creates a new package that will read or write to the file +gem+.

def initialize gem # :notnew:
def initialize gem, security_policy # :notnew:
@gem = gem

@build_time = Time.now
@checksums = {}
@contents = nil
@digests = Hash.new { |h, algorithm| h[algorithm] = {} }
@files = nil
@security_policy = nil
@security_policy = security_policy
@signatures = {}
@signer = nil
@spec = nil
end

##
# Copies this package to +path+ (if possible)

def copy_to path
FileUtils.cp @gem.path, path unless File.exist? path
end

##
# Adds a checksum for each entry in the gem to checksums.yaml.gz.

@@ -200,7 +207,11 @@ def add_contents tar # :nodoc:

def add_files tar # :nodoc:
@spec.files.each do |file|
stat = File.stat file
stat = File.lstat file

if stat.symlink?
tar.add_symlink file, File.readlink(file), stat.mode
end

next unless stat.file?

@@ -371,6 +382,8 @@ def extract_tar_gz io, destination_dir, pattern = "*" # :nodoc:
FileUtils.chmod entry.header.mode, destination
end if entry.file?

File.symlink(install_location(entry.header.linkname, destination_dir), destination) if entry.symlink?

verbose destination
end
end
@@ -611,4 +624,3 @@ def verify_gz entry # :nodoc:
require 'rubygems/package/tar_reader'
require 'rubygems/package/tar_reader/entry'
require 'rubygems/package/tar_writer'

4 changes: 2 additions & 2 deletions library/rubygems/package/old.rb
Original file line number Diff line number Diff line change
@@ -18,14 +18,14 @@ class Gem::Package::Old < Gem::Package
# Creates a new old-format package reader for +gem+. Old-format packages
# cannot be written.

def initialize gem
def initialize gem, security_policy
require 'fileutils'
require 'zlib'
Gem.load_yaml

@contents = nil
@gem = gem
@security_policy = nil
@security_policy = security_policy
@spec = nil
end

8 changes: 7 additions & 1 deletion library/rubygems/package/tar_reader/entry.rb
Original file line number Diff line number Diff line change
@@ -102,6 +102,13 @@ def file?
@header.typeflag == "0"
end

##
# Is this tar entry a symlink?

def symlink?
@header.typeflag == "2"
end

##
# The position in the tar entry

@@ -144,4 +151,3 @@ def rewind
end

end

15 changes: 12 additions & 3 deletions library/rubygems/package/tar_test_case.rb
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ def calc_checksum(header)
SP(Z(to_oct(sum, 6)))
end

def header(type, fname, dname, length, mode, mtime, checksum = nil)
def header(type, fname, dname, length, mode, mtime, checksum = nil, linkname = "")
checksum ||= " " * 8

arr = [ # struct tarfile_entry_posix
@@ -83,7 +83,7 @@ def header(type, fname, dname, length, mode, mtime, checksum = nil)
Z(to_oct(mtime, 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)
ASCIIZ(linkname, 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
@@ -117,6 +117,12 @@ def tar_file_header(fname, dname, mode, length, mtime)
header("0", fname, dname, length, mode, mtime, checksum)
end

def tar_symlink_header(fname, prefix, mode, mtime, linkname)
h = header("2", fname, prefix, 0, mode, mtime, nil, linkname)
checksum = calc_checksum(h)
header("2", fname, prefix, 0, mode, mtime, checksum, linkname)
end

def to_oct(n, pad_size)
"%0#{pad_size}o" % n
end
@@ -133,5 +139,8 @@ def util_dir_entry
util_entry tar_dir_header("foo", "bar", 0, Time.now)
end

end
def util_symlink_entry
util_entry tar_symlink_header("foo", "bar", 0, Time.now, "link")
end

end
20 changes: 19 additions & 1 deletion library/rubygems/package/tar_writer.rb
Original file line number Diff line number Diff line change
@@ -233,6 +233,25 @@ def add_file_simple(name, mode, size) # :yields: io
self
end

##
# Adds symlink +name+ with permissions +mode+, linking to +target+.

def add_symlink(name, target, mode)
check_closed

name, prefix = split_name name

header = Gem::Package::TarHeader.new(:name => name, :mode => mode,
:size => 0, :typeflag => "2",
:linkname => target,
:prefix => prefix,
:mtime => Time.now).to_s

@io.write header

self
end

##
# Raises IOError if the TarWriter is closed

@@ -323,4 +342,3 @@ def split_name(name) # :nodoc:
end

end

5 changes: 3 additions & 2 deletions library/rubygems/platform.rb
Original file line number Diff line number Diff line change
@@ -95,6 +95,7 @@ def initialize(arch)
[os, version]
when /netbsdelf/ then [ 'netbsdelf', nil ]
when /openbsd(\d+\.\d+)?/ then [ 'openbsd', $1 ]
when /bitrig(\d+\.\d+)?/ then [ 'bitrig', $1 ]
when /solaris(\d+\.\d+)?/ then [ 'solaris', $1 ]
# test
when /^(\w+_platform)(\d+)?/ then [ $1, $2 ]
@@ -147,8 +148,8 @@ def ===(other)
return nil unless Gem::Platform === other

# cpu
(@cpu == 'universal' or other.cpu == 'universal' or @cpu == other.cpu or
(@cpu == 'arm' and other.cpu =~ /\Aarm/)) and
([nil,'universal'].include?(@cpu) or [nil, 'universal'].include?(other.cpu) or @cpu == other.cpu or
(@cpu == 'arm' and other.cpu =~ /\Aarm/)) and

# os
@os == other.os and
3 changes: 1 addition & 2 deletions library/rubygems/rdoc.rb
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
require 'rdoc/rubygems_hook'
loaded_hook = true
module Gem
RDoc = RDoc::RubygemsHook
RDoc = ::RDoc::RubygemsHook
end
rescue LoadError
end
@@ -332,4 +332,3 @@ def setup
end unless loaded_hook

Gem.done_installing(&Gem::RDoc.method(:generation_hook))

Loading

0 comments on commit d0d5ff6

Please sign in to comment.