enhancerepo 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/CHANGELOG.rdoc +18 -0
  2. data/Manifest.txt +85 -0
  3. data/README +10 -0
  4. data/README.rdoc +15 -0
  5. data/Rakefile +48 -0
  6. data/TODO.rdoc +4 -0
  7. data/bin/enhancerepo +4 -0
  8. data/lib/enhance_repo.rb +36 -0
  9. data/lib/enhance_repo/cli.rb +150 -0
  10. data/lib/enhance_repo/config_opts.rb +98 -0
  11. data/lib/enhance_repo/logger.rb +67 -0
  12. data/lib/enhance_repo/other.rb +80 -0
  13. data/lib/enhance_repo/package_id.rb +81 -0
  14. data/lib/enhance_repo/product_id.rb +30 -0
  15. data/lib/enhance_repo/rpm_md.rb +27 -0
  16. data/lib/enhance_repo/rpm_md/data.rb +55 -0
  17. data/lib/enhance_repo/rpm_md/delta_info.rb +205 -0
  18. data/lib/enhance_repo/rpm_md/extra_primary_data.rb +45 -0
  19. data/lib/enhance_repo/rpm_md/file_lists.rb +81 -0
  20. data/lib/enhance_repo/rpm_md/index.rb +144 -0
  21. data/lib/enhance_repo/rpm_md/other.rb +69 -0
  22. data/lib/enhance_repo/rpm_md/primary.rb +123 -0
  23. data/lib/enhance_repo/rpm_md/products.rb +142 -0
  24. data/lib/enhance_repo/rpm_md/repo.rb +202 -0
  25. data/lib/enhance_repo/rpm_md/resource.rb +44 -0
  26. data/lib/enhance_repo/rpm_md/suse_data.rb +191 -0
  27. data/lib/enhance_repo/rpm_md/suse_info.rb +88 -0
  28. data/lib/enhance_repo/rpm_md/update.rb +141 -0
  29. data/lib/enhance_repo/rpm_md/update_info.rb +244 -0
  30. data/lib/enhance_repo/rpm_md/update_smart_fields.rb +127 -0
  31. data/lib/enhance_repo/xml_comparer.rb +117 -0
  32. data/lib/tempdir.rb +62 -0
  33. data/lib/tempdir/tempfile.rb +21 -0
  34. data/test/all_tests.rb +27 -0
  35. data/test/data/packages/a-1.0.spec +19 -0
  36. data/test/data/packages/a-2.0.spec +24 -0
  37. data/test/data/repodata/update-test-11.1/filelists.xml.gz +0 -0
  38. data/test/data/repodata/update-test-11.1/other.xml.gz +0 -0
  39. data/test/data/repodata/update-test-11.1/primary.xml.gz +0 -0
  40. data/test/data/repodata/update-test-11.1/repomd.xml +21 -0
  41. data/test/data/repomd.xml +21 -0
  42. data/test/data/rpms/repo-1/a-1.0-0.x86_64.rpm +0 -0
  43. data/test/data/rpms/repo-1/a-1.0_2.0-0_0.x86_64.delta.rpm +0 -0
  44. data/test/data/rpms/repo-1/a-2.0-0.x86_64.rpm +0 -0
  45. data/test/data/rpms/repo-1/repodata/deltainfo.xml.gz +0 -0
  46. data/test/data/rpms/repo-1/repodata/deltainfo.xml.gz.gz +0 -0
  47. data/test/data/rpms/repo-1/repodata/filelists.xml.gz +0 -0
  48. data/test/data/rpms/repo-1/repodata/other.xml.gz +0 -0
  49. data/test/data/rpms/repo-1/repodata/primary.xml.gz +0 -0
  50. data/test/data/rpms/repo-1/repodata/repomd.xml +45 -0
  51. data/test/data/rpms/repo-1/repodata/susedata.xml.gz +0 -0
  52. data/test/data/rpms/repo-1/repodata/updateinfo.xml.gz +0 -0
  53. data/test/data/rpms/repo-1/repoparts/update-a-1.xml +22 -0
  54. data/test/data/rpms/repo-with-product/a-1.0-0.x86_64.rpm +0 -0
  55. data/test/data/rpms/repo-with-product/openSUSE-release-11.2-1.6.i586.rpm +0 -0
  56. data/test/data/rpms/repo-with-product/openSUSE-release-dvd-11.2-1.6.i586.rpm +0 -0
  57. data/test/data/rpms/repo-with-product/repodata/filelists.xml.gz +0 -0
  58. data/test/data/rpms/repo-with-product/repodata/other.xml.gz +0 -0
  59. data/test/data/rpms/repo-with-product/repodata/primary.xml.gz +0 -0
  60. data/test/data/rpms/repo-with-product/repodata/products.xml.gz +0 -0
  61. data/test/data/rpms/repo-with-product/repodata/repomd.xml +27 -0
  62. data/test/data/rpms/update-test-11.1/update-test-affects-package-manager.rpm +0 -0
  63. data/test/data/rpms/update-test-11.1/update-test-interactive.rpm +0 -0
  64. data/test/data/rpms/update-test-11.1/update-test-optional.rpm +0 -0
  65. data/test/data/rpms/update-test-11.1/update-test-reboot-needed.rpm +0 -0
  66. data/test/data/rpms/update-test-11.1/update-test-security.rpm +0 -0
  67. data/test/data/rpms/update-test-11.1/update-test-trival.rpm +0 -0
  68. data/test/data/rpms/update-test-factory/update-test-affects-package-manager-0-9999.1.2.noarch.rpm +0 -0
  69. data/test/data/rpms/update-test-factory/update-test-interactive-0-9999.1.2.noarch.rpm +0 -0
  70. data/test/data/rpms/update-test-factory/update-test-optional-0-9999.1.2.noarch.rpm +0 -0
  71. data/test/data/rpms/update-test-factory/update-test-reboot-needed-0-9999.1.2.noarch.rpm +0 -0
  72. data/test/data/rpms/update-test-factory/update-test-relogin-suggested-0-9999.1.2.noarch.rpm +0 -0
  73. data/test/data/rpms/update-test-factory/update-test-security-0-9999.1.2.noarch.rpm +0 -0
  74. data/test/deltainfo_test.rb +50 -0
  75. data/test/extensions_test.rb +31 -0
  76. data/test/index_test.rb +51 -0
  77. data/test/primary_test.rb +51 -0
  78. data/test/products_test.rb +51 -0
  79. data/test/repo_test.rb +72 -0
  80. data/test/repomdindex_test.rb +58 -0
  81. data/test/rpmmd_test.rb +60 -0
  82. data/test/susedata_test.rb +53 -0
  83. data/test/tempdir_test.rb +62 -0
  84. data/test/test_helper.rb +53 -0
  85. data/test/update_test.rb +80 -0
  86. data/test/updateinfo_test.rb +59 -0
  87. metadata +267 -0
