Class: Pod::Installer::PodfileValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/cocoapods/installer/podfile_validator.rb

Overview

Validate the podfile before installing to catch errors and problems

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(podfile, podfile_dependency_cache = Analyzer::PodfileDependencyCache.from_podfile(podfile)) ⇒ PodfileValidator

Initialize a new instance

Parameters:

  • podfile (Podfile)

    The podfile to validate

  • podfile_dependency_cache (Analyzer::PodfileDependencyCache) (defaults to: Analyzer::PodfileDependencyCache.from_podfile(podfile))

    An (optional) cache of all the dependencies in the podfile


27
28
29
30
31
32
33
# File 'lib/cocoapods/installer/podfile_validator.rb', line 27

def initialize(podfile, podfile_dependency_cache = Analyzer::PodfileDependencyCache.from_podfile(podfile))
  @podfile = podfile
  @podfile_dependency_cache = podfile_dependency_cache
  @errors = []
  @warnings = []
  @validated = false
end

Instance Attribute Details

#errorsArray<String> (readonly)

Returns any errors that have occured during the validation.

Returns:

  • (Array<String>)

    any errors that have occured during the validation


13
14
15
# File 'lib/cocoapods/installer/podfile_validator.rb', line 13

def errors
  @errors
end

#podfilePodfile (readonly)

Returns The podfile being validated.

Returns:

  • (Podfile)

    The podfile being validated


9
10
11
# File 'lib/cocoapods/installer/podfile_validator.rb', line 9

def podfile
  @podfile
end

#warningsArray<String> (readonly)

Returns any warnings that have occured during the validation.

Returns:

  • (Array<String>)

    any warnings that have occured during the validation


17
18
19
# File 'lib/cocoapods/installer/podfile_validator.rb', line 17

def warnings
  @warnings
end

Instance Method Details

#add_error(error) ⇒ Object (private)


67
68
69
# File 'lib/cocoapods/installer/podfile_validator.rb', line 67

def add_error(error)
  errors << error
end

#add_warning(warning) ⇒ Object (private)


71
72
73
# File 'lib/cocoapods/installer/podfile_validator.rb', line 71

def add_warning(warning)
  warnings << warning
end

#messageObject

A message describing any errors in the validation


61
62
63
# File 'lib/cocoapods/installer/podfile_validator.rb', line 61

def message
  errors.join("\n")
end

#target_definition_inherits?(parent: nil, child: nil) ⇒ Boolean (private)

Returns:

  • (Boolean)

147
148
149
150
151
152
153
154
155
# File 'lib/cocoapods/installer/podfile_validator.rb', line 147

def target_definition_inherits?(parent: nil, child: nil)
  if parent == child
    true
  elsif child.exclusive?
    false
  else
    target_definition_inherits?(:parent => parent, :child => child.parent)
  end
end

#valid?Boolean

Wether the podfile is valid is not NOTE: Will execute validate if the podfile has not yet been validated

Returns:

  • (Boolean)

52
53
54
55
56
# File 'lib/cocoapods/installer/podfile_validator.rb', line 52

def valid?
  validate unless @validated

  @validated && errors.empty?
end

#validateObject

Validate the podfile Errors are added to the errors array


38
39
40
41
42
43
44
45
46
# File 'lib/cocoapods/installer/podfile_validator.rb', line 38

def validate
  validate_installation_options
  validate_pod_directives
  validate_no_abstract_only_pods!
  validate_dependencies_are_present!
  validate_no_duplicate_targets!

  @validated = true
end

#validate_conflicting_external_sources!(dependency) ⇒ Object (private)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/cocoapods/installer/podfile_validator.rb', line 89

def validate_conflicting_external_sources!(dependency)
  external_source = dependency.external_source
  return false if external_source.nil?

  available_downloaders = Downloader.downloader_class_by_key.keys
  specified_downloaders = external_source.select { |key| available_downloaders.include?(key) }
  if specified_downloaders.size > 1
    add_error "The dependency `#{dependency.name}` specifies more than one download strategy(#{specified_downloaders.keys.join(',')})." \
      'Only one is allowed'
  end

  pod_spec_or_path = external_source[:podspec].present? || external_source[:path].present?
  if pod_spec_or_path && specified_downloaders.size > 0
    add_error "The dependency `#{dependency.name}` specifies `podspec` or `path` in combination with other" \
      ' download strategies. This is not allowed'
  end
end

#validate_dependencies_are_present!void (private)

Note:

The workspace is created in any case and all the user projects are added to it, however the projects are not integrated as there is no way to discern between target definitions which are empty and target definitions which just serve the purpose to wrap other ones. This is not an issue because empty target definitions generate empty libraries.

This method returns an undefined value.

Warns the user if the podfile is empty.


118
119
120
121
122
# File 'lib/cocoapods/installer/podfile_validator.rb', line 118

def validate_dependencies_are_present!
  if @podfile_dependency_cache.target_definition_list.all?(&:empty?)
    add_warning 'The Podfile does not contain any dependencies.'
  end
end

#validate_installation_optionsObject (private)


75
76
77
78
79
80
81
# File 'lib/cocoapods/installer/podfile_validator.rb', line 75

def validate_installation_options
  installation_options = podfile.installation_options

  # Validate `incremental_installation` depends on `generate_multiple_pod_projects`
  invalid = installation_options.incremental_installation? && installation_options.incremental_installation != installation_options.generate_multiple_pod_projects
  add_error 'The installation option `incremental_installation` requires the option `generate_multiple_pod_projects` to also be enabled.' if invalid
end

#validate_no_abstract_only_pods!Object (private)

Verifies that no dependencies in the Podfile will end up not being built at all. In other words, all dependencies should belong to a non-abstract target, or be inherited by a target where inheritance == complete.


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/cocoapods/installer/podfile_validator.rb', line 128

def validate_no_abstract_only_pods!
  @podfile_dependency_cache.target_definition_list.each do |target_definition|
    dependencies = @podfile_dependency_cache.target_definition_dependencies(target_definition)
    next if dependencies.empty?
    next unless target_definition.abstract?

    children = target_definition.recursive_children
    next if children.any? { |child_target_definition| target_definition_inherits?(:parent => target_definition, :child => child_target_definition) }

    add_warning "The abstract target #{target_definition.name} is not inherited by a concrete target, " \
      "so the following dependencies won't make it into any targets in your project:" \
      "\n    - #{dependencies.map(&:to_s).sort.join("\n    - ")}"

    next if target_definition.platform

    add_error "The abstract target #{target_definition.name} must specify a platform since its dependencies are not inherited by a concrete target."
  end
end

#validate_no_duplicate_targets!Object (private)


157
158
159
160
161
162
163
164
165
# File 'lib/cocoapods/installer/podfile_validator.rb', line 157

def validate_no_duplicate_targets!
  @podfile_dependency_cache.target_definition_list.group_by { |td| [td.name, td.user_project_path] }.
    each do |(name, project), definitions|
    next unless definitions.size > 1
    error = "The target `#{name}` is declared multiple times"
    error << " for the project `#{project}`" if project
    add_error(error << '.')
  end
end

#validate_pod_directivesObject (private)


83
84
85
86
87
# File 'lib/cocoapods/installer/podfile_validator.rb', line 83

def validate_pod_directives
  @podfile_dependency_cache.podfile_dependencies.each do |dependency|
    validate_conflicting_external_sources!(dependency)
  end
end