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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
import os
import subprocess
import sys
from git_deps.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
from flask.json import jsonify
from werkzeug.security import safe_join
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()
try:
webserver.run(port=options.port, debug=options.debug,
host=options.bindaddr)
except OSError as e:
print("\n!!! ERROR: Could not start server:")
print("!!!")
print("!!! " + str(e))
print("!!!")
if e.strerror == "Address already in use":
print("!!! Do you already have a git deps server running?")
print("!!! If so, stop it first and try again.")
print("!!!")
print("!!! Aborting.")
sys.exit(1)
|