Class: Pod::Command::Spec::Create

Inherits:
Pod::Command::Spec show all
Defined in:
lib/cocoapods/command/spec/create.rb

Instance Method Summary collapse

Methods inherited from Pod::Command::Spec

#all_paths_from_set, #get_path_of_spec, #pathname_from_spec, #spec_and_source_from_set, #validate_regex!

Methods inherited from Pod::Command

#ensure_master_spec_repo_exists!, ensure_not_root_or_allowed!, git_version, #installer_for_config, options, report_error, run, #verify_lockfile_exists!, verify_minimum_git_version!, #verify_podfile_exists!, verify_xcode_license_approved!

Methods included from Pod::Config::Mixin

#config

Constructor Details

#initialize(argv) ⇒ Create

Returns a new instance of Create.


17
18
19
20
21
# File 'lib/cocoapods/command/spec/create.rb', line 17

def initialize(argv)
  @name_or_url = argv.shift_argument
  @url = argv.shift_argument
  super
end

Instance Method Details

#default_data_for_template(name) ⇒ Object (private)

TODO:

It would be nice to have a template class that accepts options and uses the default ones if not provided.

TODO:

The template is outdated.

Templates and GitHub information retrieval for spec create


53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/cocoapods/command/spec/create.rb', line 53

def default_data_for_template(name)
  {
    :name => name,
    :version => '0.0.1',
    :summary =>  "A short description of #{name}.",
    :homepage => "http://EXAMPLE/#{name}",
    :author_name => Executable.capture_command('git', %w(config --get user.name), :capture => :out).first.strip,
    :author_email => Executable.capture_command('git', %w(config --get user.email), :capture => :out).first.strip,
    :source_url => "http://EXAMPLE/#{name}.git",
    :ref_type => ':tag',
    :ref => '#{spec.version}',
  }
end

#github_data_for_template(repo_id) ⇒ Object (private)

Raises:


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/cocoapods/command/spec/create.rb', line 67

