tpkg 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/Rakefile +1 -1
  2. data/bin/tpkg +28 -23
  3. data/lib/tpkg.rb +243 -233
  4. data/lib/tpkg/deployer.rb +37 -32
  5. metadata +2 -2
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ spec = Gem::Specification.new do |s|
5
5
  s.add_dependency('facter')
6
6
  s.add_dependency('net-ssh')
7
7
  s.add_dependency('ddao-kwalify')
8
- s.version = '2.0.1'
8
+ s.version = '2.1.0'
9
9
  s.authors = ['Darren Dao', 'Jason Heiss']
10
10
  s.email = 'tpkg-users@lists.sourceforge.net'
11
11
  s.homepage = 'http://tpkg.sourceforge.net'
data/bin/tpkg CHANGED
@@ -9,7 +9,6 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
9
9
 
10
10
  require 'optparse'
11
11
  require 'tpkg'
12
- require 'etc'
13
12
 
14
13
  #
15
14
  # Parse the command line options
@@ -108,30 +107,36 @@ opts.on('--verify', '-V', '=NAME', 'Verify packages') do |opt|
108
107
  @action = :verify
109
108
  @action_value = opt
110
109
  end
111
- opts.on('--start', '=NAME', 'Start the init script for the specified package', Array) do |opt|
110
+ opts.on('--start', '=NAME', 'Start the init script for specified package', Array) do |opt|
112
111
  @rerun_with_sudo = true
113
112
  @action = :execute_init
114
113
  @init_options[:packages] = opt
115
114
  @init_options[:cmd] = 'start'
116
115
  end
117
- opts.on('--stop', '=NAME', 'Stop the init script for the specified package', Array) do |opt|
116
+ opts.on('--stop', '=NAME', 'Stop the init script for specified package', Array) do |opt|
118
117
  @rerun_with_sudo = true
119
118
  @action = :execute_init
120
119
  @init_options[:packages] = opt
121
120
  @init_options[:cmd] = 'stop'
122
121
  end
123
- opts.on('--restart', '=NAME', 'Restart the init script for the specified package', Array) do |opt|
122
+ opts.on('--restart', '=NAME', 'Restart the init script for specified package', Array) do |opt|
124
123
  @rerun_with_sudo = true
125
124
  @action = :execute_init
126
125
  @init_options[:packages] = opt
127
126
  @init_options[:cmd] = 'restart'
128
127
  end
129
- opts.on('--reload', '=NAME', 'Reload the init script for the specified package', Array) do |opt|
128
+ opts.on('--reload', '=NAME', 'Reload the init script for specified package', Array) do |opt|
130
129
  @rerun_with_sudo = true
131
130
  @action = :execute_init
132
131
  @init_options[:packages] = opt
133
132
  @init_options[:cmd] = 'reload'
134
133
  end
134
+ opts.on('--status', '=NAME', 'Get status from init script for specified package', Array) do |opt|
135
+ @rerun_with_sudo = true
136
+ @action = :execute_init
137
+ @init_options[:packages] = opt
138
+ @init_options[:cmd] = 'status'
139
+ end
135
140
  opts.on('--start-all', 'Start the init scripts for all packages') do |opt|
136
141
  @rerun_with_sudo = true
137
142
  @action = :execute_init
@@ -152,7 +157,7 @@ opts.on('--reload-all', 'Reload the init script for all packages') do |opt|
152
157
  @action = :execute_init
153
158
  @init_options[:cmd] = 'reload'
154
159
  end
155
- opts.on('--exec-init', '=NAME', 'Execute init scripts for the specified packages', Array) do |opt|
160
+ opts.on('--exec-init', '=NAME', 'Execute init scripts for specified packages', Array) do |opt|
156
161
  @rerun_with_sudo = true
157
162
  @init_options[:packages] = opt
158
163
  @action = :execute_init
@@ -161,7 +166,7 @@ opts.on('--init-script', '=NAME', 'What init scripts to execute', Array) do |opt
161
166
  @rerun_with_sudo = true
162
167
  @init_options[:scripts] = opt
163
168
  end
164
- opts.on('--init-cmd', '=CMD', 'Invoke the specified init script command') do |opt|
169
+ opts.on('--init-cmd', '=CMD', 'Invoke specified init script command') do |opt|
165
170
  @rerun_with_sudo = true
166
171
  @init_options[:cmd] = opt
167
172
  end
@@ -306,7 +311,7 @@ def instantiate_tpkg(options = {})
306
311
  sources = options["sources"] || []
307
312
  report_server = nil
308
313
 
309
- [File.join(Tpkg::CONFIGDIR, 'tpkg.conf'), File.join(ENV['HOME'], ".tpkg.conf")].each do |configfile|
314
+ [File.join(Tpkg::DEFAULT_CONFIGDIR, 'tpkg.conf'), File.join(ENV['HOME'], ".tpkg.conf")].each do |configfile|
310
315
  if File.exist?(configfile)
311
316
  IO.foreach(configfile) do |line|
312
317
  line.chomp!
@@ -337,23 +342,23 @@ def instantiate_tpkg(options = {})
337
342
  # if they don't realize there's an environment variable set.
338
343
  warn "Using base '#{base}' base from $TPKG_HOME"
339
344
  end
340
- if !@sudo
341
- curruid = Etc.getpwuid.uid
345
+
346
+ if !@sudo
347
+ curruid = Process.euid
342
348
  if curruid == 0
343
- puts "** ERROR **\n--no-sudo cannot be used as 'root' user or with sudo command."
344
- exit 1
345
- end
346
- if !File::exists?(File.join(ENV['HOME'], ".tpkg.conf"))
347
- puts "** ERROR **\nWhen specifying --no-sudo, #{File.join(ENV['HOME'], ".tpkg.conf")} and custom 'base' dir with write privileges is required\n" and exit 1
348
- elsif base == '/home/t'
349
- puts "** ERROR **\nWhen specifying --no-sudo, custom base dir with write privileges is required\n" and exit 1
349
+ # Besides there being no point to running with --no-sudo when root, we
350
+ # don't want users to accidentally create files/directories that can't be
351
+ # modified by other users who properly run --no-sudo as a regular user.
352
+ raise "--no-sudo cannot be used as 'root' user or via sudo"
350
353
  end
351
- baseuid = File.stat(base).uid
352
- if baseuid != curruid
353
- puts "** ERROR **\nbase dir (#{base}) not owned by you.\n"
354
- exit 1
354
+ baseuid = File.stat(base).uid
355
+ # We want to ensure that all --no-sudo usage within a given base directory
356
+ # is done under the same account.
357
+ if baseuid != curruid
358
+ raise "Base dir #{base} owned by UID #{baseuid}, not your UID #{curruid}"
355
359
  end
356
360
  end
361
+
357
362
  tpkg = Tpkg.new(:base => base, :sources => sources, :report_server => report_server, :lockforce => @lockforce, :force => @force, :sudo => @sudo)
358
363
  end
359
364
 
@@ -378,8 +383,8 @@ if @deploy
378
383
  @deploy_options["abort-on-fail"] = false
379
384
 
380
385
  # check to see if ssh-key is accessible
381
- ssh_key = @deploy_options["use-ssh-key"]
382
- if ssh_key && ssh_key.is_a?(String)
386
+ if @deploy_options["use-ssh-key"]
387
+ ssh_key = @deploy_options["ssh-key"]
383
388
  if !File.readable?(ssh_key) && Process.euid == 0
384
389
  raise "Unable to read ssh key from #{ssh_key}"
385
390
  elsif !File.readable?(ssh_key)
@@ -56,8 +56,7 @@ require 'kwalify' # for validating yaml
56
56
 
57
57
  class Tpkg
58
58
 
59
- VERSION = '2.0.1'
60
- CONFIGDIR = '/etc'
59
+ VERSION = '2.1.0'
61
60
 
62
61
  GENERIC_ERR = 1
63
62
  POSTINSTALL_ERR = 2
@@ -121,11 +120,11 @@ class Tpkg
121
120
  raise "Unable to find GNU tar or bsdtar in PATH"
122
121
  end
123
122
  end
124
- # bsdtar uses pax format by default. This format allows for vendor extensions, such
123
+ # bsdtar uses pax format by default. This format allows for vendor extensions, such
125
124
  # as the SCHILY.* extensions which were introduced by star). bsdtar actually uses
126
125
  # these extensions. These extension headers includde useful, but not vital information.
127
126
  # gnu tar should just ignore them and gives a warning. This is what the latest gnu tar
128
- # will do. However, on older gnu tar, it only threw an error at the end. The work
127
+ # will do. However, on older gnu tar, it only threw an error at the end. The work
129
128
  # around is to explicitly tell gnu tar to ignore those extensions.
130
129
  if @@tarinfo[:type] == 'gnu' && @@tarinfo[:version] != 'unknown' && @@tarinfo[:version] >= '1.15.1'
131
130
  @@taroptions = "--pax-option='delete=SCHILY.*,delete=LIBARCHIVE.*'"
@@ -286,7 +285,7 @@ class Tpkg
286
285
  # code (tar) ever touch the user's files.
287
286
  system("#{find_tar} -C #{pkgsrcdir} -cf - . | #{find_tar} -C #{tpkgdir} -xpf -") || raise("Package content copy failed")
288
287
 
289
- # check metadata file
288
+ # check metadata file
290
289
  errors = []
291
290
  metadata = Metadata::instantiate_from_dir(tpkgdir)
292
291
  if !metadata
@@ -298,14 +297,15 @@ class Tpkg
298
297
  schema_dir = File.join(File.dirname(File.dirname(__FILE__)), "schema")
299
298
  # This is the directory where we put our dtd/schema for validating
300
299
  # the metadata file
