class Installer

Constants

BIT64
BUILD_DIR
CONFIG
DISTFILES_DIR
GEM_INSTALL_FILES
HOSED_VERSIONS

Mysterious “ghost” releases which lack files

P4API_REMOTE_BASENAME
P4RUBY_REMOTE_BASENAME
RAW_INSTALL_FILES
RB_BASENAME
SERVER
SERVER_TOP_DIR
SO_BASENAME
WORK_DIR

Public Instance Methods

build() click to toggle source
# File install.rb, line 325
def build
  puts "building..."
  rm_rf(BUILD_DIR)
  mkdir_p(BUILD_DIR)

  @s.specs.each { |spec|
    unpack(spec.local, BUILD_DIR)
  }

  Dir.chdir(BUILD_DIR) {
    api_dir = Pathname.glob("p4api*").last
    p4ruby_dir = Pathname.glob("p4ruby*").last
    Dir.chdir(p4ruby_dir) {
      ruby("p4conf.rb", "--apidir", "../#{api_dir}")
      make
    }
    @s.p4ruby_build_dir = BUILD_DIR + p4ruby_dir
  }
end
config() click to toggle source
# File install.rb, line 112
def config
  if CONFIG["LIBRUBYARG_SHARED"].empty?
    raise "error: ruby must be configured with --enable-shared"
  end

  @s.ftp = Net::FTP.new(SERVER).tap { |t|
    t.passive = true
    t.login
  }

  @s.p4api =  LazyStruct.new.tap { |t|
    t.basename = P4API_REMOTE_BASENAME
  }

  @s.p4ruby = LazyStruct.new.tap { |t|
    t.basename = P4RUBY_REMOTE_BASENAME
  }

  @s.specs = [ @s.p4ruby, @s.p4api ]
  @s.specs.each { |spec|
    spec.local = DISTFILES_DIR + spec.basename
  }
  
  unless @s.version
    @s.version = latest_version
  end

  @s.version_dir = SERVER_TOP_DIR + "r#{@s.version}"

  unless @s.platform
    @s.platform = guess_platform
  end

  if @s.platform =~ %rnt/
    @s.p4api.remote = @s.version_dir + "bin.#{@s.platform}"
  else
    @s.p4api.remote = @s.version_dir + "bin.#{@s.platform}" + @s.p4api.basename
    @s.p4ruby.remote = @s.version_dir + "bin.tools" + @s.p4ruby.basename
  end


end
fetch() click to toggle source
# File install.rb, line 270
def fetch
  @s.specs.each { |spec|
    fetch_spec(spec)
  }
end
fetch_spec(spec) click to toggle source
# File install.rb, line 262
def fetch_spec(spec)
  unless @s.local
    mkdir_p(spec.local.dirname)
    puts "downloading ftp://#{SERVER}/#{spec.remote} ..."
    @s.ftp.getbinaryfile(spec.remote.to_s, spec.local.to_s)
  end
end
find_ruby_version(spec) click to toggle source
# File install.rb, line 386
def find_ruby_version(spec)
  remote_files_matching(spec.remote, %rp4ruby\d\d.exe/) {|r_ver|

    #Find the latest version of p4ruby for this version of ruby
    v_max = CONFIG["MAJOR"]
    v_min = CONFIG["MINOR"]
    version = [v_max, v_min].join
    if r_ver.to_s =~ %rp4ruby#{version}.exe/
      return "p4ruby#{version}.exe"
    end

  }
  nil
end
guess_cpu() click to toggle source
# File install.rb, line 155
def guess_cpu
  if CONFIG["target_os"] =~ %rdarwin!
    if CONFIG["build"] =~ %ri686|x86_64/
      "x86_64"
    else
      "x86"
    end
  else
    case CONFIG["target_cpu"]
    when %ria!
      "ia64"
    when %r86!
      # note: with '_'
      "x86" + (BIT64 ? "_64" : "")
    when %r(ppc|sparc)!
      # note: without '_'
      $1 + (BIT64 ? "64" : "")
    else
      ""
    end
  end
