diff --git a/.ruby-version b/.ruby-version index 2aaf252..b1b25a5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-1.9.3-p392 +2.2.2 diff --git a/.travis.yml b/.travis.yml index 8916457..ecc596a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,9 @@ notifications: on_success: always script: 'bundle exec rake' rvm: - - 2.0.0 - 1.9.3 - - 1.9.2 - - 1.8.7 - - ree -# - rbx # Removed because travis is choking on rbx and doesn't find rbx-2.0.0-rc1 which was tested locally - - jruby-18mode + - 2.0.0 + - 2.1.0 + - 2.2.0 + - 2.2.2 - jruby-19mode diff --git a/Gemfile b/Gemfile index b850155..a4c19ce 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,6 @@ source 'http://www.rubygems.org' gem 'open4', :platform => :ruby_18 +gem 'test-unit' # Specify your gem's dependencies in methadone.gemspec gemspec diff --git a/README.rdoc b/README.rdoc index 299d258..83d2ab6 100644 --- a/README.rdoc +++ b/README.rdoc @@ -51,15 +51,12 @@ http://a1.mzstatic.com/us/r30/Publication/v4/2c/f7/90/2cf7902f-f709-9125-c73d-87 == Platforms * The build runs on Travis for: - * MRI Ruby 1.8.7 * MRI Ruby 1.9.2 * MRI Ruby 1.9.3 - * RBX - * REE + * MRI Ruby 2.0.0 + * MRI Ruby 2.1.0 * JRuby in both 1.8 and 1.9 mode -It should work on 2.0.0 but there's a weird bundler issue where some of the aruba tests fail in odd ways. - == Bootstrapping a new CLI App The +methadone+ command-line app will bootstrap a new command-line app, setting up a proper gem structure, unit tests, and cucumber-based tests with aruba: @@ -148,7 +145,7 @@ Methadone::CLILogger is designed to handle this. It's a proper subclass of Ruby See {CLILogger's rdoc}[http://davetron5000.github.com/methadone/rdoc/classes/Methadone/CLILogger.html] and then {CLILogging's}[http://davetron5000.github.com/methadone/rdoc/classes/Methadone/CLILogging.html] for more. -Currently, there are classes the assist in directing output logger-style to the right place; basically ensuring that errors go to +STDERR+ and everything else goes to +STDOUT+. All of this is, of course, configurable +Currently, there are classes that assist in directing output logger-style to the right place; basically ensuring that errors go to +STDERR+ and everything else goes to +STDOUT+. All of this is, of course, configurable == Cucumber Steps diff --git a/bin/methadone b/bin/methadone index 8245051..e69fb44 100755 --- a/bin/methadone +++ b/bin/methadone @@ -70,10 +70,29 @@ main do |app_name| copy_file "test/tc_something.rb", :from => :test_unit, :binding => binding end + gemspec = "#{gemname}.gemspec" + gem_variable = File.open(gemspec) { |x| x.read }.match(/(\w+)\.executables/)[1] + license = options[:license] warn "warning: your app has no license" unless license license = nil if license == 'NONE' - copy_file "#{options[:license]}_LICENSE.txt", :as => "LICENSE.txt" if license + if license + copy_file "#{options[:license]}_LICENSE.txt", :as => "LICENSE.txt" + else + #Remove the MIT license generated by `bundle gem` + debug "Making sure no LICENSE.txt file exists at the root of the repo" + FileUtils.rm_f "LICENSE.txt" + end + + #Ensure the gemspec file mentions the correct license + gemspec_content = File.read(gemspec) + if gemspec_content =~ /(^\s*#{gem_variable}\.license\s*=\s*).*/ + gemspec_content.gsub!(/(^\s*#{gem_variable}\.license\s*=\s*).*/,"\\1#{license.to_s.inspect}") + else + gemspec_content.gsub!(/(^\s*#{gem_variable}\.name\s*=\s*.*)/,"\\1\n #{gem_variable}.license=#{license.to_s.inspect}") + end + File.open(gemspec,'w') {|f| f.write gemspec_content } + # TODO: bundle gem creates README.md regardless of using_readme setting. copy_file "README.rdoc", :binding => binding if using_readme @@ -82,20 +101,27 @@ main do |app_name| copy_file "features/step_definitions/executable_steps.rb", :as => "#{gemname}_steps.rb" copy_file "bin/executable", :as => gemname, :executable => true, :binding => binding, :from => (multi ? :multicommand : :full) - gemspec = "#{gemname}.gemspec" - gem_variable = File.open(gemspec) { |x| x.read }.match(/(\w+)\.executables/)[1] add_to_file gemspec, [ " #{gem_variable}.add_development_dependency('rdoc')", " #{gem_variable}.add_development_dependency('aruba')", - " #{gem_variable}.add_development_dependency('rake', '~> 0.9.2')", + " #{gem_variable}.add_development_dependency('rake')", " #{gem_variable}.add_dependency('methadone', '~> #{Methadone::VERSION}')", ], :before => /^end\s*$/ + ruby_major,ruby_minor,ruby_patch = RUBY_VERSION.split(/\./).map(&:to_i) + + if ruby_major >= 2 && ruby_minor >= 2 + add_to_file gemspec, [ + " #{gem_variable}.add_development_dependency('test-unit')", + ], :before => /^end\s*$/ + end if rspec add_to_file gemspec, [ - " #{gem_variable}.add_development_dependency('rspec')", + " #{gem_variable}.add_development_dependency('rspec', '~> 3')", ], :before => /^end\s*$/ end + + sh! %q(git add --all .) end options[:readme] = true @@ -116,7 +142,7 @@ on "-c cmd1,cmd2,cmdN", "--commands", Array, "Generate framework for a cli app t end end -licenses = %w(mit apache custom NONE) +licenses = %w(mit apache gplv2 gplv3 custom NONE) on("-l LICENSE","--license",licenses,"Specify the license for your project",'(' + licenses.join('|') + ')') use_log_level_option diff --git a/features/bootstrap.feature b/features/bootstrap.feature index a34fc09..560edde 100644 --- a/features/bootstrap.feature +++ b/features/bootstrap.feature @@ -36,8 +36,9 @@ Feature: Bootstrap a new command-line app And the file "tmp/newgem/.gitignore" should match /.DS_Store/ And the file "tmp/newgem/newgem.gemspec" should match /add_development_dependency\('aruba'/ And the file "tmp/newgem/newgem.gemspec" should match /add_development_dependency\('rdoc'/ - And the file "tmp/newgem/newgem.gemspec" should match /add_development_dependency\('rake', '~> 0.9.2'/ + And the file "tmp/newgem/newgem.gemspec" should match /add_development_dependency\('rake'/ And the file "tmp/newgem/newgem.gemspec" should match /add_dependency\('methadone'/ + And the file "tmp/newgem/newgem.gemspec" should include "test-unit" if needed And the file "tmp/newgem/newgem.gemspec" should use the same block variable throughout Given I cd to "tmp/newgem" And my app's name is "newgem" @@ -50,16 +51,16 @@ Feature: Bootstrap a new command-line app |--log-level| And the banner should document that this app takes no arguments When I successfully run `rake -T -I../../lib` - Then the output should contain "rake clean # Remove any temporary products" - And the output should contain "rake clobber # Remove any generated file" - And the output should contain "rake clobber_rdoc # Remove RDoc HTML files" - And the output should contain "rake features # Run Cucumber features" - And the output should contain "rake rdoc # Build RDoc HTML files" - And the output should contain "rake release # Create tag v0.0.1 and build and push newgem-0.0.1.gem to Rubygems" - And the output should contain "rake rerdoc # Rebuild RDoc HTML files" - And the output should contain "rake test # Run tests" - And the output should match /rake install # Build and install newgem-0.0.1.gem into system gems/ - And the output should match /rake build # Build newgem-0.0.1.gem into the pkg directory/ + Then the output should match /rake clean/ + And the output should match /rake clobber/ + And the output should match /rake clobber_rdoc/ + And the output should match /rake features/ + And the output should match /rake rdoc/ + And the output should match /rake release/ + And the output should match /rake rerdoc/ + And the output should match /rake test/ + And the output should match /rake install/ + And the output should match /rake build/ When I run `rake -I../../../../lib` Then the exit status should be 0 And the output should match /1 tests, 1 assertions, 0 failures, 0 errors/ @@ -100,22 +101,15 @@ Feature: Bootstrap a new command-line app And I cd to "tmp/new-gem" And my app's name is "new-gem" When I successfully run `bin/new-gem --version` with "lib" in the library path - Then the output should contain: - """ - new-gem version 0.0.1 - """ + Then the output should match /new-gem version 0/ - @wip Scenario: Version flag can be used to only show the app version with a custom format Given I successfully run `methadone tmp/new-gem` And "bin/new-gem" has configured version to show only the version with a custom format and not help And I cd to "tmp/new-gem" And my app's name is "new-gem" When I successfully run `bin/new-gem --version` with "lib" in the library path - Then the output should contain: - """ - new-gem V0.0.1 - """ + Then the output should match /new-gem V0/ Scenario: Won't squash an existing dir When I successfully run `methadone tmp/newgem` @@ -166,3 +160,10 @@ Feature: Bootstrap a new command-line app And the banner should document that this app's arguments are: |app_name|which is required| And there should be a one line summary of what the app does + + Scenario: The whole initial state of the app has been staged with git + Given I successfully run `methadone -l custom tmp/newgem` + And I cd to "tmp/newgem" + When I successfully run `git ls-files --others --deleted ` + Then the output should match /\A\Z/ + diff --git a/features/license.feature b/features/license.feature index e0d51ae..0a9ea64 100644 --- a/features/license.feature +++ b/features/license.feature @@ -11,16 +11,6 @@ Feature: Users should get the license included Then newgem's license should be an empty file And the README should reference the need for a license - Scenario Outline: Include one of a few stock licenses - When I successfully run `methadone -l tmp/newgem` - Then newgem's license should be the license - And the README should reference this license - - Examples: - |license| - |apache| - |mit| - Scenario: We only support a few licenses When I run `methadone -l foobar tmp/newgem` Then the exit status should not be 0 @@ -30,8 +20,24 @@ Feature: Users should get the license included When I successfully run `methadone tmp/newgem` Then the stderr should contain "warning: your app has no license" And the README should not reference a license + And the file "tmp/newgem/LICENSE.txt" should not exist Scenario: No license specified explicitly When I successfully run `methadone -l NONE tmp/newgem` Then the stderr should not contain "warning: your app has no license" And the README should not reference a license + And the file "tmp/newgem/LICENSE.txt" should not exist + + Scenario Outline: Include one of a few stock licenses + When I successfully run `methadone -l tmp/newgem` + Then newgem's license should be the license + And the README should reference this license + And LICENSE.txt should contain user information and program name + + Examples: + |license| + |apache| + |mit| + |gplv2| + |gplv3| + diff --git a/features/multilevel_commands.feature b/features/multilevel_commands.feature index ef5b06b..6b63071 100644 --- a/features/multilevel_commands.feature +++ b/features/multilevel_commands.feature @@ -41,7 +41,7 @@ Feature: Support multi-level commands And the file "tmp/multigem/.gitignore" should match /.DS_Store/ And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency\('aruba'/ And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency\('rdoc'/ - And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency\('rake', '~> 0.9.2'/ + And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency "rake", "~> 10.0"/ And the file "tmp/multigem/multigem.gemspec" should match /add_dependency\('methadone'/ And the file "tmp/multigem/multigem.gemspec" should use the same block variable throughout And the file "tmp/multigem/bin/multigem" should match /command "walk" => Multigem::Commands::Walk/ diff --git a/features/rspec_support.feature b/features/rspec_support.feature index b864aa8..e932b0d 100644 --- a/features/rspec_support.feature +++ b/features/rspec_support.feature @@ -17,14 +17,8 @@ Feature: Bootstrap a new command-line app using RSpec instead of Test::Unit And the file "tmp/newgem/newgem.gemspec" should match /add_development_dependency\('rspec'/ When I cd to "tmp/newgem" And I successfully run `rake -T -I../../lib` - Then the output should contain: - """ - rake spec # Run RSpec code examples - """ - And the output should not contain: - """ - rake test # Run tests - """ + Then the output should match /rake spec/ + And the output should not match /rake test/ When I run `rake spec -I../../lib` Then the exit status should be 0 And the output should contain: diff --git a/features/step_definitions/bootstrap_steps.rb b/features/step_definitions/bootstrap_steps.rb index 6610dc8..e959069 100644 --- a/features/step_definitions/bootstrap_steps.rb +++ b/features/step_definitions/bootstrap_steps.rb @@ -39,3 +39,9 @@ end end end + +Then /^the file "(.*?)" should include "(.*?)" if needed$/ do |file, gemname| + if RUBY_VERSION =~ /^2\./ && RUBY_VERSION !~ /^2.0/ && RUBY_VERSION !~ /^2.1/ + step %{the file "#{file}" should match /add_development_dependency\\('#{gemname}/} + end +end diff --git a/features/step_definitions/license_steps.rb b/features/step_definitions/license_steps.rb index a5f06db..b6fc63e 100644 --- a/features/step_definitions/license_steps.rb +++ b/features/step_definitions/license_steps.rb @@ -5,6 +5,7 @@ Then /^newgem's license should be the (\w+) license/ do |license| @license = license step %(a file named "tmp/newgem/LICENSE.txt" should exist) + step %(the file "tmp/newgem/newgem.gemspec" should match /#{@license}/) end Then /^the README should reference this license$/ do @@ -22,3 +23,8 @@ step %(the file "tmp/newgem/README.rdoc" should match /License:: INSERT LICENSE HERE/) end +Then(/^LICENSE\.txt should contain user information and program name$/) do + step %(the file "tmp/newgem/LICENSE.txt" should match /#{`git config user.name`}/) + step %(the file "tmp/newgem/LICENSE.txt" should match /newgem/) + step %(the file "tmp/newgem/LICENSE.txt" should match /#{Time.now.year}/) +end diff --git a/lib/methadone/cli.rb b/lib/methadone/cli.rb index a0a17e9..1ea42f6 100644 --- a/lib/methadone/cli.rb +++ b/lib/methadone/cli.rb @@ -106,5 +106,19 @@ def normalize_command(cmd) cmd.tr('A-Z','a-z').gsub(/[^a-z0-9_]/,'_').sub(/^_*/,'') end + def render_license_partial(partial) + ERB.new(File.read(template_dir('full/'+partial))).result(binding).strip + end + + def gemspec + @gemspec || @gemspec=_get_gemspec + end + private + def _get_gemspec + files=Dir.glob("*.gemspec") + raise "Multiple gemspec files" if files.size>1 + raise "No gemspec file" if files.size < 1 + Gem::Specification::load(files.first) + end end end diff --git a/lib/methadone/cli_logger.rb b/lib/methadone/cli_logger.rb index d6a4f58..ee48ad5 100644 --- a/lib/methadone/cli_logger.rb +++ b/lib/methadone/cli_logger.rb @@ -85,13 +85,16 @@ def initialize(log_device=$stdout,error_device=$stderr) super(log_device) @stderr_logger = Logger.new(error_device) - @split_logs = log_device.tty? && error_device.tty? + log_device_tty = tty?(log_device) + error_device_tty = tty?(error_device) + + @split_logs = log_device_tty && error_device_tty self.level = Logger::Severity::INFO @stderr_logger.level = DEFAULT_ERROR_LEVEL - self.formatter = BLANK_FORMAT if log_device.tty? - @stderr_logger.formatter = BLANK_FORMAT if error_device.tty? + self.formatter = BLANK_FORMAT if log_device_tty + @stderr_logger.formatter = BLANK_FORMAT if error_device_tty end def level=(level) @@ -119,5 +122,12 @@ def error_formatter=(formatter) @stderr_logger.formatter=formatter end + private + + def tty?(device_or_string) + return device_or_string.tty? if device_or_string.respond_to? :tty? + false + end + end end diff --git a/lib/methadone/cli_logging.rb b/lib/methadone/cli_logging.rb index e2b22cd..e5e5252 100644 --- a/lib/methadone/cli_logging.rb +++ b/lib/methadone/cli_logging.rb @@ -74,7 +74,11 @@ def fatal(progname = nil, &block); logger.fatal(progname,&block); end } # Call this *if* you've included Methadone::Main to set up a --log-level option for your app - # that will allow the user to configure the logging level. + # that will allow the user to configure the logging level. You can pass an optional hash with + # :toggle_debug_on_signal => to enable runtime toggling of the log level by sending the + # signal to your app + # + # +args+:: optional hash # # Example: # @@ -86,12 +90,48 @@ def fatal(progname = nil, &block); logger.fatal(progname,&block); end # # go! # - def use_log_level_option + # Example with runtime toggling: + # + # + # main do + # # your app + # end + # + # use_log_level_option :toggle_debug_on_signal => 'USR1' + # + # go! + def use_log_level_option(args = {}) on("--log-level LEVEL",LOG_LEVELS,'Set the logging level', '(' + LOG_LEVELS.keys.join('|') + ')', '(Default: info)', :global) do |level| @log_level = level + @log_level_original = level + @log_level_toggled = false logger.level = level + + setup_toggle_trap(args[:toggle_debug_on_signal]) + end + end + + private + + # Call this to toggle the log level between debug and its initial value + def toggle_log_level + @log_level_original = logger.level unless @log_level_toggled + logger.level = if @log_level_toggled + @log_level_original + else + LOG_LEVELS['debug'] + end + @log_level_toggled = !@log_level_toggled + @log_level = logger.level + end + + def setup_toggle_trap(signal) + if signal + Signal.trap(signal) do + toggle_log_level + end end end end diff --git a/lib/methadone/cucumber.rb b/lib/methadone/cucumber.rb index 0b3f5b7..47e847a 100644 --- a/lib/methadone/cucumber.rb +++ b/lib/methadone/cucumber.rb @@ -7,7 +7,7 @@ module Methadone # When I get help for "command_to_run" # # * Make sure that each option shows up in the help and has *some* sort of documentation. By default, - # the options won't be re2quired to be negatable. + # the options won't be required to be negatable. # # Then the following options should be documented: # |--force| @@ -166,8 +166,9 @@ module Cucumber Then /^there should be a one line summary of what the app does$/ do output_lines = all_output.split(/\n/) - output_lines.should have_at_least(4).items - # [0] is a blank line, [1] is our banner, which we've checked for + output_lines.size.should >= 4 + # [0] is a blank line, + # [1] is our banner, which we've checked for output_lines[2].should match(/^\s*$/) output_lines[3].should match(/^\w+\s+\w+/) end diff --git a/lib/methadone/execution_strategy/base.rb b/lib/methadone/execution_strategy/base.rb index a747137..91f695e 100644 --- a/lib/methadone/execution_strategy/base.rb +++ b/lib/methadone/execution_strategy/base.rb @@ -18,17 +18,17 @@ class Base # [2]:: A Process::Status-like objects that responds to exitstatus which returns # the exit code of the command (e.g. 0 for success). def run_command(command) - subclass_must_impelment! + subclass_must_implement! end # Returns the class that, if caught by calling #run_command, represents the underlying command # not existing. For example, in MRI Ruby, if you try to execute a non-existent command, # you get a Errno::ENOENT. def exception_meaning_command_not_found - subclass_must_impelment! + subclass_must_implement! end protected - def subclass_must_impelment!; raise "subclass must implement"; end + def subclass_must_implement!; raise "subclass must implement"; end end end end diff --git a/lib/methadone/main.rb b/lib/methadone/main.rb index d78218f..be7f3e0 100644 --- a/lib/methadone/main.rb +++ b/lib/methadone/main.rb @@ -189,14 +189,18 @@ def defaults_from_env_var(env_var) @env_var = env_var end - # Set the name of the file, in the user's home directory, where defaults can be configured. + # Set the path to the file where defaults can be configured. + # # The format of this file can be either a simple string of options, like what goes # in the environment variable (see #defaults_from_env_var), or YAML, in which case # it should be a hash where keys are the option names, and values their defaults. # - # filename:: name of the file, relative to the user's home directory + # Relative paths will be expanded relative to the user's home directory. + # + # filename:: path to the file. If relative, will look in user's HOME directory. + # If absolute, this is the absolute path to where the file should be. def defaults_from_config_file(filename,options={}) - @rc_file = File.join(ENV['HOME'],filename) + @rc_file = File.expand_path(filename, ENV['HOME']) end # Start your command-line app, exiting appropriately when diff --git a/lib/methadone/sh.rb b/lib/methadone/sh.rb index 19b673b..66dc87c 100644 --- a/lib/methadone/sh.rb +++ b/lib/methadone/sh.rb @@ -196,7 +196,10 @@ def execution_strategy end def sh_logger - @sh_logger ||= self.logger + @sh_logger ||= begin + raise StandardError, "No logger set! Please include Methadone::CLILogging or provide your own via #set_sh_logger." unless self.respond_to?(:logger) + self.logger + end end # Safely call our block, even if the user passed in a lambda diff --git a/lib/methadone/version.rb b/lib/methadone/version.rb index 3af7770..0c69c86 100644 --- a/lib/methadone/version.rb +++ b/lib/methadone/version.rb @@ -1,3 +1,3 @@ module Methadone #:nodoc: - VERSION = "1.0.0" #:nodoc: + VERSION = "1.9.1" #:nodoc: end diff --git a/methadone-clinic.gemspec b/methadone-clinic.gemspec index e9fef4c..2c55c13 100644 --- a/methadone-clinic.gemspec +++ b/methadone-clinic.gemspec @@ -25,8 +25,8 @@ Gem::Specification.new do |s| s.add_development_dependency("simplecov", "~> 0.5") s.add_development_dependency("clean_test") s.add_development_dependency("mocha", "0.13.2") - s.add_development_dependency("minitest", "4.6.1") s.add_development_dependency("sdoc") s.add_development_dependency("pry") - s.add_development_dependency("rspec") # needed so that rspec-bootstrapped app test can run + s.add_development_dependency("rspec", "~> 3") + s.add_development_dependency("i18n", "= 0.6.1") end diff --git a/templates/full/_license_head.txt.erb b/templates/full/_license_head.txt.erb new file mode 100644 index 0000000..e98521c --- /dev/null +++ b/templates/full/_license_head.txt.erb @@ -0,0 +1,2 @@ +Name: <%= gemspec.name %><%#TODO: Get program name more efficiently -%> +Copyright (c) <%= Time.now.year %> <%=`git config user.name`.strip %> diff --git a/templates/full/apache_LICENSE.txt.erb b/templates/full/apache_LICENSE.txt.erb index d645695..5ee976f 100644 --- a/templates/full/apache_LICENSE.txt.erb +++ b/templates/full/apache_LICENSE.txt.erb @@ -187,7 +187,8 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Name: <%= gemspec.name %><%#TODO: Get program name more efficiently -%> + Copyright <%= Time.now.year %> <%=`git config user.name` %> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/templates/full/bin/executable.erb b/templates/full/bin/executable.erb index 5f4db9e..d611894 100644 --- a/templates/full/bin/executable.erb +++ b/templates/full/bin/executable.erb @@ -41,7 +41,7 @@ class App version <%= module_name %>::VERSION - use_log_level_option + use_log_level_option :toggle_debug_on_signal => 'USR1' go! end diff --git a/templates/full/gplv2_LICENSE.txt.erb b/templates/full/gplv2_LICENSE.txt.erb new file mode 100644 index 0000000..e8e1481 --- /dev/null +++ b/templates/full/gplv2_LICENSE.txt.erb @@ -0,0 +1,14 @@ +<%= render_license_partial('_license_head.txt.erb') %> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see . diff --git a/templates/full/gplv3_LICENSE.txt.erb b/templates/full/gplv3_LICENSE.txt.erb new file mode 100644 index 0000000..72b85c2 --- /dev/null +++ b/templates/full/gplv3_LICENSE.txt.erb @@ -0,0 +1,15 @@ +<%= render_license_partial('_license_head.txt.erb') %> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + diff --git a/templates/full/mit_LICENSE.txt.erb b/templates/full/mit_LICENSE.txt.erb index 60a3e34..761154c 100644 --- a/templates/full/mit_LICENSE.txt.erb +++ b/templates/full/mit_LICENSE.txt.erb @@ -1,4 +1,4 @@ -Copyright (c) <%= Time.now.year %> YOUR NAME +<%= render_license_partial('_license_head.txt.erb') %> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/templates/rspec/spec/something_spec.rb.erb b/templates/rspec/spec/something_spec.rb.erb index 22b13e2..d44a53f 100644 --- a/templates/rspec/spec/something_spec.rb.erb +++ b/templates/rspec/spec/something_spec.rb.erb @@ -1,5 +1,5 @@ describe "TestSomething" do it "should be true" do - true.should be_true + expect(true).to eq(true) end end diff --git a/test/base_test.rb b/test/base_test.rb index 9e5c0aa..3a43ba9 100644 --- a/test/base_test.rb +++ b/test/base_test.rb @@ -1,12 +1,20 @@ -require 'simplecov' -SimpleCov.start do - add_filter "/test" +if RUBY_PLATFORM == 'java' + puts "Simplecov seems to cause JRuby to barf, so use another ruby if you want to check coverage" +else + require 'simplecov' + SimpleCov.start do + add_filter "/test" + end end + require 'test/unit' require 'rspec/expectations' require 'clean_test/test_case' require 'ostruct' require 'pry' +RSpec::Matchers.configuration.syntax = :should + class BaseTest < Clean::Test::TestCase + include RSpec::Matchers end diff --git a/test/test_cli_logger.rb b/test/test_cli_logger.rb index 6554f70..344ad30 100644 --- a/test/test_cli_logger.rb +++ b/test/test_cli_logger.rb @@ -1,6 +1,7 @@ require 'base_test' require 'methadone' require 'stringio' +require 'tempfile' class TestCLILogger < BaseTest include Methadone @@ -158,6 +159,27 @@ def tty?; true; end } end + test_that "we can use filenames as log devices" do + Given { + tempfile = Tempfile.new("stderr_log") + @stdout_file = tempfile.path + tempfile.close + + tempfile = Tempfile.new("stdout_log") + @stderr_file = tempfile.path + tempfile.close + } + When { + @logger = CLILogger.new(@stdout_file,@stderr_file) + @logger.info("some info") + @logger.error("some error") + } + Then { + File.read(@stdout_file).should =~ /some info/ + File.read(@stderr_file).should =~ /some error/ + } + end + private def log_all_levels diff --git a/test/test_cli_logging.rb b/test/test_cli_logging.rb index d6f56c8..098e30f 100644 --- a/test/test_cli_logging.rb +++ b/test/test_cli_logging.rb @@ -5,6 +5,8 @@ class TestCLILogging < BaseTest include Methadone + SLEEP_TIME = 0.1 + def setup @blank_format = proc do |severity,datetime,progname,msg| msg + "\n" @@ -122,11 +124,61 @@ def teardown } end + + test_that "when we enable runtime log level toggling, it toggles the log level on receiving the set signal" do + Given { + @app = MyAppThatActsLikeItUsesMain.new + @app.call_use_log_level_option( :toggle_debug_on_signal => 'USR2' ) + @level = Logger::INFO + @app.use_option(@level) + } + When { + send_signal_and_wait_a_moment('USR2') + } + Then { + @app.logger.level.should == Logger::DEBUG + } + end + + test_that "when we toggle the log level and change the logger, the new logger has also it's log level increased" do + Given { + @app = MyAppThatActsLikeItUsesMain.new + @app.call_use_log_level_option( :toggle_debug_on_signal => 'USR2' ) + @level = Logger::INFO + @app.use_option(@level) + } + When { + send_signal_and_wait_a_moment('USR2') + @other_logger = OpenStruct.new + @app.change_logger(@other_logger) + } + Then { + @other_logger.level.should == Logger::DEBUG + } + end + + test_that "when we enable runtime log level toggling and send the signal twice, the original log level is restored" do + Given { + @app = MyAppThatActsLikeItUsesMain.new + @app.call_use_log_level_option( :toggle_debug_on_signal => 'USR2' ) + @level = Logger::INFO + @app.use_option(@level) + } + When { + send_signal_and_wait_a_moment('USR2') + send_signal_and_wait_a_moment('USR2') + } + Then { + @app.logger.level.should == Logger::INFO + } + end + + class MyAppThatActsLikeItUsesMain include Methadone::CLILogging - def call_use_log_level_option - use_log_level_option + def call_use_log_level_option(args = {}) + use_log_level_option(args) end def use_option(level) @@ -183,4 +235,9 @@ def doit def logger_id; logger.object_id; end end + + def send_signal_and_wait_a_moment(signal) + Process.kill(signal, $$) + sleep(SLEEP_TIME) # call sleep to give the trap handler a chance to kick in + end end diff --git a/test/test_main.rb b/test/test_main.rb index dd189b3..38b8c6a 100644 --- a/test/test_main.rb +++ b/test/test_main.rb @@ -199,7 +199,7 @@ def teardown end } Then { - assert_raises Methadone::Error do + assert_raises Methadone::Error do When run_go! end } @@ -340,7 +340,7 @@ def teardown on("--[no-]negatable") on("--flag FLAG","-f","Some documentation string") on("--flag-with-dashes FOO") - on("--other") do + on("--other") do options[:some_other] = true end @@ -393,7 +393,7 @@ def teardown test_that "I can specify which arguments my app takes and if they are required as well as document them" do Given { main {} - @db_name_desc = any_string + @db_name_desc = any_string @user_desc = any_string @password_desc = any_string @@ -427,7 +427,7 @@ def teardown test_that "I can specify which arguments my app takes and if they are singular or optional plural" do Given { main {} - + arg :db_name arg :user, :required, :one arg :tables, :any @@ -704,6 +704,31 @@ def teardown end + test_that "we can get defaults from an absolute config filename" do + tempfile = Tempfile.new('methadone_test.rc') + Given app_to_use_rc_file(tempfile.path) + And { + @flag_value = any_string + rc_file = File.join(tempfile.path) + File.open(rc_file,'w') do |file| + file.puts({ + 'switch' => true, + 'flag' => @flag_value, + }.to_yaml) + end + } + When { + @code = lambda { go! } + } + Then { + assert_exits(0,&@code) + @switch.should == true + @flag.should == @flag_value + } + + end + + test_that "we can specify an rc file even if it doesn't exist" do Given app_to_use_rc_file And { @@ -1002,7 +1027,7 @@ def teardown } Then { assert_exits(0,&@code) - @first.should be_true + @first.should be_truthy @second.should be_nil } end @@ -1077,7 +1102,7 @@ def teardown } Then { assert_exits(0,&@code) - @first.should be_true + @first.should be_truthy @second.should be_nil @third.should == 'value' } @@ -1112,7 +1137,7 @@ def teardown private - def app_to_use_rc_file + def app_to_use_rc_file(rc_file = '.my_app.rc') lambda { reset! @switch = nil @@ -1124,7 +1149,7 @@ def app_to_use_rc_file @args = args end - defaults_from_config_file '.my_app.rc' + defaults_from_config_file rc_file on('--switch','Some Switch') on('--flag FOO','Some Flag') @@ -1157,7 +1182,7 @@ def app_to_use_environment def main_shouldve_been_called Proc.new { assert @called,"Main block wasn't called?!" } end - + def run_go_safely Proc.new { safe_go! } end diff --git a/test/test_multi.rb b/test/test_multi.rb index ce675bb..264ccd5 100644 --- a/test/test_multi.rb +++ b/test/test_multi.rb @@ -19,7 +19,7 @@ class Walk on '-s', '--silly-walk' on '-d', '--direction DIRECTION', Integer, "Compass cardinal direction" arg "distance", "How far to walk" - + end class Run include Methadone::Main @@ -39,7 +39,7 @@ class Greet options[:lang] = 'es' - main do + main do msg = case options[:lang] when 'en' 'Hello' @@ -118,7 +118,7 @@ class WontWork } Then number_of_commands_should_be(0) Then { - expect(@error).to be_a_kind_of(::Methadone::InvalidProvider) + @error.should be_a_kind_of(::Methadone::InvalidProvider) } end @@ -132,7 +132,7 @@ class WontWork } When run_go_safely Then { - expect(opts.selected_command).to eq('walk') + opts.selected_command.should eq('walk') } end @@ -144,9 +144,9 @@ class WontWork } When run_go_safely Then { - expect(opts.command_names).to include('walk') - expect(opts.command_names).to include('run') - expect($stdout.string).to match(/walk called/) + opts.command_names.should include('walk') + opts.command_names.should include('run') + $stdout.string.should match(/walk called/) } And number_of_commands_should_be(2) end @@ -279,16 +279,16 @@ class WontWork $stdout.string.should match /HELLO/ } end - + private - def commands_should_include(cmd) - proc { expect(opts.commands.keys).to include(cmd)} + def commands_should_include(cmd) + proc { opts.commands.keys.should include(cmd) } end def number_of_commands_should_be(num) proc { opts.commands.keys.length.should be(num)} - end + end def provider_for_command(cmd) opts.commands[cmd] @@ -365,7 +365,7 @@ def main_should_not_be_called def main_shouldve_been_called Proc.new { assert @main_called,"Main block wasn't called?!" } end - + def run_go_safely Proc.new { safe_go! } end @@ -401,5 +401,5 @@ def get_const(class_name) Object.module_eval("::#{$1}", __FILE__, __LINE__) end - + end diff --git a/test/test_sh.rb b/test/test_sh.rb index 5ce3d13..d2b9fbd 100644 --- a/test/test_sh.rb +++ b/test/test_sh.rb @@ -1,7 +1,7 @@ require 'base_test' require 'methadone' -class TestSH < Clean::Test::TestCase +class TestSH < BaseTest include Methadone::SH include Methadone::CLILogging @@ -143,7 +143,7 @@ def fatal(msg); @fatals << msg; end use_capturing_logger @command = test_command("foo") @block_called = false - } + } When { @exit_code = sh @command do @block_called = true @@ -160,7 +160,7 @@ def fatal(msg); @fatals << msg; end use_capturing_logger @command = test_command("foo") @block_called = false - } + } When { @exit_code = sh @command, :expected => [2] do @block_called = true @@ -180,7 +180,7 @@ def fatal(msg); @fatals << msg; end @command = test_command("foo") @block_called = false @exitstatus_received = nil - } + } When { @exit_code = self.send(method,@command,:expected => expected) do |_,_,exitstatus| @block_called = true @@ -242,7 +242,7 @@ def fatal(msg); @fatals << msg; end } end - test_that "sh! runs a command that will fail and includes an error message that appears in the exception" do + test_that "sh! runs a command that will fail and includes an error message that appears in the exception" do Given { use_capturing_logger @command = test_command("foo") @@ -261,8 +261,8 @@ def fatal(msg); @fatals << msg; end class MyTestApp include Methadone::SH - def initialize(logger) - set_sh_logger(logger) + def initialize(logger=nil) + set_sh_logger(logger) if logger end end @@ -280,6 +280,19 @@ def initialize(logger) } end + test_that "when we don't have CLILogging included and fail to provide a logger, an exception is thrown" do + Given { + @test_app = MyTestApp.new + @command = test_command + } + When { + @code = lambda { @test_app.sh @command } + } + Then { + exception = assert_raises(StandardError,&@code) + } + end + class MyExecutionStrategy include Clean::Test::Any attr_reader :command