fpm-fry 0.1.3

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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/bin/fpm-fry +10 -0
  3. data/lib/cabin/nice_output.rb +70 -0
  4. data/lib/fpm/fry/block_enumerator.rb +25 -0
  5. data/lib/fpm/fry/build_output_parser.rb +22 -0
  6. data/lib/fpm/fry/client.rb +162 -0
  7. data/lib/fpm/fry/command/cook.rb +370 -0
  8. data/lib/fpm/fry/command.rb +90 -0
  9. data/lib/fpm/fry/detector.rb +109 -0
  10. data/lib/fpm/fry/docker_file.rb +149 -0
  11. data/lib/fpm/fry/joined_io.rb +63 -0
  12. data/lib/fpm/fry/os_db.rb +35 -0
  13. data/lib/fpm/fry/plugin/alternatives.rb +90 -0
  14. data/lib/fpm/fry/plugin/edit_staging.rb +66 -0
  15. data/lib/fpm/fry/plugin/exclude.rb +18 -0
  16. data/lib/fpm/fry/plugin/init.rb +53 -0
  17. data/lib/fpm/fry/plugin/platforms.rb +10 -0
  18. data/lib/fpm/fry/plugin/script_helper.rb +176 -0
  19. data/lib/fpm/fry/plugin/service.rb +100 -0
  20. data/lib/fpm/fry/plugin.rb +3 -0
  21. data/lib/fpm/fry/recipe/builder.rb +267 -0
  22. data/lib/fpm/fry/recipe.rb +141 -0
  23. data/lib/fpm/fry/source/dir.rb +56 -0
  24. data/lib/fpm/fry/source/git.rb +90 -0
  25. data/lib/fpm/fry/source/package.rb +202 -0
  26. data/lib/fpm/fry/source/patched.rb +118 -0
  27. data/lib/fpm/fry/source.rb +47 -0
  28. data/lib/fpm/fry/stream_parser.rb +98 -0
  29. data/lib/fpm/fry/tar.rb +71 -0
  30. data/lib/fpm/fry/templates/debian/after_install.erb +9 -0
  31. data/lib/fpm/fry/templates/debian/before_install.erb +13 -0
  32. data/lib/fpm/fry/templates/debian/before_remove.erb +13 -0
  33. data/lib/fpm/fry/templates/redhat/after_install.erb +2 -0
  34. data/lib/fpm/fry/templates/redhat/before_install.erb +6 -0
  35. data/lib/fpm/fry/templates/redhat/before_remove.erb +6 -0
  36. data/lib/fpm/fry/templates/sysv.erb +125 -0
  37. data/lib/fpm/fry/templates/upstart.erb +15 -0
  38. data/lib/fpm/fry/ui.rb +12 -0
  39. data/lib/fpm/package/docker.rb +186 -0
  40. metadata +111 -0