end
guess_platform(opts = {}) click to toggle source
# File install.rb, line 199
def guess_platform(opts = {})
  config_os = CONFIG["target_os"].downcase
  windows_cpu = BIT64 ? "x64" : "x86"

  if config_os =~ %rcygwin!
    "cygwin" + windows_cpu
  elsif config_os =~ %r(mswin|mingw)!
    "nt" + windows_cpu
  elsif @s.local
    "<local>"
  else
    if match = config_os.match(%r\A\D+!)
      guess_version(match[0])
    else
      nil
    end
  end
end
guess_version(os) click to toggle source
# File install.rb, line 178
def guess_version(os)
  if match = %xuname -a`.match(%r#{os}\s+\S+\s+(\d+)\.(\d+)!)
    version = match.captures.join
    cpu = guess_cpu
    platforms = self.platforms
    built_platforms = (0..version.to_i).map { |n|
      [os, n.to_s, cpu].join
    }.select { |platform|
      platforms.include? platform
    }
    if os =~ %rdarwin/
      built_platforms.pop
      built_platforms.last
    else
      built_platforms.last
    end
  else
    nil
  end
end
install() click to toggle source
# File install.rb, line 353
def install
  puts "installing..."
  Dir.chdir(@s.p4ruby_build_dir) {
    make("install")
  }
  if @s.gem_config
    raw_install_to_gem_install
  end
end
install_fail() { || ... } click to toggle source
# File install.rb, line 245
def install_fail
  yield
  exit(1)
end
latest_version() click to toggle source
# File install.rb, line 304
def latest_version
  versions.reverse_each{ |v|
    begin
      remote_files_matching("#{SERVER_TOP_DIR}/r#{v}/bin.tools",%rp4ruby/) do
        return v
      end
    rescue
      next
    end
  }
end
make(*args) click to toggle source
# File install.rb, line 316
def make(*args)
  sys("make", *args)
end
parse_command_line() click to toggle source
# File install.rb, line 46
def parse_command_line
  OptionParser.new("Usage: ruby install.rb [options]", 24, "") {
    |parser|
    parser.on(
      "--version NN.N",
      "Version to download, e.g. 08.1. Default finds latest.") {
      |version|
      @s.version = version
    }
    parser.on(
      "--list-versions",
      "List available versions.") {
      @s.list_versions = true
    }
    parser.on(
      "--platform PLATFORM",
      "Perforce-named platform to download. Default guesses.") {
      |platform|
      @s.platform = platform
    }
    parser.on(
      "--list-platforms",
      "List available platforms for the given version.") {
      @s.list_platforms = true
    }
    parser.on(
      "--gem",
      "Gem configuration (for the gem installer).") {
      @s.gem_config = true
    }
    parser.on(
      "--uninstall",
      "Uninstall.") {
      @s.uninstall = true
    }
    parser.on(
      "--local",
      "Use the files in work/distfiles (manual download).") {
      @s.local = true
    }
    parser.parse(ARGV)
  }
end
platform_fail() click to toggle source
# File install.rb, line 218
def platform_fail
  install_fail {
    @s.version = "<version>"
    @s.platform = "<platform>"
    message = %Q{
      Auto-fetch not yet handled for this platform.  Run:
  
      \truby install.rb --list-platforms
  
      to see the available platforms, then run
  
      \truby install.rb --platform PLATFORM
  
      with your platform.
  
      If all of the above fails, manually fetch
  
      \tftp://#{SERVER}/#{@s.p4api.remote}
  
      Copy it to #{@s.p4api.local} and run install.rb --local.
    }.gsub(%r^ +(?=\S)!, "")

    mkdir_p(DISTFILES_DIR)
    puts message
  }
end
platforms() click to toggle source
# File install.rb, line 288
def platforms
  remote_files_matching(@s.version_dir, %rbin\.(\w+)!) { |match|
    match.captures.first
  }.reject { |platform|
    platform =~ %rjava!
  }.sort
end
raw_install_to_gem_install() click to toggle source
# File install.rb, line 345
def raw_install_to_gem_install
  RAW_INSTALL_FILES.zip(GEM_INSTALL_FILES) { |source, dest|
    mkdir_p(dest.dirname)
    puts "move #{source} --> #{dest}"
    mv(source, dest)
  }
end
remote_files_matching(dir, regex) { |match| ... } click to toggle source
# File install.rb, line 276
def remote_files_matching(dir, regex)
  @s.ftp.ls(dir.to_s).map { |entry|
    if match = entry.match(regex)
      yield match
    else
      nil
    end
  }.reject { |entry|
    entry.nil?
  }
end
ruby(*args) click to toggle source
# File install.rb, line 320
def ruby(*args)
  exe = Pathname.new(CONFIG["bindir"]) + CONFIG["RUBY_INSTALL_NAME"]
  sys(exe.to_s, *args)
end
run() click to toggle source
# File install.rb, line 90
def run
  @s = LazyStruct.new
  parse_command_line
  config
  if @s.uninstall
    uninstall
  elsif @s.list_platforms
    puts platforms
  elsif @s.list_versions
    puts versions
  elsif @s.platform.nil?
    platform_fail
  elsif @s.platform =~ %r\Ant!
    windows_install
  else
    fetch
    build
    install
    verify_install
  end
end
sys(*args) click to toggle source
# File install.rb, line 250
def sys(*args)
  system(*args).tap { |result|
    unless result
      raise "system() failed: #{args.join(" ")}"
    end
  }
end
uninstall() click to toggle source
# File install.rb, line 439
def uninstall
  RAW_INSTALL_FILES.each { |file|
    if file.exist?
      puts "delete #{file}"
      rm_f(file)
    end
  }
end
unpack(distfile, target_dir) click to toggle source
# File install.rb, line 258
def unpack(distfile, target_dir)
  sys("tar", "zxvf", distfile.to_s, "-C", target_dir.to_s)
end
verify_install(on_error = nil) click to toggle source
# File install.rb, line 363
def verify_install(on_error = nil)
  puts "verifying..."
  files =
    if @s.gem_config
      GEM_INSTALL_FILES
    else
      RAW_INSTALL_FILES
    end.map { |t| t.expand_path }

  if files.all? { |t| t.exist? }
    puts "Installed files:"
    puts files
  elsif on_error
    install_fail(&on_error)
  else
    install_fail {
      puts "These files were supposed to be installed, but were not:"
      puts files
      puts "Install failed!"
    }
  end
end
versions() click to toggle source
# File install.rb, line 296
def versions
  remote_files_matching(SERVER_TOP_DIR, %rr([0-8]\d\.\d)!) { |match|
    match.captures.first
  }.reject { |version|
    HOSED_VERSIONS.include? version
  }.sort
end
windows_install() click to toggle source
# File install.rb, line 401
def windows_install
  #
  # For Windows, p4ruby is located in the p4api directory on the
  # perforce server -- switcharoo --
  #
  spec = @s.p4api
  
  p4ruby_exe = find_ruby_version(spec)
  if p4ruby_exe && !(spec.remote.to_s =~ %rp4ruby/)
    spec.remote += p4ruby_exe.to_s
  else
    abort("Failed to find a suitable p4ruby executable for ruby #{CONFIG["MAJOR"]}.#{CONFIG["MINOR"]}")
  end
  fetch_spec(spec)

  error = lambda {
    puts "The Perforce P4Ruby Windows installer failed!"
    puts "You may re-run it manually here:"
    puts spec.local.expand_path
  }

  puts "running Perforce P4Ruby Windows installer..."
  if system(spec.local.to_s, "/S", "/v/qn")
    if @s.gem_config
      sleep(1)
      raw_install_to_gem_install
      sleep(1)
      unless system(spec.local, "/V", "/x", "/S", "/v/qn")
        # We don't much care if this fails; just write to the log
        puts "Note: the Perforce P4Ruby Windows uninstaller failed."
      end
    end
    verify_install(error)
  else
    install_fail(&error)
  end
end