class Roger::Release

The release runner

Attributes

config[R]
project[R]
stack[R]

Public Class Methods

new(project, config = {}) click to toggle source

@option config [:git, :fixed] :scm The SCM to use (default = :git) @option config [String, Pathname] :target_path The path/directory to put the release into @option config [String, Pathname]:build_path Temporary path used to build the release @option config [Boolean] :cleanup_build Wether or not to remove the build_path after we're

done (default = true)

@option config [lambda] :cp Function to be called for copying @option config [Boolean] :blank Keeps the release clean, don't automatically add any

processors or finalizers (default = false)
# File lib/roger/release.rb, line 30
def initialize(project, config = {})
  real_project_path = project.path.realpath
  defaults = {
    scm: :git,
    source_path: project.html_path.realpath,
    target_path: real_project_path + "releases",
    build_path: real_project_path + "build",
    cp: lambda do |source, dest|
      if RUBY_PLATFORM.match("mswin") || RUBY_PLATFORM.match("mingw")
        unless system(["echo d | xcopy", "/E", "/Y", source.to_s.gsub("/", "\\"),
                      dest.to_s.gsub("/", "\\")].join(" "))
          raise "Could not copy build directory using xcopy"
        end
      else
        unless system(Shellwords.join(["cp", "-LR", "#{source}/", dest.to_s]))
          raise "Could not copy build directory using cp"
        end
      end
    end,
    blank: false,
    cleanup_build: true
  }

  @config = {}.update(defaults).update(config)

  @project = project
  @stack = []
end

Public Instance Methods

banner(options = {}) { || ... } click to toggle source

Generates a banner if a block is given, or returns the currently set banner. It automatically takes care of adding comment marks around the banner.

The default banner looks like this:

Version : v1.0.0 =

Date : 2012-06-20 =

@option options [:css,:js,:html,false] :comment Wether or not to comment the output and in

what style. (default=js)
build_path() click to toggle source

Accessor for build_path The build_path is a temporary directory where the release will be built

@return Pathname the build_path

# File lib/roger/release.rb, line 71
def build_path
  Pathname.new(config[:build_path])
end
cleanup(pattern) click to toggle source

Files to clean up in the build directory just before finalization happens

@param [String] Pattern to glob within build directory

@examples

release.cleanup "**/.DS_Store"
# File lib/roger/release.rb, line 135
def cleanup(pattern)
  @stack << Cleaner.new(pattern)
end
comment(string, options = {}) click to toggle source

@param [String] string The string to comment

@option options [:html, :css, :js] :style The comment style to use

(default=:js, which is the same as :css)

@option options [Boolean] :per_line Comment per line or make one block? (default=true)

# File lib/roger/release.rb, line 196
def comment(string, options = {})
  options = {
    style: :css,
    per_line: true
  }.update(options)

  commenters = {
    html: proc { |s| "<!-- #{s} -->" },
    css: proc { |s| "/* #{s} */" },
    js: proc { |s| "/* #{s} */" }
  }

  commenter = commenters[options[:style]] || commenters[:js]

  if options[:per_line]
    string = string.split(/\r?\n/)
    string.map { |s| commenter.call(s) }.join("\n")
  else
    commenter.call(string)
  end
end
finalize(finalizer, options = {}) click to toggle source

Write out the whole release into a directory, zip file or anything you can imagine finalize can be called multiple times, it just will run all of them.

The default finalizer is :dir

@param [Symbol, Proc] Finalizer to use

@examples

release.finalize :zip
# File lib/roger/release.rb, line 125
def finalize(finalizer, options = {})
  @stack << [self.class.get_callable(finalizer, Roger::Release::Finalizers.map), options]
end
inject(variables, options) click to toggle source

Inject variables into files with an optional filter

@examples

release.inject({"VERSION" => release.version, "DATE" => release.date},
  :into => %w{_doc/toc.html})
release.inject({"CHANGELOG" => {:file => "", :filter => BlueCloth}},
  :into => %w{_doc/changelog.html})
# File lib/roger/release.rb, line 104
def inject(variables, options)
  @stack << Injector.new(variables, options)
end
run!() click to toggle source

Actually perform the release

# File lib/roger/release.rb, line 171
def run!
  project.mode = :release

  # Validate paths
  validate_paths!

  # Extract mockup
  copy_source_path_to_build_path!

  validate_stack!

  # Run stack
  run_stack!

  # Cleanup
  cleanup! if config[:cleanup_build]