301
- elsif File.exist?(File.join(CONFIGDIR, 'tpkg', 'schema'))
302
- schema_dir = File.join(CONFIGDIR, 'tpkg', 'schema')
300
+ # FIXME: This method should become an instance method and use @configdir
301
+ elsif File.exist?(File.join(DEFAULT_CONFIGDIR, 'tpkg', 'schema'))
302
+ schema_dir = File.join(DEFAULT_CONFIGDIR, 'tpkg', 'schema')
303
303
  else
304
304
  warn "Warning: unable to find schema for tpkg.yml"
305
305
  end
306
306
 
307
307
  errors = metadata.validate(schema_dir) if schema_dir
308
- if errors && !errors.empty?
308
+ if errors && !errors.empty?
309
309
  puts "Bad metadata file. Possible error(s):"
310
310
  errors.each {|e| puts e }
311
311
  raise "Failed to create package." unless options[:force]
@@ -316,10 +316,10 @@ class Tpkg
316
316
  File.open(File.join(tpkgdir, "file_metadata.bin"), "w") do |file|
317
317
  filemetadata = get_filemetadata_from_directory(tpkgdir)
318
318
  filemetadata[:files].each do |file1|
319
- if metadata[:files] && metadata[:files][:files] &&
319
+ if metadata[:files] && metadata[:files][:files] &&
320
320
  metadata[:files][:files].any?{|file2|file2[:path] == file1[:path] && file2[:config]}
321
321
  file1[:config] = true
322
- end
322
+ end
323
323
  end
324
324
  data = filemetadata.to_hash.recursively{|h| h.stringify_keys }
325
325
  Marshal::dump(data, file)
@@ -344,7 +344,7 @@ class Tpkg
344
344
  data = {:actual_file => working_path, :metadata => metadata, :file_metadata => tpkgfile}
345
345
  perms, uid, gid = predict_file_perms_and_ownership(data)
346
346
  # crontab needs to be owned by root, and is not writable by group or others
347
- if uid != 0
347
+ if uid != 0
348
348
  warn "Warning: Your cron jobs in \"#{tpkgfile[:path]}\" might fail to run because the file is not owned by root."
349
349
  end
350
350
  if (perms & 0022) != 0
@@ -369,7 +369,7 @@ class Tpkg
369
369
  package_directory = File.join(workdir, package_filename)
370
370
  Dir.mkdir(package_directory)
371
371
 
372
- if outdir
372
+ if outdir
373
373
  pkgfile = File.join(outdir, package_filename + '.tpkg')
374
374
  else
375
375
  pkgfile = File.join(File.dirname(pkgsrcdir), package_filename + '.tpkg')
@@ -386,7 +386,7 @@ class Tpkg
386
386
  File.delete(pkgfile)
387
387
  end
388
388
 
389
- # update metadata file with the tpkg version
389
+ # update metadata file with the tpkg version
390
390
  metadata.add_tpkg_version(VERSION)
391
391
 
392
392
  # Tar up the tpkg directory
@@ -395,7 +395,7 @@ class Tpkg
395
395
 
396
396
  # Checksum the tarball
397
397
  # Older ruby version doesn't support this
398
- # digest = Digest::SHA256.file(tpkgfile).hexdigest
398
+ # digest = Digest::SHA256.file(tpkgfile).hexdigest
399
399
  digest = Digest::SHA256.hexdigest(File.read(tpkgfile))
400
400
 
401
401
  # Create checksum.xml
@@ -410,7 +410,7 @@ class Tpkg
410
410
 
411
411
  # compress if needed
412
412
  if options[:compress]
413
- tpkgfile = compress_file(tpkgfile, options[:compress])
413
+ tpkgfile = compress_file(tpkgfile, options[:compress])
414
414
  end
415
415
 
416
416
  # Tar up checksum.xml and the main tarball
@@ -494,7 +494,7 @@ class Tpkg
494
494
  return FileMetadata.new(Marshal::dump(filemetadata),'bin')
495
495
  end
496
496
 
497
- def self.verify_package_checksum(package_file, options = {})
497
+ def self.verify_package_checksum(package_file, options = {})
498
498
  topleveldir = options[:topleveldir] || package_toplevel_directory(package_file)
499
499
  # Extract checksum.xml from the package
500
500
  checksum_xml = nil
@@ -555,10 +555,10 @@ class Tpkg
555
555
  file = File.join('tpkg', "tpkg.#{format}")
556
556
 
557
557
  # use popen3 instead of popen because popen display stderr when there's an error such as
558
- # tpkg.yml not being there, which is something we want to ignore since old tpkg doesn't
558
+ # tpkg.yml not being there, which is something we want to ignore since old tpkg doesn't
559
559
  # have tpkg.yml file
560
560
  extract_tpkg_tar_command = cmd_to_extract_tpkg_tar(package_file, topleveldir)
561
- stdin, stdout, stderr = Open3.popen3("#{extract_tpkg_tar_command} | #{find_tar} -xf - -O #{file}")
561
+ stdin, stdout, stderr = Open3.popen3("#{extract_tpkg_tar_command} | #{find_tar} -xf - -O #{file}")
562
562
  filecontent = stdout.read
563
563
  if filecontent.nil? or filecontent.empty?
564
564
  next
@@ -975,33 +975,6 @@ class Tpkg
975
975
  gid.to_i
976
976
  end
977
977
 
978
- def self.gethttp(uri)
979
- if uri.scheme != 'http' && uri.scheme != 'https'
980
- # It would be possible to add support for FTP and possibly
981
- # other things if anyone cares
982
- raise "Only http/https URIs are supported, got: '#{uri}'"
983
- end
984
- http = Net::HTTP.new(uri.host, uri.port)
985
- if uri.scheme == 'https'
986
- # Eliminate the OpenSSL "using default DH parameters" warning
987
- if File.exist?(File.join(CONFIGDIR, 'tpkg', 'dhparams'))
988
- dh = OpenSSL::PKey::DH.new(IO.read(File.join(CONFIGDIR, 'tpkg', 'dhparams')))
989
- Net::HTTP.ssl_context_accessor(:tmp_dh_callback)
990
- http.tmp_dh_callback = proc { dh }
991
- end
992
- http.use_ssl = true
993
- if File.exist?(File.join(CONFIGDIR, 'tpkg', 'ca.pem'))
994
- http.ca_file = File.join(CONFIGDIR, 'tpkg', 'ca.pem')
995
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
996
- elsif File.directory?(File.join(CONFIGDIR, 'tpkg', 'ca'))
997
- http.ca_path = File.join(CONFIGDIR, 'tpkg', 'ca')
998
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
999
- end
1000
- end
1001
- http.start
1002
- http
1003
- end
1004
-
1005
978
  # foo
1006
979
  # foo=1.0
1007
980
  # foo=1.0=1
@@ -1012,7 +985,7 @@ class Tpkg
1012
985
  parts = request.split('=')
1013
986
 
1014
987
  # upgrade/remove/query options could take package filenames
1015
- # We're assuming that the filename ends in .tpkg and has a version number that starts
988
+ # We're assuming that the filename ends in .tpkg and has a version number that starts
1016
989
  # with a digit. For example: foo-1.0.tpkg, foo-bar-1.0-1.tpkg
1017
990
  if request =~ /\.tpkg$/
1018
991
  req = {:filename => request, :name => request.split(/-\d/)[0]}
@@ -1038,10 +1011,10 @@ class Tpkg
1038
1011
 
1039
1012
  # deploy_options is used for configuration the deployer. It is a map of option_names => option_values. Possible
1040
1013
  # options are: use-ssh-key, deploy-as, worker-count, abort-on-fail
1041
- #
1014
+ #
1042
1015
  # deploy_params is an array that holds the list of paramters that is used when invoking tpkg on to the remote
1043
- # servers where we want to deploy to.
1044
- #
1016
+ # servers where we want to deploy to.
1017
+ #
1045
1018
  # servers is an array, a filename or a callback that list the remote servers where we want to deploy to
1046
1019
  def self.deploy(deploy_params, deploy_options, servers)
1047
1020
  servers.uniq!
@@ -1105,7 +1078,7 @@ class Tpkg
1105
1078
  return File.basename(filename) !~ /^\./
1106
1079
  end
1107
1080
 
1108
- # helper method for predicting the permissions and ownership of a file that
1081
+ # helper method for predicting the permissions and ownership of a file that
1109
1082
  # will be installed by tpkg. This is done by looking at:
1110
1083
  # 1) its current perms & ownership
1111
1084
  # 2) the file_defaults settings of the metadata file
@@ -1138,7 +1111,7 @@ class Tpkg
1138
1111
  perms = file_metadata[:posix][:perms] if file_metadata[:posix][:perms]
1139
1112
  end
1140
1113
  return perms, uid, gid
1141
- end
1114
+ end
1142
1115
 
1143
1116
  # Given a package file, figure out if tpkg.tar was compressed
1144
1117
  # Return what type of compression. If tpkg.tar wasn't compressed, then return nil.
@@ -1147,7 +1120,7 @@ class Tpkg
1147
1120
  IO.popen("#{find_tar} #{@@taroptions} -tf #{package_file}") do |pipe|
1148
1121
  pipe.each do |file|
1149
1122
  if file =~ /tpkg.tar.gz$/
1150
- compression = "gzip"
1123
+ compression = "gzip"
1151
1124
  elsif file =~ /tpkg.tar.bz2$/
1152
1125
  compression = "bz2"
1153
1126
  end
@@ -1170,7 +1143,7 @@ class Tpkg
1170
1143
  end
1171
1144
 
1172
1145
  # Compresses the file using the compression type
1173
- # specified by the compress flag
1146
+ # specified by the compress flag
1174
1147
  # Returns the compressed file
