vagabund 0.0.20

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.
@@ -0,0 +1,48 @@
1
+ module Vagabund
2
+ module Settler
3
+ module Errors
4
+ class SettlerError < Vagrant::Errors::VagrantError
5
+ attr_reader :original_error
6
+
7
+ error_namespace "vagabund.settler.errors"
8
+
9
+ def message(orig=true)
10
+ return super() if !orig || original_error.nil?
11
+ "#{original_error.class.name}: #{original_error.message}"
12
+ end
13
+
14
+ def backtrace(orig=true)
15
+ !orig || original_error.nil? ? super() : original_error.backtrace
16
+ end
17
+
18
+ def initialize(*args)
19
+ @original_error = args.shift if args.first.is_a?(Exception)
20
+ super(*args)
21
+ end
22
+ end
23
+
24
+ class PackageError < SettlerError; end
25
+ class ProjectError < SettlerError; end
26
+
27
+ class PackageBuildError < PackageError
28
+ error_key :package_build_error
29
+ end
30
+
31
+ class PackageCleanError < PackageError
32
+ error_key :package_clean_error
33
+ end
34
+
35
+ class PackageExtractionError < PackageError
36
+ error_key :package_extraction_error
37
+ end
38
+
39
+ class PackageInstallError < PackageError
40
+ error_key :package_install_error
41
+ end
42
+
43
+ class PackagePullError < PackageError
44
+ error_key :package_pull_error
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,215 @@
1
+ require_relative 'package_config'
2
+
3
+ module Vagabund
4
+ module Settler
5
+ module Packages
6
+ class Base
7
+ attr_reader :config
8
+
9
+ def provision(machine)
10
+ exec_before :package, machine
11
+
12
+ if skip?
13
+ machine.ui.warn "Skipping package #{name}-#{version} because skip flag was set."
14
+ return
15
+ end
16
+
17
+ pull machine
18
+ extract machine
19
+ build machine
20
+ install machine
21
+ clean machine
22
+
23
+ exec_after :package, machine
24
+ end
25
+
26
+ def build(machine)
27
+ exec_before :build, machine
28
+ machine.ui.detail "Building #{name}-#{version}..."
29
+ action_exec config.builder, machine
30
+ exec_after :build, machine
31
+ rescue StandardError => e
32
+ raise Settler::Errors::PackageBuildError, e
33
+ end
34
+
35
+ def clean(machine)
36
+ exec_before :clean, machine
37
+ machine.ui.detail "Cleaning up after #{name}-#{version}..."
38
+ action_exec config.cleaner, machine
39
+ exec_after :clean, machine
40
+ rescue StandardError => e
41
+ raise Settler::Errors::PackageCleanError, e
42
+ end
43
+
44
+ def extract(machine)
45
+ exec_before :extract, machine
46
+ machine.ui.detail "Unpacking #{name}-#{version}..."
47
+ action_exec config.extractor, machine
48
+ exec_after :extract, machine
49
+ rescue StandardError => e
50
+ raise Settler::Errors::PackageExtractionError, e
51
+ end
52
+
53
+ def install(machine)
54
+ exec_before :install, machine
55
+ machine.ui.detail "Installing #{name}-#{version}..."
56
+ action_exec config.installer, machine
57
+ exec_after :install, machine
58
+ rescue StandardError => e
59
+ raise Settler::Errors::PackageInstallError, e
60
+ end
61
+
62
+ def pull(machine)
63
+ exec_before :pull, machine
64
+ machine.ui.detail "Retrieving sources for #{name}-#{version}..."
65
+ action_exec config.puller, machine
66
+ exec_after :pull, machine
67
+ rescue StandardError => e
68
+ raise Settler::Errors::PackagePullError, e
69
+ end
70
+
71
+ def exec_before(action, machine)
72
+ hook_exec :before, action, machine
73
+ end
74
+
75
+ def exec_after(action, machine)
76
+ hook_exec :after, action, machine
77
+ end
78
+
79
+ def hook_exec(hook, action, machine)
80
+ hook_action = "#{hook.to_s}_#{action.to_s.gsub(/[eo]r$/, '')}"
81
+ return if config.send(hook_action).nil? || config.send(hook_action).empty?
82
+
83
+ machine.ui.detail "Executing custom :#{hook_action} hooks for package #{name}-#{version}..."
84
+ config.send(hook_action).each do |hact|
85
+ action_exec hact, machine
86
+ end
87
+ rescue StandardError => e
88
+ raise Settler::Errors::PackageError, e
89
+ end
90
+
91
+ def action_exec(command, machine)
92
+ self.class.instance_eval do
93
+ [:ask, :detail, :error, :info, :output, :warn].each do |cmd|
94
+ define_method cmd do |*args, &block|
95
+ machine.ui.send cmd, *args, &block
96
+ end
97
+ end
98
+
99
+ [:execute, :sudo, :test].each do |cmd|
100
+ define_method cmd do |*args, &block|
101
+ opts = {verbose: false}.merge(args.extract_options!)
102
+ if opts[:verbose] == true
103
+ machine.communicate.send cmd, *args, opts do |type,data|
104
+ color = type == :stderr ? :red : :green
105
+ options = {
106
+ color: color,
107
+ new_line: false,
108
+ prefix: false
109
+ }
110
+
111
+ detail(data, options)
112
+ block.call(type, data) unless block.nil?
113
+ end
114
+ else
115
+ machine.communicate.send cmd, *args, opts, &block
116
+ end
117
+ end
118
+ end
119
+
120
+ define_method :capture do |*args, &block|
121
+ output = ''
122
+ machine.communicate.execute *args do |type,data|
123
+ output += data if type == :stdout
124
+ block.call(type, data) unless block.nil?
125
+ end
126
+ output
127
+ end
128
+ end
129
+
130
+ instance_exec self, machine, machine.communicate, &command if command.is_a?(Proc)
131
+
132
+ self.class.instance_eval do
133
+ [:ask, :detail, :error, :info, :output, :warn, :capture, :execute, :sudo, :test].each do |cmd|
134
+ undef_method cmd
135
+ end
136
+ end
137
+ end
138
+
139
+ def configure(&block)
140
+ config.configure &block
141
+ end
142
+
143
+ def local_package
144
+ config.local_package
145
+ end
146
+ alias_method :local_file, :local_package
147
+
148
+ def build_path
149
+ config.build_path
150
+ end
151
+
152
+ def build_root
153
+ config.build_root
154
+ end
155
+
156
+ def name
157
+ config.name
158
+ end
159
+
160
+ def version
161
+ config.version
162
+ end
163
+
164
+ def source
165
+ config.source
166
+ end
167
+
168
+ def skip(s)
169
+ @skip = s unless s.nil?
170
+ @skip
171
+ end
172
+ alias_method :skip=, :skip
173
+
174
+ def skip?
175
+ @skip
176
+ end
177
+
178
+ protected
179
+
180
+ #
181
+ # Base.new 'poppler', '0.24.5', {url: 'http://poppler.freedesktop.org/poppler-0.24.5.tar.xz'}
182
+ #
183
+ # Supported source types:
184
+ # git: 'git url'
185
+ # local: '/path/to/local/file'
186
+ # url: 'http://example.com/path/to/file'
187
+ # url: 'ftp://user:pass@example.com/path/to/file'
188
+ # scp: '[user@]example.com:/path/to/file' # this might require ssh forwarding
189
+ def initialize(*args, &block)
190
+ opts = args.extract_options!
191
+ opts = {name: args.shift, version: args.shift}.merge(opts)
192
+ @config = PackageConfig.new(opts, &block)
193
+ end
194
+
195
+ def build_path_exists?(machine)
196
+ return machine.communicate.test("[ -d #{build_path} ]") ? true : false
197
+ end
198
+
199
+ def package_exists?(machine)
200
+ return machine.communicate.test("[ -f #{existing_package_file(machine)} ]") ? true : false
201
+ end
202
+
203
+ def existing_package_file(machine)
204
+ pkg_file = local_file
205
+
206
+ while !machine.communicate.test("[ -f #{pkg_file} ]") && !File.extname(pkg_file).empty? do
207
+ pkg_file = File.join(build_root, File.basename(pkg_file, File.extname(pkg_file)))
208
+ end
209
+ pkg_file
210
+ end
211
+
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,39 @@
1
+ module Vagabund
2
+ module Settler
3
+ module Packages
4
+ class Config
5
+
6
+ def packages
7
+ @packages ||= []
8
+ end
9
+
10
+ def add_package(*args, &block)
11
+ if args.first.is_a?(Packages::Base)
12
+ pkg = args.shift
13
+ pkg.configure &block if block_given?
14
+ packages << pkg
15
+ else
16
+ add_package Package.new(*args, &block)
17
+ end
18
+ end
19
+ alias_method :package, :add_package
20
+ alias_method :package=, :add_package
21
+
22
+ def method_missing(meth, *args, &block)
23
+ packages.send meth, *args, &block
24
+ end
25
+
26
+ def respond_to_missing?(meth, include_private=false)
27
+ packages.respond_to? meth, include_private
28
+ end
29
+
30
+ protected
31
+
32
+ def initialize(*args)
33
+ @settler_config = args.shift if args.first.is_a?(Settler::Config)
34
+ @packages = args.shift if args.first.is_a?(Array)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,118 @@
1
+ module Vagabund
2
+ module Settler
3
+ module Packages
4
+ class PackageConfig
5
+ attr_reader :config, :source
6
+
7
+ # Bit of metaprogramming to define methods like builder, installer,
8
+ # before_build, after_install, etc.
9
+ %w(package builder cleaner extractor installer puller).each do |action|
10
+ %w(before after).each do |hook|
11
+ hook_action = "#{hook}_#{action.gsub(/[eo]r$/, '')}"
12
+
13
+ # Defines before/after 'hook' methods for each action: before_build,
14
+ # before_pull, after_install, etc.
15
+ define_method hook_action.to_sym do |*args, &block|
16
+ if args.first.is_a?(String)
17
+ command = args.shift
18
+ opts = args.extract_options!
19
+
20
+ cmd_proc = Proc.new do |package, machine, channel|
21
+ cmd = "cd #{package.build_path}; #{command}"
22
+ execute cmd, {verbose: true}.merge(opts)
23
+ end
24
+
25
+ config.send "#{hook_action}=".to_sym, [] if config.send(hook_action.to_sym).nil?
26
+ config.send(hook_action.to_sym) << cmd_proc
27
+ end
28
+
29
+ if !args.empty? && (args.first.nil? || args.first.is_a?(Proc))
30
+ config.send "#{hook_action}=".to_sym, [] if config.send(hook_action.to_sym).nil?
31
+ config.send(hook_action.to_sym) << args.shift
32
+ end
33
+
34
+ if !block.nil? # block_given? doesn't work here
35
+ config.send "#{hook_action}=".to_sym, [] if config.send(hook_action.to_sym).nil?
36
+ config.send(hook_action.to_sym) << block
37
+ end
38
+
39
+ config.send "#{hook_action}".to_sym
40
+ end
41
+ end
42
+
43
+ if action == 'package'
44
+ alias_method :before, :before_package
45
+ alias_method :after, :after_package
46
+ next
47
+ end
48
+
49
+ # Defines custom action methods to override the built-in puller,
50
+ # extractor, builder, installer and cleaner.
51
+ define_method action.to_sym do |*args, &block|
52
+ if args.first.is_a?(String)
53
+ command = args.shift
54
+ opts = args.extract_options!
55
+
56
+ cmd_proc = Proc.new do |package, machine, channel|
57
+ cmd = "cd #{package.build_path}; #{command}"
58
+ execute cmd, {verbose: true}.merge(opts)
59
+ end
60
+
61
+ config.send "#{action}=".to_sym, cmd_proc
62
+ end
63
+
64
+ config.send "#{action}=".to_sym, args.shift if !args.empty? && (args.first.nil? || args.first.is_a?(Proc))
65
+ config.send "#{action}=".to_sym, block if !block.nil? # block_given? doesn't work here
66
+
67
+ config.send action.to_sym
68
+ end
69
+ alias_method "#{action}=".to_sym, action.to_sym
70
+ alias_method "#{action.gsub(/[eo]r$/, '')}_with".to_sym, action.to_sym
71
+ end
72
+
73
+ def build_root
74
+ config.build_root ||= "/tmp/#{name}-#{version}"
75
+ end
76
+
77
+ def build_path
78
+ config.build_path ||= File.join(build_root, "#{name}-#{version}")
79
+ end
80
+
81
+ def local_package
82
+ config.local_package ||= File.join(build_root, (File.basename(source.origin) rescue "#{name}-#{version}"))
83
+ end
84
+ alias_method :local_file, :local_package
85
+
86
+ def configure(&block)
87
+ instance_eval &block if block_given?
88
+ end
89
+
90
+ def method_missing(meth, *args, &block)
91
+ config.send meth, *args, &block
92
+ end
93
+
94
+ def respond_to_missing?(meth, include_private=false)
95
+ config.respond_to? meth, include_private
96
+ end
97
+
98
+ protected
99
+
100
+ def initialize(*args, &block)
101
+ @config = OpenStruct.new({builder: Package::BUILDER, cleaner: Package::CLEANER, extractor: Package::EXTRACTOR, installer: Package::INSTALLER, puller: Package::PULLER}.merge(args.extract_options!))
102
+
103
+ if config.respond_to?(:git)
104
+ @source = Sources::Git.new(config.git)
105
+ elsif config.respond_to?(:url)
106
+ @source = Sources::Url.new(config.url)
107
+ elsif config.respond_to?(:local)
108
+ @source = Sources::Local.new(config.local)
109
+ #elsif config.respond_to?(:scp)
110
+ # remote scp
111
+ end
112
+
113
+ configure &block if block_given?
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,101 @@
1
+ require_relative 'errors'
2
+ require_relative 'packages/base'
3
+
4
+ module Vagabund
5
+ module Settler
6
+ module Packages
7
+ end
8
+
9
+ class Package < Packages::Base
10
+ EXTENSIONS = ['.gz', '.bz', '.bz2', '.xz', '.zip', '.tar', '.tgz', '.tbz', '.tbz2', '.txz']
11
+
12
+ BUILDER = Proc.new do |package, machine, channel|
13
+ execute "cd #{build_path}; ./configure && make", verbose: true
14
+ end
15
+
16
+ CLEANER = Proc.new do |package, machine, channel|
17
+ sudo "rm -rf #{build_root}"
18
+ end
19
+
20
+ EXTRACTOR = Proc.new do |package, machine, channel|
21
+ if build_path_exists?(machine)
22
+ machine.ui.warn "Build path #{build_path} already exists, using it for the build. If you would like to use a clean source tree, you should manually remove it and run `vagrant provision` again."
23
+ elsif File.directory?(local_package)
24
+ execute "cp -r #{local_package} #{build_path}" if local_package != build_path
25
+ else
26
+ execute "mkdir -p #{build_path}"
27
+ local_ext = File.extname(local_package)
28
+
29
+ case local_ext
30
+ when '.gz'
31
+ execute "cd #{build_root}; gzip -dc #{local_package} > #{build_path}/#{File.basename(local_package, local_ext)}"
32
+ when '.tgz'
33
+ execute "cd #{build_root}; gzip -dc #{local_package} > #{build_path}/#{File.basename(local_package, local_ext)}.tar"
34
+ when '.bz', '.bz2'
35
+ execute "cd #{build_root}; bzip2 -dc #{local_package} > #{build_path}/#{File.basename(local_package, local_ext)}"
36
+ when '.tbz', '.tbz2'
37
+ execute "cd #{build_root}; bzip2 -dc #{local_package} > #{build_path}/#{File.basename(local_package, local_ext)}.tar"
38
+ when '.xz'
39
+ execute "cd #{build_root}; xz -dc #{local_package} > #{build_path}/#{File.basename(local_package, local_ext)}"
40
+ when '.txz'
41
+ execute "cd #{build_root}; xz -dc #{local_package} > #{build_path}/#{File.basename(local_package, local_ext)}.tar"
42
+ when '.zip'
43
+ execute "cd #{build_root}; unzip #{local_package} -d #{build_path}"
44
+ execute("cd #{build_path}; mv #{File.basename(local_package, local_ext)}/* ./") rescue nil
45
+ execute("cd #{build_path}; mv #{File.basename(local_package, local_ext)}/.* ./") rescue nil
46
+ execute("cd #{build_path}; mv #{name}-#{version}/* ./") rescue nil
47
+ execute("cd #{build_path}; mv #{name}-#{version}/.* ./") rescue nil
48
+ execute("cd #{build_path}; rm -rf #{File.basename(local_package, local_ext)}") rescue nil
49
+ when '.tar'
50
+ begin
51
+ execute "cd #{build_root}; tar xf #{local_package} #{File.basename(local_package, local_ext)} -C #{build_path}"
52
+ rescue
53
+ begin
54
+ execute "cd #{build_root}; tar xf #{local_package} #{name}-#{version} -C #{build_path}"
55
+ rescue
56
+ execute "cd #{build_root}; tar xf #{local_package} -C #{build_path}"
57
+ end
58
+ end
59
+ end
60
+
61
+ build_files = ""
62
+ execute "cd #{build_path}; ls" do |type, data|
63
+ build_files = data
64
+ end
65
+
66
+ if build_files.split($/).length == 1
67
+ new_package_file = File.basename(build_files.chomp)
68
+ if Package::EXTENSIONS.include?(File.extname(new_package_file))
69
+ execute "mv #{File.join(build_path, new_package_file)} #{build_root}"
70
+ sudo "rm -rf #{local_package} #{build_path}"
71
+ config.local_package = File.join(build_root, new_package_file)
72
+
73
+ # Re-execute this proc directly instead of going back through extract() or action_exec()
74
+ detail "Unpacking #{local_package}..."
75
+ instance_exec self, machine, machine.communicate, &EXTRACTOR
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+
82
+ INSTALLER = Proc.new do |package, machine, channel|
83
+ sudo "cd #{build_path}; make install", verbose: true
84
+ end
85
+
86
+ PULLER = Proc.new do |package, machine, channel|
87
+ if package_exists?(machine)
88
+ config.local_package = existing_package_file(machine)
89
+ machine.ui.warn "Package #{local_package} already exists, using it for the build. If you would like to re-download the package, you should manually remove it then run `vagrant provision` again."
90
+ else
91
+ source.pull machine, local_package
92
+ end
93
+ end
94
+
95
+ def self.new(*args, &block)
96
+ Packages::Base.new(*args, &block)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
@@ -0,0 +1,120 @@
1
+ require_relative 'project_config'
2
+
3
+ module Vagabund
4
+ module Settler
5
+ module Projects
6
+ class Base
7
+ attr_reader :config
8
+
9
+ def provision(machine)
10
+ exec_before :project, machine
11
+ pull machine
12
+ exec_after :project, machine
13
+ end
14
+
15
+ def pull(machine)
16
+ exec_before :pull, machine
17
+ if config.puller.nil?
18
+ config.source.pull machine, project_path
19
+ else
20
+ action_exec config.puller, machine
21
+ end
22
+ exec_after :pull, machine
23
+ rescue StandardError => e
24
+ raise Settler::Errors::ProjectError, e
25
+ end
26
+
27
+ def exec_before(action, machine)
28
+ hook_exec :before, action, machine
29
+ end
30
+
31
+ def exec_after(action, machine)
32
+ hook_exec :after, action, machine
33
+ end
34
+
35
+ def hook_exec(hook, action, machine)
36
+ hook_action = "#{hook.to_s}_#{action.to_s.gsub(/[eo]r$/, '')}"
37
+ return if config.send(hook_action).nil? || config.send(hook_action).empty?
38
+
39
+ machine.ui.detail "Executing custom :#{hook_action} hooks for project #{name}..."
40
+ config.send(hook_action).each do |hact|
41
+ action_exec hact, machine
42
+ end
43
+ rescue StandardError => e
44
+ raise Settler::Errors::ProjectError, e
45
+ end
46
+
47
+ def action_exec(command, machine)
48
+ self.class.instance_eval do
49
+ [:ask, :detail, :error, :info, :output, :warn].each do |cmd|
50
+ define_method cmd do |*args, &block|
51
+ machine.ui.send cmd, *args, &block
52
+ end
53
+ end
54
+ [:execute, :sudo, :test].each do |cmd|
55
+ define_method cmd do |*args, &block|
56
+ opts = {verbose: false}.merge(args.extract_options!)
57
+ if opts[:verbose] == true
58
+ machine.communicate.send cmd, *args, opts do |type,data|
59
+ color = type == :stderr ? :red : :green
60
+ options = {
61
+ color: color,
62
+ new_line: false,
63
+ prefix: false
64
+ }
65
+
66
+ detail(data, options)
67
+ block.call(type, data) unless block.nil?
68
+ end
69
+ else
70
+ machine.communicate.send cmd, *args, opts, &block
71
+ end
72
+ end
73
+ end
74
+
75
+ define_method :capture do |*args, &block|
76
+ output = ''
77
+ machine.communicate.execute *args do |type,data|
78
+ output += data if type == :stdout
79
+ block.call(type, data) unless block.nil?
80
+ end
81
+ output
82
+ end
83
+ end
84
+
85
+ instance_exec self, machine, machine.communicate, &command if command.is_a?(Proc)
86
+
87
+ self.class.instance_eval do
88
+ [:ask, :detail, :error, :info, :output, :warn, :capture, :execute, :sudo, :test].each do |cmd|
89
+ undef_method cmd
90
+ end
91
+ end
92
+ end
93
+
94
+ def configure(&block)
95
+ config.configure &block
96
+ end
97
+
98
+ def name
99
+ config.name
100
+ end
101
+
102
+ def project_path
103
+ config.project_path
104
+ end
105
+
106
+ protected
107
+
108
+ #
109
+ # Base.new 'my_project', {git: 'git@github.com:/user/repo.git'}
110
+ #
111
+ def initialize(*args, &block)
112
+ opts = args.extract_options!
113
+ opts = {name: args.shift}.merge(opts)
114
+ @config = ProjectConfig.new(opts, &block)
115
+ end
116
+
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,51 @@
1
+ module Vagabund
2
+ module Settler
3
+ module Projects
4
+ class Config
5
+
6
+ def projects_path
7
+ @projects_path ||= '/vagrant'
8
+ end
9
+ alias_method :path, :projects_path
10
+
11
+ def projects_path=(path)
12
+ @projects_path = path
13
+ end
14
+ alias_method :path=, :projects_path=
15
+
16
+ def projects
17
+ @projects ||= []
18
+ end
19
+
20
+ def add_project(*args, &block)
21
+ if args.first.is_a?(Projects::Base)
22
+ prj = args.shift
23
+ prj.config.projects_path ||= projects_path
24
+ prj.configure &block if block_given?
25
+ projects << prj
26
+ else
27
+ args.push({projects_path: projects_path}.merge(args.extract_options!))
28
+ add_project Project.new(*args, &block)
29
+ end
30
+ end
31
+ alias_method :project, :add_project
32
+ alias_method :project=, :add_project
33
+
34
+ def method_missing(meth, *args, &block)
35
+ projects.send meth, *args, &block
36
+ end
37
+
38
+ def respond_to_missing?(meth, include_private=false)
39
+ projects.respond_to? meth, include_private
40
+ end
41
+
42
+ protected
43
+
44
+ def initialize(*args)
45
+ @settler_config = args.shift if args.first.is_a?(Settler::Config)
46
+ @projects = args.shift if args.first.is_a?(Array)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end