tpkg 1.16.2 → 1.18.2
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 +2 -2
- data/bin/cpan2tpkg +82 -14
- data/bin/tpkg +54 -29
- data/bin/tpkg_xml_to_yml +19 -0
- data/lib/tpkg.rb +225 -145
- data/lib/tpkg/metadata.rb +37 -20
- metadata +7 -5
data/Rakefile
CHANGED
|
@@ -4,7 +4,7 @@ spec = Gem::Specification.new do |s|
|
|
|
4
4
|
s.summary = 'tpkg Application Packaging & Deployment'
|
|
5
5
|
s.add_dependency('facter')
|
|
6
6
|
s.add_dependency('net-ssh')
|
|
7
|
-
s.version = '1.
|
|
7
|
+
s.version = '1.18.2'
|
|
8
8
|
s.authors = ['Darren Dao', 'Jason Heiss']
|
|
9
9
|
s.email = 'tpkg-users@lists.sourceforge.net'
|
|
10
10
|
s.homepage = 'http://tpkg.sourceforge.net'
|
|
@@ -12,7 +12,7 @@ spec = Gem::Specification.new do |s|
|
|
|
12
12
|
s.platform = Gem::Platform::RUBY
|
|
13
13
|
s.required_ruby_version = '>=1.8'
|
|
14
14
|
s.files = Dir['**/**']
|
|
15
|
-
s.executables = [ 'tpkg', 'cpan2tpkg', 'gem2tpkg' ]
|
|
15
|
+
s.executables = [ 'tpkg', 'cpan2tpkg', 'gem2tpkg', 'tpkg_xml_to_yml' ]
|
|
16
16
|
end
|
|
17
17
|
Rake::GemPackageTask.new(spec).define
|
|
18
18
|
|
data/bin/cpan2tpkg
CHANGED
|
@@ -36,7 +36,6 @@ All options can be shortened to anything that's unique.
|
|
|
36
36
|
EOF
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
# FIXME: we're not actually using $modver, we're just letting CPAN installed the latest available version
|
|
40
39
|
my $modver;
|
|
41
40
|
my $pkgver = 1;
|
|
42
41
|
my %extradeps = ();
|
|
@@ -58,6 +57,13 @@ usage() if (!$getopt);
|
|
|
58
57
|
usage() if ($help);
|
|
59
58
|
usage() if (!$module);
|
|
60
59
|
|
|
60
|
+
# FIXME: we're not actually using $modver, we're just letting CPAN install
|
|
61
|
+
# the latest available version
|
|
62
|
+
if ($modver)
|
|
63
|
+
{
|
|
64
|
+
die "--version not implemented\n";
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
my @extradepsopts = split(/,/, $extradepsopts);
|
|
62
68
|
while (scalar @extradepsopts)
|
|
63
69
|
{
|
|
@@ -161,16 +167,51 @@ print "Installed modules to be packaged (except Perl):\n";
|
|
|
161
167
|
print join(', ', $extinst->modules), "\n";
|
|
162
168
|
|
|
163
169
|
# Inspect temp directory and package each installed module
|
|
164
|
-
foreach my $name ($extinst->modules)
|
|
170
|
+
MODULE: foreach my $name ($extinst->modules)
|
|
165
171
|
{
|
|
166
|
-
next if ($name eq 'Perl');
|
|
172
|
+
next MODULE if ($name eq 'Perl');
|
|
167
173
|
print "Packaging $name\n";
|
|
168
|
-
my $dashname = $name;
|
|
169
|
-
$dashname =~ s/::/-/g;
|
|
170
|
-
my $ver = $extinst->version($name);
|
|
171
|
-
print "Module version is $ver\n";
|
|
172
174
|
my %deps = ();
|
|
173
175
|
my $mod = CPAN::Shell->expand('Module', $name);
|
|
176
|
+
# Sometimes calling expand on a result from EU::I->modules doesn't
|
|
177
|
+
# work. For example, if the user requests Date::Parse that module
|
|
178
|
+
# is part of the TimeDate distribution. EU::I->modules will return
|
|
179
|
+
# ['Perl', 'TimeDate'], but calling expand on TimeDate fails. It
|
|
180
|
+
# seems like we should find an alternative to EU::I->modules,
|
|
181
|
+
# something that returns the distributions installed rather than the
|
|
182
|
+
# modules.
|
|
183
|
+
if (!$mod)
|
|
184
|
+
{
|
|
185
|
+
# If EU::I->modules only returned two results we can safely
|
|
186
|
+
# assume the !Perl one is whatever the user asked to have
|
|
187
|
+
# installed and use its expansion instead. Continue the example
|
|
188
|
+
# mentioned above, calling expand on TimeDate fails but calling
|
|
189
|
+
# expand on Date::Parse works, for whatever reason.
|
|
190
|
+
if (scalar($extinst->modules) == 2)
|
|
191
|
+
{
|
|
192
|
+
# We've already called expand on the user's request, so we
|
|
193
|
+
# can reuse that result.
|
|
194
|
+
$mod = $modobj;
|
|
195
|
+
warn "Failed to expand $name the usual way, secondary efforts ",
|
|
196
|
+
"successful\n";
|
|
197
|
+
}
|
|
198
|
+
else
|
|
199
|
+
{
|
|
200
|
+
warn "Failed to expand $name, secondary efforts failed, skipping\n";
|
|
201
|
+
next MODULE;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
# Note that this won't work if we ever implement letting the user
|
|
205
|
+
# select a specific version (via the --version CLI option), as
|
|
206
|
+
# expand presumably returns the info for the latest available
|
|
207
|
+
# version of the distribution. Note that EU::I->version returns the
|
|
208
|
+
# version of the module, not the version of the distribution, and
|
|
209
|
+
# those can differ. We're packaging the distribution, which may
|
|
210
|
+
# include multiple modules with their own, differing versions.
|
|
211
|
+
my $ver = module_to_dist_ver($mod);
|
|
212
|
+
print "Module version is $ver\n";
|
|
213
|
+
my $pkgname = module_to_pkg_name($mod);
|
|
214
|
+
print "Package name, based on distribution, is $pkgname\n";
|
|
174
215
|
# Looks like newer versions of CPAN.pm have a CPAN::Module::distribution()
|
|
175
216
|
# method. What I'm using here is a little hacky but works, so I
|
|
176
217
|
# don't think it is worth forcing users to use a newer version.
|
|
@@ -199,7 +240,7 @@ foreach my $name ($extinst->modules)
|
|
|
199
240
|
%prereqs = ();
|
|
200
241
|
}
|
|
201
242
|
}
|
|
202
|
-
foreach my $dep (keys %prereqs)
|
|
243
|
+
PREREQ: foreach my $dep (keys %prereqs)
|
|
203
244
|
{
|
|
204
245
|
# Skip dependencies on core modules
|
|
205
246
|
my $depmod = CPAN::Shell->expand('Module', $dep);
|
|
@@ -213,15 +254,14 @@ foreach my $name ($extinst->modules)
|
|
|
213
254
|
if ($depmod->inst_file =~ m,/home/t/perl,)
|
|
214
255
|
{
|
|
215
256
|
print "Prereq $dep is a core module, skipping\n";
|
|
216
|
-
next;
|
|
257
|
+
next PREREQ;
|
|
217
258
|
}
|
|
218
259
|
|
|
219
|
-
my $
|
|
220
|
-
$
|
|
221
|
-
$deps{$dashdep} = {};
|
|
260
|
+
my $deppkgname = module_to_pkg_name($depmod);
|
|
261
|
+
$deps{$deppkgname} = {};
|
|
222
262
|
if ($prereqs{$dep} ne '0')
|
|
223
263
|
{
|
|
224
|
-
$deps{$
|
|
264
|
+
$deps{$deppkgname}{minimum_version} = $prereqs{$dep};
|
|
225
265
|
}
|
|
226
266
|
}
|
|
227
267
|
}
|
|
@@ -248,7 +288,7 @@ foreach my $name ($extinst->modules)
|
|
|
248
288
|
print $xmlfh '<?xml version="1.0" encoding="UTF-8"?>', "\n";
|
|
249
289
|
print $xmlfh '<!DOCTYPE tpkg SYSTEM "http://tpkg.sourceforge.net/tpkg-1.0.dtd">', "\n";
|
|
250
290
|
print $xmlfh '<tpkg>', "\n";
|
|
251
|
-
print $xmlfh " <name>cpan-perl$majorminor-$
|
|
291
|
+
print $xmlfh " <name>cpan-perl$majorminor-$pkgname</name>", "\n";
|
|
252
292
|
print $xmlfh " <version>$ver</version>", "\n";
|
|
253
293
|
print $xmlfh " <package_version>$pkgver</package_version>", "\n";
|
|
254
294
|
print $xmlfh ' <maintainer>cpan2tpkg</maintainer>', "\n";
|
|
@@ -346,3 +386,31 @@ foreach my $name ($extinst->modules)
|
|
|
346
386
|
system("tpkg --make $tpkgdir");
|
|
347
387
|
}
|
|
348
388
|
|
|
389
|
+
# Pass in an expanded module (CPAN::Shell->expand), get back a name
|
|
390
|
+
# suitable for use in packaging.
|
|
391
|
+
# The package name is based on the distribution that contains the
|
|
392
|
+
# module, as sometimes multiple modules are packaged into a single
|
|
393
|
+
# distribution file.
|
|
394
|
+
sub module_to_pkg_name
|
|
395
|
+
{
|
|
396
|
+
my $mod = shift;
|
|
397
|
+
my $distfilename = basename($mod->{RO}{CPAN_FILE});
|
|
398
|
+
my $pkgname = $distfilename;
|
|
399
|
+
# Cut off the version and suffix
|
|
400
|
+
# I.e. TimeDate-1.20.tar.gz -> TimeDate
|
|
401
|
+
$pkgname =~ s/-\d.*//;
|
|
402
|
+
return $pkgname;
|
|
403
|
+
}
|
|
404
|
+
# Pass in an expanded module (CPAN::Shell->expand), get back the version
|
|
405
|
+
# of the associated distribution.
|
|
406
|
+
sub module_to_dist_ver
|
|
407
|
+
{
|
|
408
|
+
my $mod = shift;
|
|
409
|
+
my $distfilename = basename($mod->{RO}{CPAN_FILE});
|
|
410
|
+
# Cut off the distribution name and suffix
|
|
411
|
+
# I.e. TimeDate-1.20.tar.gz -> 1.20
|
|
412
|
+
$distfilename =~ /-(\d.*?)\.\D/;
|
|
413
|
+
my $distver = $1;
|
|
414
|
+
return $distver;
|
|
415
|
+
}
|
|
416
|
+
|
data/bin/tpkg
CHANGED
|
@@ -29,6 +29,7 @@ require 'tpkg'
|
|
|
29
29
|
@worker_count = 10
|
|
30
30
|
@rerun_with_sudo = false
|
|
31
31
|
@tpkg_options = {}
|
|
32
|
+
@init_options = {}
|
|
32
33
|
|
|
33
34
|
def rerun_with_sudo_if_necessary
|
|
34
35
|
if Process.euid != 0 && @sudo
|
|
@@ -97,39 +98,60 @@ opts.on('--verify', '-V', '=NAME', 'Verify packages') do |opt|
|
|
|
97
98
|
end
|
|
98
99
|
opts.on('--start', '=NAME', 'Start the init script for the specified package', Array) do |opt|
|
|
99
100
|
@rerun_with_sudo = true
|
|
100
|
-
@action = :
|
|
101
|
-
@
|
|
101
|
+
@action = :execute_init
|
|
102
|
+
@init_options[:packages] = opt
|
|
103
|
+
@init_options[:cmd] = 'start'
|
|
102
104
|
end
|
|
103
105
|
opts.on('--stop', '=NAME', 'Stop the init script for the specified package', Array) do |opt|
|
|
104
106
|
@rerun_with_sudo = true
|
|
105
|
-
@action = :
|
|
106
|
-
@
|
|
107
|
+
@action = :execute_init
|
|
108
|
+
@init_options[:packages] = opt
|
|
109
|
+
@init_options[:cmd] = 'stop'
|
|
107
110
|
end
|
|
108
111
|
opts.on('--restart', '=NAME', 'Restart the init script for the specified package', Array) do |opt|
|
|
109
112
|
@rerun_with_sudo = true
|
|
110
|
-
@action = :
|
|
111
|
-
@
|
|
113
|
+
@action = :execute_init
|
|
114
|
+
@init_options[:packages] = opt
|
|
115
|
+
@init_options[:cmd] = 'restart'
|
|
112
116
|
end
|
|
113
117
|
opts.on('--reload', '=NAME', 'Reload the init script for the specified package', Array) do |opt|
|
|
114
118
|
@rerun_with_sudo = true
|
|
115
|
-
@action = :
|
|
116
|
-
@
|
|
119
|
+
@action = :execute_init
|
|
120
|
+
@init_options[:packages] = opt
|
|
121
|
+
@init_options[:cmd] = 'reload'
|
|
117
122
|
end
|
|
118
123
|
opts.on('--start-all', 'Start the init scripts for all packages') do |opt|
|
|
119
124
|
@rerun_with_sudo = true
|
|
120
|
-
@action = :
|
|
125
|
+
@action = :execute_init
|
|
126
|
+
@init_options[:cmd] = 'start'
|
|
121
127
|
end
|
|
122
128
|
opts.on('--stop-all', 'Stop the init script for all packages') do |opt|
|
|
123
129
|
@rerun_with_sudo = true
|
|
124
|
-
@action = :
|
|
130
|
+
@action = :execute_init
|
|
131
|
+
@init_options[:cmd] = 'stop'
|
|
125
132
|
end
|
|
126
133
|
opts.on('--restart-all', 'Restart the init script for all packages') do |opt|
|
|
127
134
|
@rerun_with_sudo = true
|
|
128
|
-
@action = :
|
|
135
|
+
@action = :execute_init
|
|
136
|
+
@init_options[:cmd] = 'restart'
|
|
129
137
|
end
|
|
130
138
|
opts.on('--reload-all', 'Reload the init script for all packages') do |opt|
|
|
131
139
|
@rerun_with_sudo = true
|
|
132
|
-
@action = :
|
|
140
|
+
@action = :execute_init
|
|
141
|
+
@init_options[:cmd] = 'reload'
|
|
142
|
+
end
|
|
143
|
+
opts.on('--exec-init', '=NAME', 'Execute init scripts for the specified packages', Array) do |opt|
|
|
144
|
+
@rerun_with_sudo = true
|
|
145
|
+
@init_options[:packages] = opt
|
|
146
|
+
@action = :execute_init
|
|
147
|
+
end
|
|
148
|
+
opts.on('--init-script', '=NAME', 'What init scripts to execute', Array) do |opt|
|
|
149
|
+
@rerun_with_sudo = true
|
|
150
|
+
@init_options[:scripts] = opt
|
|
151
|
+
end
|
|
152
|
+
opts.on('--init-cmd', '=CMD', 'Invoke the specified init script command') do |opt|
|
|
153
|
+
@rerun_with_sudo = true
|
|
154
|
+
@init_options[:cmd] = opt
|
|
133
155
|
end
|
|
134
156
|
opts.on('--query', '-q', '=NAMES', 'List installed packages', Array) do |opt|
|
|
135
157
|
# People mistype -qa instead of --qa frequently
|
|
@@ -178,8 +200,8 @@ opts.on('--dw', '=INTEGER', 'Number of workers for deploying') do |opt|
|
|
|
178
200
|
@worker_count = opt.to_i
|
|
179
201
|
@deploy_params = @deploy_params - ['--dw', @worker_count, "--dw=#{opt}"]
|
|
180
202
|
end
|
|
181
|
-
opts.on('--qX', '=FILENAME', 'Display tpkg.xml of the given package') do |opt|
|
|
182
|
-
@action = :
|
|
203
|
+
opts.on('--qX', '=FILENAME', 'Display tpkg.xml or tpkg.yml of the given package') do |opt|
|
|
204
|
+
@action = :query_tpkg_metadata
|
|
183
205
|
@action_value = opt
|
|
184
206
|
end
|
|
185
207
|
opts.on('--qenv', "Display machine's information") do |opt|
|
|
@@ -360,18 +382,12 @@ when :verify
|
|
|
360
382
|
end
|
|
361
383
|
puts "Package verification failed" unless success
|
|
362
384
|
end
|
|
363
|
-
when :
|
|
364
|
-
tpkg = instantiate_tpkg(@tpkg_options)
|
|
365
|
-
ret_val = tpkg.execute_init(@action_value, "start")
|
|
366
|
-
when :stop_init
|
|
367
|
-
tpkg = instantiate_tpkg(@tpkg_options)
|
|
368
|
-
ret_val = tpkg.execute_init(@action_value, "stop")
|
|
369
|
-
when :restart_init
|
|
385
|
+
when :execute_init
|
|
370
386
|
tpkg = instantiate_tpkg(@tpkg_options)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
ret_val = tpkg.execute_init(@
|
|
387
|
+
if @init_options[:cmd].nil?
|
|
388
|
+
raise "You didn't specify what init command to run"
|
|
389
|
+
end
|
|
390
|
+
ret_val = tpkg.execute_init(@init_options)
|
|
375
391
|
when :query_installed
|
|
376
392
|
tpkg = instantiate_tpkg(@tpkg_options)
|
|
377
393
|
req = nil
|
|
@@ -418,6 +434,8 @@ when :query_info
|
|
|
418
434
|
next if already_displayed[metadata[:filename]]
|
|
419
435
|
already_displayed[metadata[:filename]] = true
|
|
420
436
|
[:name, :version, :package_version, :operatingsystem, :architecture, :maintainer, :description, :bugreporting].each do |field|
|
|
437
|
+
metadata[field] = 'any' if field == :operatingsystem && metadata[field].nil?
|
|
438
|
+
metadata[field] = 'any' if field == :architecture && metadata[field].nil?
|
|
421
439
|
if metadata[field]
|
|
422
440
|
if metadata[field].kind_of?(Array)
|
|
423
441
|
puts "#{field}: #{metadata[field].join(',')}"
|
|
@@ -426,6 +444,10 @@ when :query_info
|
|
|
426
444
|
end
|
|
427
445
|
end
|
|
428
446
|
end
|
|
447
|
+
if metadata[:dependencies]
|
|
448
|
+
puts "This package depends on other packages, use --qd/--qld to view the dependencies."
|
|
449
|
+
end
|
|
450
|
+
puts "================================================================================"
|
|
429
451
|
end
|
|
430
452
|
when :query_list_files
|
|
431
453
|
tpkg = instantiate_tpkg(@tpkg_options)
|
|
@@ -498,6 +520,7 @@ when :query_requires
|
|
|
498
520
|
next if pkg[:source] != :currently_installed
|
|
499
521
|
puts "The following package(s) require #{pkg[:metadata][:filename]}:"
|
|
500
522
|
dependencies.each do | requiree, deps |
|
|
523
|
+
next if deps.nil?
|
|
501
524
|
deps.each do | dep |
|
|
502
525
|
if Tpkg::package_meets_requirement?(pkg, dep)
|
|
503
526
|
puts " #{requiree}"
|
|
@@ -546,12 +569,14 @@ when :query_depends
|
|
|
546
569
|
end
|
|
547
570
|
end
|
|
548
571
|
end
|
|
549
|
-
when :
|
|
572
|
+
when :query_tpkg_metadata
|
|
550
573
|
tpkg = instantiate_tpkg(@tpkg_options)
|
|
551
|
-
if
|
|
552
|
-
puts
|
|
574
|
+
if File.exist?(@action_value)
|
|
575
|
+
puts Tpkg::extract_tpkg_metadata_file(@action_value)
|
|
576
|
+
elsif File.exists?(File.join(tpkg.installed_directory, @action_value))
|
|
577
|
+
puts Tpkg::extract_tpkg_metadata_file(File.join(tpkg.installed_directory, @action_value))
|
|
553
578
|
else
|
|
554
|
-
puts
|
|
579
|
+
puts "File #{@action_value} doesn't exist."
|
|
555
580
|
end
|
|
556
581
|
when :query_env
|
|
557
582
|
puts "Operating System: #{Tpkg::get_os}"
|
data/bin/tpkg_xml_to_yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/ruby -w
|
|
2
|
+
|
|
3
|
+
# This script expects one argument, which is the tpkg.xml file
|
|
4
|
+
# that you want to convert to yml format.
|
|
5
|
+
# The resulting data is output to stdout
|
|
6
|
+
require 'tpkg'
|
|
7
|
+
|
|
8
|
+
if ARGV.size < 1
|
|
9
|
+
raise "You didn't specify a file"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
xmlfile = ARGV[0]
|
|
13
|
+
if !File.exist?(xmlfile)
|
|
14
|
+
raise "File doesn't exist"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
metadata_text = File.read(xmlfile)
|
|
18
|
+
metadata = Metadata.new(metadata_text, 'xml')
|
|
19
|
+
metadata.write($stdout)
|
data/lib/tpkg.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
##############################################################################
|
|
2
2
|
# tpkg package management system library
|
|
3
|
-
# Copyright 2009, AT&T Interactive
|
|
3
|
+
# Copyright 2009, 2010 AT&T Interactive
|
|
4
4
|
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
|
5
5
|
##############################################################################
|
|
6
6
|
|
|
@@ -48,7 +48,7 @@ require 'metadata'
|
|
|
48
48
|
|
|
49
49
|
class Tpkg
|
|
50
50
|
|
|
51
|
-
VERSION = '1.
|
|
51
|
+
VERSION = '1.18.2'
|
|
52
52
|
CONFIGDIR = '/etc'
|
|
53
53
|
|
|
54
54
|
POSTINSTALL_ERR = 2
|
|
@@ -241,8 +241,8 @@ class Tpkg
|
|
|
241
241
|
# by the package. For example, checksum, path, relocatable or not, etc.
|
|
242
242
|
File.open(File.join(tpkgdir, "file_metadata.bin"), "w") do |file|
|
|
243
243
|
filemetadata = get_filemetadata_from_directory(tpkgdir)
|
|
244
|
-
Marshal::dump(filemetadata.
|
|
245
|
-
# YAML::dump(filemetadata.
|
|
244
|
+
Marshal::dump(filemetadata.to_hash, file)
|
|
245
|
+
# YAML::dump(filemetadata.to_hash, file)
|
|
246
246
|
end
|
|
247
247
|
|
|
248
248
|
# Check all the files are there as specified in the metadata config file
|
|
@@ -510,7 +510,8 @@ class Tpkg
|
|
|
510
510
|
tpkg_xml = REXML::Document.new(pipe.read)
|
|
511
511
|
end
|
|
512
512
|
if !$?.success?
|
|
513
|
-
|
|
513
|
+
warn "Warning: Extracting tpkg.xml from #{package_file} failed"
|
|
514
|
+
return nil
|
|
514
515
|
end
|
|
515
516
|
|
|
516
517
|
# Insert an attribute on the root element with the package filename
|
|
@@ -543,7 +544,7 @@ class Tpkg
|
|
|
543
544
|
metadata << existing_metadata[File.basename(pkg)]
|
|
544
545
|
else
|
|
545
546
|
xml = xml_metadata_from_package(pkg)
|
|
546
|
-
metadata << xml.root
|
|
547
|
+
metadata << xml.root if xml
|
|
547
548
|
end
|
|
548
549
|
end
|
|
549
550
|
|
|
@@ -560,8 +561,13 @@ class Tpkg
|
|
|
560
561
|
existing_metadata = {}
|
|
561
562
|
|
|
562
563
|
if File.exists?(existing_metadata_file)
|
|
563
|
-
|
|
564
|
-
|
|
564
|
+
metadata_lists = File.read(File.join(directory, 'metadata.yml')).split("---")
|
|
565
|
+
metadata_lists.each do | metadata_text |
|
|
566
|
+
if metadata_text =~ /^:?filename:(.+)/
|
|
567
|
+
filename = $1.strip
|
|
568
|
+
existing_metadata[filename] = Metadata.new(metadata_text,'yml')
|
|
569
|
+
end
|
|
570
|
+
end
|
|
565
571
|
end
|
|
566
572
|
|
|
567
573
|
# Populate the metadata array with metadata for all of the packages
|
|
@@ -577,7 +583,7 @@ class Tpkg
|
|
|
577
583
|
|
|
578
584
|
return metadata
|
|
579
585
|
end
|
|
580
|
-
|
|
586
|
+
|
|
581
587
|
# Extracts the metadata from a directory of package files and saves it
|
|
582
588
|
# to metadata.xml in that directory
|
|
583
589
|
def self.extract_metadata(directory, dest=nil)
|
|
@@ -605,7 +611,7 @@ class Tpkg
|
|
|
605
611
|
# And write that out to metadata.yml
|
|
606
612
|
metadata_tmpfile = Tempfile.new('metadata.yml', dest)
|
|
607
613
|
metadata.each do | metadata |
|
|
608
|
-
YAML::dump(metadata.
|
|
614
|
+
YAML::dump(metadata.to_hash, metadata_tmpfile)
|
|
609
615
|
end
|
|
610
616
|
metadata_tmpfile.close
|
|
611
617
|
File.chmod(0644, metadata_tmpfile.path)
|
|
@@ -698,7 +704,9 @@ class Tpkg
|
|
|
698
704
|
# A req for a native package must be satisfied by a native package
|
|
699
705
|
puts "Package fails native requirement" if @@debug
|
|
700
706
|
result = false
|
|
701
|
-
elsif
|
|
707
|
+
elsif req[:filename]
|
|
708
|
+
result = false if req[:filename] != metadata[:filename]
|
|
709
|
+
elsif req[:type] == :tpkg &&
|
|
702
710
|
(pkg[:source] == :native_installed || pkg[:source] == :native_available)
|
|
703
711
|
# Likewise a req for a tpkg must be satisfied by a tpkg
|
|
704
712
|
puts "Package fails non-native requirement" if @@debug
|
|
@@ -771,6 +779,9 @@ class Tpkg
|
|
|
771
779
|
puts "Package fails name" if @@debug
|
|
772
780
|
result = false
|
|
773
781
|
end
|
|
782
|
+
if result
|
|
783
|
+
puts "Package matches" if @@debug
|
|
784
|
+
end
|
|
774
785
|
result
|
|
775
786
|
end
|
|
776
787
|
|
|
@@ -963,18 +974,11 @@ class Tpkg
|
|
|
963
974
|
req = {}
|
|
964
975
|
parts = request.split('=')
|
|
965
976
|
|
|
966
|
-
# upgrade/remove/query options
|
|
967
|
-
#
|
|
968
|
-
#
|
|
969
|
-
if
|
|
970
|
-
|
|
971
|
-
req[:name] = metadata[:name]
|
|
972
|
-
req[:minimum_version] = metadata[:version].to_s
|
|
973
|
-
req[:maximum_version] = metadata[:version].to_s
|
|
974
|
-
if metadata[:package_version] && !metadata[:package_version].to_s.empty?
|
|
975
|
-
req[:minimum_package_version] = metadata[:package_version].to_s
|
|
976
|
-
req[:maximum_package_version] = metadata[:package_version].to_s
|
|
977
|
-
end
|
|
977
|
+
# upgrade/remove/query options could take package filenames
|
|
978
|
+
# assuming that the filename is of the correct format, such as
|
|
979
|
+
# foo-1.0.tpkg or foo-1.0-1.tpkg
|
|
980
|
+
if request =~ /\.tpkg$/
|
|
981
|
+
req = {:filename => request, :name => request.split("-")[0]}
|
|
978
982
|
elsif parts.length > 2 && parts[-2] =~ /^[\d\.]/ && parts[-1] =~ /^[\d\.]/
|
|
979
983
|
package_version = parts.pop
|
|
980
984
|
version = parts.pop
|
|
@@ -991,6 +995,7 @@ class Tpkg
|
|
|
991
995
|
else
|
|
992
996
|
req[:name] = parts.join('-')
|
|
993
997
|
end
|
|
998
|
+
req[:type] = :tpkg
|
|
994
999
|
req
|
|
995
1000
|
end
|
|
996
1001
|
|
|
@@ -1032,21 +1037,22 @@ class Tpkg
|
|
|
1032
1037
|
end
|
|
1033
1038
|
end
|
|
1034
1039
|
|
|
1035
|
-
def self.
|
|
1040
|
+
def self.extract_tpkg_metadata_file(package_file)
|
|
1036
1041
|
result = ""
|
|
1037
1042
|
workdir = ""
|
|
1038
1043
|
begin
|
|
1039
1044
|
topleveldir = Tpkg::package_toplevel_directory(package_file)
|
|
1040
1045
|
workdir = Tpkg::tempdir(topleveldir)
|
|
1041
1046
|
system("#{find_tar} -xf #{package_file} -O #{File.join(topleveldir, 'tpkg.tar')} | #{find_tar} -C #{workdir} -xpf -")
|
|
1042
|
-
|
|
1043
|
-
if
|
|
1044
|
-
|
|
1047
|
+
|
|
1048
|
+
if File.exist?(File.join(workdir,"tpkg", "tpkg.yml"))
|
|
1049
|
+
metadata_file = File.join(workdir,"tpkg", "tpkg.yml")
|
|
1050
|
+
elsif File.exist?(File.join(workdir,"tpkg", "tpkg.xml"))
|
|
1051
|
+
metadata_file = File.join(workdir,"tpkg", "tpkg.xml")
|
|
1045
1052
|
else
|
|
1046
|
-
|
|
1047
|
-
result = f.read
|
|
1048
|
-
end
|
|
1053
|
+
raise "#{package_file} does not contain metadata configuration file."
|
|
1049
1054
|
end
|
|
1055
|
+
result = File.read(metadata_file)
|
|
1050
1056
|
rescue
|
|
1051
1057
|
puts "Failed to extract package."
|
|
1052
1058
|
ensure
|
|
@@ -1275,13 +1281,12 @@ class Tpkg
|
|
|
1275
1281
|
if @@debug
|
|
1276
1282
|
@sources.each do |source|
|
|
1277
1283
|
count = metadata.inject(0) do |memo,m|
|
|
1278
|
-
# metadata is a hash of pkgname => array of
|
|
1279
|
-
#
|
|
1284
|
+
# metadata is a hash of pkgname => array of Metadata
|
|
1285
|
+
# objects.
|
|
1280
1286
|
# Thus m is a 2 element array of [pkgname, array of
|
|
1281
|
-
#
|
|
1282
|
-
#
|
|
1283
|
-
|
|
1284
|
-
memo + m[1].select{|mh| mh[:source] == source}.length
|
|
1287
|
+
# Metadata objects] And thus m[1] is the array of
|
|
1288
|
+
# Metadata objects.
|
|
1289
|
+
memo + m[1].select{|mo| mo.source == source}.length
|
|
1285
1290
|
end
|
|
1286
1291
|
puts "Found #{count} packages from #{source}"
|
|
1287
1292
|
end
|
|
@@ -1346,34 +1351,35 @@ class Tpkg
|
|
|
1346
1351
|
{:arg => 'available', :header => 'Available', :source => :native_available} ].each do |yum|
|
|
1347
1352
|
puts "available_native_packages running 'yum list #{yum[:arg]} #{pkgname}'" if @@debug
|
|
1348
1353
|
stderr_first_line = nil
|
|
1349
|
-
Open3.popen3("yum
|
|
1354
|
+
Open3.popen3("yum info #{yum[:arg]} #{pkgname}") do |stdin, stdout, stderr|
|
|
1350
1355
|
stdin.close
|
|
1351
1356
|
read_packages = false
|
|
1357
|
+
name = version = package_version = nil
|
|
1352
1358
|
stdout.each_line do |line|
|
|
1353
1359
|
if line =~ /#{yum[:header]} Packages/
|
|
1354
1360
|
# Skip the header lines until we get to this line
|
|
1355
1361
|
read_packages = true
|
|
1356
1362
|
elsif read_packages
|
|
1357
|
-
|
|
1363
|
+
if line =~ /^Name\s*:\s*(.+)/
|
|
1364
|
+
name = $1.strip
|
|
1365
|
+
elsif line =~ /^Arch\s*:\s*(.+)/
|
|
1366
|
+
arch = $1.strip
|
|
1367
|
+
elsif line =~ /^Version\s*:\s*(.+)/
|
|
1368
|
+
version = $1.strip.to_s
|
|
1369
|
+
elsif line =~ /^Release\s*:\s*(.+)/
|
|
1370
|
+
package_version = $1.strip.to_s
|
|
1371
|
+
elsif line =~ /^Repo\s*:\s*(.+)/
|
|
1372
|
+
repo = $1.strip
|
|
1373
|
+
elsif line =~ /^\s*$/
|
|
1374
|
+
pkg = pkg_for_native_package(name, version, package_version, yum[:source])
|
|
1375
|
+
native_packages << pkg
|
|
1376
|
+
name = version = package_version = nil
|
|
1377
|
+
end
|
|
1358
1378
|
# In the end we ignore the architecture. Anything that
|
|
1359
1379
|
# shows up in yum should be installable on this box, and
|
|
1360
1380
|
# the chance of a mismatch between facter's idea of the
|
|
1361
1381
|
# architecture and RPM's idea is high. I.e. i386 vs i686
|
|
1362
1382
|
# or i32e vs x86_64 or whatever.
|
|
1363
|
-
name, arch = name_and_arch.split('.')
|
|
1364
|
-
# This is prone to error, as both the version and release
|
|
1365
|
-
# (what we call package version) could contain '-', so
|
|
1366
|
-
# there's no reliable way to parse the combined value.
|
|
1367
|
-
# RPM can show them separately, but seemingly not yum.
|
|
1368
|
-
# We could use rpm to list installed packages, but we
|
|
1369
|
-
# have to use yum to get available packages so we're
|
|
1370
|
-
# stuck with the problem.
|
|
1371
|
-
verparts = ver_and_release.split('-')
|
|
1372
|
-
package_version = verparts.pop
|
|
1373
|
-
version = verparts.join('-')
|
|
1374
|
-
# Create the pkg structure
|
|
1375
|
-
pkg = pkg_for_native_package(name, version, package_version, yum[:source])
|
|
1376
|
-
native_packages << pkg
|
|
1377
1383
|
end
|
|
1378
1384
|
end
|
|
1379
1385
|
stderr_first_line = stderr.gets
|
|
@@ -1629,7 +1635,7 @@ class Tpkg
|
|
|
1629
1635
|
begin
|
|
1630
1636
|
FileUtils.mkdir_p(package_metadata_dir)
|
|
1631
1637
|
File.open(metadata_file, "w") do |file|
|
|
1632
|
-
YAML::dump(m.
|
|
1638
|
+
YAML::dump(m.to_hash, file)
|
|
1633
1639
|
end
|
|
1634
1640
|
rescue Errno::EACCES
|
|
1635
1641
|
raise if Process.euid == 0
|
|
@@ -1778,18 +1784,21 @@ class Tpkg
|
|
|
1778
1784
|
files
|
|
1779
1785
|
end
|
|
1780
1786
|
|
|
1781
|
-
# Returns the best solution that meets the given requirements. Some
|
|
1782
|
-
#
|
|
1783
|
-
#
|
|
1784
|
-
#
|
|
1785
|
-
#
|
|
1786
|
-
#
|
|
1787
|
+
# Returns the best solution that meets the given requirements. Some or all
|
|
1788
|
+
# packages may be optionally pre-selected and specified via the packages
|
|
1789
|
+
# parameter, otherwise packages are picked from the set of available
|
|
1790
|
+
# packages. The requirements parameter is an array of package requirements.
|
|
1791
|
+
# The packages parameter is in the form of a hash with package names as keys
|
|
1792
|
+
# pointing to arrays of package specs (our standard hash of package metadata
|
|
1793
|
+
# and source). The core_packages parameter is an array of the names of
|
|
1794
|
+
# packages that should be considered core requirements, i.e. the user
|
|
1795
|
+
# specifically requested they be installed or upgraded. The return value
|
|
1787
1796
|
# will be an array of package specs.
|
|
1788
1797
|
MAX_POSSIBLE_SOLUTIONS_TO_CHECK = 10000
|
|
1789
1798
|
def best_solution(requirements, packages, core_packages)
|
|
1790
1799
|
# Dup objects passed to us so that resolve_dependencies is free to
|
|
1791
1800
|
# change them without potentially messing up our caller
|
|
1792
|
-
result = resolve_dependencies(requirements.dup, packages.dup, core_packages.dup)
|
|
1801
|
+
result = resolve_dependencies(requirements.dup, {:tpkg => packages.dup, :native => {}}, core_packages.dup)
|
|
1793
1802
|
if @@debug
|
|
1794
1803
|
if result[:solution]
|
|
1795
1804
|
puts "bestsol picks: #{result[:solution].inspect}" if @@debug
|
|
@@ -1801,21 +1810,30 @@ class Tpkg
|
|
|
1801
1810
|
end
|
|
1802
1811
|
|
|
1803
1812
|
# Recursive method used by best_solution
|
|
1813
|
+
# Parameters mostly map from best_solution, but packages turns into a hash
|
|
1814
|
+
# with two possible keys, :tpkg and :native. The value for the :tpkg key
|
|
1815
|
+
# would be the packages parameter from best_solution. Native packages are
|
|
1816
|
+
# only installed due to dependencies, we don't let the user request them
|
|
1817
|
+
# directly, so callers of best_solution never need to pass in a package list
|
|
1818
|
+
# for native packages. Separating the two sets of packages allows us to
|
|
1819
|
+
# calculate a solution that contains both a tpkg and a native package with
|
|
1820
|
+
# the same name. This may be necessary if different dependencies of the
|
|
1821
|
+
# core packages end up needing both.
|
|
1804
1822
|
def resolve_dependencies(requirements, packages, core_packages, number_of_possible_solutions_checked=0)
|
|
1805
1823
|
# Make sure we have populated package lists for all requirements.
|
|
1806
1824
|
# Filter the package lists against the requirements and
|
|
1807
1825
|
# ensure we can at least satisfy the initial requirements.
|
|
1808
1826
|
requirements.each do |req|
|
|
1809
|
-
if !packages[req[:name]]
|
|
1827
|
+
if !packages[req[:type]][req[:name]]
|
|
1810
1828
|
puts "resolvedeps initializing packages for #{req.inspect}" if @@debug
|
|
1811
|
-
packages[req[:name]] =
|
|
1829
|
+
packages[req[:type]][req[:name]] =
|
|
1812
1830
|
available_packages_that_meet_requirement(req)
|
|
1813
1831
|
else
|
|
1814
1832
|
# Loop over packages and eliminate ones that don't work for
|
|
1815
1833
|
# this requirement
|
|
1816
1834
|
puts "resolvedeps filtering packages for #{req.inspect}" if @@debug
|
|
1817
|
-
packages[req[:name]] =
|
|
1818
|
-
packages[req[:name]].select do |pkg|
|
|
1835
|
+
packages[req[:type]][req[:name]] =
|
|
1836
|
+
packages[req[:type]][req[:name]].select do |pkg|
|
|
1819
1837
|
# When this method is called recursively there might be a
|
|
1820
1838
|
# nil entry inserted into packages by the sorting code
|
|
1821
1839
|
# below. We need to skip those.
|
|
@@ -1824,7 +1842,7 @@ class Tpkg
|
|
|
1824
1842
|
end
|
|
1825
1843
|
end
|
|
1826
1844
|
end
|
|
1827
|
-
if packages[req[:name]].empty?
|
|
1845
|
+
if packages[req[:type]][req[:name]].empty?
|
|
1828
1846
|
if @@debug
|
|
1829
1847
|
puts "No packages matching #{req.inspect}"
|
|
1830
1848
|
end
|
|
@@ -1832,15 +1850,17 @@ class Tpkg
|
|
|
1832
1850
|
end
|
|
1833
1851
|
end
|
|
1834
1852
|
# Sort the packages
|
|
1835
|
-
|
|
1836
|
-
pkgs
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1853
|
+
[:tpkg, :native].each do |type|
|
|
1854
|
+
packages[type].each do |pkgname, pkgs|
|
|
1855
|
+
pkgs.sort!(&SORT_PACKAGES)
|
|
1856
|
+
# Only currently installed packages are allowed to score 0.
|
|
1857
|
+
# Anything else can score 1 at best. This ensures
|
|
1858
|
+
# that we prefer the solution which leaves the most
|
|
1859
|
+
# currently installed packages alone.
|
|
1860
|
+
if pkgs[0][:source] != :currently_installed &&
|
|
1861
|
+
pkgs[0][:source] != :native_installed
|
|
1862
|
+
pkgs.unshift(nil)
|
|
1863
|
+
end
|
|
1844
1864
|
end
|
|
1845
1865
|
end
|
|
1846
1866
|
|
|
@@ -1885,13 +1905,16 @@ class Tpkg
|
|
|
1885
1905
|
# [a2, b2, c2] (avg 2)
|
|
1886
1906
|
|
|
1887
1907
|
# Divide packages into core and non-core packages
|
|
1888
|
-
corepkgs = packages.reject{|pkgname, pkgs| !core_packages.include?(pkgname)}
|
|
1889
|
-
noncorepkgs =
|
|
1908
|
+
corepkgs = packages[:tpkg].reject{|pkgname, pkgs| !core_packages.include?(pkgname)}
|
|
1909
|
+
noncorepkgs = {}
|
|
1910
|
+
noncorepkgs[:tpkg] = packages[:tpkg].reject{|pkgname, pkgs| core_packages.include?(pkgname)}
|
|
1911
|
+
noncorepkgs[:native] = packages[:native]
|
|
1890
1912
|
|
|
1891
1913
|
# Calculate total package depth, the sum of the lengths (or rather
|
|
1892
1914
|
# the max array index) of each array of packages.
|
|
1893
1915
|
coretotaldepth = corepkgs.inject(0) {|memo, pkgs| memo + pkgs[1].length - 1}
|
|
1894
|
-
noncoretotaldepth = noncorepkgs.inject(0) {|memo, pkgs| memo + pkgs[1].length - 1}
|
|
1916
|
+
noncoretotaldepth = noncorepkgs[:tpkg].inject(0) {|memo, pkgs| memo + pkgs[1].length - 1} +
|
|
1917
|
+
noncorepkgs[:native].inject(0) {|memo, pkgs| memo + pkgs[1].length - 1}
|
|
1895
1918
|
if @@debug
|
|
1896
1919
|
puts "resolvedeps coretotaldepth #{coretotaldepth}"
|
|
1897
1920
|
puts "resolvedeps noncoretotaldepth #{noncoretotaldepth}"
|
|
@@ -1935,7 +1958,7 @@ class Tpkg
|
|
|
1935
1958
|
# {:pkgs=>{a1,b0}, :remaining_coredepth=0}
|
|
1936
1959
|
if coresol[:remaining_coredepth] == 0
|
|
1937
1960
|
# Second pass, add combinations of non-core packages
|
|
1938
|
-
if noncorepkgs.empty?
|
|
1961
|
+
if noncorepkgs[:tpkg].empty? && noncorepkgs[:native].empty?
|
|
1939
1962
|
puts "resolvedeps noncorepkgs empty, checking solution" if @@debug
|
|
1940
1963
|
result = check_solution(coresol, requirements, packages, core_packages, number_of_possible_solutions_checked)
|
|
1941
1964
|
if result[:solution]
|
|
@@ -1948,45 +1971,47 @@ class Tpkg
|
|
|
1948
1971
|
puts "resolvedeps noncoredepth: #{noncoredepth}" if @@debug
|
|
1949
1972
|
coresol[:remaining_noncoredepth] = noncoredepth
|
|
1950
1973
|
solutions = [coresol]
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1974
|
+
[:tpkg, :native].each do |nctype|
|
|
1975
|
+
noncorepkgs[nctype].each do |ncpkgname, ncpkgs|
|
|
1976
|
+
puts "resolvedeps noncorepkg #{nctype} #{ncpkgname}: #{ncpkgs.inspect}" if @@debug
|
|
1977
|
+
new_solutions = []
|
|
1978
|
+
solutions.each do |solution|
|
|
1979
|
+
remaining_noncoredepth = solution[:remaining_noncoredepth]
|
|
1980
|
+
puts "resolvedeps :remaining_noncoredepth: #{remaining_noncoredepth}" if @@debug
|
|
1981
|
+
(0..[remaining_noncoredepth, ncpkgs.length-1].min).each do |ncpkgdepth|
|
|
1982
|
+
puts "resolvedeps ncpkgdepth: #{ncpkgdepth}" if @@debug
|
|
1983
|
+
# We insert a nil entry in some situations (see the sort
|
|
1984
|
+
# step earlier), so skip nil entries in the pkgs array.
|
|
1985
|
+
if ncpkgs[ncpkgdepth] != nil
|
|
1986
|
+
sol = solution.dup
|
|
1987
|
+
# Hash#dup doesn't dup each key/value, so we need to
|
|
1988
|
+
# explicitly dup :pkgs so that each copy has an
|
|
1989
|
+
# independent array that we can modify.
|
|
1990
|
+
sol[:pkgs] = solution[:pkgs].dup
|
|
1991
|
+
sol[:remaining_noncoredepth] -= ncpkgdepth
|
|
1992
|
+
sol[:pkgs] << ncpkgs[ncpkgdepth]
|
|
1993
|
+
new_solutions << sol
|
|
1994
|
+
# If this is a complete combination of packages then
|
|
1995
|
+
# proceed to the next step
|
|
1996
|
+
puts "resolvedeps sol[:pkgs] #{sol[:pkgs].inspect}" if @@debug
|
|
1997
|
+
if sol[:pkgs].length == packages[:tpkg].length + packages[:native].length
|
|
1998
|
+
puts "resolvedeps complete pkg set: #{sol.inspect}" if @@debug
|
|
1999
|
+
# Solutions with remaining depth are duplicates of
|
|
2000
|
+
# solutions we already checked at lower depth levels
|
|
2001
|
+
if sol[:remaining_noncoredepth] == 0
|
|
2002
|
+
result = check_solution(sol, requirements, packages, core_packages, number_of_possible_solutions_checked)
|
|
2003
|
+
if result[:solution]
|
|
2004
|
+
return result
|
|
2005
|
+
else
|
|
2006
|
+
number_of_possible_solutions_checked = result[:number_of_possible_solutions_checked]
|
|
2007
|
+
end
|
|
1983
2008
|
end
|
|
1984
2009
|
end
|
|
1985
2010
|
end
|
|
1986
2011
|
end
|
|
1987
2012
|
end
|
|
2013
|
+
solutions = new_solutions
|
|
1988
2014
|
end
|
|
1989
|
-
solutions = new_solutions
|
|
1990
2015
|
end
|
|
1991
2016
|
end
|
|
1992
2017
|
end
|
|
@@ -2036,7 +2061,7 @@ class Tpkg
|
|
|
2036
2061
|
newreqs_that_need_packages = []
|
|
2037
2062
|
newreqs.each do |newreq|
|
|
2038
2063
|
puts "checksol checking newreq: #{newreq.inspect}" if @@debug
|
|
2039
|
-
if packages[newreq[:name]]
|
|
2064
|
+
if packages[newreq[:type]][newreq[:name]]
|
|
2040
2065
|
pkg = solution[:pkgs].find{|solpkg| solpkg[:metadata][:name] == newreq[:name]}
|
|
2041
2066
|
puts "checksol newreq pkg: #{pkg.inspect}" if @@debug
|
|
2042
2067
|
if Tpkg::package_meets_requirement?(pkg, newreq)
|
|
@@ -2171,7 +2196,13 @@ class Tpkg
|
|
|
2171
2196
|
Tpkg::get_os =~ /Solaris/
|
|
2172
2197
|
init_directory = File.join(@file_system_root, 'etc')
|
|
2173
2198
|
end
|
|
2174
|
-
|
|
2199
|
+
|
|
2200
|
+
# in case user specify levels in yaml as string/integer instead of array
|
|
2201
|
+
if !levels.kind_of?(Array)
|
|
2202
|
+
levels = levels.to_s.split(//)
|
|
2203
|
+
end
|
|
2204
|
+
|
|
2205
|
+
levels.each do |level|
|
|
2175
2206
|
links[File.join(init_directory, "rc#{level}.d", 'S' + start.to_s + File.basename(installed_path))] = installed_path
|
|
2176
2207
|
end
|
|
2177
2208
|
elsif Tpkg::get_os =~ /FreeBSD/
|
|
@@ -2260,12 +2291,22 @@ class Tpkg
|
|
|
2260
2291
|
end
|
|
2261
2292
|
case operation
|
|
2262
2293
|
when :install
|
|
2263
|
-
|
|
2264
|
-
|
|
2294
|
+
begin
|
|
2295
|
+
IO.popen("#{externalpath} '#{pkgfile}' install", 'w') do |pipe|
|
|
2296
|
+
pipe.write(data)
|
|
2297
|
+
end
|
|
2298
|
+
rescue => e
|
|
2299
|
+
# Tell the user which external and package were involved, otherwise
|
|
2300
|
+
# failures in externals are very hard to debug
|
|
2301
|
+
raise e.exception("External #{name} #{operation} for #{File.basename(pkgfile)}: " + e.message)
|
|
2265
2302
|
end
|
|
2266
2303
|
when :remove
|
|
2267
|
-
|
|
2268
|
-
|
|
2304
|
+
begin
|
|
2305
|
+
IO.popen("#{externalpath} '#{pkgfile}' remove", 'w') do |pipe|
|
|
2306
|
+
pipe.write(data)
|
|
2307
|
+
end
|
|
2308
|
+
rescue => e
|
|
2309
|
+
raise e.exception("External #{name} #{operation} for #{File.basename(pkgfile)}: " + e.message)
|
|
2269
2310
|
end
|
|
2270
2311
|
else
|
|
2271
2312
|
raise "Bug, unknown external operation #{operation}"
|
|
@@ -2718,7 +2759,7 @@ class Tpkg
|
|
|
2718
2759
|
end
|
|
2719
2760
|
|
|
2720
2761
|
file = File.open(File.join(package_metadata_dir, "file_metadata.bin"), "w")
|
|
2721
|
-
Marshal.dump(file_metadata.
|
|
2762
|
+
Marshal.dump(file_metadata.to_hash, file)
|
|
2722
2763
|
file.close
|
|
2723
2764
|
else
|
|
2724
2765
|
warn "Warning: package #{File.basename(package_file)} does not include file_metadata information."
|
|
@@ -2737,7 +2778,8 @@ class Tpkg
|
|
|
2737
2778
|
metadata_for_installed_packages.each do |metadata|
|
|
2738
2779
|
if !pkgname || pkgname == metadata[:name]
|
|
2739
2780
|
req = { :name => metadata[:name],
|
|
2740
|
-
:minimum_version => metadata[:version]
|
|
2781
|
+
:minimum_version => metadata[:version],
|
|
2782
|
+
:type => :tpkg }
|
|
2741
2783
|
if metadata[:package_version]
|
|
2742
2784
|
req[:minimum_package_version] = metadata[:package_version]
|
|
2743
2785
|
end
|
|
@@ -2756,7 +2798,7 @@ class Tpkg
|
|
|
2756
2798
|
version = installed_xml[:version]
|
|
2757
2799
|
# For each currently installed package we insert a requirement for
|
|
2758
2800
|
# at least that version of the package
|
|
2759
|
-
req = { :name => name, :minimum_version => version }
|
|
2801
|
+
req = { :name => name, :minimum_version => version, :type => :tpkg }
|
|
2760
2802
|
requirements << req
|
|
2761
2803
|
# Initialize the list of possible packages for this req
|
|
2762
2804
|
if !packages[name]
|
|
@@ -2782,6 +2824,7 @@ class Tpkg
|
|
|
2782
2824
|
|
|
2783
2825
|
requests.each do |request|
|
|
2784
2826
|
puts "parse_requests processing #{request.inspect}" if @@debug
|
|
2827
|
+
|
|
2785
2828
|
if request =~ /^[-\w=<>\d\.]+$/ && !File.file?(request) # basic package specs ('foo' or 'foo=1.0')
|
|
2786
2829
|
puts "parse_requests request looks like package spec" if @@debug
|
|
2787
2830
|
|
|
@@ -2816,6 +2859,7 @@ class Tpkg
|
|
|
2816
2859
|
FileUtils.rm_rf(localpath)
|
|
2817
2860
|
end
|
|
2818
2861
|
req[:name] = metadata[:name]
|
|
2862
|
+
req[:type] = :tpkg
|
|
2819
2863
|
pkg = { :metadata => metadata, :source => source }
|
|
2820
2864
|
|
|
2821
2865
|
newreqs << req
|
|
@@ -2824,7 +2868,7 @@ class Tpkg
|
|
|
2824
2868
|
packages[req[:name]] = [pkg]
|
|
2825
2869
|
end
|
|
2826
2870
|
end
|
|
2827
|
-
|
|
2871
|
+
|
|
2828
2872
|
requirements.concat(newreqs)
|
|
2829
2873
|
newreqs
|
|
2830
2874
|
end
|
|
@@ -2845,23 +2889,24 @@ class Tpkg
|
|
|
2845
2889
|
request_satisfied = false # whether or not this request can be satisfied
|
|
2846
2890
|
possible_errors = []
|
|
2847
2891
|
pkgs.each do |pkg|
|
|
2892
|
+
good_package = true
|
|
2848
2893
|
metadata = pkg[:metadata]
|
|
2849
|
-
req = { :name => metadata[:name] }
|
|
2894
|
+
req = { :name => metadata[:name], :type => :tpkg }
|
|
2850
2895
|
# Quick sanity check that the package can be installed on this machine.
|
|
2851
2896
|
if !Tpkg::package_meets_requirement?(pkg, req)
|
|
2852
2897
|
possible_errors << " Requested package #{metadata[:filename]} doesn't match this machine's OS or architecture"
|
|
2898
|
+
good_package = false
|
|
2853
2899
|
next
|
|
2854
2900
|
end
|
|
2855
2901
|
# a sanity check that there is at least one package
|
|
2856
2902
|
# available for each dependency of this package
|
|
2857
|
-
dep_satisfied = true
|
|
2858
2903
|
metadata[:dependencies].each do |depreq|
|
|
2859
2904
|
if available_packages_that_meet_requirement(depreq).empty? && !Tpkg::packages_meet_requirement?(packages.values.flatten, depreq)
|
|
2860
2905
|
possible_errors << " Requested package #{metadata[:filename]} depends on #{depreq.inspect}, no packages that satisfy that dependency are available"
|
|
2861
|
-
|
|
2906
|
+
good_package = false
|
|
2862
2907
|
end
|
|
2863
2908
|
end if metadata[:dependencies]
|
|
2864
|
-
request_satisfied = true if
|
|
2909
|
+
request_satisfied = true if good_package
|
|
2865
2910
|
end
|
|
2866
2911
|
if !request_satisfied
|
|
2867
2912
|
errors << ["Unable to find any packages which satisfy #{name}. Possible error(s):"]
|
|
@@ -2987,7 +3032,11 @@ class Tpkg
|
|
|
2987
3032
|
name = pkg[:metadata][:name]
|
|
2988
3033
|
version = pkg[:metadata][:version]
|
|
2989
3034
|
package_version = pkg[:metadata][:package_version]
|
|
2990
|
-
|
|
3035
|
+
pkgname = "#{name}-#{version}"
|
|
3036
|
+
if package_version
|
|
3037
|
+
pkgname << "-#{package_version}"
|
|
3038
|
+
end
|
|
3039
|
+
puts "Native #{pkgname}"
|
|
2991
3040
|
else
|
|
2992
3041
|
puts pkg[:metadata][:filename]
|
|
2993
3042
|
end
|
|
@@ -3008,13 +3057,20 @@ class Tpkg
|
|
|
3008
3057
|
parse_requests(requests, requirements, packages)
|
|
3009
3058
|
check_requests(packages)
|
|
3010
3059
|
core_packages = []
|
|
3011
|
-
currently_installed_requirements = []
|
|
3060
|
+
#currently_installed_requirements = []
|
|
3012
3061
|
requirements.each do |req|
|
|
3013
3062
|
core_packages << req[:name] if !core_packages.include?(req[:name])
|
|
3014
|
-
|
|
3015
|
-
|
|
3063
|
+
|
|
3064
|
+
# This was here to ensure that nothing went backwards. But I guess in the
|
|
3065
|
+
# install case (as opposed to upgrade) going backwards can't really happen,
|
|
3066
|
+
# we may just install an older version alongside a newer version, which is
|
|
3067
|
+
# perfectly fine.
|
|
3068
|
+
# currently_installed_requirements.concat(
|
|
3069
|
+
# requirements_for_currently_installed_package(req[:name]))
|
|
3016
3070
|
end
|
|
3017
|
-
requirements.concat(currently_installed_requirements).uniq!
|
|
3071
|
+
#requirements.concat(currently_installed_requirements).uniq!
|
|
3072
|
+
|
|
3073
|
+
|
|
3018
3074
|
|
|
3019
3075
|
puts "install calling best_solution" if @@debug
|
|
3020
3076
|
puts "install requirements: #{requirements.inspect}" if @@debug
|
|
@@ -3192,7 +3248,11 @@ class Tpkg
|
|
|
3192
3248
|
metadata_for_installed_packages.each do | metadata |
|
|
3193
3249
|
metadata[:dependencies].each do | dep |
|
|
3194
3250
|
if dep[:name] == req[:name]
|
|
3195
|
-
|
|
3251
|
+
# Package metadata is almost usable as-is as a req, just need to
|
|
3252
|
+
# set :type
|
|
3253
|
+
addreq = metadata.to_hash
|
|
3254
|
+
addreq[:type] = :tpkg
|
|
3255
|
+
additional_requirements << addreq
|
|
3196
3256
|
end
|
|
3197
3257
|
end if metadata[:dependencies]
|
|
3198
3258
|
end
|
|
@@ -3330,10 +3390,10 @@ class Tpkg
|
|
|
3330
3390
|
# If the old and new packages have overlapping externals flag them
|
|
3331
3391
|
# to be skipped so that the external isn't removed and then
|
|
3332
3392
|
# immediately re-added
|
|
3333
|
-
oldpkgs = installed_packages_that_meet_requirement({:name => pkg[:metadata][:name]})
|
|
3393
|
+
oldpkgs = installed_packages_that_meet_requirement({:name => pkg[:metadata][:name], :type => :tpkg})
|
|
3334
3394
|
externals_to_skip = []
|
|
3335
3395
|
pkg[:metadata][:externals].each do |external|
|
|
3336
|
-
if oldpkgs.all? {|oldpkg| oldpkg[:metadata][:externals].include?(external)}
|
|
3396
|
+
if oldpkgs.all? {|oldpkg| oldpkg[:metadata][:externals] && oldpkg[:metadata][:externals].include?(external)}
|
|
3337
3397
|
externals_to_skip << external
|
|
3338
3398
|
end
|
|
3339
3399
|
end if pkg[:metadata][:externals]
|
|
@@ -3416,7 +3476,7 @@ class Tpkg
|
|
|
3416
3476
|
# We ignore native dependencies because there is no way a removal
|
|
3417
3477
|
# can break a native dependency, we don't support removing native
|
|
3418
3478
|
# packages.
|
|
3419
|
-
if req[:type] != :native
|
|
3479
|
+
if req[:type] != :native
|
|
3420
3480
|
iptmr = installed_packages_that_meet_requirement(req)
|
|
3421
3481
|
if iptmr.all? { |pkg| pkg_files_to_remove.include?(pkg[:metadata][:filename]) }
|
|
3422
3482
|
non_removable_pkg_files |= iptmr.map{ |pkg| pkg[:metadata][:filename]}
|
|
@@ -3768,32 +3828,43 @@ class Tpkg
|
|
|
3768
3828
|
end
|
|
3769
3829
|
return results
|
|
3770
3830
|
end
|
|
3771
|
-
|
|
3772
|
-
def execute_init(
|
|
3831
|
+
|
|
3832
|
+
def execute_init(options, *moreoptions)
|
|
3773
3833
|
ret_val = 0
|
|
3774
3834
|
packages_to_execute_on = []
|
|
3775
|
-
if
|
|
3835
|
+
if options.is_a?(Hash)
|
|
3836
|
+
action = options[:cmd]
|
|
3837
|
+
requested_packages = options[:packages]
|
|
3838
|
+
requested_init_scripts = options[:scripts]
|
|
3839
|
+
else # for backward compatibility
|
|
3840
|
+
action = moreoptions[0]
|
|
3841
|
+
requested_packages = options
|
|
3842
|
+
end
|
|
3843
|
+
|
|
3844
|
+
# if user specified no packages, then assume all
|
|
3845
|
+
if requested_packages.nil?
|
|
3776
3846
|
packages_to_execute_on = installed_packages_that_meet_requirement(nil)
|
|
3777
3847
|
else
|
|
3778
|
-
|
|
3848
|
+
requested_packages.each do |request|
|
|
3779
3849
|
req = Tpkg::parse_request(request)
|
|
3780
3850
|
packages_to_execute_on.concat(installed_packages_that_meet_requirement(req))
|
|
3781
3851
|
end
|
|
3782
3852
|
end
|
|
3783
3853
|
|
|
3784
3854
|
packages_to_execute_on.each do |pkg|
|
|
3785
|
-
ret_val |= execute_init_for_package(pkg, action)
|
|
3855
|
+
ret_val |= execute_init_for_package(pkg, action, requested_init_scripts)
|
|
3786
3856
|
end
|
|
3787
3857
|
return ret_val
|
|
3788
3858
|
end
|
|
3789
|
-
|
|
3790
|
-
def execute_init_for_package(pkg, action)
|
|
3859
|
+
|
|
3860
|
+
def execute_init_for_package(pkg, action, requested_init_scripts = nil)
|
|
3791
3861
|
ret_val = 0
|
|
3792
|
-
init_scripts_metadata = init_scripts(pkg[:metadata])
|
|
3793
3862
|
|
|
3863
|
+
# Get init scripts metadata for the given package
|
|
3864
|
+
init_scripts_metadata = init_scripts(pkg[:metadata])
|
|
3794
3865
|
# warn if there's no init script and then return
|
|
3795
3866
|
if init_scripts_metadata.nil? || init_scripts_metadata.empty?
|
|
3796
|
-
warn "Warning: There is no init script for #{pkg[:metadata][:name]}"
|
|
3867
|
+
warn "Warning: There is no init script for #{pkg[:metadata][:name]}."
|
|
3797
3868
|
return 1
|
|
3798
3869
|
end
|
|
3799
3870
|
|
|
@@ -3805,9 +3876,18 @@ class Tpkg
|
|
|
3805
3876
|
init = {}
|
|
3806
3877
|
init[:path] = installed_path
|
|
3807
3878
|
init[:start] = init_info[:init][:start] || 0
|
|
3808
|
-
|
|
3879
|
+
|
|
3880
|
+
# if user requests specific init scripts, then only include those
|
|
3881
|
+
if requested_init_scripts.nil? or
|
|
3882
|
+
requested_init_scripts && requested_init_scripts.include?(File.basename(installed_path))
|
|
3883
|
+
init_scripts << init
|
|
3884
|
+
end
|
|
3809
3885
|
end
|
|
3810
3886
|
|
|
3887
|
+
if requested_init_scripts && init_scripts.empty?
|
|
3888
|
+
warn "Warning: There are no init scripts that satisfy your request: #{requested_init_scripts.inspect} for package #{pkg[:metadata][:name]}."
|
|
3889
|
+
end
|
|
3890
|
+
|
|
3811
3891
|
# Reverse order if doing stop.
|
|
3812
3892
|
if action == "stop"
|
|
3813
3893
|
ordered_init_scripts = init_scripts.sort{ |a,b| b[:start] <=> a[:start] }
|
|
@@ -3880,7 +3960,7 @@ class Tpkg
|
|
|
3880
3960
|
|
|
3881
3961
|
# TODO: update server side to accept yaml data
|
|
3882
3962
|
def send_update_to_server
|
|
3883
|
-
metadata = metadata_for_installed_packages.collect{|metadata| metadata.
|
|
3963
|
+
metadata = metadata_for_installed_packages.collect{|metadata| metadata.to_hash}
|
|
3884
3964
|
yml = YAML.dump(metadata)
|
|
3885
3965
|
begin
|
|
3886
3966
|
update_uri = URI.parse("#{@report_server}")
|
data/lib/tpkg/metadata.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'yaml'
|
|
2
|
+
require 'rexml/document'
|
|
2
3
|
|
|
3
4
|
module SymbolizeKeys
|
|
4
5
|
|
|
@@ -86,14 +87,14 @@ class Metadata
|
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
def [](key)
|
|
89
|
-
return
|
|
90
|
+
return to_hash[key]
|
|
90
91
|
end
|
|
91
92
|
|
|
92
93
|
def []=(key,value)
|
|
93
|
-
|
|
94
|
+
to_hash[key]=value
|
|
94
95
|
end
|
|
95
96
|
|
|
96
|
-
def
|
|
97
|
+
def to_hash
|
|
97
98
|
if @hash
|
|
98
99
|
return @hash
|
|
99
100
|
end
|
|
@@ -101,6 +102,18 @@ class Metadata
|
|
|
101
102
|
if @format == 'yml'
|
|
102
103
|
hash = YAML::load(@metadata_text)
|
|
103
104
|
@hash = hash.extend(SymbolizeKeys)
|
|
105
|
+
|
|
106
|
+
# We need this for backward compatibility. With xml, we specify
|
|
107
|
+
# native dependency as type: :native rather then native: true
|
|
108
|
+
@hash[:dependencies].each do | dep |
|
|
109
|
+
if !dep[:type]
|
|
110
|
+
if dep[:native]
|
|
111
|
+
dep[:type] = :native
|
|
112
|
+
else
|
|
113
|
+
dep[:type] = :tpkg
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end if @hash[:dependencies]
|
|
104
117
|
else
|
|
105
118
|
@hash = metadata_xml_to_hash
|
|
106
119
|
end
|
|
@@ -108,18 +121,18 @@ class Metadata
|
|
|
108
121
|
end
|
|
109
122
|
|
|
110
123
|
def write(file)
|
|
111
|
-
YAML::dump(
|
|
124
|
+
YAML::dump(to_hash, file)
|
|
112
125
|
end
|
|
113
126
|
|
|
114
127
|
def get_files_list
|
|
115
128
|
end
|
|
116
129
|
|
|
117
130
|
def generate_package_filename
|
|
118
|
-
name =
|
|
119
|
-
version =
|
|
131
|
+
name = to_hash[:name]
|
|
132
|
+
version = to_hash[:version]
|
|
120
133
|
packageversion = nil
|
|
121
|
-
if
|
|
122
|
-
packageversion =
|
|
134
|
+
if to_hash[:package_version] && !to_hash[:package_version].to_s.empty?
|
|
135
|
+
packageversion = to_hash[:package_version]
|
|
123
136
|
end
|
|
124
137
|
package_filename = "#{name}-#{version}"
|
|
125
138
|
if packageversion
|
|
@@ -127,11 +140,11 @@ class Metadata
|
|
|
127
140
|
end
|
|
128
141
|
|
|
129
142
|
|
|
130
|
-
if
|
|
131
|
-
if
|
|
132
|
-
package_filename << "-#{Metadata::clean_for_filename(
|
|
143
|
+
if to_hash[:operatingsystem] and !to_hash[:operatingsystem].empty?
|
|
144
|
+
if to_hash[:operatingsystem].length == 1
|
|
145
|
+
package_filename << "-#{Metadata::clean_for_filename(to_hash[:operatingsystem].first)}"
|
|
133
146
|
else
|
|
134
|
-
operatingsystems =
|
|
147
|
+
operatingsystems = to_hash[:operatingsystem].dup
|
|
135
148
|
# Genericize any equivalent operating systems
|
|
136
149
|
# FIXME: more generic handling of equivalent OSs is probably called for
|
|
137
150
|
operatingsystems.each do |os|
|
|
@@ -154,9 +167,9 @@ class Metadata
|
|
|
154
167
|
end
|
|
155
168
|
end
|
|
156
169
|
end
|
|
157
|
-
if
|
|
158
|
-
if
|
|
159
|
-
package_filename << "-#{Metadata::clean_for_filename(
|
|
170
|
+
if to_hash[:architecture] and !to_hash[:architecture].empty?
|
|
171
|
+
if to_hash[:architecture].length == 1
|
|
172
|
+
package_filename << "-#{Metadata::clean_for_filename(to_hash[:architecture].first)}"
|
|
160
173
|
else
|
|
161
174
|
package_filename << "-multiarch"
|
|
162
175
|
end
|
|
@@ -167,16 +180,16 @@ class Metadata
|
|
|
167
180
|
|
|
168
181
|
def verify_required_fields
|
|
169
182
|
REQUIRED_FIELDS.each do |reqfield|
|
|
170
|
-
if
|
|
183
|
+
if to_hash[reqfield].nil?
|
|
171
184
|
raise "Required field #{reqfield} not found"
|
|
172
|
-
elsif
|
|
185
|
+
elsif to_hash[reqfield].to_s.empty?
|
|
173
186
|
raise "Required field #{reqfield} is empty"
|
|
174
187
|
end
|
|
175
188
|
end
|
|
176
189
|
end
|
|
177
190
|
|
|
178
191
|
def metadata_xml_to_hash
|
|
179
|
-
# Don't do anything if metadata is from xml file
|
|
192
|
+
# Don't do anything if metadata is not from xml file
|
|
180
193
|
return if @format != "xml"
|
|
181
194
|
|
|
182
195
|
metadata_hash = {}
|
|
@@ -230,6 +243,8 @@ class Metadata
|
|
|
230
243
|
end
|
|
231
244
|
if depxml.elements['native']
|
|
232
245
|
dep[:type] = :native
|
|
246
|
+
else
|
|
247
|
+
dep[:type] = :tpkg
|
|
233
248
|
end
|
|
234
249
|
deps << dep
|
|
235
250
|
end
|
|
@@ -247,6 +262,8 @@ class Metadata
|
|
|
247
262
|
end
|
|
248
263
|
if conflictxml.elements['native']
|
|
249
264
|
conflict[:type] = :native
|
|
265
|
+
else
|
|
266
|
+
conflict[:type] = :tpkg
|
|
250
267
|
end
|
|
251
268
|
conflicts << conflict
|
|
252
269
|
end
|
|
@@ -387,13 +404,13 @@ class Metadata
|
|
|
387
404
|
end
|
|
388
405
|
|
|
389
406
|
class FileMetadata < Metadata
|
|
390
|
-
def
|
|
407
|
+
def to_hash
|
|
391
408
|
if @hash
|
|
392
409
|
return @hash
|
|
393
410
|
end
|
|
394
411
|
|
|
395
412
|
if @format == 'bin'
|
|
396
|
-
|
|
413
|
+
hash = Marshal::load(@metadata_text)
|
|
397
414
|
@hash = hash.extend(SymbolizeKeys)
|
|
398
415
|
elsif @format == 'yml'
|
|
399
416
|
hash = YAML::load(@metadata_text)
|
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.18.2
|
|
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:
|
|
13
|
+
date: 2010-01-28 00:00:00 -08:00
|
|
14
14
|
default_executable:
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
@@ -39,18 +39,20 @@ executables:
|
|
|
39
39
|
- tpkg
|
|
40
40
|
- cpan2tpkg
|
|
41
41
|
- gem2tpkg
|
|
42
|
+
- tpkg_xml_to_yml
|
|
42
43
|
extensions: []
|
|
43
44
|
|
|
44
45
|
extra_rdoc_files: []
|
|
45
46
|
|
|
46
47
|
files:
|
|
47
48
|
- bin/cpan2tpkg
|
|
48
|
-
- bin/
|
|
49
|
+
- bin/tpkg_xml_to_yml
|
|
49
50
|
- bin/tpkg
|
|
51
|
+
- bin/gem2tpkg
|
|
52
|
+
- lib/tpkg/versiontype.rb
|
|
50
53
|
- lib/tpkg/deployer.rb
|
|
51
|
-
- lib/tpkg/metadata.rb
|
|
52
54
|
- lib/tpkg/thread_pool.rb
|
|
53
|
-
- lib/tpkg/
|
|
55
|
+
- lib/tpkg/metadata.rb
|
|
54
56
|
- lib/tpkg.rb
|
|
55
57
|
- Rakefile
|
|
56
58
|
has_rdoc: true
|