leancloud 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7ea3a36559564040abe311c634791161bfc9e1e8
4
+ data.tar.gz: 9a035fae9c97c3e544da238b1da3ed568ba6a939
5
+ SHA512:
6
+ metadata.gz: 09bed82e1611372f1c0f11cc6ae3fb50a7c4f9b2c6df38012a026b606f6ba8895647a699bee941975d87fa30956b6303fd308709293b0bae021565dc42fa8b39
7
+ data.tar.gz: 32ba82b61fe48338e5ed0bc3a7ff9792d46fcc4504ee2c12b55894587c084bca1d7f3779c6f3d60161337b4a13b2d4cbaad7405d2f2fb4561013de0b1435f6e1
data/bin/leancloud ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'clactive'
5
+ require 'leancloud'
6
+
7
+ CLActive do
8
+
9
+ option :version, '-v', '--version', 'LeanCloud Gem version'
10
+ action do |opts|
11
+ puts LeanCloud::VERSION if version?
12
+ end
13
+
14
+ subcmd :init do
15
+ option :sdk_version, '-v v', '--version=sdk_version', 'Leancloud SDK version'
16
+ option :ios_version, '-i i', '--ios=ios_version', 'Project base SDK version'
17
+ option :name, '-n n', '--name=name', 'XCode project name'
18
+ option :target, '-t t', '--target=target', 'XCode project target'
19
+ option :components, '-c c', '--components=componenets', 'Leancloud SDK componenets'
20
+ action do |opts|
21
+ begin
22
+ leancloud = LeanCloud::Initializer.new(opts)
23
+ leancloud.create
24
+ rescue SignalException
25
+ rescue Exception => e
26
+ raise e
27
+ end
28
+ end
29
+ end
30
+
31
+ subcmd :install do
32
+ option :file, '-f f', '--file=file', 'Install by the specified Leanfile'
33
+ action do |opts|
34
+ begin
35
+ leancloud = LeanCloud::Installer.new
36
+ leancloud.install(opts[:file])
37
+ rescue SignalException
38
+ rescue Exception => e
39
+ raise e
40
+ ensure
41
+ leancloud.destroy
42
+ end
43
+ end
44
+ end
45
+
46
+ subcmd :upload_symbol do
47
+ option :id, '-i i', '--id=id', 'App ID'
48
+ option :key, '-k k', '--key=key', 'App Key'
49
+ option :file, '-f f', '--file=file', 'DSYM file path'
50
+ option :verbose, '-v', '--verbose', 'Verbose mode'
51
+ action do |opts|
52
+ leancloud = LeanCloud::SymbolUploader.new(opts)
53
+ leancloud.upload
54
+ end
55
+ end
56
+
57
+ end
Binary file
data/lib/leancloud.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'leancloud/leanobject'
2
+ require 'leancloud/http'
3
+ require 'leancloud/installer'
4
+ require 'leancloud/initializer'
5
+
6
+ # LeanCloud main module
7
+ module LeanCloud
8
+ VERSION = '0.0.6'
9
+ end
@@ -0,0 +1,2 @@
1
+ require 'leancloud/http/lean_http'
2
+ require 'leancloud/http/symbol_uploader'
@@ -0,0 +1,17 @@
1
+ require 'uri'
2
+
3
+ module LeanCloud
4
+
5
+ # LeanCloud HTTP manager
6
+ class LeanHTTP < LeanObject
7
+ BASE_URL = 'https://api.leancloud.cn/1.1/'
8
+
9
+ protected
10
+
11
+ def api(path)
12
+ URI.join(BASE_URL, path)
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,135 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+ require 'mustache'
4
+ require 'leancloud/http/lean_http'
5
+
6
+ module LeanCloud
7
+
8
+ # LeanCloud symbol uploader
9
+ class SymbolUploader < LeanHTTP
10
+
11
+ def initialize(opts)
12
+ @options = opts
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :dsym_path
18
+ attr_reader :dsym_macho
19
+ attr_reader :dsym_archs
20
+ attr_reader :tmp_dir
21
+
22
+ def verbose?
23
+ @verbose ||= !@options[:verbose].nil?
24
+ end
25
+
26
+ def dsym_path
27
+ @dsym_path ||= (
28
+ path = @options[:file]
29
+ path if !path.nil? and File.readable?(path)
30
+ )
31
+ end
32
+
33
+ def dsym_macho
34
+ @dsym_macho ||= Dir.glob(File.join(dsym_path, 'Contents/Resources/DWARF/*')).first
35
+ end
36
+
37
+ def lipo_dsym_archs
38
+ info = %x(lipo -info #{dsym_macho} 2>/dev/null)
39
+ arch_list = info[/[^:]+$/].strip
40
+ arch_list.split(' ')
41
+ end
42
+
43
+ def dsym_archs
44
+ @dsym_archs ||= lipo_dsym_archs
45
+ end
46
+
47
+ def tmp_dir
48
+ @tmp_dir ||= File.join(Dir.tmpdir(), 'cn.leancloud/symbols')
49
+ end
50
+
51
+ def validate_options
52
+ exit_with_info('DSYM file not found') unless dsym_path
53
+ report_error('LeanCloud App ID not found') unless @options[:id]
54
+ report_error('LeanCloud App Key not found') unless @options[:key]
55
+ end
56
+
57
+ def symbol_path(arch)
58
+ File.join(tmp_dir, "#{arch}.sym")
59
+ end
60
+
61
+ def dump_cmd_template
62
+ <<-EOT.gsub(/^[ \t]+/, '')
63
+ {{#archs}}
64
+ leancloud_dump_syms -a {{name}} #{dsym_path} > {{path}} 2>/dev/null
65
+ {{/archs}}
66
+ EOT
67
+ end
68
+
69
+ def dump_symbol
70
+ FileUtils.mkdir_p(tmp_dir)
71
+
72
+ archs = dsym_archs.map { |arch| { name: arch, path: symbol_path(arch) } }
73
+
74
+ cmd = Mustache.render(dump_cmd_template, archs: archs)
75
+
76
+ puts "Command for dump symbol files:\n#{cmd}" if verbose?
77
+
78
+ system(cmd)
79
+ end
80
+
81
+ def symbol_fields
82
+ fields = []
83
+
84
+ dsym_archs.each do |arch|
85
+ path = symbol_path(arch)
86
+ next if !File.readable?(path) or File.zero?(path)
87
+ fields << "-F \"symbol_file_#{arch}=@#{path}\""
88
+ end
89
+
90
+ fields
91
+ end
92
+
93
+ def send_symbol
94
+ fields = symbol_fields
95
+
96
+ return if fields.empty?
97
+
98
+ form_fields = fields.join(" \\\n")
99
+ url = api('stats/breakpad/symbols')
100
+
101
+ cmd = <<-EOC.gsub(/^[ \t]+/, '')
102
+ curl -X POST \\
103
+ -H "X-AVOSCloud-Application-Id: #{@options[:id]}" \\
104
+ -H "X-AVOSCloud-Application-Key: #{@options[:key]}" \\
105
+ #{form_fields} \\
106
+ #{url} 2>/dev/null
107
+ EOC
108
+
109
+ puts "Command for uploading symbol files:\n#{cmd}" if verbose?
110
+ puts 'Uploading symbol files...'
111
+
112
+ response = %x(#{cmd})
113
+
114
+ unless '{}' == response
115
+ report_error("Failed to upload symbol files:\n#{response}")
116
+ else
117
+ puts 'Uploaded symbol files.'
118
+ end
119
+ end
120
+
121
+ def report_error(msg)
122
+ fail msg
123
+ end
124
+
125
+ public
126
+
127
+ def upload
128
+ validate_options
129
+ dump_symbol
130
+ send_symbol
131
+ end
132
+
133
+ end
134
+
135
+ end
@@ -0,0 +1,101 @@
1
+ module LeanCloud
2
+
3
+ # Leanfile template initializer
4
+ class Initializer < LeanObject
5
+
6
+ def initialize(opts)
7
+ @options = opts
8
+ @leanfile_path = LeanCloud::Installer::LEANFILE_PATH
9
+ end
10
+
11
+ private
12
+
13
+ attr_accessor :options
14
+
15
+ def template
16
+ @template ||= <<-EOT.gsub(/^[ \t]+/, '')
17
+ # Leanfile
18
+ # -*- mode: yaml -*- vim:ft=yaml
19
+
20
+ ---
21
+ # LeanCloud SDK version (optional)
22
+ # If empty, defaults to the latest version
23
+ version: {{version}}
24
+
25
+ # Your project base SDK version
26
+ base_sdk_version: {{base_sdk_version}}
27
+
28
+ # Your project name (optional)
29
+ # If empty, defaults to the single project in current directory
30
+ xcodeproj: {{xcodeproj}}
31
+
32
+ # Target name of your project (optional)
33
+ # If empty, defaults to the target which matches project's name
34
+ target: {{target}}
35
+
36
+ # LeanCloud SDK components
37
+ components:
38
+ {{#components}}
39
+ - {{value}}
40
+ {{/components}}
41
+ EOT
42
+ end
43
+
44
+ def validate_version_number(version)
45
+ if !version.nil? and !Gem::Version.correct?(version)
46
+ exit_with_error("Illegal version numner: #{version}")
47
+ end
48
+ end
49
+
50
+ def validate_options
51
+ validate_version_number(options[:sdk_version])
52
+ validate_version_number(options[:ios_version])
53
+ end
54
+
55
+ def component_list(components)
56
+ result = []
57
+
58
+ unless components.nil?
59
+ components.split(',').each do |component|
60
+ value = component.strip
61
+ result << { 'value' => value } unless value.empty?
62
+ end
63
+
64
+ result.uniq!
65
+ end
66
+
67
+ result
68
+ end
69
+
70
+ def generate_leanfile
71
+ opts = options
72
+ components = component_list(opts[:components])
73
+
74
+ content = Mustache.render(template, {
75
+ 'version' => opts[:sdk_version],
76
+ 'base_sdk_version' => opts[:ios_version],
77
+ 'xcodeproj' => opts[:name],
78
+ 'target' => opts[:target],
79
+ 'components' => components
80
+ })
81
+
82
+ File.open(@leanfile_path, 'w') do |file|
83
+ file.write(content)
84
+ end
85
+ end
86
+
87
+ def prompt(existed)
88
+ puts "#{existed ? 'Reinitialized existing' : 'Initialized'} Leanfile"
89
+ end
90
+
91
+ public
92
+
93
+ def create
94
+ validate_options
95
+ existed = File.exist?(@leanfile_path)
96
+ generate_leanfile
97
+ prompt(existed)
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,340 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'yaml'
4
+ require 'json'
5
+ require 'net/http'
6
+ require 'xcodeproj'
7
+ require 'open-uri'
8
+ require 'fileutils'
9
+ require 'mustache'
10
+ require 'erb'
11
+
12
+ module LeanCloud
13
+
14
+ # LeanCloud SDK installer
15
+ class Installer < LeanObject
16
+
17
+ include ERB::Util
18
+
19
+ LEANFILE_PATH = 'Leanfile'
20
+ LEANCLOUD_SDK_ROOT = 'LeanCloud'
21
+ LEANCLOUD_SDK_GROUP = 'LeanCloud'
22
+ LEANCLOUD_SDK_PREFIX = 'AVOSCloud'
23
+
24
+ def initialize
25
+ @leanfile_path = LEANFILE_PATH
26
+ @root_path = LEANCLOUD_SDK_ROOT
27
+ @stash_name = 'Stash'
28
+ @stash_path = File.join(@root_path, @stash_name)
29
+ @sdk_path = File.join(@stash_path, 'Frameworks.zip')
30
+ @frameworks_path = File.join(@stash_path, 'Frameworks')
31
+ @modules_path = File.join(@stash_path, 'Modules')
32
+ @lean_group = LEANCLOUD_SDK_GROUP
33
+ @sdk_prefix = LEANCLOUD_SDK_PREFIX
34
+ @sdk_url_prefix = 'https://download.avoscloud.com/1/downloadSDK?'
35
+
36
+ @system_frameworks = %w(
37
+ CFNetwork
38
+ SystemConfiguration
39
+ MobileCoreServices
40
+ CoreTelephony
41
+ CoreLocation
42
+ CoreGraphics
43
+ QuartzCore
44
+ Security
45
+ )
46
+
47
+ @system_libraries = %w(icucore)
48
+
49
+ @lean_component_map = {
50
+ 'basic' => '基础模块',
51
+ 'SNS' => '社交模块',
52
+ 'IM' => '实时通信'
53
+ }
54
+ end
55
+
56
+ private
57
+
58
+ attr_accessor :config
59
+ attr_accessor :version
60
+ attr_accessor :base_sdk_version
61
+ attr_accessor :target
62
+
63
+ def version
64
+ @version ||= config['version']
65
+ end
66
+
67
+ def base_sdk_version
68
+ @base_sdk_version ||= config['base_sdk_version']
69
+ end
70
+
71
+ def target
72
+ @target ||= target_with_name(config['target'])
73
+ end
74
+
75
+ def patch_sdk_version(target)
76
+ version = base_sdk_version
77
+ target.define_singleton_method(:sdk_version) do
78
+ version
79
+ end
80
+ end
81
+
82
+ def target_with_name(name)
83
+ if name
84
+ targets = project.targets.select { |target| target.name.eql?(name) }
85
+ target = targets.first
86
+ patch_sdk_version(target) if target
87
+ target
88
+ else
89
+ name = File.basename(project.path, '.*')
90
+ target_with_name(name)
91
+ end
92
+ end
93
+
94
+ def search_single_xcodeproj
95
+ projects = Dir.glob('*.xcodeproj')
96
+
97
+ if projects.length == 0
98
+ exit_with_error('No Xcode project found')
99
+ elsif projects.length > 1
100
+ exit_with_error('Too many Xcode projects, please specify one in Leanfile')
101
+ end
102
+
103
+ projects.first
104
+ end
105
+
106
+ def project_path
107
+ if config['xcodeproj']
108
+ path = config['xcodeproj']
109
+ path = path + '.xcodeproj' unless path.end_with?('.xcodeproj')
110
+ path
111
+ else
112
+ search_single_xcodeproj
113
+ end
114
+ end
115
+
116
+ def project
117
+ @proj ||= Xcodeproj::Project.open(project_path)
118
+ rescue RuntimeError
119
+ nil
120
+ end
121
+
122
+ def read_leanfile
123
+ unless File.readable?(@leanfile_path)
124
+ exit_with_error('Can not find a readable Leanfile')
125
+ end
126
+
127
+ self.config = YAML.load(File.read(@leanfile_path))
128
+
129
+ rescue SyntaxError => e
130
+ exit_with_error("Leanfile has syntax error: #{e.message}")
131
+ end
132
+
133
+ def make_validation
134
+ exit_with_error('Base SDK version not specified') unless base_sdk_version
135
+ exit_with_error("Project #{project_path} can not be opened") unless project
136
+ exit_with_error('Target not found') unless target
137
+ end
138
+
139
+ def create_directory_tree
140
+ FileUtils.mkdir_p(@frameworks_path)
141
+ FileUtils.mkdir_p(@modules_path)
142
+ end
143
+
144
+ def param_join(hash)
145
+ hash.map { |k, v| "#{k}=#{v}" }.join('&')
146
+ end
147
+
148
+ def lean_components
149
+ components = config['components']
150
+
151
+ if components.is_a?(Array)
152
+ result = components.uniq
153
+ result.delete('basic')
154
+ result
155
+ else
156
+ []
157
+ end
158
+ end
159
+
160
+ def component_param_arr
161
+ result = [url_encode(@lean_component_map['basic'])]
162
+
163
+ lean_components.each do |key|
164
+ next unless @lean_component_map.key?(key)
165
+ result << url_encode(@lean_component_map[key])
166
+ end
167
+
168
+ result
169
+ end
170
+
171
+ def fetch_latest_version
172
+ json = Net::HTTP.get(URI('https://download.leancloud.cn/sdk/latest.json'))
173
+ version_info = JSON.parse(json)
174
+ version_info['ios']
175
+ end
176
+
177
+ def sdk_query_string
178
+ version = fetch_latest_version if version.nil?
179
+
180
+ hash = {
181
+ 'type' => 'ios',
182
+ 'components' => component_param_arr.join(','),
183
+ 'version' => "v#{version}"
184
+ }
185
+
186
+ param_join(hash)
187
+ end
188
+
189
+ def generate_sdk_url
190
+ @sdk_url_prefix + sdk_query_string
191
+ end
192
+
193
+ def download_framework
194
+ sdk_url = generate_sdk_url
195
+
196
+ show_message('Downloading LeanCloud SDK')
197
+
198
+ open(@sdk_path, 'wb') do |file|
199
+ file << open(sdk_url).read
200
+ end
201
+ rescue SocketError
202
+ exit_with_error('Download LeanCloud SDK failed')
203
+ end
204
+
205
+ def frameworks_entries
206
+ entries = []
207
+
208
+ Dir.glob("#{@root_path}/*").select do |entry|
209
+ next unless entry.end_with?('.framework')
210
+ entries << entry
211
+ end
212
+
213
+ entries
214
+ end
215
+
216
+ def move_components
217
+ frameworks_entries.each do |framework|
218
+ FileUtils.rm_rf(framework)
219
+ end
220
+
221
+ Dir.glob("#{@frameworks_path}/**/*.framework").each do |framework|
222
+ FileUtils.mv(framework, @root_path)
223
+ end
224
+
225
+ Dir.glob("#{@modules_path}/**/*.framework").each do |framework|
226
+ FileUtils.mv(framework, @root_path)
227
+ end
228
+ end
229
+
230
+ def clean_stash
231
+ system("rm -rf #{@stash_path}") unless '/' == @stash_path
232
+ end
233
+
234
+ def unzip_sdk
235
+ show_message('Unpacking LeanCloud SDK package')
236
+
237
+ quiet = '> /dev/null 2>&1'
238
+ unzip_cmd = <<-EOS
239
+ unzip -q #{@sdk_path} -d #{@frameworks_path} #{quiet}
240
+ unzip -q #{@frameworks_path}/\\*.zip -d #{@modules_path} #{quiet}
241
+ EOS
242
+
243
+ system(unzip_cmd)
244
+ move_components
245
+ end
246
+
247
+ def lean_group
248
+ project[@lean_group] || project.new_group(@lean_group)
249
+ end
250
+
251
+ def remove_legency_frameworks
252
+ phase = target.frameworks_build_phase
253
+
254
+ references = []
255
+ phase.files.each do |ref|
256
+ file = ref.file_ref
257
+ references << file if file.name.include?(@sdk_prefix)
258
+ end
259
+
260
+ references.each { |ref| phase.remove_file_reference(ref) }
261
+
262
+ lean_group.clear
263
+ end
264
+
265
+ def add_frameworks
266
+ show_message('Integrating frameworks')
267
+
268
+ frameworks_entries.each do |entry|
269
+ ref = lean_group.new_reference(entry)
270
+ target.frameworks_build_phase.add_file_reference(ref)
271
+ end
272
+ end
273
+
274
+ def add_build_setting(key, value)
275
+ target.build_configurations.each do |bc|
276
+ values = []
277
+ origin_values = bc.build_settings[key]
278
+ values.push(origin_values).flatten! if origin_values
279
+ values << value unless values.include?(value)
280
+ bc.build_settings[key] = values
281
+ end
282
+ end
283
+
284
+ def add_framework_search_path
285
+ add_build_setting('FRAMEWORK_SEARCH_PATHS', "\"$(SRCROOT)/#{@root_path}\"")
286
+ end
287
+
288
+ def add_linker_flags_if_needed
289
+ if Gem::Version.new(base_sdk_version) < Gem::Version.new('5.0')
290
+ add_build_setting('OTHER_LDFLAGS', '-fobjc-arc')
291
+ end
292
+ end
293
+
294
+ def save_project
295
+ project.save
296
+ end
297
+
298
+ def add_system_frameworks
299
+ target.add_system_frameworks(@system_frameworks)
300
+ end
301
+
302
+ def add_system_libraries
303
+ target.add_system_libraries(@system_libraries)
304
+ end
305
+
306
+ def integrate_sdk
307
+ unzip_sdk
308
+ remove_legency_frameworks
309
+ add_frameworks
310
+ add_framework_search_path
311
+ add_linker_flags_if_needed
312
+ add_system_frameworks
313
+ add_system_libraries
314
+ save_project
315
+ end
316
+
317
+ def finish
318
+ show_success('Install succeeded')
319
+ end
320
+
321
+ public
322
+
323
+ def install(file = nil)
324
+ @leanfile_path = file if file
325
+
326
+ read_leanfile
327
+ make_validation
328
+ create_directory_tree
329
+ download_framework
330
+ integrate_sdk
331
+ finish
332
+ end
333
+
334
+ def destroy
335
+ clean_stash
336
+ end
337
+
338
+ end
339
+
340
+ end
@@ -0,0 +1,32 @@
1
+ require 'colorize'
2
+
3
+ module LeanCloud
4
+
5
+ # Root class
6
+ class LeanObject
7
+
8
+ def show_error(msg)
9
+ puts(msg.colorize(:red))
10
+ end
11
+
12
+ def exit_with_error(msg)
13
+ show_error(msg)
14
+ exit
15
+ end
16
+
17
+ def exit_with_info(msg)
18
+ puts msg
19
+ exit
20
+ end
21
+
22
+ def show_success(msg)
23
+ puts(msg.colorize(:green))
24
+ end
25
+
26
+ def show_message(msg)
27
+ puts("==> #{msg}")
28
+ end
29
+
30
+ end
31
+
32
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leancloud
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Tianyong Tang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xcodeproj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.23.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.23.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.7.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.7.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: clactive
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: mustache
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ description: LeanCloud command line tool.
70
+ email: ttang@leancloud.rocks
71
+ executables:
72
+ - leancloud
73
+ - leancloud_dump_syms
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - lib/leancloud/http/lean_http.rb
78
+ - lib/leancloud/http/symbol_uploader.rb
79
+ - lib/leancloud/http.rb
80
+ - lib/leancloud/initializer.rb
81
+ - lib/leancloud/installer.rb
82
+ - lib/leancloud/leanobject.rb
83
+ - lib/leancloud.rb
84
+ - bin/leancloud
85
+ - bin/leancloud_dump_syms
86
+ homepage: https://leancloud.cn/
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: '2.0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.0.14
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: LeanCloud
110
+ test_files: []