enhancerepo 0.4.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/CHANGELOG.rdoc +18 -0
- data/Manifest.txt +85 -0
- data/README +10 -0
- data/README.rdoc +15 -0
- data/Rakefile +48 -0
- data/TODO.rdoc +4 -0
- data/bin/enhancerepo +4 -0
- data/lib/enhance_repo.rb +36 -0
- data/lib/enhance_repo/cli.rb +150 -0
- data/lib/enhance_repo/config_opts.rb +98 -0
- data/lib/enhance_repo/logger.rb +67 -0
- data/lib/enhance_repo/other.rb +80 -0
- data/lib/enhance_repo/package_id.rb +81 -0
- data/lib/enhance_repo/product_id.rb +30 -0
- data/lib/enhance_repo/rpm_md.rb +27 -0
- data/lib/enhance_repo/rpm_md/data.rb +55 -0
- data/lib/enhance_repo/rpm_md/delta_info.rb +205 -0
- data/lib/enhance_repo/rpm_md/extra_primary_data.rb +45 -0
- data/lib/enhance_repo/rpm_md/file_lists.rb +81 -0
- data/lib/enhance_repo/rpm_md/index.rb +144 -0
- data/lib/enhance_repo/rpm_md/other.rb +69 -0
- data/lib/enhance_repo/rpm_md/primary.rb +123 -0
- data/lib/enhance_repo/rpm_md/products.rb +142 -0
- data/lib/enhance_repo/rpm_md/repo.rb +202 -0
- data/lib/enhance_repo/rpm_md/resource.rb +44 -0
- data/lib/enhance_repo/rpm_md/suse_data.rb +191 -0
- data/lib/enhance_repo/rpm_md/suse_info.rb +88 -0
- data/lib/enhance_repo/rpm_md/update.rb +141 -0
- data/lib/enhance_repo/rpm_md/update_info.rb +244 -0
- data/lib/enhance_repo/rpm_md/update_smart_fields.rb +127 -0
- data/lib/enhance_repo/xml_comparer.rb +117 -0
- data/lib/tempdir.rb +62 -0
- data/lib/tempdir/tempfile.rb +21 -0
- data/test/all_tests.rb +27 -0
- data/test/data/packages/a-1.0.spec +19 -0
- data/test/data/packages/a-2.0.spec +24 -0
- data/test/data/repodata/update-test-11.1/filelists.xml.gz +0 -0
- data/test/data/repodata/update-test-11.1/other.xml.gz +0 -0
- data/test/data/repodata/update-test-11.1/primary.xml.gz +0 -0
- data/test/data/repodata/update-test-11.1/repomd.xml +21 -0
- data/test/data/repomd.xml +21 -0
- data/test/data/rpms/repo-1/a-1.0-0.x86_64.rpm +0 -0
- data/test/data/rpms/repo-1/a-1.0_2.0-0_0.x86_64.delta.rpm +0 -0
- data/test/data/rpms/repo-1/a-2.0-0.x86_64.rpm +0 -0
- data/test/data/rpms/repo-1/repodata/deltainfo.xml.gz +0 -0
- data/test/data/rpms/repo-1/repodata/deltainfo.xml.gz.gz +0 -0
- data/test/data/rpms/repo-1/repodata/filelists.xml.gz +0 -0
- data/test/data/rpms/repo-1/repodata/other.xml.gz +0 -0
- data/test/data/rpms/repo-1/repodata/primary.xml.gz +0 -0
- data/test/data/rpms/repo-1/repodata/repomd.xml +45 -0
- data/test/data/rpms/repo-1/repodata/susedata.xml.gz +0 -0
- data/test/data/rpms/repo-1/repodata/updateinfo.xml.gz +0 -0
- data/test/data/rpms/repo-1/repoparts/update-a-1.xml +22 -0
- data/test/data/rpms/repo-with-product/a-1.0-0.x86_64.rpm +0 -0
- data/test/data/rpms/repo-with-product/openSUSE-release-11.2-1.6.i586.rpm +0 -0
- data/test/data/rpms/repo-with-product/openSUSE-release-dvd-11.2-1.6.i586.rpm +0 -0
- data/test/data/rpms/repo-with-product/repodata/filelists.xml.gz +0 -0
- data/test/data/rpms/repo-with-product/repodata/other.xml.gz +0 -0
- data/test/data/rpms/repo-with-product/repodata/primary.xml.gz +0 -0
- data/test/data/rpms/repo-with-product/repodata/products.xml.gz +0 -0
- data/test/data/rpms/repo-with-product/repodata/repomd.xml +27 -0
- data/test/data/rpms/update-test-11.1/update-test-affects-package-manager.rpm +0 -0
- data/test/data/rpms/update-test-11.1/update-test-interactive.rpm +0 -0
- data/test/data/rpms/update-test-11.1/update-test-optional.rpm +0 -0
- data/test/data/rpms/update-test-11.1/update-test-reboot-needed.rpm +0 -0
- data/test/data/rpms/update-test-11.1/update-test-security.rpm +0 -0
- data/test/data/rpms/update-test-11.1/update-test-trival.rpm +0 -0
- data/test/data/rpms/update-test-factory/update-test-affects-package-manager-0-9999.1.2.noarch.rpm +0 -0
- data/test/data/rpms/update-test-factory/update-test-interactive-0-9999.1.2.noarch.rpm +0 -0
- data/test/data/rpms/update-test-factory/update-test-optional-0-9999.1.2.noarch.rpm +0 -0
- data/test/data/rpms/update-test-factory/update-test-reboot-needed-0-9999.1.2.noarch.rpm +0 -0
- data/test/data/rpms/update-test-factory/update-test-relogin-suggested-0-9999.1.2.noarch.rpm +0 -0
- data/test/data/rpms/update-test-factory/update-test-security-0-9999.1.2.noarch.rpm +0 -0
- data/test/deltainfo_test.rb +50 -0
- data/test/extensions_test.rb +31 -0
- data/test/index_test.rb +51 -0
- data/test/primary_test.rb +51 -0
- data/test/products_test.rb +51 -0
- data/test/repo_test.rb +72 -0
- data/test/repomdindex_test.rb +58 -0
- data/test/rpmmd_test.rb +60 -0
- data/test/susedata_test.rb +53 -0
- data/test/tempdir_test.rb +62 -0
- data/test/test_helper.rb +53 -0
- data/test/update_test.rb +80 -0
- data/test/updateinfo_test.rb +59 -0
- metadata +267 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
module EnhanceRepo
|
|
27
|
+
|
|
28
|
+
def self.enable_logger
|
|
29
|
+
# support both log4r and ruby logger
|
|
30
|
+
begin
|
|
31
|
+
require 'log4r'
|
|
32
|
+
include Log4r
|
|
33
|
+
@logger = Log4r::Logger.new 'enhancerepo'
|
|
34
|
+
console_format = Log4r::PatternFormatter.new(:pattern => "%l:\t %m")
|
|
35
|
+
@logger.add Log4r::StdoutOutputter.new('console', :formatter=>console_format)
|
|
36
|
+
rescue LoadError
|
|
37
|
+
require 'logger'
|
|
38
|
+
@logger = ::Logger.new(STDERR)
|
|
39
|
+
end
|
|
40
|
+
EnhanceRepo.logger.level = using_log4r? ? Log4r::INFO : ::Logger::INFO
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.using_log4r?
|
|
44
|
+
(! (Object.const_get(:Log4r) rescue nil).nil?)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.enable_debug
|
|
48
|
+
EnhanceRepo.logger.level = using_log4r? ? Log4r::DEBUG : ::Logger::DEBUG
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.logger
|
|
52
|
+
@logger
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.logger=(logger)
|
|
56
|
+
@logger = logger
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# provide easy access to classes to the
|
|
60
|
+
# global logger
|
|
61
|
+
module Logger
|
|
62
|
+
def log
|
|
63
|
+
EnhanceRepo.logger
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
module EnhanceRepo
|
|
26
|
+
# represents
|
|
27
|
+
# filelist data
|
|
28
|
+
#
|
|
29
|
+
# See:
|
|
30
|
+
# http://en.opensuse.org/Standards/Rpm_Metadata
|
|
31
|
+
#
|
|
32
|
+
class Other
|
|
33
|
+
|
|
34
|
+
def initialize(dir)
|
|
35
|
+
@dir = dir
|
|
36
|
+
@rpmfiles = []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def read
|
|
40
|
+
Dir["#{@dir}/**/*.rpm"].each do |rpmfile|
|
|
41
|
+
@rpmfiles << rpmfile
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def empty?
|
|
46
|
+
@rpmfiles.empty?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def write_package(file, rpmfile)
|
|
50
|
+
b = Builder::XmlMarkup.new(:target=>file, :indent=>2, :initial=>2)
|
|
51
|
+
pkgid = PackageId.new(rpmfile)
|
|
52
|
+
puts pkgid.rpm.methods.sort
|
|
53
|
+
pkgid[RPM::TAG_CHANGELOGTEXT].each do |ch|
|
|
54
|
+
puts ch
|
|
55
|
+
end
|
|
56
|
+
exit
|
|
57
|
+
b.package('pkgid'=>pkgid.checksum, 'name' => pkgid.name, 'arch'=>pkgid.arch ) do | b |
|
|
58
|
+
b.version('epoch' => pkgid.version.e, 'ver' => pkgid.version.v, 'rel' => pkgid.version.r)
|
|
59
|
+
pkgid.files.each do |f|
|
|
60
|
+
b.file f
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# write filelists.xml
|
|
66
|
+
def write(file)
|
|
67
|
+
#builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
|
68
|
+
#builder.instruct!
|
|
69
|
+
#xml = builder.tag!("otherdata", 'xmlns' => 'xmlns="http://linux.duke.edu/metadata/other"', 'packages'=> @rpmfiles.size ) do |b|
|
|
70
|
+
@rpmfiles.each do |rpmfile|
|
|
71
|
+
# done package tag
|
|
72
|
+
write_package(file, rpmfile)
|
|
73
|
+
end
|
|
74
|
+
# next package
|
|
75
|
+
#end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
require 'digest/sha1'
|
|
27
|
+
require 'rpm'
|
|
28
|
+
|
|
29
|
+
module EnhanceRepo
|
|
30
|
+
|
|
31
|
+
# thin wrapper over rpm package
|
|
32
|
+
class PackageId
|
|
33
|
+
attr_accessor :checksum
|
|
34
|
+
attr_accessor :path
|
|
35
|
+
attr_accessor :rpm
|
|
36
|
+
|
|
37
|
+
def initialize(rpmfile)
|
|
38
|
+
@path = rpmfile
|
|
39
|
+
@rpm = RPM::Package.open(rpmfile)
|
|
40
|
+
@checksum = Digest::SHA1.hexdigest(File.new(rpmfile).read)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Forward other methods
|
|
44
|
+
def method_missing(sym, *args)
|
|
45
|
+
@rpm.send(sym, *args)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
@checksum.hash
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def eql?(other)
|
|
53
|
+
@checksum == other.checksum
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# match function at name and nvr level
|
|
57
|
+
def matches(ident)
|
|
58
|
+
# if the name matches, then it is sufficient
|
|
59
|
+
return true if ident == @rpm.name
|
|
60
|
+
# if not, compare the edition without release
|
|
61
|
+
return true if ident == "#{@rpm.name}-#{@rpm.version.v}"
|
|
62
|
+
# if not, compare the edition with release
|
|
63
|
+
return true if ident == "#{@rpm.name}-#{@rpm.version.v}-#{@rpm.version.r}"
|
|
64
|
+
# if not, also the architecture
|
|
65
|
+
return true if ident == "#{@rpm.name}-#{@rpm.version.v}-#{@rpm.version.r}"
|
|
66
|
+
# and finally arch
|
|
67
|
+
return true if ident == "#{@rpm.name}-#{@rpm.version.v}-#{@rpm.version.r}.#{@rpm.arch}"
|
|
68
|
+
return false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_s
|
|
72
|
+
@rpm.to_s
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def ident
|
|
76
|
+
"#{@rpm.to_s}.#{@rpm.arch}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
module EnhanceRepo
|
|
26
|
+
class ProductId
|
|
27
|
+
attr_accessor :label
|
|
28
|
+
attr_accessor :cpeid
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
lib = File.dirname(__FILE__)
|
|
26
|
+
|
|
27
|
+
require File.join(lib, 'rpm_md', 'repo.rb')
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
module EnhanceRepo
|
|
27
|
+
module RpmMd
|
|
28
|
+
|
|
29
|
+
# represents a metadata unit
|
|
30
|
+
class Data
|
|
31
|
+
include Logger
|
|
32
|
+
|
|
33
|
+
# initialize the extra data with a name
|
|
34
|
+
# or use the class name as default
|
|
35
|
+
def initialize(name)
|
|
36
|
+
@name = name
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def name
|
|
40
|
+
defined?(@name) ? @name : self.class.to_s.split("::").last.downcase
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def metadata_filename
|
|
44
|
+
"repodata/#{name}.xml#{should_compress? ? '.gz' : ''}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# wether the metadata should be compressed
|
|
48
|
+
def should_compress?
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#--
|
|
2
|
+
#
|
|
3
|
+
# enhancerepo is a rpm-md repository metadata tool.
|
|
4
|
+
# Copyright (C) 2008, 2009 Novell Inc.
|
|
5
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
20
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
|
21
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
|
22
|
+
#
|
|
23
|
+
#++
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
require 'rubygems'
|
|
27
|
+
require 'nokogiri'
|
|
28
|
+
require 'yaml'
|
|
29
|
+
require 'rpm'
|
|
30
|
+
require 'pp'
|
|
31
|
+
require 'pathname'
|
|
32
|
+
|
|
33
|
+
module EnhanceRepo
|
|
34
|
+
module RpmMd
|
|
35
|
+
|
|
36
|
+
include REXML
|
|
37
|
+
|
|
38
|
+
class DeltaRpm < PackageId
|
|
39
|
+
attr_accessor :sequence, :sourcerpm
|
|
40
|
+
|
|
41
|
+
def initialize(filename)
|
|
42
|
+
super(filename)
|
|
43
|
+
`applydeltarpm -i '#{filename}'`.each_line do |line|
|
|
44
|
+
key, value = line.chop.split(':')
|
|
45
|
+
value.gsub!(/ /, '')
|
|
46
|
+
@sequence = value if key == "sequence"
|
|
47
|
+
@sourcerpm = value if key == "source rpm"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def hash
|
|
52
|
+
ident.hash
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def eql?(other)
|
|
56
|
+
ident == other.ident
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class DeltaInfo < Data
|
|
62
|
+
|
|
63
|
+
def initialize(dir)
|
|
64
|
+
@dir = dir
|
|
65
|
+
# here we store known deltas
|
|
66
|
+
# we index by new package
|
|
67
|
+
# and in every slot we store an
|
|
68
|
+
# array with such deltas
|
|
69
|
+
@deltas = Hash.new
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def delta_count
|
|
73
|
+
@deltas.size
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def empty?
|
|
77
|
+
return @deltas.empty?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Create delta rpms for the last
|
|
81
|
+
# n versions of some rpm.
|
|
82
|
+
#
|
|
83
|
+
# So if you have
|
|
84
|
+
# foo-4.rpm
|
|
85
|
+
# foo-3.rpm
|
|
86
|
+
# foo-2.rpm
|
|
87
|
+
# foo-1.rpm
|
|
88
|
+
#
|
|
89
|
+
# Creating deltas with n = 1 will
|
|
90
|
+
# create a delta for going to
|
|
91
|
+
# version 3 to 4. While n = 2 would
|
|
92
|
+
# create a delta to go from 2 to 4 too.
|
|
93
|
+
#
|
|
94
|
+
# options are :n => number of deltas (default 1)
|
|
95
|
+
# and :outputdir => defaulting to the same
|
|
96
|
+
# input directory
|
|
97
|
+
def create_deltas(opts={})
|
|
98
|
+
outputdir = opts[:outputdir] || @dir
|
|
99
|
+
n = opts[:n] || 1
|
|
100
|
+
|
|
101
|
+
log.info "Scanning rpms for delta generation (#{n} levels)"
|
|
102
|
+
#log.info "Creating deltarpms : level #{n}"
|
|
103
|
+
# make a hash name -> array of packages
|
|
104
|
+
pkgs = Hash.new
|
|
105
|
+
|
|
106
|
+
Dir["#{@dir}/**/*.rpm"].each do |rpmfile|
|
|
107
|
+
#puts "Delta: #{rpmfile}"
|
|
108
|
+
rpm = PackageId.new(rpmfile)
|
|
109
|
+
|
|
110
|
+
pkgs[rpm.name] = Array.new if not pkgs.has_key?(rpm.name)
|
|
111
|
+
pkgs[rpm.name] << rpm
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# now that we have al packages, sort them by version
|
|
115
|
+
pkgs.each do |pkgname, pkglist|
|
|
116
|
+
|
|
117
|
+
pkglist.sort! { |a,b| a.version <=> b.version }
|
|
118
|
+
pkglist.reverse!
|
|
119
|
+
# now that the list is sorted, the new rpm is the first
|
|
120
|
+
newpkg = pkglist.shift
|
|
121
|
+
c = 0
|
|
122
|
+
if not pkglist.empty?
|
|
123
|
+
for pkg in pkglist
|
|
124
|
+
break if c == n
|
|
125
|
+
# do not create a delta for the same package
|
|
126
|
+
next if newpkg.version == pkg.version
|
|
127
|
+
# do not create a delta for different archs
|
|
128
|
+
next if newpkg.arch != pkg.arch
|
|
129
|
+
oldpkg = pkg
|
|
130
|
+
# use the same dir as the new rpm
|
|
131
|
+
log.info "`-> creating delta - #{oldpkg.to_s} -> #{newpkg.to_s} (#{c+1}/#{n})"
|
|
132
|
+
# calculate directory where to save the delta. Use the newpkg
|
|
133
|
+
# relative to the origin directory,
|
|
134
|
+
# this only works because we know the rpm is inside @dir
|
|
135
|
+
subdir = Pathname.new(newpkg.path).relative_path_from(Pathname.new(@dir)).dirname
|
|
136
|
+
# calculate the deltarpm name
|
|
137
|
+
deltafile = File.join(outputdir, subdir, delta_package_name(oldpkg,newpkg))
|
|
138
|
+
FileUtils.mkdir_p File.dirname(deltafile)
|
|
139
|
+
#puts "makedeltarpm #{oldpkg.path} #{newpkg.path} #{deltafile}"
|
|
140
|
+
`makedeltarpm '#{oldpkg.path}' '#{newpkg.path}' '#{deltafile}'`
|
|
141
|
+
c += 1
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# figure out the name of a delta rpm
|
|
150
|
+
def delta_package_name(oldpkg, newpkg)
|
|
151
|
+
deltarpm = ""
|
|
152
|
+
if ( oldpkg.version.v == newpkg.version.v )
|
|
153
|
+
# if the version is the same, then it is specified only once, and the range
|
|
154
|
+
# is used for the releases
|
|
155
|
+
deltarpm = "#{oldpkg.name}-#{oldpkg.version.v}-#{oldpkg.version.r}_#{newpkg.version.r}.#{oldpkg.arch}.delta.rpm"
|
|
156
|
+
else
|
|
157
|
+
deltarpm = "#{oldpkg.name}-#{oldpkg.version.v}_#{newpkg.version.v}-#{oldpkg.version.r}_#{newpkg.version.r}.#{oldpkg.arch}.delta.rpm"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def add_deltas
|
|
162
|
+
Dir["#{@dir}/**/*.delta.rpm"].each do |deltafile|
|
|
163
|
+
delta = DeltaRpm.new(deltafile)
|
|
164
|
+
#puts "Delta: #{deltafile} for '#{delta.ident}'"
|
|
165
|
+
@deltas[delta] = Array.new if @deltas[delta].nil?
|
|
166
|
+
@deltas[delta] << delta
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# write a update out
|
|
172
|
+
def write(file)
|
|
173
|
+
builder = Nokogiri::XML::Builder.new do |b|
|
|
174
|
+
b.deltainfo do
|
|
175
|
+
@deltas.each do |ident, deltas|
|
|
176
|
+
b.newpackage( 'name' => ident.name, 'arch' => ident.arch,
|
|
177
|
+
'version' => ident.version.v,
|
|
178
|
+
'release' => ident.version.r ) do |b|
|
|
179
|
+
deltas.each do |delta|
|
|
180
|
+
# get the edition by getting the name out
|
|
181
|
+
version = RPM::Version.new(delta.sourcerpm.gsub(/#{Regexp.escape(delta.name)}-/, ''))
|
|
182
|
+
b.delta('oldepoch'=>0, 'oldversion'=>version.v, 'oldrelease'=>version.r) do |b|
|
|
183
|
+
# remove the base dir, make it relative
|
|
184
|
+
delta_abs_path = Pathname.new(delta.path).realpath
|
|
185
|
+
base_dir_abs_path = Pathname.new(@dir).realpath
|
|
186
|
+
relative_path = delta_abs_path.relative_path_from(base_dir_abs_path)
|
|
187
|
+
b.filename relative_path
|
|
188
|
+
b.sequence(delta.sequence)
|
|
189
|
+
b.size(File.size(delta.path))
|
|
190
|
+
b.checksum(delta.checksum, 'type'=>'sha')
|
|
191
|
+
end # </delta>
|
|
192
|
+
end
|
|
193
|
+
end # </newpackage>
|
|
194
|
+
end # each delta
|
|
195
|
+
end #</deltainfo>
|
|
196
|
+
end
|
|
197
|
+
# ready builder
|
|
198
|
+
file.write(builder.doc.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML))
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
end
|
|
205
|
+
end
|