garlic_rails3_compatibility 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +64 -0
- data/License.txt +20 -0
- data/README.rdoc +143 -0
- data/Rakefile +56 -0
- data/Todo.txt +4 -0
- data/VERSION +1 -0
- data/bin/garlic +81 -0
- data/garlic_rails3_compatibility.gemspec +64 -0
- data/lib/garlic.rb +34 -0
- data/lib/garlic/configurator.rb +59 -0
- data/lib/garlic/generator.rb +29 -0
- data/lib/garlic/repo.rb +121 -0
- data/lib/garlic/session.rb +145 -0
- data/lib/garlic/shell.rb +67 -0
- data/lib/garlic/target.rb +140 -0
- data/lib/garlic/tasks.rb +23 -0
- data/lib/tabtab_definitions/garlic.rb +15 -0
- data/sh/garlic.sh +34 -0
- data/spec/garlic/repo_spec.rb +38 -0
- data/spec/spec_helper.rb +2 -0
- data/templates/default.rb +26 -0
- data/templates/rspec.rb +32 -0
- data/templates/shoulda.rb +28 -0
- metadata +91 -0
data/History.txt
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
== 0.1.10
|
2
|
+
|
3
|
+
* 2 minor enhancements
|
4
|
+
* updated gemspec for gemcutter and rubyforge
|
5
|
+
* templates now include rails 2.3
|
6
|
+
|
7
|
+
|
8
|
+
== 0.1.9
|
9
|
+
|
10
|
+
* 1 major enhancement
|
11
|
+
* added garlic shell commands (sh/garlic.sh) for easing the garlic workflow
|
12
|
+
to use them, add this to your ~/.profile
|
13
|
+
|
14
|
+
source `garlic --path`/sh/garlic.sh
|
15
|
+
|
16
|
+
== 0.1.8
|
17
|
+
|
18
|
+
* 1 bugfix
|
19
|
+
* fix problem where dependencies weren't checking out repo tags or branches properly
|
20
|
+
|
21
|
+
== 0.1.7
|
22
|
+
|
23
|
+
* 2 minor enhancement
|
24
|
+
* Fix problem whereby garlic update_repos wasn't updating repos correctly
|
25
|
+
* utilise Garlic::Generator in tabtab definition
|
26
|
+
|
27
|
+
== 0.1.6 2008-11-27
|
28
|
+
|
29
|
+
* 3 minor enhancements
|
30
|
+
* Updated Readme/TODO
|
31
|
+
* Some crufty output is now suppressed/removed
|
32
|
+
* garlic all command cleans the work path
|
33
|
+
|
34
|
+
* 1 bugfix
|
35
|
+
* --targets, -t option now actually works
|
36
|
+
|
37
|
+
== 0.1.5 2008-11-25
|
38
|
+
|
39
|
+
* 4 minor enhancements
|
40
|
+
* Removed 'all_targets' - just use ruby to DRY up garlic.rb
|
41
|
+
* Changed templates wrt above
|
42
|
+
* Better tabtab completions
|
43
|
+
* Updated TODO
|
44
|
+
|
45
|
+
== 0.1.4 2008-11-20
|
46
|
+
|
47
|
+
* 1 minor enhancement
|
48
|
+
* Added tabtab definitions that are in the right place
|
49
|
+
|
50
|
+
== 0.1.3 2008-11-20
|
51
|
+
|
52
|
+
* 1 minor enhancement
|
53
|
+
* Added tabtab definitions
|
54
|
+
|
55
|
+
== 0.1.2
|
56
|
+
|
57
|
+
* 2 major enhancements
|
58
|
+
* garlic CLI
|
59
|
+
* repos are now stored in ~/.garlic/repos (and this shared across multiple garlic sessions), work is in ./.garlic
|
60
|
+
|
61
|
+
== 0.1.1
|
62
|
+
|
63
|
+
* 1 major enhancement:
|
64
|
+
* freelancing-god added gem goodness
|
data/License.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2009 Ian White - ian.w.white@ardes.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
= garlic
|
2
|
+
|
3
|
+
<b>lightweight continuous integration for rails using git</b>
|
4
|
+
|
5
|
+
This is not a CI server, use cruisecontrol.rb or integrity for that. This is a simple set
|
6
|
+
of commands (or rake tasks) that let you specify a bunch of rails builds to run against, and
|
7
|
+
dependencies to install.
|
8
|
+
|
9
|
+
This is aimed at testing plugins (or apps) against multiple versions of rails,
|
10
|
+
and allows specifying other plugin dependencies (and their versions and any
|
11
|
+
setup requried).
|
12
|
+
|
13
|
+
If you want to run your specs (or whatever) against different versions of gems
|
14
|
+
that you have installed, then check out {ginger}[http://github.com/freelancing-god/ginger] by {Pat Allen}[http://github.com/freelancing-god]
|
15
|
+
|
16
|
+
Garlic works by cloning git repos for all your dependencies (so they all must be
|
17
|
+
git repos), and then using git to checkout various tags and branches to build
|
18
|
+
your app against.
|
19
|
+
|
20
|
+
Here's an example of running a plugin against 3 different rails verisons and 3 different rspec versions: {gist 28786}[http://gist.github.com/28786]
|
21
|
+
|
22
|
+
== It's still new, and not shiny yet
|
23
|
+
|
24
|
+
Please feel free to make it shinier. I'm successfully using it on most of my plugins, and I test
|
25
|
+
with rspec and cucumber.
|
26
|
+
|
27
|
+
Check out the {TODO LIST}[http://github.com/ianwhite/garlic/tree/master/Todo.txt]
|
28
|
+
|
29
|
+
== Get up and running quickly
|
30
|
+
|
31
|
+
You have a plugin and you want it tested against different versions of rails?
|
32
|
+
|
33
|
+
<b>1.</b> install garlic as a gem (see below)
|
34
|
+
|
35
|
+
<b>2.</b> cd into your (say, rspec tested) plugin directory
|
36
|
+
|
37
|
+
garlic generate rspec > garlic.rb
|
38
|
+
garlic install_repos
|
39
|
+
garlic
|
40
|
+
|
41
|
+
<b>3.</b> See what happens, edit garlic.rb to change rails versions and other stuff.
|
42
|
+
|
43
|
+
garlic --help # will probably help
|
44
|
+
|
45
|
+
== Installing
|
46
|
+
|
47
|
+
Install the garlic gem
|
48
|
+
|
49
|
+
# from rubyforge or gemcutter
|
50
|
+
sudo gem install garlic
|
51
|
+
|
52
|
+
# from github
|
53
|
+
sudo gem install ianwhite-garlic --source=http://gems.github.com
|
54
|
+
|
55
|
+
(if you want the very latest version)
|
56
|
+
|
57
|
+
git clone git://github.com/ianwhite/garlic
|
58
|
+
cd garlic
|
59
|
+
rake package
|
60
|
+
sudo gem install pkg/garlic-<code>*</code>.gem
|
61
|
+
|
62
|
+
== Example
|
63
|
+
|
64
|
+
To see garlic in action, download resources_controller_, a rails plugin that uses garlic for CI.
|
65
|
+
|
66
|
+
git clone git://github.com/ianwhite/resources_controller
|
67
|
+
|
68
|
+
|
69
|
+
run garlic
|
70
|
+
|
71
|
+
garlic all
|
72
|
+
|
73
|
+
This will clone all the required git repos (done only once), set up the target railses (done once), then run the targets.
|
74
|
+
|
75
|
+
=== Once you've committed some changes
|
76
|
+
|
77
|
+
You can prepare and run all the targets again (without fetching remote repos) by doing
|
78
|
+
|
79
|
+
garlic
|
80
|
+
|
81
|
+
This will prepare all the targets, using the current HEAD of the repos, and run the
|
82
|
+
CI task again.
|
83
|
+
|
84
|
+
=== Specifying particular targets
|
85
|
+
|
86
|
+
If you just want to run against a particular target or targets, you can use the -t option,
|
87
|
+
or if using Rake, the TARGET or TARGETS env var.
|
88
|
+
|
89
|
+
garlic -t edge
|
90
|
+
|
91
|
+
== Running Shell commands across multiple targets
|
92
|
+
|
93
|
+
Check dis out
|
94
|
+
|
95
|
+
garlic shell # {Example output}[http://gist.github.com/28795]
|
96
|
+
|
97
|
+
You can pipe any thing into garlic shell and it will execute across all of your garlic targets
|
98
|
+
|
99
|
+
== Rake tasks
|
100
|
+
|
101
|
+
If you prefer to use garlic via rake tasks, then just require 'garlic/tasks' and you'll get a bunch of em.
|
102
|
+
Once required, do rake -T to see descriptions.
|
103
|
+
|
104
|
+
== garlic workflow shell commands
|
105
|
+
|
106
|
+
If you add the following line to your .profile
|
107
|
+
|
108
|
+
source `garlic --path`/sh/garlic.sh
|
109
|
+
|
110
|
+
Then you'll get these 4 new shell commands:
|
111
|
+
|
112
|
+
gcd [target] cds into the specified target working repo
|
113
|
+
gcdp [target] cds into the specified target plugin in the working repo
|
114
|
+
gup cds back up to the garlic'd repo from within a working path
|
115
|
+
gpush [branch] from within a working repo, pushes changes back to the local garlic target, and resets
|
116
|
+
local changes in that target to HEAD.
|
117
|
+
|
118
|
+
This means you might have a workflow as follows (example is for a plugin):
|
119
|
+
|
120
|
+
# run garlic, see probs in '2-2-stable'
|
121
|
+
|
122
|
+
gcdp 2-2 # => takes you into the working repo in the '2-2-stable' target
|
123
|
+
|
124
|
+
# fix the changes, make some commits
|
125
|
+
|
126
|
+
gpush # => pushes the changes back to the enclosing garlic'd repo
|
127
|
+
gup # => go back up there
|
128
|
+
garlic # => rerun garlic to see how the changes affect the other targets
|
129
|
+
|
130
|
+
== Lend a hand
|
131
|
+
|
132
|
+
This is an early release, so there is plenty of scope for changes and improvement
|
133
|
+
If you want to lend a hand, get in touch.
|
134
|
+
|
135
|
+
(c) Ian White 2008-2009 - ian.w.white@gmail.com
|
136
|
+
MIT Licence
|
137
|
+
|
138
|
+
== Lent a hand
|
139
|
+
|
140
|
+
Thanks very much to:
|
141
|
+
|
142
|
+
* Pat Allan
|
143
|
+
* Dr Nic Williams (API suggestions)
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
|
8
|
+
|
9
|
+
require 'garlic'
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'jeweler'
|
13
|
+
|
14
|
+
Jeweler::Tasks.new do |s|
|
15
|
+
s.name = "garlic_rails3_compatibility"
|
16
|
+
s.version = Garlic::Version::String
|
17
|
+
s.summary = "Test your project across multiple versions of rails/dependencies"
|
18
|
+
s.description = "CI tool to test your project across multiple versions of rails/dependencies"
|
19
|
+
s.email = "scott@railsnewbie.com"
|
20
|
+
s.homepage = "http://github.com/smtlaissezfaire/garlic"
|
21
|
+
s.authors = ["Scott Taylor", "Ian White"]
|
22
|
+
end
|
23
|
+
|
24
|
+
Jeweler::GemcutterTasks.new
|
25
|
+
|
26
|
+
Jeweler::RubyforgeTasks.new do |rubyforge|
|
27
|
+
rubyforge.doc_task = "doc"
|
28
|
+
end
|
29
|
+
|
30
|
+
namespace :release do
|
31
|
+
desc "Release current version to github, gemcutter and rubyforge"
|
32
|
+
task :all => ['release', 'gemcutter:release', 'rubyforge:release']
|
33
|
+
end
|
34
|
+
|
35
|
+
rescue LoadError
|
36
|
+
puts "Jeweler not available for gem tasks. Install it with: sudo gem install jeweler"
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
require 'hanna/rdoctask'
|
41
|
+
rescue LoadError
|
42
|
+
end
|
43
|
+
|
44
|
+
Rake::RDocTask.new(:doc) do |d|
|
45
|
+
d.options << '--all'
|
46
|
+
d.rdoc_dir = 'doc'
|
47
|
+
d.main = 'README.rdoc'
|
48
|
+
d.title = "garlic API Docs"
|
49
|
+
d.rdoc_files.include('README.rdoc', 'History.txt', 'License.txt', 'Todo.txt', 'VERSION', 'lib/**/*.rb')
|
50
|
+
end
|
51
|
+
task :rdoc => :doc
|
52
|
+
|
53
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
54
|
+
t.warning = true
|
55
|
+
end
|
56
|
+
task :default => :spec
|
data/Todo.txt
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.10
|
data/bin/garlic
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
4
|
+
|
5
|
+
require 'getoptlong'
|
6
|
+
require 'rake'
|
7
|
+
require 'garlic'
|
8
|
+
|
9
|
+
include Garlic
|
10
|
+
|
11
|
+
USAGE = "USAGE: garlic [options] [command] (try garlic --help)"
|
12
|
+
|
13
|
+
HELP = <<-end_doc
|
14
|
+
garlic - run a command in different versions of rails
|
15
|
+
|
16
|
+
USAGE: garlic [options] [command]
|
17
|
+
|
18
|
+
COMMANDS:
|
19
|
+
#{Garlic::Session.commands_with_description.map{|method, desc| " %-17s %s" % [method, desc]}.join("\n")}
|
20
|
+
|
21
|
+
The default command is "default"
|
22
|
+
|
23
|
+
OPTIONS:
|
24
|
+
--help -h You're reading it
|
25
|
+
--verbose -v Show work
|
26
|
+
--config CONFIG -c Specify a different location of garlic config
|
27
|
+
--backtrace Show ruby backtrace on error
|
28
|
+
--targets TARGETS -t Specify subset of targets comma separated or
|
29
|
+
regexp part e.g. -t 2-1,2-2
|
30
|
+
|
31
|
+
You can generate a sample garlic.rb with
|
32
|
+
garlic generate [TEMPLATE [PLUGIN_NAME]] (Available templates: #{available_templates.join(', ')})
|
33
|
+
|
34
|
+
end_doc
|
35
|
+
|
36
|
+
@verbose = false
|
37
|
+
|
38
|
+
GetoptLong.new(
|
39
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT],
|
40
|
+
['--verbose', '-v', GetoptLong::NO_ARGUMENT],
|
41
|
+
['--targets', '-t', GetoptLong::REQUIRED_ARGUMENT],
|
42
|
+
['--config', '-c', GetoptLong::REQUIRED_ARGUMENT],
|
43
|
+
['--backtrace', GetoptLong::NO_ARGUMENT],
|
44
|
+
['--path', GetoptLong::NO_ARGUMENT],
|
45
|
+
['--version', GetoptLong::NO_ARGUMENT]
|
46
|
+
).each do |opt, arg|
|
47
|
+
case opt
|
48
|
+
when '--help' then STDOUT << HELP; exit true
|
49
|
+
when '--path' then puts File.dirname(File.dirname(File.expand_path(__FILE__))); exit true
|
50
|
+
when '--version' then puts Garlic::Version::String; exit true
|
51
|
+
when '--verbose' then @verbose = true
|
52
|
+
when '--config' then @config_file = arg
|
53
|
+
when '--targets' then @run_targets = arg
|
54
|
+
when '--backtrace' then @backtrace = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
begin
|
59
|
+
if ARGV.first == 'generate'
|
60
|
+
generate_config(*ARGV[1..-1])
|
61
|
+
else
|
62
|
+
# run a garlic command
|
63
|
+
raise "Unknown command: #{ARGV.first}" unless ARGV.empty? || Garlic::Session.commands.include?(ARGV.first)
|
64
|
+
|
65
|
+
verbose(@verbose)
|
66
|
+
|
67
|
+
# configure the garlic runner
|
68
|
+
garlic(@config_file) # load up the garlic instance
|
69
|
+
garlic.verbose = @verbose
|
70
|
+
garlic.run_targets = @run_targets
|
71
|
+
|
72
|
+
# run the command
|
73
|
+
ARGV << 'default' if ARGV.empty?
|
74
|
+
garlic.send *ARGV
|
75
|
+
end
|
76
|
+
|
77
|
+
rescue Exception => e
|
78
|
+
STDERR << "\n#{USAGE}\n\nError: #{e.message}\n\n"
|
79
|
+
raise e if @backtrace
|
80
|
+
exit false
|
81
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{garlic_rails3_compatibility}
|
8
|
+
s.version = "0.1.10"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Scott Taylor", "Ian White"]
|
12
|
+
s.date = %q{2011-06-03}
|
13
|
+
s.default_executable = %q{garlic}
|
14
|
+
s.description = %q{CI tool to test your project across multiple versions of rails/dependencies}
|
15
|
+
s.email = %q{scott@railsnewbie.com}
|
16
|
+
s.executables = ["garlic"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"History.txt",
|
22
|
+
"License.txt",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"Todo.txt",
|
26
|
+
"VERSION",
|
27
|
+
"bin/garlic",
|
28
|
+
"garlic_rails3_compatibility.gemspec",
|
29
|
+
"lib/garlic.rb",
|
30
|
+
"lib/garlic/configurator.rb",
|
31
|
+
"lib/garlic/generator.rb",
|
32
|
+
"lib/garlic/repo.rb",
|
33
|
+
"lib/garlic/session.rb",
|
34
|
+
"lib/garlic/shell.rb",
|
35
|
+
"lib/garlic/target.rb",
|
36
|
+
"lib/garlic/tasks.rb",
|
37
|
+
"lib/tabtab_definitions/garlic.rb",
|
38
|
+
"sh/garlic.sh",
|
39
|
+
"spec/garlic/repo_spec.rb",
|
40
|
+
"spec/spec_helper.rb",
|
41
|
+
"templates/default.rb",
|
42
|
+
"templates/rspec.rb",
|
43
|
+
"templates/shoulda.rb"
|
44
|
+
]
|
45
|
+
s.homepage = %q{http://github.com/smtlaissezfaire/garlic}
|
46
|
+
s.require_paths = ["lib"]
|
47
|
+
s.rubygems_version = %q{1.3.7}
|
48
|
+
s.summary = %q{Test your project across multiple versions of rails/dependencies}
|
49
|
+
s.test_files = [
|
50
|
+
"spec/garlic/repo_spec.rb",
|
51
|
+
"spec/spec_helper.rb"
|
52
|
+
]
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
else
|
60
|
+
end
|
61
|
+
else
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
data/lib/garlic.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "garlic/session"
|
2
|
+
require "garlic/configurator"
|
3
|
+
require "garlic/repo"
|
4
|
+
require "garlic/target"
|
5
|
+
require "garlic/generator"
|
6
|
+
require "garlic/shell"
|
7
|
+
|
8
|
+
module Garlic
|
9
|
+
include Generator
|
10
|
+
|
11
|
+
module Version
|
12
|
+
String = File.read(File.dirname(File.dirname(__FILE__)) + '/VERSION').strip
|
13
|
+
Major, Minor, Patch = String.split('.').map{|i| i.to_i}
|
14
|
+
end
|
15
|
+
|
16
|
+
# return the current garlic session
|
17
|
+
def garlic(config = nil, &block)
|
18
|
+
@garlic ||= Garlic::Session.new(self)
|
19
|
+
load_config(config)
|
20
|
+
@garlic.configure(&block) if block_given?
|
21
|
+
@garlic
|
22
|
+
end
|
23
|
+
|
24
|
+
# load config from
|
25
|
+
def load_config(config = nil)
|
26
|
+
unless @garlic_config_file
|
27
|
+
@garlic_config_file = config || "garlic.rb"
|
28
|
+
unless File.exists?(@garlic_config_file)
|
29
|
+
raise "garlic requries a configuration file (can't find #{@garlic_config_file}), try:\n garlic generate [#{available_templates.join('|')}] > garlic.rb"
|
30
|
+
end
|
31
|
+
eval File.read(@garlic_config_file)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Garlic
|
2
|
+
# Configures the garlic runner in a decalarative style
|
3
|
+
class Configurator
|
4
|
+
attr_reader :garlic
|
5
|
+
|
6
|
+
def initialize(garlic, &block)
|
7
|
+
@garlic = garlic
|
8
|
+
instance_eval(&block) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def repo(name, options = {})
|
12
|
+
options[:name] = name
|
13
|
+
options[:path] ||= "#{garlic.repo_path}/#{name}"
|
14
|
+
garlic.repos << Repo.new(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def target(name, options = {}, &block)
|
18
|
+
options[:name] = name
|
19
|
+
options[:path] = "#{garlic.work_path}/#{name_to_path(name)}"
|
20
|
+
BlockParser.new(options, [:prepare, :run], &block) if block_given?
|
21
|
+
garlic.targets << Target.new(garlic, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def respond_to?(method)
|
25
|
+
super || garlic.respond_to?("#{method}=")
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def name_to_path(name)
|
30
|
+
name.gsub(/[^\w\d_.-]/,'_').downcase
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(attribute, value)
|
34
|
+
if garlic.respond_to?("#{attribute}=")
|
35
|
+
garlic.send("#{attribute}=", value)
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class BlockParser
|
42
|
+
attr_reader :options, :whitelist
|
43
|
+
|
44
|
+
def initialize(options, whitelist = [], &block)
|
45
|
+
@options = options
|
46
|
+
@whitelist = whitelist
|
47
|
+
instance_eval(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing(method, *args, &block)
|
51
|
+
if block_given? && args.empty? && (whitelist.empty? || whitelist.include?(method))
|
52
|
+
options[method.to_sym] = block
|
53
|
+
else
|
54
|
+
raise ArgumentError, "Don't know how to parse #{method} #{args.inspect unless args.empty?}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Garlic
|
4
|
+
# generate a garlic config file
|
5
|
+
module Generator
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
TEMPLATES_PATH = File.expand_path("~/.garlic/templates")
|
9
|
+
|
10
|
+
def generate_config(template = 'default', plugin = nil)
|
11
|
+
raise "unknown template: #{template}.\nUse one of #{available_templates.join(', ')} or create your own in #{TEMPLATES_PATH}" unless available_templates.include?(template)
|
12
|
+
plugin ||= File.basename(File.expand_path('.'))
|
13
|
+
puts eval("<<-EOD\n" + File.read(File.join(TEMPLATES_PATH, "#{template}.rb")) + "\nEOD")
|
14
|
+
end
|
15
|
+
|
16
|
+
def available_templates
|
17
|
+
copy_templates unless File.exists?(TEMPLATES_PATH)
|
18
|
+
Dir[File.join(TEMPLATES_PATH, '*')].map {|f| File.basename(f.sub(/.rb$/,'')) }
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
def copy_templates
|
23
|
+
mkdir_p TEMPLATES_PATH, :verbose => false
|
24
|
+
Dir[File.join(File.dirname(__FILE__), '../../templates/*.rb')].each do |file|
|
25
|
+
cp file, File.join(TEMPLATES_PATH, File.basename(file)), :verbose => false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/garlic/repo.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
module Garlic
|
2
|
+
# This class represents a local git repo
|
3
|
+
class Repo
|
4
|
+
attr_reader :url, :local, :path, :name
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
if @url = options[:url]
|
8
|
+
@url = File.expand_path(@url) unless options[:url] =~ /^\w+(:|@)/
|
9
|
+
end
|
10
|
+
|
11
|
+
@path = options[:path] or raise ArgumentError, "Repo requires a :path"
|
12
|
+
@path = File.expand_path(@path)
|
13
|
+
|
14
|
+
@local = options[:local]
|
15
|
+
@local = File.expand_path(@local) if @local
|
16
|
+
|
17
|
+
@name = options[:name] || File.basename(@path)
|
18
|
+
end
|
19
|
+
|
20
|
+
class<<self
|
21
|
+
def path?(path)
|
22
|
+
File.directory?(File.join(path, '.git'))
|
23
|
+
end
|
24
|
+
|
25
|
+
def tree_ish(options)
|
26
|
+
[:tree_ish, :tree, :branch, :tag, :commit, :sha].each do |key|
|
27
|
+
return options[key] if options[key]
|
28
|
+
end
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def head_sha(path)
|
33
|
+
`cd #{path}; git log HEAD -1 --pretty=format:\"%H\"`
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def install
|
38
|
+
if File.exists?(path)
|
39
|
+
puts "\nSkipping #{name}, as it exists"
|
40
|
+
else
|
41
|
+
puts "\nInstalling #{name}"
|
42
|
+
sh "git clone #{url}#{" --reference #{local}" if local} #{path}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def update
|
47
|
+
puts "\nUpdating #{name}..."
|
48
|
+
if Repo.path?(path)
|
49
|
+
if url
|
50
|
+
begin
|
51
|
+
checkout 'master'
|
52
|
+
cd(path) do
|
53
|
+
sh "git fetch origin", :verbose => false
|
54
|
+
sh "git pull", :verbose => false
|
55
|
+
end
|
56
|
+
rescue Exception => e
|
57
|
+
puts "\n\nIt seems there was a problem.\nTry running rake garlic:reset_repos\n\n"
|
58
|
+
raise e
|
59
|
+
end
|
60
|
+
else
|
61
|
+
puts "No url for #{name} given, so not updating"
|
62
|
+
end
|
63
|
+
elsif File.exists?(path)
|
64
|
+
raise "\nRepo #{name} (#{path}) is not a git repo.\nRemove it and run rake garlic:install_repos\n\n"
|
65
|
+
else
|
66
|
+
raise "\nRepo #{name} missing from #{path}.\nPlease run rake garlic:install_repos\n\n"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def check
|
71
|
+
if !Repo.path?(path)
|
72
|
+
raise "#{name} is missing from #{path}, or is not a git repo"
|
73
|
+
elsif url && !same_url?(origin_url)
|
74
|
+
raise "#{name}'s url has changed from #{url} to #{origin_url}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def reset
|
79
|
+
cd(path) { sh "git reset --hard master" }
|
80
|
+
checkout('master')
|
81
|
+
end
|
82
|
+
|
83
|
+
def checkout(tree_ish)
|
84
|
+
cd(path) { sh "git checkout -q #{tree_ish}", :verbose => false }
|
85
|
+
end
|
86
|
+
|
87
|
+
def export_to(export_path)
|
88
|
+
rm_rf export_path; mkdir_p export_path
|
89
|
+
cd(path) do
|
90
|
+
sh "git archive --format=tar HEAD > #{File.join(export_path, "#{name}.tar")}", :verbose => false
|
91
|
+
end
|
92
|
+
cd(export_path) do
|
93
|
+
`tar -x -f #{name}.tar`
|
94
|
+
rm "#{name}.tar"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def clone_to(clone_path)
|
99
|
+
mkdir_p File.dirname(clone_path)
|
100
|
+
cd (File.dirname(clone_path)) do
|
101
|
+
sh "git clone #{path} #{clone_path}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def origin_url
|
106
|
+
unless @origin_url
|
107
|
+
match = `cd #{path}; git remote show -n origin`.match(/URL: (.*)\n/)
|
108
|
+
@origin_url = (match && match[1])
|
109
|
+
end
|
110
|
+
@origin_url
|
111
|
+
end
|
112
|
+
|
113
|
+
def same_url?(url)
|
114
|
+
self.url.sub(/\/?(\.git)?$/, '') == url.sub(/\/?(\.git)?$/, '')
|
115
|
+
end
|
116
|
+
|
117
|
+
def head_sha
|
118
|
+
Repo.head_sha(path)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Garlic
|
2
|
+
# this class runs the top level garlic commands
|
3
|
+
class Session
|
4
|
+
attr_reader :actor, :run_targets
|
5
|
+
attr_accessor :repos, :targets, :repo_path, :work_path, :verbose
|
6
|
+
|
7
|
+
def initialize(actor = nil, &block)
|
8
|
+
@actor = actor
|
9
|
+
self.repos = []
|
10
|
+
self.targets = []
|
11
|
+
self.work_path = ".garlic"
|
12
|
+
self.repo_path = "~/.garlic/repos"
|
13
|
+
configure(&block) if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure(&block)
|
17
|
+
Configurator.new(self, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def repo(name)
|
21
|
+
repos.detect {|r| r.name == name.to_s} or raise "Can't find repo: #{name}"
|
22
|
+
end
|
23
|
+
|
24
|
+
# convert a possible string argument into an array
|
25
|
+
def run_targets=(targets)
|
26
|
+
targets = targets.split(',').map{|t| t.strip} if targets.is_a?(String)
|
27
|
+
@run_targets = targets
|
28
|
+
end
|
29
|
+
|
30
|
+
### garlic commands ###
|
31
|
+
|
32
|
+
# meta data about command methods which can be used by both rake and the cli tool
|
33
|
+
@@commands, @@command_descriptions = [], {}
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def define_command(name, desc, &block)
|
37
|
+
@@commands << name
|
38
|
+
@@command_descriptions[name] = desc
|
39
|
+
define_method name, &block
|
40
|
+
end
|
41
|
+
|
42
|
+
def commands_with_description
|
43
|
+
@@commands.map{|m| [m, @@command_descriptions[m]]}
|
44
|
+
end
|
45
|
+
|
46
|
+
def command_description(name)
|
47
|
+
@@command_descriptions[name]
|
48
|
+
end
|
49
|
+
|
50
|
+
def commands
|
51
|
+
@@command_descriptions.keys.map {|c| c.to_s}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
define_command :default, "Check repos, prepare TARGETs, and run TARGETs" do
|
56
|
+
check_repos
|
57
|
+
prepare
|
58
|
+
run
|
59
|
+
end
|
60
|
+
|
61
|
+
define_command :all, "Install and update all repos, prepare and run TARGETs" do
|
62
|
+
install_repos
|
63
|
+
update_repos
|
64
|
+
clean
|
65
|
+
prepare
|
66
|
+
run
|
67
|
+
end
|
68
|
+
|
69
|
+
define_command :install_repos, "Install required repositories" do
|
70
|
+
repos.each {|repo| repo.install}
|
71
|
+
end
|
72
|
+
|
73
|
+
define_command :update_repos, "Update repositories" do
|
74
|
+
repos.each {|repo| repo.update}
|
75
|
+
end
|
76
|
+
|
77
|
+
define_command :check_repos, "Check that repos are what they are supposed to be" do
|
78
|
+
errors = []
|
79
|
+
repos.each do |repo|
|
80
|
+
begin
|
81
|
+
repo.check
|
82
|
+
rescue Exception => e
|
83
|
+
errors << "- #{e.message}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
errors.length == 0 or raise "\n#{errors.join("\n")}\n\nPlease remove these repos and run garlic install_repos\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
define_command :reset_repos, "Reset all repos to their master branch" do
|
90
|
+
repos.each {|repo| repo.reset}
|
91
|
+
end
|
92
|
+
|
93
|
+
define_command :clean, "Remove the work done by garlic" do
|
94
|
+
rm_rf work_path
|
95
|
+
end
|
96
|
+
|
97
|
+
define_command :prepare, "Prepare each garlic TARGET" do
|
98
|
+
determine_targets.each {|target| target.prepare }
|
99
|
+
end
|
100
|
+
|
101
|
+
define_command :shell, "Run shell commands from stdin across specified targets" do |*path|
|
102
|
+
shell = Shell.new(determine_targets)
|
103
|
+
shell.current_path = path.first if path.first
|
104
|
+
shell.run
|
105
|
+
end
|
106
|
+
|
107
|
+
define_command :path, "return the work dir for the specified target" do |*path_target|
|
108
|
+
self.run_targets = path_target.first if path_target.any?
|
109
|
+
puts determine_targets.first.path
|
110
|
+
end
|
111
|
+
|
112
|
+
define_command :run, "Run each garlic TARGET" do
|
113
|
+
these_targets = determine_targets
|
114
|
+
target_names, failed_names = these_targets.map{|t| t.name}, []
|
115
|
+
|
116
|
+
puts "\n#{'='*78}\nTargets: #{target_names.join(', ')}\n#{'='*78}\n"
|
117
|
+
these_targets.each do |target|
|
118
|
+
puts "\n#{'-'*78}\nTarget: #{target.name} (commit #{target.rails_sha[0..6]}, run at #{Time.now})\n#{'-'*78}\n"
|
119
|
+
begin
|
120
|
+
target.run
|
121
|
+
puts "\ntarget: #{target.name} PASS"
|
122
|
+
rescue
|
123
|
+
puts "\ntarget: #{target.name} FAIL"
|
124
|
+
failed_names << target.name
|
125
|
+
end
|
126
|
+
end
|
127
|
+
puts "\n#{'='*78}\n"
|
128
|
+
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"
|
129
|
+
puts "All specified targets passed: #{target_names.join(', ')}.\n\n"
|
130
|
+
end
|
131
|
+
|
132
|
+
def respond_to?(method)
|
133
|
+
super(method) || (actor && actor.respond_to?(method))
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
def method_missing(method, *args, &block)
|
138
|
+
actor ? actor.send(method, *args, &block) : super
|
139
|
+
end
|
140
|
+
|
141
|
+
def determine_targets
|
142
|
+
run_targets ? targets.select{|t| t.name =~ /(?:#{run_targets.join("|")})/i} : targets
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/garlic/shell.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
begin
|
3
|
+
require 'term/ansicolor'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
|
7
|
+
module Garlic
|
8
|
+
class Shell
|
9
|
+
include FileUtils
|
10
|
+
|
11
|
+
attr_reader :current_path
|
12
|
+
|
13
|
+
def initialize(targets)
|
14
|
+
@current_path = '.'
|
15
|
+
@targets = targets
|
16
|
+
raise "Garlic::Shell requires at least one target" if @targets.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_path=(path)
|
20
|
+
if path =~ /^(\/|\~)/
|
21
|
+
STDOUT << red << "#{path}: only relative paths allowed\n" << clear
|
22
|
+
else
|
23
|
+
full_path = File.expand_path(File.join(@targets.first.path, current_path, path))
|
24
|
+
if File.exists?(full_path)
|
25
|
+
@current_path = full_path.include?(@targets.first.path) ? full_path.sub(@targets.first.path,'') : '.'
|
26
|
+
else
|
27
|
+
STDOUT << red << "#{path}: no such directory\n" << clear
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
STDOUT << green << "Garlic interactive session: type shell commands\n" << clear << prompt
|
34
|
+
while (command = STDIN.gets) do
|
35
|
+
command.strip!.empty? || process(command)
|
36
|
+
STDOUT << prompt
|
37
|
+
end
|
38
|
+
rescue Interrupt
|
39
|
+
ensure
|
40
|
+
STDOUT << green << "Garlic interactive session ended\n" << clear
|
41
|
+
end
|
42
|
+
|
43
|
+
def process(command)
|
44
|
+
if command =~ /^cd (.*)$/
|
45
|
+
self.current_path = $1
|
46
|
+
else
|
47
|
+
@targets.each do |target|
|
48
|
+
cd File.join(target.path, current_path) do
|
49
|
+
STDOUT << magenta << target.name + ":\n" << clear
|
50
|
+
system(command) || STDOUT << red << "command failed\n" << clear
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
[:red, :green, :magenta, :clear].each do |colour|
|
58
|
+
define_method colour do
|
59
|
+
Term::ANSIColor.send(colour) rescue ""
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def prompt
|
64
|
+
green + "garlic:#{@current_path.sub(/^\.|\//,'')}> " + clear
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'shell'
|
2
|
+
|
3
|
+
module Garlic
|
4
|
+
class Target
|
5
|
+
attr_reader :garlic, :path, :name, :rails_repo_name, :tree_ish
|
6
|
+
|
7
|
+
def initialize(garlic, options = {})
|
8
|
+
@garlic = garlic
|
9
|
+
@tree_ish = Repo.tree_ish(options) || 'origin/master'
|
10
|
+
@rails_repo_name = options[:rails] || 'rails'
|
11
|
+
@path = options[:path] or raise ArgumentError, "Target requires a :path"
|
12
|
+
@path = File.expand_path(@path)
|
13
|
+
@name = options[:name] || File.basename(@path)
|
14
|
+
@prepare = options[:prepare]
|
15
|
+
@run = options[:run]
|
16
|
+
end
|
17
|
+
|
18
|
+
def prepare
|
19
|
+
puts "\nPreparing target #{name} (#{tree_ish})"
|
20
|
+
install_rails
|
21
|
+
runner.run(&@prepare) if @prepare
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
runner.run(&@run) if @run
|
26
|
+
end
|
27
|
+
|
28
|
+
def rails_sha
|
29
|
+
read_sha('vendor/rails')
|
30
|
+
end
|
31
|
+
|
32
|
+
def shell
|
33
|
+
unless @shell
|
34
|
+
@shell = Shell.new
|
35
|
+
@shell.verbose = false
|
36
|
+
@shell.cd path
|
37
|
+
end
|
38
|
+
@shell
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def runner
|
43
|
+
@runner ||= Target::Runner.new(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_sha(install_path)
|
47
|
+
File.read(File.join(path, install_path, '.git_sha')) rescue nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_sha(install_path, sha)
|
51
|
+
File.open(File.join(path, install_path, '.git_sha'), 'w+') {|f| f << sha}
|
52
|
+
end
|
53
|
+
|
54
|
+
def install_rails
|
55
|
+
rails_repo = garlic.repo(rails_repo_name)
|
56
|
+
rails_repo.checkout(tree_ish)
|
57
|
+
if File.exists?(path)
|
58
|
+
puts "Rails app for #{name} exists"
|
59
|
+
else
|
60
|
+
puts "Creating rails app for #{name}..."
|
61
|
+
|
62
|
+
if File.exists?(rails_bin = "#{rails_repo.path}/bin/rails")
|
63
|
+
`ruby #{rails_bin} new #{path}`
|
64
|
+
|
65
|
+
cd path do
|
66
|
+
`bundle install`
|
67
|
+
end
|
68
|
+
else
|
69
|
+
`ruby #{rails_repo.path}/railties/bin/rails #{path}`
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
install_dependency(rails_repo, 'vendor/rails') do
|
74
|
+
# remove secret token so that rails 3 installer doesn't freeze
|
75
|
+
`rm -rf config/initializers/secret_token.rb`
|
76
|
+
`rake rails:update`
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def install_dependency(repo, install_path = ".", options = {}, &block)
|
81
|
+
repo = garlic.repo(repo) unless repo.is_a?(Repo)
|
82
|
+
tree_ish = Repo.tree_ish(options)
|
83
|
+
|
84
|
+
if options[:clone]
|
85
|
+
if Repo.path?(install_path)
|
86
|
+
puts "#{install_path} exists, and is a repo"
|
87
|
+
cd(install_path) { `git fetch origin` }
|
88
|
+
else
|
89
|
+
puts "cloning #{repo.name} to #{install_path}"
|
90
|
+
repo.clone_to(File.join(path, install_path))
|
91
|
+
end
|
92
|
+
cd(install_path) { `git checkout #{tree_ish || repo.head_sha}` }
|
93
|
+
|
94
|
+
else
|
95
|
+
old_tree_ish = repo.head_sha
|
96
|
+
repo.checkout(tree_ish) if tree_ish
|
97
|
+
if read_sha(install_path) == repo.head_sha
|
98
|
+
puts "#{install_path} is up to date at #{tree_ish || repo.head_sha[0..6]}"
|
99
|
+
else
|
100
|
+
puts "#{install_path} needs update to #{tree_ish || repo.head_sha[0..6]}, exporting archive from #{repo.name}..."
|
101
|
+
repo.export_to(File.join(path, install_path))
|
102
|
+
cd(path) { garlic.instance_eval(&block) } if block_given?
|
103
|
+
write_sha(install_path, repo.head_sha)
|
104
|
+
end
|
105
|
+
repo.checkout(old_tree_ish) if tree_ish
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
class Runner
|
111
|
+
attr_reader :target
|
112
|
+
|
113
|
+
def initialize(target)
|
114
|
+
@target = target
|
115
|
+
end
|
116
|
+
|
117
|
+
def run(&block)
|
118
|
+
cd target.path do
|
119
|
+
instance_eval(&block)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def method_missing(method, *args, &block)
|
124
|
+
target.garlic.send(method, *args, &block)
|
125
|
+
end
|
126
|
+
|
127
|
+
def respond_to?(method)
|
128
|
+
super(method) || target.garlic.respond_to?(method)
|
129
|
+
end
|
130
|
+
|
131
|
+
def plugin(plugin, options = {}, &block)
|
132
|
+
target.send(:install_dependency, plugin, "vendor/plugins/#{options[:as] || plugin}", options, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
def dependency(repo, dest, options = {}, &block)
|
136
|
+
target.send(:install_dependency, repo, dest, options, &block)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/lib/garlic/tasks.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'garlic'))
|
2
|
+
|
3
|
+
include Garlic
|
4
|
+
|
5
|
+
# configure the garlic runner
|
6
|
+
garlic ENV['CONFIG'] do
|
7
|
+
verbose ['true', 'yes', '1'].include?(ENV['VERBOSE'])
|
8
|
+
run_targets ENV['TARGETS'] || ENV['TARGET']
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Run garlic:default (CONFIG=path, TARGETS=list, VERBOSE=true)"
|
12
|
+
task :garlic do
|
13
|
+
garlic.default
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :garlic do
|
17
|
+
Garlic::Session.commands_with_description.each do |command, description|
|
18
|
+
desc description
|
19
|
+
task command do
|
20
|
+
garlic.send command
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "garlic/session"
|
2
|
+
require "garlic/generator"
|
3
|
+
|
4
|
+
TabTab::Definition.register('garlic', :import => '--help') do |g|
|
5
|
+
Garlic::Session.commands.each do |c|
|
6
|
+
g.command c
|
7
|
+
end
|
8
|
+
|
9
|
+
g.command :generate do
|
10
|
+
class << self
|
11
|
+
include Garlic::Generator
|
12
|
+
end
|
13
|
+
available_templates
|
14
|
+
end
|
15
|
+
end
|
data/sh/garlic.sh
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# garlic shell helpers
|
2
|
+
|
3
|
+
# cd into the work path of a garlic target
|
4
|
+
gcd ()
|
5
|
+
{
|
6
|
+
cd `garlic path $1`
|
7
|
+
}
|
8
|
+
|
9
|
+
# cd into probable plugin dir of a garlic target
|
10
|
+
gcdp ()
|
11
|
+
{
|
12
|
+
here=`pwd | sed 's/.*\///'`
|
13
|
+
cd `garlic path $1`/vendor/plugins/$here
|
14
|
+
}
|
15
|
+
|
16
|
+
# cd back up to enclosing garlic project
|
17
|
+
gup ()
|
18
|
+
{
|
19
|
+
cd `pwd | sed 's/\.garlic.*//'`
|
20
|
+
}
|
21
|
+
|
22
|
+
# push changes back to local garlic origin, resetting the origin
|
23
|
+
gpush ()
|
24
|
+
{
|
25
|
+
if [ `pwd | sed 's/\.garlic//'` == `pwd` ]; then
|
26
|
+
echo "gpush can only be used in a garlic work repo";
|
27
|
+
else
|
28
|
+
git push origin $1 2>&1 | grep -v warning;
|
29
|
+
here=`pwd`;
|
30
|
+
gup;
|
31
|
+
git reset --hard;
|
32
|
+
cd $here;
|
33
|
+
fi
|
34
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
|
2
|
+
|
3
|
+
describe Garlic::Repo do
|
4
|
+
describe "new(:url => 'some/local/repo', :path => 'some/dest')" do
|
5
|
+
before { @repo = Garlic::Repo.new(:url => 'some/local/repo', :path => 'some/dest') }
|
6
|
+
|
7
|
+
it "should expand the path" do
|
8
|
+
@repo.path.should == File.expand_path('some/dest')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should expand the url" do
|
12
|
+
@repo.url.should == File.expand_path('some/local/repo')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have name == 'dest' (basename of path)" do
|
16
|
+
@repo.name.should == 'dest'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#install' do
|
20
|
+
before do
|
21
|
+
@repo.stub!(:puts) # silence!
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should 'git clone <repo> <dest>" do
|
25
|
+
@repo.should_receive(:sh).with("git clone #{@repo.url} #{@repo.path}")
|
26
|
+
@repo.install
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "new(:url => 'git://remote/repo', :path => 'some/dest')" do
|
32
|
+
before { @repo = Garlic::Repo.new(:url => 'git://remote/repo', :path => 'some/dest') }
|
33
|
+
|
34
|
+
it "should NOT expand the url" do
|
35
|
+
@repo.url == 'git://remote/repo'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# typical vanilla garlic configuration
|
2
|
+
|
3
|
+
garlic do
|
4
|
+
# this plugin
|
5
|
+
repo "#{plugin}", :path => '.'
|
6
|
+
|
7
|
+
# other repos
|
8
|
+
repo "rails", :url => "git://github.com/rails/rails"
|
9
|
+
|
10
|
+
# target railses
|
11
|
+
['master', '2-3-stable', '2-2-stable', '2-1-stable', '2-0-stable'].each do |rails|
|
12
|
+
|
13
|
+
# declare how to prepare, and run each CI target
|
14
|
+
target rails, :tree_ish => "origin/#{rails}" do
|
15
|
+
prepare do
|
16
|
+
plugin "#{plugin}", :clone => true # so we can work in targets
|
17
|
+
end
|
18
|
+
|
19
|
+
run do
|
20
|
+
cd "vendor/plugins/#{plugin}" do
|
21
|
+
sh "rake"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/templates/rspec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# typical rspec garlic configuration
|
2
|
+
|
3
|
+
garlic do
|
4
|
+
# this plugin
|
5
|
+
repo "#{plugin}", :path => '.'
|
6
|
+
|
7
|
+
# other repos
|
8
|
+
repo "rails", :url => "git://github.com/rails/rails"
|
9
|
+
repo "rspec", :url => "git://github.com/dchelimsky/rspec"
|
10
|
+
repo "rspec-rails", :url => "git://github.com/dchelimsky/rspec-rails"
|
11
|
+
|
12
|
+
# target railses
|
13
|
+
['master', '2-3-stable', '2-2-stable', '2-1-stable', '2-0-stable'].each do |rails|
|
14
|
+
|
15
|
+
# declare how to prepare, and run each CI target
|
16
|
+
target rails, :tree_ish => "origin/#{rails}" do
|
17
|
+
prepare do
|
18
|
+
plugin "#{plugin}", :clone => true # so we can work in targets
|
19
|
+
plugin "rspec"
|
20
|
+
plugin "rspec-rails" do
|
21
|
+
`script/generate rspec -f`
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
run do
|
26
|
+
cd "vendor/plugins/#{plugin}" do
|
27
|
+
sh "rake"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# typical shoulda garlic configuration
|
2
|
+
|
3
|
+
garlic do
|
4
|
+
# this plugin
|
5
|
+
repo "#{plugin}", :path => '.'
|
6
|
+
|
7
|
+
# other repos
|
8
|
+
repo "rails", :url => "git://github.com/rails/rails"
|
9
|
+
repo "shoulda", :url => "git://github.com/thoughtbot/shoulda"
|
10
|
+
|
11
|
+
# target railses
|
12
|
+
['master', '2-3-stable', '2-2-stable', '2-1-stable', '2-0-stable'].each do |rails|
|
13
|
+
|
14
|
+
# declare how to prepare, and run each CI target
|
15
|
+
target rails, :tree_ish => "origin/#{rails}" do
|
16
|
+
prepare do
|
17
|
+
plugin "#{plugin}", :clone => true # so we can work in targets
|
18
|
+
plugin "shoulda"
|
19
|
+
end
|
20
|
+
|
21
|
+
run do
|
22
|
+
cd "vendor/plugins/#{plugin}" do
|
23
|
+
sh "rake"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: garlic_rails3_compatibility
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 10
|
10
|
+
version: 0.1.10
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Scott Taylor
|
14
|
+
- Ian White
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-06-03 00:00:00 -04:00
|
20
|
+
default_executable: garlic
|
21
|
+
dependencies: []
|
22
|
+
|
23
|
+
description: CI tool to test your project across multiple versions of rails/dependencies
|
24
|
+
email: scott@railsnewbie.com
|
25
|
+
executables:
|
26
|
+
- garlic
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files:
|
30
|
+
- README.rdoc
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- License.txt
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- Todo.txt
|
37
|
+
- VERSION
|
38
|
+
- bin/garlic
|
39
|
+
- garlic_rails3_compatibility.gemspec
|
40
|
+
- lib/garlic.rb
|
41
|
+
- lib/garlic/configurator.rb
|
42
|
+
- lib/garlic/generator.rb
|
43
|
+
- lib/garlic/repo.rb
|
44
|
+
- lib/garlic/session.rb
|
45
|
+
- lib/garlic/shell.rb
|
46
|
+
- lib/garlic/target.rb
|
47
|
+
- lib/garlic/tasks.rb
|
48
|
+
- lib/tabtab_definitions/garlic.rb
|
49
|
+
- sh/garlic.sh
|
50
|
+
- spec/garlic/repo_spec.rb
|
51
|
+
- spec/spec_helper.rb
|
52
|
+
- templates/default.rb
|
53
|
+
- templates/rspec.rb
|
54
|
+
- templates/shoulda.rb
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: http://github.com/smtlaissezfaire/garlic
|
57
|
+
licenses: []
|
58
|
+
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.3.7
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Test your project across multiple versions of rails/dependencies
|
89
|
+
test_files:
|
90
|
+
- spec/garlic/repo_spec.rb
|
91
|
+
- spec/spec_helper.rb
|