vanagon 0.3.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +13 -0
  3. data/README.md +175 -0
  4. data/bin/build +33 -0
  5. data/bin/devkit +22 -0
  6. data/bin/repo +26 -0
  7. data/bin/ship +15 -0
  8. data/lib/vanagon.rb +8 -0
  9. data/lib/vanagon/common.rb +2 -0
  10. data/lib/vanagon/common/pathname.rb +87 -0
  11. data/lib/vanagon/common/user.rb +25 -0
  12. data/lib/vanagon/component.rb +157 -0
  13. data/lib/vanagon/component/dsl.rb +307 -0
  14. data/lib/vanagon/component/source.rb +66 -0
  15. data/lib/vanagon/component/source/git.rb +60 -0
  16. data/lib/vanagon/component/source/http.rb +158 -0
  17. data/lib/vanagon/driver.rb +112 -0
  18. data/lib/vanagon/engine/base.rb +82 -0
  19. data/lib/vanagon/engine/docker.rb +40 -0
  20. data/lib/vanagon/engine/local.rb +40 -0
  21. data/lib/vanagon/engine/pooler.rb +85 -0
  22. data/lib/vanagon/errors.rb +28 -0
  23. data/lib/vanagon/extensions/string.rb +11 -0
  24. data/lib/vanagon/optparse.rb +62 -0
  25. data/lib/vanagon/platform.rb +245 -0
  26. data/lib/vanagon/platform/deb.rb +71 -0
  27. data/lib/vanagon/platform/dsl.rb +293 -0
  28. data/lib/vanagon/platform/osx.rb +100 -0
  29. data/lib/vanagon/platform/rpm.rb +76 -0
  30. data/lib/vanagon/platform/rpm/wrl.rb +39 -0
  31. data/lib/vanagon/platform/solaris_10.rb +182 -0
  32. data/lib/vanagon/platform/solaris_11.rb +138 -0
  33. data/lib/vanagon/platform/swix.rb +35 -0
  34. data/lib/vanagon/project.rb +251 -0
  35. data/lib/vanagon/project/dsl.rb +218 -0
  36. data/lib/vanagon/utilities.rb +299 -0
  37. data/spec/fixures/component/invalid-test-fixture.json +3 -0
  38. data/spec/fixures/component/mcollective.service +1 -0
  39. data/spec/fixures/component/test-fixture.json +4 -0
  40. data/spec/lib/vanagon/common/pathname_spec.rb +103 -0
  41. data/spec/lib/vanagon/common/user_spec.rb +36 -0
  42. data/spec/lib/vanagon/component/dsl_spec.rb +443 -0
  43. data/spec/lib/vanagon/component/source/git_spec.rb +19 -0
  44. data/spec/lib/vanagon/component/source/http_spec.rb +43 -0
  45. data/spec/lib/vanagon/component/source_spec.rb +99 -0
  46. data/spec/lib/vanagon/component_spec.rb +22 -0
  47. data/spec/lib/vanagon/engine/base_spec.rb +40 -0
  48. data/spec/lib/vanagon/engine/docker_spec.rb +40 -0
  49. data/spec/lib/vanagon/engine/pooler_spec.rb +54 -0
  50. data/spec/lib/vanagon/platform/deb_spec.rb +60 -0
  51. data/spec/lib/vanagon/platform/dsl_spec.rb +128 -0
  52. data/spec/lib/vanagon/platform/rpm_spec.rb +41 -0
  53. data/spec/lib/vanagon/platform/solaris_11_spec.rb +44 -0
  54. data/spec/lib/vanagon/platform_spec.rb +53 -0
  55. data/spec/lib/vanagon/project/dsl_spec.rb +203 -0
  56. data/spec/lib/vanagon/project_spec.rb +44 -0
  57. data/spec/lib/vanagon/utilities_spec.rb +140 -0
  58. data/templates/Makefile.erb +116 -0
  59. data/templates/deb/changelog.erb +5 -0
  60. data/templates/deb/conffiles.erb +3 -0
  61. data/templates/deb/control.erb +21 -0
  62. data/templates/deb/dirs.erb +3 -0
  63. data/templates/deb/docs.erb +1 -0
  64. data/templates/deb/install.erb +3 -0
  65. data/templates/deb/postinst.erb +46 -0
  66. data/templates/deb/postrm.erb +15 -0
  67. data/templates/deb/prerm.erb +17 -0
  68. data/templates/deb/rules.erb +25 -0
  69. data/templates/osx/postinstall.erb +24 -0
  70. data/templates/osx/preinstall.erb +19 -0
  71. data/templates/osx/project-installer.xml.erb +19 -0
  72. data/templates/rpm/project.spec.erb +217 -0
  73. data/templates/solaris/10/depend.erb +3 -0
  74. data/templates/solaris/10/pkginfo.erb +13 -0
  75. data/templates/solaris/10/postinstall.erb +37 -0
  76. data/templates/solaris/10/preinstall.erb +7 -0
  77. data/templates/solaris/10/preremove.erb +6 -0
  78. data/templates/solaris/10/proto.erb +5 -0
  79. data/templates/solaris/11/p5m.erb +73 -0
  80. metadata +172 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0273c4745ecf7c50f369b6ea518caf46b92c8e07
