leancloud 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []