polisher 0.10.2 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/bin/binary_gem_resolver.rb +2 -2
  3. data/bin/bundler2yum.rb +51 -0
  4. data/bin/check_ruby_spec.rb +32 -0
  5. data/bin/gem_dependency_checker.rb +13 -242
  6. data/bin/gem_mapper.rb +27 -0
  7. data/bin/gems2update.rb +27 -0
  8. data/bin/git_gem_diff.rb +48 -0
  9. data/bin/git_gem_updater.rb +3 -3
  10. data/bin/missing_deps.rb +29 -0
  11. data/bin/polisher-config.rb +17 -0
  12. data/bin/ruby_rpm_spec_updater.rb +23 -2
  13. data/lib/polisher.rb +5 -12
  14. data/lib/polisher/adaptors/checker_loader.rb +78 -0
  15. data/lib/polisher/{upstream.rb → adaptors/upstream.rb} +1 -0
  16. data/lib/polisher/adaptors/version_checker.rb +57 -0
  17. data/lib/polisher/adaptors/version_checker/bodhi.rb +29 -0
  18. data/lib/polisher/adaptors/version_checker/errata.rb +29 -0
  19. data/lib/polisher/adaptors/version_checker/fedora.rb +29 -0
  20. data/lib/polisher/adaptors/version_checker/gem.rb +27 -0
  21. data/lib/polisher/adaptors/version_checker/git.rb +29 -0
  22. data/lib/polisher/adaptors/version_checker/koji.rb +29 -0
  23. data/lib/polisher/adaptors/version_checker/yum.rb +29 -0
  24. data/lib/polisher/cli/all.rb +22 -0
  25. data/lib/polisher/cli/bin/gem_dependency_checker.rb +85 -0
  26. data/lib/polisher/cli/bin/gem_mapper.rb +37 -0
  27. data/lib/polisher/cli/bin/gems2update.rb +86 -0
  28. data/lib/polisher/cli/bin/missing_deps.rb +35 -0
  29. data/lib/polisher/cli/conf.rb +18 -0
  30. data/lib/polisher/cli/default.rb +25 -0
  31. data/lib/polisher/cli/format.rb +130 -0
  32. data/lib/polisher/cli/sources.rb +106 -0
  33. data/lib/polisher/cli/specifier.rb +30 -0
  34. data/lib/polisher/cli/status.rb +50 -0
  35. data/lib/polisher/cli/targets.rb +88 -0
  36. data/lib/polisher/gem.rb +41 -338
  37. data/lib/polisher/gem/attributes.rb +20 -0
  38. data/lib/polisher/gem/dependencies.rb +63 -0
  39. data/lib/polisher/gem/diff.rb +39 -0
  40. data/lib/polisher/gem/files.rb +111 -0
  41. data/lib/polisher/gem/parser.rb +85 -0
  42. data/lib/polisher/gem/retriever.rb +137 -0
  43. data/lib/polisher/{gem_state.rb → gem/state.rb} +6 -6
  44. data/lib/polisher/gem/versions.rb +131 -0
  45. data/lib/polisher/gemfile.rb +20 -89
  46. data/lib/polisher/gemfile/attributes.rb +19 -0
  47. data/lib/polisher/gemfile/deps.rb +43 -0
  48. data/lib/polisher/gemfile/parser.rb +45 -0
  49. data/lib/polisher/git/pkg.rb +33 -238
  50. data/lib/polisher/git/pkg/attributes.rb +60 -0
  51. data/lib/polisher/git/pkg/builder.rb +47 -0
  52. data/lib/polisher/git/pkg/repo.rb +82 -0
  53. data/lib/polisher/git/pkg/updater.rb +53 -0
  54. data/lib/polisher/git/pkg/versions.rb +40 -0
  55. data/lib/polisher/git/project.rb +1 -1
  56. data/lib/polisher/git/repo.rb +79 -76
  57. data/lib/polisher/{vendor.rb → mixins/vendored_deps.rb} +4 -7
  58. data/lib/polisher/mixins/versioned_dependencies.rb +86 -0
  59. data/lib/polisher/record.rb +2 -0
  60. data/lib/polisher/rpm.rb +23 -0
  61. data/lib/polisher/rpm/patch.rb +10 -8
  62. data/lib/polisher/rpm/requirement.rb +33 -189
  63. data/lib/polisher/rpm/requirement/attributes.rb +43 -0
  64. data/lib/polisher/rpm/requirement/comparison.rb +97 -0
  65. data/lib/polisher/rpm/requirement/gem_reference.rb +46 -0
  66. data/lib/polisher/rpm/requirement/parser.rb +41 -0
  67. data/lib/polisher/rpm/spec.rb +97 -436
  68. data/lib/polisher/rpm/spec/check.rb +14 -0
  69. data/lib/polisher/rpm/spec/comparison.rb +64 -0
  70. data/lib/polisher/rpm/spec/files.rb +15 -0
  71. data/lib/polisher/rpm/spec/gem_files.rb +65 -0
  72. data/lib/polisher/rpm/spec/gem_reference.rb +59 -0
  73. data/lib/polisher/rpm/spec/gem_requirements.rb +73 -0
  74. data/lib/polisher/rpm/spec/parser.rb +106 -0
  75. data/lib/polisher/rpm/spec/requirements.rb +31 -0
  76. data/lib/polisher/rpm/spec/subpackages.rb +23 -0
  77. data/lib/polisher/rpm/spec/updater.rb +268 -0
  78. data/lib/polisher/specifier.rb +13 -0
  79. data/lib/polisher/targets.rb +36 -0
  80. data/lib/polisher/{apt.rb → targets/apt.rb} +1 -1
  81. data/lib/polisher/targets/bodhi.rb +43 -0
  82. data/lib/polisher/{bugzilla.rb → targets/bugzilla.rb} +1 -1
  83. data/lib/polisher/targets/errata.rb +55 -0
  84. data/lib/polisher/targets/errata/build.rb +24 -0
  85. data/lib/polisher/targets/fedora.rb +47 -0
  86. data/lib/polisher/targets/koji.rb +39 -0
  87. data/lib/polisher/targets/koji/builder.rb +38 -0
  88. data/lib/polisher/targets/koji/diff.rb +39 -0
  89. data/lib/polisher/targets/koji/rpc.rb +43 -0
  90. data/lib/polisher/targets/koji/versions.rb +67 -0
  91. data/lib/polisher/targets/rhn.rb +12 -0
  92. data/lib/polisher/targets/yum.rb +36 -0
  93. data/lib/polisher/{component.rb → util/component.rb} +3 -3
  94. data/lib/polisher/util/conf_helpers.rb +77 -0
  95. data/lib/polisher/util/config.rb +45 -0
  96. data/lib/polisher/util/core_ext.rb +59 -0
  97. data/lib/polisher/{error.rb → util/error.rb} +0 -0
  98. data/lib/polisher/{gem_cache.rb → util/gem_cache.rb} +1 -1
  99. data/lib/polisher/{git_cache.rb → util/git_cache.rb} +0 -0
  100. data/lib/polisher/{logger.rb → util/logger.rb} +2 -0
  101. data/lib/polisher/{tag_mapper.rb → util/tag_mapper.rb} +1 -1
  102. data/lib/polisher/version.rb +1 -1
  103. data/spec/{upstream_spec.rb → adaptors/upstream_spec.rb} +1 -1
  104. data/spec/{version_checker_spec.rb → adaptors/version_checker_spec.rb} +1 -6
  105. data/spec/data/activesupport-4.1.4.gem +0 -0
  106. data/spec/data/rubygem-activesupport-with-doc.spec +247 -0
  107. data/spec/data/rubygem-activesupport-without-requires.spec +232 -0
  108. data/spec/data/rubygem-activesupport.spec +0 -122
  109. data/spec/fixtures/gem_json.rb +49 -0
  110. data/spec/fixtures/gem_spec.rb +13 -0
  111. data/spec/fixtures/gemfile.rb +10 -0
  112. data/spec/fixtures/local_gem.rb +62 -0
  113. data/spec/fixtures/rpm_spec.rb +91 -0
  114. data/spec/gem/attributes_spec.rb +17 -0
  115. data/spec/gem/diff_spec.rb +80 -0
  116. data/spec/gem/files_spec.rb +171 -0
  117. data/spec/gem/parser_spec.rb +44 -0
  118. data/spec/gem/retriever_spec.rb +124 -0
  119. data/spec/gem/state_spec.rb +79 -0
  120. data/spec/gem/versions_spec.rb +148 -0
  121. data/spec/gem_spec.rb +5 -347
  122. data/spec/gemfile/deps_spec.rb +20 -0
  123. data/spec/gemfile/parser_spec.rb +26 -0
  124. data/spec/gemfile_spec.rb +0 -34
  125. data/spec/git/pkg/attributes_spec.rb +128 -0
  126. data/spec/git/pkg/builder_spec.rb +63 -0
  127. data/spec/git/pkg/repo_spec.rb +146 -0
  128. data/spec/git/pkg/updater_spec.rb +86 -0
  129. data/spec/git/pkg/versions_spec.rb +42 -0
  130. data/spec/git/pkg_spec.rb +21 -0
  131. data/spec/git/project_spec.rb +21 -0
  132. data/spec/git/repo_spec.rb +160 -0
  133. data/spec/{vendor_spec.rb → mixins/vendored_deps_spec.rb} +2 -4
  134. data/spec/mixins/versioned_dependencies_spec.rb +48 -0
  135. data/spec/rpm/patch_spec.rb +48 -0
  136. data/spec/rpm/requirement/attributes_spec.rb +34 -0
  137. data/spec/rpm/requirement/comparison_spec.rb +286 -0
  138. data/spec/rpm/requirement/gem_spec.rb +49 -0
  139. data/spec/rpm/requirement/parser_spec.rb +31 -0
  140. data/spec/rpm/requirement_spec.rb +8 -334
  141. data/spec/rpm/spec/check_spec.rb +25 -0
  142. data/spec/rpm/spec/comparison_spec.rb +55 -0
  143. data/spec/rpm/spec/files_spec.rb +17 -0
  144. data/spec/rpm/spec/gem_files_spec.rb +112 -0
  145. data/spec/rpm/spec/gem_reference_spec.rb +99 -0
  146. data/spec/rpm/spec/gem_requirement_spec.rb +38 -0
  147. data/spec/rpm/spec/parser_spec.rb +64 -0
  148. data/spec/rpm/spec/requirements_spec.rb +10 -0
  149. data/spec/rpm/spec/subpackages_spec.rb +38 -0
  150. data/spec/rpm/spec/updater_spec.rb +486 -0
  151. data/spec/rpm/spec_spec.rb +27 -174
  152. data/spec/spec_helper.rb +7 -107
  153. data/spec/support/coveralls.rb +10 -0
  154. data/spec/support/fixtures.rb +8 -0
  155. data/spec/support/paths.rb +20 -0
  156. data/spec/support/rspec.rb +20 -0
  157. data/spec/support/vcr.rb +11 -0
  158. data/spec/{bodhi_spec.rb → targets/bodhi_spec.rb} +3 -1
  159. data/spec/{errata_spec.rb → targets/errata_spec.rb} +2 -2
  160. data/spec/{fedora_spec.rb → targets/fedora_spec.rb} +3 -3
  161. data/spec/targets/koji/builder_spec.rb +48 -0
  162. data/spec/targets/koji/diff_spec.rb +36 -0
  163. data/spec/targets/koji/rpc_spec.rb +28 -0
  164. data/spec/{koji_spec.rb → targets/koji/versions_spec.rb} +1 -59
  165. data/spec/targets/koji_spec.rb +11 -0
  166. data/spec/{yum_spec.rb → targets/yum_spec.rb} +1 -1
  167. data/spec/{component_spec.rb → util/component_spec.rb} +1 -1
  168. data/spec/{core_spec.rb → util/core_ext_spec.rb} +2 -3
  169. metadata +278 -88
  170. data/lib/polisher/bodhi.rb +0 -23
  171. data/lib/polisher/config.rb +0 -32
  172. data/lib/polisher/core.rb +0 -101
  173. data/lib/polisher/errata.rb +0 -75
  174. data/lib/polisher/fedora.rb +0 -46
  175. data/lib/polisher/git.rb +0 -8
  176. data/lib/polisher/koji.rb +0 -159
  177. data/lib/polisher/rhn.rb +0 -15
  178. data/lib/polisher/version_checker.rb +0 -177
  179. data/lib/polisher/yum.rb +0 -37
  180. data/spec/git_spec.rb +0 -445
