Version 0.9.3 (IIRC) set the ZLib code in package.rb to always read from a memory string rather than a FileIO object.  This was to avoid buffer errors on Windows boxen.  Unfortunately, it seems that we still get zlib problems.  Jamis Buck reported a problem with the capistrano gem on windows XP.  After some deep diving, he came up with with a workaround version of zipped_stream that doesn't blow up with a buffer error ... at least for this time around.  Essentially, Jamis's fix replaces GZipReader with some Ruby code that does the equivalent directly with ZLib calls.

I've made a beta version of RubyGems with his patch (you can get it with: gem update --system --source http://onestepback.org/betagems). 

Jamis points out that this is cargo cult programming at its finest.  I.e. we really don't know *why* it fixes it.  All we know is that it does fix it in this one instance.  We really need someone to dive into ZLib and see if we can get the windows version fixed.  

I've attached Jamis's original email.  He has a slightly longer version we may want to consider if this fix seems to be worthwhile.  Thank you for your time.

{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf420
{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red0\green0\blue0;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural

\f0\b\fs28 \cf2 From: 
\f1\b0 \cf3 Jamis Buck <[EMAIL PROTECTED]>\

\f0\b \cf2 Date: 
\f1\b0 \cf3 June 19, 2007 4:07:05 PM EDT\

\f0\b \cf2 To: 
\f1\b0 \cf3 [EMAIL PROTECTED]

\f0\b \cf2 Subject: \cf3 cargo culting at it's best, a solution that works for no apparent reason\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural

\f1\b0\fs24 \cf3 \
Here's my work-around for the Zlib issue. Just replace the zipped_stream method in package.rb with the following:\
\
    def zipped_stream(entry)\
      entry.read(10) # skip the gzip header\
      zis = Zlib::Inflate.new(-Zlib::MAX_WBITS)\
      is = StringIO.new(zis.inflate(entry.read))\
    ensure\
      zis.finish if zis\
    end\
\
A slightly more robust gzip reader looks something like this (sorry about the magic numbers, it was just a proof of concept. if you want to use this more robust approach, let me know and I can do it up right with symbolic constants):\
\
  require 'zlib'\
\
  File.open("out.gz", "rb") do |f|\
    head = f.read(10)\
\
    abort "bad magic" if head[0] != 0x1f || head[1] != 0x8b\
    abort "bad compression method #\{head[2]\}" if head[2] != 8\
    abort "multipart gzip is unsupported" if head[3] & 0x2 != 0\
    abort "encrypted gzip is unsupported" if head[3] & 0x20 != 0\
    abort "unknown flags #\{head[3]\}" if head[3] & 0xc0 != 0\
\
    if head[3] & 0x4 != 0\
      len = f.read(2).unpack("n").first\
      f.read(len + 2)\
    end\
\
    if head[3] & 0x8 != 0\
      loop \{ break if f.read(1) == 0 \}\
    end\
\
    if head[3] & 0x10 != 0\
      loop \{ break if f.read(1) == 0 \}\
    end\
\
    zis = Zlib::Inflate.new(-Zlib::MAX_WBITS)\
    result = zis.inflate(f.read)\
\
    puts "got #\{result.length\} bytes"\
  end\
\
- Jamis\
\
}


-- 
-- Jim Weirich



_______________________________________________
Rubygems-developers mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rubygems-developers

Reply via email to