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, 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, 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
#copied_entries, #copy_entry, #copy_metadata, #default_shell, #execmd, #expand_pessimistic_constraints, #logger, #mknod_w, #program_exists?, #program_in_path?, #safesystem, #safesystemout, #tar_cmd
Constructor Details
#initialize ⇒ Package
Returns a new instance of Package.
118 119 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 |
# File 'lib/fpm/package.rb', line 118 def initialize # Attributes for this specific package @attributes = {} # 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 = {} staging_path build_path end |
Instance Attribute Details
#architecture ⇒ Object
What architecture is this package for?
79 80 81 |
# File 'lib/fpm/package.rb', line 79 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.
112 113 114 |
# File 'lib/fpm/package.rb', line 112 def attributes @attributes end |
#attrs ⇒ Object
Returns the value of attribute attrs.
114 115 116 |
# File 'lib/fpm/package.rb', line 114 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>/…
73 74 75 |
# File 'lib/fpm/package.rb', line 73 def category @category end |
#config_files ⇒ Object
Array of configuration files
106 107 108 |
# File 'lib/fpm/package.rb', line 106 def config_files @config_files end |
#conflicts ⇒ Object
Array of things this package conflicts with. (Not all packages support this)
90 91 92 |
# File 'lib/fpm/package.rb', line 90 def conflicts @conflicts end |
#dependencies ⇒ Object
Array of dependencies.
82 83 84 |
# File 'lib/fpm/package.rb', line 82 def dependencies @dependencies end |
#description ⇒ Object
a summary or description of the package
97 98 99 |
# File 'lib/fpm/package.rb', line 97 def description @description end |
#directories ⇒ Object
Returns the value of attribute directories.
108 109 110 |
# File 'lib/fpm/package.rb', line 108 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.
46 47 48 |
# File 'lib/fpm/package.rb', line 46 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.
55 56 57 |
# File 'lib/fpm/package.rb', line 55 def iteration @iteration end |
#license ⇒ Object
A identifier representing the license. Any string is fine.
76 77 78 |
# File 'lib/fpm/package.rb', line 76 def license @license end |
#maintainer ⇒ Object
Who maintains this package? This could be the upstream author or the package maintainer. You pick.
59 60 61 |
# File 'lib/fpm/package.rb', line 59 def maintainer @maintainer end |
#name ⇒ Object
The name of this package
38 39 40 |
# File 'lib/fpm/package.rb', line 38 def name @name end |
#provides ⇒ Object
Array of things this package provides. (Not all packages support this)
86 87 88 |
# File 'lib/fpm/package.rb', line 86 def provides @provides end |
#replaces ⇒ Object
Array of things this package replaces. (Not all packages support this)
94 95 96 |
# File 'lib/fpm/package.rb', line 94 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.
103 104 105 |
# File 'lib/fpm/package.rb', line 103 def scripts @scripts end |
#url ⇒ Object
URL for this package. Could be the homepage. Could be the download url. You pick.
67 68 69 |
# File 'lib/fpm/package.rb', line 67 def url @url end |
#vendor ⇒ Object
A identifier representing the vendor. Any string is fine. This is usually who produced the software.
63 64 65 |
# File 'lib/fpm/package.rb', line 63 def vendor @vendor end |
#version ⇒ Object
Get the version of this package
41 42 43 |
# File 'lib/fpm/package.rb', line 41 def version @version end |
Class Method Details
.apply_options(clampcommand) ⇒ Object
448 449 450 451 452 453 454 |
# File 'lib/fpm/package.rb', line 448 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
456 457 458 459 460 461 462 463 |
# File 'lib/fpm/package.rb', line 456 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
409 410 411 412 |
# File 'lib/fpm/package.rb', line 409 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
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
# File 'lib/fpm/package.rb', line 420 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”
468 469 470 |
# File 'lib/fpm/package.rb', line 468 def type self.name.split(':').last.downcase end |
.types ⇒ Object
Get a list of all known package subclasses
415 416 417 |
# File 'lib/fpm/package.rb', line 415 def types return @subclasses end |
Instance Method Details
#build_path(path = nil) ⇒ Object
def staging_path
261 262 263 264 265 266 267 268 269 |
# File 'lib/fpm/package.rb', line 261 def build_path(path=nil) @build_path ||= ::Dir.mktmpdir("package-#{type}-build") #, ::Dir.pwd) 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.
272 273 274 275 |
# File 'lib/fpm/package.rb', line 272 def cleanup cleanup_staging cleanup_build end |
#cleanup_build ⇒ Object
def cleanup_staging
284 285 286 287 288 289 |
# File 'lib/fpm/package.rb', line 284 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
277 278 279 280 281 282 |
# File 'lib/fpm/package.rb', line 277 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
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/fpm/package.rb', line 189 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.
222 223 224 225 |
# File 'lib/fpm/package.rb', line 222 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
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
# File 'lib/fpm/package.rb', line 361 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.
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/fpm/package.rb', line 299 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
240 241 242 243 |
# File 'lib/fpm/package.rb', line 240 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.
246 247 248 249 |
# File 'lib/fpm/package.rb', line 246 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.
498 499 500 501 502 503 504 505 506 507 |
# File 'lib/fpm/package.rb', line 498 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
251 252 253 254 255 256 257 258 259 |
# File 'lib/fpm/package.rb', line 251 def staging_path(path=nil) @staging_path ||= ::Dir.mktmpdir("package-#{type}-staging") #, ::Dir.pwd) if path.nil? return @staging_path else return File.join(@staging_path, path) end end |
#to_s(fmt = nil) ⇒ Object
349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/fpm/package.rb', line 349 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’
184 185 186 |
# File 'lib/fpm/package.rb', line 184 def type self.class.type end |