@@ -0,0 +1,97 @@
1
+ # Polisher RPM Requirement Gem Comparison Mixin
2
+ #
3
+ # Licensed under the MIT license
4
+ # Copyright (C) 2013-2014 Red Hat, Inc.
5
+
6
+ module Polisher
7
+ module RPM
8
+ module RequirementComparison
9
+ def ==(other)
10
+ @br == other.br &&
11
+ @name == other.name &&
12
+ @condition == other.condition &&
13
+ @version == other.version
14
+ end
15
+
16
+ # Greatest Common Denominator,
17
+ # Max version in list that is less than the local version
18
+ def gcd(versions)
19
+ require 'versionomy'
20
+ lversion = Versionomy.parse(version)
21
+ versions.collect { |v| Versionomy.parse(v) }
22
+ .sort { |a, b| a <=> b }.reverse
23
+ .find { |v| v < lversion }.to_s
24
+ end
25
+
26
+ # Minimum gem version which satisfies this dependency
27
+ def min_satisfying_version
28
+ require 'versionomy'
29
+ return "0.0" if version.nil? ||
30
+ condition == '<' ||
31
+ condition == '<='
32
+ return version if condition == '=' ||
33
+ condition == '>='
34
+ Versionomy.parse(version).bump(:tiny).to_s # condition == '>'
35
+ end
36
+
37
+ # Max gem version which satisfies this dependency
38
+ #
39
+ # Can't automatically deduce in '<' case, so if that is the conditional
40
+ # we require a version list, and will return the gcd from it
41
+ def max_satisfying_version(versions = nil)
42
+ return Float::INFINITY if version.nil? ||
43
+ condition == '>' ||
44
+ condition == '>='
45
+ return version if condition == '=' ||
46
+ condition == '<='
47
+
48
+ raise ArgumentError if versions.nil?
49
+ gcd(versions)
50
+ end
51
+
52
+ # Minimum gem version for which this dependency fails
53
+ def min_failing_version
54
+ require 'versionomy'
55
+ raise ArgumentError if version.nil?
56
+ return "0.0" if condition == '>' ||
57
+ condition == '>='
58
+ return version if condition == '<'
59
+ Versionomy.parse(version).bump(:tiny).to_s # condition == '<=' and '='
60
+ end
61
+
62
+ # Max gem version for which this dependency fails
63
+ #
64
+ # Can't automatically deduce in '>=', and '=' cases, so if that is the
65
+ # conditional we require a version list, and will return the gcd from it
66
+ def max_failing_version(versions = nil)
67
+ raise ArgumentError if version.nil? ||
68
+ condition == '<=' ||
69
+ condition == '<'
70
+ return version if condition == '>'
71
+
72
+ raise ArgumentError if versions.nil?
73
+ gcd(versions)
74
+ end
75
+
76
+ # Return bool indicating if requirement matches specified
77
+ # depedency.
78
+ #
79
+ # Comparison mechanism will depend on type of class
80
+ # passed to this. Valid types include
81
+ # - Polisher::RPM::Requirements
82
+ # - ::Gem::Dependency
83
+ def matches?(dep)
84
+ require 'gem2rpm'
85
+
86
+ return self == dep if dep.is_a?(self.class)
87
+ raise ArgumentError unless dep.is_a?(::Gem::Dependency)
88
+
89
+ return false if !gem? || gem_name != dep.name
90
+ return true if version.nil?
91
+
92
+ Gem2Rpm::Helpers.expand_requirement([dep.requirement.to_s.split])
93
+ .any? { |req| req.first == condition && req.last.to_s == version }
94
+ end
95
+ end # module RequirementComparison
96
+ end # module RPM
97
+ end # module Polisher
@@ -0,0 +1,46 @@
1
+ # Polisher RPM Requirement Gem Reference Mixin
2
+ #
3
+ # Licensed under the MIT license
4
+ # Copyright (C) 2013-2014 Red Hat, Inc.
5
+
6
+ module Polisher
7
+ module RPM
8
+ module RequirementGemReference
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ # Instantiate / return new rpm spec requirements from gem dependency.
15
+ #
16
+ # Because a gem dependency may result in multiple spec requirements
17
+ # this will always return an array of Requirement instances
18
+ def from_gem_dep(gem_dep, br = false)
19
+ require 'gem2rpm'
20
+
21
+ gem_dep.requirement.to_s.split(',').collect do |req|
22
+ expanded = Gem2Rpm::Helpers.expand_requirement [req.split]
23
+ expanded.collect do |e|
24
+ new :name => "#{prefix}(#{gem_dep.name})",
25
+ :condition => e.first.to_s,
26
+ :version => e.last.to_s,
27
+ :br => br
28
+ end
29
+ end.flatten
30
+ end
31
+ end # module ClassMethods
32
+
33
+ # Whether or not this requirement specified a ruby gem dependency
34
+ def gem?
35
+ !!(str =~ RPM::Spec::SPEC_GEM_REQ_MATCHER)
36
+ end
37
+
38
+ # Return the name of the gem which this requirement is for.
39
+ # Returns nil if this is not a gem requirement
40
+ def gem_name
41
+ # XXX need to explicitly run regex here to get $1
42
+ !!(str =~ RPM::Spec::SPEC_GEM_REQ_MATCHER) ? $1 : nil
43
+ end
44
+ end # module RequirementGemReference
45
+ end # module RPM
46
+ end # module Polisher
@@ -0,0 +1,41 @@
1
+ # Polisher RPM Requirement Parser Mixin
2
+ #
3
+ # Licensed under the MIT license
4
+ # Copyright (C) 2013-2014 Red Hat, Inc.
5
+
6
+ module Polisher
7
+ module RPM
8
+ module RequirementParser
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ # Instantiate / return new rpm spec requirements from string
15
+ def parse(str, opts = {})
16
+ stra = str.split
17
+ br = str.include?('BuildRequires')
18
+ name = condition = version = nil
19
+
20
+ if str.include?('Requires')
21
+ name = stra[1]
22
+ condition = stra[2]
23
+ version = stra[3]
24
+
25
+ else
26
+ name = stra[0]
27
+ condition = stra[1]
28
+ version = stra[2]
29
+
30
+ end
31
+
32
+ req = new({:name => name,
33
+ :condition => condition,
34
+ :version => version,
35
+ :br => br}.merge(opts))
36
+ req
37
+ end
38
+ end # module ClassMethods
39
+ end # module RequirementParser
40
+ end # module RPM
41
+ end # module Polisher
@@ -3,443 +3,104 @@
3
3
  # Licensed under the MIT license
