Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

0.1.2 - garlic now works as a command line tool

  • Loading branch information...
commit ea4d8e6512d2fc40adb8e64057553e8f20586c59 1 parent 09af25f
Ian White authored
2  .gitignore
View
@@ -2,4 +2,4 @@
work/*
repos/*
*.tmproj
-garlic-*.gem
+garlic-*.gem
5 CHANGELOG
View
@@ -0,0 +1,5 @@
+* 0.1.2
+ * making use of garlic as a gem
+ * changed paths, repos are now stored in ~/.garlic/repos (and this shared across multiple garlic sessions), work is in .garlic_work
+
+* 0.1.1 freelancing-god added gem goodness
1  README
View
104 README.rdoc → README.textile
View
@@ -1,30 +1,39 @@
-= garlic: lightweight continuous integration for rails using git
+h1. garlic: lightweight continuous integration for rails using git
This is not a CI server, use cruisecontrol.rb for that. This is a simple set
of rake tasks that let you specify a bunch of rails builds to run against, and
dependencies to install.
-It works by cloning git repos for all your dependencies (so they all must be
-on git), and then using git to checkout various tags and branches to build
-your app against.
+This is aimed at testing plugins (or apps) against multiple versions of rails,
+and allows specifying other plugin dependencies (and their versions and any
+setup requried).
+
+If you want to run your specs (or whatever) against different versions of gems
+that you have installed, then check out "ginger":http://github.com/freelancing-god/ginger by "Pat Allen":http://github.com/freelancing-god
+Garlic works by cloning git repos for all your dependencies (so they all must be
+git repos), and then using git to checkout various tags and branches to build
+your app against.
-== Example
+h2. Example
-To see garlic in action, download resources_controller, a rails plugin that uses
+To see garlic in action, download response_for, a rails plugin that uses
garlic for CI.
- git clone git://github.com/ianwhite/resources_controller
- cd resources_controller
- cp garlic_example.rb garlic.rb # you might like to look at this file and edit\
- # it if you have local clones of rails and rspec
- rake get_garlic
+ git clone git://github.com/ianwhite/response_for
+
+Install the garlic gem
+
+ sudo gem install ianwhite-garlic --source=http://gems.github.com
+
+run garlic
+
rake garlic:all
This will clone all the required git repos (done only once), set up the target
railses (done once), then run the targets.
-=== Once you've made some changes
+h3. Once you've made some changes
You can prepare and run all the targets again (without fetching remote repos) by doing
@@ -33,7 +42,7 @@ You can prepare and run all the targets again (without fetching remote repos) by
This will prepare all the targets, using the current HEAD of the repos, and run the
CI task again.
-=== Specifying particular targets
+h3. Specifying particular targets
If you just want to run against a particular target or targets, you can use the TARGET or TARGETS
env var.
@@ -41,7 +50,7 @@ env var.
rake garlic TARGET=edge
rake garlic TARGETS=2.0.1,2.0.2
-== Example workflow
+h2. Example workflow
Let's say I'm patching resources_controller.
@@ -64,7 +73,7 @@ Now, I make some changes
rake garlic
# ... everything is fine, so I can merge these into master, or send a pull request
-=== How do I run the specs on uncommitted code?
+h3. How do I run the specs on uncommitted code?
The best way is to make the changes in one of the 'work' targets. For example:
@@ -82,37 +91,28 @@ Now you can push these changes back upstream to your local 'master' repo
Then cd back up there, and run rake garlic to verify your changes against the other
targets. If these all pass, you can push, or send a pull request
-== How to add garlic to your repo (example: rails plugin)
-
-==== 1. add the get_garlic task to your main Rakefile
+h2.How to add garlic to your repo (example: rails plugin)
- # load up garlic if it's here
- if File.directory?(File.join(File.dirname(__FILE__), 'garlic'))
- require File.join(File.dirname(__FILE__), 'garlic/lib/garlic_tasks')
- require File.join(File.dirname(__FILE__), 'garlic')
- end
+h4. 1. require the garlic tasks into your own Rakefile
- desc "clone the garlic repo (for running ci tasks)"
- task :get_garlic do
- sh "git clone git://github.com/ianwhite/garlic.git garlic"
+ # rescue this just in case the plugin user doesn't have garlic
+ begin
+ require 'garlic'
+ rescue LoadError
end
-==== 2. add a garlic.rb or garlic_example.rb
-
-I tend to use garlic_example.rb, and others can copy this to garlic.rb, which can be modified and ignored by git.
+h4. 2. add a garlic.rb
An example garlic.rb:
garlic do
- # default paths are 'garlic/work', and 'garlic/repos'
- work_path "my/work"
- repo_path "my/repos"
-
- repo 'rails', :url => 'git://github.com/rails/rails'#, :local => "~/dev/vendor/rails"
- repo 'rspec', :url => 'git://github.com/dchelimsky/rspec'#, :local => "~/dev/vendor/rspec"
- repo 'rspec-rails', :url => 'git://github.com/dchelimsky/rspec-rails'#, :local => "~/dev/vendor/rspec-rails"
+ # repos
+ repo 'rails', :url => 'git://github.com/rails/rails'
+ repo 'rspec', :url => 'git://github.com/dchelimsky/rspec'
+ repo 'rspec-rails', :url => 'git://github.com/dchelimsky/rspec-rails'
repo 'resources_controller', :path => '.'
+ # targets
target 'edge'
target '2.0-stable', :branch => 'origin/2-0-stable'
target '2.0.2', :tag => 'v2.0.2'
@@ -121,23 +121,26 @@ An example garlic.rb:
prepare do
plugin 'resources_controller', :clone => true
plugin 'rspec'
- plugin('rspec-rails') { sh "script/generate rspec -f" }
+ plugin 'rspec-rails' do
+ sh "script/generate rspec -f"
+ end
end
run do
- cd("vendor/plugins/resources_controller") { sh "rake spec:rcov:verify" }
+ cd "vendor/plugins/resources_controller"
+ sh "rake spec:rcov:verify"
+ end
end
end
end
-==== 3. ignore the garlic artefacts
+h4. 3. ignore the garlic artefacts
-Example .gitignore (for the case where you have garlic_example.rb)
+Example .gitignore
- garlic.rb
- garlic
+ .garlic_work
-==== 4. Run it
+h4. 4. Run it
rake garlic:all
@@ -149,20 +152,9 @@ To make sure you're running against the latest repos:
rake garlic:update_repos
-== Notes
-
-- To configure the dependencies and targets, take a look at the top level Rakefile
- * resources_controller doesn't work with 1.2.3, to test this try adding
- target '1.2.3', :tag => 'v1.2.3'
- in garlic.rb, then running
- rake garlic:prepare
- rake garlic:run
- and you'll see that it fails against 1.2.3
-
-
-== First release
+h2. Lend a hand
-This is the first release, so there is plenty of scope for changes and improvement
+This is an early release, so there is plenty of scope for changes and improvement
If you want to lend a hand, get in touch.
(c) Ian White 2008 - ian.w.white@gmail.com
28 Rakefile
View
@@ -9,21 +9,21 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
require 'garlic'
spec = Gem::Specification.new do |s|
- s.name = "garlic"
- s.version = Garlic::Version::String
- s.summary = "Lightweight set of rake tasks to help with CI."
- s.description = "Lightweight set of rake tasks to help with CI."
- s.author = "Ian White"
- s.email = "ian.w.white@gmail.com"
- s.homepage = "http://github.com/ianwhite/garlic/tree"
- s.has_rdoc = false
- s.test_files = FileList["spec/**/*_spec.rb"]
- s.files = FileList[
- "lib/**/*.rb",
- "MIT-LICENSE",
- "README.rdoc",
- "TODO"
+ s.name = "garlic"
+ s.version = Garlic::Version::String
+ s.summary = "Lightweight set of rake tasks to help with CI."
+ s.description = "Lightweight set of rake tasks to help with CI."
+ s.author = "Ian White"
+ s.email = "ian.w.white@gmail.com"
+ s.homepage = "http://github.com/ianwhite/garlic/tree"
+ s.has_rdoc = true
+ s.rdoc_options << "--title" << "Garlic" << "--line-numbers"
+ s.test_files = FileList["spec/**/*_spec.rb"]
+ s.files = FileList[
+ "lib/**/*.rb", "templates/*.rb",
+ "MIT-LICENSE", "README.textile", "TODO", "CHANGELOG"
]
+ s.executables = ["garlic"]
end
Rake::GemPackageTask.new(spec) do |p|
1  TODO
View
@@ -1,2 +1 @@
-* Make garlic a gem - and remove the need to clone the garlic repo each time
* rewrite using grit? (research: is grit the defacto standard for ruby controlling git?)
74 bin/garlic
View
@@ -0,0 +1,74 @@
+#!/usr/bin/env ruby
+
+require 'getoptlong'
+require 'rubygems'
+require 'rake'
+require 'garlic'
+
+include Garlic
+
+USAGE = "USAGE: garlic [options] [command] (try garlic --help)"
+
+HELP = <<-end_doc
+garlic - run a command in different versions of rails
+
+USAGE: garlic [options] [command]
+
+COMMANDS:
+#{Garlic::Runner.commands_with_description.map{|method, desc| " %-17s %s" % [method, desc]}.join("\n")}
+
+ The default command is "default"
+
+OPTIONS:
+ --help -h You're reading it
+ --verbose -v Show work
+ --config CONFIG -c Specify a different location of garlic config
+ --targets TARGETS -t Specify subset of targets, e.g. edge,2.1.0 (default all)
+ --backtrace Show ruby bakctrace on error
+
+You can generate a sample garlic.rb with
+ garlic generate [TEMPLATE [PLUGIN_NAME]] (Available templates: #{available_templates.join(', ')})
+
+end_doc
+
+GetoptLong.new(
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
+ ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
+ ['--targets', '-t', GetoptLong::REQUIRED_ARGUMENT],
+ ['--config', '-c', GetoptLong::REQUIRED_ARGUMENT],
+ ['--backtrace', GetoptLong::NO_ARGUMENT]
+ ).each do |opt, arg|
+ case opt
+ when '--help' then STDOUT << HELP; exit true
+ when '--verbose' then @verbose = true
+ when '--config' then @config_file = arg
+ when '--targets' then @run_targets = arg
+ when '--backtrace' then @backtrace = true
+ end
+end
+
+begin
+ # generate a config file
+ if ARGV.first == 'generate'
+ generate_config(*ARGV[1..-1])
+
+ # run a garlic command
+ else
+ raise "Unknown command: #{ARGV.first}" unless ARGV.empty? || Garlic::Runner.commands.include?(ARGV.first)
+
+ # configure the garlic runner
+ garlic @config_file do
+ verbose @verbose
+ run_targets @run_targets
+ end
+
+ # run the command
+ ARGV << 'default' if ARGV.empty?
+ garlic.send *ARGV
+ end
+
+rescue Exception => e
+ STDERR << "\n#{USAGE}\n\nError: #{e.message}\n\n"
+ raise e if @backtrace
+ exit false
+end
12 garlic.gemspec
View
@@ -1,18 +1,16 @@
-# -*- encoding: utf-8 -*-
-
Gem::Specification.new do |s|
s.name = %q{garlic}
- s.version = "0.1.1"
+ s.version = "0.1.2"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Ian White"]
- s.date = %q{2008-10-11}
+ s.date = %q{2008-10-30}
s.description = %q{Lightweight set of rake tasks to help with CI.}
s.email = %q{ian.w.white@gmail.com}
- s.files = ["lib/garlic/configurator.rb", "lib/garlic/garlic.rb", "lib/garlic/repo.rb", "lib/garlic/target.rb", "lib/garlic/tasks.rb", "lib/garlic.rb", "MIT-LICENSE", "README.rdoc", "TODO", "spec/garlic/repo_spec.rb"]
+ s.files = ["lib/garlic/configurator.rb", "lib/garlic/repo.rb", "lib/garlic/session.rb", "lib/garlic/target.rb", "lib/garlic/tasks.rb", "lib/garlic.rb", "MIT-LICENSE", "README.textile", "TODO", "CHANGELOG", "spec/garlic/repo_spec.rb"]
s.homepage = %q{http://github.com/ianwhite/garlic/tree}
s.require_paths = ["lib"]
- s.rubygems_version = %q{1.3.0}
+ s.rubygems_version = %q{1.2.0}
s.summary = %q{Lightweight set of rake tasks to help with CI.}
s.test_files = ["spec/garlic/repo_spec.rb"]
@@ -20,7 +18,7 @@ Gem::Specification.new do |s|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ if current_version >= 3 then
else
end
else
27 lib/garlic.rb
View
@@ -1,14 +1,37 @@
-require "garlic/garlic"
+require "garlic/runner"
require "garlic/configurator"
require "garlic/repo"
require "garlic/target"
+require "garlic/generator"
+require "garlic/shell"
module Garlic
+ include Generator
+
module Version
Major = 0
Minor = 1
- Tiny = 1
+ Tiny = 2
String = [Major, Minor, Tiny].join('.')
end
+
+ # return the current garlic runner
+ def garlic(config = nil, &block)
+ @garlic ||= Garlic::Runner.new(self)
+ load_config(config)
+ @garlic.configure(&block) if block_given?
+ @garlic
+ end
+
+ # load config from
+ def load_config(config = nil)
+ unless @garlic_config_file
+ @garlic_config_file = config || "garlic.rb"
+ unless File.exists?(@garlic_config_file)
+ raise "garlic requries a configuration file (can't find #{@garlic_config_file}), try:\n garlic generate [#{available_templates.join('|')}] > garlic.rb"
+ end
+ eval File.read(@garlic_config_file)
+ end
+ end
end
22 lib/garlic/configurator.rb
View
@@ -1,4 +1,5 @@
module Garlic
+ # Configures the garlic runner in a decalarative style
class Configurator
attr_reader :garlic
@@ -7,14 +8,6 @@ def initialize(garlic, &block)
instance_eval(&block) if block_given?
end
- def work_path(path)
- garlic.work_path = path
- end
-
- def repo_path(path)
- garlic.repo_path = path
- end
-
def repo(name, options = {})
options[:name] = name
options[:path] ||= "#{garlic.repo_path}/#{name}"
@@ -33,6 +26,19 @@ def target(name, options = {}, &block)
garlic.targets << Target.new(garlic, options)
end
+ def respond_to?(method)
+ super || garlic.respond_to?("#{method}=")
+ end
+
+ protected
+ def method_missing(attribute, value)
+ if garlic.respond_to?("#{attribute}=")
+ garlic.send("#{attribute}=", value)
+ else
+ super
+ end
+ end
+
class BlockParser
attr_reader :options, :whitelist
99 lib/garlic/garlic.rb
View
@@ -1,99 +0,0 @@
-module Garlic
- class Garlic
- attr_reader :actor
- attr_accessor :repos, :targets, :all_targets, :repo_path, :work_path
-
- def initialize(actor = nil, &block)
- @runners = {}
- @actor = actor
- self.repos = []
- self.targets = []
- self.all_targets = {}
- self.work_path = "garlic/work"
- self.repo_path = "garlic/repos"
- configure(&block) if block_given?
- end
-
- def method_missing(method, *args, &block)
- actor ? actor.send(method, *args, &block) : super
- end
-
- def respond_to?(method)
- super(method) || (actor && actor.respond_to?(method))
- end
-
- def configure(&block)
- Configurator.new(self, &block)
- end
-
- def repo(name)
- repos.detect {|r| r.name == name.to_s} or raise "Can't find repo: #{name}"
- end
-
- def install_repos
- repos.each {|repo| repo.install}
- end
-
- def update_repos
- repos.each {|repo| repo.update}
- end
-
- def check_repos
- errors = []
- repos.each do |repo|
- begin
- repo.check
- rescue Exception => e
- errors << "- #{e.message}"
- end
- end
- errors.length == 0 or raise "\n#{errors.join("\n")}\n\nPlease remove these repos and run rake garlic:install_repos\n"
- end
-
- def reset_repos
- repos.each {|repo| repo.reset}
- end
-
- def clean
- rm_rf work_path
- end
-
- def prepare
- determine_targets.each {|target| target.prepare }
- ensure
- repo('rails').checkout('master') # we get rails back to master if something goes wrong
- end
-
- def run
- these_targets = determine_targets
- target_names, failed_names = these_targets.collect {|t| t.name}, []
-
- puts "\n#{'='*78}\nTargets: #{target_names.join(', ')}\n#{'='*78}\n"
- these_targets.each do |target|
- puts "\n#{'-'*78}\nTarget: #{target.name} (commit #{target.rails_sha[0..6]}, run at #{Time.now})\n#{'-'*78}\n"
- begin
- target.run
- puts "\ntarget: #{target.name} PASS"
- rescue
- puts "\ntarget: #{target.name} FAIL"
- failed_names << target.name
- end
- end
- puts "\n#{'='*78}\n"
- failed_names.length > 0 and raise "The following targets passed: #{(target_names - failed_names).join(', ')}.\n\nThe following targets FAILED: #{failed_names.join(', ')}.\n\n"
- puts "All specified targets passed: #{target_names.join(', ')}.\n\n"
- end
-
-private
- def determine_targets
- if names =ENV['TARGETS'] || ENV['TARGET']
- names = [*names.split(',')]
- these_targets = targets.select{|t| names.include?(t.name)}
- else
- these_targets = targets
- end
- these_targets.length == 0 and raise "\n\nNo targets found, use TARGET=name, or TARGETS=name1,name2"
- these_targets
- end
- end
-end
27 lib/garlic/generator.rb
View
@@ -0,0 +1,27 @@
+module Garlic
+ # generate a garlic config file
+ module Generator
+ include FileUtils
+
+ TEMPLATES_PATH = File.expand_path("~/.garlic/templates")
+
+ def generate_config(template = 'default', plugin = nil)
+ raise "unknown template: #{template}.\nUse one of #{available_templates.join(', ')} or create your own in #{TEMPLATES_PATH}" unless available_templates.include?(template)
+ plugin ||= File.basename(File.expand_path('.'))
+ puts eval("<<-EOD\n" + File.read(File.join(TEMPLATES_PATH, "#{template}.rb")) + "\nEOD")
+ end
+
+ def available_templates
+ copy_templates unless File.exists?(TEMPLATES_PATH)
+ Dir[File.join(TEMPLATES_PATH, '*')].map {|f| File.basename(f.sub(/.rb$/,'')) }
+ end
+
+ protected
+ def copy_templates
+ mkdir_p TEMPLATES_PATH
+ Dir[File.join(File.dirname(__FILE__), '../../templates/*.rb')].each do |file|
+ cp file, File.join(TEMPLATES_PATH, File.basename(file))
+ end
+ end
+ end
+end
145 lib/garlic/runner.rb
View
@@ -0,0 +1,145 @@
+module Garlic
+ # this class runs the top level garlic commands
+ class Runner
+ attr_reader :actor, :run_targets
+ attr_accessor :repos, :targets, :all_targets, :repo_path, :work_path, :verbose
+
+ def initialize(actor = nil, &block)
+ @actor = actor
+ self.repos = []
+ self.targets = []
+ self.all_targets = {}
+ self.work_path = ".garlic"
+ self.repo_path = "~/.garlic/repos"
+ configure(&block) if block_given?
+ end
+
+ def configure(&block)
+ Configurator.new(self, &block)
+ end
+
+ def repo(name)
+ repos.detect {|r| r.name == name.to_s} or raise "Can't find repo: #{name}"
+ end
+
+ # convert a possible string argument into an array
+ def run_targets=(targets)
+ targets = targets.split(',').map{|t| t.strip} if targets.is_a?(String)
+ @run_targets = targets
+ end
+
+ ### garlic commands ###
+
+ # meta data about command methods which can be used by both rake and the cli tool
+ @@commands, @@command_descriptions = [], {}
+
+ class << self
+ def define_command(name, desc, &block)
+ @@commands << name
+ @@command_descriptions[name] = desc
+ define_method name, &block
+ end
+
+ def commands_with_description
+ @@commands.map{|m| [m, @@command_descriptions[m]]}
+ end
+
+ def command_description(name)
+ @@command_descriptions[name]
+ end
+
+ def commands
+ @@command_descriptions.keys.map {|c| c.to_s}
+ end
+ end
+
+ define_command :default, "Check repos, prepare TARGETs, and run TARGETs" do
+ check_repos
+ prepare
+ run
+ end
+
+ define_command :all, "Install and update all repos, prepare and run TARGETs" do
+ install_repos
+ update_repos
+ prepare
+ run
+ end
+
+ define_command :install_repos, "Install required repositories" do
+ repos.each {|repo| repo.install}
+ end
+
+ define_command :update_repos, "Update repositories" do
+ repos.each {|repo| repo.update}
+ end
+
+ define_command :check_repos, "Check that repos are what they are supposed to be" do
+ errors = []
+ repos.each do |repo|
+ begin
+ repo.check
+ rescue Exception => e
+ errors << "- #{e.message}"
+ end
+ end
+ errors.length == 0 or raise "\n#{errors.join("\n")}\n\nPlease remove these repos and run garlic install_repos\n"
+ end
+
+ define_command :reset_repos, "Reset all repos to their master branch" do
+ repos.each {|repo| repo.reset}
+ end
+
+ define_command :clean, "Remove the work done by garlic" do
+ rm_rf work_path
+ end
+
+ define_command :prepare, "Prepare each garlic TARGET" do
+ begin
+ determine_targets.each {|target| target.prepare }
+ ensure
+ repo('rails').checkout('master') # we get rails back to master if something goes wrong
+ end
+ end
+
+ # highly experimental: subject to change
+ define_command :shell, "Run shell commands across specified targets" do |*path|
+ shell = Shell.new(determine_targets)
+ shell.current_path = path.first if path.first
+ shell.run
+ end
+
+ define_command :run, "Run each garlic TARGET" do
+ these_targets = determine_targets
+ target_names, failed_names = these_targets.map{|t| t.name}, []
+
+ puts "\n#{'='*78}\nTargets: #{target_names.join(', ')}\n#{'='*78}\n"
+ these_targets.each do |target|
+ puts "\n#{'-'*78}\nTarget: #{target.name} (commit #{target.rails_sha[0..6]}, run at #{Time.now})\n#{'-'*78}\n"
+ begin
+ target.run
+ puts "\ntarget: #{target.name} PASS"
+ rescue
+ puts "\ntarget: #{target.name} FAIL"
+ failed_names << target.name
+ end
+ end
+ puts "\n#{'='*78}\n"
+ failed_names.length > 0 and raise "The following targets passed: #{(target_names - failed_names).join(', ')}.\n\nThe following targets FAILED: #{failed_names.join(', ')}.\n\n"
+ puts "All specified targets passed: #{target_names.join(', ')}.\n\n"
+ end
+
+ def respond_to?(method)
+ super(method) || (actor && actor.respond_to?(method))
+ end
+
+protected
+ def method_missing(method, *args, &block)
+ actor ? actor.send(method, *args, &block) : super
+ end
+
+ def determine_targets
+ run_targets ? targets.select{|t| run_targets.include?(t.name)} : targets
+ end
+ end
+end
67 lib/garlic/shell.rb
View
@@ -0,0 +1,67 @@
+require 'fileutils'
+begin
+ require 'term/ansicolor'
+rescue LoadError
+end
+
+module Garlic
+ class Shell
+ include FileUtils
+
+ attr_reader :current_path
+
+ def initialize(targets)
+ @current_path = '.'
+ @targets = targets
+ raise "Garlic::Shell requires at least one target" if @targets.empty?
+ end
+
+ def current_path=(path)
+ if path =~ /^(\/|\~)/
+ STDOUT << red << "#{path}: only relative paths allowed\n" << clear
+ else
+ full_path = File.expand_path(File.join(@targets.first.path, current_path, path))
+ if File.exists?(full_path)
+ @current_path = full_path.include?(@targets.first.path) ? full_path.sub(@targets.first.path,'') : '.'
+ else
+ STDOUT << red << "#{path}: no such directory\n" << clear
+ end
+ end
+ end
+
+ def run
+ STDOUT << green << "Garlic interactive session: type shell commands\n" << clear << prompt
+ while (command = STDIN.gets) do
+ command.strip!.empty? || process(command)
+ STDOUT << prompt
+ end
+ rescue Interrupt
+ ensure
+ STDOUT << green << "Garlic interactive session ended\n" << clear
+ end
+
+ def process(command)
+ if command =~ /^cd (.*)$/
+ self.current_path = $1
+ else
+ @targets.each do |target|
+ cd File.join(target.path, current_path) do
+ STDOUT << magenta << target.name + ":\n" << clear
+ system(command) || STDOUT << red << "command failed\n" << clear
+ end
+ end
+ end
+ end
+
+ private
+ [:red, :green, :magenta, :clear].each do |colour|
+ define_method colour do
+ Term::ANSIColor.send(colour) rescue ""
+ end
+ end
+
+ def prompt
+ green + "garlic:#{@current_path.sub(/^\.|\//,'')}> " + clear
+ end
+ end
+end
15 lib/garlic/target.rb
View
@@ -1,3 +1,5 @@
+require 'shell'
+
module Garlic
class Target
attr_reader :garlic, :path, :name, :rails_repo_name, :tree_ish
@@ -20,7 +22,7 @@ def prepare
runner.run(&@prepare) if @prepare
end
- def run
+ def run(command = nil)
runner.run(&garlic.all_targets[:run]) if garlic.all_targets[:run]
runner.run(&@run) if @run
end
@@ -29,9 +31,18 @@ def rails_sha
read_sha('vendor/rails')
end
+ def shell
+ unless @shell
+ @shell = Shell.new
+ @shell.verbose = false
+ @shell.cd path
+ end
+ @shell
+ end
+
private
def runner
- @runner ||= Runner.new(self)
+ @runner ||= Target::Runner.new(self)
end
def read_sha(install_path)
60 lib/garlic/tasks.rb
View
@@ -1,51 +1,23 @@
-$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
-require "garlic"
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'garlic'))
-def garlic(&block)
- @garlic ||= Garlic::Garlic.new(self)
- @garlic.configure(&block) if block_given?
- @garlic
+include Garlic
+
+# configure the garlic runner
+garlic ENV['CONFIG'] do
+ verbose ['true', 'yes', '1'].include?(ENV['VERBOSE'])
+ run_targets ENV['TARGETS'] || ENV['TARGET']
end
-desc "Prepare and run specified TARGET(S) (default all)"
-task :garlic => ['garlic:prepare_targets', 'garlic:run_targets']
+desc "Run garlic:default (CONFIG=path, TARGETS=list, VERBOSE=true)"
+task :garlic do
+ garlic.default
+end
namespace :garlic do
- desc "Install repos, update repos, check repos, prepare targets, and run CI in them"
- task :all => [:install_repos, :update_repos, :check_repos, :prepare_targets, :run_targets]
-
- desc "Prepare specified TARGET(S) (default all)"
- task :prepare_targets do
- garlic.prepare
- end
-
- desc "Clean all of the work away, but not the repos"
- task :clean do
- garlic.clean
- end
-
- desc "Run the CI 'run' task in specified TARGET(S) (default all)"
- task :run_targets do
- garlic.run
- end
-
- desc "Install required repositories"
- task :install_repos do
- garlic.install_repos
- end
-
- desc "Update installed repositories"
- task :update_repos do
- garlic.update_repos
- end
-
- desc "Check that repositories are installed"
- task :check_repos do
- garlic.check_repos
- end
-
- desc "Reset all repos back to master"
- task :reset_repos do
- garlic.reset_repos
+ Garlic::Runner.commands_with_description.each do |command, description|
+ desc description
+ task command do
+ garlic.send command
+ end
end
end
28 templates/default.rb
View
@@ -0,0 +1,28 @@
+# typical vanilla garlic configuration
+
+garlic do
+ # this plugin
+ repo "#{plugin}", :path => '.'
+
+ # other repos
+ repo "rails", :url => "git://github.com/rails/rails"
+
+ # targets
+ target "edge", :branch => 'origin/master'
+ target "2.1", :branch => "origin/2-1-stable"
+ target "2.0", :branch => "origin/2-0-stable"
+ target "1.2", :branch => "origin/1-2-stable"
+
+ # all targets
+ all_targets do
+ prepare do
+ plugin "#{plugin}", :clone => true # so we can work in targets
+ end
+
+ run do
+ cd "vendor/plugins/#{plugin}" do
+ sh "rake"
+ end
+ end
+ end
+end
34 templates/rspec.rb
View
@@ -0,0 +1,34 @@
+# typical rspec garlic configuration
+
+garlic do
+ # this plugin
+ repo "#{plugin}", :path => '.'
+
+ # other repos
+ repo "rails", :url => "git://github.com/rails/rails"
+ repo "rspec", :url => "git://github.com/dchelimsky/rspec"
+ repo "rspec-rails", :url => "git://github.com/dchelimsky/rspec-rails"
+
+ # targets
+ target "edge", :branch => 'origin/master'
+ target "2.1", :branch => "origin/2-1-stable"
+ target "2.0", :branch => "origin/2-0-stable"
+ target "1.2", :branch => "origin/1-2-stable"
+
+ # all targets
+ all_targets do
+ prepare do
+ plugin "#{plugin}", :clone => true # so we can work in targets
+ plugin "rspec"
+ plugin "rspec-rails" do
+ sh "script/generate rspec -f"
+ end
+ end
+
+ run do
+ cd "vendor/plugins/#{plugin}" do
+ sh "rake"
+ end
+ end
+ end
+end
30 templates/shoulda.rb
View
@@ -0,0 +1,30 @@
+# typical shoulda garlic configuration
+
+garlic do
+ # this plugin
+ repo "#{plugin}", :path => '.'
+
+ # other repos
+ repo "rails", :url => "git://github.com/rails/rails"
+ repo "shoulda", :url => "git://github.com/thoughtbot/shoulda"
+
+ # targets
+ target "edge", :branch => 'origin/master'
+ target "2.1", :branch => "origin/2-1-stable"
+ target "2.0", :branch => "origin/2-0-stable"
+ target "1.2", :branch => "origin/1-2-stable"
+
+ # all targets
+ all_targets do
+ prepare do
+ plugin "#{plugin}", :clone => true # so we can work in targets
+ plugin "shoulda"
+ end
+
+ run do
+ cd "vendor/plugins/#{plugin}" do
+ sh "rake"
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.