def github_data_for_template(repo_id)
  repo = GitHub.repo(repo_id)
  raise Informative, "Unable to fetch data for `#{repo_id}`" unless repo
  user = GitHub.user(repo['owner']['login'])
  raise Informative, "Unable to fetch data for `#{repo['owner']['login']}`" unless user
  data = {}

  data[:name]          = repo['name']
  data[:summary]       = (repo['description'] || '').gsub(/["]/, '\"')
  data[:homepage]      = (repo['homepage'] && !repo['homepage'].empty?) ? repo['homepage'] : repo['html_url']
  data[:author_name]   = user['name'] || user['login']
  data[:author_email]  = user['email'] || '[email protected]'
  data[:source_url]    = repo['clone_url']

  data.merge suggested_ref_and_version(repo)
end

#runObject


28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/cocoapods/command/spec/create.rb', line 28

def run
  if repo_id_match = (@url || @name_or_url).match(%r{github.com/([^/\.]*\/[^/\.]*)\.*})
    repo_id = repo_id_match[1]
    data = github_data_for_template(repo_id)
    data[:name] = @name_or_url if @url
    UI.puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
  else
    data = default_data_for_template(@name_or_url)
  end

  spec = spec_template(data)
  (Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
  UI.puts "\nSpecification created at #{data[:name]}.podspec".green
end

#semantic_versioning_notice(repo_id, repo) ⇒ Object (private)


251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/cocoapods/command/spec/create.rb', line 251

def semantic_versioning_notice(repo_id, repo)
  <<-EOS

#{'――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}

I’ve recently added [#{repo}](https://github.com/CocoaPods/Specs/tree/master/#{repo}) to the [CocoaPods](https://github.com/CocoaPods/CocoaPods) package manager repo.

CocoaPods is a tool for managing dependencies for OSX and iOS Xcode projects and provides a central repository for iOS/OSX libraries. This makes adding libraries to a project and updating them extremely easy and it will help users to resolve dependencies of the libraries they use.

However, #{repo} doesn't have any version tags. I’ve added the current HEAD as version 0.0.1, but a version tag will make dependency resolution much easier.

[Semantic version](https://semver.org) tags (instead of plain commit hashes/revisions) allow for [resolution of cross-dependencies](https://github.com/CocoaPods/Specs/wiki/Cross-dependencies-resolution-example).

In case you didn’t know this yet; you can tag the current HEAD as, for instance, version 1.0.0, like so:

```
$ git tag -a 1.0.0 -m "Tag release 1.0.0"
$ git push --tags
```

#{'――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}

#{'[!] This repo does not appear to have semantic version tags.'.yellow}

After commiting the specification, consider opening a ticket with the template displayed above:
  - link:  https://github.com/#{repo_id}/issues/new
  - title: Please add semantic version tags
  EOS
end

#spec_template(data) ⇒ Object (private)


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
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
# File 'lib/cocoapods/command/spec/create.rb', line 109

def spec_template(data)
  <<-SPEC
#
#  Be sure to run `pod spec lint #{data[:name]}.podspec' to ensure this is a
#  valid spec and to remove all comments including this before submitting the spec.
#
#  To learn more about Podspec attributes see https://guides.cocoapods.org/syntax/podspec.html
#  To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#

Pod::Spec.new do |spec|

  # ―――  Spec Metadata  ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  These will help people to find your library, and whilst it
  #  can feel like a chore to fill in it's definitely to your advantage. The
  #  summary should be tweet-length, and the description more in depth.
  #

  spec.name         = "#{data[:name]}"
  spec.version      = "#{data[:version]}"
  spec.summary      = "#{data[:summary]}"

  # This description is used to generate tags and improve search results.
  #   * Think: What does it do? Why did you write it? What is the focus?
  #   * Try to keep it short, snappy and to the point.
  #   * Write the description between the DESC delimiters below.
  #   * Finally, don't worry about the indent, CocoaPods strips it!
  spec.description  = <<-DESC
           DESC

  spec.homepage     = "#{data[:homepage]}"
  # spec.screenshots  = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"


  # ―――  Spec License  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Licensing your code is important. See https://choosealicense.com for more info.
  #  CocoaPods will detect a license file if there is a named LICENSE*
  #  Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
  #

  spec.license      = "MIT (example)"
  # spec.license      = { :type => "MIT", :file => "FILE_LICENSE" }


  # ――― Author Metadata  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the authors of the library, with email addresses. Email addresses
  #  of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
  #  accepts just a name if you'd rather not provide an email address.
  #
  #  Specify a social_media_url where others can refer to, for example a twitter
  #  profile URL.
  #

  spec.author             = { "#{data[:author_name]}" => "#{data[:author_email]}" }
  # Or just: spec.author    = "#{data[:author_name]}"
  # spec.authors            = { "#{data[:author_name]}" => "#{data[:author_email]}" }
  # spec.social_media_url   = "https://twitter.com/#{data[:author_name]}"

  # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If this Pod runs only on iOS or OS X, then specify the platform and
  #  the deployment target. You can optionally include the target after the platform.
  #

  # spec.platform     = :ios
  # spec.platform     = :ios, "5.0"

  #  When using multiple platforms
  # spec.ios.deployment_target = "5.0"
  # spec.osx.deployment_target = "10.7"
  # spec.watchos.deployment_target = "2.0"
  # spec.tvos.deployment_target = "9.0"


  # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the location from where the source should be retrieved.
  #  Supports git, hg, bzr, svn and HTTP.
  #

  spec.source       = { :git => "#{data[:source_url]}", #{data[:ref_type]} => "#{data[:ref]}" }


  # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  CocoaPods is smart about how it includes source code. For source files
  #  giving a folder will include any swift, h, m, mm, c & cpp files.
  #  For header files it will include any header in the folder.
  #  Not including the public_header_files will make all headers public.
  #

  spec.source_files  = "Classes", "Classes/**/*.{h,m}"
  spec.exclude_files = "Classes/Exclude"

  # spec.public_header_files = "Classes/**/*.h"


  # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  A list of resources included with the Pod. These are copied into the
  #  target bundle with a build phase script. Anything else will be cleaned.
  #  You can preserve files from being cleaned, please don't preserve
  #  non-essential files like tests, examples and documentation.
  #

  # spec.resource  = "icon.png"
  # spec.resources = "Resources/*.png"

  # spec.preserve_paths = "FilesToSave", "MoreFilesToSave"


  # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Link your library with frameworks, or libraries. Libraries do not include
  #  the lib prefix of their name.
  #

  # spec.framework  = "SomeFramework"
  # spec.frameworks = "SomeFramework", "AnotherFramework"

  # spec.library   = "iconv"
  # spec.libraries = "iconv", "xml2"


  # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If your library depends on compiler flags you can set them in the xcconfig hash
  #  where they will only apply to your library. If you depend on other Podspecs
  #  you can include multiple dependencies to ensure it works.

  # spec.requires_arc = true

  # spec.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
  # spec.dependency "JSONKit", "~> 1.4"

end
  SPEC
end

#suggested_ref_and_version(repo) ⇒ Object (private)


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/command/spec/create.rb', line 84

def suggested_ref_and_version(repo)
  tags = GitHub.tags(repo['html_url']).map { |tag| tag['name'] }
  versions_tags = {}
  tags.each do |tag|
    clean_tag = tag.gsub(/^v(er)? ?/, '')
    versions_tags[Gem::Version.new(clean_tag)] = tag if Gem::Version.correct?(clean_tag)
  end
  version = versions_tags.keys.sort.last || '0.0.1'
  data = { :version => version }
  if version == '0.0.1'
    branches        = GitHub.branches(repo['html_url'])
    master_name     = repo['master_branch'] || 'master'
    master          = branches.find { |branch| branch['name'] == master_name }
    raise Informative, "Unable to find any commits on the master branch for the repository `#{repo['html_url']}`" unless master
    data[:ref_type] = ':commit'
    data[:ref]      = master['commit']['sha']
  else
    data[:ref_type] = ':tag'
    data[:ref]      = versions_tags[version]
    data[:ref]      = '#{spec.version}' if "#{version}" == versions_tags[version]
    data[:ref]      = 'v#{spec.version}' if "v#{version}" == versions_tags[version]
  end
  data
end

#validate!Object


23
24
25
26
# File 'lib/cocoapods/command/spec/create.rb', line 23

def validate!
  super
  help! 'A pod name or repo URL is required.' unless @name_or_url
end