sync-podspec 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 96ed1a2d4e72534f8644b017e0153b99ea16c85f03aefad7221e68357446eb1b
4
+ data.tar.gz: a58e9a4e936d58465af37294c789df28e62a85676f1f96384efa9410c1af426e
5
+ SHA512:
6
+ metadata.gz: d3e81b92359fb27b0456851532322fa11660be1cdff80b7015ad2b956191f034799b7bd62ecad84e1028990fb5370967ddbbbfaa59ba4199d91d1f8a95ae8c22
7
+ data.tar.gz: bd52427d4313aceacdf8236afa352aa57a5287d077d0c641ec39911a77a8891c6fc34290500c60e5cdb8a0ce35d65ef7799e32943a6fcc8ba5b776c863bbf9ec
@@ -0,0 +1 @@
1
+ require 'pod/command/sync-podspec'
@@ -0,0 +1,267 @@
1
+ require 'tempfile'
2
+ require 'fileutils'
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ module Pod
6
+ class Command
7
+ class Repo < Command
8
+ class Sync < Repo
9
+ self.summary = 'Push new specifications to a spec-repo without lint validation'
10
+
11
+ self.description = <<-DESC
12
+ Validates `NAME.podspec` or `*.podspec` in the current working dir,
13
+ creates a directory and version folder for the pod in the local copy of
14
+ `REPO` (#{Config.instance.repos_dir}/[REPO]), copies the podspec file into the
15
+ version directory, and finally it pushes `REPO` to its remote.
16
+ DESC
17
+
18
+ self.arguments = [
19
+ CLAide::Argument.new('REPO', true),
20
+ CLAide::Argument.new('NAME.podspec', false),
21
+ ]
22
+
23
+ def self.options
24
+ [
25
+ ['--allow-warnings', 'Allows pushing even if there are warnings'],
26
+ ['--use-libraries', 'Linter uses static libraries to install the spec'],
27
+ ['--use-modular-headers', 'Lint uses modular headers during installation'],
28
+ ["--sources=#{Pod::TrunkSource::TRUNK_REPO_URL}", 'The sources from which to pull dependent pods ' \
29
+ '(defaults to all available repos). Multiple sources must be comma-delimited'],
30
+ ['--local-only', 'Does not perform the step of pushing REPO to its remote'],
31
+ ['--no-private', 'Lint includes checks that apply only to public repos'],
32
+ ['--skip-import-validation', 'Lint skips validating that the pod can be imported'],
33
+ ['--skip-tests', 'Lint skips building and running tests during validation'],
34
+ ['--commit-message="Fix bug in pod"', 'Add custom commit message. Opens default editor if no commit ' \
35
+ 'message is specified'],
36
+ ['--use-json', 'Convert the podspec to JSON before pushing it to the repo'],
37
+ ['--swift-version=VERSION', 'The `SWIFT_VERSION` that should be used when linting the spec. ' \
38
+ 'This takes precedence over the Swift versions specified by the spec or a `.swift-version` file'],
39
+ ['--no-overwrite', 'Disallow pushing that would overwrite an existing spec'],
40
+ ].concat(super)
41
+ end
42
+
43
+ def initialize(argv)
44
+ @allow_warnings = argv.flag?('allow-warnings')
45
+ @local_only = argv.flag?('local-only')
46
+ @repo = argv.shift_argument
47
+ @source = source_for_repo
48
+ @source_urls = argv.option('sources', config.sources_manager.all.map(&:url).join(',')).split(',')
49
+ @podspec = argv.shift_argument
50
+ @use_frameworks = !argv.flag?('use-libraries')
51
+ @use_modular_headers = argv.flag?('use-modular-headers', false)
52
+ @private = argv.flag?('private', true)
53
+ @message = argv.option('commit-message')
54
+ @commit_message = argv.flag?('commit-message', false)
55
+ @use_json = argv.flag?('use-json')
56
+ @swift_version = argv.option('swift-version', nil)
57
+ @skip_import_validation = argv.flag?('skip-import-validation', false)
58
+ @skip_tests = argv.flag?('skip-tests', false)
59
+ @allow_overwrite = argv.flag?('overwrite', true)
60
+ super
61
+ end
62
+
63
+ def validate!
64
+ super
65
+ help! 'A spec-repo name or url is required.' unless @repo
66
+ unless @source && @source.repo.directory?
67
+ raise Informative,
68
+ "Unable to find the `#{@repo}` repo. " \
69
+ 'If it has not yet been cloned, add it via `pod repo add`.'
70
+ end
71
+ end
72
+
73
+ def run
74
+ open_editor if @commit_message && @message.nil?
75
+ check_if_push_allowed
76
+ check_repo_status
77
+ update_repo
78
+ add_specs_to_repo
79
+ push_repo unless @local_only
80
+ end
81
+
82
+ #---------------------------------------------------------------------#
83
+
84
+ private
85
+
86
+ # @!group Push sub-steps
87
+
88
+ extend Executable
89
+ executable :git
90
+
91
+ # Open default editor to allow users to enter commit message
92
+ #
93
+ def open_editor
94
+ return if ENV['EDITOR'].nil?
95
+
96
+ file = Tempfile.new('cocoapods')
97
+ File.chmod(0777, file.path)
98
+ file.close
99
+
100
+ system("#{ENV['EDITOR']} #{file.path}")
101
+ @message = File.read file.path
102
+ end
103
+
104
+ # Temporary check to ensure that users do not push accidentally private
105
+ # specs to the master repo.
106
+ #
107
+ def check_if_push_allowed
108
+ if @source.is_a?(CDNSource)
109
+ raise Informative, 'Cannot push to a CDN source, as it is read-only.'
110
+ end
111
+
112
+ remotes, = Executable.capture_command('git', %w(remote --verbose), :capture => :merge, :chdir => repo_dir)
113
+ master_repo_urls = [
114
+ 'git@github.com:CocoaPods/Specs.git',
115
+ 'https://github.com/CocoaPods/Specs.git',
116
+ ]
117
+ is_master_repo = master_repo_urls.any? do |url|
118
+ remotes.include?(url)
119
+ end
120
+
121
+ if is_master_repo
122
+ raise Informative, 'To push to the CocoaPods master repo use ' \
123
+ "the `pod trunk push` command.\n\nIf you are using a fork of " \
124
+ 'the master repo for private purposes we recommend to migrate ' \
125
+ 'to a clean private repo. To disable this check remove the ' \
126
+ 'remote pointing to the CocoaPods master repo.'
127
+ end
128
+ end
129
+
130
+ # Checks that the repo is clean.
131
+ #
132
+ # @raise If the repo is not clean.
133
+ #
134
+ # @todo Add specs for staged and unstaged files.
135
+ #
136
+ # @todo Gracefully handle the case where source is not under git
137
+ # source control.
138
+ #
139
+ # @return [void]
140
+ #
141
+ def check_repo_status
142
+ porcelain_status, = Executable.capture_command('git', %w(status --porcelain), :capture => :merge, :chdir => repo_dir)
143
+ clean = porcelain_status == ''
144
+ raise Informative, "The repo `#{@repo}` at #{UI.path repo_dir} is not clean" unless clean
145
+ end
146
+
147
+ # Updates the git repo against the remote.
148
+ #
149
+ # @return [void]
150
+ #
151
+ def update_repo
152
+ UI.puts "Updating the `#{@repo}' repo\n".yellow
153
+ git!(%W(-C #{repo_dir} pull))
154
+ end
155
+
156
+ # Commits the podspecs to the source, which should be a git repo.
157
+ #
158
+ # @note The pre commit hook of the repo is skipped as the podspecs have
159
+ # already been linted.
160
+ #
161
+ # @return [void]
162
+ #
163
+ def add_specs_to_repo
164
+ UI.puts "\nAdding the #{'spec'.pluralize(count)} to the `#{@repo}' repo\n".yellow
165
+ podspec_files.each do |spec_file|
166
+ spec = Pod::Specification.from_file(spec_file)
167
+ output_path = @source.pod_path(spec.name) + spec.version.to_s
168
+ message = if @message && !@message.empty?
169
+ @message
170
+ elsif output_path.exist?
171
+ "[Fix] #{spec}"
172
+ elsif output_path.dirname.directory?
173
+ "[Update] #{spec}"
174
+ else
175
+ "[Add] #{spec}"
176
+ end
177
+
178
+ if output_path.exist? && !@allow_overwrite
179
+ raise Informative, "#{spec} already exists and overwriting has been disabled."
180
+ end
181
+
182
+ FileUtils.mkdir_p(output_path)
183
+
184
+ if @use_json
185
+ json_file_name = "#{spec.name}.podspec.json"
186
+ json_file = File.join(output_path, json_file_name)
187
+ File.open(json_file, 'w') { |file| file.write(spec.to_pretty_json) }
188
+ else
189
+ FileUtils.cp(spec_file, output_path)
190
+ end
191
+
192
+ # only commit if modified
193
+ if repo_git('status', '--porcelain').include?(spec.name)
194
+ UI.puts " - #{message}"
195
+ repo_git('add', spec.name)
196
+ repo_git('commit', '--no-verify', '-m', message)
197
+ else
198
+ UI.puts " - [No change] #{spec}"
199
+ end
200
+ end
201
+ end
202
+
203
+ # Pushes the git repo against the remote.
204
+ #
205
+ # @return [void]
206
+ #
207
+ def push_repo
208
+ UI.puts "\nPushing the `#{@repo}' repo\n".yellow
209
+ repo_git('push', 'origin', 'HEAD')
210
+ end
211
+
212
+ #---------------------------------------------------------------------#
213
+
214
+ private
215
+
216
+ # @!group Private helpers
217
+
218
+ # @return result of calling the git! with args in repo_dir
219
+ #
220
+ def repo_git(*args)
221
+ git!(['-C', repo_dir] + args)
222
+ end
223
+
224
+ # @return [Pathname] The directory of the repository.
225
+ #
226
+ def repo_dir
227
+ @source.specs_dir
228
+ end
229
+
230
+ # @return [Array<Pathname>] The path of the specifications to push.
231
+ #
232
+ def podspec_files
233
+ if @podspec
234
+ path = Pathname(@podspec)
235
+ raise Informative, "Couldn't find #{@podspec}" unless path.exist?
236
+ [path]
237
+ else
238
+ #files = Pathname.glob('*.podspec{,.json}')
239
+ files = Pathname.glob('**/*.podspec{,.json}')
240
+ raise Informative, "Couldn't find any podspec files in current directory" if files.empty?
241
+ files
242
+ end
243
+ end
244
+
245
+ # @return [Integer] The number of the podspec files to push.
246
+ #
247
+ def count
248
+ podspec_files.count
249
+ end
250
+
251
+ # Returns source for @repo
252
+ #
253
+ # @note If URL is invalid or repo doesn't exist, validate! will throw the error
254
+ #
255
+ # @return [Source]
256
+ #
257
+ def source_for_repo
258
+ config.sources_manager.source_with_name_or_url(@repo) unless @repo.nil?
259
+ rescue
260
+ nil
261
+ end
262
+
263
+ #---------------------------------------------------------------------#
264
+ end
265
+ end
266
+ end
267
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sync-podspec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - quangmv
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cocoapods
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.10.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.10.0
27
+ description: Push new specifications to a spec-repo without
28
+ email:
29
+ - quang.app@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/cocoapods_plugin.rb
35
+ - lib/pod/command/sync-podspec.rb
36
+ homepage: https://github.com/quangmv
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.0.3
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Push new specifications to a spec-repo without lint validation
59
+ test_files: []