4
4
  # Copyright (C) 2013-2014 Red Hat, Inc.
5
5
 
6
- require 'polisher/core'
7
- require 'polisher/gem'
8
- require 'polisher/rpm/requirement'
9
- require 'polisher/component'
6
+ require 'polisher/rpm/spec/requirements'
7
+ require 'polisher/rpm/spec/files'
8
+ require 'polisher/rpm/spec/subpackages'
9
+ require 'polisher/rpm/spec/check'
10
10
 
11
- module Polisher
12
- deps = ['gem2rpm', 'versionomy', 'active_support', 'active_support/core_ext']
13
- Component.verify("RPM::Spec", *deps) do
14
- module RPM
15
- class Spec
16
- # RPM Spec Requirement Prefix
17
- def self.requirement_prefix
18
- Requirement.prefix
19
- end
20
-
21
- def requirement_prefix
22
- self.class.requirement_prefix
23
- end
24
-
25
- def self.package_prefix
26
- requirement_prefix
27
- end
28
-
29
- AUTHOR = "#{ENV['USER']} <#{ENV['USER']}@localhost.localdomain>"
30
-
31
- COMMENT_MATCHER = /^\s*#.*/
32
- GEM_NAME_MATCHER = /^%global\s*gem_name\s(.*)$/
33
- SPEC_NAME_MATCHER = /^Name:\s*#{package_prefix}-(.*)$/
34
- SPEC_VERSION_MATCHER = /^Version:\s*(.*)$/
35
- SPEC_RELEASE_MATCHER = /^Release:\s*(.*)$/
36
- SPEC_REQUIRES_MATCHER = /^Requires:\s*(.*)$/
37
- SPEC_BUILD_REQUIRES_MATCHER = /^BuildRequires:\s*(.*)$/
38
- SPEC_GEM_REQ_MATCHER = /^.*\s*#{requirement_prefix}\((.*)\)(\s*(.*))?$/
39
- SPEC_SUBPACKAGE_MATCHER = /^%package\s(.*)$/
40
- SPEC_CHANGELOG_MATCHER = /^%changelog$/
41
- SPEC_FILES_MATCHER = /^%files$/
42
- SPEC_SUBPKG_FILES_MATCHER = /^%files\s*(.*)$/
43
- SPEC_DOC_FILES_MATCHER = /^%files doc$/
44
- SPEC_CHECK_MATCHER = /^%check$/
45
-
46
- FILE_MACRO_MATCHERS =
47
- [/^%doc\s/, /^%config\s/, /^%attr\s/,
48
- /^%verify\s/, /^%docdir.*/, /^%dir\s/,
49
- /^%defattr.*/, /^%exclude\s/, /^%{gem_instdir}\/+/]
50
-
51
- FILE_MACRO_REPLACEMENTS =
52
- {"%{_bindir}" => 'bin',
53
- "%{gem_libdir}" => 'lib'}
54
-
55
- attr_accessor :metadata
56
-
57
- # Return the currently configured author
58
- def self.current_author
59
- ENV['POLISHER_AUTHOR'] || AUTHOR
60
- end
61
-
62
- def initialize(metadata={})
63
- @metadata = metadata
64
- end
65
-
66
- # Dispatch all missing methods to lookup calls in rpm spec metadata
67
- def method_missing(method, *args, &block)
68
- # proxy to metadata
69
- if @metadata.has_key?(method)
70
- @metadata[method]
71
-
72
- else
73
- super(method, *args, &block)
74
- end
75
- end
76
-
77
- # Return gem corresponding to spec name/version
78
- def upstream_gem
79
- @gem ||= Polisher::Gem.from_rubygems gem_name, version
80
- end
81
-
82
- # Return boolean indicating if spec has a %check section
83
- def has_check?
84
- @metadata.has_key?(:has_check) && @metadata[:has_check]
85
- end
86
-
87
- # Return all the Requires for the specified gem
88
- def requirements_for_gem(gem_name)
89
- @metadata[:requires].nil? ? [] :
90
- @metadata[:requires].select { |r| r.gem_name == gem_name }
91
- end
92
-
93
- # Return all the BuildRequires for the specified gem
94
- def build_requirements_for_gem(gem_name)
95
- @metadata[:build_requires].nil? ? [] :
96
- @metadata[:build_requires].select { |r| r.gem_name == gem_name }
97
- end
98
-
99
- # Return bool indicating if this spec specifies all the
100
- # requirements in the specified gem dependency
101
- #
102
- # @param [Gem::Dependency] gem_dep dependency which to retreive / compare
103
- # requirements
104
- def has_all_requirements_for?(gem_dep)
105
- reqs = self.requirements_for_gem gem_dep.name
106
- # create a spec requirement dependency for each expanded subrequirement,
107
- # verify we can find a match for that
108
- gem_dep.requirement.to_s.split(',').all? { |greq|
109
- Gem2Rpm::Helpers.expand_requirement([greq.split]).all? { |ereq|
110
- tereq = Requirement.new :name => "#{requirement_prefix}(#{gem_dep.name})",
111
- :condition => ereq.first,
112
- :version => ereq.last.to_s
113
- reqs.any? { |req| req.matches?(tereq)}
114
- }
115
- }
116
- end
117
-
118
- # Return list of gem dependencies for which we have no
119
- # corresponding requirements
120
- def missing_deps_for(gem)
121
- # Comparison by name here assuming if it is in existing spec,
122
- # spec author will have ensured versions are correct for their purposes
123
- gem.deps.select { |dep| requirements_for_gem(dep.name).empty? }
124
- end
125
-
126
- # Return list of gem dev dependencies for which we have
127
- # no corresponding requirements
128
- def missing_dev_deps_for(gem)
129
- # Same note as in #missing_deps_for above
130
- gem.dev_deps.select { |dep| build_requirements_for_gem(dep.name).empty? }
131
- end
132
-
133
- # Return list of dependencies of upstream gem which
134
- # have not been included
135
- def excluded_deps
136
- missing_deps_for(upstream_gem)
137
- end
138
-
139
- # Return boolean indicating if the specified gem is on excluded list
140
- def excludes_dep?(gem_name)
141
- excluded_deps.any? { |d| d.name == gem_name }
142
- end
143
-
144
- # Return list of dev dependencies of upstream gem which
145
- # have not been included
146
- def excluded_dev_deps
147
- missing_dev_deps_for(upstream_gem)
148
- end
149
-
150
- # Return boolean indicating if the specified gem is on
151
- # excluded dev dep list
152
- def excludes_dev_dep?(gem_name)
153
- excluded_dev_deps.any? { |d| d.name == gem_name }
154
- end
155
-
156
- # Return all gem Requires
157
- def gem_requirements
158
- @metadata[:requires].nil? ? [] :
159
- @metadata[:requires].select { |r| r.gem? }
160
- end
161
-
162
- # Return all gem BuildRequires
163
- def gem_build_requirements
164
- @metadata[:build_requires].nil? ? [] :
165
- @metadata[:build_requires].select { |r| r.gem? }
166
- end
167
-
168
- # Return all non gem Requires
169
- def non_gem_requirements
170
- @metadata[:requires].nil? ? [] :
171
- @metadata[:requires].select { |r| !r.gem? }
172
- end
173
-
174
- # Return all non gem BuildRequires
175
- def non_gem_build_requirements
176
- @metadata[:build_requires].nil? ? [] :
177
- @metadata[:build_requires].select { |r| !r.gem? }
178
- end
179
-
180
- # Return all gem requirements _not_ in the specified gem
181
- def extra_gem_requirements(gem)
182
- gem_reqs = gem.deps.collect { |d| requirements_for_gem(d.name) }.flatten
183
- gem_requirements - gem_reqs
184
- end
185
-
186
- # Return all gem build requirements _not_ in the specified gem
187
- def extra_gem_build_requirements(gem)
188
- gem_reqs = gem.deps.collect { |d| requirements_for_gem(d.name) }.flatten
189
- gem_build_requirements - gem_reqs
190
- end
191
-
192
- # Parse the specified rpm spec and return new RPM::Spec instance from metadata
193
- #
194
- # @param [String] string contents of spec to parse
195
- # @return [Polisher::RPM::Spec] spec instantiated from rpmspec metadata
196
- def self.parse(spec)
197
- in_subpackage = false
198
- in_changelog = false
199
- in_files = false
200
- subpkg_name = nil
201
- meta = {:contents => spec}
202
- spec.each_line { |l|
203
- if l =~ COMMENT_MATCHER
204
- ;
205
-
206
- # TODO support optional gem prefix
207
- elsif l =~ GEM_NAME_MATCHER
208
- meta[:gem_name] = $1.strip
209
- meta[:gem_name] = $1.strip
210
-
211
- elsif l =~ SPEC_NAME_MATCHER &&
212
- $1.strip != "%{gem_name}"
213
- meta[:gem_name] = $1.strip
214
-
215
- elsif l =~ SPEC_VERSION_MATCHER
216
- meta[:version] = $1.strip
217
-
218
- elsif l =~ SPEC_RELEASE_MATCHER
219
- meta[:release] = $1.strip
220
-
221
- elsif l =~ SPEC_SUBPACKAGE_MATCHER
222
- subpkg_name = $1.strip
223
- in_subpackage = true
224
-
225
- elsif l =~ SPEC_REQUIRES_MATCHER &&
226
- !in_subpackage
227
- meta[:requires] ||= []
228
- meta[:requires] << RPM::Requirement.parse($1.strip)
229
-
230
- elsif l =~ SPEC_BUILD_REQUIRES_MATCHER &&
231
- !in_subpackage
232
- meta[:build_requires] ||= []
233
- meta[:build_requires] << RPM::Requirement.parse($1.strip)
234
-
235
- elsif l =~ SPEC_CHANGELOG_MATCHER
236
- in_changelog = true
237
-
238
- elsif l =~ SPEC_FILES_MATCHER
239
- subpkg_name = nil
240
- in_files = true
241
-
242
- elsif l =~ SPEC_SUBPKG_FILES_MATCHER
243
- subpkg_name = $1.strip
244
- in_files = true
245
-
246
- elsif l =~ SPEC_CHECK_MATCHER
247
- meta[:has_check] = true
248
-
249
- elsif in_changelog
250
- meta[:changelog] ||= ""
251
- meta[:changelog] << l
11
+ require 'polisher/rpm/spec/updater'
12
+ require 'polisher/rpm/spec/parser'
13
+ require 'polisher/rpm/spec/comparison'
252
14
 
253
- elsif in_files
254
- tgt = subpkg_name.nil? ? meta[:gem_name] : subpkg_name
255
- meta[:files] ||= {}
256
- meta[:files][tgt] ||= []
15
+ require 'polisher/rpm/spec/gem_files'
16
+ require 'polisher/rpm/spec/gem_reference'
17
+ require 'polisher/rpm/spec/gem_requirements'
257
18
 
258
- sl = l.strip.unrpmize
259
- meta[:files][tgt] << sl unless sl.blank?
260
- end
261
- }
262
-
263
- meta[:changelog_entries] = meta[:changelog] ?
264
- meta[:changelog].split("\n\n") : []
265
- meta[:changelog_entries].collect! { |c| c.strip }.compact!
266
-
267
- self.new meta
268
- end
269
-
270
- # Update RPM::Spec metadata to new gem
271
- #
272
- # @param [Polisher::Gem] new_source new gem to update rpmspec to
273
- def update_to(new_source)
274
- update_deps_from(new_source)
275
- update_files_from(new_source)
276
- update_metadata_from(new_source)
277
- end
278
-
279
- private
280
-
281
- # Update spec dependencies from new source
282
- def update_deps_from(new_source)
283
- @metadata[:requires] =
284
- non_gem_requirements +
285
- extra_gem_requirements(new_source) +
286
- new_source.deps.select { |r| !excludes_dep?(r.name) }
287
- .collect { |r| RPM::Requirement.from_gem_dep(r) }.flatten
288
-
289
- @metadata[:build_requires] =
290
- non_gem_build_requirements +
291
- extra_gem_build_requirements(new_source) +
292
- new_source.dev_deps.select { |r| !excludes_dev_dep?(r.name) }
293
- .collect { |r| RPM::Requirement.from_gem_dep(r, true) }.flatten
294
- end
295
-
296
- # Internal helper to update spec files from new source
297
- def update_files_from(new_source)
298
- to_add = new_source.file_paths
299
- @metadata[:files] ||= {}
300
- @metadata[:files].each { |pkg,spec_files|
301
- (new_source.file_paths & to_add).each { |gem_file|
302
- # skip files already included in spec or in dir in spec
303
- has_file = spec_files.any? { |sf|
304
- gem_file.gsub(sf,'') != gem_file
305
- }
306
-
307
- to_add.delete(gem_file)
308
- to_add << gem_file.rpmize if !has_file &&
309
- !Gem.ignorable_file?(gem_file)
310
- }
311
- }
312
-
313
- @metadata[:new_files] = to_add.select { |f| !Gem.doc_file?(f) }
314
- @metadata[:new_docs] = to_add - @metadata[:new_files]
315
- end
316
-
317
- # Internal helper to update spec metadata from new source
318
- def update_metadata_from(new_source)
319
- # update to new version
320
- @metadata[:version] = new_source.version
321
- @metadata[:release] = "1%{?dist}"
322
-
323
- # add changelog entry
324
- changelog_entry = <<EOS
325
- * #{Time.now.strftime("%a %b %d %Y")} #{RPM::Spec.current_author} - #{@metadata[:version]}-1
326
- - Update to version #{new_source.version}
327
- EOS
328
- @metadata[:changelog_entries] ||= []
329
- @metadata[:changelog_entries].unshift changelog_entry.rstrip
330
- end
331
-
332
- public
333
-
334
- # Return properly formatted rpmspec as string
335
- #
336
- # @return [String] string representation of rpm spec
337
- def to_string
338
- contents = @metadata[:contents]
339
-
340
- # replace version / release
341
- contents.gsub!(SPEC_VERSION_MATCHER, "Version: #{@metadata[:version]}")
342
- contents.gsub!(SPEC_RELEASE_MATCHER, "Release: #{@metadata[:release]}")
343
-
344
- # add changelog entry
345
- cp = contents.index SPEC_CHANGELOG_MATCHER
346
- cpn = contents.index "\n", cp
347
- contents = contents[0...cpn+1] +
348
- @metadata[:changelog_entries].join("\n\n")
349
-
350
- # update requires/build requires
351
- rp = contents.index SPEC_REQUIRES_MATCHER
352
- brp = contents.index SPEC_BUILD_REQUIRES_MATCHER
353
- tp = rp < brp ? rp : brp
354
-
355
- pp = contents.index SPEC_SUBPACKAGE_MATCHER
356
- pp = -1 if pp.nil?
357
-
358
- lrp = contents.rindex SPEC_REQUIRES_MATCHER, pp
359
- lbrp = contents.rindex SPEC_BUILD_REQUIRES_MATCHER, pp
360
- ltp = lrp > lbrp ? lrp : lbrp
361
-
362
- ltpn = contents.index "\n", ltp
363
-
364
- contents.slice!(tp...ltpn)
365
- contents.insert tp,
366
- (@metadata[:requires].collect { |r| "Requires: #{r.str}" } +
367
- @metadata[:build_requires].collect { |r| "BuildRequires: #{r.str}" }).join("\n")
368
-
369
- # add new files
370
- fp = contents.index SPEC_FILES_MATCHER
371
- lfp = contents.index SPEC_SUBPKG_FILES_MATCHER, fp + 1
372
- lfp = contents.index SPEC_CHANGELOG_MATCHER if lfp.nil?
373
-
374
- contents.insert lfp - 1, @metadata[:new_files].join("\n") + "\n"
375
-
376
- # add new doc files
377
- fp = contents.index SPEC_DOC_FILES_MATCHER
378
- fp = contents.index SPEC_FILES_MATCHER if fp.nil?
379
- lfp = contents.index SPEC_SUBPKG_FILES_MATCHER, fp + 1
380
- lfp = contents.index SPEC_CHANGELOG_MATCHER if lfp.nil?
381
-
382
- contents.insert lfp - 1, @metadata[:new_docs].join("\n") + "\n"
383
-
384
- # return new contents
385
- contents
386
- end
387
-
388
- # Compare this spec to a sepecified upstream gem source
389
- # and return result.
390
- #
391
- # upstream_source should be an instance of Polisher::Gem,
392
- # Polisher::Gemfile, or other class defining a 'deps'
393
- # accessor that returns an array of Gem::Requirement dependencies
394
- #
395
- # Result will be a hash containing the shared dependencies as
396
- # well as those that differ and their respective differences
397
- def compare(upstream_source)
398
- same = {}
399
- diff = {}
400
- upstream_source.deps.each do |d|
401
- spec_reqs = self.requirements_for_gem(d.name)
402
- spec_reqs_specifier = spec_reqs.empty? ? nil :
403
- spec_reqs.collect { |req| req.specifier }
404
-
405
- if spec_reqs.nil?
406
- diff[d.name] = {:spec => nil,
407
- :upstream => d.requirement.to_s}
408
-
409
- elsif !spec_reqs.any? { |req| req.matches?(d) } ||
410
- !self.has_all_requirements_for?(d)
411
- diff[d.name] = {:spec => spec_reqs_specifier,
412
- :upstream => d.requirement.to_s}
413
-
414
- elsif !diff.has_key?(d.name)
415
- same[d.name] = {:spec => spec_reqs_specifier,
416
- :upstream => d.requirement.to_s }
417
- end
418
- end
419
-
420
- @metadata[:requires].each do |req|
421
- next unless req.gem?
422
-
423
- upstream_dep = upstream_source.deps.find { |d| d.name == req.gem_name }
424
-
425
- if upstream_dep.nil?
426
- diff[req.gem_name] = {:spec => req.specifier,
427
- :upstream => nil}
428
-
429
- elsif !req.matches?(upstream_dep)
430
- diff[req.gem_name] = {:spec => req.specifier,
431
- :upstream => upstream_dep.requirement.to_s }
432
-
433
- elsif !diff.has_key?(req.gem_name)
434
- same[req.gem_name] = {:spec => req.specifier,
435
- :upstream => upstream_dep.requirement.to_s }
436
- end
437
- end unless @metadata[:requires].nil?
438
-
439
- {:same => same, :diff => diff}
440
- end
441
-
442
- end # class Spec
443
- end # module RPM
444
- end # Component.verify("RPM::Spec")
19
+ module Polisher
20
+ module RPM
21
+ class Spec
22
+ include SpecRequirements
23
+ include SpecFiles
24
+ include SpecSubpackages
25
+ include SpecCheck
26
+
27
+ include SpecUpdater
28
+ include SpecParser
29
+ include SpecComparison
30
+
31
+ # TODO: make these mixins optional depending on if rpm corresponds to gem
32
+ include SpecGemFiles
33
+ include SpecGemReference
34
+ include SpecGemRequirements
35
+
36
+ AUTHOR = "#{ENV['USER']} <#{ENV['USER']}@localhost.localdomain>"
37
+
38
+ # metadata keys parsed
39
+ # @see [Polisher::RPM::SpecParser::ClassMethods#parse]
40
+ METADATA_IDS = [:contents, :gem_name, :version, :release,
41
+ :requires, :build_requires, :has_check, :changelog,
42
+ :pkg_excludes, :pkg_files, :changelog_entries]
43
+
44
+ COMMENT_MATCHER = /^\s*#.*/
45
+ GEM_NAME_MATCHER = /^%global\s*gem_name\s(.*)$/
46
+ SPEC_NAME_MATCHER = /^Name:\s*#{package_prefix}-(.*)$/
47
+ SPEC_VERSION_MATCHER = /^Version:\s*(.*)$/
48
+ SPEC_RELEASE_MATCHER = /^Release:\s*(.*)$/
49
+ SPEC_REQUIRES_MATCHER = /^Requires:\s*(.*)$/
50
+ SPEC_BUILD_REQUIRES_MATCHER = /^BuildRequires:\s*(.*)$/
51
+ SPEC_GEM_REQ_MATCHER = /^.*\s*#{requirement_prefix}\((.*)\)(\s*(.*))?$/
52
+ SPEC_SUBPACKAGE_MATCHER = /^%package\s(.*)$/
53
+ SPEC_DOC_SUBPACKAGE_MATCHER = /^%package\sdoc$/
54
+ SPEC_CHANGELOG_MATCHER = /^%changelog$/
55
+ SPEC_FILES_MATCHER = /^%files$/
56
+ SPEC_SUBPKG_FILES_MATCHER = /^%files\s*(.*)$/
57
+ SPEC_EXCLUDED_FILE_MATCHER = /^%exclude\s+(.*)$/
58
+ SPEC_PREP_MATCHER = /^%prep$/
59
+ SPEC_CHECK_MATCHER = /^%check$/
60
+ SPEC_DESCRIPTION_MATCHER = /^%description$/
61
+
62
+ FILE_MACRO_MATCHERS =
63
+ [/^%doc\s/, /^%config\s/, /^%attr\s/,
64
+ /^%verify\s/, /^%docdir.*/, /^%dir\s/, /^%defattr.*/,
65
+ /^%{gem_instdir}\/+/, /^%{gem_cache}/, /^%{gem_spec}/, /^%{gem_docdir}/]
66
+
67
+ FILE_MACRO_REPLACEMENTS =
68
+ {"%{_bindir}" => 'bin', "%{gem_libdir}" => 'lib'}
69
+
70
+ attr_accessor :metadata
71
+
72
+ def initialize(metadata = nil)
73
+ @metadata = self.class.default_metadata.merge(metadata || {})
74
+ end
75
+
76
+ # Dispatch all missing methods to lookup calls in rpm spec metadata
77
+ def method_missing(method, *args, &block)
78
+ # proxy to metadata
79
+ return @metadata[method] if @metadata.key?(method)
80
+
81
+ # return nil if metadata value not set
82
+ return nil if METADATA_IDS.include?(method)
83
+
84
+ # set value if invoking metadata setter
85
+ id = method[0...-1].intern if method[-1] == '='
86
+ metadata_setter = METADATA_IDS.include?(id) && args.length == 1
87
+ return @metadata[id] = args.first if metadata_setter
88
+
89
+ # dispatch to default behaviour
90
+ super(method, *args, &block)
91
+ end
92
+
93
+ # Return contents of spec as string
94
+ #
95
+ # @return [String] string representation of rpm spec
96
+ def to_string
97
+ contents
98
+ end
99
+
100
+ # Return length of contents
101
+ def length
102
+ contents.length
103
+ end
104
+ end # class Spec
105
+ end # module RPM
445
106
  end # module Polisher