├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── Rakefile.erb ├── Readme.markdown ├── bin └── gem-this ├── gem-this.gemspec ├── lib ├── gem_this.rb └── rubygems_plugin.rb └── test ├── gem_this_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | rdoc -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gem 'shoulda' 4 | gem 'rake', '0.9.2' 5 | gemspec -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | gem-this (0.3.7) 5 | 6 | GEM 7 | remote: http://rubygems.org/ 8 | specs: 9 | builder (3.0.0) 10 | cucumber (1.1.4) 11 | builder (>= 2.1.2) 12 | diff-lcs (>= 1.1.2) 13 | gherkin (~> 2.7.1) 14 | json (>= 1.4.6) 15 | term-ansicolor (>= 1.0.6) 16 | diff-lcs (1.1.3) 17 | gherkin (2.7.6) 18 | json (>= 1.4.6) 19 | json (1.6.5) 20 | rake (0.9.2) 21 | rspec (2.8.0) 22 | rspec-core (~> 2.8.0) 23 | rspec-expectations (~> 2.8.0) 24 | rspec-mocks (~> 2.8.0) 25 | rspec-core (2.8.0) 26 | rspec-expectations (2.8.0) 27 | diff-lcs (~> 1.1.2) 28 | rspec-mocks (2.8.0) 29 | shoulda (2.11.3) 30 | term-ansicolor (1.0.7) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | cucumber 37 | gem-this! 38 | rake (= 0.9.2) 39 | rspec 40 | shoulda 41 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "rubygems/package_task" 3 | require "rdoc/task" 4 | 5 | task :default => :test 6 | 7 | require "rake/testtask" 8 | Rake::TestTask.new do |t| 9 | t.libs = [File.expand_path("lib"), "test"] 10 | t.test_files = FileList["test/**/*_test.rb"] 11 | t.verbose = true 12 | end 13 | 14 | # This builds the actual gem. For details of what all these options 15 | # mean, and other ones you can add, check the documentation here: 16 | # 17 | # http://rubygems.org/read/chapter/20 18 | # 19 | spec = Gem::Specification.new do |s| 20 | 21 | # Change these as appropriate 22 | s.name = "gem-this" 23 | s.version = "0.3.7" 24 | s.summary = "Make existing code into a gem, without any fuss." 25 | s.author = "James Adam" 26 | s.email = "james@lazyatom.com" 27 | s.homepage = "http://github.com/lazyatom/gem-this" 28 | 29 | s.has_rdoc = true 30 | # s.extra_rdoc_files = %w(Readme.markdown) 31 | # s.rdoc_options = %w(--main Readme.markdown) 32 | 33 | # Add any extra files to include in the gem 34 | s.files = %w(Rakefile Readme.markdown Rakefile.erb) + Dir.glob("{bin,lib,test}/**/*") 35 | s.executables = FileList["bin/**"].map { |f| File.basename(f) } 36 | s.require_paths = ["bin", "lib"] 37 | 38 | # If you want to depend on other gems, add them here, along with any 39 | # relevant versions 40 | # s.add_dependency("some_other_gem", "~> 0.1.0") 41 | 42 | # If your tests use any gems, include them here 43 | s.add_development_dependency("shoulda") 44 | s.add_development_dependency("rspec") 45 | s.add_development_dependency("cucumber") 46 | 47 | # If you want to publish automatically to rubyforge, you'll may need 48 | # to tweak this, and the publishing task below too. 49 | s.rubyforge_project = "gem-this" 50 | 51 | s.required_rubygems_version = Gem::Requirement.new(">= 1.3") 52 | end 53 | 54 | # This task actually builds the gem. We also regenerate a static 55 | # .gemspec file, which is useful if something (i.e. GitHub) will 56 | # be automatically building a gem for this project. If you're not 57 | # using GitHub, edit as appropriate. 58 | Gem::PackageTask.new(spec) do |pkg| 59 | pkg.gem_spec = spec 60 | end 61 | 62 | desc "Build the gemspec file #{spec.name}.gemspec" 63 | task :gemspec do 64 | file = File.dirname(__FILE__) + "/#{spec.name}.gemspec" 65 | File.open(file, "w") {|f| f << spec.to_ruby } 66 | end 67 | 68 | task :package => :gemspec 69 | 70 | # Generate documentation 71 | RDoc::Task.new do |rd| 72 | rd.main = "Readme.markdown" 73 | rd.rdoc_files.include("Readme.markdown", "lib/**/*.rb") 74 | rd.rdoc_dir = "rdoc" 75 | end 76 | 77 | desc 'Clear out RDoc and generated packages' 78 | task :clean => [:clobber_rdoc, :clobber_package] do 79 | rm "#{spec.name}.gemspec" 80 | end 81 | 82 | desc 'Tag the repository in git with gem version number' 83 | task :tag do 84 | changed_files = `git diff --cached --name-only`.split("\n") + `git diff --name-only`.split("\n") 85 | if changed_files.empty? || changed_files == ['Rakefile'] 86 | Rake::Task["package"].invoke 87 | 88 | if `git tag`.split("\n").include?("v#{spec.version}") 89 | raise "Version #{spec.version} has already been released" 90 | end 91 | `git add #{File.expand_path("../#{spec.name}.gemspec", __FILE__)} Rakefile` 92 | `git commit -m "Released version #{spec.version}"` 93 | `git tag v#{spec.version}` 94 | `git push --tags` 95 | `git push` 96 | else 97 | raise "Repository contains uncommitted changes; either commit or stash." 98 | end 99 | end 100 | 101 | desc "Tag and publish the gem to rubygems.org" 102 | task :publish => :tag do 103 | `gem push pkg/#{spec.name}-#{spec.version}.gem` 104 | end -------------------------------------------------------------------------------- /Rakefile.erb: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "rubygems/package_task" 3 | require "rdoc/task" 4 | 5 | <% if using_rspec? %> 6 | require "rspec" 7 | require "rspec/core/rake_task" 8 | RSpec::Core::RakeTask.new do |t| 9 | t.rspec_opts = %w(--format documentation --colour) 10 | end 11 | <% elsif using_test_unit? %> 12 | require "rake/testtask" 13 | Rake::TestTask.new do |t| 14 | t.libs << "test" 15 | t.test_files = FileList["test/**/*_test.rb"] 16 | t.verbose = true 17 | end 18 | <% end %> 19 | 20 | <% if using_cucumber? %> 21 | require 'cucumber' 22 | require 'cucumber/rake/task' 23 | Cucumber::Rake::Task.new('features') do |t| 24 | t.cucumber_opts = %w{--format pretty} 25 | end 26 | <% end %> 27 | 28 | <% if default_tasks.empty? %> 29 | task :default => :package do 30 | puts "Don't forget to write some tests!" 31 | end 32 | <% else %> 33 | task :default => <%= default_tasks.inspect %> 34 | <% end %> 35 | 36 | # This builds the actual gem. For details of what all these options 37 | # mean, and other ones you can add, check the documentation here: 38 | # 39 | # http://rubygems.org/read/chapter/20 40 | # 41 | spec = Gem::Specification.new do |s| 42 | 43 | # Change these as appropriate 44 | s.name = "<%= name %>" 45 | s.version = "0.1.0" 46 | s.summary = "What this thing does" 47 | s.author = "<%= author_name %>" 48 | s.email = "<%= author_email %>" 49 | s.homepage = "<%= author_url %>" 50 | 51 | s.has_rdoc = true 52 | <% if readme %> 53 | s.extra_rdoc_files = %w(<%= readme %>) 54 | s.rdoc_options = %w(--main <%= readme %>) 55 | 56 | # Add any extra files to include in the gem 57 | <% else %> 58 | # You should probably have a README of some kind. Change the filename 59 | # as appropriate 60 | # s.extra_rdoc_files = %w(README) 61 | # s.rdoc_options = %w(--main README) 62 | 63 | # Add any extra files to include in the gem (like your README) 64 | <% end %> 65 | s.files = %w(<%= files_in_root %>) + Dir.glob(<%= dirs_to_include_glob.inspect %>) 66 | <% if has_executables? %> 67 | s.executables = FileList["bin/**"].map { |f| File.basename(f) } 68 | <% end %> 69 | <% if has_lib_directory? %> 70 | s.require_paths = ["lib"] 71 | <% else %> 72 | 73 | # You need to put your code in a directory which can then be added to 74 | # the $LOAD_PATH by rubygems. Typically this is lib, but you don't seem 75 | # to have that directory. You'll need to set the line below to whatever 76 | # directory your code is in. Rubygems is going to assume lib if you leave 77 | # this blank. 78 | # 79 | # s.require_paths = ["lib"] 80 | <% end %> 81 | 82 | # If you want to depend on other gems, add them here, along with any 83 | # relevant versions 84 | # s.add_dependency("some_other_gem", "~> 0.1.0") 85 | 86 | # If your tests use any gems, include them here 87 | <% if development_dependencies.any? %> 88 | <% development_dependencies.each do |dependency| %> 89 | s.add_development_dependency("<%= dependency %>") 90 | <% end %> 91 | <% else %> 92 | # s.add_development_dependency("mocha") # for example 93 | <% end %> 94 | end 95 | 96 | # This task actually builds the gem. We also regenerate a static 97 | # .gemspec file, which is useful if something (i.e. GitHub) will 98 | # be automatically building a gem for this project. If you're not 99 | # using GitHub, edit as appropriate. 100 | # 101 | # To publish your gem online, install the 'gemcutter' gem; Read more 102 | # about that here: http://gemcutter.org/pages/gem_docs 103 | Gem::PackageTask.new(spec) do |pkg| 104 | pkg.gem_spec = spec 105 | end 106 | 107 | desc "Build the gemspec file #{spec.name}.gemspec" 108 | task :gemspec do 109 | file = File.dirname(__FILE__) + "/#{spec.name}.gemspec" 110 | File.open(file, "w") {|f| f << spec.to_ruby } 111 | end 112 | 113 | # If you don't want to generate the .gemspec file, just remove this line. Reasons 114 | # why you might want to generate a gemspec: 115 | # - using bundler with a git source 116 | # - building the gem without rake (i.e. gem build blah.gemspec) 117 | # - maybe others? 118 | task :package => :gemspec 119 | 120 | # Generate documentation 121 | RDoc::Task.new do |rd| 122 | <% if readme %>rd.main = "<%= readme %>"<% end %> 123 | rd.rdoc_files.include(<%= %{"#{readme}", } if readme %>"lib/**/*.rb") 124 | rd.rdoc_dir = "rdoc" 125 | end 126 | 127 | desc 'Clear out RDoc and generated packages' 128 | task :clean => [:clobber_rdoc, :clobber_package] do 129 | rm "#{spec.name}.gemspec" 130 | end 131 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | Most of the time, I don't set out to write a gem. 2 | ================================================= 3 | 4 | Perhaps I'm not audacious enough to consider every piece of code I write to be worthy of use by other developers. Perhaps. 5 | 6 | But, more likely than that, it's just that I don't think that far ahead. I'm more interested in playing with the idea at the start, rather than thinking about how other people are going to remember - nay, worship my name, years in the future. 7 | 8 | Anyway, sometimes - after a bit of tinkering and pondering - I do end up with a library that I consider gem-worthy and fit for consumption. But every time I look at the existing tools to build gems, I'm paralysed by the comprehensive nature of their function. 9 | 10 | Often, they'll try to generate a particular directory structure, with test stubs and a website, which is fine in principle, but I've already got my code the way I want it; I'm not generating a new project. 11 | 12 | Even worse, sometimes they'll add themselves as dependencies for your gem! Yuck. 13 | 14 | I am not interested in that. I just want the simplest thing that could possibly work, to build my gem and make it available to the world. I will add any bells and whistles that I want later. 15 | 16 | And so: 17 | 18 | Gem This 19 | ======== 20 | 21 | The `gem-this` command expects to be run in the directory of your existing code: 22 | 23 | $ cd my-project 24 | $ mate lib/sweet_code.rb 25 | ... hacking ... 26 | $ gem-this 27 | 28 | New in 0.2.0: we also register a gem command, so you can just type: 29 | 30 | $ gem this 31 | 32 | When you run `gem-this`, it will create a new `Rakefile` in your project directory. If you already had a `Rakefile`, it will append to the end of it, so your existing tasks are safe. 33 | 34 | $ rake -T 35 | rake clean # Clear out RDoc and generated packages 36 | rake clobber_package # Remove package products 37 | rake clobber_rdoc # Remove rdoc products 38 | rake gem # Build the gem file gem-this-0.1.0.gem 39 | rake package # Build all the packages 40 | rake rdoc # Build the rdoc HTML Files 41 | rake repackage # Force a rebuild of the package files 42 | rake rerdoc # Force a rebuild of the RDOC files 43 | 44 | 45 | The simplest thing to do next is simply run `rake package`: 46 | 47 | mkdir -p pkg 48 | Successfully built RubyGem 49 | Name: my-project 50 | Version: 0.1.0 51 | File: my-project-0.1.0.gem 52 | mv my-project-0.1.0.gem pkg/my-project-0.1.0.gem 53 | 54 | As you can tell, it's used the current directory name as the name of the gem. But, you can change any of that. Just open your `Rakefile` and edit the details. 55 | 56 | It tries to be a little bit clever, detecting the presence of a few directories (like `bin`, `test` and `spec`) and behave accordingly. If you're already using git, it will ignore the `rdoc` and `pkg` directories for you. 57 | 58 | What next? 59 | ---------- 60 | 61 | For the most part, `gem-this` simply sets up a good base for you to customise yourself, with as little fuss or overhead as possible. It's up to you if you want make it more sophisticated, but I trust you. 62 | 63 | Don't worry; you'll be fine. 64 | 65 | 66 | Advanced usage! 67 | --------------- 68 | 69 | If you have developed some custom tasks that you find yourself using again and again, and want them to be made available for any new gems you create, now you can! Just drop your tasks into `~/.gem-this`, and they will be automatically copied into any Rakefiles that gem-this generates. 70 | 71 | For example, this is what is in *my* `.gem-this` file: 72 | 73 | desc 'Tag the repository in git with gem version number' 74 | task :tag => [:gemspec, :package] do 75 | if `git diff --cached`.empty? 76 | if `git tag`.split("\n").include?("v#{spec.version}") 77 | raise "Version #{spec.version} has already been released" 78 | end 79 | `git add #{File.expand_path("../#{spec.name}.gemspec", __FILE__)}` 80 | `git commit -m "Released version #{spec.version}"` 81 | `git tag v#{spec.version}` 82 | `git push --tags` 83 | `git push` 84 | else 85 | raise "Unstaged changes still waiting to be committed" 86 | end 87 | end 88 | 89 | desc "Tag and publish the gem to rubygems.org" 90 | task :publish => :tag do 91 | `gem push pkg/#{spec.name}-#{spec.version}.gem` 92 | end 93 | 94 | Your workflow is in your hands. Enjoy! 95 | 96 | 97 | Thanks 98 | ====== 99 | 100 | Inspiration, and sometimes code chunks, were taking from lots of the existing gem tools, but particularly 'gemify' (wish I could've used that name!) and 'simple-gem'. 101 | 102 | 103 | MIT License 104 | =========== 105 | 106 | (c) James Adam 2009, or whatever 107 | 108 | Permission is hereby granted, free of charge, to any person obtaining a copy 109 | of this software and associated documentation files (the "Software"), to deal 110 | in the Software without restriction, including without limitation the rights 111 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 112 | copies of the Software, and to permit persons to whom the Software is 113 | furnished to do so, subject to the following conditions: 114 | 115 | The above copyright notice and this permission notice shall be included in 116 | all copies or substantial portions of the Software. 117 | 118 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 119 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 120 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 121 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 122 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 123 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 124 | THE SOFTWARE. -------------------------------------------------------------------------------- /bin/gem-this: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'gem_this' 4 | 5 | args = ARGV.dup 6 | 7 | if args.first =~ /-?-h/ 8 | puts GemThis::SUMMARY 9 | puts "Usage: #{__FILE__} [-d -h] [gem name]" 10 | puts "If a gem name is not given, the name of the current directory will be used as the gem" 11 | puts "-h help, prints out this message." 12 | puts "-d #{GemThis::DEBUG_MESSAGE}" 13 | exit 14 | end 15 | 16 | debug = args.delete("-d") 17 | 18 | GemThis.new(args.first || File.basename(Dir.pwd), :debug => debug).create_rakefile 19 | 20 | exit -------------------------------------------------------------------------------- /gem-this.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | 3 | Gem::Specification.new do |s| 4 | s.name = %q{gem-this} 5 | s.version = "0.3.7" 6 | 7 | s.required_rubygems_version = Gem::Requirement.new(">= 1.3") if s.respond_to? :required_rubygems_version= 8 | s.authors = ["James Adam"] 9 | s.date = %q{2011-06-20} 10 | s.default_executable = %q{gem-this} 11 | s.email = %q{james@lazyatom.com} 12 | s.executables = ["gem-this"] 13 | s.files = ["Rakefile", "Readme.markdown", "Rakefile.erb", "bin/gem-this", "lib/gem_this.rb", "lib/rubygems_plugin.rb", "test/gem_this_test.rb", "test/test_helper.rb"] 14 | s.homepage = %q{http://github.com/lazyatom/gem-this} 15 | s.require_paths = ["bin", "lib"] 16 | s.rubyforge_project = %q{gem-this} 17 | s.rubygems_version = %q{1.4.1} 18 | s.summary = %q{Make existing code into a gem, without any fuss.} 19 | 20 | if s.respond_to? :specification_version then 21 | s.specification_version = 3 22 | 23 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then 24 | s.add_development_dependency(%q, [">= 0"]) 25 | s.add_development_dependency(%q, [">= 0"]) 26 | s.add_development_dependency(%q, [">= 0"]) 27 | else 28 | s.add_dependency(%q, [">= 0"]) 29 | s.add_dependency(%q, [">= 0"]) 30 | s.add_dependency(%q, [">= 0"]) 31 | end 32 | else 33 | s.add_dependency(%q, [">= 0"]) 34 | s.add_dependency(%q, [">= 0"]) 35 | s.add_dependency(%q, [">= 0"]) 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/gem_this.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | require 'erb' 3 | require 'etc' 4 | 5 | class GemThis 6 | SUMMARY = "Creates a Rakefile suitable for turning the current project into a gem." 7 | DEBUG_MESSAGE = "debug, only prints out the generated Rakefile." 8 | 9 | class << self 10 | attr_accessor :custom_task_file 11 | end 12 | self.custom_task_file = ENV['HOME'] && File.expand_path("~/.gem-this") 13 | 14 | attr_reader :name, :debug 15 | 16 | def initialize(name, options={}) 17 | @name = name 18 | options = {:default => false, :silent => false}.update(options) 19 | @debug = options[:debug] 20 | @silent = options[:silent] 21 | end 22 | 23 | def create_rakefile 24 | template = ERB.new File.read(File.join(File.dirname(__FILE__), '..', 'Rakefile.erb')), nil, '<>' 25 | rakefile = template.result(binding) 26 | if self.class.custom_task_file && File.exist?(self.class.custom_task_file) 27 | rakefile += "\n" + File.read(self.class.custom_task_file) 28 | end 29 | 30 | if debug 31 | puts rakefile 32 | else 33 | if File.exist?('Rakefile') 34 | log "Appended to existing Rakefile" 35 | File.open('Rakefile', 'a') { |f| 2.times { f.puts }; f.write rakefile } 36 | else 37 | log "Writing new Rakefile" 38 | File.open('Rakefile', 'w') { |f| f.write rakefile } 39 | end 40 | add_to_gitignore if using_git? 41 | end 42 | unless has_lib_directory? 43 | log "You don't seem to have a lib directory - please edit the Rakefile to set where your code is." 44 | false 45 | end 46 | end 47 | 48 | private 49 | 50 | def log(message) 51 | puts(message) unless @silent 52 | end 53 | 54 | def author_name 55 | Etc.getpwnam(ENV['USER']).gecos rescue ENV['USER'] # for Windows 56 | end 57 | 58 | def author_email 59 | email = '' 60 | 61 | # even if using git, author may not have specified email address 62 | if using_git? 63 | email = %x{git config --get user.email}.strip 64 | end 65 | 66 | email == '' ? "youremail@example.com" : email 67 | end 68 | 69 | def author_url 70 | "http://yoursite.example.com" 71 | end 72 | 73 | def using_rspec? 74 | File.directory?('spec') 75 | end 76 | 77 | def using_cucumber? 78 | File.directory?('features') 79 | end 80 | 81 | def using_test_unit? 82 | File.directory?('test') 83 | end 84 | 85 | def has_executables? 86 | File.directory?('bin') 87 | end 88 | 89 | def has_lib_directory? 90 | File.directory?("lib") 91 | end 92 | 93 | def dirs_to_include_glob 94 | dirs = %w(bin test spec lib).select { |d| File.directory?(d) } 95 | glob_parts = ["**", "*"] 96 | if dirs.any? 97 | glob_parts.unshift("{"+dirs.join(",")+"}") 98 | end 99 | File.join(*glob_parts) 100 | end 101 | 102 | def readme 103 | Dir['*'].find { |f| f =~ /readme/i } 104 | end 105 | 106 | def files_in_root 107 | Dir['*'].reject { |f| File.directory?(f) }.join(" ") 108 | end 109 | 110 | def using_git? 111 | File.exist?(".git") 112 | end 113 | 114 | def default_tasks 115 | tasks = [] 116 | tasks << "test" if using_test_unit? 117 | tasks << "spec" if using_rspec? 118 | tasks << "features" if using_cucumber? 119 | tasks 120 | end 121 | 122 | def development_dependencies 123 | deps = [] 124 | deps << "rspec" if using_rspec? 125 | deps << "cucumber" if using_cucumber? 126 | deps 127 | end 128 | 129 | def add_to_gitignore 130 | return unless File.exist?(".gitignore") 131 | ignores = File.readlines(".gitignore") 132 | ignores += ["pkg", "rdoc"] 133 | File.open(".gitignore", "w") { |f| f.write ignores.map { |l| l.strip }.uniq.join("\n") } 134 | end 135 | end 136 | -------------------------------------------------------------------------------- /lib/rubygems_plugin.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems/command_manager' 2 | require 'rubygems/command' 3 | require 'gem_this' 4 | 5 | class Gem::Commands::ThisCommand < Gem::Command 6 | def initialize 7 | super 'this', GemThis::SUMMARY, :debug => false 8 | add_option('-d', '--debug', GemThis::DEBUG_MESSAGE) do |debug, options| 9 | options[:debug] = debug 10 | end 11 | end 12 | 13 | def summary 14 | GemThis::SUMMARY 15 | end 16 | 17 | def execute 18 | GemThis.new(options[:args].first || File.basename(Dir.pwd), options).create_rakefile 19 | end 20 | end 21 | 22 | Gem::CommandManager.instance.register_command :this 23 | -------------------------------------------------------------------------------- /test/gem_this_test.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'test_helper') 2 | 3 | class GemThisTest < Test::Unit::TestCase 4 | context "When building a gem" do 5 | setup do 6 | build_gem do 7 | touch "README" 8 | touch "lib/thing.rb" 9 | touch "lib/thing/some/aspect/many/levels/deep.rb" 10 | end 11 | end 12 | 13 | should "contain lib files" do 14 | assert_gem_contains "lib/thing.rb" 15 | end 16 | 17 | should "contain deeply nested files" do 18 | assert_gem_contains "lib/thing/some/aspect/many/levels/deep.rb" 19 | end 20 | 21 | should "include the README" do 22 | assert_gem_contains "README" 23 | end 24 | 25 | should "put lib in require path" do 26 | assert_gem_spec :require_paths, ["lib"] 27 | end 28 | end 29 | 30 | context "When building a gem with tests" do 31 | setup do 32 | build_gem do 33 | touch "lib/thing.rb" 34 | touch "test/thing_test.rb" 35 | end 36 | end 37 | 38 | should "contain test files" do 39 | assert_gem_contains "test/thing_test.rb" 40 | end 41 | 42 | should "create a rake task for running tests" do 43 | assert_rake_task :test 44 | end 45 | 46 | end 47 | 48 | context "When building a gem with specs" do 49 | setup do 50 | build_gem do 51 | touch "lib/thing.rb" 52 | touch "spec/my_spec.rb" 53 | end 54 | end 55 | 56 | should "contain spec files" do 57 | assert_gem_contains "spec/my_spec.rb" 58 | end 59 | 60 | should "create a rake task for running specs" do 61 | assert_rake_task :spec 62 | end 63 | end 64 | 65 | context "When building a gem with features" do 66 | setup do 67 | build_gem do 68 | touch "lib/thing.rb" 69 | touch "features/gem-this.feature" 70 | end 71 | end 72 | 73 | should "create a rake task for running features" do 74 | assert_rake_task :features 75 | end 76 | 77 | should "add a features task to the default rake task dependencies" do 78 | assert_default_rake_task_dependencies_contains :features 79 | end 80 | end 81 | 82 | context "When building a gem without a lib directory" do 83 | setup do 84 | create_gem do 85 | touch "code/my_code_is_in_here_for_some_reason.rb" 86 | end 87 | end 88 | 89 | should "not build the gem" do 90 | assert_doesnt_hang do 91 | assert !@gem.build # the real test is whether or not this returns at all. 92 | end 93 | end 94 | end 95 | 96 | context "When the user has a .gem-this file" do 97 | setup do 98 | create_gem_this_file %{ 99 | desc "Something for my gems" 100 | task :custom_task do 101 | end 102 | } 103 | build_gem do 104 | touch "README" 105 | touch "lib/thing.rb" 106 | end 107 | end 108 | 109 | should "include custom tasks in the Rakefile" do 110 | assert_rake_task :custom_task 111 | end 112 | end 113 | 114 | context "When the user has no .gem-this file specified" do 115 | setup do 116 | GemThis.custom_task_file = nil 117 | end 118 | 119 | should "not raise exception when building gem" do 120 | assert_nothing_raised { build_gem {} } 121 | end 122 | end 123 | 124 | context "When the specified .gem-this file does not exist" do 125 | setup do 126 | GemThis.custom_task_file = "hopefully/this/file/doesnt/exist" 127 | end 128 | 129 | should "not raise exception when building gem" do 130 | assert_nothing_raised { build_gem {} } 131 | end 132 | end 133 | end 134 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'shoulda' 4 | require 'fileutils' 5 | require 'tempfile' 6 | require 'yaml' 7 | require 'timeout' 8 | require 'rake' 9 | require 'gem_this' 10 | 11 | class GemBuilder 12 | attr_reader :gem_path 13 | 14 | def initialize(name, &block) 15 | @name = name 16 | @gem_path = temporary_gem_name 17 | FileUtils.mkdir_p(@gem_path) 18 | FileUtils.cd(@gem_path) do 19 | instance_eval &block 20 | end 21 | end 22 | 23 | def touch(name) 24 | FileUtils.mkdir_p(File.dirname(name)) 25 | FileUtils.touch(name) 26 | end 27 | 28 | def path_to_gem 29 | File.join(@gem_path, "pkg", @name + "-0.1.0.gem") 30 | end 31 | 32 | def build 33 | result = nil 34 | FileUtils.cd(@gem_path) do 35 | result = ::GemThis.new(@name, :debug => false, :silent => true).create_rakefile 36 | `rake package 2>&1` 37 | end 38 | result 39 | end 40 | 41 | private 42 | 43 | def temporary_gem_name 44 | t = Tempfile.new('gem-this') 45 | gem_name = t.path 46 | t.unlink 47 | File.join(gem_name, @name) 48 | end 49 | end 50 | 51 | class Test::Unit::TestCase 52 | def assert_gem_contains(*paths) 53 | paths.each do |path| 54 | assert gem_spec.files.include?(path), "gem should include #{path}" 55 | end 56 | end 57 | 58 | def assert_gem_spec(part, value, message = nil) 59 | assert_equal value, gem_spec.send(part), message 60 | end 61 | 62 | def assert_rake_task(task) 63 | tasks = in_gem { `rake -T`.split("\n").map { |line| line.split[1] } } 64 | assert tasks.include?(task.to_s), "#{tasks.inspect} did not include #{task}" 65 | end 66 | 67 | def assert_default_rake_task_dependencies_contains(task) 68 | in_gem { 69 | load 'RakeFile' 70 | assert prerequisites_for('default').include?(task.to_s), prerequisites_for('default').inspect 71 | } 72 | end 73 | 74 | def assert_doesnt_hang(duration=5, message=nil, &block) 75 | assert_nothing_raised("should return within #{duration} seconds") do 76 | Timeout::timeout(duration, &block) 77 | end 78 | end 79 | 80 | def in_gem(&block) 81 | result = nil 82 | FileUtils.cd(@gem.gem_path) do 83 | result = yield 84 | end 85 | result 86 | end 87 | 88 | def create_gem(name="test_gem", &block) 89 | @gem = GemBuilder.new(name, &block) 90 | end 91 | 92 | def build_gem(name="test_gem", &block) 93 | create_gem(name, &block).build 94 | end 95 | 96 | def gem_spec 97 | in_gem { YAML.load(`gem specification #{@gem.path_to_gem}`) } 98 | end 99 | 100 | def create_gem_this_file(content) 101 | t = Tempfile.new('gem-this-task-file') 102 | t.puts content 103 | t.close 104 | GemThis.custom_task_file = t.path 105 | end 106 | 107 | private 108 | def find_task(task_name) 109 | @tasks ||= Rake.application.tasks 110 | @tasks.find {|task| task.name == task_name} 111 | end 112 | 113 | def prerequisites_for(task_name) 114 | find_task(task_name).prerequisites 115 | end 116 | end 117 | --------------------------------------------------------------------------------