1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
import os
import subprocess
from gitutils import GitUtils
from git_deps.detector import DependencyDetector
from git_deps.errors import InvalidCommitish
from git_deps.listener.json import JSONDependencyListener
from git_deps.utils import abort, standard_logger
def serve(options):
try:
import flask
from flask import Flask, send_file, safe_join
from flask.json import jsonify
except ImportError:
abort("Cannot find flask module which is required for webserver mode.")
logger = standard_logger(__name__, options.debug)
webserver = Flask('git-deps')
here = os.path.dirname(os.path.realpath(__file__))
root = os.path.join(here, 'html')
webserver.root_path = root
logger.debug("Webserver root is %s" % root)
##########################################################
# Static content
@webserver.route('/')
def main_page():
return send_file('git-deps.html')
@webserver.route('/tip-template.html')
def tip_template():
return send_file('tip-template.html')
@webserver.route('/test.json')
def data():
return send_file('test.json')
def make_subdir_handler(subdir):
def subdir_handler(filename):
path = safe_join(root, subdir)
path = safe_join(path, filename)
if os.path.exists(path):
return send_file(path)
else:
flask.abort(404)
return subdir_handler
for subdir in ('node_modules', 'css', 'js'):
fn = make_subdir_handler(subdir)
route = '/%s/<path:filename>' % subdir
webserver.add_url_rule(route, subdir + '_handler', fn)
##########################################################
# Dynamic content
def json_error(status_code, error_class, message, **extra):
json = {
'status': status_code,
'error_class': error_class,
'message': message,
}
json.update(extra)
response = jsonify(json)
response.status_code = status_code
return response
@webserver.route('/options')
def send_options():
client_options = options.__dict__
client_options['repo_path'] = os.getcwd()
return jsonify(client_options)
@webserver.route('/deps.json/<revspec>')
def deps(revspec):
detector = DependencyDetector(options)
listener = JSONDependencyListener(options)
detector.add_listener(listener)
if '..' in revspec:
try:
revisions = GitUtils.rev_list(revspec)
except subprocess.CalledProcessError:
return json_error(
422, 'Invalid revision range',
"Could not resolve revision range '%s'" % revspec,
revspec=revspec)
else:
revisions = [revspec]
for rev in revisions:
try:
detector.get_commit(rev)
except InvalidCommitish:
return json_error(
422, 'Invalid revision',
"Could not resolve revision '%s'" % rev,
rev=rev)
detector.find_dependencies(rev)
tip_commit = detector.get_commit(revisions[0])
tip_sha1 = tip_commit.hex
json = listener.json()
json['query'] = {
'revspec': revspec,
'revisions': revisions,
'tip_sha1': tip_sha1,
'tip_abbrev': GitUtils.abbreviate_sha1(tip_sha1),
}
return jsonify(json)
# We don't want to see double-decker warnings, so check
# WERKZEUG_RUN_MAIN which is only set for the first startup, not
# on app reloads.
if options.debug and not os.getenv('WERKZEUG_RUN_MAIN'):
print("!! WARNING! Debug mode enabled, so webserver is completely "
"insecure!")
print("!! Arbitrary code can be executed from browser!")
print()
webserver.run(port=options.port, debug=options.debug,
host=options.bindaddr)
|