1175
1148
  def self.compress_file(file, compress)
1176
1149
  if compress == true or compress == "gzip"
@@ -1183,7 +1156,7 @@ class Tpkg
1183
1156
  raise "Compression #{compress} is not supported"
1184
1157
  end
1185
1158
  if !$?.success? or !File.exists?(result)
1186
- raise "Failed to compress the package"
1159
+ raise "Failed to compress the package"
1187
1160
  end
1188
1161
  return result
1189
1162
  end
@@ -1203,10 +1176,11 @@ class Tpkg
1203
1176
  #
1204
1177
 
1205
1178
  DEFAULT_BASE = '/opt/tpkg'
1179
+ DEFAULT_CONFIGDIR = '/etc'
1206
1180
 
1207
1181
  def initialize(options)
1208
1182
  # Options
1209
- @base = options[:base]
1183
+ @base = options[:base] ? options[:base] : DEFAULT_BASE
1210
1184
  # An array of filenames or URLs which point to individual package files
1211
1185
  # or directories containing packages and extracted metadata.
1212
1186
  @sources = []
@@ -1238,11 +1212,14 @@ class Tpkg
1238
1212
  @sudo = options[:sudo]
1239
1213
  end
1240
1214
 
1215
+ @configdir = DEFAULT_CONFIGDIR
1216
+
1241
1217
  @file_system_root = '/' # Not sure if this needs to be more portable
1242
1218
  # This option is only intended for use by the test suite
1243
1219
  if options[:file_system_root]
1244
1220
  @file_system_root = options[:file_system_root]
1245
1221
  @base = File.join(@file_system_root, @base)
1222
+ @configdir = File.join(@file_system_root, @configdir)
1246
1223
  end
1247
1224
 
1248
1225
  # Various external scripts that we run might need to adjust things for
@@ -1264,7 +1241,7 @@ class Tpkg
1264
1241
  if Tpkg::get_os =~ /Darwin/
1265
1242
  # Try to help our Mac OS X users, otherwise this could be
1266
1243
  # rather confusing.
1267
- warn "\nNote: /home is controlled by the automounter by default on Mac OS X.\n" +
1244
+ warn "\nNote: /home is controlled by the automounter by default on Mac OS X.\n" +
1268
1245
  "You'll either need to disable that in /etc/auto_master or configure\n" +
1269
1246
  "tpkg to use a different base via tpkg.conf.\n"
1270
1247
  end
@@ -1277,7 +1254,7 @@ class Tpkg
1277
1254
  @tmp_directory = File.join(@var_directory, 'tmp')
1278
1255
  @log_directory = File.join(@var_directory, 'logs')
1279
1256
  # It is important to create these dirs in correct order
