andys-mason 0.1.0

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/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Mason
2
+
3
+ Build things
4
+
5
+ $ gem install mason
6
+
7
+ ### Install buildpacks locally
8
+
9
+ $ mason buildpacks
10
+ * buildpacks (~/.mason/buildpacks)
11
+ = nodejs: https://github.com/heroku/heroku-buildpack-nodejs.git
12
+ = ruby: https://github.com/ddollar/heroku-buildpack-ruby.git
13
+
14
+ $ mason buildpacks:install https://github.com/heroku/heroku-buildpack-python.git
15
+ * installing buildpack https://github.com/heroku/heroku-buildpack-python.git
16
+
17
+ ### Use buildpacks to build things
18
+
19
+ $ mason build /tmp/app
20
+ * detecting buildpack... done
21
+ = name: Ruby
22
+ = url: https://github.com/heroku/heroku-buildpack-ruby.git
23
+ * compiling:
24
+ ... COMPILE OUTPUT
25
+ * packaging... done
26
+ = type: dir
27
+ = file: /tmp/mason.out
28
+
29
+ $ mason build /tmp/app -t dir -o /tmp/compiledapp
30
+ * detecting buildpack... done
31
+ = name: Ruby
32
+ = url: https://github.com/heroku/heroku-buildpack-ruby.git
33
+ * compiling...
34
+ ... COMPILE OUTPUT
35
+ * packaging... done
36
+ = type: dir
37
+ = dir: /tmp/compiledapp
38
+
39
+ $ mason build /tmp/app -b https://github.com/ddollar/buildpack-other.git -t tgz
40
+ * detecting buildpack... done
41
+ = name: Other
42
+ = url: https://github.com/ddollar/buildpack-other.git
43
+ * compiling...
44
+ ... COMPILE OUTPUT
45
+ * packaging... done
46
+ = type: tgz
47
+ = file: /tmp/app.tgz
48
+
49
+ ### Build things for other platforms using Vagrant
50
+
51
+ You will need [VirtualBox](https://www.virtualbox.org/wiki/Downloads) for Vagrant to function.
52
+
53
+ $ gem install vagrant
54
+
55
+ $ vagrant box add lucid64 http://files.vagrantup.com/lucid64.box
56
+
57
+ $ mason stacks:create lucid64
58
+ * creating stack lucid64... done
59
+
60
+ $ mason stacks:up lucid64
61
+ * booting stack lucid64 (this may take a while)... done
62
+
63
+ $ mason:build /tmp/app -t tgz -o /tmp/compiled.tgz -s lucid64
64
+ * booting stack lucid64 (this may take a while)... done
65
+ * detecting buildpack... done
66
+ = name: Baz
67
+ = url: https://github.com/ddollar/buildpack-baz.git
68
+ * compiling...
69
+ ... COMPILE OUTPUT
70
+ * packaging... done
71
+ = type: tgz
72
+ = dir: /tmp/compiled.tgz
data/bin/mason ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require "mason/cli"
6
+
7
+ begin
8
+ Mason::CLI.run
9
+ rescue Errno::EPIPE
10
+ rescue Mason::CommandFailed => ex
11
+ end
@@ -0,0 +1,5 @@
1
+ Vagrant::Config.run do |config|
2
+ config.vagrant.dotfile_name = File.expand_path("~/.mason/vagrant")
3
+
4
+ BOXES
5
+ end
data/lib/mason.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Mason
2
+
3
+ class CommandFailed < StandardError; end
4
+
5
+ end
@@ -0,0 +1,99 @@
1
+ require "mason"
2
+ require "tmpdir"
3
+ require "yaml"
4
+ require "foreman/engine"
5
+
6
+ class Mason::Buildpack
7
+
8
+ attr_reader :dir, :name, :url
9
+
10
+ def initialize(dir)
11
+ @dir = dir
12
+ Dir.chdir(@dir) do
13
+ @name = File.basename(@dir)
14
+ @url = %x{ git config remote.origin.url }.chomp
15
+ end
16
+ end
17
+
18
+ def <=>(other)
19
+ self.name <=> other.name
20
+ end
21
+
22
+ def detect(app)
23
+ mkchtmpdir do
24
+ output = %x{ #{script("detect")} "#{app}" }
25
+ $?.exitstatus.zero? ? output.chomp : nil
26
+ end
27
+ end
28
+
29
+ def compile(app, env_file=nil, cache=nil)
30
+ cache_dir = cache || "#{app}/.git/cache"
31
+ puts " caching in #{cache_dir}"
32
+ compile_dir = Dir.mktmpdir
33
+ FileUtils.rm_rf compile_dir
34
+ FileUtils.cp_r app, compile_dir, :preserve => true
35
+ FileUtils.mkdir_p cache_dir
36
+ Dir.chdir(compile_dir) do
37
+ IO.popen(%{ #{script("compile")} "#{compile_dir}" "#{cache_dir}" }) do |io|
38
+ until io.eof?
39
+ data = io.gets
40
+ data.gsub!(/^-----> /, " + ")
41
+ data.gsub!(/^ /, " ")
42
+ data.gsub!(/^\s+\!\s+$/, "")
43
+ data.gsub!(/^\s+\!\s+/, " ! ")
44
+ data.gsub!(/^\s+$/, "")
45
+ print data
46
+ end
47
+ end
48
+ raise "compile failed" unless $?.exitstatus.zero?
49
+ end
50
+ release = YAML.load(`#{script('release')} "#{compile_dir}"`)
51
+ write_env(compile_dir, release, env_file)
52
+ write_procfile(compile_dir, release)
53
+ compile_dir
54
+ end
55
+
56
+ private
57
+
58
+ def write_env(compile_dir, release, env_file)
59
+ env = env_file ? Foreman::Engine.new.load_env(env_file) : {}
60
+ config_vars = release["config_vars"] || {}
61
+ config = config_vars.merge(env)
62
+
63
+ File.open(File.join(compile_dir, ".env"), "w") do |f|
64
+ f.puts config.map{|k, v| "#{k}=#{v}"}.join("\n")
65
+ end
66
+ end
67
+
68
+ def write_procfile(compile_dir, release)
69
+ filename = File.join(compile_dir, "Procfile")
70
+ process_types = release["default_process_types"] || {}
71
+
72
+ if File.exists? filename
73
+ Foreman::Procfile.new(filename).entries.each do |e|
74
+ process_types[e.name] = e.command
75
+ end
76
+ end
77
+
78
+ File.open(filename, "w") do |f|
79
+ process_types.each do |name, command|
80
+ f.puts "#{name}: #{command}"
81
+ end
82
+ end
83
+ end
84
+
85
+ def mkchtmpdir
86
+ ret = nil
87
+ Dir.mktmpdir do |dir|
88
+ Dir.chdir(dir) do
89
+ ret = yield(dir)
90
+ end
91
+ end
92
+ ret
93
+ end
94
+
95
+ def script(name)
96
+ File.join(dir, "bin", name)
97
+ end
98
+ end
99
+
@@ -0,0 +1,75 @@
1
+ require "fileutils"
2
+ require "mason"
3
+ require "mason/buildpack"
4
+ require "uri"
5
+ require "digest/sha1"
6
+
7
+ class Mason::Buildpacks
8
+
9
+ def self.install(url, ad_hoc=false)
10
+ root_dir = ad_hoc ? ad_hoc_root : root
11
+ FileUtils.mkdir_p root_dir
12
+
13
+ Dir.chdir(root_dir) do
14
+ uri = URI.parse(url)
15
+ if uri.path =~ /buildpack-(\w+)/
16
+ name = $1
17
+ name += "-#{Digest::SHA1.hexdigest(url).to_s[0 .. 8]}" if ad_hoc
18
+ branch = uri.fragment || "master"
19
+ if File.exists?(name)
20
+ # Can't do a fetch here as it won't update local branches
21
+ system "cd #{name} && git checkout master && git pull"
22
+ raise "failed to update buildpack checkout" unless $?.exitstatus.zero?
23
+ else
24
+ system "git clone #{url.split('#').first} #{name} >/dev/null 2>&1"
25
+ raise "failed to clone buildpack" unless $?.exitstatus.zero?
26
+ end
27
+ system "cd #{name} && git checkout #{branch} 2> /dev/null"
28
+ raise "failed to check out branch #{branch}" unless $?.exitstatus.zero?
29
+ File.expand_path(root_dir + "/" + name)
30
+ else
31
+ raise "BUILDPACK should be a url containing buildpack-NAME.git"
32
+ end
33
+ end
34
+ end
35
+
36
+ def self.uninstall(name)
37
+ Dir.chdir(root) do
38
+ raise "#{name} buildpack is not installed" unless File.exists?(name)
39
+ FileUtils.rm_rf name
40
+ end
41
+ end
42
+
43
+ def self.root(ad_hoc=false, expand=true)
44
+ dir = "~/.mason/buildpacks"
45
+ expand ? File.expand_path(dir) : dir
46
+ end
47
+
48
+ def self.ad_hoc_root(expand=true)
49
+ dir = "~/.mason/buildpacks-ad-hoc"
50
+ expand ? File.expand_path(dir) : dir
51
+ end
52
+
53
+ def self.buildpacks
54
+ @buildpacks ||= begin
55
+ Dir[File.join(root, "*")].map do |buildpack_dir|
56
+ Mason::Buildpack.new(buildpack_dir)
57
+ end
58
+ end
59
+ end
60
+
61
+ def self.detect(app, buildpack_url)
62
+ if buildpack_url
63
+ puts "Using $BUILDPACK_URL: #{buildpack_url}"
64
+ buildpack_dir = install(buildpack_url, true)
65
+ return Mason::Buildpack.new(buildpack_dir)
66
+ else
67
+ buildpacks.each do |buildpack|
68
+ ret = buildpack.detect(app)
69
+ return [buildpack, ret] if ret
70
+ end
71
+ end
72
+ nil
73
+ end
74
+
75
+ end
data/lib/mason/cli.rb ADDED
@@ -0,0 +1,279 @@
1
+ require "mason"
2
+ require "mason/buildpacks"
3
+ require "mason/stacks"
4
+ require "mason/version"
5
+ require "thor"
6
+ require "thor/shell/basic"
7
+
8
+ class Mason::CLI < Thor
9
+
10
+ class_option :debug, :type => :boolean, :desc => "show backtraces"
11
+ class_option :help, :type => :boolean, :aliases => "-h", :desc => "help for this command"
12
+
13
+ map %w( -v -V --version ) => :version
14
+
15
+ desc "version", "display version"
16
+
17
+ def version
18
+ puts "mason v#{Mason::VERSION}"
19
+ end
20
+
21
+ desc "build APP", "build an app"
22
+
23
+ method_option :buildpack, :type => :string, :aliases => "-b", :desc => "use a custom buildpack"
24
+ method_option :output, :type => :string, :aliases => "-o", :desc => "output location"
25
+ method_option :quiet, :type => :boolean, :aliases => "-q", :desc => "quiet packaging output"
26
+ method_option :stack, :type => :string, :aliases => "-s", :desc => "use a stack for building"
27
+ method_option :type, :type => :string, :aliases => "-t", :desc => "output type (dir, img, tgz)"
28
+ method_option :env_file, :type => :string, :aliases => "-e", :desc => "config environment file"
29
+ method_option :cache, :type => :string, :aliases => "-c", :desc => "cache directory"
30
+
31
+ def build(app)
32
+ app = File.expand_path(app)
33
+
34
+ raise "no such directory: #{app}" unless File.exists?(app)
35
+
36
+ type = options[:type]
37
+ output = options[:output]
38
+
39
+ type = File.extname(output)[1..-1] if !type && output
40
+ output = "#{app}.#{type}" if !output && type
41
+
42
+ type ||= "dir"
43
+ output ||= "/tmp/mason.out"
44
+
45
+ output = File.expand_path(output)
46
+
47
+ raise "no such output format: #{type}" unless %w( dir img tgz ).include?(type)
48
+
49
+ if stack = options[:stack]
50
+ if Mason::Stacks.state(stack) == :up
51
+ puts "* using stack #{stack}"
52
+ else
53
+ print "* booting stack #{stack} (this may take a while)... "
54
+ Mason::Stacks.up(stack)
55
+ puts "done"
56
+ end
57
+
58
+ buildpacks_dir = File.expand_path("~/.mason/share/#{stack}/buildpacks")
59
+ compile_dir = File.expand_path("~/.mason/share/#{stack}/app")
60
+ mason_dir = File.expand_path("~/.mason/share/#{stack}/mason")
61
+
62
+ FileUtils.rm_rf buildpacks_dir
63
+ FileUtils.rm_rf compile_dir
64
+ FileUtils.rm_rf mason_dir
65
+
66
+ FileUtils.cp_r(File.expand_path("~/.mason/buildpacks"), buildpacks_dir,
67
+ :preserve => true)
68
+ FileUtils.cp_r(File.expand_path("../../../", __FILE__), mason_dir,
69
+ :preserve => true)
70
+ FileUtils.cp_r(app, compile_dir, :preserve => true)
71
+
72
+ mason_args = %{ /share/app -q -o /share/output -t #{type} }
73
+ mason_args += %{ -b "#{options[:buildpack]}" } if options[:buildpack]
74
+
75
+ Mason::Stacks.run(stack, <<-COMMAND)
76
+ gem spec thor 2>&1 >/dev/null || sudo gem install thor
77
+ /usr/bin/env ruby -rubygems /share/mason/bin/mason build #{mason_args}
78
+ COMMAND
79
+
80
+ FileUtils.rm_rf output
81
+ FileUtils.cp_r(File.expand_path("~/.mason/share/#{stack}/output"), output,
82
+ :preserve => true)
83
+
84
+ puts "* packaging"
85
+ puts " = type: #{type}"
86
+ puts " = location: #{output}"
87
+ else
88
+ print "* detecting buildpack... "
89
+
90
+ buildpack_url = ENV["BUILDPACK_URL"] || options[:buildpack]
91
+ buildpack, ret = Mason::Buildpacks.detect(app, buildpack_url)
92
+ raise "no valid buildpack detected" unless buildpack
93
+
94
+ puts "done"
95
+ puts " = name: #{buildpack.name}"
96
+ puts " = url: #{buildpack.url}"
97
+ puts " = display: #{ret}"
98
+
99
+ puts "* compiling..."
100
+ compile_dir = buildpack.compile(app, options[:env_file], options[:cache])
101
+
102
+ print "* packaging... " unless options[:quiet]
103
+ case type.to_sym
104
+ when :tgz then
105
+ Dir.chdir(compile_dir) do
106
+ system %{ tar czf "#{output}" . }
107
+ end
108
+ when :img then
109
+ raise "img not supported yet"
110
+ when :dir then
111
+ FileUtils.rm_rf output
112
+ FileUtils.cp_r compile_dir, output, :preserve => true
113
+ else
114
+ raise "no such output type: #{type}"
115
+ end
116
+
117
+ unless options[:quiet]
118
+ puts "done"
119
+ puts " = type: #{type}"
120
+ puts " = location: #{output}"
121
+ end
122
+ end
123
+
124
+ end
125
+
126
+ desc "vagrant COMMAND", "run a vagrant command in the mason environment"
127
+
128
+ def vagrant(*args)
129
+ Mason::Stacks.vagrant(args)
130
+ end
131
+
132
+ desc "buildpacks", "list installed buildpacks"
133
+
134
+ def buildpacks
135
+ buildpacks = Mason::Buildpacks.buildpacks
136
+
137
+ puts "* buildpacks (#{Mason::Buildpacks.root(false)})"
138
+ buildpacks.sort.each do |buildpack|
139
+ puts " = #{buildpack.name}: #{buildpack.url}"
140
+ end
141
+
142
+ puts " - no buildpacks installed, use buildpacks:install" if buildpacks.length.zero?
143
+ end
144
+
145
+ class Buildpacks < Thor
146
+
147
+ desc "buildpacks:install URL", "install a buildpack"
148
+
149
+ def install(url)
150
+ puts "* installing buildpack #{url}"
151
+ Mason::Buildpacks.install url
152
+ end
153
+
154
+ desc "buildpacks:uninstall NAME", "uninstall a buildpack"
155
+
156
+ def uninstall(name)
157
+ puts "* uninstalling buildpack #{name}"
158
+ Mason::Buildpacks.uninstall name
159
+ end
160
+
161
+ end
162
+
163
+ desc "stacks", "list available stacks"
164
+
165
+ def stacks
166
+ stacks = Mason::Stacks.stacks
167
+
168
+ puts "* available stacks"
169
+ stacks.keys.each do |name|
170
+ puts " - #{name} [#{Mason::Stacks.state(name)}]"
171
+ end
172
+
173
+ puts " - no stacks created, use stacks:create" if stacks.length.zero?
174
+ end
175
+
176
+ class Stacks < Thor
177
+
178
+ # Hackery. Take the run method away from Thor so that we can redefine it.
179
+ class << self
180
+ def is_thor_reserved_word?(word, type)
181
+ return false if word == 'run'
182
+ super
183
+ end
184
+ end
185
+
186
+ desc "stacks:create VAGRANT_BOX_NAME", "create a new stack"
187
+
188
+ method_option :name, :type => :string, :aliases => "-n", :desc => "use an alternate stack name"
189
+
190
+ def create(box)
191
+ name = options[:name] || box
192
+ print "* creating stack #{name}... "
193
+ Mason::Stacks.create(name, box)
194
+ puts "done"
195
+ end
196
+
197
+ desc "stacks:destroy STACK", "destroy a stack"
198
+
199
+ def destroy(name)
200
+ print "* destroying stack #{name}... "
201
+ Mason::Stacks.destroy(name)
202
+ puts "done"
203
+ end
204
+
205
+ desc "stacks:up STACK", "boot a stack"
206
+
207
+ def up(name)
208
+ print "* booting stack #{name} (this will take a while)..."
209
+ Mason::Stacks.up(name)
210
+ puts "done"
211
+ end
212
+
213
+ desc "stacks:down STACK", "suspend a stack"
214
+
215
+ def down(name)
216
+ print "* stopping stack #{name}..."
217
+ Mason::Stacks.down(name)
218
+ puts "done"
219
+ end
220
+
221
+ desc "stacks:run STACK COMMAND", "run a command on a stack"
222
+
223
+ def run(name, *args)
224
+ Mason::Stacks.run(name, args.join(" "))
225
+ end
226
+
227
+ end
228
+
229
+ # hack thor
230
+ def self.run
231
+ args = ARGV.dup
232
+ parts = args.first.to_s.split(":")
233
+ method = parts.pop
234
+ ns = parts.pop
235
+
236
+ args[0] = method
237
+
238
+ klass = case ns
239
+ when "buildpacks" then Buildpacks
240
+ when "stacks" then Stacks
241
+ else self
242
+ end
243
+
244
+ unless (args & %w( -h --help )).empty?
245
+ klass.task_help(Thor::Shell::Basic.new, args.first)
246
+ return
247
+ end
248
+
249
+ klass.start(args)
250
+ rescue StandardError => ex
251
+ $stderr.puts " ! #{ex}"
252
+ $stderr.puts " " + ex.backtrace.join("\n ") if ARGV.include?("--debug")
253
+ exit 1
254
+ end
255
+
256
+ private
257
+
258
+ def vagrantfile
259
+ FileUtils.mkdir_p File.expand_path("~/.mason")
260
+ file = File.expand_path("~/.mason/Vagrantfile")
261
+ build_vagrantfile unless File.exists?(file)
262
+ file
263
+ end
264
+
265
+ def build_vagrantfile(boxes={})
266
+ data = File.read(File.expand_path("../../../data/Vagrantfile.template", __FILE__))
267
+ data.gsub! "BOXES", (boxes.map do |name, box|
268
+ <<-BOX
269
+ config.vm.define :#{name} do |config|
270
+ config.vm.box = "#{box}"
271
+ end
272
+ BOX
273
+ end.join("\n"))
274
+ File.open(File.expand_path("~/.mason/Vagrantfile"), "w") do |file|
275
+ file.puts data
276
+ end
277
+ end
278
+
279
+ end
data/lib/mason/cp_r.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Mason
2
+ def self.cp_R(src, dest, options = {})
3
+ return if options[:noop]
4
+ output = `cp -vR#{options[:preserve] ? 'p' : ''}#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}`
5
+ raise "cp failed: #{output}" unless $?.exitstatus.zero?
6
+ end
7
+ end
@@ -0,0 +1,113 @@
1
+ require "fileutils"
2
+ require "mason"
3
+
4
+ class Mason::Stacks
5
+
6
+ def self.load_vagrant!
7
+ require "vagrant"
8
+ if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new("1.0.1")
9
+ raise "mason requires vagrant 1.0.1 or higher"
10
+ end
11
+ build_vagrantfile unless File.exists?(vagrantfile)
12
+ end
13
+
14
+ def self.vagrant_env(display=false)
15
+ load_vagrant!
16
+ ui = display ? Vagrant::UI::Basic : nil
17
+ Vagrant::Environment.new(:vagrantfile_name => vagrantfile, :ui_class => ui)
18
+ end
19
+
20
+ def self.vms
21
+ vagrant_env.vms
22
+ end
23
+
24
+ def self.vagrant(args)
25
+ vagrant_env(true).cli(args)
26
+ end
27
+
28
+ def self.stacks
29
+ @stacks ||= begin
30
+ vms.inject({}) do |hash, (name, vm)|
31
+ next(hash) if name == :default
32
+ hash.update(name => vm.box ? vm.box.name : "")
33
+ end
34
+ end
35
+ end
36
+
37
+ def self.create(name, box)
38
+ raise "stack already exists: #{name}" if stacks.keys.include?(name.to_sym)
39
+ raise "vagrant box does not exist: #{box}" unless vagrant_env.boxes.map(&:name).include?(box)
40
+ build_vagrantfile(stacks.update(name => box))
41
+ end
42
+
43
+ def self.destroy(name)
44
+ raise "no such stack: #{name}" unless stacks.keys.include?(name.to_sym)
45
+ vm = vms[name.to_sym]
46
+ vm.halt rescue nil
47
+ vm.destroy rescue nil
48
+ s = stacks
49
+ s.delete(name.to_sym)
50
+ build_vagrantfile(s)
51
+ end
52
+
53
+ def self.state(name)
54
+ raise "no such stack: #{name}" unless stacks.keys.include?(name.to_sym)
55
+ case vms[name.to_sym].state.to_sym
56
+ when :running then :up
57
+ else :down
58
+ end
59
+ end
60
+
61
+ def self.up(name)
62
+ raise "no such stack: #{name}" unless stacks.keys.include?(name.to_sym)
63
+ return if state(name) == :up
64
+ vms[name.to_sym].up
65
+ end
66
+
67
+ def self.down(name)
68
+ raise "no such stack: #{name}" unless stacks.keys.include?(name.to_sym)
69
+ return if state(name) == :down
70
+ vms[name.to_sym].suspend
71
+ end
72
+
73
+ def self.run(name, command)
74
+ raise "no suck stack: #{name}" unless stacks.keys.include?(name.to_sym)
75
+ vms[name.to_sym].channel.execute(command, :error_check => false) do |type, data|
76
+ print data
77
+ end
78
+ end
79
+
80
+ def self.vagrantfile
81
+ File.expand_path("~/.mason/Vagrantfile")
82
+ end
83
+
84
+ def self.vagrantfile_template
85
+ File.expand_path("../../../data/Vagrantfile.template", __FILE__)
86
+ end
87
+
88
+ def self.share_dir(name)
89
+ dir = File.expand_path("~/.mason/share/#{name}")
90
+ FileUtils.mkdir_p dir unless File.exists?(dir)
91
+ dir
92
+ end
93
+
94
+ def self.build_vagrantfile(stacks={})
95
+ data = File.read(vagrantfile_template)
96
+ ip_base = 3
97
+ data.gsub! "BOXES", (stacks.map do |name, box|
98
+ ip_base += 1
99
+ <<-BOX
100
+ config.vm.define :#{name} do |config|
101
+ config.vm.box = "#{box}"
102
+ config.vm.base_mac = "080027706AA#{ip_base}"
103
+ config.vm.network :hostonly, "33.33.33.#{ip_base}"
104
+ config.vm.share_folder "share", "/share", "#{share_dir(name)}"
105
+ end
106
+ BOX
107
+ end.join("\n").chomp)
108
+ File.open(vagrantfile, "w") do |file|
109
+ file.puts data
110
+ end
111
+ end
112
+
113
+ end
@@ -0,0 +1,3 @@
1
+ module Mason
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: andys-mason
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Dollar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: foreman
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Build things
47
+ email: ddollar@gmail.com
48
+ executables:
49
+ - mason
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - README.md
54
+ - bin/mason
55
+ - data/Vagrantfile.template
56
+ - lib/mason.rb
57
+ - lib/mason/buildpack.rb
58
+ - lib/mason/buildpacks.rb
59
+ - lib/mason/cli.rb
60
+ - lib/mason/stacks.rb
61
+ - lib/mason/version.rb
62
+ - lib/mason/cp_r.rb
63
+ homepage: http://github.com/andys/mason
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 1.8.24
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Build things
87
+ test_files: []