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

Side by Side Diff: appengine/chromium_rietveld/codereview/views.py

Issue 1155513002: [Rietveld] Add support for patchset dependencies (Closed) Base URL: https://chromium.googlesource.com/infra/infra@master
Patch Set: Make get_depends_on_patchset return JSON instead of text 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
OLDNEW
1 # Copyright 2008 Google Inc. 1 # Copyright 2008 Google Inc.
2 # 2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); 3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License. 4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at 5 # You may obtain a copy of the License at
6 # 6 #
7 # http://www.apache.org/licenses/LICENSE-2.0 7 # http://www.apache.org/licenses/LICENSE-2.0
8 # 8 #
9 # Unless required by applicable law or agreed to in writing, software 9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, 10 # distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 from oauth2client.appengine import _safe_html 71 from oauth2client.appengine import _safe_html
72 from oauth2client.appengine import CredentialsNDBModel 72 from oauth2client.appengine import CredentialsNDBModel
73 from oauth2client.appengine import StorageByKeyName 73 from oauth2client.appengine import StorageByKeyName
74 from oauth2client.appengine import xsrf_secret_key 74 from oauth2client.appengine import xsrf_secret_key
75 from oauth2client.client import AccessTokenRefreshError 75 from oauth2client.client import AccessTokenRefreshError
76 from oauth2client.client import OAuth2WebServerFlow 76 from oauth2client.client import OAuth2WebServerFlow
77 from oauth2client import xsrfutil 77 from oauth2client import xsrfutil
78 78
79 from codereview import auth_utils 79 from codereview import auth_utils
80 from codereview import buildbucket 80 from codereview import buildbucket
81 from codereview import dependency_utils
81 from codereview import engine 82 from codereview import engine
82 from codereview import library 83 from codereview import library
83 from codereview import models 84 from codereview import models
84 from codereview import models_chromium 85 from codereview import models_chromium
85 from codereview import net 86 from codereview import net
86 from codereview import notify_xmpp 87 from codereview import notify_xmpp
87 from codereview import patching 88 from codereview import patching
88 from codereview import utils 89 from codereview import utils
89 from codereview.common import IS_DEV 90 from codereview.common import IS_DEV
90 from codereview.exceptions import FetchError 91 from codereview.exceptions import FetchError
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 class UploadForm(forms.Form): 175 class UploadForm(forms.Form):
175 176
176 subject = forms.CharField(max_length=MAX_SUBJECT) 177 subject = forms.CharField(max_length=MAX_SUBJECT)
177 description = forms.CharField(max_length=MAX_DESCRIPTION, required=False) 178 description = forms.CharField(max_length=MAX_DESCRIPTION, required=False)
178 project = forms.CharField(required=False) 179 project = forms.CharField(required=False)
179 content_upload = forms.BooleanField(required=False) 180 content_upload = forms.BooleanField(required=False)
180 separate_patches = forms.BooleanField(required=False) 181 separate_patches = forms.BooleanField(required=False)
181 base = forms.CharField(max_length=MAX_URL, required=False) 182 base = forms.CharField(max_length=MAX_URL, required=False)
182 target_ref = forms.CharField(max_length=MAX_URL, required=False) 183 target_ref = forms.CharField(max_length=MAX_URL, required=False)
183 cq_dry_run = forms.BooleanField(required=False) 184 cq_dry_run = forms.BooleanField(required=False)
185 depends_on_patchset = forms.CharField(required=False)
184 data = forms.FileField(required=False) 186 data = forms.FileField(required=False)
185 issue = forms.IntegerField(required=False) 187 issue = forms.IntegerField(required=False)
186 reviewers = forms.CharField(max_length=MAX_REVIEWERS, required=False) 188 reviewers = forms.CharField(max_length=MAX_REVIEWERS, required=False)
187 cc = forms.CharField(max_length=MAX_CC, required=False) 189 cc = forms.CharField(max_length=MAX_CC, required=False)
188 private = forms.BooleanField(required=False, initial=False) 190 private = forms.BooleanField(required=False, initial=False)
189 send_mail = forms.BooleanField(required=False) 191 send_mail = forms.BooleanField(required=False)
190 base_hashes = forms.CharField(required=False) 192 base_hashes = forms.CharField(required=False)
191 commit = forms.BooleanField(required=False) 193 commit = forms.BooleanField(required=False)
192 repo_guid = forms.CharField(required=False, max_length=MAX_URL) 194 repo_guid = forms.CharField(required=False, max_length=MAX_URL)
193 195
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 return HttpResponseBadRequest( 1053 return HttpResponseBadRequest(
1052 'Only the issue owner can edit patchset titles') 1054 'Only the issue owner can edit patchset titles')
1053 1055
1054 patchset = request.patchset 1056 patchset = request.patchset
1055 patchset.message = request.POST.get('patchset_title') 1057 patchset.message = request.POST.get('patchset_title')
1056 patchset.put() 1058 patchset.put()
1057 1059
1058 return HttpResponse('OK', content_type='text/plain') 1060 return HttpResponse('OK', content_type='text/plain')
1059 1061
1060 1062
1063 @deco.access_control_allow_origin_star
1064 @deco.require_methods('POST')
1065 @deco.patchset_required
1066 @deco.json_response
1067 def get_depends_on_patchset(request):
1068 """/<issue>/get_depends_on_patchset- The patchset this patchset depends on."""
1069 response = {}
1070 if request.patchset.depends_on_patchset:
1071 # Verify that the depended upon issue is not closed.
1072 tokens = dependency_utils.get_dependency_tokens(
1073 request.patchset.depends_on_patchset)
1074 depends_on_issue = models.Issue.get_by_id(int(tokens[0]))
1075 if depends_on_issue and not depends_on_issue.closed:
1076 response = {
1077 'issue': tokens[0],
1078 'patchset': tokens[1],
1079 }
1080 return response
1081
1082
1061 @deco.admin_required 1083 @deco.admin_required
1062 @deco.user_key_required 1084 @deco.user_key_required
1063 @deco.xsrf_required 1085 @deco.xsrf_required
1064 def block_user(request): 1086 def block_user(request):
1065 """/user/<user>/block - Blocks a specific user.""" 1087 """/user/<user>/block - Blocks a specific user."""
1066 account = models.Account.get_account_for_user(request.user_to_show) 1088 account = models.Account.get_account_for_user(request.user_to_show)
1067 if request.method == 'POST': 1089 if request.method == 'POST':
1068 form = BlockForm(request.POST) 1090 form = BlockForm(request.POST)
1069 if form.is_valid(): 1091 if form.is_valid():
1070 account.blocked = form.cleaned_data['blocked'] 1092 account.blocked = form.cleaned_data['blocked']
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1464 issue.put() 1486 issue.put()
1465 1487
1466 if cq_dry_run: 1488 if cq_dry_run:
1467 commit_checked_msg = 'The CQ bit was checked by %s to run a CQ dry run' % ( 1489 commit_checked_msg = 'The CQ bit was checked by %s to run a CQ dry run' % (
1468 cq_dry_run_triggered_by) 1490 cq_dry_run_triggered_by)
1469 make_message(request, issue, commit_checked_msg, send_mail=False, 1491 make_message(request, issue, commit_checked_msg, send_mail=False,
1470 auto_generated=True).put() 1492 auto_generated=True).put()
1471 1493
1472 first_ps_id, _ = models.PatchSet.allocate_ids(1, parent=issue.key) 1494 first_ps_id, _ = models.PatchSet.allocate_ids(1, parent=issue.key)
1473 ps_key = ndb.Key(models.PatchSet, first_ps_id, parent=issue.key) 1495 ps_key = ndb.Key(models.PatchSet, first_ps_id, parent=issue.key)
1496 depends_on_patchset = (
1497 dependency_utils.mark_as_dependent_and_get_dependency_str(
1498 form.cleaned_data.get('depends_on_patchset'), issue.key.id(),
1499 ps_key.id()))
1474 patchset = models.PatchSet( 1500 patchset = models.PatchSet(
1475 issue_key=issue.key, data=data, url=url, key=ps_key) 1501 issue_key=issue.key, data=data, url=url, key=ps_key,
1502 depends_on_patchset=depends_on_patchset)
1476 patchset.put() 1503 patchset.put()
1477 1504
1478 if not separate_patches: 1505 if not separate_patches:
1479 try: 1506 try:
1480 patches = engine.ParsePatchSet(patchset) 1507 patches = engine.ParsePatchSet(patchset)
1481 except Exception: 1508 except Exception:
1482 # catch all exceptions happening in engine.ParsePatchSet, 1509 # catch all exceptions happening in engine.ParsePatchSet,
1483 # engine.SplitPatch. With malformed diffs a variety of exceptions could 1510 # engine.SplitPatch. With malformed diffs a variety of exceptions could
1484 # happen there. 1511 # happen there.
1485 logging.exception('Exception during patch parsing') 1512 logging.exception('Exception during patch parsing')
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 account = models.Account.get_account_for_user(request.user) 1586 account = models.Account.get_account_for_user(request.user)
1560 if account.blocked: 1587 if account.blocked:
1561 return None 1588 return None
1562 if not issue.edit_allowed: 1589 if not issue.edit_allowed:
1563 # This check is done at each call site but check again as a safety measure. 1590 # This check is done at each call site but check again as a safety measure.
1564 return None 1591 return None
1565 data, url, separate_patches = data_url 1592 data, url, separate_patches = data_url
1566 message = form.cleaned_data[message_key] 1593 message = form.cleaned_data[message_key]
1567 first_id, _ = models.PatchSet.allocate_ids(1, parent=issue.key) 1594 first_id, _ = models.PatchSet.allocate_ids(1, parent=issue.key)
1568 ps_key = ndb.Key(models.PatchSet, first_id, parent=issue.key) 1595 ps_key = ndb.Key(models.PatchSet, first_id, parent=issue.key)
1596
1597 depends_on_patchset = (
1598 dependency_utils.mark_as_dependent_and_get_dependency_str(
1599 form.cleaned_data.get('depends_on_patchset'), issue.key.id(),
1600 ps_key.id()))
1569 patchset = models.PatchSet( 1601 patchset = models.PatchSet(
1570 issue_key=issue.key, message=message, data=data, url=url, key=ps_key) 1602 issue_key=issue.key, message=message, data=data, url=url, key=ps_key,
1603 depends_on_patchset=depends_on_patchset)
1571 patchset.put() 1604 patchset.put()
1572 1605
1573 if not separate_patches: 1606 if not separate_patches:
1574 try: 1607 try:
1575 patches = engine.ParsePatchSet(patchset) 1608 patches = engine.ParsePatchSet(patchset)
1576 except Exception: 1609 except Exception:
1577 logging.exception('Exception during patchset parsing') 1610 logging.exception('Exception during patchset parsing')
1578 patches = [] 1611 patches = []
1579 if not patches: 1612 if not patches:
1580 patchset.key.delete() 1613 patchset.key.delete()
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
2083 logging.info("Updating %d patches", len(patches)) 2116 logging.info("Updating %d patches", len(patches))
2084 ndb.put_multi(patches) 2117 ndb.put_multi(patches)
2085 2118
2086 2119
2087 @deco.require_methods('POST') 2120 @deco.require_methods('POST')
2088 @deco.issue_editor_required 2121 @deco.issue_editor_required
2089 @deco.xsrf_required 2122 @deco.xsrf_required
2090 def delete(request): 2123 def delete(request):
2091 """/<issue>/delete - Delete an issue. There is no way back.""" 2124 """/<issue>/delete - Delete an issue. There is no way back."""
2092 issue = request.issue 2125 issue = request.issue
2126 # Update the dependents to remove dependency on this issue.
2127 dependency_utils.remove_dependencies_from_all_patchsets(issue)
2128 # Remove this issue as a dependent.
2129 dependency_utils.remove_all_patchsets_as_dependents(issue)
2130
2093 tbd = [issue] 2131 tbd = [issue]
2094 for cls in [models.PatchSet, models.Patch, models.Comment, 2132 for cls in [models.PatchSet, models.Patch, models.Comment,
2095 models.Message, models.Content, models.TryJobResult]: 2133 models.Message, models.Content, models.TryJobResult]:
2096 tbd += cls.query(ancestor=issue.key) 2134 tbd += cls.query(ancestor=issue.key)
2097 ndb.delete_multi(entity.key for entity in tbd) 2135 ndb.delete_multi(entity.key for entity in tbd)
2098 return HttpResponseRedirect(reverse(mine)) 2136 return HttpResponseRedirect(reverse(mine))
2099 2137
2100 2138
2101 @deco.require_methods('POST') 2139 @deco.require_methods('POST')
2102 @deco.patchset_editor_required 2140 @deco.patchset_editor_required
2103 @deco.xsrf_required 2141 @deco.xsrf_required
2104 def delete_patchset(request): 2142 def delete_patchset(request):
2105 """/<issue>/patch/<patchset>/delete - Delete a patchset. 2143 """/<issue>/patch/<patchset>/delete - Delete a patchset.
2106 2144
2107 There is no way back. 2145 There is no way back.
2108 """ 2146 """
2109 # Log patchset deletion. 2147 # Log patchset deletion.
2110 patchset_num = 0 2148 patchset_num = 0
2111 for patchset in list(request.issue.patchsets): 2149 for patchset in list(request.issue.patchsets):
2112 patchset_num += 1 2150 patchset_num += 1
2113 if patchset.key.id() == request.patchset.key.id(): 2151 if patchset.key.id() == request.patchset.key.id():
2114 break 2152 break
2115 delete_msg = 'Patchset #%s (id:%s) has been deleted' % ( 2153 delete_msg = 'Patchset #%s (id:%s) has been deleted' % (
2116 patchset_num, request.patchset.key.id()) 2154 patchset_num, request.patchset.key.id())
2117 make_message(request, request.issue, delete_msg, send_mail=False, 2155 make_message(request, request.issue, delete_msg, send_mail=False,
2118 auto_generated=True).put() 2156 auto_generated=True).put()
2157 # Update all dependents of this patchset.
2158 dependency_utils.remove_dependencies(request.patchset)
2159 # Remove this patchset as a dependent.
2160 dependency_utils.remove_as_dependent(request.patchset)
2119 # Delete the patchset. 2161 # Delete the patchset.
2120 request.patchset.nuke() 2162 request.patchset.nuke()
2121 return HttpResponseRedirect(reverse(show, args=[request.issue.key.id()])) 2163 return HttpResponseRedirect(reverse(show, args=[request.issue.key.id()]))
2122 2164
2123 2165
2124 @deco.require_methods('POST') 2166 @deco.require_methods('POST')
2125 @deco.issue_editor_required 2167 @deco.issue_editor_required
2126 @deco.xsrf_required 2168 @deco.xsrf_required
2127 def close(request): 2169 def close(request):
2128 """/<issue>/close - Close an issue.""" 2170 """/<issue>/close - Close an issue."""
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
2396 values = { 2438 values = {
2397 'patchset': patchset.key.id(), 2439 'patchset': patchset.key.id(),
2398 'issue': issue.key.id(), 2440 'issue': issue.key.id(),
2399 'owner': library.get_nickname(issue.owner, True, request), 2441 'owner': library.get_nickname(issue.owner, True, request),
2400 'owner_email': issue.owner.email(), 2442 'owner_email': issue.owner.email(),
2401 'message': patchset.message, 2443 'message': patchset.message,
2402 'url': patchset.url, 2444 'url': patchset.url,
2403 'created': str(patchset.created), 2445 'created': str(patchset.created),
2404 'modified': str(patchset.modified), 2446 'modified': str(patchset.modified),
2405 'num_comments': patchset.num_comments, 2447 'num_comments': patchset.num_comments,
2448 'depends_on_patchset': patchset.depends_on_patchset,
2449 'dependent_patchsets': patchset.dependent_patchsets,
2406 'files': {}, 2450 'files': {},
2407 } 2451 }
2408 if (try_jobs): 2452 if (try_jobs):
2409 values['try_job_results'] = [ 2453 values['try_job_results'] = [
2410 t.to_dict() for t in patchset.try_job_results] 2454 t.to_dict() for t in patchset.try_job_results]
2411 2455
2412 all_no_base_file_keys_future = models.Content.query( 2456 all_no_base_file_keys_future = models.Content.query(
2413 models.Content.file_too_large == True, 2457 models.Content.file_too_large == True,
2414 ancestor=patchset.key).fetch_async(10000, keys_only=True, batch_size=1000) 2458 ancestor=patchset.key).fetch_async(10000, keys_only=True, batch_size=1000)
2415 patches_future = models.Patch.query(ancestor=patchset.key).fetch_async( 2459 patches_future = models.Patch.query(ancestor=patchset.key).fetch_async(
(...skipping 3083 matching lines...) Expand 10 before | Expand all | Expand 10 after
5499 return HttpResponseNotFound() 5543 return HttpResponseNotFound()
5500 tops = [] 5544 tops = []
5501 shame = [] 5545 shame = []
5502 for i in data: 5546 for i in data:
5503 if i.score == models.AccountStatsBase.NULL_SCORE: 5547 if i.score == models.AccountStatsBase.NULL_SCORE:
5504 shame.append(i) 5548 shame.append(i)
5505 else: 5549 else:
5506 tops.append(i) 5550 tops.append(i)
5507 return respond( 5551 return respond(
5508 request, 'leaderboard.html', {'tops': tops, 'shame': shame, 'when': when}) 5552 request, 'leaderboard.html', {'tops': tops, 'shame': shame, 'when': when})
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698