Class: Gem::SpecificationPolicy

Inherits:
Object
  • Object
show all
Includes:
UserInteraction
Defined in:
lib/rubygems/specification_policy.rb

Constant Summary collapse

VALID_NAME_PATTERN =

:nodoc:

/\A[a-zA-Z0-9\.\-\_]+\z/.freeze
SPECIAL_CHARACTERS =

:nodoc:

/\A[#{Regexp.escape('.-_')}]+/.freeze
VALID_URI_PATTERN =

:nodoc:

%r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}.freeze
%w[
  bug_tracker_uri
  changelog_uri
  documentation_uri
  homepage_uri
  mailing_list_uri
  source_code_uri
  wiki_uri
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from UserInteraction

#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction, #verbose

Methods included from DefaultUserInteraction

ui, #ui, ui=, #ui=, use_ui, #use_ui

Methods included from Text

#clean_text, #format_text, #levenshtein_distance, #min3, #truncate_text

Constructor Details

#initialize(specification) ⇒ SpecificationPolicy

:nodoc:



23
24
25
26
27
# File 'lib/rubygems/specification_policy.rb', line 23

def initialize(specification)
  @warnings = 0

  @specification = specification
end

Instance Attribute Details

#packagingObject

If set to true, run packaging-specific checks, as well.



32
33
34
# File 'lib/rubygems/specification_policy.rb', line 32

def packaging
  @packaging
end

Instance Method Details

#validate(strict = false) ⇒ Object

Checks that the specification contains all required fields, and does a very basic sanity check.

Raises InvalidSpecificationException if the spec does not pass the checks.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rubygems/specification_policy.rb', line 41

def validate(strict = false)
  validate_nil_attributes

  validate_rubygems_version

  validate_required_attributes

  validate_name

  validate_require_paths

  @specification.keep_only_files_and_directories

  validate_non_files

  validate_self_inclusion_in_files_list

  validate_specification_version

  validate_platform

  validate_array_attributes

  validate_authors_field

  

  validate_licenses

  validate_permissions

  

  validate_values

  validate_dependencies

  validate_removed_attributes

  if @warnings > 0
    if strict
      error "specification has warnings"
    else
      alert_warning help_text
    end
  end

  true
end

#validate_dependenciesObject

Implementation for Specification#validate_dependencies



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/rubygems/specification_policy.rb', line 129

def validate_dependencies # :nodoc:
  # NOTE: see REFACTOR note in Gem::Dependency about types - this might be brittle
  seen = Gem::Dependency::TYPES.inject({}) { |types, type| types.merge({ type => {}}) }

  error_messages = []
  warning_messages = []
  @specification.dependencies.each do |dep|
    if prev = seen[dep.type][dep.name]
      error_messages << "duplicate dependency on \#{dep}, (\#{prev.requirement}) use:\n  add_\#{dep.type}_dependency '\#{dep.name}', '\#{dep.requirement}', '\#{prev.requirement}'\n      MESSAGE\n    end\n\n    seen[dep.type][dep.name] = dep\n\n    prerelease_dep = dep.requirements_list.any? do |req|\n      Gem::Requirement.new(req).prerelease?\n    end\n\n    warning_messages << \"prerelease dependency on \#{dep} is not recommended\" if\n        prerelease_dep && [email protected]?\n\n    open_ended = dep.requirement.requirements.all? do |op, version|\n      not version.prerelease? and (op == '>' or op == '>=')\n    end\n\n    if open_ended\n      op, dep_version = dep.requirement.requirements.first\n\n      segments = dep_version.segments\n\n      base = segments.first 2\n\n      recommendation = if (op == '>' || op == '>=') && segments == [0]\n                         \"  use a bounded requirement, such as '~> x.y'\"\n                       else\n                         bugfix = if op == '>'\n                                    \", '> \#{dep_version}'\"\n                                  elsif op == '>=' and base != segments\n                                    \", '>= \#{dep_version}'\"\n                                  end\n\n                         \"  if \#{dep.name} is semantically versioned, use:\\n\" \\\n                         \"    add_\#{dep.type}_dependency '\#{dep.name}', '~> \#{base.join '.'}'\#{bugfix}\"\n                       end\n\n      warning_messages << [\"open-ended dependency on \#{dep} is not recommended\", recommendation].join(\"\\n\") + \"\\n\"\n    end\n  end\n  if error_messages.any?\n    error error_messages.join\n  end\n  if warning_messages.any?\n    warning_messages.each { |warning_message| warning warning_message }\n  end\nend\n"

#validate_metadataObject

Implementation for Specification#validate_metadata



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/rubygems/specification_policy.rb', line 94

def 
   = @specification.

  unless Hash === 
    error 'metadata must be a hash'
  end

  .each do |key, value|
    if !key.kind_of?(String)
      error "metadata keys must be a String"
    end

    if key.size > 128
      error "metadata key too large (#{key.size} > 128)"
    end

    if !value.kind_of?(String)
      error "metadata values must be a String"
    end

    if value.size > 1024
      error "metadata value too large (#{value.size} > 1024)"
    end

    if .include? key
      if value !~ VALID_URI_PATTERN
        error "metadata['#{key}'] has invalid link: #{value.inspect}"
      end
    end
  end
end

#validate_permissionsObject

Issues a warning for each file to be packaged which is world-readable.

Implementation for Specification#validate_permissions



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/rubygems/specification_policy.rb', line 192

def validate_permissions
  return if Gem.win_platform?

  @specification.files.each do |file|
    next unless File.file?(file)
    next if File.stat(file).mode & 0444 == 0444
    warning "#{file} is not world-readable"
  end

  @specification.executables.each do |name|
    exec = File.join @specification.bindir, name
    next unless File.file?(exec)
    next if File.stat(exec).executable?
    warning "#{exec} is not executable"
  end
end