appsendr 0.0.3 → 0.0.5
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.
- data/Manifest +4 -0
- data/Rakefile +2 -2
- data/appsendr.gemspec +5 -8
- data/lib/appsendr/client.rb +105 -29
- data/lib/appsendr/command.rb +14 -3
- data/lib/appsendr/commands/app.rb +46 -33
- data/lib/appsendr/commands/auth.rb +5 -21
- data/lib/appsendr/commands/base.rb +1 -0
- data/lib/appsendr/commands/build.rb +139 -19
- data/lib/appsendr/commands/collaborators.rb +29 -1
- data/lib/appsendr/commands/deploy.rb +13 -2
- data/lib/appsendr/commands/groups.rb +63 -0
- data/lib/appsendr/commands/help.rb +10 -3
- data/lib/appsendr/commands/portal.rb +375 -0
- data/lib/appsendr/commands/testers.rb +14 -31
- data/lib/appsendr/constants.rb +1 -1
- data/lib/appsendr/helpers.rb +31 -7
- data/lib/appsendr/progressbar.rb +236 -0
- metadata +12 -20
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 = "
|
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"
|
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.
|
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{
|
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{
|
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
|
data/lib/appsendr/client.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
155
|
-
|
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}
|
data/lib/appsendr/command.rb
CHANGED
@@ -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 "
|
31
|
-
rescue RestClient::RequestFailed
|
32
|
-
|
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
|
-
|
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
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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'
|
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 "
|
78
|
+
print "Email: "
|
77
79
|
user = ask
|
78
80
|
|
79
81
|
print "Password: "
|
80
|
-
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
|