1280
- dirs_to_create = [@installed_directory, @metadata_directory, @sources_directory,
1257
+ dirs_to_create = [@installed_directory, @metadata_directory, @sources_directory,
1281
1258
  @tmp_directory, @log_directory]
1282
1259
  dirs_to_create.each do |dir|
1283
1260
  if !File.exist?(dir)
@@ -1305,6 +1282,33 @@ class Tpkg
1305
1282
  attr_reader :sudo
1306
1283
  attr_reader :file_system_root
1307
1284
 
1285
+ def gethttp(uri)
1286
+ if uri.scheme != 'http' && uri.scheme != 'https'
1287
+ # It would be possible to add support for FTP and possibly
1288
+ # other things if anyone cares
1289
+ raise "Only http/https URIs are supported, got: '#{uri}'"
1290
+ end
1291
+ http = Net::HTTP.new(uri.host, uri.port)
1292
+ if uri.scheme == 'https'
1293
+ # Eliminate the OpenSSL "using default DH parameters" warning
1294
+ if File.exist?(File.join(@configdir, 'tpkg', 'dhparams'))
1295
+ dh = OpenSSL::PKey::DH.new(IO.read(File.join(@configdir, 'tpkg', 'dhparams')))
1296
+ Net::HTTP.ssl_context_accessor(:tmp_dh_callback)
1297
+ http.tmp_dh_callback = proc { dh }
1298
+ end
1299
+ http.use_ssl = true
1300
+ if File.exist?(File.join(@configdir, 'tpkg', 'ca.pem'))
1301
+ http.ca_file = File.join(@configdir, 'tpkg', 'ca.pem')
1302
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
1303
+ elsif File.directory?(File.join(@configdir, 'tpkg', 'ca'))
1304
+ http.ca_path = File.join(@configdir, 'tpkg', 'ca')
1305
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
1306
+ end
1307
+ end
1308
+ http.start
1309
+ http
1310
+ end
1311
+
1308
1312
  def source_to_local_directory(source)
1309
1313
  source_as_directory = source.gsub(/[^a-zA-Z0-9]/, '')
1310
1314
  File.join(@sources_directory, source_as_directory)
@@ -1327,22 +1331,22 @@ class Tpkg
1327
1331
  warn "Warning: the source directory #{source} has no metadata.yml file. Try running tpkg -x #{source} first."
1328
1332
  next
1329
1333
  end
1330
-
1334
+
1331
1335
  metadata_contents = File.read(File.join(source, 'metadata.yml'))
1332
1336
  Metadata::get_pkgs_metadata_from_yml_doc(metadata_contents, metadata, source)
1333
1337
  else
1334
1338
  uri = http = localdate = remotedate = localdir = localpath = nil
1335
-
1339
+
1336
1340
  uri = URI.join(source, 'metadata.yml')
1337
- http = Tpkg::gethttp(uri)
1338
-
1341
+ http = gethttp(uri)
1342
+
1339
1343
  # Calculate the path to the local copy of the metadata for this URI
1340
1344
  localdir = source_to_local_directory(source)
1341
1345
  localpath = File.join(localdir, 'metadata.yml')
1342
1346
  if File.exist?(localpath)
1343
1347
  localdate = File.mtime(localpath)
1344
1348
  end
1345
-
1349
+
1346
1350
  # get last modified time of the metadata file from the server
1347
1351
  response = http.head(uri.path)
1348
1352
  case response
@@ -1352,7 +1356,7 @@ class Tpkg
1352
1356
  puts "Error fetching metadata from #{uri}: #{response.body}"
1353
1357
  response.error! # Throws an exception
1354
1358
  end
1355
-
1359
+
1356
1360
  # Fetch the metadata if necessary
1357
1361
  metadata_contents = nil
1358
1362
  if !localdate || remotedate != localdate
@@ -1406,7 +1410,7 @@ class Tpkg
1406
1410
  # Populate our list of available packages for a given package name
1407
1411
  def load_available_packages(name=nil)
1408
1412
  prep_metadata
1409
-
1413
+
1410
1414
  if name
1411
1415
  if !@available_packages[name]
1412
1416
  packages = []
@@ -1417,7 +1421,7 @@ class Tpkg
1417
1421
  end
1418
1422
  end
1419
1423
  @available_packages[name] = packages
1420
-
1424
+
1421
1425
  if @@debug
1422
1426
  puts "Loaded #{@available_packages[name].size} available packages for #{name}"
1423
1427
  end
@@ -1436,7 +1440,7 @@ class Tpkg
1436
1440
  end
1437
1441
  end
1438
1442
  end
1439
-
1443
+
1440
1444
  # Used by load_available_native_packages to stuff all the info about a
1441
1445
  # native package into a hash to match the structure we pass around
1442
1446
  # internally for tpkgs
@@ -1483,7 +1487,7 @@ class Tpkg
1483
1487
  elsif line =~ /^\s*$/
1484
1488
  pkg = pkg_for_native_package(name, version, package_version, yum[:source])
1485
1489
  native_packages << pkg
1486
- name = version = package_version = nil
1490
+ name = version = package_version = nil
1487
1491
  end
1488
1492
  # In the end we ignore the architecture. Anything that
1489
1493
  # shows up in yum should be installable on this box, and
@@ -1783,7 +1787,7 @@ class Tpkg
1783
1787
 
1784
1788
  if File.directory?(@metadata_directory)
1785
1789
  Dir.foreach(@metadata_directory) do |entry|
1786
- next if entry == '.' || entry == '..'
1790
+ next if entry == '.' || entry == '..'
1787
1791
  next if package_files && !package_files.include?(entry)
1788
1792
  file_metadata = FileMetadata::instantiate_from_dir(File.join(@metadata_directory, entry))
1789
1793
  ret[file_metadata[:package_file]] = file_metadata
@@ -1802,8 +1806,8 @@ class Tpkg
1802
1806
  else
1803
1807
  pkgs = []
1804
1808
  if req
1805
- req = req.clone # we're using req as the key for our cache, so it's important
1806
- # that we clone it here. Otherwise, req can be changed later on from
1809
+ req = req.clone # we're using req as the key for our cache, so it's important
1810
+ # that we clone it here. Otherwise, req can be changed later on from
1807
1811
  # the calling method and modify our cache inadvertently
1808
1812
  if req[:type] == :native
1809
1813
  load_available_native_packages(req[:name])
@@ -1904,7 +1908,7 @@ class Tpkg
1904
1908
  end
1905
1909
  def normalize_path(path,root=nil,base=nil)
1906
1910
  root ||= @file_system_root
1907
- base ||= @base
1911
+ base ||= @base
1908
1912
  if path[0,1] == File::SEPARATOR
1909
1913
  normalized_path = File.join(root, path)
1910
1914
  else
@@ -2257,7 +2261,7 @@ class Tpkg
2257
2261
  end
2258
2262
 
2259
2263
  def download(source, path, downloaddir = nil, use_cache = true)
2260
- http = Tpkg::gethttp(URI.parse(source))
2264
+ http = gethttp(URI.parse(source))
2261
2265
  localdir = source_to_local_directory(source)
2262
2266
  localpath = File.join(localdir, File.basename(path))
2263
2267
  # Don't download again if file is already there from previous installation
@@ -2276,10 +2280,10 @@ class Tpkg
2276
2280
  # If downloaddir is specified, then download to that directory. Otherwise,
2277
2281
  # download to default source directory
2278
2282
  localdir = downloaddir || localdir
2279
- if !File.exist?(localdir)
2283
+ if !File.exist?(localdir)
2280
2284
  FileUtils.mkdir_p(localdir)
2281
2285
  end
2282
- localpath = File.join(localdir, File.basename(path))
2286
+ localpath = File.join(localdir, File.basename(path))
2283
2287
  end
2284
2288
  uri = URI.join(source, path)
2285
2289
  tmpfile = Tempfile.new(File.basename(localpath), File.dirname(localpath))
@@ -2319,7 +2323,7 @@ class Tpkg
2319
2323
  installed_path = normalize_path(tpkg_path)
2320
2324
  init_scripts[installed_path] = tpkgfile
2321
2325
  end
2322
- end
2326
+ end
2323
2327
  init_scripts
2324
2328
  end
2325
2329
 
@@ -2353,24 +2357,24 @@ class Tpkg
2353
2357
  Tpkg::get_os =~ /Solaris/
2354
2358
  init_directory = File.join(@file_system_root, 'etc')
2355
2359
  end
2356
-
2360
+
2357
2361
  # in case user specify levels in yaml as string/integer instead of array
2358
2362
  if !levels.kind_of?(Array)
2359
2363
  levels = levels.to_s.split(//)
2360
2364
  end
2361
-
2365
+
2362
2366
  levels.each do |level|
2363
2367
  links[File.join(init_directory, "rc#{level}.d", 'S' + start.to_s + File.basename(installed_path))] = installed_path
2364
2368
  end
2365
2369
  elsif Tpkg::get_os =~ /FreeBSD/
2366
- init_directory = File.join(@file_system_root, 'usr', 'local', 'etc', 'rc.d')
2370
+ init_directory = File.join(@file_system_root, 'usr', 'local', 'etc', 'rc.d')
2367
2371
  if tpkgfile[:init][:levels] && tpkgfile[:init][:levels].empty?
2368
2372
  # User doesn't want the init script linked in to auto-start
2369
2373
  else
2370
2374
  links[File.join(init_directory, File.basename(installed_path))] = installed_path
2371
2375
  end
2372
2376
  else
2373
- raise "No init script support for #{Tpkg::get_os}"
2377
+ warn "No init script support for #{Tpkg::get_os}"
2374
2378
  end
2375
2379
  end
2376
2380
  links
@@ -2380,12 +2384,12 @@ class Tpkg
2380
2384
  # package and where they need to be installed on the system
2381
2385
  def crontab_destinations(metadata)
2382
2386
  destinations = {}
2383
-
2387
+
2384
2388
  # Don't do anything unless we have to
2385
2389
  unless metadata[:files] && metadata[:files][:files]
2386
2390
  return destinations
2387
2391
  end
2388
-
2392
+
2389
2393
  metadata[:files][:files].each do |tpkgfile|
2390
2394
  if tpkgfile[:crontab]
2391
2395
  tpkg_path = tpkgfile[:path]
@@ -2429,7 +2433,7 @@ class Tpkg
2429
2433
  destinations[installed_path][:link] = File.join(@file_system_root, 'etc', 'cron.d', File.basename(installed_path))
2430
2434
  end
2431
2435
  else
2432
- raise "No crontab support for #{Tpkg::get_os}"
2436
+ warn "No crontab support for #{Tpkg::get_os}"
2433
2437
  end
2434
2438
  end
2435
2439
  end
@@ -2479,7 +2483,7 @@ class Tpkg
2479
2483
  def unpack(package_file, options={})
2480
2484
  ret_val = 0
2481
2485
 
2482
- # set env variable to let pre/post install know whether this unpack
2486
+ # set env variable to let pre/post install know whether this unpack
2483
2487
  # is part of an install or upgrade
2484
2488
  if options[:is_doing_upgrade]
2485
2489
  ENV['TPKG_ACTION'] = "upgrade"
@@ -2503,7 +2507,7 @@ class Tpkg
2503
2507
 
2504
2508
  metadata = Tpkg::metadata_from_package(package_file, {:topleveldir => topleveldir})
2505
2509
 
2506
- # Get list of files/directories that already exist in the system. Store their perm/ownership.
2510
+ # Get list of files/directories that already exist in the system. Store their perm/ownership.
2507
2511
  # That way, when we copy over the new files, we can set the new files to have the same perm/owernship.
2508
2512
  conflicting_files = {}
2509
2513
  fip = Tpkg::files_in_package(package_file)
@@ -2539,7 +2543,7 @@ class Tpkg
2539
2543
  end
2540
2544
 
2541
2545
  # Set default dir uid/gid to be same as for file.
2542
- default_dir_uid = default_uid
2546
+ default_dir_uid = default_uid
2543
2547
  default_dir_gid = default_gid
2544
2548
  default_dir_perms = 0755
2545
2549
 
@@ -2565,7 +2569,7 @@ class Tpkg
2565
2569
  if File.directory?(f)
2566
2570
  File.chown(default_dir_uid, default_dir_gid, f)
2567
2571
  else
2568
- File.chown(default_uid, default_gid, f)
2572
+ File.chown(default_uid, default_gid, f)
2569
2573
  end
2570
2574
  rescue Errno::EPERM
2571
2575
  raise if Process.euid == 0
@@ -2637,21 +2641,21 @@ class Tpkg
2637
2641
  (1..3).each do | i |
2638
2642
  begin
2639
2643
  Tpkg::decrypt(metadata[:name], working_path, options[:passphrase], *([tpkgfile[:encrypt][:algorithm]].compact))
2640
- break
2644
+ break
2641
2645
  rescue OpenSSL::CipherError
2642
2646
  @@passphrase = nil
2643
2647
  if i == 3
2644
- raise "Incorrect passphrase."
2648
+ raise "Incorrect passphrase."
2645
2649
  else
2646
2650
  puts "Incorrect passphrase. Try again."
2647
2651
  end
2648
2652
  end
2649
2653
  end
2650
2654
 
2651
- if File.file?(working_path)
2655
+ if File.file?(working_path)
2652
2656
  digest = Digest::SHA256.hexdigest(File.read(working_path))
2653
2657
  # get checksum for the decrypted file. Will be used for creating file_metadata
2654
- checksums_of_decrypted_files[File.expand_path(tpkg_path)] = digest
2658
+ checksums_of_decrypted_files[File.expand_path(tpkg_path)] = digest
2655
2659
  end
2656
2660
  end
2657
2661
  end
@@ -2786,11 +2790,14 @@ class Tpkg
2786
2790
 
2787
2791
  def install_crontabs(metadata)
2788
2792
  crontab_destinations(metadata).each do |crontab, destination|
2793
+ # FIXME: Besides the regex being ugly it is also only going to match on
2794
+ # Linux, need to figure out if there's a reason for that or if this can
2795
+ # be made more generic.
2789
2796
  if !@sudo && (destination[destination.keys.first] =~ /\/var\/spool\/cron/)
2790
- install_crontab_bycmd(metadata, crontab, destination)
2797
+ install_crontab_bycmd(metadata, crontab, destination)
2791
2798
  next
2792
2799
  end
2793
-
2800
+
2794
2801
  begin
2795
2802
  if destination[:link]
2796
2803
  install_crontab_link(metadata, crontab, destination)
@@ -2844,6 +2851,7 @@ class Tpkg
2844
2851
  end
2845
2852
  end
2846
2853
  end
2854
+ # FIXME: Can this be replaced by install_crontab_bycmd?
2847
2855
  def install_crontab_file(metadata, crontab, destination)
2848
2856
  if !File.exist?(File.dirname(destination[:file]))
2849
2857
  FileUtils.mkdir_p(File.dirname(destination[:file]))
@@ -2892,18 +2900,21 @@ class Tpkg
2892
2900
  tmpfh.write(oldcron) unless oldcron.empty?
2893
2901
  tmpfh.puts "### TPKG START - #{@base} - #{File.basename(metadata[:filename].to_s)}"
2894
2902
  tmpfh.write File.readlines(crontab)
2895
- tmpfh.puts "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}"
2903
+ tmpfh.puts "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}"
2896
2904
  tmpfh.close
2897
2905
  `crontab #{tmpf}`
2898
2906
  FileUtils.rm(tmpf)
2899
2907
  end
2900
2908
  def remove_crontabs(metadata)
2901
2909
  crontab_destinations(metadata).each do |crontab, destination|
2910
+ # FIXME: Besides the regex being ugly it is also only going to match on
2911
+ # Linux, need to figure out if there's a reason for that or if this can
2912
+ # be made more generic.
2902
2913
  if !@sudo && (destination[destination.keys.first] =~ /\/var\/spool\/cron/)
2903
- remove_crontab_bycmd(metadata, crontab, destination)
2914
+ remove_crontab_bycmd(metadata, crontab, destination)
2904
2915
  next
2905
2916
  end
2906
-
2917
+
2907
2918
  begin
2908
2919
  if destination[:link]
2909
2920
  remove_crontab_link(metadata, crontab, destination)
@@ -2935,6 +2946,7 @@ class Tpkg
2935
2946
  end
2936
2947
  end
2937
2948
  end
2949
+ # FIXME: Can this be replaced by remove_crontab_bycmd?
2938
2950
  def remove_crontab_file(metadata, crontab, destination)
2939
2951
  if File.exist?(destination[:file])
2940
2952
  tmpfile = Tempfile.new(File.basename(destination[:file]), File.dirname(destination[:file]))
@@ -3099,8 +3111,8 @@ class Tpkg
3099
3111
  if file_metadata
3100
3112
  file_metadata[:package_file] = File.basename(package_file)
3101
3113
  file_metadata[:files].each do |file|
3102
- # update file_metadata with user/group ownership and permission
3103
- acl = files_info[file[:path]]
3114
+ # update file_metadata with user/group ownership and permission
3115
+ acl = files_info[file[:path]]
3104
3116
  file.merge!(acl) unless acl.nil?
3105
3117
 
3106
3118
  # update file_metadata with the checksums of decrypted files
@@ -3212,7 +3224,7 @@ class Tpkg
3212
3224
  else # basic package specs ('foo' or 'foo=1.0')
3213
3225
  puts "parse_requests request looks like package spec" if @@debug
3214
3226
 
3215
- # Tpkg::parse_request is a class method and doesn't know where packages are installed.
3227
+ # Tpkg::parse_request is a class method and doesn't know where packages are installed.
3216
3228
  # So we have to tell it ourselves.
3217
3229
  req = Tpkg::parse_request(request, @installed_directory)
3218
3230
  newreqs << req
@@ -3230,14 +3242,14 @@ class Tpkg
3230
3242
 
3231
3243
  # After calling parse_request, we should call this method
3232
3244
  # to check whether or not we can meet the requirements/dependencies
3233
- # of the result packages
3245
+ # of the result packages
3234
3246
  def check_requests(packages)
3235
3247
  all_requests_satisfied = true # whether or not all requests can be satisfied
3236
3248
  errors = [""]
3237
3249
  packages.each do |name, pkgs|
3238
3250
  if pkgs.empty?
3239
3251
  errors << ["Unable to find any packages which satisfy #{name}"]
3240
- all_requests_satisfied = false
3252
+ all_requests_satisfied = false
3241
3253
  next
3242
3254
  end
3243
3255
 
@@ -3268,7 +3280,7 @@ class Tpkg
3268
3280
  if !request_satisfied
3269
3281
  errors << ["Unable to find any packages which satisfy #{name}. Possible error(s):"]
3270
3282
  errors << possible_errors
3271
- all_requests_satisfied = false
3283
+ all_requests_satisfied = false
3272
3284
  end
3273
3285
  end
3274
3286
 
@@ -3373,12 +3385,12 @@ class Tpkg
3373
3385
  puts "The package(s) you're trying to install conflict with the following package(s):"
3374
3386
  conflicting_pkgs = conflicting_pkgs.collect{|pkg|pkg[:metadata][:filename]}
3375
3387
  puts conflicting_pkgs.join("\n")
3376
- if options[:force_replace]
3388
+ if options[:force_replace]
3377
3389
  puts "Attemping to replace the conflicting packages."
3378
3390
  success = remove(conflicting_pkgs)
3379
3391
  return success
3380
3392
  else
3381
- puts "Try removing the conflicting package(s) first, or rerun tpkg with the --force-replace option."
3393
+ puts "Try removing the conflicting package(s) first, or rerun tpkg with the --force-replace option."
3382
3394
  return false
3383
3395
  end
3384
3396
  end
@@ -3442,7 +3454,7 @@ class Tpkg
3442
3454
  end
3443
3455
  true
3444
3456
  end
3445
-
3457
+
3446
3458
  # See parse_requests for format of requests
3447
3459
  def install(requests, passphrase=nil, options={})
3448
3460
  ret_val = 0
@@ -3451,7 +3463,7 @@ class Tpkg
3451
3463
  lock
3452
3464
  parse_requests(requests, requirements, packages)
3453
3465
  check_requests(packages)
3454
-
3466
+
3455
3467
  core_packages = []
3456
3468
  requirements.each do |req|
3457
3469
  core_packages << req[:name] if !core_packages.include?(req[:name])
@@ -3461,7 +3473,6 @@ class Tpkg
3461
3473
  puts "install requirements: #{requirements.inspect}" if @@debug
3462
3474
  puts "install packages: #{packages.inspect}" if @@debug
3463
3475
  puts "install core_packages: #{core_packages.inspect}" if @@debug
3464
- #solution_packages = best_solution(requirements.dup, packages.dup)
3465
3476
  solution_packages = best_solution(requirements, packages, core_packages)
3466
3477
  if !solution_packages
3467
3478
  raise "Unable to resolve dependencies. Try running with --debug for more info"
@@ -3469,26 +3480,26 @@ class Tpkg
3469
3480
 
3470
3481
  success = handle_conflicting_pkgs(installed_packages, solution_packages, options)
3471
3482
  return false if !success
3472
-
3483
+
3473
3484
  if !prompt_for_install(solution_packages, 'installed')
3474
3485
  unlock
3475
3486
  return false
3476
3487
  end
3477
-
3488
+
3478
3489
  # Build an array of metadata of pkgs that are already installed
3479
3490
  # We will use this later on to figure out what new packages have been installed/removed
3480
3491
  # in order to report back to the server
3481
3492
  already_installed_pkgs = metadata_for_installed_packages.collect{|metadata| metadata.to_hash}
3482
-
3493
+
3483
3494
  # Create array of packages (names) we have installed so far
3484
3495
  # We will use it later on to determine the order of how to install the packages
3485
- installed_so_far = installed_packages.collect{|pkg| pkg[:metadata][:name]}
3486
-
3496
+ installed_so_far = installed_packages.collect{|pkg| pkg[:metadata][:name]}
3497
+
3487
3498
  while pkg = solution_packages.shift
3488
3499
  # get dependencies and make sure we install the packages in the correct order
3489
3500
  # based on the dependencies
3490
3501
  dependencies = nil
3491
- if pkg[:metadata][:dependencies]
3502
+ if pkg[:metadata][:dependencies]
3492
3503
  dependencies = pkg[:metadata][:dependencies].collect { |dep| dep[:name] }.compact
3493
3504
  # don't install this pkg right now if its dependencies haven't been installed
3494
3505
  if !dependencies.empty? && !dependencies.to_set.subset?(installed_so_far.to_set)
@@ -3496,7 +3507,7 @@ class Tpkg
3496
3507
  next
3497
3508
  end
3498
3509
  end
3499
-
3510
+
3500
3511
  if pkg[:source] == :currently_installed ||
3501
3512
  pkg[:source] == :native_installed
3502
3513
  # Nothing to do for packages currently installed
@@ -3583,17 +3594,17 @@ class Tpkg
3583
3594
  end
3584
3595
  end
3585
3596
  end
3586
-
3587
- # If we're down here, it means we have installed the package. So go ahead and
3597
+
3598
+ # If we're down here, it means we have installed the package. So go ahead and
3588
3599
  # update the list of packages we installed so far
3589
3600
  installed_so_far << pkg[:metadata][:name]
3590
3601
  end # end while loop
3591
-
3602
+
3592
3603
  # log changes
3593
3604
  currently_installed = metadata_for_installed_packages.collect{|metadata| metadata.to_hash}
3594
3605
  newly_installed = currently_installed - already_installed_pkgs
3595
3606
  log_changes({:newly_installed => newly_installed})
3596
-
3607
+
3597
3608
  # send udpate back to reporting server
3598
3609
  unless @report_server.nil?
3599
3610
  options = {:newly_installed => newly_installed, :currently_installed => currently_installed}
@@ -3602,7 +3613,7 @@ class Tpkg
3602
3613
  unlock
3603
3614
  return ret_val
3604
3615
  end
3605
-
3616
+
3606
3617
  # This method can also be used for doing downgrade
3607
3618
  def upgrade(requests=nil, passphrase=nil, options={})
3608
3619
  downgrade = options[:downgrade] || false
@@ -3626,14 +3637,14 @@ class Tpkg
3626
3637
  additional_requirements = []
3627
3638
  requirements.each do |req|
3628
3639
  core_packages << req[:name] if !core_packages.include?(req[:name])
3629
-
3640
+
3630
3641
  # When doing downgrade, we don't want to include the package being
3631
3642
  # downgrade as the requirements. Otherwise, we won't be able to downgrade it
3632
- unless downgrade
3643
+ unless downgrade
3633
3644
  additional_requirements.concat(
3634
3645
  requirements_for_currently_installed_package(req[:name]))
3635
3646
  end
3636
-
3647
+
3637
3648
  # Initialize the list of possible packages for this req
3638
3649
  if !packages[req[:name]]
3639
3650
  packages[req[:name]] = available_packages_that_meet_requirement(req)
@@ -3644,7 +3655,7 @@ class Tpkg
3644
3655
  pkg[:prefer] = false
3645
3656
  end
3646
3657
  end
3647
-
3658
+
3648
3659
  # Look for pkgs that might depend on the pkg we're upgrading,
3649
3660
  # and add them to our list of requirements. We need to make sure that we can still
3650
3661
  # satisfy the dependency requirements if we were to do the upgrade.
@@ -3682,16 +3693,15 @@ class Tpkg
3682
3693
  puts "upgrade requirements: #{requirements.inspect}" if @@debug
3683
3694
  puts "upgrade packages: #{packages.inspect}" if @@debug
3684
3695
  puts "upgrade core_packages: #{core_packages.inspect}" if @@debug
3685
- #solution_packages = best_solution(requirements.dup, packages.dup)
3686
3696
  solution_packages = best_solution(requirements, packages, core_packages)
3687
-
3697
+
3688
3698
  if solution_packages.nil?
3689
3699
  raise "Unable to find solution for upgrading. Please verify that you specified the correct package(s) for upgrade. Try running with --debug for more info"
3690
3700
  end
3691
-
3701
+
3692
3702
  success = handle_conflicting_pkgs(installed_packages, solution_packages, options)
3693
3703
  return false if !success
3694
-
3704
+
3695
3705
  if downgrade
3696
3706
  prompt_action = 'downgraded'
3697
3707
  else
@@ -3701,7 +3711,7 @@ class Tpkg
3701
3711
  unlock
3702
3712
  return false
3703
3713
  end
3704
-
3714
+
3705
3715
  # Build an array of metadata of pkgs that are already installed
3706
3716
  # We will use this later on to figure out what new packages have been installed/removed
3707
3717
  # in order to report back to the server
@@ -3842,7 +3852,7 @@ class Tpkg
3842
3852
  end
3843
3853
  end
3844
3854
 
3845
- # log changes
3855
+ # log changes
3846
3856
  currently_installed = metadata_for_installed_packages.collect{|metadata| metadata.to_hash}
3847
3857
  newly_installed = currently_installed - already_installed_pkgs
3848
3858
  removed = already_installed_pkgs - currently_installed
@@ -3851,7 +3861,7 @@ class Tpkg
3851
3861
  # send update back to reporting server
3852
3862
  if !has_updates
3853
3863
  puts "No updates available"
3854
- elsif !@report_server.nil?
3864
+ elsif !@report_server.nil?
3855
3865
  options = {:newly_installed => newly_installed, :removed => removed,
3856
3866
  :currently_installed => currently_installed}
3857
3867
  send_update_to_server(options)
@@ -3882,12 +3892,12 @@ class Tpkg
3882
3892
  unlock
3883
3893
  return false
3884
3894
  end
3885
-
3895
+
3886
3896
  # Build an array of metadata of pkgs that are already installed
3887
3897
  # We will use this later on to figure out what new packages have been installed/removed
3888
3898
  # in order to report back to the server
3889
3899
  already_installed_pkgs = metadata_for_installed_packages.collect{|metadata| metadata.to_hash}
3890
-
3900
+
3891
3901
  # If user want to remove all the dependent pkgs, then go ahead
3892
3902
  # and include them in our array of things to remove
3893
3903
  if options[:remove_all_dep]
@@ -3897,7 +3907,7 @@ class Tpkg
3897
3907
  # Get list of dependency prerequisites
3898
3908
  ptr = packages_to_remove | get_prerequisites(packages_to_remove)
3899
3909
  pkg_files_to_remove = ptr.map { |pkg| pkg[:metadata][:filename] }
3900
-
3910
+
3901
3911
  # see if any other packages depends on the ones we're about to remove
3902
3912
  # If so, we can't remove that package + any of its prerequisites
3903
3913
  non_removable_pkg_files = []
@@ -3959,7 +3969,7 @@ class Tpkg
3959
3969
  end
3960
3970
  unless Tpkg::confirm
3961
3971
  unlock
3962
- return false
3972
+ return false
3963
3973
  end
3964
3974
  end
3965
3975
 
@@ -3977,19 +3987,19 @@ class Tpkg
3977
3987
  packages_to_remove.each do |pkg|
3978
3988
  pkgname = pkg[:metadata][:name]
3979
3989
  package_file = File.join(@installed_directory, pkg[:metadata][:filename])
3980
-
3990
+
3981
3991
  topleveldir = Tpkg::package_toplevel_directory(package_file)
3982
3992
  workdir = Tpkg::tempdir(topleveldir, @tmp_directory)
3983
3993
  extract_tpkg_tar_command = Tpkg::cmd_to_extract_tpkg_tar(package_file, topleveldir)
3984
3994
  system("#{extract_tpkg_tar_command} | #{@tar} #{@@taroptions} -C #{workdir} -xpf -")
3985
-
3995
+
3986
3996
  # Run preremove script
3987
3997
  if File.exist?(File.join(workdir, 'tpkg', 'preremove'))
3988
3998
  pwd = Dir.pwd
3989
3999
  # chdir into the working directory so that the user can specify a
3990
4000
  # relative path to their file/script.
3991
4001
  Dir.chdir(File.join(workdir, 'tpkg'))
3992
-
4002
+
3993
4003
  # Warn the user about non-executable files, as system will just
3994
4004
  # silently fail and exit if that's the case.
3995
4005
  if !File.executable?(File.join(workdir, 'tpkg', 'preremove'))
@@ -4000,7 +4010,7 @@ class Tpkg
4000
4010
  else
4001
4011
  system(File.join(workdir, 'tpkg', 'preremove')) || raise("Error: preremove for #{File.basename(package_file)} failed with exit value #{$?.exitstatus}")
4002
4012
  end
4003
-
4013
+
4004
4014
  # Switch back to our previous directory
4005
4015
  Dir.chdir(pwd)
4006
4016
  end
@@ -4014,14 +4024,14 @@ class Tpkg
4014
4024
  run_external(pkg[:metadata][:filename], :remove, external[:name], external[:data])
4015
4025
  end
4016
4026
  end if pkg[:metadata][:externals]
4017
-
4027
+
4018
4028
  # determine which configuration files have been modified
4019
4029
  modified_conf_files = []
4020
4030
  file_metadata = file_metadata_for_installed_packages([pkg[:metadata][:filename]]).values[0]
4021
4031
  file_metadata[:files].each do |file|
4022
4032
  if file[:config]
4023
4033
  # get expected checksum. For files that were encrypted, we're interested in the
4024
- # checksum of the decrypted version
4034
+ # checksum of the decrypted version
4025
4035
  chksum_expected = file[:checksum][:digests].first[:value]
4026
4036
  file[:checksum][:digests].each do | digest |
4027
4037
  if digest[:decrypted] == true
@@ -4035,7 +4045,7 @@ class Tpkg
4035
4045
  end
4036
4046
  end
4037
4047
  end if file_metadata
4038
-
4048
+
4039
4049
  # Remove files
4040
4050
  files_to_remove = conflicting_files(package_file, CHECK_REMOVE)
4041
4051
  # Reverse the order of the files, as directories will appear first
@@ -4065,14 +4075,14 @@ class Tpkg
4065
4075
  warn "Failed to remove file #{file}."
4066
4076
  end
4067
4077
  end
4068
-
4078
+
4069
4079
  # Run postremove script
4070
4080
  if File.exist?(File.join(workdir, 'tpkg', 'postremove'))
4071
4081
  pwd = Dir.pwd
4072
4082
  # chdir into the working directory so that the user can specify a
4073
4083
  # relative path to their file/script.
4074
4084
  Dir.chdir(File.join(workdir, 'tpkg'))
4075
-
4085
+
4076
4086
  # Warn the user about non-executable files, as system will just
4077
4087
  # silently fail and exit if that's the case.
4078
4088
  if !File.executable?(File.join(workdir, 'tpkg', 'postremove'))
@@ -4085,36 +4095,36 @@ class Tpkg
4085
4095
  # desirable. We could reinstall the package's files and raise an
4086
4096
  # exception, but this seems the best approach to me.
4087
4097
  system(File.join(workdir, 'tpkg', 'postremove')) || warn("Warning: postremove for #{File.basename(package_file)} failed with exit value #{$?.exitstatus}")
4088
- ret_val = POSTREMOVE_ERR if $?.exitstatus > 0
4089
-
4098
+ ret_val = POSTREMOVE_ERR if !$?.success?
4099
+
4090
4100
  # Switch back to our previous directory
4091
4101
  Dir.chdir(pwd)
4092
4102
  end
4093
-
4103
+
4094
4104
  File.delete(package_file)
4095
-
4105
+
4096
4106
  # delete metadata dir of this package
4097
4107
  package_metadata_dir = File.join(@metadata_directory, File.basename(package_file, File.extname(package_file)))
4098
4108
  FileUtils.rm_rf(package_metadata_dir)
4099
-
4109
+
4100
4110
  # remove native dependency stub packages if needed
4101
4111
  remove_native_stub_pkg(pkg)
4102
-
4112
+
4103
4113
  # Cleanup
4104
4114
  FileUtils.rm_rf(workdir)
4105
4115
  end
4106
-
4107
- # log changes
4116
+
4117
+ # log changes
4108
4118
  currently_installed = metadata_for_installed_packages.collect{|metadata| metadata.to_hash}
4109
4119
  removed = already_installed_pkgs - currently_installed
4110
4120
  log_changes({:removed => removed})
4111
-
4121
+
4112
4122
  # send update back to reporting server
4113
4123
  unless @report_server.nil? || options[:upgrade]
4114
4124
  options = {:removed => removed, :currently_installed => currently_installed}
4115
4125
  send_update_to_server(options)
4116
4126
  end
4117
-
4127
+
4118
4128
  unlock
4119
4129
  return ret_val
4120
4130
  end
@@ -4126,16 +4136,16 @@ class Tpkg
4126
4136
  requests.each do |request|
4127
4137
  req = Tpkg::parse_request(request)
4128
4138
  packages.concat(installed_packages_that_meet_requirement(req).collect { |pkg| pkg[:metadata][:filename] })
4129
- end
4130
-
4139
+ end
4140
+
4131
4141
  # loop through each package, and verify checksum, owner, group and perm of each file that was installed
4132
4142
  packages.each do | package_file |
4133
4143
  puts "Verifying #{package_file}"
4134
4144
  package_full_name = File.basename(package_file, File.extname(package_file))
4135
-
4145
+
4136
4146
  # Extract checksum.xml from the package
4137
4147
  checksum_xml = nil
4138
-
4148
+
4139
4149
  # get file_metadata from the installed package
4140
4150
  file_metadata = FileMetadata::instantiate_from_dir(File.join(@metadata_directory, package_full_name))
4141
4151
  if !file_metadata
@@ -4144,15 +4154,15 @@ class Tpkg
4144
4154
  results[package_file] = errors
4145
4155
  return results
4146
4156
  end
4147
-
4148
- # verify installed files match their checksum
4157
+
4158
+ # verify installed files match their checksum
4149
4159
  file_metadata[:files].each do |file|
4150
4160
  errors = []
4151
4161
  gid_expected, uid_expected, perms_expected, chksum_expected = nil
4152
4162
  fp = file[:path]
4153
-
4163
+
4154
4164
  # get expected checksum. For files that were encrypted, we're interested in the
4155
- # checksum of the decrypted version
4165
+ # checksum of the decrypted version
4156
4166
  if file[:checksum]
4157
4167
  chksum_expected = file[:checksum][:digests].first[:value]
4158
4168
  file[:checksum][:digests].each do | digest |
@@ -4161,7 +4171,7 @@ class Tpkg
4161
4171
  end
4162
4172
  end
4163
4173
  end
4164
-
4174
+
4165
4175
  # get expected acl values
4166
4176
  if file[:uid]
4167
4177
  uid_expected = file[:uid].to_i
@@ -4171,30 +4181,30 @@ class Tpkg
4171
4181
  end
4172
4182
  if file[:perms]
4173
4183
  perms_expected = file[:perms].to_s
4174
- end
4175
-
4184
+ end
4185
+
4176
4186
  fp = normalize_path(fp)
4177
-
4187
+
4178
4188
  # can't handle symlink
4179
4189
  if File.symlink?(fp)
4180
4190
  next
4181
4191
  end
4182
-
4192
+
4183
4193
  # check if file exist
4184
4194
  if !File.exists?(fp)
4185
4195
  errors << "File is missing"
4186
- else
4187
- # get actual values
4196
+ else
4197
+ # get actual values
4188
4198
  chksum_actual = Digest::SHA256.hexdigest(File.read(fp)) if File.file?(fp)
4189
4199
  uid_actual = File.stat(fp).uid
4190
4200
  gid_actual = File.stat(fp).gid
4191
4201
  perms_actual = File.stat(fp).mode.to_s(8)
4192
4202
  end
4193
-
4203
+
4194
4204
  if !chksum_expected.nil? && !chksum_actual.nil? && chksum_expected != chksum_actual
4195
4205
  errors << "Checksum doesn't match (Expected: #{chksum_expected}, Actual: #{chksum_actual}"
4196
- end
4197
-
4206
+ end
4207
+
4198
4208
  if !uid_expected.nil? && !uid_actual.nil? && uid_expected != uid_actual
4199
4209
  errors << "uid doesn't match (Expected: #{uid_expected}, Actual: #{uid_actual}) "
4200
4210
  end
@@ -4212,7 +4222,7 @@ class Tpkg
4212
4222
  end
4213
4223
  return results
4214
4224
  end
4215
-
4225
+
4216
4226
  def execute_init(options, *moreoptions)
4217
4227
  ret_val = 0
4218
4228
  packages_to_execute_on = []
@@ -4224,7 +4234,7 @@ class Tpkg
4224
4234
  action = moreoptions[0]
4225
4235
  requested_packages = options
4226
4236
  end
4227
-
4237
+
4228
4238
  # if user specified no packages, then assume all
4229
4239
  if requested_packages.nil?
4230
4240
  packages_to_execute_on = installed_packages_that_meet_requirement(nil)
@@ -4235,20 +4245,20 @@ class Tpkg
4235
4245
  packages_to_execute_on.concat(installed_packages_that_meet_requirement(req))
4236
4246
  end
4237
4247
  end
4238
-
4248
+
4239
4249
  if packages_to_execute_on.empty?
4240
4250
  warn "Warning: Unable to find package(s) \"#{requested_packages.join(",")}\"."
4241
- else
4251
+ else
4242
4252
  packages_to_execute_on.each do |pkg|
4243
4253
  ret_val |= execute_init_for_package(pkg, action, requested_init_scripts)
4244
- end
4254
+ end
4245
4255
  end
4246
4256
  return ret_val
4247
4257
  end
4248
-
4258
+
4249
4259
  def execute_init_for_package(pkg, action, requested_init_scripts = nil)
4250
4260
  ret_val = 0
4251
-
4261
+
4252
4262
  # Get init scripts metadata for the given package
4253
4263
  init_scripts_metadata = init_scripts(pkg[:metadata])
4254
4264
  # warn if there's no init script and then return
@@ -4256,7 +4266,7 @@ class Tpkg
4256
4266
  warn "Warning: There is no init script for #{pkg[:metadata][:name]}."
4257
4267
  return 1
4258
4268
  end
4259
-
4269
+
4260
4270
  # convert the init scripts metadata to an array of { path => value, start => value}
4261
4271
  # so that we can order them based on their start value. This is necessary because
4262
4272
  # we need to execute the init scripts in correct order.
@@ -4265,30 +4275,30 @@ class Tpkg
4265
4275
  init = {}
4266
4276
  init[:path] = installed_path
4267
4277
  init[:start] = init_info[:init][:start] || 0
4268
-
4278
+
4269
4279
  # if user requests specific init scripts, then only include those
4270
- if requested_init_scripts.nil? or
4280
+ if requested_init_scripts.nil? or
4271
4281
  requested_init_scripts && requested_init_scripts.include?(File.basename(installed_path))
4272
- init_scripts << init
4282
+ init_scripts << init
4273
4283
  end
4274
4284
  end
4275
-
4285
+
4276
4286
  if requested_init_scripts && init_scripts.empty?
4277
4287
  warn "Warning: There are no init scripts that satisfy your request: #{requested_init_scripts.inspect} for package #{pkg[:metadata][:name]}."
4278
4288
  end
4279
4289
 
4280
- # Reverse order if doing stop.
4290
+ # Reverse order if doing stop.
4281
4291
  if action == "stop"
4282
4292
  ordered_init_scripts = init_scripts.sort{ |a,b| b[:start] <=> a[:start] }
4283
4293
  else
4284
4294
  ordered_init_scripts = init_scripts.sort{ |a,b| a[:start] <=> b[:start] }
4285
4295
  end
4286
-
4296
+
4287
4297
  ordered_init_scripts.each do |init_script|
4288
4298
  installed_path = init_script[:path]
4289
4299
  system("#{installed_path} #{action}")
4290
- ret_val = INITSCRIPT_ERR if $?.exitstatus > 0
4291
- end
4300
+ ret_val = INITSCRIPT_ERR if !$?.success?
4301
+ end
4292
4302
  return ret_val
4293
4303
  end
4294
4304
 
@@ -4324,7 +4334,7 @@ class Tpkg
4324
4334
  File.open(@lock_pid_file) { |file| lockpid = file.gets.chomp }
4325
4335
  rescue Errno::ENOENT
4326
4336
  end
4327
-
4337
+
4328
4338
  # check that the process is actually running
4329
4339
  # if not, clean up old lock and attemp to obtain lock again
4330
4340
  if Tpkg::process_running?(lockpid)
@@ -4335,7 +4345,7 @@ class Tpkg
4335
4345
  end
4336
4346
  end
4337
4347
  end
4338
-
4348
+
4339
4349
  def unlock
4340
4350
  if @locks == 0
4341
4351
  warn "unlock called but not locked, that probably shouldn't happen"
@@ -4346,16 +4356,16 @@ class Tpkg
4346
4356
  FileUtils.rm_rf(@lock_directory)
4347
4357
  end
4348
4358
  end
4349
-
4359
+
4350
4360
  # Build a dependency map of currently installed packages
4351
- # For example, if we have pkgB and pkgC which depends on pkgA, then
4361
+ # For example, if we have pkgB and pkgC which depends on pkgA, then
4352
4362
  # the dependency map would look like this:
4353
4363
  # "pkgA.tpkg" => [{pkgB metadata}, {pkgC metadata}]
4354
4364
  def get_dependency_mapping
4355
4365
  dependency_mapping = {}
4356
4366
  installed_packages.each do | pkg |
4357
4367
  metadata = pkg[:metadata]
4358
-
4368
+
4359
4369
  # Get list of pkgs that this pkg depends on
4360
4370
  next if metadata[:dependencies].nil?
4361
4371
  depended_on = []
@@ -4363,16 +4373,16 @@ class Tpkg
4363
4373
  next if req[:type] == :native
4364
4374
  depended_on |= installed_packages_that_meet_requirement(req)
4365
4375
  end
4366
-
4376
+
4367
4377
  # populate the depencency map
4368
4378
  depended_on.each do | req_pkg |
4369
- dependency_mapping[req_pkg[:metadata][:filename]] ||= []
4379
+ dependency_mapping[req_pkg[:metadata][:filename]] ||= []
4370
4380
  dependency_mapping[req_pkg[:metadata][:filename]] << pkg
4371
4381
  end
4372
4382
  end
4373
4383
  return dependency_mapping
4374
4384
  end
4375
-
4385
+
4376
4386
  # Given a list of packages, return a list of dependents packages
4377
4387
  def get_dependents(pkgs)
4378
4388
  dependents = []
@@ -4383,10 +4393,10 @@ class Tpkg
4383
4393
  next if pkgs.nil?
4384
4394
  dependents |= pkgs
4385
4395
  to_check |= pkgs.map { |pkg| pkg[:metadata][:filename] }
4386
- end
4396
+ end
4387
4397
  return dependents
4388
4398
  end
4389
-
4399
+
4390
4400
  # Given a list of packages, return a list of all their prerequisite dependencies
4391
4401
  # Example: If pkgA depends on pkgB, and pkgB depends on pkgC, then calling this
4392
4402
  # method on pkgA will returns pkgB and pkgC
@@ -4404,7 +4414,7 @@ class Tpkg
4404
4414
  end
4405
4415
  return pre_reqs
4406
4416
  end
4407
-
4417
+
4408
4418
  # print out history packages installation/remove
4409
4419
  def installation_history
4410
4420
  if !File.exists?(File.join(@log_directory,'changes.log'))
@@ -4412,15 +4422,15 @@ class Tpkg
4412
4422
  return GENERIC_ERR
4413
4423
  end
4414
4424
  IO.foreach(File.join(@log_directory,'changes.log')) do |line|
4415
- puts line
4425
+ puts line
4416
4426
  end
4417
4427
  end
4418
-
4428
+
4419
4429
  # Download packages that meet the requests specified by the user.
4420
4430
  # Packages are downloaded into the current directory or into the directory
4421
4431
  # specified in options[:out]
4422
4432
  def download_pkgs(requests, options={})
4423
- if options[:out]
4433
+ if options[:out]
4424
4434
  if !File.exists?(options[:out])
4425
4435
  FileUtils.mkdir_p(options[:out])
4426
4436
  elsif !File.directory?(options[:out])
@@ -4429,32 +4439,32 @@ class Tpkg
4429
4439
  end
4430
4440
  end
4431
4441
  output_dir = options[:out] || Dir.pwd
4432
-
4442
+
4433
4443
  requirements = []
4434
4444
  packages = {}
4435
4445
  original_dir = Dir.pwd
4436
-
4446
+
4437
4447
  workdir = Tpkg::tempdir("tpkg_download")
4438
4448
  Dir.chdir(workdir)
4439
4449
  parse_requests(requests, requirements, packages)
4440
4450
  packages = packages.values.flatten
4441
4451
  if packages.size < 1
4442
4452
  puts "Unable to find any packages that satisfy your request. Try running with --debug for more info"
4443
- Dir.chdir(original_dir)
4453
+ Dir.chdir(original_dir)
4444
4454
  return GENERIC_ERR
4445
4455
  end
4446
-
4456
+
4447
4457
  # Confirm with user what packages will be downloaded
4448
4458
  packages.delete_if{|pkg|pkg[:source] !~ /^http/}
4449
4459
  puts "The following packages will be downloaded:"
4450
4460
  packages.each do |pkg|
4451
4461
  puts "#{pkg[:metadata][:filename]} (source: #{pkg[:source]})"
4452
4462
  end
4453
- if @@prompt && !Tpkg::confirm
4454
- Dir.chdir(original_dir)
4463
+ if @@prompt && !Tpkg::confirm
4464
+ Dir.chdir(original_dir)
4455
4465
  return 0
4456
4466
  end
4457
-
4467
+
4458
4468
  err_code = 0
4459
4469
  puts "Downloading to #{output_dir}"
4460
4470
  packages.each do |pkg|
@@ -4468,21 +4478,21 @@ class Tpkg
4468
4478
  err_code = GENERIC_ERR
4469
4479
  end
4470
4480
  end
4471
-
4481
+
4472
4482
  # clean up working directory
4473
4483
  FileUtils.rm_rf(workdir)
4474
4484
 
4475
- Dir.chdir(original_dir)
4485
+ Dir.chdir(original_dir)
4476
4486
  return err_code
4477
4487
  end
4478
-
4488
+
4479
4489
  # TODO: figure out what other methods above can be turned into protected methods
4480
4490
  protected
4481
4491
  # log changes of pkgs that were installed/removed
4482
4492
  def log_changes(options={})
4483
4493
  msg = ""
4484
4494
  user = Etc.getlogin || Etc.getpwuid(Process.uid).name
4485
- newly_installed = removed = []
4495
+ newly_installed = removed = []
4486
4496
  newly_installed = options[:newly_installed] if options[:newly_installed]
4487
4497
  removed = options[:removed] if options[:removed]
4488
4498
  removed.each do |pkg|
@@ -4497,7 +4507,7 @@ class Tpkg
4497
4507
  File.open(File.join(@log_directory,'changes.log'), 'a') {|f| f.write(msg) }
4498
4508
  end
4499
4509
  end
4500
-
4510
+
4501
4511
  def send_update_to_server(options={})
4502
4512
  request = {"client"=>Facter['fqdn'].value}
4503
4513
  request[:user] = Etc.getlogin || Etc.getpwuid(Process.uid).name
@@ -4518,12 +4528,12 @@ class Tpkg
4518
4528
  already_installed = currently_installed
4519
4529
  end
4520
4530
  request[:already_installed] = URI.escape(YAML.dump(already_installed))
4521
-
4531
+
4522
4532
  if options[:removed]
4523
4533
  removed = options[:removed]
4524
4534
  request[:removed] = URI.escape(YAML.dump(removed))
4525
4535
  end
4526
-
4536
+
4527
4537
  begin
4528
4538
  response = nil
4529
4539
  # Need to set timeout otherwise tpkg can hang for a long time when having
@@ -4531,12 +4541,12 @@ class Tpkg
4531
4541
  # I can't seem get net-ssh timeout to work so we'll just handle the timeout ourselves
4532
4542
  timeout(CONNECTION_TIMEOUT) do
4533
4543
  update_uri = URI.parse("#{@report_server}")
4534
- http = Tpkg::gethttp(update_uri)
4544
+ http = gethttp(update_uri)
4535
4545
  post = Net::HTTP::Post.new(update_uri.path)
4536
4546
  post.set_form_data(request)
4537
4547
  response = http.request(post)
4538
4548
  end
4539
-
4549
+
4540
4550
  case response
4541
4551
  when Net::HTTPSuccess
4542
4552
  puts "Successfully send update to reporter server"
@@ -4548,24 +4558,24 @@ class Tpkg
4548
4558
  end
4549
4559
  rescue Timeout::Error
4550
4560
  puts "Timed out when trying to send update to reporter server"
4551
- rescue
4561
+ rescue
4552
4562
  puts "Failed to send update to reporter server"
4553
4563
  end
4554
4564
  end
4555
-
4556
- # create and install native stub package if needed
4557
- # this stub package helps prevent user from removing native packages that
4558
- # our tpkg packages depend on
4565
+
4566
+ # create and install native stub package if needed
4567
+ # this stub package helps prevent user from removing native packages that
4568
+ # our tpkg packages depend on
4559
4569
  def stub_native_pkg(pkg)
4560
4570
  # gather all of the native dependencies
4561
4571
  native_deps = pkg[:metadata].get_native_deps
4562
-
4572
+
4563
4573
  return if native_deps.nil? or native_deps.empty?
4564
4574
 
4565
4575
  if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
4566
4576
  rpm = create_rpm("stub_for_#{pkg[:metadata][:name]}", native_deps)
4567
4577
  return if rpm.nil?
4568
-
4578
+
4569
4579
  # install the rpm
4570
4580
  cmd = "rpm -i #{rpm}"
4571
4581
  puts cmd if @@debug
@@ -4577,16 +4587,16 @@ class Tpkg
4577
4587
  # TODO: support other OSes
4578
4588
  end
4579
4589
  end
4580
-
4590
+
4581
4591
  # remove the native dependency stub packages if there's any
4582
4592
  def remove_native_stub_pkg(pkg)
4583
4593
  # Don't have to do anything if this package has no native dependencies
4584
4594
  native_deps = pkg[:metadata].get_native_deps
4585
4595
  return if native_deps.nil? or native_deps.empty?
4586
-
4596
+
4587
4597
  # the convention is that stub package is named as "stub_for_pkgname"
4588
4598
  stub_pkg_name = "stub_for_#{pkg[:metadata][:name]}"
4589
-
4599
+
4590
4600
  if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
4591
4601
  cmd = "yum -y remove #{stub_pkg_name}"
4592
4602
  puts cmd if @@debug
@@ -4598,16 +4608,16 @@ class Tpkg
4598
4608
  # TODO: support other OSes
4599
4609
  end
4600
4610
  end
4601
-
4611
+
4602
4612
  def create_rpm(name, deps=[])
4603
4613
  # setup directories for rpmbuild
4604
4614
  topdir = Tpkg::tempdir('rpmbuild')
4605
4615
  %w[BUILD RPMS SOURCES SPECS SRPMS].each do |dir|
4606
4616
  FileUtils.mkdir_p(File.join(topdir, dir))
4607
4617
  end
4608
-
4618
+
4609
4619
  dep_list = deps.collect{|dep|dep[:name]}.join(",")
4610
-
4620
+
4611
4621
  # create rpm spec file
4612
4622
  spec = <<-EOS.gsub(/^\s+/, "")
4613
4623
  Name: #{name}
@@ -4627,14 +4637,14 @@ class Tpkg
4627
4637
  File.open(spec_file, 'w') do |file|
4628
4638
  file.puts(spec)
4629
4639
  end
4630
-
4640
+
4631
4641
  # run rpmbuild
4632
4642
  system("rpmbuild -bb --define '_topdir #{topdir}' #{spec_file}")
4633
4643
  if !$?.success?
4634
4644
  warn "Warning: Failed to create native stub package for #{name}"
4635
4645
  return nil
4636
4646
  end
4637
-
4647
+
4638
4648
  # copy result over to tmpfile
4639
4649
  result = File.join(topdir, 'RPMS', 'noarch', "#{name}-1-1.noarch.rpm")
4640
4650
  rpm = nil
@@ -4643,10 +4653,10 @@ class Tpkg
4643
4653
  FileUtils.cp(result, tmpfile.path)
4644
4654
  rpm = tmpfile.path
4645
4655
  end
4646
-
4656
+
4647
4657
  # cleanup
4648
4658
  FileUtils.rm_rf(topdir)
4649
-
4659
+
4650
4660
  return rpm
4651
4661
  end
4652
4662
  end