lib/bundler/cli/gem.rb in bundler-1.7.15 vs lib/bundler/cli/gem.rb in bundler-1.8.0.pre
- old
+ new
@@ -1,78 +1,166 @@
+require 'pathname'
+
module Bundler
class CLI::Gem
- attr_reader :options, :gem_name, :thor
+ attr_reader :options, :gem_name, :thor, :name, :target
+
def initialize(options, gem_name, thor)
@options = options
- @gem_name = gem_name
+ @gem_name = resolve_name(gem_name)
@thor = thor
+
+ @name = @gem_name
+ @target = Pathname.pwd.join(gem_name)
+
+ validate_ext_name if options[:ext]
end
def run
- if options[:ext] && gem_name.index('-')
- Bundler.ui.error "You have specified a gem name which does not conform to the \n" \
- "naming guidelines for C extensions. For more information, \n" \
- "see the 'Extension Naming' section at the following URL:\n" \
- "http://guides.rubygems.org/gems-with-extensions/\n"
- exit 1
- end
+ Bundler.ui.confirm "Creating gem '#{name}'..."
- name = gem_name.chomp("/") # remove trailing slash if present
underscored_name = name.tr('-', '_')
namespaced_path = name.tr('-', '/')
- target = File.join(Dir.pwd, name)
constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] }.join
constant_name = constant_name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/
constant_array = constant_name.split('::')
git_user_name = `git config user.name`.chomp
git_user_email = `git config user.email`.chomp
+
opts = {
:name => name,
:underscored_name => underscored_name,
:namespaced_path => namespaced_path,
:makefile_path => "#{underscored_name}/#{underscored_name}",
:constant_name => constant_name,
:constant_array => constant_array,
:author => git_user_name.empty? ? "TODO: Write your name" : git_user_name,
:email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
:test => options[:test],
- :ext => options[:ext]
+ :ext => options[:ext],
+ :bin => options[:bin]
}
- gemspec_dest = File.join(target, "#{name}.gemspec")
- thor.template(File.join("newgem/Gemfile.tt"), File.join(target, "Gemfile"), opts)
- thor.template(File.join("newgem/Rakefile.tt"), File.join(target, "Rakefile"), opts)
- thor.template(File.join("newgem/LICENSE.txt.tt"), File.join(target, "LICENSE.txt"), opts)
- thor.template(File.join("newgem/README.md.tt"), File.join(target, "README.md"), opts)
- thor.template(File.join("newgem/gitignore.tt"), File.join(target, ".gitignore"), opts)
- thor.template(File.join("newgem/newgem.gemspec.tt"), gemspec_dest, opts)
- thor.template(File.join("newgem/lib/newgem.rb.tt"), File.join(target, "lib/#{namespaced_path}.rb"), opts)
- thor.template(File.join("newgem/lib/newgem/version.rb.tt"), File.join(target, "lib/#{namespaced_path}/version.rb"), opts)
- if options[:bin]
- thor.template(File.join("newgem/bin/newgem.tt"), File.join(target, 'bin', name), opts)
+
+ templates = {
+ "Gemfile.tt" => "Gemfile",
+ "gitignore.tt" => ".gitignore",
+ "lib/newgem.rb.tt" => "lib/#{namespaced_path}.rb",
+ "lib/newgem/version.rb.tt" => "lib/#{namespaced_path}/version.rb",
+ "newgem.gemspec.tt" => "#{name}.gemspec",
+ "Rakefile.tt" => "Rakefile",
+ "README.md.tt" => "README.md",
+ "bin/console.tt" => "bin/console",
+ "bin/setup.tt" => "bin/setup"
+ }
+
+ if ask_and_set(:coc, "Do you want to include a code of conduct in gems you generate?",
+ "Codes of conduct can increase contributions to your project by contributors who " \
+ "prefer collaborative, safe spaces. You can read more about the code of conduct at " \
+ "contributor-covenant.org. Having a code of conduct means agreeing to the responsibility " \
+ "of enforcing it, so be sure that you are prepared to do that. For suggestions about " \
+ "how to enforce codes of conduct, see bit.ly/coc-enforcement."
+ )
+ templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
end
- case options[:test]
- when 'rspec'
- thor.template(File.join("newgem/rspec.tt"), File.join(target, ".rspec"), opts)
- thor.template(File.join("newgem/spec/spec_helper.rb.tt"), File.join(target, "spec/spec_helper.rb"), opts)
- thor.template(File.join("newgem/spec/newgem_spec.rb.tt"), File.join(target, "spec/#{namespaced_path}_spec.rb"), opts)
- when 'minitest'
- thor.template(File.join("newgem/test/minitest_helper.rb.tt"), File.join(target, "test/minitest_helper.rb"), opts)
- thor.template(File.join("newgem/test/test_newgem.rb.tt"), File.join(target, "test/test_#{namespaced_path}.rb"), opts)
+
+ if ask_and_set(:mit, "Do you want to license your code permissively under the MIT license?",
+ "This means that any other developer or company will be legally allowed to use your code " \
+ "for free as long as they admit you created it. You can read more about the MIT license " \
+ "at choosealicense.com/licenses/mit."
+ )
+ templates.merge!("LICENSE.txt.tt" => "LICENSE.txt")
end
- if options[:test]
- thor.template(File.join("newgem/.travis.yml.tt"), File.join(target, ".travis.yml"), opts)
+
+ if test_framework = ask_and_set_test_framework
+ templates.merge!(".travis.yml.tt" => ".travis.yml")
+
+ case test_framework
+ when 'rspec'
+ templates.merge!(
+ "rspec.tt" => ".rspec",
+ "spec/spec_helper.rb.tt" => "spec/spec_helper.rb",
+ "spec/newgem_spec.rb.tt" => "spec/#{namespaced_path}_spec.rb"
+ )
+ when 'minitest'
+ templates.merge!(
+ "test/minitest_helper.rb.tt" => "test/minitest_helper.rb",
+ "test/test_newgem.rb.tt" => "test/test_#{namespaced_path}.rb"
+ )
+ end
end
+
+ templates.merge!("exe/newgem.tt" => "exe/#{name}") if options[:bin]
+
if options[:ext]
- thor.template(File.join("newgem/ext/newgem/extconf.rb.tt"), File.join(target, "ext/#{name}/extconf.rb"), opts)
- thor.template(File.join("newgem/ext/newgem/newgem.h.tt"), File.join(target, "ext/#{name}/#{underscored_name}.h"), opts)
- thor.template(File.join("newgem/ext/newgem/newgem.c.tt"), File.join(target, "ext/#{name}/#{underscored_name}.c"), opts)
+ templates.merge!(
+ "ext/newgem/extconf.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h",
+ "ext/newgem/newgem.c.tt" => "ext/#{name}/#{underscored_name}.c"
+ )
end
+
+ templates.each do |src, dst|
+ thor.template("newgem/#{src}", target.join(dst), opts)
+ end
+
Bundler.ui.info "Initializing git repo in #{target}"
Dir.chdir(target) { `git init`; `git add .` }
if options[:edit]
- thor.run("#{options["edit"]} \"#{gemspec_dest}\"") # Open gemspec in editor
+ # Open gemspec in editor
+ thor.run("#{options["edit"]} \"#{target.join("#{name}.gemspec")}\"")
end
+ end
+
+ private
+
+ def resolve_name(name)
+ Pathname.pwd.join(name).basename.to_s
+ end
+
+ def ask_and_set(key, header, message)
+ result = options[key]
+ if !Bundler.settings.all.include?("gem.#{key}")
+ if result.nil?
+ Bundler.ui.confirm header
+ result = Bundler.ui.ask("#{message} y/(n):") == "y"
+ end
+
+ Bundler.settings.set_global("gem.#{key}", result)
+ end
+
+ result || Bundler.settings["gem.#{key}"]
+ end
+
+ def validate_ext_name
+ return unless gem_name.index('-')
+
+ Bundler.ui.error "You have specified a gem name which does not conform to the \n" \
+ "naming guidelines for C extensions. For more information, \n" \
+ "see the 'Extension Naming' section at the following URL:\n" \
+ "http://guides.rubygems.org/gems-with-extensions/\n"
+ exit 1
+ end
+
+ def ask_and_set_test_framework
+ test_framework = options[:test] || Bundler.settings["gem.test"]
+ if test_framework.nil?
+ Bundler.ui.confirm "Do you want to generate tests with your gem?"
+ result = Bundler.ui.ask "Type 'rspec' or 'minitest' to generate those test files now and " \
+ "in the future. rspec/minitest/(none):"
+ if result =~ /rspec|minitest/
+ test_framework = result
+ else
+ test_framework = "false"
+ end
+ end
+
+ if Bundler.settings["gem.test"].nil?
+ Bundler.settings.set_global("gem.test", test_framework)
+ end
+
+ return if test_framework == "false"
+ test_framework
end
end
end