appsendr 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -1,6 +1,7 @@
1
1
  Manifest
2
2
  README.rdoc
3
3
  Rakefile
4
+ appsendr.gemspec
4
5
  bin/appsendr
5
6
  lib/appsendr.rb
6
7
  lib/appsendr/binary_plist.rb
@@ -12,9 +13,12 @@ lib/appsendr/commands/base.rb
12
13
  lib/appsendr/commands/build.rb
13
14
  lib/appsendr/commands/collaborators.rb
14
15
  lib/appsendr/commands/deploy.rb
16
+ lib/appsendr/commands/groups.rb
15
17
  lib/appsendr/commands/help.rb
18
+ lib/appsendr/commands/portal.rb
16
19
  lib/appsendr/commands/testers.rb
17
20
  lib/appsendr/commands/version.rb
18
21
  lib/appsendr/constants.rb
19
22
  lib/appsendr/helpers.rb
23
+ lib/appsendr/progressbar.rb
20
24
  terms
data/Rakefile CHANGED
@@ -7,10 +7,10 @@ Echoe.new('appsendr', AppSendr::VERSION) do |p|
7
7
  p.description = "A gem that will build and distribute an iphone/ipad app to the web for remote install"
8
8
  p.url = "http://www.appsendr.com/gem"
9
9
  p.author = "AppSendr"
10
- p.email = "nolanbrown@gmail.com"
10
+ p.email = "nolan@appsendr.com"
11
11
  p.ignore_pattern = ["tmp/*", "script/*"]
12
12
  p.development_dependencies = []
13
- p.runtime_dependencies = ["rest-client >=1.4.0", "rubyzip", "json_pure >=1.2.0", "aws-s3"]
13
+ p.runtime_dependencies = ["rest-client >=1.4.0", "rubyzip", "json_pure >=1.2.0"]
14
14
  p.has_rdoc = true
15
15
 
16
16
  end
data/appsendr.gemspec CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{appsendr}
5
- s.version = "0.0.3"
5
+ s.version = "0.0.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["AppSendr"]
9
- s.date = %q{2010-12-27}
9
+ s.date = %q{2011-01-23}
10
10
  s.default_executable = %q{appsendr}
11
11
  s.description = %q{A gem that will build and distribute an iphone/ipad app to the web for remote install}
12
- s.email = %q{nolanbrown@gmail.com}
12
+ s.email = %q{nolan@appsendr.com}
13
13
  s.executables = ["appsendr"]
