Module: Puppet::Util::PTomulik::Package::Ports::Functions

Included in:
PkgSearch, PortSearch, Record
Defined in:
lib/puppet/util/ptomulik/package/ports/functions.rb

Overview

Constant Summary collapse

PORTNAME_RE =

Regular expression used to match portname.

/[a-zA-Z0-9][\w\.+-]*/
PORTVERSION_RE =

Regular expression used to match package version suffix.

/[a-zA-Z0-9][\w\.,]*/
PKGNAME_RE =

Regular expression used to match pkgname.

/(#{PORTNAME_RE})-(#{PORTVERSION_RE})/
PORTORIGIN_RE =

Regular expression used to match portorigin.

/(#{PORTNAME_RE})\/(#{PORTNAME_RE})/

Instance Method Summary collapse

Instance Method Details

#escape_pattern(pattern) ⇒ String

Note:

The resultant pattern is a search pattern for an external CLI command and not a ruby regexp (it’s a string in fact).

Escape string that is to be used as a search pattern.

This method converts all characters that could be interpreted as regex special characters to corresponding escape sequences.

Parameters:

  • pattern (String)

    the search pattern to be escaped

Returns:

  • (String)

    escaped pattern.



130
131
132
133
134
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 130

def escape_pattern(pattern)
  # it's also advisable to validate user's input with pkgname?, portname? or
  # potorigin?
  pattern.gsub(/([\(\)\.\*\[\]\|])/) {|c| '\\' + c}
end

#fullname_to_pattern(names) ⇒ String

Convert a full package name to search pattern for the ‘make search` command.

Parameters:

  • names (String|Enumerable)

    the name or names to be turned into search pattern,

Returns:

  • (String)

    the resultant pattern

See Also:



164
165
166
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 164

def fullname_to_pattern(names)
  "^#{strings_to_pattern(names)}$"
end

#mk_search_pattern(key, s) ⇒ String

Convert portorigins, pkgnames or portnames to search pattern for the ‘make search` command.

What the function exactly does depends on ‘key`, that is for `:pkgname` it does `pkgname_to_pattern(s)`, for `:portname` -> `portname_to_pattern(s)` and so on.

Parameters:

  • key (Symbol)

    decides how to process ‘s`, possible values are `:pkgname`, `:portname`, `:portorigin`. For other values, the function returns result of `fullname_to_pattern(s)`.

  • s (String|Enumerable)

    a string or a sequence of strings to be turned into search pattern,

Returns:

  • (String)

    the resultant search pattern



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 215

def mk_search_pattern(key, s)
  case key
  when :pkgname
    pkgname_to_pattern(s)
  when :portname
    portname_to_pattern(s)
  when :portorigin
    portorigin_to_pattern(s)
  else
    fullname_to_pattern(s)
  end
end

#options_files(portname, portorigin = nil) ⇒ Array

Return standard names of option files for a port.

When compiling a port, its Makefile may read build options from a set of files. There is a convention to look for options in a predefined set of options files whose names are derived from portname and portorigin. Up to 4 option files may be read by Makefile (two for portname and two for portorigin) and options contained in all the files get merged.

This method returns for a given portname and portorogin a list of files that may potentially contain build options for the port. The returned names are in same order as they are read by ports Makefile’s. The last file overrides values defined in all previous file, so it’s most significant.

Parameters:

  • portname (String)

    the portname of a port,

  • portorigin (String) (defaults to: nil)

    the portorigin for a port

Returns:

  • (Array)

    an array of absolute paths to option files.



273
274
275
276
277
278
279
280
281
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 273

def options_files(portname, portorigin = nil)
    # keep sources in proper order, see /usr/ports/Mk/bsd.options.mk
    sources = [ portname ]                              # OPTIONSFILE,
    sources << portorigin.gsub(/\//,'_') if portorigin  # OPTIONS_FILE,
    sources.flatten.map{|x|
      f = File.join(self.port_dbdir,x,"options")
      [f,"#{f}.local"]
    }.flatten
end

#options_files_default_syntaxSymbol

Determine default syntax used for options

Returns:

  • (Symbol)
    • ‘:with`, if default syntax is `WITH_XXX=true|false`, or

    • ‘:set_unset`, if default syntax is `OPTION_FILE_SET+=XXX`.



302
303
304
305
306
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 302

def options_files_default_syntax()
  # TODO: I'm not sure about this test, the FreeBSD ports options are so
  #       undocummented...
  File.exist?(portsdir('Mk/bsd.options.mk')) ? :set_unset : :with
end

#options_files_portorigin(portorigin) ⇒ String|nil

Prepare the portorigin argument for the ‘options_files` method.

If the installed ports support options file with names in form ‘/var/db/ports/port_origin/options’ then the function returns the provided portorigin value. Otherwise, it returns ‘nil`.

Parameters:

  • portorigin (Strong)

    portorigin to be used

Returns:

  • (String|nil)


292
293
294
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 292

def options_files_portorigin(portorigin)
  File.exist?(portsdir('Mk/bsd.options.mk')) ? portorigin : nil
end

#pkgname?(s) ⇒ Boolean

Is this a well-formed port’s pkgname?

Parameters:

  • s

    the value to be verified

Returns:

  • (Boolean)

    ‘true` if `s` is a `String` and contains well-formed pkgname, `false` othrewise



91
92
93
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 91

def pkgname?(s)
  s.is_a?(String) and s =~ /^#{PKGNAME_RE}$/
end

#pkgname_to_pattern(pkgnames) ⇒ String

Convert pkgnames to search pattern for the ‘make search` command.

Parameters:

  • pkgnames (String|Enumerable)

    the pkgname or pkgnames to be turned into search patterns,

Returns:

  • (String)

    the resultant pattern

See Also:



186
187
188
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 186

def pkgname_to_pattern(pkgnames)
  fullname_to_pattern(pkgnames)
end

#pkgng_active?(options = {}) ⇒ Boolean

Check whether the pkgng is used by operating system.

This method uses technique proposed by ‘pkg(8)` man page to detect whether the [pkgng](wiki.freebsd.org/pkgng) database is used by local OS. The man page says:

The following script is the safest way to detect if pkg is installed
and activated:

    if TMPDIR=/dev/null ASSUME_ALWAYS_YES=1 \
        PACKAGESITE=file:///nonexistent \
        pkg info -x 'pkg(-devel)?$' >/dev/null 2>&1; then
      # pkgng-specifics
    else
      # pkg_install-specifics
    fi

The method basically does the same but the commands are invoked from within ruby.

Parameters:

  • options (Hash) (defaults to: {})

    options to customize method behavior

Options Hash (options):

  • :pkg (String)
  • :execpipe (String)

    handle to a method which executes external commands in same way as puppet’s ‘execpipe` does, , if not given, the Puppet::Util::Execution#execpipe is used.

Returns:

  • (Boolean)

    ‘true` if the pkgng is active or `false` otherwise.



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 336

def pkgng_active?(options = {})
  return @pkgng_active unless @pkgng_active.nil?

  pkg = options[:pkg] || (respond_to?(:command) ? command(:pkg) : nil)
  # Detect whether the OS uses old pkg or the new pkgng.
  @pkgng_active = false
  if pkg and FileTest.file?(pkg) and FileTest.executable?(pkg)
    ::Puppet.debug "'#{pkg}' command found, checking whether pkgng is active"
    env = { 'TMPDIR' => '/dev/null', 'ASSUME_ALWAYS_YES' => '1',
            'PACKAGESITE' => 'file:///nonexistent' }
    Puppet::Util.withenv(env) do
      begin
        # this is technique proposed by pkg(8) man page,
        cmd = [pkg,'info','-x',"'pkg(-devel)?$'",'>/dev/null', '2>&1']
        begin
          execpipe = options[:execpipe] ||
                     Puppet::Util::Execution.method(:execpipe)
        rescue NameError
          execpipe = Puppet::Util.method(:execpipe)
        end
        execpipe.call(cmd) { |pipe| pipe.each_line {} } # just ignore
        @pkgng_active = true
      rescue Puppet::ExecutionFailure
      # nothing
      end
    end
  else
    ::Puppet.debug "'pkg' command not found"
  end
  ::Puppet.debug "pkgng is #{@pkgng_active ? '' : 'in'}active on this system"
  @pkgng_active
end

#port_dbdir(path = nil) ⇒ String

Note:

You may set ‘ENV` to override defaults.

Path to ports DB directory, defaults to ‘/var/db/ports`.

Parameters:

  • path (String) (defaults to: nil)

    optional subpath to be appended to the port_dbdir

Returns:

  • (String)

    ‘/var/db/ports`, or the value defined by `ENV; if path is given, then it’s appended to the value specified above



249
250
251
252
253
254
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 249

def port_dbdir(path = nil)
  unless dir = ENV['PORT_DBDIR']
    dir = '/var/db/ports'
  end
  path ? File.join(dir, path) : dir
end

#portname?(s) ⇒ Boolean

Is this a well-formed portname?

Parameters:

  • s

    the value to be verified

Returns:

  • (Boolean)

    ‘true` if `s` is a `String` and contains well-formed portname, `false` otherwise



101
102
103
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 101

def portname?(s)
  s.is_a?(String) and s =~ /^#{PORTNAME_RE}$/
end

#portname_to_pattern(portnames) ⇒ String

Convert portnames to search pattern for the ‘make search` command.

Parameters:

  • portnames (String|Enumerable)

    the portname or portnames to be turned into search pattern,

Returns:

  • (String)

    the resultant pattern

See Also:



197
198
199
200
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 197

def portname_to_pattern(portnames)
  version_pattern = '[a-zA-Z0-9][a-zA-Z0-9\\.,_]*'
  "^#{strings_to_pattern(portnames)}-#{version_pattern}$"
end

#portorigin?(s) ⇒ Boolean

Is this a well-formed port’s origin?

Parameters:

  • s

    the value to be verified

Returns:

  • (Boolean)

    ‘true` if `s` is a `String` and contains well-formed portorigin, `false` otherwise,



81
82
83
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 81

def portorigin?(s)
  s.is_a?(String) and s =~ /^#{PORTORIGIN_RE}$/
end

#portorigin_to_pattern(origins) ⇒ String

Convert portorigins to search pattern for the ‘make search` command.

Parameters:

  • origins (String|Enumerable)

    the portorigin or portorigins to be turned into search pattern,

Returns:

  • (String)

    the resultant pattern

See Also:



175
176
177
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 175

def portorigin_to_pattern(origins)
  "^#{portsdir}/#{strings_to_pattern(origins)}$"
end

#portsdir(path = nil) ⇒ String

Note:

you may set ‘ENV` to override defaults.

Path to BSD ports source tree.

Parameters:

  • path (String) (defaults to: nil)

    optional subpath to be appended to the portsdir

Returns:

  • (String)

    ‘/usr/pkgsrc` on NetBSD, `/usr/ports` on other systems or the value defined by `ENV`; if path is given, then it’s appended to the value specified above



235
236
237
238
239
240
241
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 235

def portsdir(path = nil)
  unless dir = ENV['PORTSDIR']
    os = Facter.value(:operatingsystem)
    dir = (os == "NetBSD") ? '/usr/pkgsrc' : '/usr/ports'
  end
  path ? File.join(dir, path) : dir
end

#split_pkgname(pkgname) ⇒ Array

Split pkgname into portname and portversion.

Parameters:

  • pkgname (String)

    the name to be split

Returns:

  • (Array)

    a 2-element array: ‘[portname,portversion]`; if the input string `pkgname` cannot be split into portname and portversion, the function still returns a 2-element array in form `[pkgname,nil]`



112
113
114
115
116
117
118
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 112

def split_pkgname(pkgname)
  if m = /^#{PKGNAME_RE}$/.match(pkgname)
    m.captures
  else
    [pkgname, nil]
  end
end

#strings_to_pattern(s) ⇒ String

Note:

The resultant pattern is a search pattern for an external CLI command and not a ruby regexp (it’s a string in fact).

Convert a search key (or an array of keys) to a search pattern for ‘“make search”` command.

If ‘s` is a string, it’s just escaped with #escape_pattern and returned. If it’s a sequence of strings, then the function returns a pattern matching any of them.

Parameters:

  • s (String|Enumerable)

    a string or an array of strings to be converted to a search pattern

Returns:

  • (String)

    the resultant search pattern



149
150
151
152
153
154
155
# File 'lib/puppet/util/ptomulik/package/ports/functions.rb', line 149

def strings_to_pattern(s)
  if s.is_a?(Enumerable) and not s.instance_of?(String)
    '(' + s.map{|p| escape_pattern(p)}.join('|') + ')'
  else
    escape_pattern(s)
  end
end