class AppStack::App

represent a single stacked application

reopen app class, extend with load_compare list function

mixin app class for build copy list rubocop:disable MethodLength

Attributes

app_stacks[R]
attrs[R]
compare_list[R]
conf_file[R]
config[R]
copy_list[R]
diff_list[R]
export_groups[R]
import_list[R]
rel_path[RW]
render_list[R]
sync_list[R]

Public Class Methods

new(filename = nil, app_dir = nil) click to toggle source
# File lib/app_stack/app.rb, line 13
def initialize(filename = nil, app_dir = nil)
  @conf_file, @app_dir = filename, app_dir
  @config = load_config
  info 'loaded configuration: ', @config

  @app_stacks = {}
  @compare_list = []
  @attrs = {}
end

Public Instance Methods

app_name() click to toggle source

use the direct name of the config file as app name

# File lib/app_stack/app.rb, line 66
def app_name
  directory && File.basename(directory)
end
build_copy_list!() click to toggle source
# File lib/app_stack/operator.rb, line 7
def build_copy_list!
  @copy_list, @diff_list = [], []
  compare_list.each do |f|
    info f.label
    if File.exists?(f.to_file)
      if f.import?
        info f.skip('target exists')
        next
      end

      if f.diff?
        info f.label, 'add to diff list'
        @diff_list << f
      else
        info f.skip('not changed')
        next
      end
    end
    info f.label, 'add to copy list'
    @copy_list << f
  end
end
directory() click to toggle source
# File lib/app_stack/app.rb, line 60
def directory
  @app_dir ||= (conf_file && File.dirname(conf_file))
  File.expand_path(@app_dir)
end
do_print!() click to toggle source
# File lib/app_stack/operator.rb, line 55
def do_print!
  print_list = {}
  compare_list.each do |f|
    next unless File.exists?(f.to_file)

    print_list[f.to_file] = f
  end

  mapper = {}
  app_stacks.keys.each { |k| mapper[k] = [] }
  print_list.keys.sort.each do |k|
    f = print_list[k]
    mapper[f.from_app.app_name] << f
  end

  mapper.each do |k, list|
    puts "From #{k.to_s.bold.green}"
    list.each { |f| puts "  - #{f.to_file_short_name.blue}" }
  end
end
do_reverse!() click to toggle source
# File lib/app_stack/operator.rb, line 39
def do_reverse!
  @rev_list = {}
  @diff_list.each_with_index do |f, i|
    f.reverse!
    puts "[#{i + 1}] " + f.reverse_label
    @rev_list[i + 1] = f
  end

  return unless @rev_list.keys.size > 0
  puts "Which file you want to copy reversely?"
  print "(1 2 ...):"
  lists = gets.chomp.split(/\s+/)
  lists.each { |i| fail "unknown option #{i}" unless @rev_list[i.to_i] }
  lists.each { |i| @rev_list[i.to_i].process }
end
get_file_path(fp) click to toggle source

rubocop:enable LineLength, MethodLength

# File lib/app_stack/compare_list.rb, line 205
def get_file_path(fp)
  File.expand_path(fp, directory)
end
get_group_files(group, app) click to toggle source
# File lib/app_stack/compare_list.rb, line 186
def get_group_files(group, app)
  file_list = []
  export_groups[group.to_s].each do |fp|
    if fp.match(/[\?\*\+\{\}]+/)
      Dir[get_file_path(fp)].each { |f| file_list << f }
    else
      file = get_file_path(fp)

      if File.exists?(file)
        file_list << file
      else
        warn "[WARN] #{fp.blue} not found for #{app.app_name.bold}, group #{group.bold}, skip."
      end
    end
  end
  file_list
end
info(msg, var = nil) click to toggle source

echo message only if verbose specified to be true rubocop:disable CyclomaticComplexity

# File lib/app_stack/app.rb, line 72
def info(msg, var = nil)
  return unless options && options.verbose

  msg = "[#{app_name || self.class.name}] ".green + msg
  msg += "\n" if var && var.inspect.size > 30

  print msg
  if var
    print Term::ANSIColor.bold
    var.inspect.size > 30 ? PP.pp(var) : PP.singleline_pp(var)
    print Term::ANSIColor.reset
  end
  puts unless var && var.inspect.size > 30
end
load_compare_list!() click to toggle source
# File lib/app_stack/compare_list.rb, line 113
def load_compare_list!
  # @import_list.merge(@sync_list).merge(@render_list
  load_copy_list!(@import_list, import: true)
  load_copy_list!(@sync_list)
  load_render_list!(@render_list, render: true)
  load_local_render_list!(render: true)
end
load_copy_list!(list, opts = {}) click to toggle source
# File lib/app_stack/compare_list.rb, line 121
def load_copy_list!(list, opts = {})
  list.each do |app, exp|
    exp.each do |p| # string as group name or hash as file mapping
      opts.merge! from_app: @app_stacks[app.to_s], to_app: self
      p.is_a?(String) ? load_group!(p, opts) : load_file_map!(p, opts)
    end
  end
