polyfox/moon-basalt

View on GitHub
lib/basalt/packages.rb

Summary

Maintainability
A
3 hrs
Test Coverage
require 'basalt/version'
require 'basalt/config'
require 'basalt/basaltfile'
require 'basalt/packages/context'
require 'colorize'
require 'docopt'
require 'fileutils'
require 'ostruct'
require 'yaml'

module Basalt
  class Packages
    DOC = %Q(Usage:
  %<binname>s package new [options] NAME
  %<binname>s package install [options] NAME...
  %<binname>s package uninstall [options] NAME...
  %<binname>s package sync [options] NAME...
  %<binname>s package update [options] NAME...
  %<binname>s package list [options]
  %<binname>s package list-available [options]
  %<binname>s package list-installed [options]

Options:
  -f, --basaltfile=BASALTFILE
  -i, --install-method=METHOD
  -v, --verbose
)

    attr_writer :basaltfile

    def initialize(basaltfile = nil)
      @basaltfile = basaltfile || Basaltfile.new
    end

    def basaltfile
      @basaltfile
    end

    def basaltfile_package_map
      @basaltfile.packages.each_with_object({}) { |pkg, hash| hash[pkg.name] = pkg }
    end

    def config
      @config ||= Basalt::Config::Sys.new
    end

    def repoconfig
      @repoconfig ||= OpenStruct.new(pkgdir: basaltfile.pkgdir,
                                     install_method: basaltfile.install_method || config[:install_method])
    end

    def context
      @context ||= Context.new(config.get, repoconfig)
    end

    def generate_packages_list(options = {})
      pkgs = context.repo.installed
      m = basaltfile_package_map
      # only install packages that are listed in the basaltfile spec
      #   TODO move this elsewhere, dunno where yet.
      pkgs.select! { |pkg| m.key?(pkg.pkgname) }
      DependecySolver.solve(pkgs, options)
    end

    def generate_packages_require(options = {})
      m = basaltfile_package_map
      contents = ''
      contents << "# AutoGenerated by Basalt\n"
      contents << "$LOAD_PATH << '#{basaltfile.pkgdir}'\n\n"
      generate_packages_list(options).each do |pkg|
        next unless m[pkg.pkgname].options[:autoload]
        contents << pkg.entry_point_contents
        contents << "\n" unless contents.end_with?("\n")
      end
      filename = File.join(basaltfile.pkgdir, 'load.rb')
      File.write(filename, contents)
      STDERR.puts "\tGENERATED".light_green + "\t#{filename}"
    end

    private def each_basaltfile_package(options = {})
      basaltfile.packages.each do |bpkg|
        yield bpkg, bpkg.options.merge(options)
      end
    end

    def install(options = {})
      each_basaltfile_package(options) do |bpkg, opts|
        context.install(bpkg.name, opts)
      end
      generate_packages_require
    end

    def update(options = {})
      each_basaltfile_package(options) do |bpkg, opts|
        context.update(bpkg.name, opts)
      end
      generate_packages_require
    end

    def sync(options = {})
      each_basaltfile_package(options) do |bpkg, opts|
        context.sync(bpkg.name, opts)
      end
      generate_packages_require
    end

    private def multi_exec(list)
      if list.is_a?(Array)
        list.each do |v|
          begin
            yield v
          rescue
          end
        end
      else
        begin
          yield list
        rescue
        end
      end
    end

    def run(rootfilename, argv, rctx)
      rctx.verbose.puts 'Running package subcommand'
      doc = DOC % ({ binname: rootfilename })
      data = Docopt.docopt(doc, argv: argv, version: VERSION, help: true)

      names = data['NAME']

      options = {}
      options[:basaltfile] = data['--basaltfile'] || rctx[:basaltfile]
      options[:install_method] = data['--install-method'] || rctx[:install_method]
      options[:verbose] = data['--verbose'] || rctx[:verbose]
      rctx.verbose.puts "(#{self.class.name}).options: #{options}"

      if bsf = options[:basaltfile]
        self.basaltfile = Basaltfile.new(bsf)
      end

      if data['new']
        multi_exec(names) { |name| context.new(name, options) }
      elsif data['install']
        multi_exec(names) { |name| context.install(name, options) }
      elsif data['uninstall']
        multi_exec(names) { |name| context.uninstall(name, options) }
      elsif data['sync']
        multi_exec(names) { |name| context.sync(name, options) }
      elsif data['update']
        multi_exec(names) { |name| context.update(name, options) }
      elsif data['list']
        context.list(options)
      elsif data['list-available']
        context.list_available(options)
      elsif data['list-installed']
        context.list_installed(options)
      end
    end
  end
end