replicant-adb 0.0.1 → 1.0.1

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.
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - "1.9.3"
4
- script: "bundle exec rake test"
data/Gemfile DELETED
@@ -1,19 +0,0 @@
1
- source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
-
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
- gem "activesupport-core-ext", "~> 4.0", :require => false
9
-
10
- group :development do
11
- gem "rake", "~> 10.1"
12
- gem "bundler", "~> 1.0"
13
- gem "jeweler", "~> 1.8.7"
14
- end
15
-
16
- group :test do
17
- gem "minitest", "~> 5.0", :require => 'minitest/autorun'
18
- gem "mocha", "~> 0.14.0", :require => 'mocha/setup'
19
- end
data/Rakefile DELETED
@@ -1,40 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'rubygems'
4
- require 'bundler'
5
- require './lib/replicant/version'
6
-
7
- begin
8
- Bundler.setup(:default, :development)
9
- rescue Bundler::BundlerError => e
10
- $stderr.puts e.message
11
- $stderr.puts "Run `bundle install` to install missing gems"
12
- exit e.status_code
13
- end
14
- require 'rake'
15
-
16
- require 'jeweler'
17
- Jeweler::Tasks.new do |gem|
18
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
- gem.name = "replicant-adb"
20
- gem.version = Replicant::VERSION
21
- gem.homepage = "https://github.com/mttkay/replicant"
22
- gem.license = "MIT"
23
- gem.summary = "A REPL for the Android Debug Bridge"
24
- gem.description = "replicant is an interactive shell (a REPL) for ADB, the Android Debug Bridge"
25
- gem.email = "m.kaeppler@gmail.com"
26
- gem.authors = ["Matthias Kaeppler"]
27
- gem.files.exclude 'screenshots/**'
28
- # dependencies defined in Gemfile
29
- end
30
- Jeweler::RubygemsDotOrgTasks.new
31
-
32
- require 'rake/testtask'
33
- Rake::TestTask.new(:test) do |test|
34
- test.libs << 'lib' << 'test'
35
- test.pattern = 'test/**/*_spec.rb'
36
- test.verbose = true
37
- end
38
-
39
- task :default => :test
40
-
@@ -1,352 +0,0 @@
1
- require 'stringio'
2
-
3
- class Command
4
-
5
- def self.inherited(subclass)
6
- @@subclasses ||= []
7
- @@subclasses << subclass
8
- end
9
-
10
- def self.all
11
- (@@subclasses - [AdbCommand, ListCommand, EnvCommand]).map do |clazz|
12
- clazz.new(nil)
13
- end
14
- end
15
-
16
- def self.load(repl, command_line)
17
- if command_line == '!'
18
- # load command that lists available commands
19
- ListCommand.new(repl)
20
- elsif command_line == '?'
21
- EnvCommand.new(repl)
22
- elsif command_line.start_with?('!')
23
- # load custom command
24
- command_parts = command_line[1..-1].split
25
- command_name = command_parts.first
26
- command_args = command_parts[1..-1].join(' ')
27
- command_class = "#{command_name.capitalize}Command"
28
- begin
29
- clazz = Object.const_get(command_class)
30
- clazz.new(repl, command_args)
31
- rescue NameError => e
32
- nil
33
- end
34
- else
35
- # forward command to ADB
36
- AdbCommand.new(repl, command_line.strip)
37
- end
38
- end
39
-
40
- attr_reader :args
41
-
42
- def initialize(repl, args = nil, options = {})
43
- @repl = repl
44
- @args = args.strip if args
45
- @options = options
46
- end
47
-
48
- def name
49
- "!#{self.class.name.gsub("Command", "").downcase}"
50
- end
51
-
52
- # subclasses override this to provide a description of their functionality
53
- def description
54
- "TODO: description missing"
55
- end
56
-
57
- # subclasses override this to provide a usage example
58
- def usage
59
- end
60
-
61
- def execute
62
- if valid_args?
63
- run
64
- else
65
- output "Invalid arguments. Ex.: #{usage}"
66
- end
67
- end
68
-
69
- private
70
-
71
- def valid_args?
72
- true
73
- end
74
-
75
- def output(message)
76
- puts message unless @options[:silent]
77
- end
78
-
79
- end
80
-
81
- class AdbCommand < Command
82
-
83
- # the command line program
84
- ADB = 'adb'
85
-
86
- def run
87
- begin
88
- cmd = "#{adb} #{args}"
89
-
90
- if interactive?
91
- system cmd
92
- else
93
- cmd << " #{@repl.default_package}" if @repl.default_package && package_dependent?
94
- output cmd if @repl.debug?
95
- result = `#{cmd}`
96
- output result
97
- result
98
- end
99
- end
100
- end
101
-
102
- private
103
-
104
- def adb
105
- adb = "#{ADB}"
106
- adb << " -s #{@repl.default_device.id}" if @repl.default_device
107
- adb
108
- end
109
-
110
- def interactive?
111
- args == "shell" || args.start_with?("logcat")
112
- end
113
-
114
- def package_dependent?
115
- ["uninstall"].include?(args)
116
- end
117
- end
118
-
119
- class DevicesCommand < Command
120
- def description
121
- "print a list of connected devices"
122
- end
123
-
124
- def run
125
- adb = AdbCommand.new(@repl, "devices -l", :silent => true)
126
- device_lines = adb.execute.lines.to_a.reject do |line|
127
- line.strip.empty? || line.include?("daemon") || line.include?("List of devices")
128
- end
129
-
130
- device_ids = device_lines.map { |l| /([\S]+)\s+device/.match(l)[1] }
131
- device_products = device_lines.map { |l| /product:([\S]+)/.match(l).try(:[], 1) }
132
-
133
- device_names = device_lines.zip(device_ids).map do |l, id|
134
- /model:([\S]+)/.match(l).try(:[], 1) || detect_device_name(id)
135
- end
136
-
137
- devices = device_ids.zip(device_names, device_products).map do |id, name, product|
138
- Device.new(id, humanize_name(name, product))
139
- end
140
-
141
- output ""
142
- output devices_string(devices)
143
- output ""
144
- devices
145
- end
146
-
147
- private
148
-
149
- def detect_device_name(id)
150
- if id.start_with?("emulator-")
151
- "Android emulator"
152
- else
153
- "Unknown device"
154
- end
155
- end
156
-
157
- def humanize_name(name_string, product)
158
- if product == "vbox86p"
159
- "Genymotion " + name_string.gsub(/___[\d_]+___/, "_")
160
- else
161
- name_string
162
- end.gsub('_', ' ').squish
163
- end
164
-
165
- def devices_string(devices)
166
- device_string = if devices.any?
167
- padding = devices.map { |d| d.name.length }.max
168
- indices = (0..devices.length - 1).to_a
169
- indices.zip(devices).map { |i, d| "[#{i}] #{d.name}#{' ' * (padding - d.name.length)} | #{d.id}" }
170
- else
171
- "No devices found"
172
- end
173
- end
174
- end
175
-
176
- class PackageCommand < Command
177
-
178
- def description
179
- "set a default package to work with"
180
- end
181
-
182
- def usage
183
- "#{name} com.mydomain.mypackage"
184
- end
185
-
186
- def valid_args?
187
- args.present? && /^\w+(\.\w+)*$/ =~ args
188
- end
189
-
190
- def run
191
- output "Setting default package to #{args.inspect}"
192
- @repl.default_package = args
193
- end
194
- end
195
-
196
- class DeviceCommand < Command
197
- def description
198
- "set a default device to work with"
199
- end
200
-
201
- def usage
202
- "#{name} [<index>|<device_id>]"
203
- end
204
-
205
- def valid_args?
206
- args.present? && /\S+/ =~ args
207
- end
208
-
209
- def run
210
- default_device = if index?
211
- # user selected by index
212
- devices[args.to_i]
213
- else
214
- # user selected by device ID
215
- devices.detect { |d| d.id == args }
216
- end
217
-
218
- if default_device
219
- output "Setting default device to #{default_device.inspect}"
220
- @repl.default_device = default_device
221
- else
222
- output "No such device"
223
- end
224
- end
225
-
226
- private
227
-
228
- def index?
229
- /^\d+$/ =~ args
230
- end
231
-
232
- def devices
233
- @devices ||= DevicesCommand.new(@repl, nil, :silent => true).execute
234
- end
235
-
236
- end
237
-
238
- class ResetCommand < Command
239
-
240
- def description
241
- "clear current device and package"
242
- end
243
-
244
- def valid_args?
245
- args.blank?
246
- end
247
-
248
- def run
249
- @repl.default_device = nil
250
- @repl.default_package = nil
251
- end
252
-
253
- end
254
-
255
- class ListCommand < Command
256
- def valid_args?
257
- args.blank?
258
- end
259
-
260
- def description
261
- "print a list of available commands"
262
- end
263
-
264
- def run
265
- command_list = Command.all.sort_by {|c| c.name}.map do |command|
266
- padding = 20 - command.name.length
267
- desc = "#{command.name} #{' ' * padding} -- #{command.description}"
268
- desc
269
- end
270
- output command_list.join("\n")
271
- end
272
- end
273
-
274
- class RestartCommand < Command
275
- def description
276
- "restart ADB"
277
- end
278
-
279
- def run
280
- # Faster than kill-server, and also catches ADB instances launched by
281
- # IntelliJ. Moreover, start-server after kill-server sometimes makes the
282
- # server fail to start up unless you sleep for a second or so
283
- `killall adb`
284
- AdbCommand.new(@repl, "start-server").execute
285
- end
286
- end
287
-
288
- class LogcatCommand < Command
289
-
290
- def description
291
- "access device logs"
292
- end
293
-
294
- def valid_args?
295
- args.blank?
296
- end
297
-
298
- def run
299
- pid = if @repl.default_package
300
- processes = AdbCommand.new(@repl, "shell ps", :silent => true).execute
301
- pid_line = processes.lines.detect {|l| l.include?(@repl.default_package)}
302
- pid_line.split[1].strip if pid_line
303
- end
304
-
305
- logcat = "logcat -v time"
306
- logcat << " | grep -E '\(\s*#{pid}\)'"
307
- AdbCommand.new(@repl, logcat).execute
308
- end
309
- end
310
-
311
- class ClearCommand < Command
312
-
313
- def description
314
- "clear application data"
315
- end
316
-
317
- # TODO: this is not a very good argument validator
318
- def valid_args?
319
- args.present? || @repl.default_package
320
- end
321
-
322
- def usage
323
- "#{name} [com.example.package|<empty>(when default package is set)]"
324
- end
325
-
326
- def run
327
- package = args.present? ? args : @repl.default_package
328
- # Clear app data - cache, SharedPreferences, Databases
329
- AdbCommand.new(@repl, "shell su -c \"rm -r /data/data/#{package}/*\"").execute
330
- # Force application stop to recreate shared preferences, databases with new launch
331
- AdbCommand.new(@repl, "shell am force-stop #{package}").execute
332
- end
333
- end
334
-
335
- class EnvCommand < Command
336
-
337
- def valid_args?
338
- args.blank?
339
- end
340
-
341
- def run
342
- env = "Package: #{@repl.default_package || 'Not set'}\n"
343
- env << "Device: "
344
- device = @repl.default_device
345
- env << if device
346
- "#{device.name} (#{device.id})"
347
- else
348
- 'Not set'
349
- end
350
- output env
351
- end
352
- end
@@ -1,58 +0,0 @@
1
- require 'helper'
2
-
3
- class AdbCommandSpec < CommandSpecBase
4
-
5
- describe "a basic adb command" do
6
- before do
7
- @command = silent AdbCommand.new(@repl, "devices")
8
- @command.execute
9
- end
10
-
11
- it "sends a command to adb and captures the output" do
12
- @command.backtick_capture.must_equal "adb devices"
13
- end
14
-
15
- it "does not use Kernel#system" do
16
- @command.system_capture.must_be_nil
17
- end
18
- end
19
-
20
- describe "an interactive command" do
21
- before do
22
- @command = AdbCommand.new(@repl, "shell")
23
- @command.execute
24
- end
25
-
26
- it "is executed using a Kernel#system call" do
27
- @command.system_capture.must_equal "adb shell"
28
- end
29
-
30
- describe "when it's 'shell'" do
31
- it "is not treated as interactive when arguments are present" do
32
- command = AdbCommand.new(@repl, "shell ps")
33
- command.execute
34
- command.system_capture.must_be_nil
35
- command.backtick_capture.must_equal "adb shell ps"
36
- end
37
- end
38
- end
39
-
40
- describe "with a default package set" do
41
- before do
42
- @repl.stubs(:default_package).returns("com.myapp")
43
- end
44
-
45
- it "does not set the default package if command is not package dependent" do
46
- command = silent AdbCommand.new(@repl, "devices")
47
- command.execute
48
- command.backtick_capture.must_equal "adb devices"
49
- end
50
-
51
- it "adds the default package if command is package dependent" do
52
- command = silent AdbCommand.new(@repl, "uninstall")
53
- command.execute
54
- command.backtick_capture.must_equal "adb uninstall com.myapp"
55
- end
56
- end
57
-
58
- end