end
load_file_map!(hsh, opts) click to toggle source
# File lib/app_stack/compare_list.rb, line 172
def load_file_map!(hsh, opts)
  hsh.each do |f, t|
    t = f unless t && t.size > 0
    from_file = opts[:from_app].get_file_path(f)
    if File.exists?(from_file)
      @compare_list << CompareFile.new(
        opts.merge(from_file: opts[:from_app].get_file_path(f),
                   to_file: opts[:to_app].get_file_path(t)))
    else
      warn "[WARN] #{f.blue} not found in #{opts[:from_app].app_name.bold}, skip."
    end
  end
end
load_group!(group, opts) click to toggle source

rubocop:disable LineLength

# File lib/app_stack/compare_list.rb, line 164
def load_group!(group, opts)
  app = opts[:from_app]
  fail ParseError, "Error on #{@conf_file}, #{app.app_name.bold} did not export group #{group.bold}" unless app.export_groups[group.to_s]
  app.get_group_files(group, opts[:from_app]).each do |full_path|
    @compare_list << CompareFile.new(opts.merge(from_file: full_path))
  end
end
load_local_render_list!(opts = {}) click to toggle source
# File lib/app_stack/compare_list.rb, line 149
def load_local_render_list!(opts = {})
  config.render_local.each do |fr, to|
    from_file = get_file_path(fr)
    to = fr.sub(/\.(erb|liquid|slim)$/, '') unless to.size > 0
    if File.exists?(from_file)
      @compare_list << CompareFile.new(
        opts.merge(from_app: self, to_app: self,
                   from_file: from_file, to_file: get_file_path(to)))
    else
      warn "[WARN] #{fr.blue} not found in #{app_name.bold} (local), skip."
    end
  end
end
load_render_list!(list, opts = {}) click to toggle source

rubocop:disable MethodLength

# File lib/app_stack/compare_list.rb, line 131
def load_render_list!(list, opts = {})
  list.each do |appname, hsh|
    app = @app_stacks[appname.to_s]
    hsh.each do |fr, to|
      to = fr.sub(/\.(erb|liquid|slim)$/, '') unless to.size > 0
      from_file = app.get_file_path(fr)
      if File.exists?(from_file)
        @compare_list << CompareFile.new(
          opts.merge(from_app: app, to_app: self,
                     from_file: from_file,
                     to_file: get_file_path(to)))
      else
        warn "[WARN] #{fr.blue} not found in #{app.app_name.bold}, skip."
      end
    end
  end
end
load_stack!() click to toggle source

rubocop:disable MethodLength

# File lib/app_stack/app.rb, line 24
def load_stack!
  # load_stack.each ...
  validate_config!

  # parse all stacks
  @import_list.merge(@sync_list).merge(@render_list).keys.each do |app|
    app_dir = File.expand_path(app, File.join(directory, config.stack_dir))
    # rubocop:disable LineLength
    fail ParseError, "Error on #{@conf_file}, stack app #{app} not found in #{app_dir}" unless File.directory?(app_dir)
    # rubocop:enable LineLength
    @app_stacks[app] = App.new(AppStack.find_conf_file(app_dir), app_dir)
    @app_stacks[app].rel_path = File.join(directory, config.stack_dir, app)
    @app_stacks[app].parse_export_groups!
    @attrs = @attrs.deep_merge @app_stacks[app].config.attrs

    # info "load app #{app.bold} as", @app_stacks[app]
    info "load app #{app.bold}"
  end

  @attrs = @attrs.deep_merge config.attrs
  info 'merged attrs', attrs
  @app_stacks
end
merge!() click to toggle source
# File lib/app_stack/operator.rb, line 30
def merge!
  case
  when AppStack.options.print then do_print!
  when AppStack.options.force then do_copy!
  when AppStack.options.simulate then do_simulate!
  else diff_list.size > 0 ? do_warn : do_copy!
  end
end
options() click to toggle source
# File lib/app_stack/app.rb, line 56
def options
  AppStack.options
end
stackup!() click to toggle source

rubocop:enable MethodLength

# File lib/app_stack/app.rb, line 49
def stackup!
  load_stack!
  load_compare_list!
  build_copy_list!
  options.reverse ? do_reverse! : merge!
end

Private Instance Methods

do_copy!() click to toggle source
# File lib/app_stack/operator.rb, line 78
def do_copy!
  @copy_list.map(&:process)
end
do_simulate!() click to toggle source
# File lib/app_stack/operator.rb, line 82
def do_simulate!
  @copy_list.each { |f| puts f.label }
end
do_warn() click to toggle source
# File lib/app_stack/operator.rb, line 86
def do_warn
  puts 'These files are changed remotely:'
  i = 1
  @diff_list.each do |f|
    puts "[#{i.to_s.bold}] " + f.to_file_short_name.blue
    puts "<- #{f.from_app.app_name.bold.blue} (#{f.from_file_short_name})"
    puts f.diff.to_s(:color)
    i += 1
  end
  puts 'use -f (--force) option to overwrite all files.'
end