tpkg 1.25.1 → 1.27.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|