ensure
  project.mode = nil
end
scm(force = false) click to toggle source

Get the current SCM object

# File lib/roger/release.rb, line 84
def scm(force = false)
  return @_scm if @_scm && !force

  case config[:scm]
  when :git
    @_scm = Release::Scm::Git.new(path: source_path)
  when :fixed
    @_scm = Release::Scm::Fixed.new
  else
    raise "Unknown SCM #{options[:scm].inspect}"
  end
end
source_path() click to toggle source

Accessor for source_path The source path is the root of the project

@return Pathname the source_path

# File lib/roger/release.rb, line 79
def source_path
  Pathname.new(config[:source_path])
end
target_path() click to toggle source

Accessor for target_path The target_path is the path where the finalizers will put the release

@return Pathname the target_path

# File lib/roger/release.rb, line 63
def target_path
  Pathname.new(config[:target_path])
end
use(processor, options = {}) click to toggle source

Use a certain pre-processor

@examples

release.use :sprockets, sprockets_config
# File lib/roger/release.rb, line 112
def use(processor, options = {})
  @stack << [self.class.get_callable(processor, Roger::Release::Processors.map), options]
end

Protected Instance Methods

cleanup!() click to toggle source
# File lib/roger/release.rb, line 312
def cleanup!
  log(self, "Cleaning up build path #{build_path}")
  rm_rf(build_path)
end
copy_source_path_to_build_path!() click to toggle source
# File lib/roger/release.rb, line 292
def copy_source_path_to_build_path!
  if config[:cp]
    config[:cp].call(source_path, build_path)
  else
    mkdir(build_path)
    cp_r(source_path.children, build_path)
  end
end
default_banner() click to toggle source
# File lib/roger/release.rb, line 224
def default_banner
  banner = [
    "Version : #{scm.version}",
    "Date  : #{scm.date.strftime('%Y-%m-%d')}"
  ]

  # Find longest line
  size = banner.map(&:size).max

  # Pad all lines
  banner.map! { |b| "= #{b.ljust(size)} =" }

  div = "=" * banner.first.size
  banner.unshift(div)
  banner << div
end
ensure_clean_build_path!() click to toggle source
# File lib/roger/release.rb, line 252
def ensure_clean_build_path!
  return unless build_path.exist?

  log self, "Cleaning up previous build \"#{build_path}\""
  rm_rf(build_path)
end
ensure_dir_finalizer_in_stack!() click to toggle source
# File lib/roger/release.rb, line 281
def ensure_dir_finalizer_in_stack!
  return if find_in_stack(Roger::Release::Finalizers::Dir)

  @stack.push([Roger::Release::Finalizers::Dir.new, {}])
end
ensure_existing_target_path!() click to toggle source
# File lib/roger/release.rb, line 259
def ensure_existing_target_path!
  return if target_path.exist?

  log self, "Creating target path \"#{target_path}\""
  mkdir target_path
end
ensure_mockup_processor_in_stack!() click to toggle source
# File lib/roger/release.rb, line 275
def ensure_mockup_processor_in_stack!
  return if find_in_stack(Roger::Release::Processors::Mockup)

  @stack.unshift([Roger::Release::Processors::Mockup.new, {}])
end
find_in_stack(klass) click to toggle source

Find a processor in the stack

# File lib/roger/release.rb, line 288
def find_in_stack(klass)
  @stack.find { |(processor, _options)| processor.class == klass }
end
get_files_default_path() click to toggle source
# File lib/roger/release.rb, line 220
def get_files_default_path
  build_path
end
run_stack!() click to toggle source
# File lib/roger/release.rb, line 301
def run_stack!
  # call all objects in @stack
  @stack.each do |task|
    if task.is_a?(Array)
      task[0].call(self, task[1])
    else
      task.call(self)
    end
  end
end
validate_paths!() click to toggle source

Checks if build path exists (and cleans it up) Checks if target path exists (if not, creates it)

# File lib/roger/release.rb, line 247
def validate_paths!
  ensure_clean_build_path!
  ensure_existing_target_path!
end
validate_stack!() click to toggle source

Checks if the project will be runned If config is true it will automatically add Mockup processor

# File lib/roger/release.rb, line 268
def validate_stack!
  return if config[:blank]

  ensure_mockup_processor_in_stack!
  ensure_dir_finalizer_in_stack!
end