Skip to content
This repository

fpm fails under ruby 1.8.5 (missing Object#instance_variable_defined?) #214

Open
jordansissel opened this Issue · 14 comments

7 participants

Jordan Sissel Jeanine Adkisson Philip Reynolds Daniel Serodio heavydawson Attila Fulop James Pearson
Jordan Sissel
Owner

Looks like the backports gem doesn't define Object#instance_variable_defined?

The following is from ruby 1.8.5

# fpm
/usr/lib/ruby/gems/1.8/gems/clamp-0.3.1/lib/clamp/attribute_declaration.rb:15:in `input_type': undefined method `instance_variable_defined?' for #<FPM::Command:0xb7e77914> (NoMethodError)
        from /usr/lib/ruby/gems/1.8/gems/fpm-0.4.9/lib/fpm/command.rb:190:in `execute'
        from /usr/lib/ruby/gems/1.8/gems/clamp-0.3.1/lib/clamp/command.rb:64:in `run'
        from /usr/lib/ruby/gems/1.8/gems/cl amp-0.3.1/lib/clamp/command.rb:126:in `run'
        from /usr/lib/ruby/gems/1.8/gems/fpm-0.4.9/bin/fpm:8
        from /usr/bin/fpm:19:in `load'
        from /usr/bin/fpm:19
Jeanine Adkisson
Collaborator
jneen commented

It might be fun to just sublcass Hash and use #key? instead.

Jordan Sissel
Owner

well, I think this is in clamp, not fpm. Implementing the missing method should be easy.

Jordan Sissel
Owner

I expected the backports gem to provide it, but it doesn't at this time. I"ll file a bug there separately :)

Philip Reynolds
pjr commented

Can't see the issue open in backports, would be great to get this working with 1.8.5 (standard in el5)

Jordan Sissel
Owner

I don't have any centos5 systems at this time so I can't test any fix - I'll have a go getting vagrant up with centos 5.

Jordan Sissel
Owner

I can't even install fpm on centos5/ruby1.8.5:

[vagrant@vagrant-centos-56-64 rubygems-1.3.5]$ sudo gem install fpm
*** buffer overflow detected ***: /usr/bin/ruby terminated

How do you even install this?

Philip Reynolds
pjr commented

Yeh, CentOS 5 is OLD as is ruby 1.8.5. I nearly forgot I fixed this bug. This is fixed upstream in el5, but awaiting next minor release before we'll actually see it. You basically need a patched version of ruby.

https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=785852

You need a monkeypatched shellwords.Shellwords

  def shellescape(str)
    str = str.to_s

    # An empty argument will be skipped, so return empty quotes.
    return "''" if str.empty?

    str = str.dup

    # Treat multibyte characters as is.  It is caller's responsibility
    # to encode the string in the right encoding for the shell
    # environment.
    str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")

    # A LF cannot be escaped with a backslash because a backslash + LF
    # combo is regarded as line continuation and simply ignored.
    str.gsub!(/\n/, "'\n'")

    return str
  end

  module_function :shellescape

  class << self
    alias escape shellescape
  end

Then you need instance_variable_defined for clamp.

unless Object.respond_to?("instance_variable_defined?")
    class Object
        def instance_variable_defined?(meth)
            instance_variables.include?(meth)
        end
    end
end

Then fpm works.

$ sudo /usr/bin/fpm -s dir -t rpm -n "slashbin" -v 1.0 /bin /sbin
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.90047
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.90047
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.90047
Processing files: slashbin-1.0-1
Wrote: /tmp/package-rpm-build20120805-4842-12qmgu1/RPMS/i686/slashbin-1.0-1.i686.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.91598
Created rpm {"path":"slashbin-1.0-1.i686.rpm"}
Daniel Serodio

@pjr I'm a Ruby newbie, how do I patch Ruby 1.8.6 with this shellwords.Shellwords method? I'm using CentOS 5.5.

heavydawson

Hey deserodio,
The monkey patch involves taking the method wholesale from the latest ruby source code, and dropping it into shellwords.rb in the Ruby installation directory.
You can see the method source needed here:
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape
, and using the "Click to toggle source" option.
Copy and paste the source for that method alone into your local copy of shellwords.rb
You'll also need to add one single line after the method definition:

module_function :shellescape

, somewhere after the class definition you've just added for shellescape.

heavydawson

For what it's worth I found I had to carry out two additional hacks not mentioned here already to get FPM working for me on CentOS 5.8

FPM package.rb has to be patched with the same fix already applied to command.rb in clamp above for the "instance_variable_defined?" issue

JSON 1.6.6 has a dependency on some Ruby symbols not present in Ruby 1.8.5 (namely RSTRING_LEN), so I needed to do the following:
Add the following to ruby.h

#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#define RSTRING_LEN(s) (RSTRING(s)->len)

,then run "gem uninstall json" and "gem install json" to ensure the native extensions are rebuilt with the new header information

Daniel Serodio

Thanks @heavydawson I ended doing exactly this. In case anyone stuck with CentOS 5.5 needs to do the same, I've described the steps to intstall fpm on CentOS 5.5 here.

Attila Fulop

Neither am I a ruby programmer so it took me a while to figure out what and where exactly to patch to resolve the instance_variable_defined issue. So here it is for those with similarly limited ruby knowledge:

  1. Edit the file /usr/lib64/ruby/gems/1.8/gems/fpm-0.4.29/lib/fpm/command.rb (change the path implicitly)
  2. Paste the missing codepart before the line class FPM::Command < Clamp::command (above the comment if there is)
  3. The missing codepart to paste is:
unless Object.respond_to?("instance_variable_defined?")
    class Object
        def instance_variable_defined?(meth)
            instance_variables.include?(meth)
        end
    end
end

Good luck :)

Jordan Sissel
Owner

I think my solution here is going to be to start providing fpm as a omnibussed package you can 'apt-get install' or whatever; like Vagrant or Chef is these days.

Trying to chase down bugs in ancient versions of Ruby isn't a good use for anyone's time, and doing omnibus packaging will solve this for good!

James Pearson

You can also upgrade to a non-broken version of Ruby 1.8; here's what I use on CentOS 5:

#!/bin/bash -ex

cd /tmp/build

# There are a bunch of things that are terribly broken in Ruby 1.8.5, which is
# what CentOS 5 ships with.  So, to get things working, we upgrade to 1.8.7,
# which is the latest in the 1.8 branch.  We don't want to go all the way to
# 1.9 because RightScale uses a lot of Ruby in their scripts, and that
# transition would be much more likely to break things.

wget --no-verbose 'ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p370.tar.gz'
tar zxf ruby-1.8.7-p370.tar.gz
cd ruby-1.8.7-p370
./configure --prefix=/usr --libdir=/usr/lib64 --without-X11
make
make install
cd ../

wget --no-verbose 'http://production.cf.rubygems.org/rubygems/rubygems-1.8.24.tgz'
tar zxf rubygems-1.8.24.tgz
cd rubygems-1.8.24
ruby setup.rb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.