Class: Simp::RPM
- Inherits:
-
Object
- Object
- Simp::RPM
- Defined in:
- lib/simp/rpm.rb
Overview
Simp::RPM represents a single package that is built and packaged by the Simp team.
Constant Summary collapse
- @@gpg_keys =
Hash.new
Instance Attribute Summary collapse
-
#basename ⇒ Object
Returns the value of attribute basename.
-
#full_version ⇒ Object
Returns the value of attribute full_version.
-
#name ⇒ Object
Returns the value of attribute name.
-
#release ⇒ Object
Returns the value of attribute release.
-
#sources ⇒ Object
Returns the value of attribute sources.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
-
#version ⇒ Object
Returns the value of attribute version.
Class Method Summary collapse
-
.copy_wo_vcs(start_dir, src, dest, dereference = true) ⇒ Object
Copies specific content from one directory to another.
-
.execute(cmd) ⇒ Object
Executes a command and returns a hash with the exit status, stdout output and stderr output.
-
.get_info(rpm_source, mock_hash = nil) ⇒ Object
Parses information, such as the version, from the given specfile or RPM into a hash.
- .indent(message, indent_length) ⇒ Object
-
.load_key(gpg_key) ⇒ Object
Loads metadata for a GPG key.
- .sh(args) ⇒ Object
-
.signrpm(rpm, gpg_key) ⇒ Object
Signs the given RPM with the given gpg_key (see Simp::RPM.load_key for details on the value of this parameter).
Instance Method Summary collapse
-
#initialize(rpm_source) ⇒ RPM
constructor
Constructs a new Simp::RPM object.
Constructor Details
#initialize(rpm_source) ⇒ RPM
Constructs a new Simp::RPM object. Requires the path to the spec file from which information will be gathered.
The following information will be retreived:
- basename
-
The name of the package (as it would be queried in yum)
- version
-
The version of the package
- release
-
The release version of the package
* NOTE: If this is a 'spec' file, it will stop on the first '%'
encountered!
- full_version
-
The full version of the package: [version]-
- name
-
The full name of the package: [basename]-
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/simp/rpm.rb', line 30 def initialize(rpm_source) info = Simp::RPM.get_info(rpm_source) @basename = info[:name] @version = info[:version] @release = info[:release] @full_version = info[:full_version] @name = "#{@basename}-#{@full_version}" @sources = Array.new @verbose = false end |
Instance Attribute Details
#basename ⇒ Object
Returns the value of attribute basename.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def basename @basename end |
#full_version ⇒ Object
Returns the value of attribute full_version.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def full_version @full_version end |
#name ⇒ Object
Returns the value of attribute name.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def name @name end |
#release ⇒ Object
Returns the value of attribute release.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def release @release end |
#sources ⇒ Object
Returns the value of attribute sources.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def sources @sources end |
#verbose ⇒ Object
Returns the value of attribute verbose.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def verbose @verbose end |
#version ⇒ Object
Returns the value of attribute version.
11 12 13 |
# File 'lib/simp/rpm.rb', line 11 def version @version end |
Class Method Details
.copy_wo_vcs(start_dir, src, dest, dereference = true) ⇒ Object
Copies specific content from one directory to another.
- start_dir
-
the root directory where the original files are located within
- src
-
a pattern given to find(1) to match against the desired files to copy
- dest
-
the destination directory to receive the copies
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/simp/rpm.rb', line 45 def self.copy_wo_vcs(start_dir, src, dest, dereference=true) if dereference.nil? || dereference dereference = "--dereference" else dereference = "" end Dir.chdir(start_dir) do sh %{find #{src} \\( -path "*/.svn" -a -type d -o -path "*/.git*" \\) -prune -o -print | cpio -u --warning none --quiet --make-directories #{dereference} -p "#{dest}" 2>&1 > /dev/null} end end |
.execute(cmd) ⇒ Object
Executes a command and returns a hash with the exit status, stdout output and stderr output.
- cmd
-
command to be executed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/simp/rpm.rb', line 60 def self.execute(cmd) #puts "Executing: [#{cmd}]" outfile = File.join('/tmp', "#{ENV['USER']}_#{SecureRandom.hex}") errfile = File.join('/tmp', "#{ENV['USER']}_#{SecureRandom.hex}") pid = spawn(cmd, :out=>outfile, :err=>errfile) begin pid,status = Process.wait2(pid) rescue Errno::ECHILD # process exited before status could be determined end exit_status = status.nil? ? nil : status.exitstatus stdout = IO.read(outfile) stderr = IO.read(errfile) { :exit_status => exit_status, :stdout => stdout, :stderr => stderr } ensure FileUtils.rm_f([outfile, errfile]) end |
.get_info(rpm_source, mock_hash = nil) ⇒ Object
Parses information, such as the version, from the given specfile or RPM into a hash.
Can take an optional mock hash that should have the following structure:
:command => The actual mock command to run
:rpm_extras => Extra arguments to pass to RPM. This will probably be a
reference to the spec file itself
90 91 92 93 94 95 96 97 98 99 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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/simp/rpm.rb', line 90 def self.get_info(rpm_source, mock_hash=nil) info = { :has_dist_tag => false } rpm_cmd = "rpm -q --queryformat '%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n'" if mock_hash # Suppression of error messages is a hack for the following # scenario: # * The RPM spec file has an invalid date in its %changelog. # * The 'bogus date' warning message from rpmbuild # is sent to stderr, while RPM name, version, and release # info is sent to stdout. # * mock combines stdout and stderr in the command run. # * The 'bogus date' warning message is parsed to generate # the RPM info, instead of the RPM info message. rpm_cmd = mock_hash[:command] + ' ' + '"' + rpm_cmd + ' ' + mock_hash[:rpm_extras] + ' 2>/dev/null"' end if File.readable?(rpm_source) if File.read(rpm_source).include?('%{?dist}') info[:has_dist_tag] = true end if rpm_source.split('.').last == 'rpm' results = execute("#{rpm_cmd} -p #{rpm_source}") elsif mock_hash results = execute("#{rpm_cmd}") if info[:has_dist_tag] info[:dist_tag] = execute(%(#{mock_hash[:command]} --chroot 'rpm --eval "%{dist}"' 2>/dev/null))[:stdout].strip info[:dist_tag] = nil if (info[:dist_tag][0].chr == '%') end else results = execute("#{rpm_cmd} --specfile #{rpm_source}") end if results[:exit_status] != 0 raise "\#{indent('Error getting RPM info:', 2)}\n\#{indent(results[:stderr].strip, 5)}\n\#{indent(\"Run '\#{rpm_cmd.gsub(\"\\n\",'\\\\n')} --specfile \#{rpm_source}' to recreate the issue.\", 2)}\n" end info[:name], info[:version], info[:release], info[:arch] = results[:stdout].strip.split("\n").first.split(' ') else raise "Error: unable to read '#{rpm_source}'" end info[:full_version] = "#{info[:version]}-#{info[:release]}" return info end |
.indent(message, indent_length) ⇒ Object
147 148 149 |
# File 'lib/simp/rpm.rb', line 147 def self.indent(, indent_length) .split("\n").map {|line| ' '*indent_length + line }.join("\n") end |
.load_key(gpg_key) ⇒ Object
Loads metadata for a GPG key. The GPG key is to be used to sign RPMs. The value of gpg_key should be the full path of the directory where the key resides. If the metadata cannot be found, then the user will be prompted for it.
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 181 182 183 184 185 186 187 188 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 218 219 220 221 222 223 |
# File 'lib/simp/rpm.rb', line 155 def self.load_key(gpg_key) keydir = gpg_key File.directory?(keydir) || fail("Error: Could not find '#{keydir}'") gpg_key = File.basename(gpg_key) if @@gpg_keys[gpg_key] return @@gpg_keys[gpg_key] end gpg_name = nil gpg_password = nil begin File.read("#{keydir}/gengpgkey").each_line do |ln| name_line = ln.split(/^\s*Name-Email:/) if name_line.length > 1 gpg_name = name_line.last.strip end passwd_line = ln.split(/^\s*Passphrase:/) if passwd_line.length > 1 gpg_password = passwd_line.last.strip end end rescue Errno::ENOENT end if gpg_name.nil? puts "Warning: Could not find valid e-mail address for use with GPG." puts "Please enter e-mail address to use:" gpg_name = $stdin.gets.strip end if gpg_password.nil? if File.exist?(%(#{keydir}/password)) gpg_password = File.read(%(#{keydir}/password)).chomp end if gpg_password.nil? puts "Warning: Could not find a password in '#{keydir}/password'!" puts "Please enter your GPG key password:" system 'stty -echo' gpg_password = $stdin.gets.strip system 'stty echo' end end gpg_key_size = nil gpg_key_id = nil %x(gpg --homedir=#{keydir} --list-keys #{gpg_name} 2>&1).each_line do |line| head,data = line.split(/\s+/) if head == 'pub' gpg_key_size,gpg_key_id = data.split('/') break end end if !gpg_key_size || !gpg_key_id fail("Error getting GPG Key metadata") end @@gpg_keys[gpg_key] = { :dir => keydir, :name => gpg_name, :key_id => gpg_key_id, :key_size => gpg_key_size, :password => gpg_password } end |
.sh(args) ⇒ Object
14 15 16 |
# File 'lib/simp/rpm.rb', line 14 def self.sh(args) system args end |
.signrpm(rpm, gpg_key) ⇒ Object
Signs the given RPM with the given gpg_key (see Simp::RPM.load_key for details on the value of this parameter).
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/simp/rpm.rb', line 227 def self.signrpm(rpm, gpg_key) gpgkey = load_key(gpg_key) gpg_sig = nil %x(rpm -Kv #{rpm}).each_line do |line| if line =~ /key\sID\s(.*):/ gpg_sig = $1.strip end end unless gpg_sig == gpgkey[:key_id] signcommand = "rpm " + "--define '%_signature gpg' " + "--define '%__gpg %{_bindir}/gpg' " + "--define '%_gpg_name #{gpgkey[:name]}' " + "--define '%_gpg_path #{gpgkey[:dir]}' " + "--resign #{rpm}" begin PTY.spawn(signcommand) do |read, write, pid| begin while !read.eof? do read.expect(/pass\s?phrase:.*/) do |text| write.puts(gpgkey[:password]) write.flush end end rescue Errno::EIO # This ALWAYS happens in Ruby 1.8. end Process.wait(pid) end raise "Failure running #{signcommand}" unless $?.success? rescue Exception => e puts "Error occured while attempting to sign #{rpm}, skipping." puts e end end end |