1 #!/usr/bin/env python3 2 3 import collections 4 import functools 5 import json 6 import os 7 import re 8 9 from flask import ( 10 Blueprint, Flask, current_app, jsonify, render_template, request) 11 12 13 codereview = Blueprint('codereview', '__name__', 'templates') 14 15 16 # whether the code segment is exactly in file 17 def same(fl, code, source_dir): 18 fl = os.path.join(source_dir, fl) 19 with open(fl, 'r') as f: 20 fc = f.read() 21 return code in fc 22 23 24 # check if the file needes to be reiewed again 25 def check(codes, source_dir): 26 ret = [] 27 for item in codes: 28 fl = item.split(':')[0] 29 code = item[len(fl) + 1:] 30 ret.append(same(fl, code, source_dir)) 31 return ret 32 33 34 @codereview.route('/get_started') 35 def _get_started(): 36 project = current_app.config.project 37 source_dir = project.source_dir 38 review_db = project.review_db 39 40 lst, done= [], [] 41 for key, item in sorted(review_db.data.items()): 42 lst.append(key) 43 if item[0]: 44 done.append(all(check(item[1], source_dir))) 45 else: 46 done.append(False) 47 48 pattern_lst = project.pattern_db.load()[0] 49 abs_path = os.path.abspath(source_dir) 50 51 return jsonify(lst=json.dumps(lst), 52 done=json.dumps(done), 53 pattern_lst=json.dumps(pattern_lst), 54 path_prefix=os.path.join(abs_path, '')) 55 56 57 @codereview.route('/load_file') 58 def _load_file(): 59 project = current_app.config.project 60 source_dir = project.source_dir 61 review_db = project.review_db 62 63 path = request.args.get('path') 64 65 if path not in review_db.data.keys(): 66 print('No such entry', path) 67 return jsonify(result='') 68 deps, codes = review_db.data[path] 69 70 return jsonify(deps=json.dumps(deps), codes=json.dumps(codes), 71 okays=json.dumps(check(codes, source_dir))) 72 73 74 @codereview.route('/get_file') 75 def _get_file(): 76 path = request.args.get('path') 77 path = os.path.join(current_app.config.project.source_dir, path) 78 79 if not os.path.exists(path): 80 return jsonify(result='No such file') 81 with open(path, 'r') as f: 82 code = f.read() 83 84 return jsonify(result=code) 85 86 87 @codereview.route('/save_all') 88 def _save_all(): 89 label = request.args.get('label') 90 deps = json.loads(request.args.get('deps')) 91 codes = json.loads(request.args.get('codes')) 92 93 project = current_app.config.project 94 review_db = project.review_db 95 review_db.add_label(label, deps, codes) 96 97 return jsonify(result='done') 98 99 100 # This function add pattern to grep 101 @codereview.route('/add_pattern') 102 def _add_pattern(): 103 patt = request.args.get('pattern') 104 is_regex = request.args.get('is_regex') 105 engine = current_app.config.project.review_db 106 engine.add_pattern(patt, is_regex) 107 108 project = current_app.config.project 109 project.pattern_db.save_new_pattern(patt, is_regex) 110 return jsonify(result='done') 111 112 113 # This function does a temporary grep to the directory 114 # Not adding the result to database 115 @codereview.route('/temporary_search') 116 def _temporary_search(): 117 path = request.args.get('path') 118 patt = request.args.get('pattern') 119 is_regex = request.args.get('is_regex') 120 codesearch = current_app.config.project.codesearch 121 result = codesearch.raw_search(patt, is_regex).decode('utf-8') 122 dic = collections.defaultdict(list) 123 patt = re.compile('([^:]+):(\\d+):(.*)$') 124 for line in result.split('\n'): 125 match = patt.match(line) 126 if not match: 127 continue 128 129 file_path = match.group(1) 130 line_no = match.group(2) 131 code = match.group(3) 132 dic[file_path].append((line_no, code)) 133 134 def compare(item1, item2): 135 key1, value1 = item1 136 key2, value2 = item2 137 cnt1 = os.path.commonprefix([path, key1]).count('/') 138 cnt2 = os.path.commonprefix([path, key2]).count('/') 139 e1 = os.path.relpath(key1, path).count('/') 140 e2 = os.path.relpath(key2, path).count('/') 141 # prefer smaller edit distance 142 if e1 < e2: return -1 143 if e2 < e1: return 1 144 # prefer deeper common ancestor 145 if cnt1 > cnt2: return -1 146 if cnt2 > cnt1: return 1 147 # lexicographical order 148 if key1 < key2: return -1 149 if key2 < key1: return 1 150 return 0 151 152 result = sorted(dic.items(), key=functools.cmp_to_key(compare)) 153 return jsonify(result=json.dumps(result)) 154 155 156 @codereview.route('/') 157 def render(): 158 return render_template('index.html') 159 160 161 def create_app(project): 162 app = Flask(__name__) 163 app.register_blueprint(codereview) 164 app.config.project = project 165 return app 166