Class: Pod::Command::Generator
- Inherits:
-
Pod::Command
- Object
- Pod::Command
- Pod::Command::Generator
- Defined in:
- lib/cocoapods-generator/command/generator.rb
Overview
This is an example of a cocoapods plugin adding a top-level subcommand to the ‘pod’ command.
You can also create subcommands of existing or new commands. Say you wanted to add a subcommand to ‘list` to show newly deprecated pods, (e.g. `pod list deprecated`), there are a few things that would need to change.
-
move this file to ‘lib/pod/command/list/deprecated.rb` and update the class to exist in the the Pod::Command::List namespace
-
change this class to extend from ‘List` instead of `Command`. This tells the plugin system that it is a subcommand of `list`.
-
edit ‘lib/cocoapods_plugins.rb` to require this file
Constant Summary collapse
- SPEC_SUBGROUPS =
{ :resources => 'Resources', :frameworks => 'Frameworks', }
- ENABLE_OBJECT_USE_OBJC_FROM =
{ :ios => Version.new('6'), :osx => Version.new('10.8'), :watchos => Version.new('2.0'), :tvos => Version.new('9.0'), }
- SOURCE_FILE_EXTENSIONS =
Sandbox::FileAccessor::SOURCE_FILE_EXTENSIONS
Instance Method Summary collapse
- #add_file_accessors_paths_to_group(file_accessor_key, group_key = nil) ⇒ Object
- #add_files_to_build_phases ⇒ Object
- #add_framework_target_to_Xcodeproject ⇒ Object
- #add_frameworks_bundles ⇒ Object
- #add_header(build_file, public_headers, private_headers) ⇒ Object
- #add_libraries_to_build_phases ⇒ Object
- #add_resources ⇒ Object
- #add_source_files_references ⇒ Object
- #add_vendored_libraries ⇒ Object
- #add_vendored_library_to_build_phases(sourcekey) ⇒ Object
- #allowable_project_paths(paths) ⇒ Object
- #compiler_flags_for_consumer(consumer, arc) ⇒ Object
- #create_file_accessors ⇒ Object
- #create_spec_content ⇒ Object
- #group_for_spec(spec_name, subgroup_key = nil) ⇒ Object
- #header_mappings_dir ⇒ Object
-
#initialize(argv) ⇒ Generator
constructor
A new instance of Generator.
- #install ⇒ Object
- #results_message(results) ⇒ Object
- #run ⇒ Object
- #validate! ⇒ Object
- #validatePodspec ⇒ Object
- #xcodeproj_path ⇒ Object
Constructor Details
#initialize(argv) ⇒ Generator
Returns a new instance of Generator.
46 47 48 49 50 51 |
# File 'lib/cocoapods-generator/command/generator.rb', line 46 def initialize(argv) @spec_name = argv.shift_argument @current_path = Dir.pwd @spec_path = @current_path + '/' + @spec_name if @current_path && @spec_name super end |
Instance Method Details
#add_file_accessors_paths_to_group(file_accessor_key, group_key = nil) ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/cocoapods-generator/command/generator.rb', line 183 def add_file_accessors_paths_to_group(file_accessor_key, group_key = nil) @file_accessors.each do |file_accessor| pod_name = file_accessor.spec.name paths = file_accessor.send(file_accessor_key) paths = allowable_project_paths(paths) paths.each do |path| if !@app_project.reference_for_path(path) relative_pathname = path.relative_path_from(Pathname.new(@current_path)) relative_dir = relative_pathname.dirname lproj_regex = /\.lproj/i group = group_for_spec(file_accessor.spec.name, group_key) relative_dir.each_filename do|name| break if name.to_s =~ lproj_regex next if name == '.' group = group[name] || group.new_group(name) end file_path_name = path.is_a?(Pathname) ? path : Pathname.new(path) ref = group.new_file(file_path_name.realpath) end end end end |
#add_files_to_build_phases ⇒ Object
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/cocoapods-generator/command/generator.rb', line 258 def add_files_to_build_phases @file_accessors.each do |file_accessor| consumer = file_accessor.spec_consumer headers = file_accessor.headers public_headers = file_accessor.public_headers private_headers = file_accessor.private_headers other_source_files = file_accessor.source_files.reject { |sf| SOURCE_FILE_EXTENSIONS.include?(sf.extname) } { true => file_accessor.arc_source_files, false => file_accessor.non_arc_source_files, }.each do |arc, files| files = files - headers - other_source_files flags = compiler_flags_for_consumer(consumer, arc) regular_file_refs = files.map { |sf| @app_project.reference_for_path(sf) } @framework_target.add_file_references(regular_file_refs, flags) end header_file_refs = headers.map { |sf| @app_project.reference_for_path(sf) } @framework_target.add_file_references(header_file_refs) do |build_file| add_header(build_file, public_headers, private_headers) end other_file_refs = other_source_files.map { |sf| @app_project.reference_for_path(sf) } @framework_target.add_file_references(other_file_refs, nil) resource_refs = file_accessor.resources.flatten.map do |res| @app_project.reference_for_path(res) end # Some nested files are not directly present in the Xcode project, such as the contents # of an .xcdatamodeld directory. These files will return nil file references. resource_refs.compact! @framework_target.add_resources(resource_refs) end end |
#add_framework_target_to_Xcodeproject ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/cocoapods-generator/command/generator.rb', line 122 def add_framework_target_to_Xcodeproject project_path = xcodeproj_path podspec_consumer = consumer platform_name = consumer.platform_name deployment_target = podspec_consumer.spec.deployment platform_name target_name = @spec_name app_project = xcodeproj::Project.open project_path app_project.new_target('static_framework', target_name, platform_name, deployment_target) app_project.save app_project.recreate_user_schemes Xcodeproj::XCScheme.share_scheme(app_project.path, target_name) end |
#add_frameworks_bundles ⇒ Object
170 171 172 |
# File 'lib/cocoapods-generator/command/generator.rb', line 170 def add_frameworks_bundles add_file_accessors_paths_to_group(:vendored_frameworks, :frameworks) end |
#add_header(build_file, public_headers, private_headers) ⇒ Object
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
# File 'lib/cocoapods-generator/command/generator.rb', line 318 def add_header(build_file, public_headers, private_headers) file_ref = build_file.file_ref acl = if public_headers.include?(file_ref.real_path) 'Public' elsif private_headers.include?(file_ref.real_path) 'Private' else 'Project' end if header_mappings_dir && acl != 'Project' relative_path = file_ref.real_path.relative_path_from(header_mappings_dir) sub_dir = relative_path.dirname copy_phase_name = "Copy #{sub_dir} #{acl} Headers" copy_phase = native_target.copy_files_build_phases.find { |bp| bp.name == copy_phase_name } || native_target.new_copy_files_build_phase(copy_phase_name) copy_phase.symbol_dst_subfolder_spec = :products_directory copy_phase.dst_path = "$(#{acl.upcase}_HEADERS_FOLDER_PATH)/#{sub_dir}" copy_phase.add_file_reference(file_ref, true) else build_file.settings ||= {} build_file.settings['ATTRIBUTES'] = [acl] end end |
#add_libraries_to_build_phases ⇒ Object
297 298 299 300 301 302 303 304 |
# File 'lib/cocoapods-generator/command/generator.rb', line 297 def add_libraries_to_build_phases file_accessor = @file_accessors.first @framework_target.add_system_framework(file_accessor.spec_consumer.frameworks) @framework_target.add_system_library(file_accessor.spec_consumer.libraries) add_vendored_library_to_build_phases(:vendored_frameworks) add_vendored_library_to_build_phases(:vendored_libraries) end |
#add_resources ⇒ Object
178 179 180 181 |
# File 'lib/cocoapods-generator/command/generator.rb', line 178 def add_resources add_file_accessors_paths_to_group(:resources, :resources) add_file_accessors_paths_to_group(:resource_bundle_files, :resources) end |
#add_source_files_references ⇒ Object
166 167 168 |
# File 'lib/cocoapods-generator/command/generator.rb', line 166 def add_source_files_references add_file_accessors_paths_to_group(:source_files) end |
#add_vendored_libraries ⇒ Object
174 175 176 |
# File 'lib/cocoapods-generator/command/generator.rb', line 174 def add_vendored_libraries add_file_accessors_paths_to_group(:vendored_libraries, :frameworks) end |
#add_vendored_library_to_build_phases(sourcekey) ⇒ Object
306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/cocoapods-generator/command/generator.rb', line 306 def add_vendored_library_to_build_phases(sourcekey) file_accessor = @file_accessors.first file_accessor.send(sourcekey).each do |path| ref = @app_project.reference_for_path(path) if ref @framework_target.frameworks_build_phase.add_file_reference(ref) else help! "#{path.basename} no added to project!!" end end end |
#allowable_project_paths(paths) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/cocoapods-generator/command/generator.rb', line 217 def allowable_project_paths(paths) lproj_paths = Set.new lproj_paths_with_files = Set.new allowable_paths = paths.select do |path| path_str = path.to_s # We add the directory for a Core Data model, but not the items in it. next if path_str =~ /.*\.xcdatamodeld\/.+/i # We add the directory for a Core Data migration mapping, but not the items in it. next if path_str =~ /.*\.xcmappingmodel\/.+/i # We add the directory for an asset catalog, but not the items in it. next if path_str =~ /.*\.xcassets\/.+/i if path_str =~ /\.lproj(\/|$)/i # If the element is an .lproj directory then save it and potentially # add it later if we don't find any contained items. if path_str =~ /\.lproj$/i && path.directory? lproj_paths << path next end # Collect the paths for the .lproj directories that contain files. lproj_path = /(^.*\.lproj)\/.*/i.match(path_str)[1] lproj_paths_with_files << Pathname(lproj_path) # Directories nested within an .lproj directory are added as file # system references so their contained items are not added directly. next if path.dirname.dirname == lproj_path end true end # Only add the path for the .lproj directories that do not have anything # within them added as well. This generally happens if the glob within the # resources directory was not a recursive glob. allowable_paths + lproj_paths.subtract(lproj_paths_with_files).to_a end |
#compiler_flags_for_consumer(consumer, arc) ⇒ Object
343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/cocoapods-generator/command/generator.rb', line 343 def compiler_flags_for_consumer(consumer, arc) flags = consumer.compiler_flags.dup if !arc flags << '-fno-objc-arc' else platform_name = consumer.platform_name spec_deployment_target = consumer.spec.deployment_target(platform_name) if spec_deployment_target.nil? || Version.new(spec_deployment_target) < ENABLE_OBJECT_USE_OBJC_FROM[platform_name] flags << '-DOS_OBJECT_USE_OBJC=0' end end flags * ' ' end |
#create_file_accessors ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/cocoapods-generator/command/generator.rb', line 152 def create_file_accessors [@framework_target].each do |target| path_list = Sandbox::PathList.new(Pathname.new(Dir.new(@current_path))) specs = [@spec_content] specs.concat @spec_content.subspecs platform = Platform.new(target.platform_name, target.deployment_target) @file_accessors = specs.map do |spec| file_accessor = Sandbox::FileAccessor.new(path_list, spec.consumer(platform)) file_accessor end end end |
#create_spec_content ⇒ Object
109 110 111 |
# File 'lib/cocoapods-generator/command/generator.rb', line 109 def create_spec_content @spec_content = Specification::from_file @spec_path end |
#group_for_spec(spec_name, subgroup_key = nil) ⇒ Object
207 208 209 210 211 212 213 214 215 |
# File 'lib/cocoapods-generator/command/generator.rb', line 207 def group_for_spec(spec_name, subgroup_key = nil) if subgroup_key group_name = SPEC_SUBGROUPS[subgroup_key] else group_name = spec_name end @app_project[group_name] || @app_project.new_group(group_name) end |
#header_mappings_dir ⇒ Object
358 359 360 361 362 363 |
# File 'lib/cocoapods-generator/command/generator.rb', line 358 def header_mappings_dir file_accessor = @file_accessors.first header_mappings_dir = if dir = file_accessor.spec_consumer.header_mappings_dir file_accessor.path_list.root + dir end end |
#install ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/cocoapods-generator/command/generator.rb', line 135 def install project_path = xcodeproj_path @app_project = Xcodeproj::Project.open(project_path) @framework_target = @app_project.targets.find { |target| target.name == @spec_content.name } create_file_accessors add_source_files_references add_frameworks_bundles add_vendored_libraries add_resources add_files_to_build_phases add_libraries_to_build_phases @app_project.save end |
#results_message(results) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/cocoapods-generator/command/generator.rb', line 76 def (results) = '' results.each do |result| if result.platforms == [:ios] = '[iOS] ' elsif result.platforms == [:osx] = '[OSX] ' elsif result.platforms == [:watchos] = '[watchOS] ' elsif result.platforms == [:tvos] = '[tvOS] ' end = '' if result.is_a?(Result) subspecs = result.subspecs.uniq if subspecs.count > 2 = '[' + subspecs[0..2].join(', ') + ', and more...] ' elsif subspecs.count > 0 = '[' + subspecs.join(',') + '] ' end end case result.type when :error then type = 'ERROR' when :warning then type = 'WARN' when :note then type = 'NOTE' else raise "#{result.type}" end << " - #{type.ljust(5)} | #{}#{}#{result.attribute_name}: #{result.}\n" end << "\n" end |
#run ⇒ Object
62 63 64 65 66 |
# File 'lib/cocoapods-generator/command/generator.rb', line 62 def run create_spec_content validatePodspec install end |
#validate! ⇒ Object
53 54 55 56 57 58 59 60 |
# File 'lib/cocoapods-generator/command/generator.rb', line 53 def validate! super if @spec_name.nil? || File.extname(@spec_name) != ".podspec" help! 'A *.podspec file is required.' Process.exit! false end end |
#validatePodspec ⇒ Object
68 69 70 71 72 73 74 |
# File 'lib/cocoapods-generator/command/generator.rb', line 68 def validatePodspec linter = Specification::Linter.new(@spec_path) linter.lint results = [] results.concat(linter.results.to_a) puts results end |
#xcodeproj_path ⇒ Object
113 114 115 116 117 118 119 120 |
# File 'lib/cocoapods-generator/command/generator.rb', line 113 def xcodeproj_path project_path = File. File.basename(@spec_name, ".podspec") + '.xcodeproj', @current_path if !File.exists? project_path help! "Please make sure has #{File.basename project_path} in current directory." Process.exit! false end project_path end |