class Raygun::Runner

Constants

CARBONFIVE_REPO

Attributes

app_dir[RW]
app_name[RW]
camel_name[RW]
current_ruby_patch_level[RW]
current_ruby_version[RW]
dash_name[RW]
prototype_repo[RW]
snake_name[RW]
target_dir[RW]
title_name[RW]

Public Class Methods

new(target_dir, prototype_repo) click to toggle source
# File lib/raygun/raygun.rb, line 21
def initialize(target_dir, prototype_repo)
  @target_dir     = target_dir
  @app_dir        = File.expand_path(target_dir.strip.to_s)
  @app_name       = File.basename(app_dir).gsub(/\s+/, "-")
  @dash_name      = app_name.tr("_", "-")
  @snake_name     = app_name.tr("-", "_")
  @camel_name     = camelize(snake_name)
  @title_name     = titleize(snake_name)
  @prototype_repo = prototype_repo

  @current_ruby_version     = RUBY_VERSION
  @current_ruby_patch_level = if RUBY_VERSION < "2.1.0" # Ruby adopted semver starting with 2.1.0.
                                "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
                              else
                                RUBY_VERSION.to_s
                              end
end

Protected Class Methods

parse(_args) click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/raygun/raygun.rb, line 252
def parse(_args)
  raygun = nil

  options = OpenStruct.new
  options.target_dir     = nil
  options.prototype_repo = CARBONFIVE_REPO

  parser = OptionParser.new do |opts|
    opts.banner = "Usage: raygun [options] NEW_APP_DIRECTORY"

    opts.on("-h", "--help", "Show raygun usage") do
      usage_and_exit(opts)
    end
    opts.on(
      "-p",
      "--prototype [github_repo]",
      "Prototype github repo (e.g. carbonfive/raygun-rails)."
    ) do |prototype|
      options.prototype_repo = prototype
    end

    opts.on("-v", "--version", "Print the version number") do
      puts Raygun::VERSION
      exit 1
    end
  end

  begin
    parser.parse!
    options.target_dir = ARGV.first

    raise OptionParser::InvalidOption if options.target_dir.nil?

    raygun = Raygun::Runner.new(options.target_dir, options.prototype_repo)
  rescue OptionParser::InvalidOption
    usage_and_exit(parser)
  end

  raygun
end
usage_and_exit(parser) click to toggle source

rubocop:enable Metrics/MethodLength

# File lib/raygun/raygun.rb, line 294
def usage_and_exit(parser)
  puts parser
  exit 1
end

Public Instance Methods

check_raygun_version() click to toggle source
# File lib/raygun/raygun.rb, line 76
def check_raygun_version
  required_raygun_version =
    `tar xfz #{@prototype} --include "*.raygun-version" -O 2> /dev/null`.chomp ||
    ::Raygun::VERSION
  return unless Gem::Version.new(required_raygun_version) > Gem::Version.new(::Raygun::VERSION)

  puts  ""
  print "Hold up!".colorize(:red)
  print " This version of the raygun gem (".colorize(:light_red)
  print "#{::Raygun::VERSION})".colorize(:white)
  print " is too old to generate this application (needs ".colorize(:light_red)
  print required_raygun_version.to_s.colorize(:white)
  puts  " or newer).".colorize(:light_red)
  puts  ""
  print "Please update the gem by running ".colorize(:light_red)
  print "gem update raygun".colorize(:white)
  puts  ", and try again. Thanks!".colorize(:light_red)
  puts  ""
  exit 1
end
check_target() click to toggle source
# File lib/raygun/raygun.rb, line 39
def check_target
  return if Dir["#{@app_dir}/*"].empty?

  puts "Misfire! The target directory isn't empty... aim elsewhere.".colorize(:light_red)
  exit 1
end
clean_up_unwanted_files() click to toggle source
# File lib/raygun/raygun.rb, line 139
def clean_up_unwanted_files
  FileUtils.rm "#{app_dir}/.raygun-version", force: true
end
configure_new_app() click to toggle source
# File lib/raygun/raygun.rb, line 131
def configure_new_app
  clean_up_unwanted_files

  update_ruby_version

  initialize_git
end
copy_prototype() click to toggle source
# File lib/raygun/raygun.rb, line 97
def copy_prototype
  FileUtils.mkdir_p(app_dir)

  shell "tar xfz #{@prototype} -C \"#{app_dir}\""

  # Github includes an extra directory layer in the tag tarball.
  extraneous_dir = Dir.glob("#{app_dir}/*").first
  dirs_to_move   = Dir.glob("#{extraneous_dir}/*", File::FNM_DOTMATCH)
    .reject { |d| %w[. ..].include?(File.basename(d)) }

  FileUtils.mv         dirs_to_move, app_dir
  FileUtils.remove_dir extraneous_dir

  C5Conventions.install(target: app_dir) if @prototype_repo == CARBONFIVE_REPO