14
- s.extra_rdoc_files = ["README.rdoc", "bin/appsendr", "lib/appsendr.rb", "lib/appsendr/binary_plist.rb", "lib/appsendr/client.rb", "lib/appsendr/command.rb", "lib/appsendr/commands/app.rb", "lib/appsendr/commands/auth.rb", "lib/appsendr/commands/base.rb", "lib/appsendr/commands/build.rb", "lib/appsendr/commands/collaborators.rb", "lib/appsendr/commands/deploy.rb", "lib/appsendr/commands/help.rb", "lib/appsendr/commands/testers.rb", "lib/appsendr/commands/version.rb", "lib/appsendr/constants.rb", "lib/appsendr/helpers.rb"]
15
- s.files = ["Manifest", "README.rdoc", "Rakefile", "bin/appsendr", "lib/appsendr.rb", "lib/appsendr/binary_plist.rb", "lib/appsendr/client.rb", "lib/appsendr/command.rb", "lib/appsendr/commands/app.rb", "lib/appsendr/commands/auth.rb", "lib/appsendr/commands/base.rb", "lib/appsendr/commands/build.rb", "lib/appsendr/commands/collaborators.rb", "lib/appsendr/commands/deploy.rb", "lib/appsendr/commands/help.rb", "lib/appsendr/commands/testers.rb", "lib/appsendr/commands/version.rb", "lib/appsendr/constants.rb", "lib/appsendr/helpers.rb", "terms", "appsendr.gemspec"]
14
+ s.extra_rdoc_files = ["README.rdoc", "bin/appsendr", "lib/appsendr.rb", "lib/appsendr/binary_plist.rb", "lib/appsendr/client.rb", "lib/appsendr/command.rb", "lib/appsendr/commands/app.rb", "lib/appsendr/commands/auth.rb", "lib/appsendr/commands/base.rb", "lib/appsendr/commands/build.rb", "lib/appsendr/commands/collaborators.rb", "lib/appsendr/commands/deploy.rb", "lib/appsendr/commands/groups.rb", "lib/appsendr/commands/help.rb", "lib/appsendr/commands/portal.rb", "lib/appsendr/commands/testers.rb", "lib/appsendr/commands/version.rb", "lib/appsendr/constants.rb", "lib/appsendr/helpers.rb", "lib/appsendr/progressbar.rb"]
15
+ s.files = ["Manifest", "README.rdoc", "Rakefile", "bin/appsendr", "lib/appsendr.rb", "lib/appsendr/binary_plist.rb", "lib/appsendr/client.rb", "lib/appsendr/command.rb", "lib/appsendr/commands/app.rb", "lib/appsendr/commands/auth.rb", "lib/appsendr/commands/base.rb", "lib/appsendr/commands/build.rb", "lib/appsendr/commands/collaborators.rb", "lib/appsendr/commands/deploy.rb", "lib/appsendr/commands/groups.rb", "lib/appsendr/commands/help.rb", "lib/appsendr/commands/portal.rb", "lib/appsendr/commands/testers.rb", "lib/appsendr/commands/version.rb", "lib/appsendr/constants.rb", "lib/appsendr/helpers.rb", "lib/appsendr/progressbar.rb", "terms", "appsendr.gemspec"]
16
16
  s.homepage = %q{http://www.appsendr.com/gem}
17
17
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Appsendr", "--main", "README.rdoc"]
18
18
  s.require_paths = ["lib"]
@@ -28,17 +28,14 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency(%q<rest-client>, [">= 1.4.0"])
29
29
  s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
30
30
  s.add_runtime_dependency(%q<json_pure>, [">= 1.2.0"])
31
- s.add_runtime_dependency(%q<aws-s3>, [">= 0"])
32
31
  else
33
32
  s.add_dependency(%q<rest-client>, [">= 1.4.0"])
34
33
  s.add_dependency(%q<rubyzip>, [">= 0"])
35
34
  s.add_dependency(%q<json_pure>, [">= 1.2.0"])
36
- s.add_dependency(%q<aws-s3>, [">= 0"])
37
35
  end
38
36
  else
39
37
  s.add_dependency(%q<rest-client>, [">= 1.4.0"])
40
38
  s.add_dependency(%q<rubyzip>, [">= 0"])
41
39
  s.add_dependency(%q<json_pure>, [">= 1.2.0"])
42
- s.add_dependency(%q<aws-s3>, [">= 0"])
43
40
  end
44
41
  end
@@ -4,7 +4,7 @@ require 'uri'
4
4
  require 'time'
5
5
  require 'appsendr/constants'
6
6
  require 'json/pure' unless {}.respond_to?(:to_json)
7
- require 'aws/s3'
7
+
8
8
  # A Ruby class to call the AppSendr REST API.
9
9
  #
10
10
  # Example:
@@ -64,6 +64,17 @@ class AppSendr::Client
64
64
  post('/api/app/create.json', {:name=>name})
65
65
  end
66
66
 
67
+ def devices(app_id,plist=true)
68
+ format = "json"
69
+ format = "plist" if plist
70
+
71
+ if app_id
72
+ get("/api/tester/devices.#{format}", {:app_id=>app_id})
73
+ else
74
+ get("/api/tester/devices.#{format}")
75
+ end
76
+ end
77
+
67
78
  def add_tester(app_id,email,name,udid=nil)
68
79
  post('/api/tester/create.json',{:email=>email, :name=>name, :app_id=>app_id.to_s});
69
80
  end
@@ -88,6 +99,16 @@ class AppSendr::Client
88
99
  get('/api/app/groups/'+app_id.to_s+'.json')
89
100
  end
90
101
 
102
+
103
+ def add_group_tester(app_id,name, email)
104
+ post('/api/group/add_tester.json',{:name=>name,:app_id=>app_id.to_s, :email=>email});
105
+ end
106
+
107
+ def remove_group_tester(app_id, name, email)
108
+ post('/api/group/remove_tester.json',{:name=>name,:app_id=>app_id.to_s, :email=>email});
109
+ end
110
+
111
+
91
112
  ### add_collaborator
92
113
 
93
114
  def add_collaborator(app_id,emaill)
@@ -105,11 +126,11 @@ class AppSendr::Client
105
126
  def testers(app_id)
106
127
  get('/api/app/testers/'+app_id.to_s+'.json')
107
128
  end
108
- def notify(app_id)
109
- get('/api/app/notify/'+app_id.to_s+'.json')
129
+ def notify(app_id,group=nil)
130
+ post('/api/app/notify/'+app_id.to_s+'.json',{:group=>group})
110
131
  end
111
132
 
112
- def upload(app_id, ipa,provisioning,notify, notes, bundle_id, icon)
133
+ def upload(app_id, ipa,provisioning, notify, notes, bundle_id, icon, later=false)
113
134
  params = {
114
135
  :provisioning_profile => File.new(provisioning, 'rb'),
115
136
  :notes=>notes,
@@ -119,41 +140,82 @@ class AppSendr::Client
119
140
  :app_id => app_id.to_s
120
141
  # :ipa=>
121
142
  }
122
-
123
143
  if icon
124
144
  params[:icon] = File.new(icon,'rb')
125
145
  end
126
- if(is_file_to_large?(ipa))
127
- puts "IPA is too large to upload."
128
- else
129
- params[:ipa] = File.new(ipa, 'rb')
130
-
131
- post('/api/version/create/', {:version=>params})
132
- end
146
+
147
+ if later
148
+ params[:upload_later] = File.basename(ipa)
149
+
150
+ else
151
+ params[:ipa] = File.new(ipa, 'rb')
152
+
153
+ end
154
+
155
+ post('/api/version/create.json', {:version=>params})
133
156
  end
134
157
 
135
- protected
136
- def is_file_to_large?(file)
137
- in_mb = size_of_file(file).to_f
138
- if in_mb > 10
139
- return true
140
- else
141
- return false
142
- end
143
-
158
+ def initialize_multipart(app_id, version_id, ipa)
159
+ ipa_name = File.basename(ipa)
160
+
161
+ params = {}
162
+ params[:ipa_path] = upload_path(app_id,version_id,ipa_name)
163
+ params[:ipa_name] = ipa_name
164
+ params[:id] = version_id
165
+
166
+ post('/api/version/multipart_init.json', {:version=>params})
144
167
  end
168
+
169
+ def upload_part(app_id, version_id, ipa, upload_id, part_number, chunk)
170
+ ipa_name = File.basename(ipa)
171
+ ipa_size = File.size(ipa)
172
+
173
+ params = {}
174
+ params[:ipa_chunk] = File.new(chunk,'rb')
175
+ params[:ipa_size] = ipa_size
176
+ params[:ipa_path] = upload_path(app_id,version_id,ipa_name)
177
+ params[:upload_id] = upload_id
178
+ params[:part_number] = part_number
179
+ params[:id] = version_id
145
180
 
146
- def size_of_file(file)
147
- size = File.size(file)
148
- mb = 1024.0 * 1024.0
149
- in_mb = size / mb
150
-
181
+ retryable( :tries => 5 ) do
182
+ resp = post('/api/version/multipart_upload_part.json', {:version=>params})
183
+ return resp
184
+ end
151
185
  end
186
+
187
+ def finish_multipart(app_id, version_id, ipa, upload_id, parts)
188
+ ipa_name = File.basename(ipa)
189
+ ipa_size = File.size(ipa)
152
190
 
191
+ params = {}
192
+ params[:ipa_size] = ipa_size
193
+ params[:ipa_path] = upload_path(app_id,version_id,ipa_name)
194
+ params[:upload_id] = upload_id
195
+ params[:parts] = parts
196
+ params[:id] = version_id
153
197
 
154
- def upload_to_s3_directly
155
- @s3_url = "http://appsendr.s3.amazonaws.com/"
156
-
198
+ post('/api/version/multipart_finished.json', {:version=>params})
199
+
200
+
201
+ end
202
+
203
+ def abort_multipart(app_id, version_id, ipa, upload_id)
204
+ params = { :version=> {
205
+ :ipa_path=>upload_path(app_id,version_id,File.basename(ipa)),
206
+ :upload_id=>upload_id,
207
+ :id=>version_id
208
+ }
209
+ }
210
+ post('/api/version/abort_multipart.json',params)
211
+
212
+ end
213
+
214
+ protected
215
+
216
+
217
+ def upload_path(app_id,version_id,ipa_name)
218
+ "app/#{app_id}/#{version_id}/ipa/#{ipa_name}"
157
219
  end
158
220
 
159
221
  def api_params(params={})
@@ -161,6 +223,20 @@ class AppSendr::Client
161
223
 
162
224
  end
163
225
 
226
+ def retryable(options = {}, &block)
227
+ opts = { :tries => 1, :on => Exception }.merge(options)
228
+
229
+ retry_exception, retries = opts[:on], opts[:tries]
230
+
231
+ begin
232
+ return yield
233
+ rescue retry_exception
234
+ retry if (retries -= 1) > 0
235
+ end
236
+
237
+ yield
238
+ end
239
+
164
240
  def get(uri,params={})
165
241
  params[:api_key] ||= @api_key
166
242
  resp = RestClient.get @resource.url+uri, {:params=>params}
@@ -1,6 +1,7 @@
1
1
  require 'appsendr/helpers'
2
2
  require 'appsendr/binary_plist'
3
3
  require 'appsendr/commands/base'
4
+ require 'appsendr/progressbar'
4
5
 
5
6
  Dir["#{File.dirname(__FILE__)}/commands/*.rb"].each { |c| require c }
6
7
 
@@ -27,13 +28,23 @@ module AppSendr
27
28
  error "Authentication failure"
28
29
  end
29
30
  rescue RestClient::ResourceNotFound
30
- error "Resouce not found."
31
- rescue RestClient::RequestFailed
32
- error "Something went wrong with the server."
31
+ error "Record not found. Are you allowed to access this record?"
32
+ rescue RestClient::RequestFailed => e
33
+ begin
34
+ response = JSON.parse(e.http_body)
35
+ display "=== Errors"
36
+ response['message'].each{|err|
37
+ display err.join(" ")
38
+ }
39
+ rescue
40
+ error "Something went wrong with the server."
41
+ end
33
42
  rescue CommandFailed => e
34
43
  error e.message
35
44
  rescue Interrupt => e
36
45
  error "\n[canceled]"
46
+ rescue Exception => e
47
+ error e
37
48
  end
38
49
  end
39
50
 
@@ -7,7 +7,7 @@ module AppSendr::Command
7
7
  def list
8
8
  list = appsendr.list
9
9
  if list["message"].size > 0
10
- display "=== Your apps"
10
+ message "Your apps"
11
11
  i = 0
12
12
  display list["message"].map {|app, id|
13
13
  "#{i+=1}. #{app['name'].ljust(35)}"
@@ -23,15 +23,42 @@ module AppSendr::Command
23
23
  # password = extract_option('--password')
24
24
  # display password
25
25
  #
26
+ name = args.join(" ").strip
26
27
 
27
- if require_in_project_and_no_droppr(1,"an app name","a name to create an app on appsendr",true)
28
- name = args.join(" ").strip
29
- resp = appsendr.create(name)
30
- make_appsendr_dir if resp['message']
31
- @app = [resp['message']['id'],resp['message']['name']]
32
- write_app
33
- display "Your app has been created."
34
-
28
+ if require_project(1,"an app name","a name to create an app on appsendr",true)
29
+ if has_project_droppr?
30
+ list = appsendr.list
31
+ if list["message"].size > 0
32
+ list["message"].each{|app|
33
+ if app['name'] == name
34
+ remove_appsendr_dir
35
+ make_appsendr_dir
36
+
37
+ @app = [ app['id'], app['name']]
38
+ write_app
39
+ display "Your app has been linked."
40
+ return
41
+ end
42
+ }
43
+
44
+ resp = appsendr.create(name)
45
+ remove_appsendr_dir
46
+ make_appsendr_dir if resp['message']
47
+ @app = [resp['message']['id'],resp['message']['name']]
48
+ write_app
49
+ display "Your app has been created."
50
+
51
+ else
52
+ error "This app is linked to another account's app"
53
+ end
54
+ else
55
+ resp = appsendr.create(name)
56
+ make_appsendr_dir if resp['message']
57
+ @app = [resp['message']['id'],resp['message']['name']]
58
+ write_app
59
+ display "Your app has been created."
60
+ end
61
+
35
62
  end
36
63
  end
37
64
 
@@ -40,7 +67,7 @@ module AppSendr::Command
40
67
 
41
68
  resp = appsendr.current_version(get_app_id)
42
69
  if resp["message"].size > 0
43
- display "=== Your last install url is:"
70
+ message "Your last install url is:"
44
71
  url = resp["message"][0]['install_url']
45
72
  display url
46
73
  do_copy = option_exists?('--copy', false)
@@ -83,7 +110,7 @@ module AppSendr::Command
83
110
  lines = []
84
111
  list = appsendr.list
85
112
  if list["message"].size > 0
86
- display "=== Your apps"
113
+ message "Your apps"
87
114
  i = 0
88
115
  list["message"].each{|app|
89
116
  apps.push({"name"=>app['name'], "id"=>app['id']})
@@ -100,32 +127,13 @@ module AppSendr::Command
100
127
  display "You have no apps."
101
128
  end
102
129
  end
103
-
104
- def groups
105
- if in_project_dir?
106
-
107
- groups = appsendr.groups(get_app_id)
108
- if groups["message"].size > 0
109
- display "=== Your groups"
110
- i = 0
111
- display groups["message"].map {|app, id|
112
- "#{i+=1}. #{app['name'].ljust(35)}"
113
- }.join("\n")
114
- else
115
- display "You have no groups."
116
- end
117
- else
118
- error("You are not in a project directory")
119
- end
120
- end
121
-
122
-
130
+
123
131
  def versions
124
132
  if in_project_dir?
125
133
 
126
134
  groups = appsendr.versions(get_app_id)
127
135
  if groups["message"].size > 0
128
- display "=== Your versions"
136
+ message "Your versions"
129
137
  i = 0
130
138
  display groups["message"].map {|app, id|
131
139
  "#{i+=1}. #{app['notes']} #{app['install_url']}"
@@ -189,7 +197,12 @@ module AppSendr::Command
189
197
  # end
190
198
 
191
199
  protected
192
-
200
+ def remove_appsendr_dir
201
+ if in_project_dir?
202
+ FileUtils.rm_r(Dir.pwd+"/"+AppSendr::PROJECT_DIR)
203
+ end
204
+ end
205
+
193
206
  def make_appsendr_dir
194
207
  if in_project_dir?
195
208
  FileUtils.mkdir_p(Dir.pwd+"/"+AppSendr::PROJECT_DIR)
@@ -22,7 +22,9 @@ module AppSendr::Command
22
22
  end
23
23
 
24
24
  def host
25
- ENV['APPDROPPR_HOST'] || 'appsendr.com' ##'appsendr.heroku.com' #
25
+ ENV['APPDROPPR_HOST'] || 'appsendr.com'
26
+ #ENV['APPDROPPR_HOST'] || '0.0.0.0:3000'
27
+
26
28
  end
27
29
 
28
30
  def reauthorize
@@ -73,33 +75,15 @@ module AppSendr::Command
73
75
  def ask_for_credentials
74
76
  puts "Enter your AppSendr credentials."
75
77
 
76
- print "Username: "
78
+ print "Email: "
77
79
  user = ask
78
80
 
79
81
  print "Password: "
80
- password = running_on_windows? ? ask_for_password_on_windows : ask_for_password
82
+ password = ask_for_password
81
83
 
82
84
  [ user, password ]
83
85
  end
84
86
 
85
- def ask_for_password_on_windows
86
- require "Win32API"
87
- char = nil
88
- password = ''
89
-
90
- while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do
91
- break if char == 10 || char == 13 # received carriage return or newline
92
- if char == 127 || char == 8 # backspace and delete
93
- password.slice!(-1, 1)
94
- else
95
- # windows might throw a -1 at us so make sure to handle RangeError
96
- (password << char.chr) rescue RangeError
97
- end
98
- end
99
- puts
100
- return password
101
- end
102
-
103
87
  def ask_for_password
104
88
  echo_off
105
89
  password = ask
@@ -51,6 +51,7 @@ module AppSendr::Command
51
51
  def option_exists?(options, default=true)
52
52
  values = options.is_a?(Array) ? options : [options]
53
53
  return false unless opt_index = args.select { |a| values.include? a }.first
54
+ args.delete(opt_index)
54
55
  return true
55
56
  end
56
57