@@ -0,0 +1,56 @@
1
+ require 'fpm/fry/source'
2
+ require 'fileutils'
3
+ require 'digest'
4
+ module FPM; module Fry ; module Source
5
+ class Dir
6
+
7
+ REGEX = %r!\A(?:file:|/|\.)!
8
+
9
+ def self.guess( url )
10
+ Source::guess_regex(REGEX, url)
11
+ end
12
+
13
+ class Cache < Struct.new(:package, :dir)
14
+ extend Forwardable
15
+
16
+ def_delegators :package, :url, :logger, :file_map
17
+
18
+ def tar_io
19
+ cmd = ['tar','-c','.']
20
+ logger.debug("Running tar",cmd: cmd, dir: dir)
21
+ ::Dir.chdir(dir) do
22
+ return IO.popen(cmd)
23
+ end
24
+ end
25
+
26
+ def copy_to(dst)
27
+ children = ::Dir.new(dir).select{|x| x[0...1] != "." }.map{|x| File.join(dir,x) }
28
+ FileUtils.cp_r(children, dst)
29
+ end
30
+
31
+ def cachekey
32
+ dig = Digest::SHA2.new
33
+ tar_io.each(1024) do |block|
34
+ dig << block
35
+ end
36
+ return dig.hexdigest
37
+ end
38
+ end
39
+
40
+ attr :url, :logger, :file_map
41
+
42
+ def initialize( url, options = {} )
43
+ @url = URI(url)
44
+ if @url.relative?
45
+ @url.path = File.expand_path(@url.path)
46
+ end
47
+ @logger = options.fetch(:logger){ Cabin::Channel.get }
48
+ @file_map = options.fetch(:file_map){ {'' => ''} }
49
+ end
50
+
51
+ def build_cache(_)
52
+ Cache.new(self, url.path)
53
+ end
54
+ end
55
+ end ; end ; end
56
+
@@ -0,0 +1,90 @@
1
+ require 'fileutils'
2
+ require 'forwardable'
3
+ require 'open3'
4
+ require 'fpm/fry/source'
5
+ module FPM; module Fry ; module Source
6
+ class Git
7
+
8
+ REGEX = %r!\A(?:git:|\S+@\S+:\S+\.git\z|https?:.*\.git\z|ssh:.*\.git\z)!
9
+
10
+ def self.guess( url )
11
+ Source::guess_regex(REGEX, url)
12
+ end
13
+
14
+ class Cache < Struct.new(:package, :tempdir)
15
+ extend Forwardable
16
+
17
+ def_delegators :package, :url, :rev, :logger, :file_map
18
+
19
+ def update
20
+ begin
21
+ if !File.exists? repodir
22
+ if git('init', '--bare') != 0
23
+ raise "Initializing git repository failed"
24
+ end
25
+ end
26
+ if git('fetch','--depth=1', url.to_s, rev) != 0
27
+ raise "Failed to fetch from remote #{url.to_s} ( #{rev} )"
28
+ end
29
+ return self
30
+ rescue Errno::ENOENT
31
+ raise "Cannot find git binary. Is it installed?"
32
+ end
33
+ end
34
+
35
+ def tar_io
36
+ cmd = [package.git, "--git-dir=#{repodir}",'archive','--format=tar','FETCH_HEAD']
37
+ logger.debug("Running git",cmd: cmd)
38
+ IO.popen(cmd)
39
+ end
40
+
41
+ def copy_to(dst)
42
+ cmd = [package.git, "--git-dir=#{repodir}", "--work-tree=#{dst}",'checkout','FETCH_HEAD','--','*']
43
+ logger.debug("Running git",cmd: cmd)
44
+ system(*cmd, chdir: dst)
45
+ end
46
+
47
+ def cachekey
48
+ cmd = [package.git, "--git-dir=#{repodir}",'rev-parse','FETCH_HEAD^{tree}']
49
+ logger.debug("Running git",cmd: cmd)
50
+ return IO.popen(cmd).read.chomp
51
+ end
52
+ private
53
+ def repodir
54
+ File.join(tempdir,File.basename(url.path))
55
+ end
56
+
57
+ def git(*args)
58
+ cmd = [package.git, "--git-dir=#{repodir}",*args]
59
+ logger.debug("Running git",cmd: cmd.join(' '))
60
+ Open3.popen3(*cmd) do |sin, out, err, thr|
61
+ sin.close
62
+ out.each_line do |line|
63
+ logger.debug(line.chomp)
64
+ end
65
+ err.each_line do |line|
66
+ logger.debug(line.chomp)
67
+ end
68
+ return thr.value
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ attr :logger, :git, :rev, :file_map, :url
75
+
76
+ def initialize( url, options = {} )
77
+ url = url.sub(/\A(\S+@\S+):(\S+\.git)\z/,'ssh://\1/\2')
78
+ @url = URI(url)
79
+ @logger = options.fetch(:logger){ Cabin::Channel.get }
80
+ @rev = options[:branch] || options[:tag] || options[:rev] || 'HEAD'
81
+ @file_map = options.fetch(:file_map){ {'' => ''} }
82
+ @git = options[:git] || 'git'
83
+ end
84
+
85
+ def build_cache(tempdir)
86
+ Cache.new(self, tempdir).update
87
+ end
88
+
89
+ end
90
+ end ; end ; end
@@ -0,0 +1,202 @@
1
+ require 'uri'
2
+ require 'digest'
3
+ require 'net/http'
4
+ require 'forwardable'
5
+ require 'zlib'
6
+ require 'fpm/fry/source'
7
+ module FPM; module Fry ; module Source
8
+ class Package
9
+
10
+ REGEX = %r!\Ahttps?:!
11
+
12
+ def self.guess( url )
13
+ Source::guess_regex(REGEX, url)
14
+ end
15
+
16
+ class RedirectError < CacheFailed
17
+ end
18
+
19
+ class Cache < Struct.new(:package,:tempdir)
20
+ extend Forwardable
21
+
22
+ def_delegators :package, :url, :checksum, :checksum_algorithm, :agent, :logger, :file_map
23
+
24
+ def initialize(*_)
25
+ super
26
+ if !checksum
27
+ update!
28
+ end
29
+ end
30
+
31
+ def cache_valid?
32
+ c = @observed_checksum || checksum
33
+ begin
34
+ checksum_algorithm.file(tempfile).hexdigest == c
35
+ rescue Errno::ENOENT
36
+ return false
37
+ end
38
+ end
39
+
40
+ def update!
41
+ if cache_valid?
42
+ logger.debug("Found valid cache", url: url, tempfile: tempfile)
43
+ return
44
+ end
45
+ d = checksum_algorithm.new
46
+ f = nil
47
+ fetch_url(url) do |resp|
48
+ begin
49
+ f = File.new(tempfile,'w')
50
+ resp.read_body do | chunk |
51
+ d.update(chunk)
52
+ f.write(chunk)
53
+ end
54
+ rescue => e
55
+ raise CacheFailed, e
56
+ ensure
57
+ f.close
58
+ end
59
+ end
60
+
61
+ @observed_checksum = d.hexdigest
62
+ logger.debug("got checksum", checksum: @observed_checksum)
63
+ if checksum
64
+ if d.hexdigest != checksum
65
+ raise CacheFailed.new("Checksum failed",given: d.hexdigest, expected: checksum)
66
+ end
67
+ else
68
+ return true
69
+ end
70
+ end
71
+
72
+ def fetch_url( url, redirs = 3, &block)
73
+ url = URI(url.to_s) unless url.kind_of? URI
74
+ Net::HTTP.get_response(url) do |resp|
75
+ case(resp)
76
+ when Net::HTTPRedirection
77
+ if redirs == 0
78
+ raise RedirectError, "Too many redirects"
79
+ end
80
+ logger.debug("Following redirect", url: url.to_s , location: resp['location'])
81
+ return fetch_url( resp['location'], redirs - 1, &block)
82
+ when Net::HTTPSuccess
83
+ return block.call(resp)
84
+ else
85
+ raise CacheFailed.new('Unable to fetch file',url: url.to_s, http_code: resp.code, http_message: resp.message)
86
+ end
87
+ end
88
+ end
89
+
90
+ def tempfile
91
+ File.join(tempdir,File.basename(url.path))
92
+ end
93
+
94
+ def cachekey
95
+ @observed_checksum || checksum
96
+ end
97
+
98
+ end
99
+
100
+ class TarCache < Cache
101
+
102
+ def tar_io
103
+ update!
104
+ ioclass.open(tempfile)
105
+ end
106
+
107
+ def copy_to(dst)
108
+ update!
109
+ cmd = ['tar','-xf',tempfile,'-C',dst]
110
+ logger.debug("Running tar",cmd: cmd)
111
+ system(*cmd)
112
+ end
113
+
114
+ protected
115
+ def ioclass
116
+ File
117
+ end
118
+ end
119
+
120
+ class TarGzCache < TarCache
121
+ protected
122
+
123
+ def ioclass
124
+ Zlib::GzipReader
125
+ end
126
+ end
127
+
128
+ class ZipCache < Cache
129
+
130
+ def tar_io
131
+ if !::File.directory?( unpacked_tmpdir )
132
+ workdir = unpacked_tmpdir + '.tmp'
133
+ begin
134
+ FileUtils.mkdir(workdir)
135
+ rescue Errno::EEXIST
136
+ FileUtils.rm_rf(workdir)
137
+ FileUtils.mkdir(workdir)
138
+ end
139
+ copy_to( workdir )
140
+ File.rename(workdir, unpacked_tmpdir)
141
+ end
142
+ cmd = ['tar','-c','.']
143
+ logger.debug("Running tar",cmd: cmd, dir: unpacked_tmpdir)
144
+ ::Dir.chdir(unpacked_tmpdir) do
145
+ return IO.popen(cmd)
146
+ end
147
+ end
148
+
149
+ def copy_to(dst)
150
+ update!
151
+ cmd = ['unzip', tempfile, '-d', dst ]
152
+ logger.debug("Running unzip",cmd: cmd)
153
+ system(*cmd, out: '/dev/null')
154
+ end
155
+
156
+ def unpacked_tmpdir
157
+ File.join(tempdir, cachekey)
158
+ end
159
+ end
160
+
161
+ CACHE_CLASSES = {
162
+ '.tar' => TarCache,
163
+ '.tar.gz' => TarGzCache,
164
+ '.tgz' => TarGzCache,
165
+ '.zip' => ZipCache
166
+ }
167
+
168
+ attr :file_map, :data, :url, :extension, :checksum, :checksum_algorithm, :agent, :logger
169
+
170
+ def initialize( url, options = {} )
171
+ @url = URI(url)
172
+ @extension = options.fetch(:extension){
173
+ CACHE_CLASSES.keys.find{|ext|
174
+ @url.path.end_with?(ext)
175
+ }
176
+ }
177
+ @logger = options.fetch(:logger){ Cabin::Channel.get }
178
+ @checksum = options[:checksum]
179
+ @checksum_algorithm = guess_checksum_algorithm(options[:checksum])
180
+ @file_map = options.fetch(:file_map){ {'' => ''} }
181
+ end
182
+
183
+ def build_cache(tempdir)
184
+ CACHE_CLASSES.fetch(extension).new(self, tempdir)
185
+ end
186
+ private
187
+
188
+ def guess_checksum_algorithm( checksum )
189
+ case(checksum)
190
+ when nil
191
+ return Digest::SHA256
192
+ when /\A(sha256:)?[0-9a-f]{64}\z/ then
193
+ return Digest::SHA256
194
+ when /\A(sha1:)?[0-9a-f]{40}\z/ then
195
+ return Digest::SHA1
196
+ else
197
+ raise "Unknown checksum algorithm"
198
+ end
199
+ end
200
+
201
+ end
202
+ end end end
@@ -0,0 +1,118 @@
1
+ require 'fpm/fry/tar'
2
+ require 'digest'
3
+ module FPM; module Fry ; module Source
4
+ class Patched
5
+
6
+ class Cache < Struct.new(:package, :tmpdir)
7
+ extend Forwardable
8
+
9
+ def_delegators :package, :logger, :file_map
10
+
11
+ attr :inner
12
+
13
+ def initialize(*_)
14
+ @updated = false
15
+ super
16
+ @inner = package.inner.build_cache(tmpdir)
17
+ end
18
+
19
+ def update!
20
+ @updated ||= begin
21
+ if !File.directory?(unpacked_tmpdir)
22
+ workdir = unpacked_tmpdir + '.tmp'
23
+ begin
24
+ FileUtils.mkdir(workdir)
25
+ rescue Errno::EEXIST
26
+ FileUtils.rm_rf(workdir)
27
+ FileUtils.mkdir(workdir)
28
+ end
29
+ if inner.respond_to? :copy_to
30
+ inner.copy_to(workdir)
31
+ else
32
+ ex = Tar::Extractor.new(logger: logger)
33
+ tio = inner.tar_io
34
+ begin
35
+ ex.extract(workdir, ::Gem::Package::TarReader.new(tio), chown: false)
36
+ ensure
37
+ tio.close
38
+ end
39
+ end
40
+ package.patches.each do |patch|
41
+ cmd = ['patch','-p1','-i',patch[:file]]
42
+ chdir = File.expand_path(patch.fetch(:chdir,'.'),workdir)
43
+ logger.debug("Running patch",cmd: cmd, dir: chdir )
44
+ system(*cmd, chdir: chdir, out: :close)
45
+ end
46
+ File.rename(workdir, unpacked_tmpdir)
47
+ end
48
+ true
49
+ end
50
+ end
51
+ private :update!
52
+
53
+ def tar_io
54
+ update!
55
+ cmd = ['tar','-c','.']
56
+ logger.debug("Running tar",cmd: cmd, dir: unpacked_tmpdir)
57
+ # IO.popen( ..., chdir: ... ) doesn't work on older ruby
58
+ ::Dir.chdir(unpacked_tmpdir) do
59
+ return IO.popen(cmd)
60
+ end
61
+ end
62
+
63
+ def cachekey
64
+ dig = Digest::SHA2.new
65
+ dig << inner.cachekey << "\x00"
66
+ package.patches.each do |patch|
67
+ dig.file(patch[:file])
68
+ dig << "\x00"
69
+ end
70
+ return dig.hexdigest
71
+ end
72
+
73
+ def unpacked_tmpdir
74
+ File.join(tmpdir, cachekey)
75
+ end
76
+
77
+ end
78
+
79
+ attr :inner, :patches
80
+
81
+ extend Forwardable
82
+
83
+ def_delegators :inner, :logger, :file_map
84
+
85
+ def initialize( inner , options = {})
86
+ @inner = inner
87
+ @patches = Array(options[:patches]).map do |file|
88
+ if file.kind_of? String
89
+ options = {file: file}
90
+ elsif file.kind_of? Hash
91
+ options = file.dup
92
+ else
93
+ raise ArgumentError, "Expected a Hash or a String, got #{file.inspect}"
94
+ end
95
+ options[:file] = File.expand_path(options[:file])
96
+ if !File.exists?(options[:file])
97
+ raise ArgumentError, "File doesn't exist: #{options[:file]}"
98
+ end
99
+ options
100
+ end
101
+ end
102
+
103
+ def build_cache(tmpdir)
104
+ Cache.new(self,tmpdir)
105
+ end
106
+
107
+ def self.decorate(options)
108
+ if options.key?(:patches) && Array(options[:patches]).size > 0
109
+ p = options.delete(:patches)
110
+ return new( yield(options), patches: p )
111
+ else
112
+ return yield options
113
+ end
114
+ end
115
+ end
116
+
117
+ end ; end ; end
118
+
@@ -0,0 +1,47 @@
1
+ module FPM; module Fry ; module Source
2
+
3
+ class CacheFailed < StandardError
4
+
5
+ attr :options
6
+
7
+ def initialize(e, opts = {})
8
+ if e.kind_of? Exception
9
+ @options = {reason: e}.merge opts
10
+ super(e.message)
11
+ else
12
+ @options = opts.dup
13
+ super(e.to_s)
14
+ end
15
+ end
16
+ end
17
+
18
+ module Null
19
+
20
+ module Cache
21
+ def self.tar_io
22
+ StringIO.new("\x00"*1024)
23
+ end
24
+ def self.file_map
25
+ return {}
26
+ end
27
+ def self.cachekey
28
+ return '0' * 32
29
+ end
30
+ end
31
+
32
+ def self.build_cache(*_)
33
+ return Cache
34
+ end
35
+
36
+ end
37
+
38
+ class << self
39
+
40
+ def guess_regex(rx, url)
41
+ if m = rx.match(url.to_s)
42
+ return m[0].size
43
+ end
44
+ end
45
+
46
+ end
47
+ end ; end ; end
@@ -0,0 +1,98 @@
1
+ require 'excon/middlewares/base'
2
+ module FPM; module Fry
3
+ class StreamParser
4
+
5
+ class ShortRead < EOFError
6
+ end
7
+
8
+ class Instance < Excon::Middleware::Base
9
+
10
+ def initialize(stack, parser)
11
+ super(stack)
12
+ @parser = parser
13
+ end
14
+
15
+ def response_call(datum)
16
+ if datum[:response]
17
+ # probably mocked
18
+ if datum[:response][:body]
19
+ @parser.parse(StringIO.new(datum[:response][:body]))
20
+ end
21
+ return @stack.response_call(datum)
22
+ else
23
+ socket = datum[:connection].send(:socket)
24
+ begin
25
+ line = socket.readline
26
+ match = /^HTTP\/\d+\.\d+\s(\d{3})\s/.match(line)
27
+ end while !match
28
+ status = match[1].to_i
29
+
30
+ datum[:response] = {
31
+ :body => '',
32
+ :headers => Excon::Headers.new,
33
+ :status => status,
34
+ :remote_ip => socket.respond_to?(:remote_ip) && socket.remote_ip,
35
+ }
36
+ Excon::Response.parse_headers(socket, datum)
37
+
38
+ @parser.parse(socket)
39
+ return @stack.response_call(datum)
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ attr :out, :err
46
+
47
+ def initialize(out, err)
48
+ @out, @err = out, err
49
+ @state = :null
50
+ @left = 0
51
+ end
52
+
53
+ def new(stack)
54
+ Instance.new(stack, self)
55
+ end
56
+
57
+ def parse(socket)
58
+ left = 0
59
+ streams = {1 => out, 2 => err}
60
+ loop do
61
+ type = read_exactly(socket,4){|part|
62
+ if part.bytesize == 0
63
+ return
64
+ else
65
+ raise ShortRead
66
+ end
67
+ }.unpack("c".freeze)[0]
68
+ stream = streams.fetch(type){ raise ArgumentError, "Wrong stream type: #{type}"}
69
+ len = read_exactly(socket,4).unpack('I>')[0]
70
+ while len > 0
71
+ chunk = socket.read([64,len].min)
72
+ raise ShortRead if chunk.nil?
73
+ len -= chunk.bytesize
74
+ stream.write(chunk)
75
+ end
76
+ end
77
+ end
78
+
79
+ def read_exactly(socket, len)
80
+ buf = ""
81
+ left = len
82
+ while left != 0
83
+ read = socket.read(left)
84
+ if read.nil?
85
+ if block_given?
86
+ yield buf
87
+ else
88
+ raise ShortRead
89
+ end
90
+ end
91
+ buf << read
92
+ left = len - buf.bytesize
93
+ end
94
+ return buf
95
+ end
96
+
97
+ end
98
+ end ; end
@@ -0,0 +1,71 @@
1
+ module FPM; module Fry; end ; end
2
+
3
+ class FPM::Fry::Tar
4
+
5
+ class Extractor
6
+
7
+ def initialize( options = {} )
8
+ @logger = options.fetch(:logger){ Cabin::Channel.get }
9
+ end
10
+
11
+ def extract(destdir, reader, options = {})
12
+ reader.each do |entry|
13
+ extract_entry(File.join(destdir, entry.full_name), entry, options)
14
+ end
15
+ end
16
+
17
+ def extract_entry(dest, entry, options = {})
18
+ full_name = entry.full_name
19
+ mode = entry.header.mode
20
+
21
+ destdir = File.dirname(dest)
22
+ uid = map_user(entry.header.uid, entry.header.uname)
23
+ gid = map_group(entry.header.gid, entry.header.gname)
24
+
25
+ @logger.debug('Extracting','file' => dest, 'uid'=> uid, 'gid' => gid, 'entry.fullname' => full_name, 'entry.mode' => mode )
26
+
27
+ case(entry.header.typeflag)
28
+ when "5" # Directory
29
+ FileUtils.mkdir_p(dest, :mode => mode)
30
+ when "2" # Symlink
31
+ destdir = File.dirname(dest)
32
+ FileUtils.mkdir_p(destdir, :mode => 0755)
33
+ File.symlink( entry.header.linkname, dest )
34
+ when "0" # File
35
+ destdir = File.dirname(dest)
36
+ FileUtils.mkdir_p(destdir, :mode => 0755)
37
+ File.open(dest, "wb", entry.header.mode) do |os|
38
+ loop do
39
+ data = entry.read(4096)
40
+ break unless data
41
+ os.write(data)
42
+ end
43
+ os.fsync
44
+ end
45
+ else
46
+ @logger.warn('Ignoring unknown tar entry',name: full_name)
47
+ return
48
+ end
49
+ FileUtils.chmod(entry.header.mode, dest)
50
+ chown( uid, gid, dest ) if options.fetch(:chown,true)
51
+ end
52
+
53
+ def chown( uid, gid, path )
54
+ FileUtils.chown( uid, gid, path )
55
+ rescue Errno::EPERM
56
+ @logger.warn('Unable to chown file', 'file' => path, 'uid' => uid, 'gid' => gid)
57
+ end
58
+
59
+ def map_user( uid, _ )
60
+ return uid
61
+ end
62
+
63
+ def map_group( gid, _ )
64
+ return gid
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+ case "$1" in
3
+ configure)
4
+ <%= configure.join("\n") %>
5
+ ;;
6
+ *)
7
+ exit 1
8
+ ;;
9
+ esac
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+
3
+ case "$1" in
4
+ install)
5
+ <%= install.join("\n") %>
6
+ ;;
7
+ upgrade)
8
+ <%= upgrade.join("\n") %>
9
+ ;;
10
+ *)
11
+ exit 1
12
+ ;;
13
+ esac