1. Gem::
  2. Commands::
  3. RebuildCommand

class Gem::Commands::RebuildCommand

Public Class Methods

Source
# File lib/rubygems/commands/rebuild_command.rb, line 13definitializesuper"rebuild","Attempt to reproduce a build of a gem."add_option"--diff","If the files don't match, compare them using diffoscope."do|_value,options|options[:diff] =trueendadd_option"--force","Skip validation of the spec."do|_value,options|options[:force] =trueendadd_option"--strict","Consider warnings as errors when validating the spec."do|_value,options|options[:strict] =trueendadd_option"--source GEM_SOURCE","Specify the source to download the gem from."do|value,options|options[:source] =valueendadd_option"--original GEM_FILE","Specify a local file to compare against (instead of downloading it)."do|value,options|options[:original_gem_file] =valueendadd_option"--gemspec GEMSPEC_FILE","Specify the name of the gemspec file."do|value,options|options[:gemspec_file] =valueendadd_option"-C PATH","Run as if gem build was started in <PATH> instead of the current working directory."do|value,options|options[:build_path] =valueendend
Calls superclass methodGem::Command::new

Public Instance Methods

Source
# File lib/rubygems/commands/rebuild_command.rb, line 72defexecutegem_name,gem_version =get_gem_name_and_versionold_dir,new_dir =prep_dirsgem_filename ="#{gem_name}-#{gem_version}.gem"old_file =File.join(old_dir,gem_filename)new_file =File.join(new_dir,gem_filename)ifoptions[:original_gem_file]FileUtils.copy_file(options[:original_gem_file],old_file)elsedownload_gem(gem_name,gem_version,old_file)endrg_version =rubygems_version(old_file)unlessrg_version==Gem::VERSIONalert_error<<-EOFYou need to use the same RubyGems version #{gem_name} v#{gem_version} was built with.#{gem_name} v#{gem_version} was built using RubyGems v#{rg_version}.Gem files include the version of RubyGems used to build them.This means in order to reproduce #{gem_filename}, you must also use RubyGems v#{rg_version}.You're using RubyGems v#{Gem::VERSION}.Please install RubyGems v#{rg_version} and try again.      EOFterminate_interaction1endsource_date_epoch =get_timestamp(old_file).to_sifbuild_path =options[:build_path]Dir.chdir(build_path) {build_gem(gem_name,source_date_epoch,new_file) }elsebuild_gem(gem_name,source_date_epoch,new_file)endcompare(source_date_epoch,old_file,new_file)end

Private Instance Methods

Source
# File lib/rubygems/commands/rebuild_command.rb, line 190defbuild_gem(gem_name,source_date_epoch,output_file)gemspec =options[:gemspec_file]||find_gemspec("#{gem_name}.gemspec")ifgemspecbuild_package(gemspec,source_date_epoch,output_file)elsealert_errorerror_message(gem_name)terminate_interaction(1)endend
Source
# File lib/rubygems/commands/rebuild_command.rb, line 201defbuild_package(gemspec,source_date_epoch,output_file)with_source_date_epoch(source_date_epoch)dospec =Gem::Specification.load(gemspec)ifspecGem::Package.build(spec,options[:force],options[:strict],output_file      )elsealert_error"Error loading gemspec. Aborting."terminate_interaction1endendend
Source
# File lib/rubygems/commands/rebuild_command.rb, line 131defcompare(source_date_epoch,old_file,new_file)date =Time.at(source_date_epoch.to_i).strftime("%F %T %Z")old_hash =sha256(old_file)new_hash =sha256(new_file)saysay"Built at: #{date} (#{source_date_epoch})"say"Original build saved to:   #{old_file}"say"Reproduced build saved to: #{new_file}"say"Working directory: #{options[:build_path] || Dir.pwd}"saysay"Hash comparison:"say"  #{old_hash}\t#{old_file}"say"  #{new_hash}\t#{new_file}"sayifold_hash==new_hashsay"SUCCESS - original and rebuild hashes matched"elsesay"FAILURE - original and rebuild hashes did not match"sayifoptions[:diff]ifsystem("diffoscope",old_file,new_file).nil?alert_error"error: could not find `diffoscope` executable"endelsesay"Pass --diff for more details (requires diffoscope to be installed)."endterminate_interaction1endend
Source
# File lib/rubygems/commands/rebuild_command.rb, line 235defdownload_gem(gem_name,gem_version,old_file)# This code was based loosely off the `gem fetch` command.version ="= #{gem_version}"dep =Gem::Dependency.newgem_name,versionspecs_and_sources,errors =Gem::SpecFetcher.fetcher.spec_for_dependencydep# There should never be more than one item in specs_and_sources,# since we search for an exact version.spec,source =specs_and_sources[0]ifspec.nil?show_lookup_failuregem_name,version,errors,options[:domain]terminate_interaction1enddownload_path =source.downloadspecFileUtils.move(download_path,old_file)say"Downloaded #{gem_name} version #{gem_version} as #{old_file}."end
Source
# File lib/rubygems/commands/rebuild_command.rb, line 227deferror_message(gem_name)ifgem_name"Couldn't find a gemspec file matching '#{gem_name}' in #{Dir.pwd}"else"Couldn't find a gemspec file in #{Dir.pwd}"endend
Source
# File lib/rubygems/commands/rebuild_command.rb, line 177defget_gem_name_and_versionargs =options[:args]|| []ifargs.length==2gem_name,gem_version =argselsifargs.length>2raiseGem::CommandLineError,"Too many arguments"elseraiseGem::CommandLineError,"Expected GEM_NAME and GEM_VERSION arguments (gem rebuild GEM_NAME GEM_VERSION)"end  [gem_name,gem_version]end
Source
# File lib/rubygems/commands/rebuild_command.rb, line 120defget_timestamp(file)mtime =nilFile.open(file,Gem.binary_mode)do|f|Gem::Package::TarReader.new(f)do|tar|mtime =tar.seek("metadata.gz") {|tf|tf.header.mtime }endendmtimeend
Source
# File lib/rubygems/commands/rebuild_command.rb, line 166defprep_dirsrebuild_dir =Dir.mktmpdir("gem_rebuild")old_dir =File.join(rebuild_dir,"old")new_dir =File.join(rebuild_dir,"new")FileUtils.mkdir_p(old_dir)FileUtils.mkdir_p(new_dir)  [old_dir,new_dir]end
Source
# File lib/rubygems/commands/rebuild_command.rb, line 259defrubygems_version(gem_file)Gem::Package.new(gem_file).spec.rubygems_versionend
Source
# File lib/rubygems/commands/rebuild_command.rb, line 116defsha256(file)Digest::SHA256.hexdigest(Gem.read_binary(file))end
Source
# File lib/rubygems/commands/rebuild_command.rb, line 218defwith_source_date_epoch(source_date_epoch)old_sde =ENV["SOURCE_DATE_EPOCH"]ENV["SOURCE_DATE_EPOCH"] =source_date_epoch.to_syieldensureENV["SOURCE_DATE_EPOCH"] =old_sdeend