Class: Solaris::Patchdiag

Inherits:
Object
  • Object
show all
Defined in:
lib/solaris/patchdiag.rb

Overview

Class to represent the Oracle patchdiag “database” (file). See the following Oracle support publication for format: support.oracle.com/CSP/main/article?cmd=show&type=NOT&doctype=REFERENCE&id=1019527.1

Constant Summary collapse

DEFAULT_XREF_FILE =

Default patchdiag.xref file, as for Patch Check Advanced cache

'/var/tmp/patchdiag.xref'
DEFAULT_XREF_URL =

URL of latest patchdiag.xref from Oracle.

'https://getupdates.oracle.com/reports/patchdiag.xref'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xref_file = DEFAULT_XREF_FILE) ⇒ Patchdiag

Create a new patchdiag database object by reading the given xref file (this may be a filename (string) or a fileish object (File, StringIO)). If no xref file is given then the default is read (/var/tmp/patchdiag.xref); this is the cache file used by Patch Check Advanced (pca).



30
31
32
33
34
35
36
# File 'lib/solaris/patchdiag.rb', line 30

def initialize(xref_file=DEFAULT_XREF_FILE)
  xref_file = File.new( xref_file ) if xref_file.is_a?(String)
  @entries = xref_file.
    readlines.
    reject { |line| line =~ /^#|^\s*$/ }. # discard comments, blanks
    map { |line| PatchdiagEntry.new( line ) }
end

Instance Attribute Details

#entriesObject

An array containing all entries (of class PatchdiagEntry) read from the patchdiag.xref file.



23
24
25
# File 'lib/solaris/patchdiag.rb', line 23

def entries
  @entries
end

Class Method Details

.download!(opts = {}) ⇒ Object

Download the patchdiag database and return it as a string. Note the contents will be returned as a string but not saved to disk unless :to_file or :to_dir are given. For the options hash argument see Solaris::Util.download!



42
43
44
45
# File 'lib/solaris/patchdiag.rb', line 42

def Patchdiag.download!(opts={})
  url = opts.delete( :url ) || DEFAULT_XREF_URL
  Util.download!( url, opts )
end

.open(xref_file = DEFAULT_XREF_FILE, &blk) ⇒ Object

Open the given optional patchdiag xref file and yield to the optional block.



49
50
51
52
53
54
55
56
# File 'lib/solaris/patchdiag.rb', line 49

def Patchdiag.open(xref_file=DEFAULT_XREF_FILE, &blk)
  patchdiag = Patchdiag.new( xref_file )
  if block_given?
    yield patchdiag
  else
    patchdiag
  end
end

Instance Method Details

#all(opts = {}) ⇒ Object

Return all patchdiag entries (PatchdiagEntry) defined in the patchdiag.xref. This method scans the entire patchdiag database so may be a little slow: callers are encouraged to cache or memoize their results.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/solaris/patchdiag.rb', line 100

def all(opts={})

  # Defaults
  order = :ascending
  sort_by = :patch

  # Parse options
  opts.each do |key, value|
    case key
    when :sort_by
      raise ArgumentError, "Invalid sort_by #{value.inspect}" unless [ :patch, :date ].include?( value )
      sort_by = value
    when :order
      raise ArgumentError, "Invalid order #{value.inspect}" unless [ :ascending, :descending ].include?( value )
      order = value
    else
      raise ArgumentError, "Unknown option key #{key.inspect}"
    end
  end

  # Compute the lambda for sorting.
  if order == :ascending
    boat_op = lambda { |x,y| x.send( sort_by ) <=> y.send( sort_by ) }
  else
    boat_op = lambda { |x,y| y.send( sort_by ) <=> x.send( sort_by ) }
  end

  # Sort and return.
  @entries.sort { |x,y| boat_op.call( x, y ) }

end

#find(patch) ⇒ Object

Returns an array of Solaris::PatchdiagEntry from the patchdiag with the given patch number (a String like xxxxxx-yy or xxxxxx or a Solaris::Patch). Returns an empty array if no such patches can be found.



61
62
63
64
65
66
# File 'lib/solaris/patchdiag.rb', line 61

def find(patch)
  patch = Patch.new( patch.to_s )
  property = patch.minor ? :to_s : :major
  comparator = patch.send( property )
  all.select { |pde| pde.patch.send( property ) == comparator }
end

#latest(patch) ⇒ Object

Return the Solaris::PatchdiagEntry of the latest version of the given patch (a String like xxxxxx-yy or xxxxxx or a Solaris::Patch). Throws Solaris::Patch::NotFound if the patch cannot be found in patchdiag.xref.



71
72
73
74
75
# File 'lib/solaris/patchdiag.rb', line 71

def latest(patch)
  major = Patch.new( patch.to_s ).major
  find( major ).max ||
    raise( Solaris::Patch::NotFound, "Cannot find patch #{patch} in patchdiag.xref" )
end

#successor(patch) ⇒ Object

Return the Solaris::PatchdiagEntry of the latest non-obsolete successor of this patch. Throws Solaris::Patch::NotFound if the patch or any of its named successors cannot be found in patchdiag.xref.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/solaris/patchdiag.rb', line 80

def successor(patch)
  patch = Patch.new( patch.to_s )
  if ! patch.minor || ! entry = find( patch ).first
    entry = latest( patch )
  end
  raise Solaris::Patch::NotFound,
    "Cannot find patch #{patch} in patchdiag.xref" unless entry
  if entry.obsolete?
    succ = entry.successor # may raise
    successor( succ )
  elsif entry.bad?
    raise BadSuccessor, "Terminal successor #{patch} is bad/withdrawn"
  else
    entry
  end
end