Class: FPM::Package
- Inherits:
-
Object
- Object
- FPM::Package
- Includes:
- Cabin::Inspectable, Util
- Defined in:
- lib/fpm/package.rb,
lib/fpm/namespace.rb
Overview
This class is the parent of all packages. If you want to implement an FPM package type, you’ll inherit from this.
Direct Known Subclasses
APK, CPAN, Deb, Dir, Empty, FreeBSD, Gem, NPM, OSXpkg, P5P, PEAR, Pacman, Pkgin, PleaseRun, Puppet, Python, RPM, Sh, Snap, Solaris, Tar, Virtualenv, Zip
Defined Under Namespace
Classes: APK, CPAN, Deb, Dir, Empty, FileAlreadyExists, FreeBSD, Gem, InvalidArgument, NPM, OSXpkg, P5P, PEAR, Pacman, ParentDirectoryMissing, Pkgin, PleaseRun, Puppet, Python, RPM, Sh, Snap, Solaris, Tar, Virtualenv, Zip
Instance Attribute Summary collapse
-
#architecture ⇒ Object
What architecture is this package for?.
-
#attributes ⇒ Object
Any other attributes specific to this package.
-
#attrs ⇒ Object
Returns the value of attribute attrs.
-
#category ⇒ Object
The category of this package.
-
#config_files ⇒ Object
Array of configuration files.
-
#conflicts ⇒ Object
Array of things this package conflicts with.
-
#dependencies ⇒ Object
Array of dependencies.
-
#description ⇒ Object
a summary or description of the package.
-
#directories ⇒ Object
Returns the value of attribute directories.
-
#epoch ⇒ Object
The epoch version of this package This is used most when an upstream package changes it’s versioning style so standard comparisions wouldn’t work.
-
#iteration ⇒ Object
The iteration of this package.
-
#license ⇒ Object
A identifier representing the license.
-
#maintainer ⇒ Object
Who maintains this package? This could be the upstream author or the package maintainer.
-
#name ⇒ Object
The name of this package.
-
#provides ⇒ Object
Array of things this package provides.
-
#replaces ⇒ Object
Array of things this package replaces.
-
#scripts ⇒ Object
hash of scripts for maintainer/package scripts (postinstall, etc).
-
#url ⇒ Object
URL for this package.
-
#vendor ⇒ Object
A identifier representing the vendor.
-
#version ⇒ Object
Get the version of this package.
Class Method Summary collapse
-
.apply_options(clampcommand) ⇒ Object
Apply the options for this package on the clamp command.
-
.default_attributes(&block) ⇒ Object
def apply_options.
-
.inherited(klass) ⇒ Object
This method is invoked when subclass occurs.
-
.option(flag, param, help, options = {}, &block) ⇒ Object
This allows packages to define flags for the fpm command line.
-
.type ⇒ Object
Get the type of this package class.
-
.types ⇒ Object
Get a list of all known package subclasses.
Instance Method Summary collapse
-
#build_path(path = nil) ⇒ Object
def staging_path.
-
#cleanup ⇒ Object
Clean up any temporary storage used by this class.
-
#cleanup_build ⇒ Object
def cleanup_staging.
-
#cleanup_staging ⇒ Object
def cleanup.
-
#convert(klass) ⇒ Object
Convert this package to a new package type.
-
#converted_from(origin) ⇒ Object
This method is invoked on a package when it has been converted to a new package format.
-
#edit_file(path) ⇒ Object
def to_s.
-
#files ⇒ Object
List all files in the staging_path.
-
#initialize ⇒ Package
constructor
A new instance of Package.
-
#input(thing_to_input) ⇒ Object
Add a new source to this package.
-
#output(path) ⇒ Object
Output this package to the given path.
-
#script(script_name) ⇒ Object
Get the contents of the script by a given name.
-
#staging_path(path = nil) ⇒ Object
def output.
- #to_s(fmt = nil) ⇒ Object
-
#type ⇒ Object
Get the ‘type’ for this instance.
Methods included from Util
#ar_cmd, #ar_cmd_deterministic?, #copied_entries, #copy_entry, #copy_metadata, #default_shell, #execmd, #expand_pessimistic_constraints, #logger, #mknod_w, #program_exists?, #program_in_path?, #safesystem, #safesystemout, #tar_cmd, #tar_cmd_supports_sort_names_and_set_mtime?
Constructor Details
#initialize ⇒ Package
Returns a new instance of Package.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/fpm/package.rb', line 120 def initialize # Attributes for this specific package @attributes = { # Default work location :workdir => ::Dir.tmpdir } # Reference # http://www.debian.org/doc/manuals/maint-guide/first.en.html # http://wiki.debian.org/DeveloperConfiguration # https://github.com/jordansissel/fpm/issues/37 if ENV.include?("DEBEMAIL") and ENV.include?("DEBFULLNAME") # Use DEBEMAIL and DEBFULLNAME as the default maintainer if available. @maintainer = "#{ENV["DEBFULLNAME"]} <#{ENV["DEBEMAIL"]}>" else # TODO(sissel): Maybe support using 'git config' for a default as well? # git config --get user.name, etc can be useful. # # Otherwise default to user@currenthost @maintainer = "<#{ENV["USER"]}@#{Socket.gethostname}>" end # Set attribute defaults based on flags # This allows you to define command line options with default values # that also are obeyed if fpm is used programmatically. self.class.default_attributes do |attribute, value| attributes[attribute] = value end @name = nil @architecture = "native" @description = "no description given" @version = nil @epoch = nil @iteration = nil @url = nil @category = "default" @license = "unknown" @vendor = "none" # Iterate over all the options and set defaults if self.class.respond_to?(:declared_options) self.class..each do |option| option.attribute_name.tap do |attr| # clamp makes option attributes available as accessor methods # do --foo-bar is available as 'foo_bar' # make these available as package attributes. attr = "#{attr}?" if !respond_to?(attr) input.attributes[attr.to_sym] = send(attr) if respond_to?(attr) end end end @provides = [] @conflicts = [] @replaces = [] @dependencies = [] @scripts = {} @config_files = [] @directories = [] @attrs = {} build_path # Dont' initialize staging_path just yet, do it lazily so subclass can get a word in. end |
Instance Attribute Details
#architecture ⇒ Object
What architecture is this package for?
81 82 83 |
# File 'lib/fpm/package.rb', line 81 def architecture @architecture end |
#attributes ⇒ Object
Any other attributes specific to this package. This is where you’d put rpm, deb, or other specific attributes.
114 115 116 |
# File 'lib/fpm/package.rb', line 114 def attributes @attributes end |
#attrs ⇒ Object
Returns the value of attribute attrs.
116 117 118 |
# File 'lib/fpm/package.rb', line 116 def attrs @attrs end |
#category ⇒ Object
The category of this package. RedHat calls this ‘Group’ Debian calls this ‘Section’ FreeBSD would put this in /usr/ports/<category>/…
75 76 77 |
# File 'lib/fpm/package.rb', line 75 def category @category end |
#config_files ⇒ Object
Array of configuration files
108 109 110 |
# File 'lib/fpm/package.rb', line 108 def config_files @config_files end |
#conflicts ⇒ Object
Array of things this package conflicts with. (Not all packages support this)
92 93 94 |
# File 'lib/fpm/package.rb', line 92 def conflicts @conflicts end |
#dependencies ⇒ Object
Array of dependencies.
84 85 86 |
# File 'lib/fpm/package.rb', line 84 def dependencies @dependencies end |
#description ⇒ Object
a summary or description of the package
99 100 101 |
# File 'lib/fpm/package.rb', line 99 def description @description end |
#directories ⇒ Object
Returns the value of attribute directories.
110 111 112 |
# File 'lib/fpm/package.rb', line 110 def directories @directories end |
#epoch ⇒ Object
The epoch version of this package This is used most when an upstream package changes it’s versioning style so standard comparisions wouldn’t work.
48 49 50 |
# File 'lib/fpm/package.rb', line 48 def epoch @epoch end |
#iteration ⇒ Object
The iteration of this package.
Debian calls this 'release' and is the last '-NUMBER' in the version
RedHat has this as 'Release' in the .spec file
FreeBSD calls this 'PORTREVISION'
Iteration can be nil. If nil, the fpm package implementation is expected to handle any default value that should be instead.
57 58 59 |
# File 'lib/fpm/package.rb', line 57 def iteration @iteration end |
#license ⇒ Object
A identifier representing the license. Any string is fine.
78 79 80 |
# File 'lib/fpm/package.rb', line 78 def license @license end |
#maintainer ⇒ Object
Who maintains this package? This could be the upstream author or the package maintainer. You pick.
61 62 63 |
# File 'lib/fpm/package.rb', line 61 def maintainer @maintainer end |
#name ⇒ Object
The name of this package
40 41 42 |
# File 'lib/fpm/package.rb', line 40 def name @name end |
#provides ⇒ Object
Array of things this package provides. (Not all packages support this)
88 89 90 |
# File 'lib/fpm/package.rb', line 88 def provides @provides end |
#replaces ⇒ Object
Array of things this package replaces. (Not all packages support this)
96 97 98 |
# File 'lib/fpm/package.rb', line 96 def replaces @replaces end |
#scripts ⇒ Object
hash of scripts for maintainer/package scripts (postinstall, etc)
The keys are :before_install, etc The values are the text to use in the script.
105 106 107 |
# File 'lib/fpm/package.rb', line 105 def scripts @scripts end |
#url ⇒ Object
URL for this package. Could be the homepage. Could be the download url. You pick.
69 70 71 |
# File 'lib/fpm/package.rb', line 69 def url @url end |
#vendor ⇒ Object
A identifier representing the vendor. Any string is fine. This is usually who produced the software.
65 66 67 |
# File 'lib/fpm/package.rb', line 65 def vendor @vendor end |
#version ⇒ Object
Get the version of this package
43 44 45 |
# File 'lib/fpm/package.rb', line 43 def version @version end |
Class Method Details
.apply_options(clampcommand) ⇒ Object
453 454 455 456 457 458 459 |
# File 'lib/fpm/package.rb', line 453 def (clampcommand) @options ||= [] @options.each do |args| flag, param, help, , block = args clampcommand.option(flag, param, help, , &block) end end |
.default_attributes(&block) ⇒ Object
def apply_options
461 462 463 464 465 466 467 468 |
# File 'lib/fpm/package.rb', line 461 def default_attributes(&block) return if @options.nil? @options.each do |flag, param, help, , _block| attr = flag.first.gsub(/^-+/, "").gsub(/-/, "_").gsub("[no_]", "") attr += "?" if param == :flag yield attr.to_sym, [:default] end end |
.inherited(klass) ⇒ Object
This method is invoked when subclass occurs.
Lets us track all known FPM::Package subclasses
414 415 416 417 |
# File 'lib/fpm/package.rb', line 414 def inherited(klass) @subclasses ||= {} @subclasses[klass.name.gsub(/.*:/, "").downcase] = klass end |
.option(flag, param, help, options = {}, &block) ⇒ Object
This allows packages to define flags for the fpm command line
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/fpm/package.rb', line 425 def option(flag, param, help, ={}, &block) @options ||= [] if !flag.is_a?(Array) flag = [flag] end if param == :flag # Automatically make 'flag' (boolean) options tunable with '--[no-]...' flag = flag.collect { |f| "--[no-]#{type}-#{f.gsub(/^--/, "")}" } else flag = flag.collect { |f| "--#{type}-#{f.gsub(/^--/, "")}" } end help = "(#{type} only) #{help}" @options << [flag, param, help, , block] end |
.type ⇒ Object
Get the type of this package class.
For “Foo::Bar::BAZ” this will return “baz”
473 474 475 |
# File 'lib/fpm/package.rb', line 473 def type self.name.split(':').last.downcase end |
.types ⇒ Object
Get a list of all known package subclasses
420 421 422 |
# File 'lib/fpm/package.rb', line 420 def types return @subclasses end |
Instance Method Details
#build_path(path = nil) ⇒ Object
def staging_path
266 267 268 269 270 271 272 273 274 |
# File 'lib/fpm/package.rb', line 266 def build_path(path=nil) @build_path ||= Stud::Temporary.directory("package-#{type}-build") if path.nil? return @build_path else return File.join(@build_path, path) end end |
#cleanup ⇒ Object
Clean up any temporary storage used by this class.
277 278 279 280 |
# File 'lib/fpm/package.rb', line 277 def cleanup cleanup_staging cleanup_build end |
#cleanup_build ⇒ Object
def cleanup_staging
289 290 291 292 293 294 |
# File 'lib/fpm/package.rb', line 289 def cleanup_build if File.directory?(build_path) logger.debug("Cleaning up build path", :path => build_path) FileUtils.rm_r(build_path) end end |
#cleanup_staging ⇒ Object
def cleanup
282 283 284 285 286 287 |
# File 'lib/fpm/package.rb', line 282 def cleanup_staging if File.directory?(staging_path) logger.debug("Cleaning up staging path", :path => staging_path) FileUtils.rm_r(staging_path) end end |
#convert(klass) ⇒ Object
Convert this package to a new package type
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/fpm/package.rb', line 194 def convert(klass) logger.info("Converting #{self.type} to #{klass.type}") exclude pkg = klass.new pkg.cleanup_staging # purge any directories that may have been created by klass.new # copy other bits ivars = [ :@architecture, :@category, :@config_files, :@conflicts, :@dependencies, :@description, :@epoch, :@iteration, :@license, :@maintainer, :@name, :@provides, :@replaces, :@scripts, :@url, :@vendor, :@version, :@directories, :@staging_path, :@attrs ] ivars.each do |ivar| #logger.debug("Copying ivar", :ivar => ivar, :value => instance_variable_get(ivar), #:from => self.type, :to => pkg.type) pkg.instance_variable_set(ivar, instance_variable_get(ivar)) end # Attributes are special! We do not want to remove the default values of # the destination package type unless their value is specified on the # source package object. pkg.attributes.merge!(self.attributes) pkg.converted_from(self.class) return pkg end |
#converted_from(origin) ⇒ Object
This method is invoked on a package when it has been converted to a new package format. The purpose of this method is to do any extra conversion steps, like translating dependency conditions, etc.
227 228 229 230 |
# File 'lib/fpm/package.rb', line 227 def converted_from(origin) # nothing to do by default. Subclasses may implement this. # See the RPM package class for an example. end |
#edit_file(path) ⇒ Object
def to_s
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/fpm/package.rb', line 366 def edit_file(path) editor = ENV['FPM_EDITOR'] || ENV['EDITOR'] || 'vi' logger.info("Launching editor", :file => path) command = "#{editor} #{Shellwords.escape(path)}" system("#{editor} #{Shellwords.escape(path)}") if !$?.success? raise ProcessFailed.new("'#{editor}' failed (exit code " \ "#{$?.exitstatus}) Full command was: " \ "#{command}"); end if File.size(path) == 0 raise "Empty file after editing: #{path.inspect}" end end |
#files ⇒ Object
List all files in the staging_path
The paths will all be relative to staging_path and will not include that path.
This method will emit ‘leaf’ paths. Files, symlinks, and other file-like things are emitted. Intermediate directories are ignored, but empty directories are emitted.
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/fpm/package.rb', line 304 def files is_leaf = lambda do |path| # True if this is a file/symlink/etc, but not a plain directory return true if !(File.directory?(path) and !File.symlink?(path)) # Empty directories are leafs as well. return true if ::Dir.entries(path).sort == [".", ".."] # False otherwise (non-empty directory, etc) return false end # is_leaf # Find all leaf-like paths (files, symlink, empty directories, etc) # Also trim the leading path such that '#{staging_path}/' is removed from # the path before returning. # # Wrapping Find.find in an Enumerator is required for sane operation in ruby 1.8.7, # but requires the 'backports' gem (which is used in other places in fpm) return Enumerator.new { |y| Find.find(staging_path) { |path| y << path } } \ .select { |path| path != staging_path } \ .select { |path| is_leaf.call(path) } \ .collect { |path| path[staging_path.length + 1.. -1] } end |
#input(thing_to_input) ⇒ Object
Add a new source to this package. The exact behavior depends on the kind of package being managed.
For instance:
-
for FPM::Package::Dir, << expects a path to a directory or files.
-
for FPM::Package::RPM, << expects a path to an rpm.
The idea is that you can keep pumping in new things to a package for later conversion or output.
Implementations are expected to put files relevant to the ‘input’ in the staging_path
245 246 247 248 |
# File 'lib/fpm/package.rb', line 245 def input(thing_to_input) raise NotImplementedError.new("#{self.class.name} does not yet support " \ "reading #{self.type} packages") end |
#output(path) ⇒ Object
Output this package to the given path.
251 252 253 254 |
# File 'lib/fpm/package.rb', line 251 def output(path) raise NotImplementedError.new("#{self.class.name} does not yet support " \ "creating #{self.type} packages") end |
#script(script_name) ⇒ Object
Get the contents of the script by a given name.
If template_scripts? is set in attributes (often by the –template-scripts flag), then apply it as an ERB template.
519 520 521 522 523 524 525 526 527 528 |
# File 'lib/fpm/package.rb', line 519 def script(script_name) if attributes[:template_scripts?] erb = ERB.new(scripts[script_name], nil, "-") # TODO(sissel): find the original file name for the file. erb.filename = "script(#{script_name})" return erb.result(binding) else return scripts[script_name] end end |
#staging_path(path = nil) ⇒ Object
def output
256 257 258 259 260 261 262 263 264 |
# File 'lib/fpm/package.rb', line 256 def staging_path(path=nil) @staging_path ||= Stud::Temporary.directory("package-#{type}-staging") if path.nil? return @staging_path else return File.join(@staging_path, path) end end |
#to_s(fmt = nil) ⇒ Object
354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/fpm/package.rb', line 354 def to_s(fmt=nil) fmt = "NAME.EXTENSION" if fmt.nil? return fmt.gsub("ARCH", to_s_arch) \ .gsub("NAME", to_s_name) \ .gsub("FULLVERSION", to_s_fullversion) \ .gsub("VERSION", to_s_version) \ .gsub("ITERATION", to_s_iteration) \ .gsub("EPOCH", to_s_epoch) \ .gsub("TYPE", to_s_type) \ .gsub("EXTENSION", to_s_extension) end |
#type ⇒ Object
Get the ‘type’ for this instance.
For FPM::Package::ABC, this returns ‘abc’
189 190 191 |
# File 'lib/fpm/package.rb', line 189 def type self.class.type end |