Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1896)

Side by Side Diff: sky/tools/skydb

Issue 1164023004: Rename skydb to mojodb (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Update docs Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/HACKING.md ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 from skypy.skyserver import SkyServer
7 import argparse
8 import json
9 import logging
10 import os
11 import pipes
12 import re
13 import requests
14 import signal
15 import skypy.paths
16 import StringIO
17 import subprocess
18 import sys
19 import time
20 import urlparse
21 import platform
22
23 SUPPORTED_MIME_TYPES = [
24 'text/html',
25 'text/sky',
26 'text/plain',
27 ]
28
29 DEFAULT_SKY_COMMAND_PORT = 7777
30 GDB_PORT = 8888
31 SKY_SERVER_PORT = 9999
32 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example s/home.sky"
33
34 ANDROID_PACKAGE = "org.chromium.mojo.shell"
35 ANDROID_ACTIVITY = "%s/.MojoShellActivity" % ANDROID_PACKAGE
36 ANDROID_APK_NAME = 'MojoShell.apk'
37
38 PID_FILE_PATH = "/tmp/skydb.pids"
39 CACHE_LINKS_PATH = '/tmp/mojo_cache_links'
40
41 SRC_ROOT = skypy.paths.Paths('ignored').src_root
42 ADB_PATH = os.path.join(SRC_ROOT,
43 'third_party/android_tools/sdk/platform-tools/adb')
44
45 # TODO(iansf): Fix undefined behavior when you have more than one device attache d.
46 SYSTEM_LIBS_ROOT_PATH = '/tmp/device_libs/%s' % (subprocess.check_output([ADB_PA TH, 'get-serialno']).strip())
47
48
49 # FIXME: Move this into mopy.config
50 def gn_args_from_build_dir(build_dir):
51 gn_cmd = [
52 'gn', 'args',
53 build_dir,
54 '--list', '--short'
55 ]
56 config = {}
57 for line in subprocess.check_output(gn_cmd).strip().split('\n'):
58 # FIXME: This doesn't handle = in values.
59 key, value = line.split(' = ')
60 config[key] = value
61 return config
62
63
64 def ensure_assets_are_downloaded(build_dir):
65 sky_pkg_dir = os.path.join(build_dir, 'gen', 'dart-pkg', 'sky')
66 sky_pkg_lib_dir = os.path.join(sky_pkg_dir, 'lib')
67 sky_icons_dir = \
68 os.path.join(sky_pkg_lib_dir, 'assets', 'material-design-icons')
69 if not os.path.isdir(sky_icons_dir):
70 logging.info('NOTE: sky/assets/material-design-icons missing, '
71 'Running `download_material_design_icons` for you.')
72 subprocess.check_call(
73 [os.path.join(sky_pkg_lib_dir, 'download_material_design_icons')])
74
75 class SkyDebugger(object):
76 def __init__(self):
77 self.pids = {}
78 self.paths = None
79
80 def _server_root_for_url(self, url_or_path):
81 path = os.path.abspath(url_or_path)
82 if os.path.commonprefix([path, SRC_ROOT]) == SRC_ROOT:
83 server_root = SRC_ROOT
84 else:
85 server_root = os.path.dirname(path)
86 logging.warn(
87 '%s is outside of mojo root, using %s as server root' %
88 (path, server_root))
89 return server_root
90
91 def _in_chromoting(self):
92 return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False)
93
94 def _wrap_for_android(self, shell_args):
95 # am shell --esa: (someone shoot me now)
96 # [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
97 # (to embed a comma into a string escape it using "\,")
98 escaped_args = map(lambda arg: arg.replace(',', '\\,'), shell_args)
99 return [
100 ADB_PATH, 'shell',
101 'am', 'start',
102 '-W',
103 '-S',
104 '-a', 'android.intent.action.VIEW',
105 '-n', ANDROID_ACTIVITY,
106 # FIXME: This quoting is very error-prone. Perhaps we should read
107 # our args from a file instead?
108 '--esa', 'parameters', ','.join(escaped_args),
109 ]
110
111 def _build_mojo_shell_command(self, args, is_android):
112 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer')
113 for mime_type in SUPPORTED_MIME_TYPES]
114
115 remote_command_port = self.pids.get('remote_sky_command_port', self.pids ['sky_command_port'])
116 remote_server_port = self.pids.get('remote_sky_server_port', self.pids[' sky_server_port'])
117
118 shell_args = [
119 '--v=1',
120 '--content-handlers=%s' % ','.join(content_handlers),
121 '--url-mappings=mojo:window_manager=mojo:kiosk_wm',
122 '--args-for=mojo:debugger %d --wm' % remote_command_port,
123 'mojo:debugger',
124 ]
125
126 if args.url_or_path:
127 shell_args.append(
128 '--args-for=mojo:window_manager %s' % self._url_from_args(args))
129
130 if args.trace_startup:
131 shell_args.append('--trace-startup')
132
133 # Map all mojo: urls to http: urls using the --origin command.
134 build_dir_url = SkyServer.url_for_path(
135 remote_server_port,
136 self.pids['sky_server_root'],
137 self.pids['build_dir'])
138
139 # TODO(eseidel): We should do this on linux, but we need to fix
140 # mojo http loading to be faster first.
141 if is_android:
142 shell_args += ['--origin=%s' % build_dir_url]
143
144 # Desktop-only work-around for mojo crashing under chromoting.
145 if not is_android and args.use_osmesa:
146 shell_args.append(
147 '--args-for=mojo:native_viewport_service --use-osmesa')
148
149 if is_android and args.gdb:
150 shell_args.append('--wait-for-debugger')
151 shell_args.append('--predictable-app-filenames')
152
153 if 'remote_sky_server_port' in self.pids:
154 shell_command = self._wrap_for_android(shell_args)
155 else:
156 shell_command = [self.paths.mojo_shell_path] + shell_args
157
158 return shell_command
159
160 def sky_server_for_args(self, args, packages_root):
161 # FIXME: This is a hack. sky_server should just take a build_dir
162 # not a magical "configuration" name.
163 configuration = os.path.basename(os.path.normpath(self.paths.build_dir))
164 server_root = self._server_root_for_url(args.url_or_path)
165 return SkyServer(SKY_SERVER_PORT, configuration, server_root, packages_r oot)
166
167 def _create_paths_for_build_dir(self, build_dir):
168 # skypy.paths.Paths takes a root-relative build_dir argument. :(
169 abs_build_dir = os.path.abspath(build_dir)
170 root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT)
171 return skypy.paths.Paths(root_relative_build_dir)
172
173 def _find_remote_pid_for_package(self, package):
174 ps_output = subprocess.check_output([ADB_PATH, 'shell', 'ps'])
175 for line in ps_output.split('\n'):
176 fields = line.split()
177 if fields and fields[-1] == package:
178 return fields[1]
179 return None
180
181 def _find_install_location_for_package(self, package):
182 pm_command = [ADB_PATH, 'shell', 'pm', 'path', package]
183 pm_output = subprocess.check_output(pm_command)
184 # e.g. package:/data/app/org.chromium.mojo.shell-1/base.apk
185 return pm_output.split(':')[-1]
186
187 def start_command(self, args):
188 # FIXME: Lame that we use self for a command-specific variable.
189 self.paths = self._create_paths_for_build_dir(args.build_dir)
190 self.stop_command(None) # Quit any existing process.
191
192 # FIXME: This is probably not the right way to compute is_android
193 # from the build directory?
194 gn_args = gn_args_from_build_dir(self.paths.build_dir)
195 is_android = 'android_sdk_version' in gn_args
196
197 ensure_assets_are_downloaded(args.build_dir)
198
199 shell_found = True
200 if is_android:
201 apk_path = os.path.join(self.paths.build_dir, 'apks', ANDROID_APK_NA ME)
202 if not os.path.exists(apk_path):
203 print "%s not found in build_dir '%s'" % \
204 (ANDROID_APK_NAME, os.path.join(args.build_dir, 'apks'))
205 shell_found = False
206 elif not os.path.exists(self.paths.mojo_shell_path):
207 print "mojo_shell not found in build_dir '%s'" % args.build_dir
208 shell_found = False
209
210 if not shell_found:
211 print "Are you sure you sure that's a valid build_dir location?"
212 print "See skydb start --help for more info"
213 sys.exit(2)
214
215 if is_android and args.gdb and not 'is_debug' in gn_args:
216 # FIXME: We don't include gdbserver in the release APK...
217 print "Cannot debug Release builds on Android"
218 sys.exit(2)
219
220 dart_pkg_dir = os.path.join(self.paths.build_dir, 'gen', 'dart-pkg')
221 packages_root = os.path.join(dart_pkg_dir, 'packages')
222
223 sky_server = self.sky_server_for_args(args, packages_root)
224 self.pids['sky_server_pid'] = sky_server.start()
225 self.pids['sky_server_port'] = sky_server.port
226 self.pids['sky_server_root'] = sky_server.root
227
228 self.pids['build_dir'] = self.paths.build_dir
229 self.pids['sky_command_port'] = args.command_port
230
231 if is_android:
232 # TODO(eseidel): This should move into a helper method and handle
233 # failures with nice messages explaining how to get root.
234 subprocess.check_call([ADB_PATH, 'root'])
235
236 # We could make installing conditional on an argument.
237 # -r to replace an existing apk, -d to allow version downgrade.
238 subprocess.check_call([ADB_PATH, 'install', '-r', '-d', apk_path])
239
240 port_string = 'tcp:%s' % sky_server.port
241 subprocess.check_call([
242 ADB_PATH, 'reverse', port_string, port_string
243 ])
244 self.pids['remote_sky_server_port'] = sky_server.port
245
246 port_string = 'tcp:%s' % args.command_port
247 subprocess.check_call([
248 ADB_PATH, 'forward', port_string, port_string
249 ])
250 self.pids['remote_sky_command_port'] = args.command_port
251
252 shell_command = self._build_mojo_shell_command(args, is_android)
253
254 # On android we can't launch inside gdb, but rather have to attach.
255 if not is_android and args.gdb:
256 shell_command = ['gdbserver', ':%d' % GDB_PORT] + shell_command
257
258 print ' '.join(map(pipes.quote, shell_command))
259 # This pid is meaningless on android (it's the adb shell pid)
260 start_command_pid = subprocess.Popen(shell_command).pid
261
262 if is_android:
263 # TODO(eseidel): am start -W does not seem to work?
264 pid_tries = 0
265 while True:
266 pid = self._find_remote_pid_for_package(ANDROID_PACKAGE)
267 if pid or pid_tries > 3:
268 break
269 logging.debug('No pid for %s yet, waiting' % ANDROID_PACKAGE)
270 time.sleep(5)
271 pid_tries += 1
272
273 if not pid:
274 logging.error('Failed to find mojo_shell pid on device!')
275 return
276 self.pids['mojo_shell_pid'] = pid
277 else:
278 self.pids['mojo_shell_pid'] = start_command_pid
279
280 if args.gdb and is_android:
281 # We push our own copy of gdbserver with the package since
282 # the default gdbserver is a different version from our gdb.
283 package_path = \
284 self._find_install_location_for_package(ANDROID_PACKAGE)
285 gdb_server_path = os.path.join(
286 os.path.dirname(package_path), 'lib/arm/gdbserver')
287 gdbserver_cmd = [
288 ADB_PATH, 'shell',
289 gdb_server_path, '--attach',
290 ':%d' % GDB_PORT,
291 str(self.pids['mojo_shell_pid'])
292 ]
293 print ' '.join(map(pipes.quote, gdbserver_cmd))
294 self.pids['adb_shell_gdbserver_pid'] = \
295 subprocess.Popen(gdbserver_cmd).pid
296
297 port_string = 'tcp:%d' % GDB_PORT
298 subprocess.check_call([
299 ADB_PATH, 'forward', port_string, port_string
300 ])
301 self.pids['remote_gdbserver_port'] = GDB_PORT
302
303 if not args.gdb:
304 if not self._wait_for_sky_command_port():
305 logging.error('Failed to start sky')
306 self.stop_command(None)
307 else:
308 # We could just run gdb_attach_command here, but when I do that
309 # it auto-suspends in my zsh. Unclear why.
310 # self.gdb_attach_command(args)
311 print "Run 'skydb gdb_attach' to attach."
312
313 def _kill_if_exists(self, key, name):
314 pid = self.pids.pop(key, None)
315 if not pid:
316 logging.info('No pid for %s, nothing to do.' % name)
317 return
318 logging.info('Killing %s (%d).' % (name, pid))
319 try:
320 os.kill(pid, signal.SIGTERM)
321 except OSError:
322 logging.info('%s (%d) already gone.' % (name, pid))
323
324 def stop_command(self, args):
325 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown.
326 # self._run_basic_command('/quit')
327
328 self._kill_if_exists('sky_server_pid', 'sky_server')
329
330 if 'remote_sky_server_port' in self.pids:
331 port_string = 'tcp:%s' % self.pids['remote_sky_server_port']
332 subprocess.call([ADB_PATH, 'reverse', '--remove', port_string])
333
334 if 'remote_sky_command_port' in self.pids:
335 # adb forward --remove takes the *host* port, not the remote port.
336 port_string = 'tcp:%s' % self.pids['sky_command_port']
337 subprocess.call([ADB_PATH, 'forward', '--remove', port_string])
338
339 subprocess.call([
340 ADB_PATH, 'shell', 'am', 'force-stop', ANDROID_PACKAGE])
341 else:
342 # Only try to kill mojo_shell if it's running locally.
343 self._kill_if_exists('mojo_shell_pid', 'mojo_shell')
344
345 if 'remote_gdbserver_port' in self.pids:
346 self._kill_if_exists('adb_shell_gdbserver_pid',
347 'adb shell gdbserver')
348
349 port_string = 'tcp:%s' % self.pids['remote_gdbserver_port']
350 subprocess.call([ADB_PATH, 'forward', '--remove', port_string])
351 self.pids = {} # Clear out our pid file.
352
353 def _url_from_args(self, args):
354 if urlparse.urlparse(args.url_or_path).scheme:
355 return args.url_or_path
356 # The load happens on the remote device, use the remote port.
357 remote_sky_server_port = self.pids.get('remote_sky_server_port',
358 self.pids['sky_server_port'])
359 return SkyServer.url_for_path(remote_sky_server_port,
360 self.pids['sky_server_root'], args.url_or_path)
361
362 def load_command(self, args):
363 self._run_basic_command('/load', self._url_from_args(args))
364
365 def _read_mojo_map(self):
366 # TODO(eseidel): Does not work for android.
367 mojo_map_path = "/tmp/mojo_shell.%d.maps" % self.pids['mojo_shell_pid']
368 with open(mojo_map_path, 'r') as maps_file:
369 lines = maps_file.read().strip().split('\n')
370 return dict(map(lambda line: line.split(' '), lines))
371
372 def stop_tracing_command(self, args):
373 file_name = args.file_name
374 trace = self._send_command_to_sky('/stop_tracing').content
375 with open(file_name, "wb") as trace_file:
376 trace_file.write('{"traceEvents":[')
377 trace_file.write(trace)
378 trace_file.write(']}')
379 print "Trace saved in %s" % file_name
380
381 def stop_profiling_command(self, args):
382 self._run_basic_command('/stop_profiling')
383 mojo_map = self._read_mojo_map()
384
385 # TODO(eseidel): We should have a helper for resolving urls, etc.
386 remote_server_port = self.pids.get('remote_sky_server_port', self.pids[' sky_server_port'])
387 build_dir_url = SkyServer.url_for_path(
388 remote_server_port,
389 self.pids['sky_server_root'],
390 self.pids['build_dir'])
391
392 # Map /tmp cache paths to urls and then to local build_dir paths.
393 def map_to_local_paths(match):
394 path = match.group('mojo_path')
395 url = mojo_map.get(path)
396 if url and url.startswith(build_dir_url):
397 return url.replace(build_dir_url, self.pids['build_dir'])
398 return match.group(0)
399
400 MOJO_PATH_RE = re.compile(r'(?P<mojo_path>\S+\.mojo)')
401 MOJO_NAME_RE = re.compile(r'(?P<mojo_name>\w+)\.mojo')
402
403 with open("sky_viewer.pprof", "rb+") as profile_file:
404 # ISO-8859-1 can represent arbitrary binary while still keeping
405 # ASCII characters in the ASCII range (allowing us to regexp).
406 # http://en.wikipedia.org/wiki/ISO/IEC_8859-1
407 as_string = profile_file.read().decode('iso-8859-1')
408 # Using the mojo_shell.PID.maps file tmp paths to build_dir paths.
409 as_string = MOJO_PATH_RE.sub(map_to_local_paths, as_string)
410 # In release foo.mojo is stripped but libfoo_library.so isn't.
411 as_string = MOJO_NAME_RE.sub(r'lib\1_library.so', as_string)
412 profile_file.seek(0)
413 profile_file.write(as_string.encode('iso-8859-1'))
414 profile_file.truncate()
415
416 def _command_base_url(self):
417 return 'http://localhost:%s' % self.pids['sky_command_port']
418
419 def _send_command_to_sky(self, command_path, payload=None):
420 url = 'http://localhost:%s%s' % (
421 self.pids['sky_command_port'], command_path)
422 if payload:
423 response = requests.post(url, payload)
424 else:
425 response = requests.get(url)
426 return response
427
428 def _run_basic_command(self, command_path, payload=None):
429 print self._send_command_to_sky(command_path, payload=payload).text
430
431 # FIXME: These could be made into a context object with __enter__/__exit__.
432 def _load_pid_file(self, path):
433 try:
434 with open(path, 'r') as pid_file:
435 return json.load(pid_file)
436 except:
437 if os.path.exists(path):
438 logging.warn('Failed to read pid file: %s' % path)
439 return {}
440
441 def _write_pid_file(self, path, pids):
442 try:
443 with open(path, 'w') as pid_file:
444 json.dump(pids, pid_file, indent=2, sort_keys=True)
445 except:
446 logging.warn('Failed to write pid file: %s' % path)
447
448 def _add_basic_command(self, subparsers, name, url_path, help_text):
449 parser = subparsers.add_parser(name, help=help_text)
450 command = lambda args: self._run_basic_command(url_path)
451 parser.set_defaults(func=command)
452
453 def _wait_for_sky_command_port(self):
454 tries = 0
455 while True:
456 try:
457 self._run_basic_command('/')
458 return True
459 except:
460 tries += 1
461 if tries == 3:
462 logging.warn('Still waiting for sky on port %s' %
463 self.pids['sky_command_port'])
464 if tries > 10:
465 return False
466 time.sleep(1)
467
468 def logcat_command(self, args):
469 TAGS = [
470 'AndroidHandler',
471 'MojoMain',
472 'MojoShellActivity',
473 'MojoShellApplication',
474 'chromium',
475 ]
476 subprocess.call([ADB_PATH, 'logcat', '-d', '-s'] + TAGS)
477
478 def _pull_system_libraries(self, system_libs_root):
479 # Pull down the system libraries this pid has already mapped in.
480 # TODO(eseidel): This does not handle dynamic loads.
481 library_cacher_path = os.path.join(
482 self.paths.sky_tools_directory, 'android_library_cacher.py')
483 subprocess.call([
484 library_cacher_path, system_libs_root, self.pids['mojo_shell_pid']
485 ])
486
487 # TODO(eseidel): adb_gdb does, this, unclear why solib-absolute-prefix
488 # doesn't make this explicit listing not necessary?
489 return subprocess.check_output([
490 'find', system_libs_root,
491 '-mindepth', '1',
492 '-maxdepth', '4',
493 '-type', 'd',
494 ]).strip().split('\n')
495
496 def _add_android_library_links(self, links_path):
497 # TODO(eseidel): This might not match mojo_shell on the device?
498 # TODO(eseidel): Should we pass libmojo_shell.so as 'file' to gdb?
499 shell_link_path = os.path.join(links_path, 'libmojo_shell.so')
500 if os.path.lexists(shell_link_path):
501 os.unlink(shell_link_path)
502 os.symlink(self.paths.mojo_shell_path, shell_link_path)
503
504 def gdb_attach_command(self, args):
505 self.paths = self._create_paths_for_build_dir(self.pids['build_dir'])
506
507 if not os.path.exists(CACHE_LINKS_PATH):
508 os.makedirs(CACHE_LINKS_PATH)
509 cache_linker_path = os.path.join(
510 self.paths.sky_tools_directory, 'mojo_cache_linker.py')
511 subprocess.check_call([
512 cache_linker_path, CACHE_LINKS_PATH, self.paths.build_dir])
513
514 symbol_search_paths = [
515 self.pids['build_dir'],
516 CACHE_LINKS_PATH,
517 ]
518 gdb_path = '/usr/bin/gdb'
519
520 eval_commands = [
521 'directory %s' % self.paths.src_root,
522 'file %s' % self.paths.mojo_shell_path,
523 'target remote localhost:%s' % GDB_PORT,
524 ]
525
526 # A bunch of extra work is needed for android:
527 if 'remote_sky_server_port' in self.pids:
528 self._add_android_library_links(CACHE_LINKS_PATH)
529
530 system_lib_dirs = self._pull_system_libraries(SYSTEM_LIBS_ROOT_PATH)
531 eval_commands.append(
532 'set solib-absolute-prefix %s' % SYSTEM_LIBS_ROOT_PATH)
533
534 symbol_search_paths = system_lib_dirs + symbol_search_paths
535
536 # TODO(eseidel): We need to look up the toolchain somehow?
537 if platform.system() == 'Darwin':
538 gdb_path = os.path.join(SRC_ROOT, 'third_party/android_tools/ndk /'
539 'toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 /'
540 'bin/arm-linux-androideabi-gdb')
541 else:
542 gdb_path = os.path.join(SRC_ROOT, 'third_party/android_tools/ndk /'
543 'toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/ '
544 'bin/arm-linux-androideabi-gdb')
545
546 # Set solib-search-path after letting android modify symbol_search_paths
547 eval_commands.append(
548 'set solib-search-path %s' % ':'.join(symbol_search_paths))
549
550 exec_command = [gdb_path]
551 for command in eval_commands:
552 exec_command += ['--eval-command', command]
553
554 print " ".join(exec_command)
555
556 # Write out our pid file before we exec ourselves.
557 self._write_pid_file(PID_FILE_PATH, self.pids)
558
559 # Exec gdb directly to avoid python intercepting symbols, etc.
560 os.execv(exec_command[0], exec_command)
561
562 def print_crash_command(self, args):
563 logcat_cmd = [ADB_PATH, 'logcat', '-d']
564 logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE)
565
566 stack_path = os.path.join(SRC_ROOT,
567 'tools', 'android_stack_parser', 'stack')
568 stack = subprocess.Popen([stack_path, '-'], stdin=logcat.stdout)
569 logcat.wait()
570 stack.wait()
571
572 def pids_command(self, args):
573 print json.dumps(self.pids, indent=1)
574
575 def main(self):
576 logging.basicConfig(level=logging.WARNING)
577 logging.getLogger("requests").setLevel(logging.WARNING)
578
579 self.pids = self._load_pid_file(PID_FILE_PATH)
580
581 parser = argparse.ArgumentParser(description='Sky launcher/debugger')
582 subparsers = parser.add_subparsers(help='sub-command help')
583
584 start_parser = subparsers.add_parser('start',
585 help='launch a new mojo_shell with sky')
586 start_parser.add_argument('--gdb', action='store_true')
587 start_parser.add_argument('--command-port', type=int,
588 default=DEFAULT_SKY_COMMAND_PORT)
589 start_parser.add_argument('--use-osmesa', action='store_true',
590 default=self._in_chromoting())
591 start_parser.add_argument('build_dir', type=str)
592 start_parser.add_argument('url_or_path', nargs='?', type=str,
593 default=DEFAULT_URL)
594 start_parser.add_argument('--show-command', action='store_true',
595 help='Display the shell command and exit')
596 start_parser.add_argument('--trace-startup', action='store_true')
597 start_parser.set_defaults(func=self.start_command)
598
599 stop_parser = subparsers.add_parser('stop',
600 help=('stop sky (as listed in %s)' % PID_FILE_PATH))
601 stop_parser.set_defaults(func=self.stop_command)
602
603 pids_parser = subparsers.add_parser('pids',
604 help='dump the current skydb pids file')
605 pids_parser.set_defaults(func=self.pids_command)
606
607 logcat_parser = subparsers.add_parser('logcat',
608 help=('dump sky-related logs from device'))
609 logcat_parser.set_defaults(func=self.logcat_command)
610
611 print_crash_parser = subparsers.add_parser('print_crash',
612 help=('dump (and symbolicate) recent crash-stacks'))
613 print_crash_parser.set_defaults(func=self.print_crash_command)
614
615 gdb_attach_parser = subparsers.add_parser('gdb_attach',
616 help='launch gdb and attach to gdbserver launched from start --gdb')
617 gdb_attach_parser.set_defaults(func=self.gdb_attach_command)
618
619 self._add_basic_command(subparsers, 'start_tracing', '/start_tracing',
620 'starts tracing the running sky instance')
621 self._add_basic_command(subparsers, 'reload', '/reload',
622 'reload the current page')
623 self._add_basic_command(subparsers, 'start_profiling', '/start_profiling ',
624 'starts profiling the running sky instance (Linux only)')
625
626 stop_tracing_parser = subparsers.add_parser('stop_tracing',
627 help='stops tracing the running sky instance')
628 stop_tracing_parser.add_argument('file_name', type=str, default='sky_vie wer.trace')
629 stop_tracing_parser.set_defaults(func=self.stop_tracing_command)
630
631 stop_profiling_parser = subparsers.add_parser('stop_profiling',
632 help='stops profiling the running sky instance (Linux only)')
633 stop_profiling_parser.set_defaults(func=self.stop_profiling_command)
634
635 load_parser = subparsers.add_parser('load',
636 help='load a new page in the currently running sky')
637 load_parser.add_argument('url_or_path', type=str)
638 load_parser.set_defaults(func=self.load_command)
639
640 args = parser.parse_args()
641 args.func(args)
642
643 self._write_pid_file(PID_FILE_PATH, self.pids)
644
645
646 if __name__ == '__main__':
647 SkyDebugger().main()
OLDNEW
« no previous file with comments | « sky/HACKING.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698