lib/bundlegem/cli/gem.rb in bundlegem-0.0.5 vs lib/bundlegem/cli/gem.rb in bundlegem-0.0.6
- old
+ new
@@ -14,12 +14,10 @@
validate_ext_name if options[:ext]
end
def run
- # Bundler.ui.confirm "Creating gem '#{name}'..."
-
raise_project_with_that_name_already_exists! if File.exists?(target)
underscored_name = name.tr('-', '_')
namespaced_path = name.tr('-', '/')
constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] unless p.empty?}.join
@@ -43,79 +41,16 @@
:ext => options[:ext],
:bin => options[:bin],
:bundler_version => bundler_dependency_version
}
ensure_safe_gem_name(name, constant_array)
-
- # Hmmm... generate dynamically instead? Yes, overwritten below
- templates = {
- 'Gemfile.tt' => "Gemfile",
- 'changelog.tt' => "changelog",
- 'gitignore.tt' => ".gitignore",
- 'lib/#{name}.rb.tt' => "lib/#{namespaced_path}.rb",
- 'lib/#{name}/version.rb.tt' => "lib/#{namespaced_path}/version.rb",
- '#{name}.gemspec.tt' => "#{name}.gemspec",
- 'Rakefile.tt' => "Rakefile",
- 'README.md.tt' => "README.md",
- 'bin/console.tt' => "bin/console"
- }
-
-
- 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
-
- 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."
- )
- config[:mit] = true
- templates.merge!("LICENSE.txt.tt" => "LICENSE.txt")
- end
-
- 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/#{name}_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]
- 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
-
- puts "Creating new project folder\n\n"
-
template_src = match_template_src
template_directories = dynamically_generate_template_directories
- templates = dynamically_generate_templates || templates
+ templates = dynamically_generate_templates(config)
+ puts "Creating new project folder '#{name}'\n\n"
create_template_directories(template_directories, target)
templates.each do |src, dst|
template("#{template_src}/#{src}", target.join(dst), config)
end
@@ -137,140 +72,123 @@
private
def dynamically_generate_template_directories
# return nil if options["template"].nil?
- template_src = get_template_src
+ template_src = TemplateManager.get_template_src(options)
template_dirs = {}
Dir.glob("#{template_src}/**/*").each do |f|
next unless File.directory? f
base_path = f[template_src.length+1..-1]
template_dirs.merge!(base_path => base_path.gsub('#{name}', "#{name}") )
end
template_dirs
end
- def dynamically_generate_templates
- return nil if options["template"].nil?
+ # This function should be eliminated over time so that other methods conform to the
+ # new algo for generating templates automatically.
+ # Really, this function generates a template_src to template_dst naming
+ # structure so that a later method can copy all the template files from the
+ # source and rename them properly
+ def generate_templates_for_built_in_gems(config)
+ # Hmmm... generate dynamically instead? Yes, overwritten below
+ templates = {
+ 'Gemfile.tt' => "Gemfile",
+ 'changelog.tt' => "changelog",
+ 'gitignore.tt' => ".gitignore",
+ 'lib/#{name}.rb.tt' => "lib/#{config[:namespaced_path]}.rb",
+ 'lib/#{name}/version.rb.tt' => "lib/#{config[:namespaced_path]}/version.rb",
+ '#{name}.gemspec.tt' => "#{config[:name]}.gemspec",
+ 'Rakefile.tt' => "Rakefile",
+ 'README.md.tt' => "README.md",
+ 'bin/console.tt' => "bin/console"
+ }
- template_src = get_template_src
-
- templates = {}
- Dir.glob("#{template_src}/**/*.tt").each do |f|
- base_path = f[template_src.length+1..-1]
- templates.merge!(base_path => base_path.gsub(/\.tt$/, "").gsub('#{name}', "#{name}") )
- end
-
- raise_no_files_in_template_error! if templates.empty?
+ prompt_coc!(templates)
+ prompt_mit!(templates, config)
+ prompt_test_framework!(templates, config)
+ templates.merge!("exe/newgem.tt" => "exe/#{config[:name]}") if config[:bin]
+
+ if config[:ext]
+ templates.merge!(
+ "ext/newgem/extconf.rb.tt" => "ext/#{config[:name]}/extconf.rb",
+ "ext/newgem/newgem.h.tt" => "ext/#{config[:name]}/#{config[:underscored_name]}.h",
+ "ext/newgem/newgem.c.tt" => "ext/#{config[:name]}/#{config[:underscored_name]}.c"
+ )
+ end
templates
end
+ # Figures out the translation between all the .tt file to their
+ # destination names
+ def dynamically_generate_templates(config)
+ #if options["template"].nil? # if it's doing some of the built in template
+ # return generate_templates_for_built_in_gems(config)
+ #else
+ template_src = TemplateManager.get_template_src(options)
+
+ templates = {}
+ Dir.glob("#{template_src}/**/{*,.*}.tt").each do |f|
+ base_path = f[template_src.length+1..-1]
+ templates.merge!(base_path => base_path.gsub(/\.tt$/, "").gsub('#{name}', "#{name}") )
+ end
+
+ raise_no_files_in_template_error! if templates.empty?
+
+ return templates
+ #end
+ end
+
def create_template_directories(template_directories, target)
template_directories.each do |k,v|
d = "#{target}/#{v}"
puts " mkdir #{d} ..."
FileUtils.mkdir_p(d)
end
end
+ # returns the full path of the template source
def match_template_src
- template_src = get_template_src
+ template_src = TemplateManager.get_template_src(options)
- if template_exists_within_repo?(template_src) or File.exists?(template_src)
+ if File.exists?(template_src)
return template_src # 'newgem' refers to the built in template that comes with the gem
else
raise_template_not_found! # else message the user that the template could not be found
end
end
-
- def get_template_src
- template_name = options["template"].nil? ? "newgem" : options["template"]
-
- if template_exists_within_repo?(template_name)
- gem_template_location = get_internal_template_location
- else
- gem_template_location = File.expand_path("~/.bundlegem/gem_templates")
- end
- template_src = "#{gem_template_location}/#{template_name}"
- end
- def template_exists_within_repo?(template_name)
- file_in_source?(template_name)
- end
- def get_internal_template_location
- File.expand_path("#{File.dirname(__FILE__)}/../templates")
- end
-
def resolve_name(name)
Pathname.pwd.join(name).basename.to_s
end
- def ask_and_set(key, header, message)
- choice = options[key] # || Bundler.settings["gem.#{key}"]
-
- if choice.nil?
- Bundler.ui.confirm header
- choice = (Bundler.ui.ask("#{message} y/(n):") =~ /y|yes/)
- Bundler.settings.set_global("gem.#{key}", choice)
- end
-
- choice
- 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
-
- test_framework
- end
-
+
def bundler_dependency_version
v = Gem::Version.new(Bundler::VERSION)
req = v.segments[0..1]
req << 'a' if v.prerelease?
req.join(".")
end
- def ensure_safe_gem_name name, constant_array
- if name =~ /^\d/
- Bundler.ui.error "Invalid gem name #{name} Please give a name which does not start with numbers."
- exit 1
- elsif Object.const_defined?(constant_array.first)
- Bundler.ui.error "Invalid gem name #{name} constant #{constant_array.join("::")} is already in use. Please choose another gem name."
- exit 1
- end
- end
+
#
# EDIT: Reworked from Thor to not rely on Thor (or do so much unneeded stuff)
#
# Gets an ERB template at the relative source, executes it and makes a copy
# at the relative destination. If the destination is not given it's assumed
@@ -289,34 +207,22 @@
#
def template(source, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/, "")
- source = File.expand_path(find_in_source_paths(source.to_s))
+ source = File.expand_path(TemplateManager.find_in_source_paths(source.to_s))
context = instance_eval("binding")
make_file(destination, config) do
content = ERB.new(::File.binread(source), nil, "-", "@output_buffer").result(context)
content = block.call(content) if block
content
end
end
- #
- # EDIT: Reworked from Thor to not rely on Thor (or do so much unneeded stuff)
- #
- def find_in_source_paths(target)
- src_in_source_path = "#{File.dirname(__FILE__)}/../templates/#{target}"
- return src_in_source_path if File.exists?(src_in_source_path)
- target # failed, hopefully full path to a user specified gem template file
- end
- def file_in_source?(target)
- src_in_source_path = "#{File.dirname(__FILE__)}/../templates/#{target}"
- File.exists?(src_in_source_path)
- end
#
# EDIT: Reworked from Thor to not rely on Thor (or do so much unneeded stuff)
#
def make_file(destination, config, &block)
@@ -346,9 +252,105 @@
def raise_template_not_found!
err_missing_template = "Could not find template folder '#{options["template"]}' in `~/.bundle/gem_templates/`. Please check to make sure your desired template exists."
puts err_missing_template
Bundler.ui.error err_missing_template
exit 1
+ end
+
+
+ ############# STUFF THAT SHOULD BE REMOVED DOWN THE ROAD
+
+ # This asks the user if they want to setup rspec or test...
+ # It's not class based, it's additive based... Plus bundlegem does this already
+ 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
+
+ test_framework
+ end
+
+ def ask_and_set(key, header, message)
+ choice = options[key] # || Bundler.settings["gem.#{key}"]
+
+ if choice.nil?
+ Bundler.ui.confirm header
+ choice = (Bundler.ui.ask("#{message} y/(n):") =~ /y|yes/)
+ Bundler.settings.set_global("gem.#{key}", choice)
+ end
+
+ choice
+ end
+
+ def prompt_coc!(templates)
+ 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
+ end
+
+ def prompt_mit!(templates, config)
+ 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."
+ )
+ config[:mit] = true
+ templates.merge!("LICENSE.txt.tt" => "LICENSE.txt")
+ end
+ end
+
+ def prompt_test_framework!(templates, config)
+ namespaced_path = config[:namespaced_path]
+ 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/#{name}_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
+ end
+
+ # This checks to see that the gem_name is a valid ruby gem name and will 'work'
+ # and won't overlap with a bundlegem constant apparently...
+ #
+ # TODO: This should be defined within the template itself in some way possibly, may have security implications
+ def ensure_safe_gem_name(name, constant_array)
+ if name =~ /^\d/
+ Bundler.ui.error "Invalid gem name #{name} Please give a name which does not start with numbers."
+ exit 1
+ elsif Object.const_defined?(constant_array.first)
+ Bundler.ui.error "Invalid gem name #{name} constant #{constant_array.join("::")} is already in use. Please choose another gem name."
+ exit 1
+ end
end
end
end