end
fetch_prototype() click to toggle source
# File lib/raygun/raygun.rb, line 46
def fetch_prototype
  print "Checking for the latest application prototype...".colorize(:yellow)
  $stdout.flush

  # Check if we can connect, or fail gracefully and use the latest cached version.
  repo        = TemplateRepo.new(prototype_repo)
  name        = repo.name
  tarball_url = repo.tarball
  sha         = repo.sha

  print " #{name}.".colorize(:white)
  $stdout.flush

  cached_prototypes_dir = File.join(Dir.home, ".raygun")
  @prototype = "#{cached_prototypes_dir}/#{name.gsub("/", "--")}-#{sha}.tar.gz"

  # Do we already have the tarball cached under ~/.raygun?
  if File.exist?(@prototype)
    puts " Using cached version.".colorize(:yellow)
  else
    print " Downloading...".colorize(:yellow)
    $stdout.flush

    # Download the tarball and install in the cache.
    Dir.mkdir(cached_prototypes_dir, 0o755) unless Dir.exist?(cached_prototypes_dir)
    shell "curl -s -L #{tarball_url} -o #{@prototype}"
    puts " done!".colorize(:yellow)
  end
end
initialize_git() click to toggle source
# File lib/raygun/raygun.rb, line 153
def initialize_git
  Dir.chdir(app_dir) do
    shell "git init"
    shell "git checkout -q -b main"
    shell "git add -A ."
    shell "git commit -m 'Raygun-zapped skeleton.'"
  end
end
print_next_steps() click to toggle source

rubocop:enable Metrics/AbcSize

print_next_steps_carbon_five() click to toggle source

rubocop:disable Metrics/AbcSize

print_next_steps_for_custom_repo() click to toggle source

rubocop:enable Metrics/AbcSize

print_plan() click to toggle source

rubocop:disable Metrics/AbcSize

rename_new_app() click to toggle source
# File lib/raygun/raygun.rb, line 113
def rename_new_app
  Dir.chdir(app_dir) do
    {
      "AppPrototype"  => camel_name,
      "app-prototype" => dash_name,
      "app_prototype" => snake_name,
      "App Prototype" => title_name
    }.each do |proto_name, new_name|
      shell "find . -type f -print | xargs #{sed_i} 's/#{proto_name}/#{new_name}/g'"
    end

    %w[d f].each do |find_type|
      shell "find . -depth -type #{find_type} -name '*app_prototype*' " \
            "-exec bash -c 'mv $0 ${0/app_prototype/#{snake_name}}' {} \\;"
    end
  end
end
update_ruby_version() click to toggle source
# File lib/raygun/raygun.rb, line 143
def update_ruby_version
  prototype_ruby_patch_level = File.read(File.expand_path("#{app_dir}/.ruby-version", __FILE__)).strip
  prototype_ruby_version     = prototype_ruby_patch_level.match(/(\d\.\d\.\d).*/)[1]

  Dir.chdir(app_dir) do
    shell "#{sed_i} 's/#{prototype_ruby_patch_level}/#{@current_ruby_patch_level}/g' .ruby-version README.md"
    shell "#{sed_i} 's/#{prototype_ruby_version}/#{@current_ruby_version}/g' Gemfile"
  end
end

Protected Instance Methods

camelize(string) click to toggle source
# File lib/raygun/raygun.rb, line 224
def camelize(string)
  result = string.sub(/^[a-z\d]*/) { $&.capitalize }
  result.gsub(%r{(?:_|(/))([a-z\d]*)}) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" }
end
sed_i() click to toggle source

Distinguish BSD vs GNU sed with the –version flag (only present in GNU sed).

# File lib/raygun/raygun.rb, line 235
def sed_i
  @sed_i ||= begin
               `sed --version &> /dev/null`
               $?.success? ? "sed -i" : "sed -i ''"
             end
end
shell(command) click to toggle source

Run a shell command and raise an exception if it fails.

# File lib/raygun/raygun.rb, line 243
def shell(command)
  output = `#{command}`
  raise "#{command} failed with status #{$?.exitstatus}." unless $?.success?

  output
end
titleize(underscored_string) click to toggle source
# File lib/raygun/raygun.rb, line 229
def titleize(underscored_string)
  result = underscored_string.tr("_", " ")
  result.gsub(/\b('?[a-z])/) { Regexp.last_match(1).capitalize }
end