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
#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.
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 180 |
# File 'lib/fpm/package.rb', line 119 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 = {} 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?
80 81 82 |
# File 'lib/fpm/package.rb', line 80 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.
113 114 115 |
# File 'lib/fpm/package.rb', line 113 def attributes @attributes end |
#attrs ⇒ Object
Returns the value of attribute attrs.
115 116 117 |
# File 'lib/fpm/package.rb', line 115 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>/…
74 75 76 |
# File 'lib/fpm/package.rb', line 74 def category @category end |
#config_files ⇒ Object
Array of configuration files
107 108 109 |
# File 'lib/fpm/package.rb', line 107 def config_files @config_files end |
#conflicts ⇒ Object
Array of things this package conflicts with. (Not all packages support this)
91 92 93 |
# File 'lib/fpm/package.rb', line 91 def conflicts @conflicts end |
#dependencies ⇒ Object
Array of dependencies.
83 84 85 |
# File 'lib/fpm/package.rb', line 83 def dependencies @dependencies end |
#description ⇒ Object
a summary or description of the package
98 99 100 |
# File 'lib/fpm/package.rb', line 98 def description @description end |
#directories ⇒ Object
Returns the value of attribute directories.
109 110 111 |
# File 'lib/fpm/package.rb', line 109 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.
47 48 49 |
# File 'lib/fpm/package.rb', line 47 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.
56 57 58 |
# File 'lib/fpm/package.rb', line 56 def iteration @iteration end |
#license ⇒ Object
A identifier representing the license. Any string is fine.
77 78 79 |
# File 'lib/fpm/package.rb', line 77 def license @license end |
#maintainer ⇒ Object
Who maintains this package? This could be the upstream author or the package maintainer. You pick.
60 61 62 |
# File 'lib/fpm/package.rb', line 60 def maintainer @maintainer end |
#name ⇒ Object
The name of this package
39 40 41 |
# File 'lib/fpm/package.rb', line 39 def name @name end |
#provides ⇒ Object
Array of things this package provides. (Not all packages support this)
87 88 89 |
# File 'lib/fpm/package.rb', line 87 def provides @provides end |
#replaces ⇒ Object
Array of things this package replaces. (Not all packages support this)
95 96 97 |
# File 'lib/fpm/package.rb', line 95 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.
104 105 106 |
# File 'lib/fpm/package.rb', line 104 def scripts @scripts end |
#url ⇒ Object
URL for this package. Could be the homepage. Could be the download url. You pick.
68 69 70 |
# File 'lib/fpm/package.rb', line 68 def url @url end |
#vendor ⇒ Object
A identifier representing the vendor. Any string is fine. This is usually who produced the software.
64 65 66 |
# File 'lib/fpm/package.rb', line 64 def vendor @vendor end |
#version ⇒ Object
Get the version of this package
42 43 44 |
# File 'lib/fpm/package.rb', line 42 def version @version end |
Class Method Details
.apply_options(clampcommand) ⇒ Object
449 450 451 452 453 454 455 |
# File 'lib/fpm/package.rb', line 449 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
457 458 459 460 461 462 463 464 |
# File 'lib/fpm/package.rb', line 457 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
410 411 412 413 |
# File 'lib/fpm/package.rb', line 410 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
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/fpm/package.rb', line 421 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”
469 470 471 |
# File 'lib/fpm/package.rb', line 469 def type self.name.split(':').last.downcase end |
.types ⇒ Object
Get a list of all known package subclasses
416 417 418 |
# File 'lib/fpm/package.rb', line 416 def types return @subclasses end |
Instance Method Details
#build_path(path = nil) ⇒ Object
def staging_path
262 263 264 265 266 267 268 269 270 |
# File 'lib/fpm/package.rb', line 262 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.
273 274 275 276 |
# File 'lib/fpm/package.rb', line 273 def cleanup cleanup_staging cleanup_build end |
#cleanup_build ⇒ Object
def cleanup_staging
285 286 287 288 289 290 |
# File 'lib/fpm/package.rb', line 285 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
278 279 280 281 282 283 |
# File 'lib/fpm/package.rb', line 278 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
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 218 |
# File 'lib/fpm/package.rb', line 190 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.
223 224 225 226 |
# File 'lib/fpm/package.rb', line 223 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
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/fpm/package.rb', line 362 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.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/fpm/package.rb', line 300 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
241 242 243 244 |
# File 'lib/fpm/package.rb', line 241 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.
247 248 249 250 |
# File 'lib/fpm/package.rb', line 247 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.
515 516 517 518 519 520 521 522 523 524 |
# File 'lib/fpm/package.rb', line 515 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
252 253 254 255 256 257 258 259 260 |
# File 'lib/fpm/package.rb', line 252 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
350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/fpm/package.rb', line 350 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’
185 186 187 |
# File 'lib/fpm/package.rb', line 185 def type self.class.type end |