blob: 6165432e7af8458a91cf93c55a024ea68b0ee287 [file] [log] [blame]
Pirama Arumuga Nainar9be014a2021-06-23 22:07:11 -07001#!/usr/bin/env python
2
3from __future__ import print_function
4
5"""The clang static analyzer results viewer.
6"""
7
8import sys
9import imp
10import os
11import posixpath
12import threading
13import time
14try:
15 from urllib.request import urlopen
16except ImportError:
17 from urllib2 import urlopen
18import webbrowser
19
20# How long to wait for server to start.
21kSleepTimeout = .05
22kMaxSleeps = int(60 / kSleepTimeout)
23
24# Default server parameters
25
26kDefaultHost = '127.0.0.1'
27kDefaultPort = 8181
28kMaxPortsToTry = 100
29
30###
31
32
33def url_is_up(url):
34 try:
35 o = urlopen(url)
36 except IOError:
37 return False
38 o.close()
39 return True
40
41
42def start_browser(port, options):
43 import webbrowser
44
45 url = 'http://%s:%d' % (options.host, port)
46
47 # Wait for server to start...
48 if options.debug:
49 sys.stderr.write('%s: Waiting for server.' % sys.argv[0])
50 sys.stderr.flush()
51 for i in range(kMaxSleeps):
52 if url_is_up(url):
53 break
54 if options.debug:
55 sys.stderr.write('.')
56 sys.stderr.flush()
57 time.sleep(kSleepTimeout)
58 else:
59 print('WARNING: Unable to detect that server started.', file=sys.stderr)
60
61 if options.debug:
62 print('%s: Starting webbrowser...' % sys.argv[0], file=sys.stderr)
63 webbrowser.open(url)
64
65
66def run(port, options, root):
67 # Prefer to look relative to the installed binary
68 share = os.path.dirname(__file__) + "/../share/scan-view"
69 if not os.path.isdir(share):
70 # Otherwise look relative to the source
71 share = os.path.dirname(__file__) + "/../../scan-view/share"
72 sys.path.append(share)
73
74 import ScanView
75 try:
76 print('Starting scan-view at: http://%s:%d' % (options.host,
77 port))
78 print(' Use Ctrl-C to exit.')
79 httpd = ScanView.create_server((options.host, port),
80 options, root)
81 httpd.serve_forever()
82 except KeyboardInterrupt:
83 pass
84
85
86def port_is_open(port):
87 try:
88 import socketserver
89 except ImportError:
90 import SocketServer as socketserver
91 try:
92 t = socketserver.TCPServer((kDefaultHost, port), None)
93 except:
94 return False
95 t.server_close()
96 return True
97
98
99def main():
100 import argparse
101 parser = argparse.ArgumentParser(description="The clang static analyzer "
102 "results viewer.")
103 parser.add_argument("root", metavar="<results directory>", type=str)
104 parser.add_argument(
105 '--host', dest="host", default=kDefaultHost, type=str,
106 help="Host interface to listen on. (default=%s)" % kDefaultHost)
107 parser.add_argument('--port', dest="port", default=None, type=int,
108 help="Port to listen on. (default=%s)" % kDefaultPort)
109 parser.add_argument("--debug", dest="debug", default=0,
110 action="count",
111 help="Print additional debugging information.")
112 parser.add_argument("--auto-reload", dest="autoReload", default=False,
113 action="store_true",
114 help="Automatically update module for each request.")
115 parser.add_argument("--no-browser", dest="startBrowser", default=True,
116 action="store_false",
117 help="Don't open a webbrowser on startup.")
118 parser.add_argument("--allow-all-hosts", dest="onlyServeLocal",
119 default=True, action="store_false",
120 help='Allow connections from any host (access '
121 'restricted to "127.0.0.1" by default)')
122 args = parser.parse_args()
123
124 # Make sure this directory is in a reasonable state to view.
125 if not posixpath.exists(posixpath.join(args.root, 'index.html')):
126 parser.error('Invalid directory, analysis results not found!')
127
128 # Find an open port. We aren't particularly worried about race
129 # conditions here. Note that if the user specified a port we only
130 # use that one.
131 if args.port is not None:
132 port = args.port
133 else:
134 for i in range(kMaxPortsToTry):
135 if port_is_open(kDefaultPort + i):
136 port = kDefaultPort + i
137 break
138 else:
139 parser.error('Unable to find usable port in [%d,%d)' %
140 (kDefaultPort, kDefaultPort+kMaxPortsToTry))
141
142 # Kick off thread to wait for server and start web browser, if
143 # requested.
144 if args.startBrowser:
145 threading.Thread(target=start_browser, args=(port, args)).start()
146
147 run(port, args, args.root)
148
149if __name__ == '__main__':
150 main()