Module: Puppet::Util::PTomulik::Packagex::Portsx::Functions

Included in:
PkgSearch, PortSearch, Record
Defined in:
lib/puppet/util/ptomulik/packagex/portsx/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/packagex/portsx/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/packagex/portsx/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/packagex/portsx/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) ⇒ 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)

    the portorigin for a port

Returns:

  • (Array)

    an array of absolute paths to option files.



269
270
271
272
273
274
275
276
277
278
# File 'lib/puppet/util/ptomulik/packagex/portsx/functions.rb', line 269

def options_files(portname, portorigin)
    [
      # keep these in proper order, see /usr/ports/Mk/bsd.options.mk
      portname,                  # OPTIONSFILE,
      portorigin.gsub(/\//,'_'), # OPTIONS_FILE,
    ].flatten.map{|x|
      f = File.join(self.port_dbdir,x,"options")
      [f,"#{f}.local"]
    }.flatten
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/packagex/portsx/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/packagex/portsx/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.



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/puppet/util/ptomulik/packagex/portsx/functions.rb', line 308

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']
        execpipe = options[:execpipe] || Puppet::Util::Execution.method(:execpipe)
        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_dbdirString

Note:

You may set ‘ENV` to override defaults.

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

Returns:

  • (String)

    ‘/var/db/ports`, or the value defined by `ENV.



245
246
247
248
249
250
# File 'lib/puppet/util/ptomulik/packagex/portsx/functions.rb', line 245

def port_dbdir
  unless dir = ENV['PORT_DBDIR']
    dir = '/var/db/ports'
  end
  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/packagex/portsx/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/packagex/portsx/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/packagex/portsx/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/packagex/portsx/functions.rb', line 175

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

#portsdirString

Note:

you may set ‘ENV` to override defaults.

Path to BSD ports source tree.

Returns:

  • (String)

    ‘/usr/pkgsrc` on NetBSD, `/usr/ports` on other systems or the value defined by `ENV`.



233
234
235
236
237
238
239
# File 'lib/puppet/util/ptomulik/packagex/portsx/functions.rb', line 233

def portsdir
  unless dir = ENV['PORTSDIR']
    os = Facter.value(:operatingsystem)
    dir = (os == "NetBSD") ? '/usr/pkgsrc' : '/usr/ports'
  end
  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/packagex/portsx/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/packagex/portsx/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