tpkg 1.25.1 → 1.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/bin/tpkg +5 -2
- data/lib/tpkg.rb +178 -47
- data/lib/tpkg/metadata.rb +40 -3
- data/schema/schema-1.0.8.yml +93 -0
- data/schema/schema-1.0.9.yml +93 -0
- data/schema/schema.yml +3 -1
- data/schema/tpkg-1.0.8.dtd +45 -0
- data/schema/tpkg-1.0.9.dtd +45 -0
- data/schema/tpkg.dtd +4 -2
- metadata +6 -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 = '1.
|
8
|
+
s.version = '1.27.1'
|
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
@@ -270,8 +270,7 @@ opts.on('--debug', 'Print lots of messages about what tpkg is doing') do |opt|
|
|
270
270
|
Tpkg::set_debug(@debug)
|
271
271
|
end
|
272
272
|
opts.on('--version', 'Show tpkg version') do |opt|
|
273
|
-
|
274
|
-
exit
|
273
|
+
@action = :query_version
|
275
274
|
end
|
276
275
|
opts.on_tail("-h", "--help", "Show this message") do
|
277
276
|
puts opts
|
@@ -491,6 +490,8 @@ when :query_info
|
|
491
490
|
end
|
492
491
|
end
|
493
492
|
end
|
493
|
+
tpkg_version = metadata[:tpkg_version] || "< 1.26.1"
|
494
|
+
puts "This package was built with tpkg version #{tpkg_version}."
|
494
495
|
if metadata[:dependencies]
|
495
496
|
puts "This package depends on other packages, use --qd/--qld to view the dependencies."
|
496
497
|
end
|
@@ -631,5 +632,7 @@ when :query_env
|
|
631
632
|
when :query_history
|
632
633
|
tpkg = instantiate_tpkg(@tpkg_options)
|
633
634
|
tpkg.installation_history
|
635
|
+
when :query_version
|
636
|
+
puts Tpkg::VERSION
|
634
637
|
end
|
635
638
|
exit ret_val
|
data/lib/tpkg.rb
CHANGED
@@ -56,7 +56,7 @@ require 'kwalify' # for validating yaml
|
|
56
56
|
|
57
57
|
class Tpkg
|
58
58
|
|
59
|
-
VERSION = '1.
|
59
|
+
VERSION = '1.27.1'
|
60
60
|
CONFIGDIR = '/etc'
|
61
61
|
|
62
62
|
GENERIC_ERR = 1
|
@@ -93,6 +93,9 @@ class Tpkg
|
|
93
93
|
def self.find_tar
|
94
94
|
if !@@tar
|
95
95
|
catch :tar_found do
|
96
|
+
if !ENV['PATH']
|
97
|
+
raise "tpkg cannot run because the PATH env variable is not set."
|
98
|
+
end
|
96
99
|
ENV['PATH'].split(':').each do |path|
|
97
100
|
TARNAMES.each do |tarname|
|
98
101
|
if File.executable?(File.join(path, tarname))
|
@@ -308,10 +311,15 @@ class Tpkg
|
|
308
311
|
raise "Failed to create package." unless options[:force]
|
309
312
|
end
|
310
313
|
|
311
|
-
# file_metadata
|
314
|
+
# file_metadata hold information for files that are installed
|
312
315
|
# by the package. For example, checksum, path, relocatable or not, etc.
|
313
316
|
File.open(File.join(tpkgdir, "file_metadata.bin"), "w") do |file|
|
314
317
|
filemetadata = get_filemetadata_from_directory(tpkgdir)
|
318
|
+
filemetadata[:files].each do |file1|
|
319
|
+
if metadata[:files][:files] && metadata[:files][:files].any?{|file2|file2[:path] == file1[:path] && file2[:config]}
|
320
|
+
file1[:config] = true
|
321
|
+
end
|
322
|
+
end
|
315
323
|
data = filemetadata.to_hash.recursively{|h| h.stringify_keys }
|
316
324
|
Marshal::dump(data, file)
|
317
325
|
end
|
@@ -378,7 +386,7 @@ class Tpkg
|
|
378
386
|
end
|
379
387
|
|
380
388
|
# update metadata file with the tpkg version
|
381
|
-
|
389
|
+
metadata.add_tpkg_version(VERSION)
|
382
390
|
|
383
391
|
# Tar up the tpkg directory
|
384
392
|
tpkgfile = File.join(package_directory, 'tpkg.tar')
|
@@ -484,12 +492,12 @@ class Tpkg
|
|
484
492
|
#return FileMetadata.new(YAML::dump(filemetadata),'yml')
|
485
493
|
return FileMetadata.new(Marshal::dump(filemetadata),'bin')
|
486
494
|
end
|
487
|
-
|
488
|
-
def self.verify_package_checksum(package_file)
|
489
|
-
topleveldir = package_toplevel_directory(package_file)
|
495
|
+
|
496
|
+
def self.verify_package_checksum(package_file, options = {})
|
497
|
+
topleveldir = options[:topleveldir] || package_toplevel_directory(package_file)
|
490
498
|
# Extract checksum.xml from the package
|
491
499
|
checksum_xml = nil
|
492
|
-
IO.popen("#{find_tar} -xf #{package_file} -O #{File.join(topleveldir, 'checksum.xml')}
|
500
|
+
IO.popen("#{find_tar} #{@@taroptions} -xf #{package_file} -O #{File.join(topleveldir, 'checksum.xml')}") do |pipe|
|
493
501
|
checksum_xml = REXML::Document.new(pipe.read)
|
494
502
|
end
|
495
503
|
if !$?.success?
|
@@ -536,8 +544,8 @@ class Tpkg
|
|
536
544
|
end
|
537
545
|
|
538
546
|
# Extracts and returns the metadata from a package file
|
539
|
-
def self.metadata_from_package(package_file)
|
540
|
-
topleveldir = package_toplevel_directory(package_file)
|
547
|
+
def self.metadata_from_package(package_file, options = {})
|
548
|
+
topleveldir = options[:topleveldir] || package_toplevel_directory(package_file)
|
541
549
|
# Verify checksum
|
542
550
|
verify_package_checksum(package_file)
|
543
551
|
# Extract and parse tpkg.xml
|
@@ -880,10 +888,7 @@ class Tpkg
|
|
880
888
|
end
|
881
889
|
|
882
890
|
def self.files_in_package(package_file, options = {})
|
883
|
-
|
884
|
-
files = {}
|
885
|
-
files[:root] = []
|
886
|
-
files[:reloc] = []
|
891
|
+
files = {:root => [], :reloc => []}
|
887
892
|
|
888
893
|
# If the metadata_directory option is available, it means this package
|
889
894
|
# has been installed and the file_metadata might be available in that directory.
|
@@ -903,6 +908,7 @@ class Tpkg
|
|
903
908
|
end
|
904
909
|
end
|
905
910
|
else
|
911
|
+
file_lists = []
|
906
912
|
topleveldir = package_toplevel_directory(package_file)
|
907
913
|
extract_tpkg_tar_cmd = cmd_to_extract_tpkg_tar(package_file, topleveldir)
|
908
914
|
IO.popen("#{extract_tpkg_tar_cmd} | #{find_tar} #{@@taroptions} -tf -") do |pipe|
|
@@ -1137,7 +1143,7 @@ class Tpkg
|
|
1137
1143
|
# Return what type of compression. If tpkg.tar wasn't compressed, then return nil.
|
1138
1144
|
def self.get_compression(package_file)
|
1139
1145
|
compression = nil
|
1140
|
-
IO.popen("#{find_tar} -tf #{package_file}
|
1146
|
+
IO.popen("#{find_tar} #{@@taroptions} -tf #{package_file}") do |pipe|
|
1141
1147
|
pipe.each do |file|
|
1142
1148
|
if file =~ /tpkg.tar.gz$/
|
1143
1149
|
compression = "gzip"
|
@@ -1154,11 +1160,11 @@ class Tpkg
|
|
1154
1160
|
def self.cmd_to_extract_tpkg_tar(package_file, topleveldir)
|
1155
1161
|
compression = get_compression(package_file)
|
1156
1162
|
if compression == "gzip"
|
1157
|
-
cmd = "#{find_tar} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar.gz')}
|
1163
|
+
cmd = "#{find_tar} #{@@taroptions} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar.gz')} | gunzip -c"
|
1158
1164
|
elsif compression == "bz2"
|
1159
|
-
cmd = "#{find_tar} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar.bz2')}
|
1165
|
+
cmd = "#{find_tar} #{@@taroptions} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar.bz2')} | bunzip2 -c"
|
1160
1166
|
else
|
1161
|
-
cmd = "#{find_tar} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar')}
|
1167
|
+
cmd = "#{find_tar} #{@@taroptions} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar')}"
|
1162
1168
|
end
|
1163
1169
|
end
|
1164
1170
|
|
@@ -1759,7 +1765,7 @@ class Tpkg
|
|
1759
1765
|
ret = {}
|
1760
1766
|
|
1761
1767
|
if package_files
|
1762
|
-
|
1768
|
+
package_files.collect!{|package_file| File.basename(package_file, File.extname(package_file))}
|
1763
1769
|
end
|
1764
1770
|
|
1765
1771
|
if File.directory?(@metadata_directory)
|
@@ -2459,7 +2465,6 @@ class Tpkg
|
|
2459
2465
|
# calling this method.
|
2460
2466
|
def unpack(package_file, options={})
|
2461
2467
|
ret_val = 0
|
2462
|
-
metadata = Tpkg::metadata_from_package(package_file)
|
2463
2468
|
|
2464
2469
|
# set env variable to let pre/post install know whether this unpack
|
2465
2470
|
# is part of an install or upgrade
|
@@ -2483,24 +2488,20 @@ class Tpkg
|
|
2483
2488
|
files_info = {} # store perms, uid, gid, etc. for files
|
2484
2489
|
checksums_of_decrypted_files = {}
|
2485
2490
|
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
files = `#{extract_tpkg_tar_cmd} | #{@tar} #{@@taroptions} -tf -`
|
2491
|
-
files = files.split("\n")
|
2491
|
+
metadata = Tpkg::metadata_from_package(package_file, {:topleveldir => topleveldir})
|
2492
|
+
|
2493
|
+
# Get list of files/directories that already exist in the system. Store their perm/ownership.
|
2494
|
+
# That way, when we copy over the new files, we can set the new files to have the same perm/owernship.
|
2492
2495
|
conflicting_files = {}
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
|
2499
|
-
if possible_conflicting_file && (File.exists?(possible_conflicting_file) && !File.symlink?(possible_conflicting_file))
|
2500
|
-
conflicting_files[File.join(workdir, file)] = File.stat(possible_conflicting_file)
|
2496
|
+
fip = Tpkg::files_in_package(package_file)
|
2497
|
+
(fip[:root] | fip[:reloc]).each do |file|
|
2498
|
+
file_in_staging = normalize_path(file, File.join(workdir, 'tpkg', 'root'), File.join(workdir, 'tpkg', 'reloc'))
|
2499
|
+
file_in_system = normalize_path(file)
|
2500
|
+
if File.exists?(file_in_system) && !File.symlink?(file_in_system)
|
2501
|
+
conflicting_files[file] = {:normalized => file_in_staging, :stat => File.stat(file_in_system)}
|
2501
2502
|
end
|
2502
2503
|
end
|
2503
|
-
|
2504
|
+
|
2504
2505
|
run_preinstall(package_file, workdir)
|
2505
2506
|
|
2506
2507
|
run_externals_for_install(metadata, workdir, options[:externals_to_skip])
|
@@ -2568,12 +2569,14 @@ class Tpkg
|
|
2568
2569
|
# Reset the permission/ownership of the conflicting files as how they were before.
|
2569
2570
|
# This needs to be done after the default permission/ownership is applied, but before
|
2570
2571
|
# the handling of ownership/permissions on specific files
|
2571
|
-
conflicting_files.each do | file,
|
2572
|
-
|
2573
|
-
|
2572
|
+
conflicting_files.each do | file, info |
|
2573
|
+
stat = info[:stat]
|
2574
|
+
file_path = info[:normalized]
|
2575
|
+
File.chmod(stat.mode, file_path)
|
2576
|
+
File.chown(stat.uid, stat.gid, file_path)
|
2574
2577
|
end
|
2575
2578
|
|
2576
|
-
# Handle any decryption
|
2579
|
+
# Handle any decryption, ownership/permissions, and other issues for specific files
|
2577
2580
|
metadata[:files][:files].each do |tpkgfile|
|
2578
2581
|
tpkg_path = tpkgfile[:path]
|
2579
2582
|
working_path = normalize_path(tpkg_path, File.join(workdir, 'tpkg', 'root'), File.join(workdir, 'tpkg', 'reloc'))
|
@@ -2639,6 +2642,12 @@ class Tpkg
|
|
2639
2642
|
end
|
2640
2643
|
end
|
2641
2644
|
end
|
2645
|
+
|
2646
|
+
# If a conf file already exists on the file system, don't overwrite it. Rename
|
2647
|
+
# the new one with .tpkgnew file extension.
|
2648
|
+
if tpkgfile[:config] && conflicting_files[tpkgfile[:path]]
|
2649
|
+
FileUtils.mv(conflicting_files[tpkgfile[:path]][:normalized], "#{conflicting_files[tpkgfile[:path]][:normalized]}.tpkgnew")
|
2650
|
+
end
|
2642
2651
|
end if metadata[:files] && metadata[:files][:files]
|
2643
2652
|
|
2644
2653
|
# We should get the perms, gid, uid stuff here since all the files
|
@@ -3515,6 +3524,8 @@ class Tpkg
|
|
3515
3524
|
else
|
3516
3525
|
if prompt_for_conflicting_files(pkgfile)
|
3517
3526
|
ret_val |= unpack(pkgfile, :passphrase => passphrase)
|
3527
|
+
# create and install stubbed native package if needed
|
3528
|
+
stub_native_pkg(pkg)
|
3518
3529
|
end
|
3519
3530
|
end
|
3520
3531
|
end
|
@@ -3588,8 +3599,10 @@ class Tpkg
|
|
3588
3599
|
if dep[:name] == req[:name]
|
3589
3600
|
# Package metadata is almost usable as-is as a req, just need to
|
3590
3601
|
# set :type
|
3591
|
-
|
3602
|
+
# and remove filename (since we're not explicitly requesting the exact file)
|
3603
|
+
addreq = metadata.to_hash.clone
|
3592
3604
|
addreq[:type] = :tpkg
|
3605
|
+
addreq[:filename] = nil
|
3593
3606
|
additional_requirements << addreq
|
3594
3607
|
end
|
3595
3608
|
end if metadata[:dependencies]
|
@@ -3768,7 +3781,8 @@ class Tpkg
|
|
3768
3781
|
ret_val |= unpack(pkgfile, :passphrase => passphrase, :externals_to_skip => externals_to_skip,
|
3769
3782
|
:is_doing_upgrade => is_doing_upgrade)
|
3770
3783
|
end
|
3771
|
-
|
3784
|
+
# create and install stubbed native package if needed
|
3785
|
+
stub_native_pkg(pkg)
|
3772
3786
|
has_updates = true
|
3773
3787
|
end
|
3774
3788
|
end
|
@@ -3946,13 +3960,36 @@ class Tpkg
|
|
3946
3960
|
run_external(pkg[:metadata][:filename], :remove, external[:name], external[:data])
|
3947
3961
|
end
|
3948
3962
|
end if pkg[:metadata][:externals]
|
3949
|
-
|
3963
|
+
|
3964
|
+
# determine which configuration files have been modified
|
3965
|
+
modified_conf_files = []
|
3966
|
+
file_metadata = file_metadata_for_installed_packages([pkg[:metadata][:filename]]).values[0]
|
3967
|
+
file_metadata[:files].each do |file|
|
3968
|
+
if file[:config]
|
3969
|
+
# get expected checksum. For files that were encrypted, we're interested in the
|
3970
|
+
# checksum of the decrypted version
|
3971
|
+
chksum_expected = file[:checksum][:digests].first[:value]
|
3972
|
+
file[:checksum][:digests].each do | digest |
|
3973
|
+
if digest[:decrypted] == true
|
3974
|
+
chksum_expected = digest[:value].to_s
|
3975
|
+
end
|
3976
|
+
end
|
3977
|
+
fp = normalize_path(file[:path])
|
3978
|
+
chksum_actual = Digest::SHA256.hexdigest(File.read(fp))
|
3979
|
+
if chksum_actual != chksum_expected
|
3980
|
+
modified_conf_files << fp
|
3981
|
+
end
|
3982
|
+
end
|
3983
|
+
end if file_metadata
|
3984
|
+
|
3950
3985
|
# Remove files
|
3951
3986
|
files_to_remove = conflicting_files(package_file, CHECK_REMOVE)
|
3952
3987
|
# Reverse the order of the files, as directories will appear first
|
3953
3988
|
# in the listing but we want to remove any files in them before
|
3954
3989
|
# trying to remove the directory.
|
3955
3990
|
files_to_remove.reverse.each do |file|
|
3991
|
+
# don't remove conf files that have been modified
|
3992
|
+
next if modified_conf_files.include?(file)
|
3956
3993
|
begin
|
3957
3994
|
if !File.directory?(file)
|
3958
3995
|
File.delete(file)
|
@@ -4006,6 +4043,9 @@ class Tpkg
|
|
4006
4043
|
package_metadata_dir = File.join(@metadata_directory, File.basename(package_file, File.extname(package_file)))
|
4007
4044
|
FileUtils.rm_rf(package_metadata_dir)
|
4008
4045
|
|
4046
|
+
# remove native dependency stub packages if needed
|
4047
|
+
remove_native_stub_pkg(pkg)
|
4048
|
+
|
4009
4049
|
# Cleanup
|
4010
4050
|
FileUtils.rm_rf(workdir)
|
4011
4051
|
end
|
@@ -4079,12 +4119,7 @@ class Tpkg
|
|
4079
4119
|
perms_expected = file[:perms].to_s
|
4080
4120
|
end
|
4081
4121
|
|
4082
|
-
|
4083
|
-
if file[:relocatable] == true
|
4084
|
-
fp = File.join(@base, fp)
|
4085
|
-
else
|
4086
|
-
fp = File.join(@file_system_root, fp)
|
4087
|
-
end
|
4122
|
+
fp = normalize_path(fp)
|
4088
4123
|
|
4089
4124
|
# can't handle symlink
|
4090
4125
|
if File.symlink?(fp)
|
@@ -4463,6 +4498,102 @@ class Tpkg
|
|
4463
4498
|
puts "Failed to send update to reporter server"
|
4464
4499
|
end
|
4465
4500
|
end
|
4501
|
+
|
4502
|
+
# create and install native stub package if needed
|
4503
|
+
# this stub package helps prevent user from removing native packages that
|
4504
|
+
# our tpkg packages depend on
|
4505
|
+
def stub_native_pkg(pkg)
|
4506
|
+
# gather all of the native dependencies
|
4507
|
+
native_deps = pkg[:metadata].get_native_deps
|
4508
|
+
|
4509
|
+
return if native_deps.nil? or native_deps.empty?
|
4510
|
+
|
4511
|
+
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
|
4512
|
+
rpm = create_rpm("stub_for_#{pkg[:metadata][:name]}", native_deps)
|
4513
|
+
return if rpm.nil?
|
4514
|
+
|
4515
|
+
# install the rpm
|
4516
|
+
cmd = "rpm -i #{rpm}"
|
4517
|
+
puts cmd if @@debug
|
4518
|
+
system(cmd)
|
4519
|
+
if !$?.success?
|
4520
|
+
warn "Warning: Failed to install native stub package for #{pkg[:metadata][:name]}"
|
4521
|
+
end
|
4522
|
+
else
|
4523
|
+
# TODO: support other OSes
|
4524
|
+
end
|
4525
|
+
end
|
4526
|
+
|
4527
|
+
# remove the native dependency stub packages if there's any
|
4528
|
+
def remove_native_stub_pkg(pkg)
|
4529
|
+
# Don't have to do anything if this package has no native dependencies
|
4530
|
+
native_deps = pkg[:metadata].get_native_deps
|
4531
|
+
return if native_deps.nil? or native_deps.empty?
|
4532
|
+
|
4533
|
+
# the convention is that stub package is named as "stub_for_pkgname"
|
4534
|
+
stub_pkg_name = "stub_for_#{pkg[:metadata][:name]}"
|
4535
|
+
|
4536
|
+
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
|
4537
|
+
cmd = "yum -y remove #{stub_pkg_name}"
|
4538
|
+
puts cmd if @@debug
|
4539
|
+
system(cmd)
|
4540
|
+
if !$?.success?
|
4541
|
+
warn "Warning: Failed to remove native stub package for #{pkg[:metadata][:name]}"
|
4542
|
+
end
|
4543
|
+
else
|
4544
|
+
# TODO: support other OSes
|
4545
|
+
end
|
4546
|
+
end
|
4466
4547
|
|
4548
|
+
def create_rpm(name, deps=[])
|
4549
|
+
# setup directories for rpmbuild
|
4550
|
+
topdir = Tpkg::tempdir('rpmbuild')
|
4551
|
+
%w[BUILD RPMS SOURCES SPECS SRPMS].each do |dir|
|
4552
|
+
FileUtils.mkdir_p(File.join(topdir, dir))
|
4553
|
+
end
|
4554
|
+
|
4555
|
+
dep_list = deps.collect{|dep|dep[:name]}.join(",")
|
4556
|
+
|
4557
|
+
# create rpm spec file
|
4558
|
+
spec = <<-EOS.gsub(/^\s+/, "")
|
4559
|
+
Name: #{name}
|
4560
|
+
Summary: stub pkg created by tpkg
|
4561
|
+
Version: 1
|
4562
|
+
Release: 1
|
4563
|
+
buildarch: noarch
|
4564
|
+
Requires: #{dep_list}
|
4565
|
+
Group: Applications/System
|
4566
|
+
License: MIT
|
4567
|
+
BuildRoot: %{_builddir}/%{name}-buildroot
|
4568
|
+
%description
|
4569
|
+
stub pkg created by tpkg for the following dependencies: #{dep_list}
|
4570
|
+
%files
|
4571
|
+
EOS
|
4572
|
+
spec_file = File.join(topdir, 'SPECS', 'pkg.spec')
|
4573
|
+
File.open(spec_file, 'w') do |file|
|
4574
|
+
file.puts(spec)
|
4575
|
+
end
|
4576
|
+
|
4577
|
+
# run rpmbuild
|
4578
|
+
system("rpmbuild -bb --define '_topdir #{topdir}' #{spec_file}")
|
4579
|
+
if !$?.success?
|
4580
|
+
warn "Warning: Failed to create native stub package for #{name}"
|
4581
|
+
return nil
|
4582
|
+
end
|
4583
|
+
|
4584
|
+
# copy result over to tmpfile
|
4585
|
+
result = File.join(topdir, 'RPMS', 'noarch', "#{name}-1-1.noarch.rpm")
|
4586
|
+
rpm = nil
|
4587
|
+
if File.exists?(result)
|
4588
|
+
tmpfile = Tempfile.new(File.basename(result))
|
4589
|
+
FileUtils.cp(result, tmpfile.path)
|
4590
|
+
rpm = tmpfile.path
|
4591
|
+
end
|
4592
|
+
|
4593
|
+
# cleanup
|
4594
|
+
FileUtils.rm_rf(topdir)
|
4595
|
+
|
4596
|
+
return rpm
|
4597
|
+
end
|
4467
4598
|
end
|
4468
4599
|
|
data/lib/tpkg/metadata.rb
CHANGED
@@ -221,8 +221,8 @@ end
|
|
221
221
|
# is that you can give it a metadata file of any format, such as yaml or xml,
|
222
222
|
# and it will provide you a uniform interface for accessing/dealing with the metadata.
|
223
223
|
class Metadata
|
224
|
-
attr_accessor :source
|
225
|
-
REQUIRED_FIELDS = [:name, :version, :maintainer]
|
224
|
+
attr_accessor :source, :file_path
|
225
|
+
REQUIRED_FIELDS = [:name, :version, :maintainer, :description]
|
226
226
|
|
227
227
|
# Cleans up a string to make it suitable for use in a filename
|
228
228
|
def self.clean_for_filename(dirtystring)
|
@@ -248,8 +248,10 @@ class Metadata
|
|
248
248
|
metadata = nil
|
249
249
|
if File.exist?(File.join(dir, 'tpkg.yml'))
|
250
250
|
metadata = Metadata.new(File.read(File.join(dir, 'tpkg.yml')), 'yml')
|
251
|
+
metadata.file_path = File.join(dir, 'tpkg.yml')
|
251
252
|
elsif File.exists?(File.join(dir, 'tpkg.xml'))
|
252
253
|
metadata = Metadata.new(File.read(File.join(dir, 'tpkg.xml')), 'xml')
|
254
|
+
metadata.file_path = File.join(dir, 'tpkg.xml')
|
253
255
|
end
|
254
256
|
return metadata
|
255
257
|
end
|
@@ -330,6 +332,33 @@ class Metadata
|
|
330
332
|
file.close
|
331
333
|
end
|
332
334
|
|
335
|
+
# Add tpkg_version to the existing tpkg.xml or tpkg.yml file
|
336
|
+
def add_tpkg_version(version)
|
337
|
+
if @format == 'xml'
|
338
|
+
metadata_xml = REXML::Document.new(@metadata_text)
|
339
|
+
if metadata_xml.root.elements["tpkg_version"] && (tpkg_version = metadata_xml.root.elements["tpkg_version"].text) != Tpkg::VERSION
|
340
|
+
warn "Warning: tpkg_version is specified as #{tpkg_version}, which doesn't match with the actual tpkg version being used (#{Tpkg::VERSION})."
|
341
|
+
elsif !metadata_xml.root.elements["tpkg_version"]
|
342
|
+
tpkg_version_ele = REXML::Element.new("tpkg_version")
|
343
|
+
tpkg_version_ele.text = Tpkg::VERSION
|
344
|
+
metadata_xml.root.add_element(tpkg_version_ele)
|
345
|
+
File.open(@file_path, 'w') do |file|
|
346
|
+
metadata_xml.write(file)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
elsif @format == 'yml'
|
350
|
+
if (tpkg_version = to_hash[:tpkg_version]) && tpkg_version != Tpkg::VERSION
|
351
|
+
warn "Warning: tpkg_version is specified as #{tpkg_version}, which doesn't match with the actual tpkg version being used (#{Tpkg::VERSION})."
|
352
|
+
elsif !tpkg_version
|
353
|
+
File.open(@file_path, 'a') do |file|
|
354
|
+
file.puts "tpkg_version: #{Tpkg::VERSION}"
|
355
|
+
end
|
356
|
+
end
|
357
|
+
else
|
358
|
+
raise "Unknown metadata format"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
333
362
|
def generate_package_filename
|
334
363
|
name = to_hash[:name]
|
335
364
|
version = to_hash[:version]
|
@@ -454,7 +483,7 @@ class Metadata
|
|
454
483
|
end
|
455
484
|
end
|
456
485
|
|
457
|
-
[:package_version, :description, :bugreporting].each do |optfield|
|
486
|
+
[:tpkg_version, :package_version, :description, :bugreporting].each do |optfield|
|
458
487
|
if metadata_xml.elements["/tpkg/#{optfield.to_s}"]
|
459
488
|
metadata_hash[optfield] =
|
460
489
|
metadata_xml.elements["/tpkg/#{optfield.to_s}"].text
|
@@ -596,6 +625,7 @@ class Metadata
|
|
596
625
|
metadata_xml.elements.each('/tpkg/files/file') do |filexml|
|
597
626
|
file = {}
|
598
627
|
file[:path] = filexml.elements['path'].text
|
628
|
+
file[:config] = true if filexml.elements['config']
|
599
629
|
if filexml.elements['encrypt']
|
600
630
|
encrypt = {}
|
601
631
|
if filexml.elements['encrypt'].attribute('precrypt') &&
|
@@ -656,6 +686,13 @@ class Metadata
|
|
656
686
|
|
657
687
|
return metadata_hash
|
658
688
|
end
|
689
|
+
|
690
|
+
def get_native_deps
|
691
|
+
dependencies = to_hash[:dependencies]
|
692
|
+
return nil if dependencies.nil? or dependencies.empty?
|
693
|
+
|
694
|
+
return dependencies.select{|dep| dep[:type] == :native}
|
695
|
+
end
|
659
696
|
end
|
660
697
|
|
661
698
|
class FileMetadata < Metadata
|
@@ -0,0 +1,93 @@
|
|
1
|
+
type: map
|
2
|
+
mapping:
|
3
|
+
"schema_file": { type: text }
|
4
|
+
"tpkg_version": { type: text }
|
5
|
+
"name": { type: str, required: yes }
|
6
|
+
"version": { type: text, required: yes }
|
7
|
+
"package_version": { type: text }
|
8
|
+
"maintainer": { type: str, required: yes }
|
9
|
+
"operatingsystem": { type: seq, sequence: [ {type: str} ] }
|
10
|
+
"architecture": { type: seq, sequence: [ {type: str} ] }
|
11
|
+
"description": { type: str }
|
12
|
+
"bugreporting": { type: str }
|
13
|
+
"dependencies":
|
14
|
+
type: seq
|
15
|
+
sequence:
|
16
|
+
- type: map
|
17
|
+
mapping:
|
18
|
+
"name": { type: str, required: yes }
|
19
|
+
"minimum_version": { type: text }
|
20
|
+
"maximum_version": { type: text }
|
21
|
+
"minimum_package_version": { type: text }
|
22
|
+
"maximum_package_version": { type: text }
|
23
|
+
"allowed_versions": { type: text }
|
24
|
+
"native": { type: bool }
|
25
|
+
"type": { type: any, pattern: /(native|tpkg)$/ }
|
26
|
+
"conflicts":
|
27
|
+
type: seq
|
28
|
+
sequence:
|
29
|
+
- type: map
|
30
|
+
mapping:
|
31
|
+
"name": { type: str, required: yes }
|
32
|
+
"minimum_version": { type: text }
|
33
|
+
"maximum_version": { type: text }
|
34
|
+
"minimum_package_version": { type: text }
|
35
|
+
"maximum_package_version": { type: text }
|
36
|
+
"native": { type: bool }
|
37
|
+
"type": { type: any, pattern: /(native|tpkg)$/ }
|
38
|
+
"externals":
|
39
|
+
type: seq
|
40
|
+
sequence:
|
41
|
+
- type: map
|
42
|
+
mapping:
|
43
|
+
"name": { type: text, required: yes }
|
44
|
+
"data": { type: text }
|
45
|
+
"datascript": { type: text }
|
46
|
+
"datafile": { type: text }
|
47
|
+
"files":
|
48
|
+
type: map
|
49
|
+
mapping:
|
50
|
+
"file_defaults":
|
51
|
+
type: map
|
52
|
+
mapping:
|
53
|
+
"posix":
|
54
|
+
type: map
|
55
|
+
mapping:
|
56
|
+
"owner": { type: text }
|
57
|
+
"group": { type: text }
|
58
|
+
"perms": { type: text }
|
59
|
+
"dirs_defaults":
|
60
|
+
type: map
|
61
|
+
mapping:
|
62
|
+
"posix":
|
63
|
+
type: map
|
64
|
+
mapping:
|
65
|
+
"owner": { type: text }
|
66
|
+
"group": { type: text }
|
67
|
+
"perms": { type: text }
|
68
|
+
"files":
|
69
|
+
type: seq
|
70
|
+
sequence:
|
71
|
+
- type: map
|
72
|
+
mapping:
|
73
|
+
"config": { type: bool, default: false }
|
74
|
+
"path": { type: text, required: yes }
|
75
|
+
"encrypt":
|
76
|
+
type: map
|
77
|
+
mapping:
|
78
|
+
"algorithm": { type: text }
|
79
|
+
"precrypt": { type: any, pattern: /^true$|^false$/ }
|
80
|
+
"init":
|
81
|
+
type: map
|
82
|
+
mapping:
|
83
|
+
"start": { type: int }
|
84
|
+
"levels": { type: seq, sequence: [ { type: int } ] }
|
85
|
+
"crontab":
|
86
|
+
type: map
|
87
|
+
mapping: { "user": { type: str } }
|
88
|
+
"posix":
|
89
|
+
type: map
|
90
|
+
mapping: { "owner": { type: text },
|
91
|
+
"group": { type: text },
|
92
|
+
"perms": { type: text } }
|
93
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
type: map
|
2
|
+
mapping:
|
3
|
+
"schema_file": { type: text }
|
4
|
+
"tpkg_version": { type: text }
|
5
|
+
"name": { type: str, required: yes }
|
6
|
+
"version": { type: text, required: yes }
|
7
|
+
"package_version": { type: text }
|
8
|
+
"maintainer": { type: str, required: yes }
|
9
|
+
"operatingsystem": { type: seq, sequence: [ {type: str} ] }
|
10
|
+
"architecture": { type: seq, sequence: [ {type: str} ] }
|
11
|
+
"description": { type: str, required: yes }
|
12
|
+
"bugreporting": { type: str }
|
13
|
+
"dependencies":
|
14
|
+
type: seq
|
15
|
+
sequence:
|
16
|
+
- type: map
|
17
|
+
mapping:
|
18
|
+
"name": { type: str, required: yes }
|
19
|
+
"minimum_version": { type: text }
|
20
|
+
"maximum_version": { type: text }
|
21
|
+
"minimum_package_version": { type: text }
|
22
|
+
"maximum_package_version": { type: text }
|
23
|
+
"allowed_versions": { type: text }
|
24
|
+
"native": { type: bool }
|
25
|
+
"type": { type: any, pattern: /(native|tpkg)$/ }
|
26
|
+
"conflicts":
|
27
|
+
type: seq
|
28
|
+
sequence:
|
29
|
+
- type: map
|
30
|
+
mapping:
|
31
|
+
"name": { type: str, required: yes }
|
32
|
+
"minimum_version": { type: text }
|
33
|
+
"maximum_version": { type: text }
|
34
|
+
"minimum_package_version": { type: text }
|
35
|
+
"maximum_package_version": { type: text }
|
36
|
+
"native": { type: bool }
|
37
|
+
"type": { type: any, pattern: /(native|tpkg)$/ }
|
38
|
+
"externals":
|
39
|
+
type: seq
|
40
|
+
sequence:
|
41
|
+
- type: map
|
42
|
+
mapping:
|
43
|
+
"name": { type: text, required: yes }
|
44
|
+
"data": { type: text }
|
45
|
+
"datascript": { type: text }
|
46
|
+
"datafile": { type: text }
|
47
|
+
"files":
|
48
|
+
type: map
|
49
|
+
mapping:
|
50
|
+
"file_defaults":
|
51
|
+
type: map
|
52
|
+
mapping:
|
53
|
+
"posix":
|
54
|
+
type: map
|
55
|
+
mapping:
|
56
|
+
"owner": { type: text }
|
57
|
+
"group": { type: text }
|
58
|
+
"perms": { type: text }
|
59
|
+
"dirs_defaults":
|
60
|
+
type: map
|
61
|
+
mapping:
|
62
|
+
"posix":
|
63
|
+
type: map
|
64
|
+
mapping:
|
65
|
+
"owner": { type: text }
|
66
|
+
"group": { type: text }
|
67
|
+
"perms": { type: text }
|
68
|
+
"files":
|
69
|
+
type: seq
|
70
|
+
sequence:
|
71
|
+
- type: map
|
72
|
+
mapping:
|
73
|
+
"config": { type: bool, default: false }
|
74
|
+
"path": { type: text, required: yes }
|
75
|
+
"encrypt":
|
76
|
+
type: map
|
77
|
+
mapping:
|
78
|
+
"algorithm": { type: text }
|
79
|
+
"precrypt": { type: any, pattern: /^true$|^false$/ }
|
80
|
+
"init":
|
81
|
+
type: map
|
82
|
+
mapping:
|
83
|
+
"start": { type: int }
|
84
|
+
"levels": { type: seq, sequence: [ { type: int } ] }
|
85
|
+
"crontab":
|
86
|
+
type: map
|
87
|
+
mapping: { "user": { type: str } }
|
88
|
+
"posix":
|
89
|
+
type: map
|
90
|
+
mapping: { "owner": { type: text },
|
91
|
+
"group": { type: text },
|
92
|
+
"perms": { type: text } }
|
93
|
+
|
data/schema/schema.yml
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
type: map
|
2
2
|
mapping:
|
3
3
|
"schema_file": { type: text }
|
4
|
+
"tpkg_version": { type: text }
|
4
5
|
"name": { type: str, required: yes }
|
5
6
|
"version": { type: text, required: yes }
|
6
7
|
"package_version": { type: text }
|
7
8
|
"maintainer": { type: str, required: yes }
|
8
9
|
"operatingsystem": { type: seq, sequence: [ {type: str} ] }
|
9
10
|
"architecture": { type: seq, sequence: [ {type: str} ] }
|
10
|
-
"description": { type: str }
|
11
|
+
"description": { type: str, required: yes }
|
11
12
|
"bugreporting": { type: str }
|
12
13
|
"dependencies":
|
13
14
|
type: seq
|
@@ -69,6 +70,7 @@ mapping:
|
|
69
70
|
sequence:
|
70
71
|
- type: map
|
71
72
|
mapping:
|
73
|
+
"config": { type: bool, default: false }
|
72
74
|
"path": { type: text, required: yes }
|
73
75
|
"encrypt":
|
74
76
|
type: map
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<!ELEMENT tpkg (name, version, package_version?, maintainer+, operatingsystem*, architecture*, description?, bugreporting?, dependencies?, externals?, files?, tpkg_version?)>
|
2
|
+
|
3
|
+
<!ELEMENT name (#PCDATA)>
|
4
|
+
<!ELEMENT version (#PCDATA)>
|
5
|
+
<!ELEMENT package_version (#PCDATA)>
|
6
|
+
<!ELEMENT maintainer (#PCDATA)>
|
7
|
+
<!ELEMENT operatingsystem (#PCDATA)>
|
8
|
+
<!ELEMENT architecture (#PCDATA)>
|
9
|
+
<!ELEMENT description (#PCDATA)>
|
10
|
+
<!ELEMENT bugreporting (#PCDATA)>
|
11
|
+
|
12
|
+
<!ELEMENT dependencies (dependency*)>
|
13
|
+
<!ELEMENT dependency (name, minimum_version?, maximum_version?, minimum_package_version?, maximum_package_version?, allowed_versions?, native?)>
|
14
|
+
<!ELEMENT minimum_version (#PCDATA)>
|
15
|
+
<!ELEMENT maximum_version (#PCDATA)>
|
16
|
+
<!ELEMENT minimum_package_version (#PCDATA)>
|
17
|
+
<!ELEMENT maximum_package_version (#PCDATA)>
|
18
|
+
<!ELEMENT allowed_versions (#PCDATA)>
|
19
|
+
<!ELEMENT native EMPTY>
|
20
|
+
|
21
|
+
<!ELEMENT externals (external*)>
|
22
|
+
<!ELEMENT external (name, (data|datafile|datascript))>
|
23
|
+
<!ELEMENT data (#PCDATA)>
|
24
|
+
<!ELEMENT datafile (#PCDATA)>
|
25
|
+
<!ELEMENT datascript (#PCDATA)>
|
26
|
+
|
27
|
+
<!ELEMENT files (file_defaults?, file*)>
|
28
|
+
<!ELEMENT file_defaults (posix?)>
|
29
|
+
<!ELEMENT posix (owner?, group?, perms?)>
|
30
|
+
<!ELEMENT owner (#PCDATA)>
|
31
|
+
<!ELEMENT group (#PCDATA)>
|
32
|
+
<!ELEMENT perms (#PCDATA)>
|
33
|
+
<!ELEMENT file (path, config?, encrypt?, init?, crontab?, posix?)>
|
34
|
+
<!ELEMENT path (#PCDATA)>
|
35
|
+
<!ELEMENT config EMPTY>
|
36
|
+
<!ELEMENT encrypt EMPTY>
|
37
|
+
<!ATTLIST encrypt precrypt (true|false) #IMPLIED>
|
38
|
+
<!ATTLIST encrypt algorithm CDATA #IMPLIED>
|
39
|
+
<!ELEMENT init (start?, levels?)>
|
40
|
+
<!ELEMENT start (#PCDATA)>
|
41
|
+
<!ELEMENT levels (#PCDATA)>
|
42
|
+
<!ELEMENT crontab (user?)>
|
43
|
+
<!ELEMENT user (#PCDATA)>
|
44
|
+
|
45
|
+
<!ELEMENT tpkg_version (#PCDATA)>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<!ELEMENT tpkg (name, version, package_version?, maintainer+, operatingsystem*, architecture*, description, bugreporting?, dependencies?, externals?, files?, tpkg_version?)>
|
2
|
+
|
3
|
+
<!ELEMENT name (#PCDATA)>
|
4
|
+
<!ELEMENT version (#PCDATA)>
|
5
|
+
<!ELEMENT package_version (#PCDATA)>
|
6
|
+
<!ELEMENT maintainer (#PCDATA)>
|
7
|
+
<!ELEMENT operatingsystem (#PCDATA)>
|
8
|
+
<!ELEMENT architecture (#PCDATA)>
|
9
|
+
<!ELEMENT description (#PCDATA)>
|
10
|
+
<!ELEMENT bugreporting (#PCDATA)>
|
11
|
+
|
12
|
+
<!ELEMENT dependencies (dependency*)>
|
13
|
+
<!ELEMENT dependency (name, minimum_version?, maximum_version?, minimum_package_version?, maximum_package_version?, allowed_versions?, native?)>
|
14
|
+
<!ELEMENT minimum_version (#PCDATA)>
|
15
|
+
<!ELEMENT maximum_version (#PCDATA)>
|
16
|
+
<!ELEMENT minimum_package_version (#PCDATA)>
|
17
|
+
<!ELEMENT maximum_package_version (#PCDATA)>
|
18
|
+
<!ELEMENT allowed_versions (#PCDATA)>
|
19
|
+
<!ELEMENT native EMPTY>
|
20
|
+
|
21
|
+
<!ELEMENT externals (external*)>
|
22
|
+
<!ELEMENT external (name, (data|datafile|datascript))>
|
23
|
+
<!ELEMENT data (#PCDATA)>
|
24
|
+
<!ELEMENT datafile (#PCDATA)>
|
25
|
+
<!ELEMENT datascript (#PCDATA)>
|
26
|
+
|
27
|
+
<!ELEMENT files (file_defaults?, file*)>
|
28
|
+
<!ELEMENT file_defaults (posix?)>
|
29
|
+
<!ELEMENT posix (owner?, group?, perms?)>
|
30
|
+
<!ELEMENT owner (#PCDATA)>
|
31
|
+
<!ELEMENT group (#PCDATA)>
|
32
|
+
<!ELEMENT perms (#PCDATA)>
|
33
|
+
<!ELEMENT file (path, config?, encrypt?, init?, crontab?, posix?)>
|
34
|
+
<!ELEMENT path (#PCDATA)>
|
35
|
+
<!ELEMENT config EMPTY>
|
36
|
+
<!ELEMENT encrypt EMPTY>
|
37
|
+
<!ATTLIST encrypt precrypt (true|false) #IMPLIED>
|
38
|
+
<!ATTLIST encrypt algorithm CDATA #IMPLIED>
|
39
|
+
<!ELEMENT init (start?, levels?)>
|
40
|
+
<!ELEMENT start (#PCDATA)>
|
41
|
+
<!ELEMENT levels (#PCDATA)>
|
42
|
+
<!ELEMENT crontab (user?)>
|
43
|
+
<!ELEMENT user (#PCDATA)>
|
44
|
+
|
45
|
+
<!ELEMENT tpkg_version (#PCDATA)>
|
data/schema/tpkg.dtd
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<!ELEMENT tpkg (name, version, package_version?, maintainer+, operatingsystem*, architecture*, description
|
1
|
+
<!ELEMENT tpkg (name, version, package_version?, maintainer+, operatingsystem*, architecture*, description, bugreporting?, dependencies?, externals?, files?, tpkg_version?)>
|
2
2
|
|
3
3
|
<!ELEMENT name (#PCDATA)>
|
4
4
|
<!ELEMENT version (#PCDATA)>
|
@@ -30,8 +30,9 @@
|
|
30
30
|
<!ELEMENT owner (#PCDATA)>
|
31
31
|
<!ELEMENT group (#PCDATA)>
|
32
32
|
<!ELEMENT perms (#PCDATA)>
|
33
|
-
<!ELEMENT file (path, encrypt?, init?, crontab?, posix?)>
|
33
|
+
<!ELEMENT file (path, config?, encrypt?, init?, crontab?, posix?)>
|
34
34
|
<!ELEMENT path (#PCDATA)>
|
35
|
+
<!ELEMENT config EMPTY>
|
35
36
|
<!ELEMENT encrypt EMPTY>
|
36
37
|
<!ATTLIST encrypt precrypt (true|false) #IMPLIED>
|
37
38
|
<!ATTLIST encrypt algorithm CDATA #IMPLIED>
|
@@ -41,3 +42,4 @@
|
|
41
42
|
<!ELEMENT crontab (user?)>
|
42
43
|
<!ELEMENT user (#PCDATA)>
|
43
44
|
|
45
|
+
<!ELEMENT tpkg_version (#PCDATA)>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tpkg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.27.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darren Dao
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-07-
|
13
|
+
date: 2010-07-29 00:00:00 +00:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -61,9 +61,11 @@ files:
|
|
61
61
|
- lib/tpkg/metadata.rb
|
62
62
|
- lib/tpkg.rb
|
63
63
|
- schema/tpkg-1.0.4.dtd
|
64
|
+
- schema/schema-1.0.9.yml
|
64
65
|
- schema/tpkg-1.0.0.dtd
|
65
66
|
- schema/tpkg-1.0.5.dtd
|
66
67
|
- schema/schema-1.0.7.yml
|
68
|
+
- schema/tpkg-1.0.9.dtd
|
67
69
|
- schema/tpkg.dtd
|
68
70
|
- schema/tpkg-1.0.1.dtd
|
69
71
|
- schema/tpkg-1.0.7.dtd
|
@@ -72,6 +74,8 @@ files:
|
|
72
74
|
- schema/tpkg-1.0.2.dtd
|
73
75
|
- schema/schema-1.0.6.yml
|
74
76
|
- schema/schema-1.0.yml
|
77
|
+
- schema/tpkg-1.0.8.dtd
|
78
|
+
- schema/schema-1.0.8.yml
|
75
79
|
- schema/tpkg-1.0.6.dtd
|
76
80
|
- schema/schema-1.0.5.yml
|
77
81
|
- bin/tpkg
|