diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index 084dc5d2d9..4672866985 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -444,10 +444,10 @@ EOM directories << mkdir end - File.open destination, "wb" do |out| - out.write entry.read + if entry.file? + File.open(destination, "wb") {|out| out.write entry.read } FileUtils.chmod file_mode(entry.header.mode), destination - end if entry.file? + end verbose destination end @@ -467,7 +467,12 @@ EOM end def file_mode(mode) # :nodoc: - ((mode & 0111).zero? ? data_mode : prog_mode) || mode + ((mode & 0111).zero? ? data_mode : prog_mode) || + # If we're not using one of the default modes, then we're going to fall + # back to the mode from the tarball. In this case we need to mask it down + # to fit into 2^16 bits (the maximum value for a mode in CRuby since it + # gets put into an unsigned short). + (mode & ((1 << 16) - 1)) end ## diff --git a/test/rubygems/packages/Bluebie-legs-0.6.2.gem b/test/rubygems/packages/Bluebie-legs-0.6.2.gem new file mode 100644 index 0000000000..60918f3bc5 Binary files /dev/null and b/test/rubygems/packages/Bluebie-legs-0.6.2.gem differ diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 9295f42dba..eebe4d86d0 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -510,6 +510,21 @@ class TestGemPackage < Gem::Package::TarTestCase assert_path_exist @destination end + def test_extract_file_permissions + pend "chmod not supported" if win_platform? + + gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__) + + package = Gem::Package.new gem_with_long_permissions + + package.extract_files @destination + + filepath = File.join @destination, "README.rdoc" + assert_path_exist filepath + + assert_equal 0104444, File.stat(filepath).mode + end + def test_extract_tar_gz_absolute package = Gem::Package.new @gem