@@ -0,0 +1,127 @@
1
+ #--
2
+ #
3
+ # enhancerepo is a rpm-md repository metadata tool.
4
+ # Copyright (C) 2008, 2009 Novell Inc.
5
+ #
6
+ # Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
+ # MA 02110-1301, USA. A copy of the GNU General Public License is
22
+ # also available at http://www.gnu.org/copyleft/gpl.html.
23
+ #
24
+ #++
25
+ #
26
+
27
+ module EnhanceRepo
28
+ module RpmMd
29
+
30
+ module UpdateSmartFields
31
+ # detects references for the given
32
+ # configuration
33
+ # options:
34
+ # :keyword => 'foo'
35
+ # would match foo-#123 foo#1234 FOO #1234 and other
36
+ # creative developer variations
37
+ # :keywords => ['foo', 'bar']
38
+ # adds various keywords at once
39
+ # :href => 'http://foo.org/?query=:id'
40
+ # website reference, :id is replaced with the
41
+ # actual detected id
42
+ # :title => 'SUSE bug #:id'
43
+ # title, :id is replaced with the detected id
44
+ # :type => 'bugzilla'
45
+ # type is just passed and set in the reference that match
46
+ # this options
47
+ def each_reference_for(opts={})
48
+ update = self
49
+ keywords = Set.new
50
+ keywords << opts[:keyword] if opts.has_key?(:keyword)
51
+ keywords = keywords.merge(opts[:keywords].to_set) if opts.has_key?(:keywords)
52
+
53
+ regexps = []
54
+ keywords.each do |keyword|
55
+ specifier = keyword.each_char.map{|x| "#{x}\\\.?"}.join
56
+ regexps << "#{specifier}[-|\\\s#|\\\s|#](\\\d+[-|\\\d+]*)"
57
+ end
58
+
59
+ regexps.each do |regexp|
60
+ references = update.description.scan(/#{regexp}/i)
61
+ references.each do |ref_id|
62
+ ref = Reference.new
63
+ ref.referenceid = ref_id.first
64
+ ref.href = opts[:href].gsub(/:id/, ref_id.join) if opts.has_key?(:href)
65
+ ref.title = opts[:title].gsub(/:id/, ref_id.join) if opts.has_key?(:title)
66
+ ref.type = opts[:type] if opts.has_key?(:type)
67
+ yield ref
68
+ end
69
+ end
70
+ end
71
+
72
+ # yields a reference in the passed
73
+ # block for every detected reference from the known
74
+ # ones
75
+ # in the update description
76
+ def each_detected_reference
77
+ each_reference_for(:keyword => 'bnc', :href => 'http://bugzilla.novell.com/:id', :title => 'Novell bugzilla #:id', :type => 'bugzilla' ) {|x| yield x}
78
+ each_reference_for(:keywords => ['rh', 'rhbz'], :href => 'http://bugzilla.redhat.com/:id', :title => 'Redhat bugzilla #:id', :type => 'bugzilla' ) {|x| yield x}
79
+ each_reference_for(:keyword => 'bgo', :href => 'http://bugzilla.gnome.org/:id', :title => 'Gnome bug #:id', :type => 'bugzilla' ) {|x| yield x}
80
+ each_reference_for(:keyword => 'kde', :href => 'http://bugs.kde.org/:id', :title => 'KDE bug #:id', :type => 'bugzilla' ) {|x| yield x}
81
+ each_reference_for(:keyword => 'kde', :href => 'http://bugs.kde.org/:id', :title => 'KDE bug #:id', :type => 'bugzilla' ) {|x| yield x}
82
+ each_reference_for(:keyword => 'cve', :href => 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-:id', :title => 'CVE-:id', :type => 'cve' ) {|x| yield x}
83
+ end
84
+
85
+ # automatically set empty fields
86
+ # needs the description to be set to
87
+ # be somehow smart
88
+ def smart_fill_blank_fields
89
+ update = self
90
+ # figure out the type (optional is default)
91
+ if update.description =~ /vulnerability|security|CVE|Secunia/
92
+ update.type = 'security'
93
+ else
94
+ update.type = 'recommended' if update.description =~ /fix|bnc#|bug|crash/
95
+ end
96
+
97
+ update.title = "#{update.type} update #{update.version} "
98
+
99
+ # now figure out the title
100
+ # if there is only package
101
+ if update.packages.size == 1
102
+ # then name the fix according to the package, and the type
103
+ update.title << "for #{update.packages.first.name}"
104
+ update.updateid = update.packages.first.name
105
+ elsif update.packages.size < 1
106
+ # do nothing, it is may be just a message
107
+ else
108
+ # figure out what the multiple packages are
109
+ if update.packages.grep(/kde/).size > 1
110
+ # assume it is a KDE update
111
+ update.title << "for KDE"
112
+ # KDE 3 or KDE4
113
+ update.updateid = "KDE3" if update.packages.grep(/kde(.+)3$/).size > 1
114
+ update.updateid = "KDE4" if update.packages.grep(/kde(.+)4$/).size > 1
115
+ elsif update.packages.grep(/kernel/).size > 1
116
+ update.title << "for the Linux kernel"
117
+ update.updateid = 'kernel'
118
+ end
119
+ end
120
+
121
+ # now figure out and fill references
122
+ each_detected_reference { |ref| update.references << ref }
123
+ end
124
+
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,117 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2009:
4
+ #
5
+ # Thilo Utke (thilo[at]upstream-berlin[dot]com)
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
+ #
8
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
+ #
10
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11
+ #
12
+ require 'nokogiri'
13
+
14
+ class XmlComparer
15
+ attr_reader :missing_nodes, :different_nodes, :superfluous_nodes
16
+
17
+ def initialize(options = {})
18
+ options.symbolize_keys!
19
+ @custom_matcher = options.delete(:custom_matcher)
20
+ @show_messages = options.delete(:show_messages)
21
+ end
22
+ def compare(target, sample)
23
+ @target_doc = Nokogiri::XML::Document.parse(target, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS)
24
+ @sample_doc = Nokogiri::XML::Document.parse(sample, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS)
25
+ @missing_nodes = []
26
+ @different_nodes = []
27
+ @superfluous_nodes = []
28
+ standard_traverse_and_compare
29
+ reverse_traverse_and_compare
30
+ p result_messages if @show_messages
31
+ are_equal?
32
+ end
33
+
34
+ def result_messages
35
+ missing_result_messages
36
+ superfluous_nodes_messages
37
+ different_nodes_messages
38
+ end
39
+
40
+ private
41
+
42
+ def are_equal?
43
+ @missing_nodes.empty? && @different_nodes.empty? && @superfluous_nodes.empty?
44
+ end
45
+
46
+ def missing_result_messages
47
+ puts "\nFollowing nodes are missing:\n" unless @missing_nodes.empty?
48
+ @missing_nodes.each do |node|
49
+ puts "#{node.to_s} at #{node.path}\n"
50
+ end
51
+ end
52
+
53
+ def superfluous_nodes_messages
54
+ puts "\nFollowing nodes are superfluous:\n" unless @superfluous_nodes.empty?
55
+ @superfluous_nodes.each do |node|
56
+ puts "#{node.to_s} at #{node.path}\n"
57
+ end
58
+ end
59
+
60
+ def different_nodes_messages
61
+ puts "\nFollowing nodes are different:\n" unless @different_nodes.empty?
62
+ @different_nodes.each do |node_pair|
63
+ puts "#{node_pair[0].to_s} vs #{node_pair[1].to_s} at #{node_pair[0].path}\n"
64
+ end
65
+ end
66
+
67
+
68
+ def standard_traverse_and_compare
69
+ traverse_and_compare(@target_doc, @sample_doc)
70
+ end
71
+
72
+ def reverse_traverse_and_compare
73
+ traverse_and_compare(@sample_doc, @target_doc)
74
+ end
75
+
76
+ def traverse_and_compare(doc, other_doc)
77
+ doc.root.traverse do |node|
78
+ other_node = find_sibling_in_other_doc(node, other_doc)
79
+ if other_node.nil?
80
+ add_to_missing_or_superfluous(node, doc)
81
+ else
82
+ @different_nodes << [node, other_node] unless in_reverse_traverse?(doc) || equal_nodes?(node, other_node)
83
+ end
84
+ end
85
+ end
86
+
87
+ def find_sibling_in_other_doc(node, doc)
88
+ sibling_in_other_doc = doc.search(node.path).first
89
+ sibling_in_other_doc
90
+ end
91
+
92
+ def add_to_missing_or_superfluous(node, doc)
93
+ (in_reverse_traverse?(doc) ? @superfluous_nodes : @missing_nodes) << node
94
+ end
95
+
96
+ def in_reverse_traverse?(doc)
97
+ doc == @sample_doc
98
+ end
99
+
100
+ def equal_nodes?(node, other_node)
101
+ return false unless node && other_node
102
+ standard_compare(node, other_node) || custom_compare(node, other_node)
103
+ end
104
+
105
+ def standard_compare(node, other_node)
106
+ if node.text?
107
+ node.text.strip == other_node.text.strip
108
+ else
109
+ Set.new(node.keys) == Set.new(other_node.keys) && Set.new(node.values) == Set.new(other_node.values)
110
+ end
111
+ end
112
+
113
+ def custom_compare(node, other_node)
114
+ return false unless @custom_matcher
115
+ @custom_matcher.call(node) && @custom_matcher.call(other_node)
116
+ end
117
+ end
data/lib/tempdir.rb ADDED
@@ -0,0 +1,62 @@
1
+ # Author:: Yuichi Tateno <hotchpotch@gmail.com>
2
+ # Copyright:: Copyright (c) 2008 Yuichi Tateno
3
+ # License:: MIT
4
+
5
+ require 'tmpdir'
6
+ require 'pathname'
7
+
8
+ class Tempdir
9
+ @@tmpdir = Pathname.new(Dir.tmpdir)
10
+ def self.tmpdir; @@tmpdir; end
11
+ def self.tmpdir=(d); @@tmpdir = Pathname.new(d); end
12
+
13
+ attr_reader :dir
14
+ def initialize(name = nil)
15
+ @dir = create_tmpdir(name)
16
+ @dir.mkpath
17
+ @exit_proc = add_exit
18
+ if block_given?
19
+ begin
20
+ yield @dir
21
+ ensure
22
+ close
23
+ end
24
+ end
25
+ end
26
+
27
+ def close
28
+ @dir.rmtree if @dir.directory?
29
+ end
30
+
31
+ def self.open(name = nil, &block)
32
+ new(name, &block)
33
+ end
34
+
35
+ private
36
+ def add_exit
37
+ at_exit {
38
+ self.close if self
39
+ }
40
+ end
41
+
42
+ def create_tmpdir(name)
43
+ tmp = Pathname.new self.class.tmpdir
44
+ if name
45
+ tmp = tmp.join(name)
46
+ raise "#{tmp.to_s} is exist." if tmp.exist?
47
+ else
48
+ tmp = tmp.join('_')
49
+ begin
50
+ tmp = tmp.parent.join randname
51
+ end while tmp.exist?
52
+ end
53
+ tmp
54
+ end
55
+
56
+ TMPDIR_PREFIX = 'ruby.tempdir.'
57
+ def randname
58
+ TMPDIR_PREFIX + (0..8).map{rand(36).to_s(36)}.join
59
+ end
60
+ end
61
+
62
+
@@ -0,0 +1,21 @@
1
+ # Author:: Yuichi Tateno <hotchpotch@gmail.com>
2
+ # Copyright:: Copyright (c) 2008 Yuichi Tateno
3
+ # License:: MIT
4
+
5
+ require 'tempdir'
6
+ require 'tempfile'
7
+
8
+ class Tempdir
9
+ class Tempfile < ::Tempfile
10
+ def self.open(name = nil, dir = nil)
11
+ name ||= (0..8).map{rand(36).to_s(36)}.join
12
+ args = dir ? [name, dir] : [name]
13
+ tmp = ::Tempfile.new *args
14
+ begin
15
+ yield tmp
16
+ ensure
17
+ tmp.close true
18
+ end
19
+ end
20
+ end
21
+ end
data/test/all_tests.rb ADDED
@@ -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
+ Dir['**/*_test.rb'].each { |test_case| require test_case }
26
+
27
+
@@ -0,0 +1,19 @@
1
+ Name: a
2
+ Summary: a package
3
+ License: Public Domain
4
+ Version: 1.0
5
+ Release: 0
6
+ %description
7
+ a simple package
8
+
9
+ %build
10
+
11
+ %install
12
+ echo "Hello friends!" > %{buildroot}/hello.txt
13
+
14
+ %files
15
+ /hello.txt
16
+
17
+ %changelog
18
+ * Mon May 11 2009 xxxx@yyyy.com
19
+ - initial package
@@ -0,0 +1,24 @@
1
+ Name: a
2
+ Summary: a package
3
+ License: Public Domain
4
+ Version: 2.0
5
+ Release: 0
6
+ %description
7
+ a simple package
8
+
9
+ %build
10
+
11
+ %install
12
+ echo "Hello friends friend friends friends!" > %{buildroot}/hello.txt
13
+
14
+ %files
15
+ /hello.txt
16
+
17
+ %changelog
18
+ * Fri Dec 4 2009 xxxx@yyyy.com
19
+ - second change fixes bnc#1111 and
20
+ kde #3444 and CVE-3333
21
+ * Thu Dec 3 2009 xxxx@yyyy.com
22
+ - first change
23
+ * Mon May 11 2009 xxxx@yyyy.com
24
+ - initial package
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <repomd xmlns="http://linux.duke.edu/metadata/repo">
3
+ <data type="other">
4
+ <location href="repodata/other.xml.gz"/>
5
+ <checksum type="sha">e32ba929fe03fef5fee9520980c97b7080f45b42</checksum>
6
+ <timestamp>1242058237</timestamp>
7
+ <open-checksum type="sha">b937b98d92d72ef0b56bb43e028d2a3b0f69e1bb</open-checksum>
8
+ </data>
9
+ <data type="filelists">
10
+ <location href="repodata/filelists.xml.gz"/>
11
+ <checksum type="sha">e62a84faf318f7504c4ca83474b9f3bf63d08212</checksum>
12
+ <timestamp>1242058237</timestamp>
13
+ <open-checksum type="sha">da885e352895c856b0b16d0c64d491d8ebc86b67</open-checksum>
14
+ </data>
15
+ <data type="primary">
16
+ <location href="repodata/primary.xml.gz"/>
17
+ <checksum type="sha">23c3c2635e772c6510733eee6a0ba0a8a1f9784e</checksum>
18
+ <timestamp>1242058237</timestamp>
19
+ <open-checksum type="sha">ad22ea87ba9696fb12eddfdf912f8e622bca6814</open-checksum>
20
+ </data>
21
+ </repomd>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <repomd xmlns="http://linux.duke.edu/metadata/repo">
3
+ <data type="other">
4
+ <location href="repodata/other.xml.gz"/>
5
+ <checksum type="sha">aa03023d1613943b3100d4cb2c5d20faa153a2cc</checksum>
6
+ <timestamp>1221950230</timestamp>
7
+ <open-checksum type="sha">4cf6a0aa1070eac689560a1ec6073ff5eed6cde5</open-checksum>
8
+ </data>
9
+ <data type="filelists">
10
+ <location href="repodata/filelists.xml.gz"/>
11
+ <checksum type="sha">010a4ca215ebc87e82b5fe0f29447e8810569d74</checksum>
12
+ <timestamp>1221950230</timestamp>
13
+ <open-checksum type="sha">74a11a8dffff05a321e624733dabdf482385aa97</open-checksum>
14
+ </data>
15
+ <data type="primary">
16
+ <location href="repodata/primary.xml.gz"/>
17
+ <checksum type="sha">4e2f1fcca9a5d3e63a0d3069fd54234626700e74</checksum>
18
+ <timestamp>1221950230</timestamp>
19
+ <open-checksum type="sha">0570b7d8860235b80e151e207ce7f1e8e2e1a20b</open-checksum>
20
+ </data>
21
+ </repomd>