4
+ data.tar.gz: 06437a1d3f2838cfd97d673fe2f82981ca917df0
5
+ SHA512:
6
+ metadata.gz: 2664084d24f35b26e7b30b4ab20c0ee910281af1722ac82363696de47af77962eb1f9cd3980f3d6af8a3aa10a0472f890f27eae66557c0c5a0aadeca96007852
7
+ data.tar.gz: f27159049e709a19879702636296d27ab31d2c40455f0c11675616a75a3c96411a017f9fefc1fec0ee460dbd4c0443a64e5f6549dbe3a48fc009f28f4d0cc551
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2014-2015 Puppet Labs
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,175 @@
1
+ ![Build Status](https://magnum.travis-ci.com/puppetlabs/vanagon.svg?token=A9NWBM3ogJqUCfos2gVF&branch=master)
2
+ The Vanagon Project
3
+ ===
4
+ * What is vanagon?
5
+ * Runtime requirements
6
+ * Configuration and Usage
7
+ * Overview
8
+ * Contributing
9
+ * License
10
+ * Maintainers
11
+
12
+ What is vanagon?
13
+ ---
14
+ Vanagon is a tool to build a single package out of a project, which can itself
15
+ contain one or more components. This tooling is being used to develop the
16
+ puppet-agent package, which contains components such as openssl, ruby, and
17
+ augeas among others. For a simple example, please see the examples directory.
18
+
19
+ Vanagon builds up a Makefile and packaging files (specfile for RPM,
20
+ control/rules/etc for DEB) and copies them to a remote host, where make can be
21
+ invoked to build all of the components and make a package of the contents.
22
+
23
+ Vanagon also provides a devkit command that will prepare a machine as a
24
+ development environment for the entire project, or restricted to individual
25
+ components of the project. The devkit command installs all required build tools,
26
+ creates a master makefile for the project, and configures, builds, and installs
27
+ all components. The result is an environment where you can work on individual
28
+ components, then rebuild the project and test the installed artifacts.
29
+
30
+ Runtime Requirements
31
+ ---
32
+ Vanagon is self-contained. A recent version of ruby should be all that is
33
+ required. Beyond that, ssh, rsync and git are also required on the host, and
34
+ ssh-server and rsync is required on the target (package installation for the
35
+ target can be customized in the platform config for the target).
36
+
37
+ Configuration and Usage
38
+ ---
39
+ Vanagon won't be much use without a project to build. Beyond that, you must
40
+ define any platforms you want to build for. Vanagon ships with some simple
41
+ binaries to use, but the one you probably care about is named 'build'.
42
+
43
+ ### `build` usage
44
+
45
+ The build command has positional arguments and position independent flags.
46
+
47
+ #### Arguments (position dependent)
48
+
49
+ ##### project name
50
+ The name of the project to build, and a file named \<project\_name\>.rb must be
51
+ present in configs/projects in the working directory.
52
+
53
+ ##### platform name
54
+ The name of the platform to build against, and a file named
55
+ \<platform\_name\>.rb must be present in configs/platforms in the working
56
+ directory.
57
+
58
+ Platform can also be a comma separated list of platforms such as platform1,platform2.
59
+
60
+ ##### target host [optional]
61
+ Target host is an optional argument to override the host selection. Instead of using
62
+ a vm collected from the pooler, the build will attempt to ssh to target as the
63
+ root user.
64
+
65
+ If building on multiple platforms, multiple targets can also be specified using
66
+ a comma separated list such as host1,host2. If less targets are specified than
67
+ platforms, the default engine (the pooler) will be used for platforms without a
68
+ target. If more targets are specified than platforms, the extra will be ignored.
69
+
70
+ #### Flagged arguments (can be anywhere in the command)
71
+
72
+ ##### -w DIR, --workdir DIR
73
+ Specifies a directory where the sources should be placed and builds performed.
74
+ Defaults to a temporary directory created with Ruby's Dir.mktmpdir.
75
+
76
+ ##### -c DIR, --configdir DIR
77
+ Specifies where project configuration is found. Defaults to $pwd/configs.
78
+
79
+ ##### -e ENGINE, --engine ENGINE
80
+ Choose a different virtualization engine to use to select the build target.
81
+ Currently supported engines are:
82
+ * `base` - Pure ssh backend; no teardown currently defined
83
+ * `local` - Build on the local machine; platform name must match the local machine
84
+ * `docker` - Builds in a docker container
85
+ * `pooler` - Selects a vm from Puppet Labs' vm pooler to build on
86
+
87
+ #### Flags (can be anywhere in the command)
88
+
89
+ ##### -p, --preserve
90
+ Indicates that the host used for building the project should be left intact
91
+ after the build instead of destroyed. The host is usually destroyed after a
92
+ successful build, or left after a failed build.
93
+
94
+ ##### -v, --verbose (not yet implemented)
95
+ Increase verbosity of output.
96
+
97
+ ##### -h, --help
98
+ Display command-line help.
99
+
100
+ #### Environment variables
101
+
102
+ ##### VANAGON\_SSH\_KEY
103
+ A full path on disk for a private ssh key to be used in ssh and rsync
104
+ communications. This will be used instead of whatever defaults are configured
105
+ in .ssh/config.
106
+
107
+ ##### VMPOOLER\_TOKEN
108
+ Used in conjunction with the pooler engine, this is a token to pass to the
109
+ vmpooler to access the API. Without this token, the default lifetime of vms
110
+ will be much shorter.
111
+
112
+ #### Example usage
113
+ `build --preserve puppet-agent el-6-i386` will build the puppet-agent project
114
+ on the el-6-i386 platform and leave the host intact afterward.
115
+
116
+ `build --engine=docker puppet-agent el-6-i386` will build the puppet-agent
117
+ project on the el-6-i386 platform using the docker engine (the platform must
118
+ have a docker\_image defined in its config).
119
+
120
+ ### `devkit` usage
121
+
122
+ The devkit command has positional arguments and position independent flagged
123
+ arguments.
124
+
125
+ #### Arguments (position dependent)
126
+
127
+ ##### project name
128
+ As in `build` arguments.
129
+
130
+ ##### platform name
131
+ As in `build` arguments.
132
+
133
+ ##### component names [optional]
134
+ Specifies specific components that should be built. If components are not
135
+ specified, then all components in the project will be built. If components
136
+ are specified as arguments, then any in the project that aren't specified
137
+ as arguments will be retrieved from packages rather than built from source.
138
+
139
+ #### Flagged arguments (can be anywhere in the command)
140
+
141
+ Supports all flagged arguments from the `build` command.
142
+
143
+ ##### -t HOST, --target HOST
144
+ As in the `build` target host optional argument.
145
+
146
+ #### Flags (can be anywhere in the command)
147
+
148
+ ##### -h, --help
149
+ Display command-line help.
150
+
151
+ Contributing
152
+ ---
153
+ We'd love to get contributions from you! Once you are up and running, take a look at the
154
+ [Contribution Documents](CONTRIBUTING.md) to see how to get your changes merged
155
+ in.
156
+
157
+ License
158
+ ---
159
+ See [LICENSE](LICENSE) file.
160
+
161
+ Overview
162
+ ---
163
+ Vanagon is broken down into three core ideas: the project, the component and
164
+ the platform. The project contains one or more components and is built for a
165
+ platform. As a quick example, if I had a ruby app and wanted to package it, the
166
+ project would probably contain a component for ruby and a component for my app.
167
+ If I wanted to build it for debian wheezy, I would define a platform called
168
+ wheezy and build my project against it.
169
+
170
+ For more detailed examples of the DSLs available, please see the
171
+ [examples](examples) directory and the YARD documentation for vanagon.
172
+
173
+ Maintainers
174
+ ---
175
+ The Release Engineering team at Puppet Labs
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ load File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "vanagon.rb"))
3
+
4
+ optparse = Vanagon::OptParse.new("#{File.basename(__FILE__)} <project-name> <platform-name> [<target>] [options]",
5
+ [:workdir, :configdir, :engine, :preserve, :verbose])
6
+ options = optparse.parse! ARGV
7
+
8
+ project = ARGV[0]
9
+ platforms = ARGV[1]
10
+ targets = ARGV[2]
11
+
12
+ if project.nil? or platforms.nil?
13
+ warn "project and platform are both required arguments."
14
+ puts optparse
15
+ exit 1
16
+ end
17
+
18
+ platform_list = platforms.split(',')
19
+ if targets
20
+ target_list = targets.split(',')
21
+ else
22
+ target_list = []
23
+ end
24
+
25
+ platform_list.zip(target_list).each do |pair|
26
+ platform, target = pair
27
+ artifact = Vanagon::Driver.new(platform, project, options.merge({ :target => target }))
28
+
29
+ artifact.verbose = true if options[:verbose]
30
+ artifact.preserve = true if options[:preserve]
31
+
32
+ artifact.run
33
+ end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ load File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "vanagon.rb"))
3
+
4
+ optparse = Vanagon::OptParse.new("#{File.basename(__FILE__)} <project-name> <platform-name> [<component-name>...] [options]",
5
+ [:workdir, :configdir, :target, :engine])
6
+ options = optparse.parse! ARGV
7
+
8
+ project = ARGV[0]
9
+ platform = ARGV[1]
10
+ components = ARGV.drop(2)
11
+
12
+ if project.nil? or platform.nil?
13
+ warn "project and platform are both required arguments."
14
+ puts optparse
15
+ exit 1
16
+ end
17
+
18
+ artifact = Vanagon::Driver.new(platform, project, options.merge({ :components => components }))
19
+
20
+ artifact.preserve = true
21
+
22
+ artifact.prepare(options[:workdir])
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV["PROJECT_ROOT"] = Dir.pwd
4
+
5
+ # Begin warning: This ship script is an internal tool.
6
+ # This is not intended to function outside of Puppet Labs' infrastructure.
7
+ # This presumes packages for this ref have already been build and shipped.
8
+ # End of warning.
9
+
10
+ # repo_target will allow us to be more granular with the selection of repos that will be constructed
11
+ # if we have not built debs or rpms, the packaging repo will fail when creating repos
12
+ if ARGV[0]
13
+ repo_target = ARGV[0].downcase
14
+ end
15
+
16
+ require 'packaging'
17
+ Pkg::Util::RakeUtils.load_packaging_tasks
18
+ case repo_target
19
+ when 'rpm'
20
+ Pkg::Util::RakeUtils.invoke_task('pl:jenkins:rpm_repos')
21
+ when 'deb'
22
+ Pkg::Util::RakeUtils.invoke_task('pl:jenkins:deb_repos')
23
+ else
24
+ Pkg::Util::RakeUtils.invoke_task('pl:jenkins:rpm_repos')
25
+ Pkg::Util::RakeUtils.invoke_task('pl:jenkins:deb_repos')
26
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV["PROJECT_ROOT"] = Dir.pwd
4
+
5
+ # Begin warning: This ship script is an internal tool.
6
+ # This is not intended to function outside of Puppet Labs' infrastructure.
7
+ # End of warning.
8
+
9
+ if Dir["output/**/*"].select { |entry| File.file?(entry) }.empty?
10
+ fail "No packages to ship in the output directory. Maybe you want to build some first?"
11
+ else
12
+ require 'packaging'
13
+ Pkg::Util::RakeUtils.load_packaging_tasks
14
+ Pkg::Util::RakeUtils.invoke_task('pl:jenkins:ship', 'artifacts', 'output')
15
+ end
@@ -0,0 +1,8 @@
1
+ LIBDIR = File.expand_path(File.dirname(__FILE__))
2
+ VANAGON_ROOT = File.join(File.expand_path(File.dirname(__FILE__)), "..")
3
+
4
+ $:.unshift(LIBDIR) unless
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(LIBDIR)
6
+
7
+ require 'vanagon/optparse'
8
+ require 'vanagon/driver'
@@ -0,0 +1,2 @@
1
+ require 'vanagon/common/pathname'
2
+ require 'vanagon/common/user'
@@ -0,0 +1,87 @@
1
+ class Vanagon
2
+ class Common
3
+ class Pathname
4
+ # @!attribute path
5
+ # @return [String] Returns clean pathname of self with consecutive
6
+ # slashes and useless dots removed. The filesystem is not accessed.
7
+ #
8
+ # @!attribute mode
9
+ # @return [String, Integer] Returns an integer representing the
10
+ # permission bits of self. The meaning of the bits is platform
11
+ # dependent; on Unix systems, see stat(2).
12
+ #
13
+ # @!attribute owner
14
+ # @return [String, Integer] Returns the numeric user id or string
15
+ # representing the user name of the owner of self.
16
+ #
17
+ # @!attribute group
18
+ # @return [String, Integer] Returns the numeric group id or string
19
+ # representing the group name of the owner of self.
20
+ attr_accessor :path, :mode, :owner, :group
21
+
22
+ # Each Pathname requires a filesystem path, and has many optional
23
+ # properties that may be set at initialization time.
24
+ # @param [String, Integer] mode the UNIX Octal permission string to use when this file is archived
25
+ # @param [String, Integer] owner the username or UID to use when this file is archived
26
+ # @param [String, Integer] group the groupname or GID to use when this file is archived
27
+ # @param [Boolean] config mark this file as a configuration file, stored as private state
28
+ # and exposed through the {#configfile?} method.
29
+ # @return [Vanagon::Common::Pathname] Returns a new Pathname instance.
30
+ def initialize(path, mode: nil, owner: nil, group: nil, config: false)
31
+ @path = File.expand_path(path)
32
+ @mode ||= mode
33
+ @owner ||= owner
34
+ @group ||= group
35
+ @config ||= config
36
+ end
37
+
38
+ # An alias to {Vanagon::Common::Pathname}'s constructor method,
39
+ # which returns a new Vanagon::Common::Pathname, explicitly marked as a file
40
+ # @see Vanagon::Common::Pathname#initialize
41
+ #
42
+ # @example Create a new Vanagon::Common::Pathname, marked as a file.
43
+ # Vanagon::Common::Pathname.file('/etc/puppet/puppet/puppet.conf')
44
+ def self.file(path, **args)
45
+ new(path, **args.merge!({ config: false}))
46
+ end
47
+
48
+ # An alias to {Vanagon::Common::Pathname}'s constructor method,
49
+ # which returns a new Vanagon::Common::Pathname, explicitly marked as a configuration file
50
+ # @see Vanagon::Common::Pathname#initialize
51
+ #
52
+ # @example Create a new configuration file, marked as a configuration file.
53
+ # Vanagon::Common::Pathname.configfile('/etc/puppet/puppet/puppet.conf')
54
+ def self.configfile(path, **args)
55
+ new(path, **args.merge!({ config: true}))
56
+ end
57
+
58
+ # @return [Boolean] true if a self is marked as a configuration file.
59
+ def configfile?
60
+ !!@config
61
+ end
62
+
63
+ # Simple test to see if any of the non-required attributes have been set in this object.
64
+ #
65
+ # @return [Boolean] whether or not mode, owner or group has been set for the object
66
+ def has_overrides?
67
+ !!(@mode || @owner || @group)
68
+ end
69
+
70
+ # Equality -- Two instances of Vanagon::Common::Pathname are equal if they
71
+ # contain the same number attributes and if each attribute is equal to
72
+ # (according to {Object#==}) the corresponding attribute in other_pathname.
73
+ #
74
+ # @return [Boolean] true if all attributes have equal values, or otherwise false.
75
+ def ==(other)
76
+ other.hash == hash
77
+ end
78
+ alias :eql? :==
79
+
80
+ # @return [Fixnum] Compute a hash-code for self, derived from its attributes;
81
+ # two Pathnames with the same content will have the same hash code (and will compare using {#eql?}).
82
+ def hash
83
+ instance_variables.map { |v| instance_variable_get(v) }.hash
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,25 @@
1
+ class Vanagon
2
+ class Common
3
+ class User
4
+ attr_accessor :name, :group, :shell, :is_system, :homedir
5
+ def initialize(name, group = nil, shell = nil, is_system = false, homedir = nil)
6
+ @name = name
7
+ @group = group ? group : @name
8
+ @shell = shell if shell
9
+ @is_system = is_system if is_system
10
+ @homedir = homedir if homedir
11
+ end
12
+
13
+ # Equality. How does it even work?
14
+ #
15
+ # @return [true, false] true if all attributes have equal values. false otherwise.
16
+ def ==(other)
17
+ other.name == self.name && \
18
+ other.group == self.group && \
19
+ other.shell == self.shell && \
20
+ other.is_system == self.is_system && \
21
+ other.homedir == self.homedir
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,157 @@
1
+ require 'vanagon/component/source'
2
+ require 'vanagon/component/dsl'
3
+
4
+ class Vanagon
5
+ class Component
6
+ # @!attribute [r] files
7
+ # @return [Set] the list of files marked for installation
8
+
9
+ attr_accessor :name, :version, :source, :url, :configure, :build, :install
10
+ attr_accessor :environment, :extract_with, :dirname, :build_requires
11
+ attr_accessor :settings, :platform, :patches, :requires, :service, :options
12
+ attr_accessor :directories, :replaces, :provides, :cleanup_source, :environment
13
+ attr_accessor :sources, :preinstall_actions, :postinstall_actions
14
+
15
+ # Loads a given component from the configdir
16
+ #
17
+ # @param name [String] the name of the component
18
+ # @param configdir [String] the path to the component config file
19
+ # @param settings [Hash] the settings to be used in the component
20
+ # @param platform [Vanagon::Platform] the platform to build the component for
21
+ # @return [Vanagon::Component] the component as specified in the component config
22
+ # @raise if the instance_eval on Component fails, the exception is reraised
23
+ def self.load_component(name, configdir, settings, platform)
24
+ compfile = File.join(configdir, "#{name}.rb")
25
+ code = File.read(compfile)
26
+ dsl = Vanagon::Component::DSL.new(name, settings, platform)
27
+ dsl.instance_eval(code, __FILE__, __LINE__)
28
+ dsl._component
29
+ rescue => e
30
+ puts "Error loading project '#{name}' using '#{compfile}':"
31
+ puts e
32
+ puts e.backtrace.join("\n")
33
+ raise e
34
+ end
35
+
36
+ # Component constructor.
37
+ #
38
+ # @param name [String] the name of the component
39
+ # @param settings [Hash] the settings to be used in the component
40
+ # @param platform [Vanagon::Platform] the platform to build the component for
41
+ # @return [Vanagon::Component] the component with the given settings and platform
42
+ def initialize(name, settings, platform)
43
+ @name = name
44
+ @settings = settings
45
+ @platform = platform
46
+ @options = {}
47
+ @build_requires = []
48
+ @requires = []
49
+ @configure = []
50
+ @install = []
51
+ @build = []
52
+ @patches = []
53
+ @files = Set.new
54
+ @directories = []
55
+ @replaces = []
56
+ @provides = []
57
+ @environment = {}
58
+ @sources = []
59
+ @preinstall_actions = []
60
+ @postinstall_actions = []
61
+ end
62
+
63
+ # Adds the given file to the list of files and returns @files.
64
+ #
65
+ # @param file [Vanagon::Common::Pathname] file to add to a component's list of files
66
+ # @return [Set, nil] Returns @files if file is successfully added to @files
67
+ # or nil if file already exists
68
+ def add_file(file)
69
+ @files.add file
70
+ end
71
+
72
+ # Deletes the given file from the list of files and returns @files.
73
+ #
74
+ # @param file [String] path of file to delete from a component's list of files
75
+ # @return [Set, nil] Returns @files if file is successfully deleted
76
+ # from @files or nil if file doesn't exist; this matches strictly on
77
+ # the path of a given file, and ignores other attributes like :mode,
78
+ # :owner, or :group.
79
+ def delete_file(file)
80
+ @files.delete_if { |this_file| this_file.path == file }
81
+ end
82
+
83
+ # Retrieve all items from @files not marked as configuration files
84
+ #
85
+ # @return [Set] all files not marked as configuration files
86
+ def files
87
+ @files.reject(&:configfile?)
88
+ end
89
+
90
+ # Retrieve all items from @files explicitly marked as configuration files
91
+ #
92
+ # @return [Set] all files explicitly marked as configuration files
93
+ def configfiles
94
+ @files.select(&:configfile?)
95
+ end
96
+
97
+ # Fetches the primary source for the component. As a side effect, also sets
98
+ # \@extract_with, @dirname and @version for the component for use in the
99
+ # makefile template
100
+ #
101
+ # @param workdir [String] working directory to put the source into
102
+ def get_source(workdir)
103
+ if @url
104
+ @source = Vanagon::Component::Source.source(@url, @options, workdir)
105
+ @source.fetch
106
+ @source.verify
107
+ @extract_with = @source.extract(@platform.tar) if @source.respond_to?(:extract)
108
+ @cleanup_source = @source.cleanup if @source.respond_to?(:cleanup)
109
+ @dirname = @source.dirname
110
+
111
+ # Git based sources probably won't set the version, so we load it if it hasn't been already set
112
+ @version ||= @source.version
113
+ else
114
+ warn "No source given for component '#{@name}'"
115
+
116
+ # If there is no source, we don't want to try to change directories, so we just change to the current directory.
117
+ @dirname = './'
118
+ end
119
+ end
120
+
121
+
122
+ # Fetches secondary sources for the component. These are just dumped into the workdir currently.
123
+ #
124
+ # @param workdir [String] working directory to put the source into
125
+ def get_sources(workdir)
126
+ @sources.each do |source|
127
+ cur_source = Vanagon::Component::Source.source(source.url, { :ref => source.ref, :sum => source.sum }, workdir)
128
+ cur_source.fetch
129
+ cur_source.verify
130
+ end
131
+ end
132
+
133
+ # Fetches patches if any are provided for the project.
134
+ #
135
+ # @param workdir [String] working directory to put the patches into
136
+ def get_patches(workdir)
137
+ unless @patches.empty?
138
+ patchdir = File.join(workdir, "patches")
139
+ FileUtils.mkdir_p(patchdir)
140
+ FileUtils.cp(@patches.map(&:path), patchdir)
141
+ end
142
+ end
143
+
144
+ # Prints the environment in a way suitable for use in a Makefile
145
+ # or shell script.
146
+ #
147
+ # @return [String] environment suitable for inclusion in a Makefile
148
+ def get_environment
149
+ if @environment.empty?
150
+ ":"
151
+ else
152
+ env = @environment.map { |key, value| %(#{key}="#{value}") }
153
+ "export #{env.join(' ')}"
154
+ end
155
+ end
156
+ end
157
+ end