diff --git a/Rakefile b/Rakefile index 674bfb4..df28bde 100644 --- a/Rakefile +++ b/Rakefile @@ -87,3 +87,25 @@ task "man" do generate_man("doc/man/pione-action-list.md", "man/pione-action-list.1") generate_man("doc/man/pione-list-param.md", "man/pione-list-param.1") end + +# +# Completion +# + +desc "generate bash completion file" +task "completion:bash" do + require 'pione/util/completion' + misc = Pione::Location[File.dirname(__FILE__)] + "misc" + source = misc + "pione-completion.erb" + target = misc + "pione-completion.bash" + Pione::Util::BashCompletion.compile(source, target) +end + +desc "generate zsh completion file" +task "completion:zsh" do + require 'pione/util/completion' + misc = Pione::Location[File.dirname(__FILE__)] + "misc" + source = misc + "pione-completion.erb" + target = misc + "pione-completion.zsh" + Pione::Util::ZshCompletion.compile(source, target) +end diff --git a/lib/pione/command.rb b/lib/pione/command.rb index 19f76aa..f958a57 100644 --- a/lib/pione/command.rb +++ b/lib/pione/command.rb @@ -17,14 +17,5 @@ module Command; end require 'pione/command/pione-relay' require 'pione/command/pione-relay-client-db' require 'pione/command/pione-relay-account-db' -require 'pione/command/pione-clean' # pione clean require 'pione/command/pione-syntax-checker' -require 'pione/command/pione-log' # pione log -require 'pione/command/pione-val' # pione-val -require 'pione/command/pione-package' require 'pione/command/pione-compiler' -require 'pione/command/pione-update-package-info' # pione update-package-info -require 'pione/command/pione-action' # pione action -require 'pione/command/pione-action-list' # pione action:list -require 'pione/command/pione-list-param' # pione list-param -require 'pione/command/pione-config' diff --git a/lib/pione/command/basic-command.rb b/lib/pione/command/basic-command.rb index 58da468..4ce3ad5 100644 --- a/lib/pione/command/basic-command.rb +++ b/lib/pione/command/basic-command.rb @@ -14,9 +14,11 @@ class << self attr_reader :execution_actions attr_reader :termination_actions attr_reader :exception_handler + attr_reader :subcommand def inherited(subclass) subclass.instance_eval do + @subcommand = {} @phase_option = {:init => {}, :setup => {}, :execution => {}, :termination => {}} @option_definition = OptionDefinition.new @command_name = nil @@ -29,6 +31,7 @@ def inherited(subclass) @execution_actions = Array.new @termination_actions = Array.new @exception_handler = {:init => {}, :setup => {}, :execution => {}, :termination => {}} + @toplevel = false # define init phase actions init :process_name @@ -43,6 +46,15 @@ def option_parser_mode(mode) @option_definition.parser_mode = mode end + # Set toplvel command. + def toplevel(b) + @toplevel = b + end + + def toplevel? + @toplevel + end + # Set progaram name or return the name. def command_name(name=nil, &b) if name @@ -72,6 +84,10 @@ def command_front(front_class=nil, &b) end end + def define_subcommand(name, subclass) + @subcommand[name] = subclass + end + forward :@option_definition, :use, :use_option forward :@option_definition, :define, :define_option forward :@option_definition, :item, :option_item @@ -160,7 +176,7 @@ def register_action(phase_actions, action, option={}) attr_accessor :action_type forward! :class, :option_definition, :command_name, :command_name_block - forward! :class, :command_banner, :command_front, :command_front_block + forward! :class, :command_banner, :command_front, :command_front_block, :subcommand def initialize(argv) @argv = argv @@ -184,6 +200,22 @@ def current_phase # Run 4 phase lifecycle of the command. This fires actions in each phase. def run + # check subcommand + if subcommand.size > 0 + if name = @argv.first + if subcommand.has_key?(name) + return subcommand[name].run(@argv.drop(1)) + else + unless name[0] == "-" + abort("no such subcommand: %s" % name) + end + end + else + abort("require a subcommand name") + end + end + + # run this command @running_thread = Thread.current enter_phase(:init) enter_phase(:setup) diff --git a/lib/pione/command/option.rb b/lib/pione/command/option.rb index d28316e..0a4e974 100644 --- a/lib/pione/command/option.rb +++ b/lib/pione/command/option.rb @@ -41,6 +41,7 @@ def use(item_name, option={}) # OptionDefinition is a class for holding option definitions. class OptionDefinition + attr_reader :items attr_accessor :parser_mode # Creata a command option context. @@ -64,18 +65,39 @@ def parse(argv, cmd) OptionParser.new do |opt| # set banner opt.banner = "Usage: %s [options]" % cmd.command_name - opt.banner << "\n\n" + cmd.command_banner + "\n" if cmd.command_banner + opt.banner << "\n" + cmd.command_banner + "\n" if cmd.command_banner # set version opt.program_name = cmd.command_name opt.version = Pione::VERSION + if cmd.subcommand.size > 0 + size = cmd.subcommand.keys.max_by{|key| key.size}.size + + # show subcommand banner + opt.separator("") + opt.separator("Subcommands:") + + # show subcommand list + cmd.subcommand.each do |key, val| + opt.separator(opt.summary_indent + ("%-#{size}s" % key) + opt.summary_indent + val.command_banner) + end + end + + # show options banner + opt.separator("") + opt.separator("Options:") + # default values @items.each {|item| data[item.name] = item.default if item.default} data.merge!(@default) # setup option parser @items.sort{|a,b| a.long <=> b.long}.each {|item| setup_item(cmd, opt, data, item)} + + # show default options + opt.on("--help", "show this help") { puts opt.help; cmd.terminate } + opt.on("--version", "show PIONE version") { puts opt.version; cmd.terminate } end.send(@parser_mode, argv) # check option's validness diff --git a/lib/pione/command/pione-action-exec.rb b/lib/pione/command/pione-action-exec.rb new file mode 100644 index 0000000..072da86 --- /dev/null +++ b/lib/pione/command/pione-action-exec.rb @@ -0,0 +1,79 @@ +module Pione + module Command + # PioneActionExec is a command that executes action from outside of rule + # engine. + class PioneActionExec < BasicCommand + # + # basic informations + # + + command_name "pione action exec" + command_banner "execute an action in literate action document" + + # + # options + # + + use_option :color + use_option :debug + + define_option(:domain) do |item| + item.long = "--domain" + item.desc = "use the domain information file" + item.default = Location["./domain.dump"] + item.value = lambda {|b| b} + end + + define_option(:directory) do |item| + item.short = "-d" + item.long = "--directory PATH" + item.desc = "execute in the PATH" + item.value = lambda {|b| Location[b]} + end + + # + # command lifecycle: setup phase + # + + setup :source + setup :action_name + setup :domain + + # Setup location of literate action document and action name. + def setup_source + abort("There are no literate action documents or packages.") if @argv[0].nil? + @location = Location[@argv[0]] + end + + # Setup action name. + def setup_action_name + abort("There is no action name.") if @argv[1].nil? + @name = @argv[1] + end + + # Load a domain information file. + def setup_domain + if option[:domain].exist? + @domain_info = System::DomainInfo.read(option[:domain]) + end + end + + # + # command lifecycle: execution phase + # + + execute :exec + + # Update pacakge info files. + def execute_exec + if action = LiterateAction::Document.load(@location).find(@name) + action.execute(@domain_info, option[:directory]) + else + abort("The action not found.") + end + rescue Location::NotFound => e + abot(e.message) + end + end + end +end diff --git a/lib/pione/command/pione-action-list.rb b/lib/pione/command/pione-action-list.rb index 0d7710e..a1f777a 100644 --- a/lib/pione/command/pione-action-list.rb +++ b/lib/pione/command/pione-action-list.rb @@ -7,9 +7,8 @@ class PioneActionList < BasicCommand # basic informations # - command_name "pione action:list" - command_banner "show list of action names in document" - PioneCommand.add_subcommand("action:list", self) + command_name "pione action list" + command_banner "list action names in document" # # options @@ -17,6 +16,13 @@ class PioneActionList < BasicCommand use_option :color + define_option(:compact) do |item| + item.long = "--compact" + item.desc = "one line list" + item.default = false + item.value = lambda {|b| b} + end + # # command lifecycle: setup phase # @@ -41,7 +47,11 @@ def execute_show_list if names.empty? abort("no action names in %s" % @location.address) else - names.each {|name| puts name} + if option[:compact] + puts names.join(" ") + else + names.each {|name| puts name} + end end end end diff --git a/lib/pione/command/pione-action-print.rb b/lib/pione/command/pione-action-print.rb new file mode 100644 index 0000000..f39a461 --- /dev/null +++ b/lib/pione/command/pione-action-print.rb @@ -0,0 +1,70 @@ +module Pione + module Command + # `PioneActionPrint` is a command that prints action contents. + class PioneActionPrint < BasicCommand + # + # basic informations + # + + command_name "pione action print" + command_banner "print action contents" + + # + # options + # + + use_option :color + + define_option(:domain) do |item| + item.long = "--domain" + item.desc = "use the domain information file" + item.default = Location["./domain.dump"] + item.value = lambda {|b| b} + end + + # + # command lifecycle: setup phase + # + + setup :source + setup :action_name + setup :domain + + # Setup source location. + def setup_source + abort("There are no literate action documents or packages.") if @argv[0].nil? + @location = Location[@argv[0]] + end + + # Setup action name. + def setup_action_name + abort("There is no action name.") if @argv[1].nil? + @name = @argv[1] + end + + # Load a domain information file. + def setup_domain + if option[:domain].exist? + @domain_info = System::DomainInfo.read(option[:domain]) + end + end + + # + # command lifecycle: execution phase + # + + execute :print + + # Print the action contents. + def execute_print + if action = LiterateAction::Document.load(@location).find(@name) + puts action.textize(@domain_info) + else + abort("The action not found.") + end + rescue Location::NotFound => e + abot(e.message) + end + end + end +end diff --git a/lib/pione/command/pione-action.rb b/lib/pione/command/pione-action.rb index b4d14fd..4d80517 100644 --- a/lib/pione/command/pione-action.rb +++ b/lib/pione/command/pione-action.rb @@ -1,3 +1,7 @@ +require 'pione/command/pione-action-exec' +require 'pione/command/pione-action-list' +require 'pione/command/pione-action-print' + module Pione module Command # PioneAction is a command definition of "pione action" for executing @@ -9,75 +13,14 @@ class PioneAction < BasicCommand command_name "pione action" command_banner "execute an action in literate action document" - PioneCommand.add_subcommand("action", self) - - # - # options - # - - use_option :color - use_option :debug - - define_option(:domain) do |item| - item.long = "--domain" - item.desc = "use the domain information file" - item.default = Location["./domain.dump"] - item.value = lambda {|b| b} - end - - define_option(:show) do |item| - item.long = "--show" - item.desc = "show the action without execution" - item.value = lambda {|b| b} - end - - define_option(:directory) do |item| - item.short = "-d" - item.long = "--directory PATH" - item.desc = "execute in the PATH" - item.value = lambda {|b| Location[b]} - end # - # command lifecycle: setup phase + # subcommands # - setup :target - setup :domain - - # Setup location of literate action document and action name. - def setup_target - abort("There are no literate action documents or packages.") if @argv[0].nil? - abort("Action name is needed.") if @argv[1].nil? - @location = Location[@argv[0]] - @name = @argv[1] - end - - # Load a domain information file. - def setup_domain - if option[:domain].exist? - @domain_info = System::DomainInfo.read(option[:domain]) - end - end - - # - # command lifecycle: execution phase - # - - execute :exec - - # Update pacakge info files. - def execute_exec - if action = LiterateAction::Document.load(@location).find(@name) - if option[:show] - puts action.textize(@domain_info) - else - action.execute(@domain_info, option[:directory]) - end - else - abort(e.message) - end - end + define_subcommand("exec", PioneActionExec) + define_subcommand("list", PioneActionList) + define_subcommand("print", PioneActionPrint) end end end diff --git a/lib/pione/command/pione-broker.rb b/lib/pione/command/pione-broker.rb index 4509d12..4d2ebf6 100644 --- a/lib/pione/command/pione-broker.rb +++ b/lib/pione/command/pione-broker.rb @@ -8,6 +8,7 @@ class PioneBroker < BasicCommand # basic informations # + toplevel true command_name("pione-broker") do |cmd| "front: %s, task_worker: %s" % [Global.front.uri, cmd.option[:task_worker]] end diff --git a/lib/pione/command/pione-clean.rb b/lib/pione/command/pione-clean.rb index d4a8ad5..00f28a0 100644 --- a/lib/pione/command/pione-clean.rb +++ b/lib/pione/command/pione-clean.rb @@ -9,7 +9,6 @@ class PioneClean < BasicCommand command_name "pione-clean" command_banner "remove PIONE's temporary files, cache, and etc." - PioneCommand.add_subcommand("clean", self) # # options diff --git a/lib/pione/command/pione-client.rb b/lib/pione/command/pione-client.rb index 7593299..b07e8ac 100644 --- a/lib/pione/command/pione-client.rb +++ b/lib/pione/command/pione-client.rb @@ -8,6 +8,7 @@ class PioneClient < BasicCommand # basic informations # + toplevel true command_name("pione-client") {|cmd| "front: %s" % Global.front.uri} command_banner "Process PIONE document." command_front Front::ClientFront diff --git a/lib/pione/command/pione-command.rb b/lib/pione/command/pione-command.rb index 8999ad0..6edd736 100644 --- a/lib/pione/command/pione-command.rb +++ b/lib/pione/command/pione-command.rb @@ -1,24 +1,21 @@ +require 'pione/command/pione-action' +require 'pione/command/pione-clean' +require 'pione/command/pione-config' +require 'pione/command/pione-log' +require 'pione/command/pione-package' +require 'pione/command/pione-val' + + module Pione module Command # PioneCommand is a facade command for PIONE's various functions. class PioneCommand < BasicCommand - # subcommand table - @subcommand = {} - - class << self - attr_reader :subcommand - - # Add the subcommand. - def add_subcommand(name, command) - @subcommand[name] = command - end - end - # # basic informations # option_parser_mode :order! + toplevel true command_name "pione" command_banner "PIONE is a rule-based workflow engine." @@ -26,20 +23,12 @@ def add_subcommand(name, command) # options # - # - # command lifecycle: execution phase - # - - execute :subcommand - - def execute_subcommand - name = @argv.first - if cmd = self.class.subcommand[name] - cmd.run(@argv.drop(1)) - else - abort("no such subcommand: %s" % name) - end - end + define_subcommand("action", PioneAction) + define_subcommand("clean", PioneClean) + define_subcommand("config", PioneConfig) + define_subcommand("log", PioneLog) + define_subcommand("package", PionePackage) + define_subcommand("val", PioneVal) end end end diff --git a/lib/pione/command/pione-config.rb b/lib/pione/command/pione-config.rb index 1b8f915..aaf4d8f 100644 --- a/lib/pione/command/pione-config.rb +++ b/lib/pione/command/pione-config.rb @@ -8,7 +8,6 @@ class PioneConfig < BasicCommand command_name "pione-config" command_banner "config PIONE global variables" - PioneCommand.add_subcommand("config", self) # # options diff --git a/lib/pione/command/pione-log.rb b/lib/pione/command/pione-log.rb index 7a583c9..991bee7 100644 --- a/lib/pione/command/pione-log.rb +++ b/lib/pione/command/pione-log.rb @@ -8,7 +8,6 @@ class PioneLog < BasicCommand command_name "pione-log" command_banner "View and convert PIONE log." - PioneCommand.add_subcommand("log", self) # # options diff --git a/lib/pione/command/pione-package-add.rb b/lib/pione/command/pione-package-add.rb new file mode 100644 index 0000000..cae2545 --- /dev/null +++ b/lib/pione/command/pione-package-add.rb @@ -0,0 +1,60 @@ +module Pione + module Command + # `PionePackageAdd` is a subcommand that adds PIONE package to package + # database in your system. + class PionePackageAdd < BasicCommand + # + # basic informations + # + + command_name "pione package add" + command_banner "add the package to package database" + + # + # options + # + + define_option(:tag) do |item| + item.long = "--tag=NAME" + item.desc = "specify tag name" + item.value = :as_is + end + + # + # command lifecycle: setup phase + # + + setup :target + + # Check archiver target location. + def setup_target + abort("There are no PIONE documents or packages.") if @argv.first.nil? + @target = @argv.first + end + + # + # command lifecycle: execution phase + # + + execute :add_package + + # Add the package to package database. + def execute_add_package + handler = Package::PackageReader.read(Location[@target]) + tag = option[:tag] || handler.info.tag + db = Package::Database.load + db.add(name: handler.info.name, editor: handler.info.editor, tag: tag, digest: handler.digest) + db.save + + # show log + args = [] + args << "editor: " + handler.info.editor if handler.info.editor + args << "tag: " + handler.info.tag if handler.info.tag + _args = args.size > 0 ? "(" + args.join(", ") + ")" : "" + Log::SystemLog.info( + "package \"%s\"%s was added to package database" % [handler.info.name, _args] + ) + end + end + end +end diff --git a/lib/pione/command/pione-package-build.rb b/lib/pione/command/pione-package-build.rb new file mode 100644 index 0000000..0c3cfa8 --- /dev/null +++ b/lib/pione/command/pione-package-build.rb @@ -0,0 +1,94 @@ +module Pione + module Command + # `PionePackageBuild` is a subcommand that builds PIONE archive package. + class PionePackageBuild < BasicCommand + # + # basic informations + # + + command_name "pione package build" + command_banner "build PIONE archive package" + + # + # options + # + + use_option :color + use_option :debug + + option_default :output, Location["./"] + + define_option(:output) do |item| + item.short = "-o" + item.long = "--output=LOCATION" + item.desc = "output file or directory location" + item.value = lambda {|val| Location[val]} + end + + define_option(:tag) do |item| + item.long = "--tag=NAME" + item.desc = "specify tag name" + item.value = :as_is + end + + define_option(:hash_id) do |item| + item.long = "--hash-id=HASH" + item.desc = "specify git hash id" + item.value = :as_is + end + + validate_option do |option| + unless option[:output].directory? + abort("Output location should be a directory: %s" % option[:output]) + end + end + + # + # command lifecycle: setup phase + # + + setup :target + + # Check archiver target location. + def setup_target + abort("There are no PIONE documents or packages.") if @argv.first.nil? + @target = @argv.first + end + + execute :build_package + + # Build a PPG package. + def execute_build_package + if ppg = try_to_archive(Location[git: @target], Location[data: @target]) + Log::SystemLog.info("Package build suceeded: %s" % ppg.address) + else + abort("Package build faild to archive.") + end + end + + # + # helper methods + # + + private + + def try_to_archive(*locations) + locations.each do |location| + begin + handler = Package::PackageReader.read(location) + cache_location = Package::PackageCache.directory_cache(handler.digest) + + # make archiver + archiver = Package::PackageArchiver.new(cache_location) + + # archive + return archiver.archive(option[:output], false) + rescue => e + Log::Debug.system("PIONE failed to archive %s: %s" % [location, e.message]) + end + end + return false + end + end + end +end diff --git a/lib/pione/command/pione-list-param.rb b/lib/pione/command/pione-package-show.rb similarity index 90% rename from lib/pione/command/pione-list-param.rb rename to lib/pione/command/pione-package-show.rb index 4e512ce..3d62c70 100644 --- a/lib/pione/command/pione-list-param.rb +++ b/lib/pione/command/pione-package-show.rb @@ -1,13 +1,12 @@ module Pione module Command - class PioneListParam < BasicCommand + class PionePackageShow < BasicCommand # # basic informations # - command_name "pione list-param" - command_banner "Show a list of parameters in the document or package." - PioneCommand.add_subcommand("list-param", self) + command_name "pione package show" + command_banner "show the package informations" # # options diff --git a/lib/pione/command/pione-update-package-info.rb b/lib/pione/command/pione-package-update.rb similarity index 72% rename from lib/pione/command/pione-update-package-info.rb rename to lib/pione/command/pione-package-update.rb index 90a6aba..b258b56 100644 --- a/lib/pione/command/pione-update-package-info.rb +++ b/lib/pione/command/pione-package-update.rb @@ -1,15 +1,13 @@ module Pione module Command - # PioneUpdatePackageInfo is a command definition of "pione - # update-package-info". - class PioneUpdatePackageInfo < BasicCommand + # `PionePackageUpdate` is a subcommand that updates PIONE package. + class PionePackageUpdate < BasicCommand # # basic informations # - command_name "pione update-package-info" - command_banner "update package info files" - PioneCommand.add_subcommand("update-package-info", self) + command_name "pione package update" + command_banner "update the package to package database" # # options @@ -42,7 +40,7 @@ def setup_target execute :update - # Update pacakge info files. + # Update update info files. def execute_update Package::PackageHandler.write_info_files(Location[@target], force: option[:force]) rescue Package::InvalidScenario => e diff --git a/lib/pione/command/pione-package.rb b/lib/pione/command/pione-package.rb index 363573f..7d91b6d 100644 --- a/lib/pione/command/pione-package.rb +++ b/lib/pione/command/pione-package.rb @@ -1,169 +1,23 @@ +require 'pione/command/pione-package-add' +require 'pione/command/pione-package-build' +require 'pione/command/pione-package-show' +require 'pione/command/pione-package-update' + module Pione module Command - # PionePackage is a command body of "pione-package". + # PionePackage is a subcommand that provides package utility tools. class PionePackage < BasicCommand # # basic informations # - command_name "pione-package" + command_name "pione package" command_banner "PIONE package utility." - # - # options - # - - use_option :color - use_option :debug - - option_default :output, Location["./"] - - define_option(:add) do |item| - item.long = '--add' - item.desc = 'add the package to package database' - item.action = lambda do |cmd, option, location| - cmd.action_type = :add - end - end - - define_option(:build) do |item| - item.long = '--build' - item.desc = 'build PIONE archive file(*.ppg)' - item.action = lambda do |cmd, option, location| - cmd.action_type = :build - end - end - - define_option(:write_info) do |item| - item.long = '--write-info' - item.desc = 'write package and scenario info files' - item.action = lambda do |cmd, option, location| - cmd.action_type = :write_info - end - end - - define_option(:list_params) do |item| - item.long = '--list-params' - item.desc = 'show user parameter list in the document' - item.action = proc {|cmd, option| cmd.action_type = :list_params} - end - - define_option(:output) do |item| - item.short = "-o" - item.long = "--output=LOCATION" - item.desc = "output file or directory location" - item.value = lambda {|val| Location[val]} - end - - define_option(:tag) do |item| - item.long = "--tag=NAME" - item.desc = "specify tag name" - item.value = :as_is - end - - define_option(:hash_id) do |item| - item.long = "--hash-id=HASH" - item.desc = "specify git hash id" - item.value = :as_is - end - - validate_option do |option| - unless option[:output].directory? - abort("output location should be a directory: %s" % option[:output]) - end - end - - # - # command lifecycle: setup phase - # - - setup :target - - # Check archiver target location. - def setup_target - abort("There are no PIONE documents or packages.") if @argv.first.nil? - @target = @argv.first - end - - # - # command lifecycle: execution phase - # - - execute :add => :add_package - - # Add the package to package database. - def execute_add_package - handler = Package::PackageReader.read(Location[@target]) - tag = option[:tag] || handler.info.tag - db = Package::Database.load - db.add(name: handler.info.name, editor: handler.info.editor, tag: tag, digest: handler.digest) - db.save - - # show log - args = [] - args << "editor: " + handler.info.editor if handler.info.editor - args << "tag: " + handler.info.tag if handler.info.tag - _args = args.size > 0 ? "(" + args.join(", ") + ")" : "" - Log::SystemLog.info( - "package \"%s\"%s was added to package database" % [handler.info.name, _args] - ) - end - - execute :build => :build_package - - # Build a PPG package. - def execute_build_package - if ppg = try_to_archive(Location[git: @target], Location[data: @target]) - Log::SystemLog.info("pione-package suceeded to build %s" % ppg.address) - else - abort("pione-package faild to archive.") - end - end - - execute :write_info => :write_info - - # Update update info files. - def execute_write_info - Package::PackageHandler.write_info_files(Location[@target]) - rescue Package::InvalidScenario => e - abort(e.message) - end - - execute :list_params => :list_params - - # Print list of user parameters. - def execute_list_params - # read package - package_handler = Package::PackageReader.read(Location[@target]) - env = package_handler.eval(Lang::Environment.new) - - Util::PackageParametersList.print(env, env.current_package_id) - end - - # - # helper methods - # - - private - - def try_to_archive(*locations) - locations.each do |location| - begin - handler = Package::PackageReader.read(location) - cache_location = Package::PackageCache.directory_cache(handler.digest) - - # make archiver - archiver = Package::PackageArchiver.new(cache_location) - - # archive - return archiver.archive(option[:output], false) - rescue => e - p e - Log::Debug.system("pione-package failed to archive %s: %s" % [location, e.message]) - end - end - return false - end + define_subcommand "add" , PionePackageAdd + define_subcommand "build" , PionePackageBuild + define_subcommand "show" , PionePackageShow + define_subcommand "update", PionePackageUpdate end end end diff --git a/lib/pione/command/pione-task-worker.rb b/lib/pione/command/pione-task-worker.rb index 94e7728..5c63342 100644 --- a/lib/pione/command/pione-task-worker.rb +++ b/lib/pione/command/pione-task-worker.rb @@ -6,6 +6,8 @@ class PioneTaskWorker < BasicCommand # basic informations # + toplevel true + command_name "pione-task-worker" do |cmd| "front: %s, parent: %s" % [Global.front.uri, cmd.option[:parent_front].uri] end diff --git a/lib/pione/command/pione-tuple-space-provider.rb b/lib/pione/command/pione-tuple-space-provider.rb index 2960d84..b934b62 100644 --- a/lib/pione/command/pione-tuple-space-provider.rb +++ b/lib/pione/command/pione-tuple-space-provider.rb @@ -6,6 +6,8 @@ class PioneTupleSpaceProvider < BasicCommand # command info # + toplevel true + command_name "pione-tuple-space-provider" do |cmd| "front: %s, parent: %s" % [Global.front.uri, cmd.option[:parent_front].uri] end diff --git a/lib/pione/command/pione-tuple-space-receiver.rb b/lib/pione/command/pione-tuple-space-receiver.rb index 11e58cd..2fb2e66 100644 --- a/lib/pione/command/pione-tuple-space-receiver.rb +++ b/lib/pione/command/pione-tuple-space-receiver.rb @@ -7,6 +7,8 @@ class PioneTupleSpaceReceiver < BasicCommand # basic informations # + toplevel true + command_name "pione-tuple-space-receiver" do |cmd| "front: %s, parent: %s" % [Global.front.uri, cmd.option[:parent_front].uri] end diff --git a/lib/pione/command/pione-val.rb b/lib/pione/command/pione-val.rb index 75c9d7e..cc1684f 100644 --- a/lib/pione/command/pione-val.rb +++ b/lib/pione/command/pione-val.rb @@ -8,7 +8,6 @@ class PioneVal < BasicCommand command_name "pione-val" command_banner "Get the evaluation result value of the PIONE expression." - PioneCommand.add_subcommand("val", self) # # options diff --git a/lib/pione/test-helper/command-helper.rb b/lib/pione/test-helper/command-helper.rb index e53dc2e..437b3df 100644 --- a/lib/pione/test-helper/command-helper.rb +++ b/lib/pione/test-helper/command-helper.rb @@ -103,11 +103,8 @@ def run(&b) def fail _args = args - _base = base context.it(template % title) do - TestHelper::Command.fail do - Pione::Command::PioneClient.run(_args) - end + TestHelper::Command.fail(Pione::Command::PioneClient, _args) end end diff --git a/lib/pione/util/completion.rb b/lib/pione/util/completion.rb new file mode 100644 index 0000000..7385b96 --- /dev/null +++ b/lib/pione/util/completion.rb @@ -0,0 +1,111 @@ +module Pione + module Util + class Completion + def self.compile(source, target) + context = self.new.context + target.write(ERB.new(source.read, nil, "-").result(context)) + end + + attr_reader :completion_command + attr_reader :completion_exec + attr_reader :name2 + attr_reader :name3 + + def toplevel_commands(mod) + mod.constants.map{|c| mod.const_get(c)}.select do |c| + c.is_a?(Class) and c < Command::BasicCommand and c.toplevel? + end.map {|cmd| [cmd.command_name, cmd]} + end + + def context + binding + end + + def descendants(keys, cmd) + if cmd.subcommand.empty? + [[keys, cmd]] + else + cmd.subcommand.inject([[keys, cmd]]) do |list, (key, child)| + _keys = keys + [key] + if child.subcommand.empty? + list << [_keys, child] + else + list.concat(descendants(_keys, child)) + end + end + end + end + end + + class BashCompletion < Completion + def initialize + @completion_command = "complete" + @completion_exec = "complete -F" + @name2 = "${COMP_WORDS[1]}" + @name3 = "${COMP_WORDS[2]}" + end + + def fun_subcommands(cmd) + compreply(make_subcommands(cmd)) + end + + def fun_options(cmd) + compreply(make_options(cmd)) + end + + private + + def compreply(options) + 'COMPREPLY=($(compgen -W "%s" -- "${COMP_WORDS[COMP_CWORD]}"));' % options + end + + def make_subcommands(cmd) + cmd.subcommand.keys.join(" ") + end + + def make_options(cmd) + items = cmd.option_definition.items + items.sort{|a, b| a.long <=> b.long}.map{|item| item.long}.join(" ") + end + end + + class ZshCompletion < Completion + def initialize + @completion_command = "compdef" + @completion_exec = "compdef" + @name2 = "${words[2]}" + @name3 = "${words[3]}" + end + + def fun_subcommands(cmd) + describe(cmd) + end + + def fun_options(cmd) + arguments(cmd) + end + + private + + def describe(cmd) + "list=(%s) _describe -t common-commands 'common commands' list;" % make_subcommands(cmd) + end + + def arguments(cmd) + "_arguments -s -S %s '*:file:_files' && return 0;" % make_options(cmd) + end + + def make_subcommands(cmd) + cmd.subcommand.map{|key, val| '%s:"%s"' % [key, val.command_banner]}.join(" ") + end + + def make_options(cmd) + items = cmd.option_definition.items + items.sort{|a, b| a.long <=> b.long}.map do |item| + name = item.long.gsub("[", "\\[").gsub("]", "\\]") + "\"%s[%s]\"" % [name, item.desc] + end.join(" ") + end + end + end +end diff --git a/misc/pione-completion.bash b/misc/pione-completion.bash new file mode 100644 index 0000000..3f529fb --- /dev/null +++ b/misc/pione-completion.bash @@ -0,0 +1,164 @@ +if type complete 1>/dev/null 2>&1; +then + + # + # `pione` command + # + + complete -F _pione pione + + _pione() { + local name2="${COMP_WORDS[1]}" + local name3="${COMP_WORDS[2]}" + + case $name2 in + action) + case $name3 in + exec) _pione_action_exec_options;; + list) _pione_action_list_options;; + print) _pione_action_print_options;; + *) _pione_action_subcommands;; + esac;; + clean) _pione_clean_options;; + config) _pione_config_options;; + log) _pione_log_options;; + package) + case $name3 in + add) _pione_package_add_options;; + build) _pione_package_build_options;; + show) _pione_package_show_options;; + update) _pione_package_update_options;; + *) _pione_package_subcommands;; + esac;; + val) _pione_val_options;; + *) _pione_subcommands;; + esac + } + + _pione_subcommands() { + COMPREPLY=($(compgen -W "action clean config log package val" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_action_subcommands() { + COMPREPLY=($(compgen -W "exec list print" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_action_exec_options() { + COMPREPLY=($(compgen -W "--[no-]color --debug[=TYPE] --directory PATH --domain" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_action_list_options() { + COMPREPLY=($(compgen -W "--[no-]color --compact" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_action_print_options() { + COMPREPLY=($(compgen -W "--[no-]color --domain" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_clean_options() { + COMPREPLY=($(compgen -W "--debug[=TYPE] --older=DATE --type=NAME" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_config_options() { + COMPREPLY=($(compgen -W "--debug[=TYPE] --file PATH --get NAME --list --set NAME VALUE --unset NAME VALUE" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_log_options() { + COMPREPLY=($(compgen -W "--[no-]color --agent-activity[=TYPE] --debug[=TYPE] --format=(XES|JSON|HTML) --location=LOCATION --log-id=ID --rule-process --task-process" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_package_subcommands() { + COMPREPLY=($(compgen -W "add build show update" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_package_add_options() { + COMPREPLY=($(compgen -W "--tag=NAME" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_package_build_options() { + COMPREPLY=($(compgen -W "--[no-]color --debug[=TYPE] --hash-id=HASH --output=LOCATION --tag=NAME" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_package_show_options() { + COMPREPLY=($(compgen -W "--[no-]color --advanced --debug[=TYPE]" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_package_update_options() { + COMPREPLY=($(compgen -W "--[no-]color --debug[=TYPE] --force" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + _pione_val_options() { + COMPREPLY=($(compgen -W "--debug[=TYPE] --domain-info=LOCATION" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + # + # `pione-client` command + # + + complete -F _pione-client pione-client + + _pione-client() { + _pione-client_options + } + + _pione-client_options() { + COMPREPLY=($(compgen -W "--[no-]color --communication-address=ADDRESS --debug[=TYPE] --dry-run --features=FEATURES --input=LOCATION --output=LOCATION --params="{Var:1,...}" --parent-front=URI --presence-notification-address=255.255.255.255:56000 --rehearse [SCENARIO] --relay=URI --request-task-worker=N --stand-alone --stream --task-worker=N --timeout SEC" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + # + # `pione-task-worker` command + # + + complete -F _pione-task-worker pione-task-worker + + _pione-task-worker() { + _pione-task-worker_options + } + + _pione-task-worker_options() { + COMPREPLY=($(compgen -W "--[no-]color --communication-address=ADDRESS --debug[=TYPE] --features=FEATURES --parent-front=URI --tuple-space-id=UUID" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + # + # `pione-broker` command + # + + complete -F _pione-broker pione-broker + + _pione-broker() { + _pione-broker_options + } + + _pione-broker_options() { + COMPREPLY=($(compgen -W "--[no-]color --communication-address=ADDRESS --daemon --debug[=TYPE] --features=FEATURES --task-worker=N" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + # + # `pione-tuple-space-provider` command + # + + complete -F _pione-tuple-space-provider pione-tuple-space-provider + + _pione-tuple-space-provider() { + _pione-tuple-space-provider_options + } + + _pione-tuple-space-provider_options() { + COMPREPLY=($(compgen -W "--[no-]color --communication-address=ADDRESS --debug[=TYPE] --parent-front=URI --presence-notification-address=255.255.255.255:56000" -- "${COMP_WORDS[COMP_CWORD]}")); + } + + # + # `pione-tuple-space-receiver` command + # + + complete -F _pione-tuple-space-receiver pione-tuple-space-receiver + + _pione-tuple-space-receiver() { + _pione-tuple-space-receiver_options + } + + _pione-tuple-space-receiver_options() { + COMPREPLY=($(compgen -W "--[no-]color --communication-address=ADDRESS --debug[=TYPE] --parent-front=URI --presence-port=PORT" -- "${COMP_WORDS[COMP_CWORD]}")); + } + +fi diff --git a/misc/pione-completion.erb b/misc/pione-completion.erb new file mode 100644 index 0000000..297656e --- /dev/null +++ b/misc/pione-completion.erb @@ -0,0 +1,50 @@ +if type <%= completion_command %> 1>/dev/null 2>&1; +then + +<%- toplevel_commands(Pione::Command).each do |key1, cmd1| -%> + # + # `<%= key1 %>` command + # + + <%= completion_exec %> _<%= key1 %> <%= key1 %> + + _<%= key1 %>() { + <%- if cmd1.subcommand.empty? -%> + _<%= key1 %>_options + <%- else -%> + local name2="<%= name2 %>" + local name3="<%= name3 %>" + + case $name2 in + <%- cmd1.subcommand.each do |key2, cmd2| -%> + <%- if cmd2.subcommand.empty? -%> + <%= key2 %>) _<%= key1 %>_<%= key2 %>_options;; + <%- else -%> + <%= key2 %>) + case $name3 in + <%- cmd2.subcommand.each do |key3, cmd3| -%> + <%= key3 %>) _<%= key1 %>_<%= key2 %>_<%= key3 %>_options;; + <%- end -%> + *) _<%= key1 %>_<%= key2 %>_subcommands;; + esac;; + <%- end -%> + <%- end -%> + *) _<%= key1 %>_subcommands;; + esac + <%- end -%> + } + + <%- descendants([key1], cmd1).each do |keys, cmd| -%> + <%- if cmd.subcommand.empty? -%> + _<%= keys.join("_") %>_options() { + <%= fun_options(cmd) %> + } + <%- else -%> + _<%= keys.join("_") %>_subcommands() { + <%= fun_subcommands(cmd) %> + } + <%- end -%> + + <%- end -%> +<%- end -%> +fi diff --git a/misc/pione-completion.zsh b/misc/pione-completion.zsh new file mode 100644 index 0000000..36d8589 --- /dev/null +++ b/misc/pione-completion.zsh @@ -0,0 +1,164 @@ +if type compdef 1>/dev/null 2>&1; +then + + # + # `pione` command + # + + compdef _pione pione + + _pione() { + local name2="${words[2]}" + local name3="${words[3]}" + + case $name2 in + action) + case $name3 in + exec) _pione_action_exec_options;; + list) _pione_action_list_options;; + print) _pione_action_print_options;; + *) _pione_action_subcommands;; + esac;; + clean) _pione_clean_options;; + config) _pione_config_options;; + log) _pione_log_options;; + package) + case $name3 in + add) _pione_package_add_options;; + build) _pione_package_build_options;; + show) _pione_package_show_options;; + update) _pione_package_update_options;; + *) _pione_package_subcommands;; + esac;; + val) _pione_val_options;; + *) _pione_subcommands;; + esac + } + + _pione_subcommands() { + list=(action:"execute an action in literate action document" clean:"remove PIONE's temporary files, cache, and etc." config:"config PIONE global variables" log:"View and convert PIONE log." package:"PIONE package utility." val:"Get the evaluation result value of the PIONE expression.") _describe -t common-commands 'common commands' list; + } + + _pione_action_subcommands() { + list=(exec:"execute an action in literate action document" list:"list action names in document" print:"print action contents") _describe -t common-commands 'common commands' list; + } + + _pione_action_exec_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--directory PATH[execute in the PATH]" "--domain[use the domain information file]" '*:file:_files' && return 0; + } + + _pione_action_list_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--compact[one line list]" '*:file:_files' && return 0; + } + + _pione_action_print_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--domain[use the domain information file]" '*:file:_files' && return 0; + } + + _pione_clean_options() { + _arguments -s -S "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--older=DATE[remove file older than the date]" "--type=NAME[remove only files of the type]" '*:file:_files' && return 0; + } + + _pione_config_options() { + _arguments -s -S "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--file PATH[config file path]" "--get NAME[get the item value]" "--list[list all]" "--set NAME VALUE[set the item]" "--unset NAME VALUE[set the item]" '*:file:_files' && return 0; + } + + _pione_log_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--agent-activity\[=TYPE\][output only agent activity log]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--format=(XES|JSON|HTML)[set format type]" "--location=LOCATION[set log location of PIONE process]" "--log-id=ID[target log id]" "--rule-process[generate rule process log]" "--task-process[generate task process log]" '*:file:_files' && return 0; + } + + _pione_package_subcommands() { + list=(add:"add the package to package database" build:"build PIONE archive package" show:"show the package informations" update:"update the package to package database") _describe -t common-commands 'common commands' list; + } + + _pione_package_add_options() { + _arguments -s -S "--tag=NAME[specify tag name]" '*:file:_files' && return 0; + } + + _pione_package_build_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--hash-id=HASH[specify git hash id]" "--output=LOCATION[output file or directory location]" "--tag=NAME[specify tag name]" '*:file:_files' && return 0; + } + + _pione_package_show_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--advanced[show advanced parameters]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" '*:file:_files' && return 0; + } + + _pione_package_update_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--force[update pacakge info files]" '*:file:_files' && return 0; + } + + _pione_val_options() { + _arguments -s -S "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--domain-info=LOCATION[location of Domain info file]" '*:file:_files' && return 0; + } + + # + # `pione-client` command + # + + compdef _pione-client pione-client + + _pione-client() { + _pione-client_options + } + + _pione-client_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--communication-address=ADDRESS[set IP address for interprocess communication]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--dry-run[turn on dry run mode]" "--features=FEATURES[set features]" "--input=LOCATION[set input directory]" "--output=LOCATION[set output directory]" "--params="{Var:1,...}"[set user parameters]" "--parent-front=URI[set parent front URI]" "--presence-notification-address=255.255.255.255:56000[set the address for sending presence notifier]" "--rehearse \[SCENARIO\][rehearse the scenario]" "--relay=URI[turn on relay mode and set relay address]" "--request-task-worker=N[set request number of task workers]" "--stand-alone[turn on stand alone mode]" "--stream[turn on stream mode]" "--task-worker=N[set task worker number that this process creates]" "--timeout SEC[timeout processing after SEC]" '*:file:_files' && return 0; + } + + # + # `pione-task-worker` command + # + + compdef _pione-task-worker pione-task-worker + + _pione-task-worker() { + _pione-task-worker_options + } + + _pione-task-worker_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--communication-address=ADDRESS[set IP address for interprocess communication]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--features=FEATURES[set features]" "--parent-front=URI[set parent front URI]" "--tuple-space-id=UUID[tuple space id that the worker joins]" '*:file:_files' && return 0; + } + + # + # `pione-broker` command + # + + compdef _pione-broker pione-broker + + _pione-broker() { + _pione-broker_options + } + + _pione-broker_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--communication-address=ADDRESS[set IP address for interprocess communication]" "--daemon[turn on daemon mode]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--features=FEATURES[set features]" "--task-worker=N[set task worker number that this process creates]" '*:file:_files' && return 0; + } + + # + # `pione-tuple-space-provider` command + # + + compdef _pione-tuple-space-provider pione-tuple-space-provider + + _pione-tuple-space-provider() { + _pione-tuple-space-provider_options + } + + _pione-tuple-space-provider_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--communication-address=ADDRESS[set IP address for interprocess communication]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--parent-front=URI[set parent front URI]" "--presence-notification-address=255.255.255.255:56000[set the address for sending presence notifier]" '*:file:_files' && return 0; + } + + # + # `pione-tuple-space-receiver` command + # + + compdef _pione-tuple-space-receiver pione-tuple-space-receiver + + _pione-tuple-space-receiver() { + _pione-tuple-space-receiver_options + } + + _pione-tuple-space-receiver_options() { + _arguments -s -S "--\[no-\]color[turn on/off color mode]" "--communication-address=ADDRESS[set IP address for interprocess communication]" "--debug\[=TYPE\][turn on debug mode about the type(system / rule_engine / ignored_exception / presence_notifier / communication)]" "--parent-front=URI[set parent front URI]" "--presence-port=PORT[set presence port number]" '*:file:_files' && return 0; + } + +fi diff --git a/test/command/spec_pione-action-exec.rb b/test/command/spec_pione-action-exec.rb new file mode 100644 index 0000000..b93f0b9 --- /dev/null +++ b/test/command/spec_pione-action-exec.rb @@ -0,0 +1,18 @@ +require 'pione/test-helper' + +TestHelper.scope do |this| + this::DIR = Location[File.dirname(__FILE__)] + ".." + "literate-action" + "data" + + describe Pione::Command::PioneActionExec do + before do + @cmd = Pione::Command::PioneActionExec + end + + it "should execute action" do + base = Location[Temppath.mkdir] + args = [(this::DIR + "HelloWorld.md").path.to_s, "SayHello", "-d", base.path.to_s] + TestHelper::Command.succeed(@cmd, args) + (base + "message.txt").read.chomp.should == "Hello, world!" + end + end +end diff --git a/test/command/spec_pione-action-list.rb b/test/command/spec_pione-action-list.rb index 709526e..d61880d 100644 --- a/test/command/spec_pione-action-list.rb +++ b/test/command/spec_pione-action-list.rb @@ -13,5 +13,11 @@ res = TestHelper::Command.succeed(@cmd, args) res.stdout.string.chomp.should == "Name1\nName2" end + + it "should show action names in compact form" do + args = ["--compact", (this::DIR + "D1.md").path.to_s] + res = TestHelper::Command.succeed(@cmd, args) + res.stdout.string.chomp.should == "Name1 Name2" + end end end diff --git a/test/command/spec_pione-action-print.rb b/test/command/spec_pione-action-print.rb new file mode 100644 index 0000000..1d37ea5 --- /dev/null +++ b/test/command/spec_pione-action-print.rb @@ -0,0 +1,17 @@ +require 'pione/test-helper' + +TestHelper.scope do |this| + this::DIR = Location[File.dirname(__FILE__)] + ".." + "literate-action" + "data" + + describe Pione::Command::PioneActionPrint do + before do + @cmd = Pione::Command::PioneActionPrint + end + + it "should print action contents" do + args = [(this::DIR + "HelloWorld.md").path.to_s, "SayHello"] + res = TestHelper::Command.succeed(@cmd, args) + res.stdout.string.chomp.should == "echo \"Hello, world!\" > message.txt" + end + end +end diff --git a/test/command/spec_pione-action.rb b/test/command/spec_pione-action.rb index 18a4a1f..e13d0a4 100644 --- a/test/command/spec_pione-action.rb +++ b/test/command/spec_pione-action.rb @@ -1,24 +1,11 @@ require 'pione/test-helper' -TestHelper.scope do |this| - this::DIR = Location[File.dirname(__FILE__)] + ".." + "literate-action" + "data" - - describe Pione::Command::PioneAction do - before do - @cmd = Pione::Command::PioneAction - end - - it "should execute action" do - base = Location[Temppath.mkdir] - args = [(this::DIR + "HelloWorld.md").path.to_s, "SayHello", "-d", base.path.to_s] - TestHelper::Command.succeed(@cmd, args) - (base + "message.txt").read.chomp.should == "Hello, world!" - end +describe Pione::Command::PioneAction do + before do + @cmd = Pione::Command::PioneAction + end - it "should show action content" do - args = [(this::DIR + "HelloWorld.md").path.to_s, "SayHello", "--show"] - res = TestHelper::Command.succeed(@cmd, args) - res.stdout.string.chomp.should == "echo \"Hello, world!\" > message.txt" - end + it "should fail with no subcommands" do + TestHelper::Command.fail(@cmd, []) end end diff --git a/test/command/spec_pione-client.rb b/test/command/spec_pione-client.rb index a24f9da..34b98f9 100644 --- a/test/command/spec_pione-client.rb +++ b/test/command/spec_pione-client.rb @@ -50,12 +50,6 @@ TestHelper::Command.fail(@cmd, args) end - it "should show parameters list of package" do - args = ["example/HelloWorld/HelloWorld.pione", "--list-params"] - res = TestHelper::Command.succeed(@cmd, args) - res.stdout.string.size.should > 0 - end - describe "example/Fib" do TestHelper::PioneClientRunner.test(self) do |runner| runner.title = "should get a result with no parameters (default fib(3))" diff --git a/test/command/spec_pione-package-add.rb b/test/command/spec_pione-package-add.rb new file mode 100644 index 0000000..f63a139 --- /dev/null +++ b/test/command/spec_pione-package-add.rb @@ -0,0 +1,55 @@ +require 'pione/test-helper' + +TestHelper.scope do |this| + this::P1 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP1" + this::P2 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP2" + this::P3 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP3" + this::P4 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP4" + + describe Pione::Command::PionePackage do + before do + @cmd = Pione::Command::PionePackageAdd + @orig_database = Global.package_database_location + Global.package_database_location = Location[Temppath.create] + end + + after do + Global.package_database_location = @orig_database + end + + it "should add package with name to database" do + TestHelper::Command.succeed(@cmd, [this::P1.path.to_s]) + db = Package::Database.load + digest = db.find("P1", nil, nil) + digest.size.should > 0 + end + + it "should add package with tag to database" do + res = TestHelper::Command.succeed(@cmd, [this::P2.path.to_s]) + db = Package::Database.load + digest = db.find("P2", nil, "v0.1.0") + digest.size.should > 0 + end + + it "should add package with editor to database" do + res = TestHelper::Command.succeed(@cmd, [this::P3.path.to_s]) + db = Package::Database.load + digest = db.find("P3", "keita.yamaguchi@gmail.com", nil) + digest.size.should > 0 + end + + it "should add package with full name to database" do + TestHelper::Command.succeed(@cmd, [this::P4.path.to_s]) + db = Package::Database.load + digest = db.find("P4", "keita.yamaguchi@gmail.com", "v0.1.0") + digest.size.should > 0 + end + + it "should add tag alias" do + TestHelper::Command.succeed(@cmd, ["--tag", "TEST", this::P4.path.to_s]) + db = Package::Database.load + digest = db.find("P4", "keita.yamaguchi@gmail.com", "TEST") + digest.size.should > 0 + end + end +end diff --git a/test/command/spec_pione-package-build.rb b/test/command/spec_pione-package-build.rb new file mode 100644 index 0000000..e18aa4e --- /dev/null +++ b/test/command/spec_pione-package-build.rb @@ -0,0 +1,57 @@ +require 'pione/test-helper' + +TestHelper.scope do |this| + this::P1 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP1" + this::P2 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP2" + this::P3 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP3" + this::P4 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP4" + + describe Pione::Command::PionePackageBuild do + before do + @cmd = Pione::Command::PionePackageBuild + @orig_database = Global.package_database_location + Global.package_database_location = Location[Temppath.create] + end + + after do + Global.package_database_location = @orig_database + end + + it "should build PIONE package with the package name" do + output_location = Location[Temppath.mkdir] + args = ["-o", output_location.path.to_s, this::P1.path.to_s] + res = TestHelper::Command.succeed(@cmd, args) + pkg = output_location + "P1.ppg" + pkg.should.exist + pkg.size.should > 0 + end + + it "should build PIONE package with the tag" do + output_location = Location[Temppath.mkdir] + args = ["-o", output_location.path.to_s, this::P2.path.to_s] + res = TestHelper::Command.succeed(@cmd, args) + pkg = output_location + "P2+v0.1.0.ppg" + pkg.should.exist + pkg.size.should > 0 + end + + it "should build PIONE package with the editor" do + output_location = Location[Temppath.mkdir] + args = ["-o", output_location.path.to_s, this::P3.path.to_s] + res = TestHelper::Command.succeed(@cmd, args) + pkg = output_location + "P3(keita.yamaguchi@gmail.com).ppg" + pkg.should.exist + pkg.size.should > 0 + end + + it "should build PIONE package with full name" do + output_location = Location[Temppath.mkdir] + args = ["-o", output_location.path.to_s, this::P4.path.to_s] + res = TestHelper::Command.succeed(@cmd, args) + pkg = output_location + "P4(keita.yamaguchi@gmail.com)+v0.1.0.ppg" + pkg.should.exist + pkg.size.should > 0 + end + end +end + diff --git a/test/command/spec_pione-list-param.rb b/test/command/spec_pione-package-show.rb similarity index 58% rename from test/command/spec_pione-list-param.rb rename to test/command/spec_pione-package-show.rb index c9ca469..84d5873 100644 --- a/test/command/spec_pione-list-param.rb +++ b/test/command/spec_pione-package-show.rb @@ -1,14 +1,31 @@ require 'pione/test-helper' TestHelper.scope do |this| + this::P1 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP1" + this::P2 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP2" + this::P3 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP3" + this::P4 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP4" this::DIR = Location[File.dirname(__FILE__)] + "data" + "pione-list-param" - describe Pione::Command::PioneListParam do + describe Pione::Command::PionePackage do + before do + @cmd = Pione::Command::PionePackageShow + @orig_database = Global.package_database_location + Global.package_database_location = Location[Temppath.create] + end + + after do + Global.package_database_location = @orig_database + end + + it "should show parameters list of the package" do + res = TestHelper::Command.succeed(@cmd, ["example/HelloWorld/HelloWorld.pione"]) + res.stdout.string.size.should > 0 + end + it "should show basic parameters" do args = [(this::DIR + "BasicParameters.pione").path.to_s] - res = TestHelper::Command.succeed do - Command::PioneListParam.run(args) - end + res = TestHelper::Command.succeed(@cmd, args) out = res.stdout.string out.should.include "B1" out.should.include "B2" @@ -23,9 +40,7 @@ it "should show basic parameters only without `--advanced` option" do args = [(this::DIR + "AdvancedParameters.pione").path.to_s] - res = TestHelper::Command.succeed do - Command::PioneListParam.run(args) - end + res = TestHelper::Command.succeed(@cmd, args) out = res.stdout.string out.should.include "B1" out.should.not.include "B2" @@ -40,9 +55,7 @@ it "should show advanced parameters with `--advanced` option" do args = [(this::DIR + "AdvancedParameters.pione").path.to_s, "--advanced"] - res = TestHelper::Command.succeed do - Command::PioneListParam.run(args) - end + res = TestHelper::Command.succeed(@cmd, args) out = res.stdout.string out.should.include "B1" out.should.include "B2" @@ -56,3 +69,4 @@ end end end + diff --git a/test/command/spec_pione-update-package-info.rb b/test/command/spec_pione-package-update.rb similarity index 94% rename from test/command/spec_pione-update-package-info.rb rename to test/command/spec_pione-package-update.rb index 1513b12..b7ee882 100644 --- a/test/command/spec_pione-update-package-info.rb +++ b/test/command/spec_pione-package-update.rb @@ -1,8 +1,8 @@ require 'pione/test-helper' -describe Pione::Command::PioneUpdatePackageInfo do +describe Pione::Command::PionePackageUpdate do before do - @cmd = Pione::Command::PioneUpdatePackageInfo + @cmd = Pione::Command::PionePackageUpdate # package @location = Location[Temppath.mkdir] diff --git a/test/command/spec_pione-package.rb b/test/command/spec_pione-package.rb index d45abb4..6e2aecb 100644 --- a/test/command/spec_pione-package.rb +++ b/test/command/spec_pione-package.rb @@ -1,106 +1,13 @@ require 'pione/test-helper' TestHelper.scope do |this| - this::P1 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP1" - this::P2 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP2" - this::P3 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP3" - this::P4 = Location[File.dirname(__FILE__)] + ".." + "command" + "data" + "PionePackageP4" - describe Pione::Command::PionePackage do before do @cmd = Pione::Command::PionePackage - @orig_database = Global.package_database_location - Global.package_database_location = Location[Temppath.create] - end - - after do - Global.package_database_location = @orig_database - end - - it "should build PIONE package with the package name" do - output_location = Location[Temppath.mkdir] - args = ["--build", "-o", output_location.path.to_s, this::P1.path.to_s] - res = TestHelper::Command.succeed(@cmd, args) - pkg = output_location + "P1.ppg" - pkg.should.exist - pkg.size.should > 0 - end - - it "should build PIONE package with the tag" do - output_location = Location[Temppath.mkdir] - args = ["--build", "-o", output_location.path.to_s, this::P2.path.to_s] - res = TestHelper::Command.succeed(@cmd, args) - pkg = output_location + "P2+v0.1.0.ppg" - pkg.should.exist - pkg.size.should > 0 - end - - it "should build PIONE package with the editor" do - output_location = Location[Temppath.mkdir] - args = ["--build", "-o", output_location.path.to_s, this::P3.path.to_s] - res = TestHelper::Command.succeed(@cmd, args) - pkg = output_location + "P3(keita.yamaguchi@gmail.com).ppg" - pkg.should.exist - pkg.size.should > 0 - end - - it "should build PIONE package with full name" do - output_location = Location[Temppath.mkdir] - args = ["--build", "-o", output_location.path.to_s, this::P4.path.to_s] - res = TestHelper::Command.succeed(@cmd, args) - pkg = output_location + "P4(keita.yamaguchi@gmail.com)+v0.1.0.ppg" - pkg.should.exist - pkg.size.should > 0 - end - - it "should add package with name to database" do - TestHelper::Command.succeed(@cmd, ["--add", this::P1.path.to_s]) - db = Package::Database.load - digest = db.find("P1", nil, nil) - digest.size.should > 0 - end - - it "should add package with tag to database" do - res = TestHelper::Command.succeed(@cmd, ["--add", this::P2.path.to_s]) - db = Package::Database.load - digest = db.find("P2", nil, "v0.1.0") - digest.size.should > 0 - end - - it "should add package with editor to database" do - res = TestHelper::Command.succeed(@cmd, ["--add", this::P3.path.to_s]) - db = Package::Database.load - digest = db.find("P3", "keita.yamaguchi@gmail.com", nil) - digest.size.should > 0 - end - - it "should add package with full name to database" do - TestHelper::Command.succeed(@cmd, ["--add", this::P4.path.to_s]) - db = Package::Database.load - digest = db.find("P4", "keita.yamaguchi@gmail.com", "v0.1.0") - digest.size.should > 0 - end - - it "should add tag alias" do - TestHelper::Command.succeed(@cmd, ["--add", "--tag", "TEST", this::P4.path.to_s]) - db = Package::Database.load - digest = db.find("P4", "keita.yamaguchi@gmail.com", "TEST") - digest.size.should > 0 - end - - it "should write a package information file" do - location = Location[Temppath.mkdir] - (this::P1 + "P1.pione").copy(location + "P1.pione") - TestHelper::Command.succeed(@cmd, ["--write-info", location.path.to_s]) - (location + "pione-package.json").should.exist end - it "should show parameters list of the package" do - args = ["example/HelloWorld/HelloWorld.pione", "--list-params"] - res = TestHelper::Command.succeed do - Pione::Command::PionePackage.run(args) - end - res.stdout.string.size.should > 0 + it "should abort with no subcommands" do + TestHelper::Command.fail(@cmd, []) end end end diff --git a/test/location/spec_dropbox-location.rb b/test/location/spec_dropbox-location.rb index 8c43ebe..3c34cbc 100644 --- a/test/location/spec_dropbox-location.rb +++ b/test/location/spec_dropbox-location.rb @@ -1,31 +1,39 @@ require 'pione/test-helper' require_relative 'location-behavior' -describe Pione::Location::DropboxLocation do - if Location::DropboxLocation.cached? and TestHelper::InternetConnectivity.ok? - before do - tuple_space = TupleSpace::TupleSpaceServer.new - Location::DropboxLocation.setup_for_cui_client(tuple_space) +# +# If you want to enable this test, you should set environment variable +# "DROPBOX_LOCATION_TEST". +# +# % DROPBOX_LOCATION_TEST=true bundle exec rake test +# +if ENV["DROPBOX_LOCATION_TEST"] == "true" + describe Pione::Location::DropboxLocation do + if Location::DropboxLocation.cached? and TestHelper::InternetConnectivity.ok? + before do + tuple_space = TupleSpace::TupleSpaceServer.new + Location::DropboxLocation.setup_for_cui_client(tuple_space) - path = Location["dropbox:/spec_dropbox-location/"] + Util::UUID.generate - @file = path + Util::UUID.generate - @dir = path - (@dir + "A").create("A") - (@dir + "B").create("B") - (@dir + "C").create("C") - (@dir + "D" + "X").create("X") - (@dir + "D" + "Y").create("Y") - (@dir + "D" + "Z").create("Z") - end + path = Location["dropbox:/spec_dropbox-location/"] + Util::UUID.generate + @file = path + Util::UUID.generate + @dir = path + (@dir + "A").create("A") + (@dir + "B").create("B") + (@dir + "C").create("C") + (@dir + "D" + "X").create("X") + (@dir + "D" + "Y").create("Y") + (@dir + "D" + "Z").create("Z") + end - after do - @file.delete - @dir.delete - end + after do + @file.delete + @dir.delete + end - behaves_like "location" - else - puts "*** Ignored the test because the cache of Dropbox's access token doesn't exist. ***" - puts "*** Run pione-client with Dropbox location once if you want run this test. ***" + behaves_like "location" + else + puts "*** Ignored the test because the cache of Dropbox's access token doesn't exist. ***" + puts "*** Run pione-client with Dropbox location once if you want run this test. ***" + end end end diff --git a/test/util/spec_completion.rb b/test/util/spec_completion.rb new file mode 100644 index 0000000..072f366 --- /dev/null +++ b/test/util/spec_completion.rb @@ -0,0 +1,22 @@ +require 'pione/test-helper' +require 'pione/util/completion' + +describe Pione::Util::BashCompletion do + it "should compile bash completion file" do + source = Global.project_root + "misc" + "pione-completion.erb" + target = Location[Temppath.create] + Util::BashCompletion.compile(source, target) + target.should.exist + target.size.should > 0 + end +end + +describe Pione::Util::ZshCompletion do + it "should compile zsh completion file" do + source = Global.project_root + "misc" + "pione-completion.erb" + target = Location[Temppath.create] + Util::ZshCompletion.compile(source, target) + target.should.exist + target.size.should > 0 + end +end