Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(24)

Side by Side Diff: codereview/views.py

Issue 974: accept patches from mercurial SVN Base: http://rietveld.googlecode.com/svn/trunk
Patch Set: Created 3 months, 1 week ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
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,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and 12 # See the License for the specific language governing permissions and
13 # limitations under the License. 13 # limitations under the License.
14 14
15 """Views for Rietveld. 15 """Views for Rietveld.
16 16
17 This requires Django 0.97.pre. 17 This requires Django 0.97.pre.
18 """ 18 """
19 19
20 20
21 ### Imports ### 21 ### Imports ###
22 22
23 23
24 # Python imports 24 # Python imports
25 import os 25 import os
26 import cgi 26 import cgi
27 import random 27 import random
28 import logging 28 import logging
29 import binascii 29 import binascii
30 import datetime 30 import datetime
31 31
32 # AppEngine imports 32 # AppEngine imports
33 from google.appengine.api import mail 33 from google.appengine.api import mail
34 from google.appengine.api import users 34 from google.appengine.api import users
35 from google.appengine.api import urlfetch 35 from google.appengine.api import urlfetch
36 from google.appengine.ext import db 36 from google.appengine.ext import db
37 from google.appengine.ext.db import djangoforms 37 from google.appengine.ext.db import djangoforms
38 38
39 # DeadlineExceededError can live in two different places 39 # DeadlineExceededError can live in two different places
40 # TODO(guido): simplify once this is fixed. 40 # TODO(guido): simplify once this is fixed.
41 try: 41 try:
42 # When deployed 42 # When deployed
43 from google.appengine.runtime import DeadlineExceededError 43 from google.appengine.runtime import DeadlineExceededError
44 except ImportError: 44 except ImportError:
45 # In the development server 45 # In the development server
46 from google.appengine.runtime.apiproxy_errors import DeadlineExceededError 46 from google.appengine.runtime.apiproxy_errors import DeadlineExceededError
47 47
48 # Django imports 48 # Django imports
49 # TODO(guido): Don't import classes/functions directly. 49 # TODO(guido): Don't import classes/functions directly.
50 from django import newforms as forms 50 from django import newforms as forms
(...skipping 393 matching lines...) Show 10 above Show 10 below
444 issue = models.Issue.get_by_id(issue_id) 444 issue = models.Issue.get_by_id(issue_id)
445 if issue is None: 445 if issue is None:
446 form.errors['issue'] = ['No issue exists with that id (%s)' % 446 form.errors['issue'] = ['No issue exists with that id (%s)' %
447 issue_id] 447 issue_id]
448 else: 448 else:
449 if request.user != issue.owner: 449 if request.user != issue.owner:
450 form.errors['user'] = ['You (%s) don\'t own this issue (%s)' % 450 form.errors['user'] = ['You (%s) don\'t own this issue (%s)' %
451 (request.user, issue_id)] 451 (request.user, issue_id)]
452 issue = None 452 issue = None
453 else: 453 else:
454 if not add_patchset_from_form(request, issue, form, 'subject'): 454 if not add_patchset_from_form(request, issue, form, 'subject'):
455 issue = None 455 issue = None
456 else: 456 else:
457 action = 'created' 457 action = 'created'
458 issue = _make_new(request, form) 458 issue = _make_new(request, form)
459 if issue is None: 459 if issue is None:
460 msg = 'Issue creation errors:\n%s' % repr(form.errors) 460 msg = 'Issue creation errors:\n%s' % repr(form.errors)
461 else: 461 else:
462 msg = ('Issue %s. URL: %s' % 462 msg = ('Issue %s. URL: %s' %
463 (action, 463 (action,
464 request.build_absolute_uri('/%s' % issue.key().id()))) 464 request.build_absolute_uri('/%s' % issue.key().id())))
465 return HttpResponse(msg, content_type='text/plain') 465 return HttpResponse(msg, content_type='text/plain')
466 466
467 467
468 class EmptyPatchSet(Exception): 468 class EmptyPatchSet(Exception):
469 """Exception used inside _make_new() to break out of the transaction.""" 469 """Exception used inside _make_new() to break out of the transaction."""
470 470
471 471
472 def _make_new(request, form): 472 def _make_new(request, form):
473 """Helper for new(). 473 """Helper for new().
474 474
475 Return a valid Issue, or None. 475 Return a valid Issue, or None.
476 """ 476 """
477 if not form.is_valid(): 477 if not form.is_valid():
478 return None 478 return None
479 479
480 data_url = _get_data_url(form) 480 data_url = _get_data_url(form)
481 if data_url is None: 481 if data_url is None:
482 return None 482 return None
483 data, url = data_url 483 data, url = data_url
484 484
485 reviewers = _get_reviewers(form) 485 reviewers = _get_reviewers(form)
486 if reviewers is None: 486 if reviewers is None:
487 return None 487 return None
488 488
489 base = form.get_base() 489 base = form.get_base()
490 if base is None: 490 if base is None:
491 return None 491 return None
492 492
493 def txn(): 493 def txn():
494 #print base
495 #print data
496 #logging.info(base)
497 #logging.info(data)
494 issue = models.Issue(subject=form.cleaned_data['subject'], 498 issue = models.Issue(subject=form.cleaned_data['subject'],
495 description=form.cleaned_data['description'], 499 description=form.cleaned_data['description'],
496 base=base, 500 base=base,
497 reviewers=reviewers, 501 reviewers=reviewers,
498 owner=request.user) 502 owner=request.user)
499 issue.put() 503 issue.put()
500 504
501 patchset = models.PatchSet(issue=issue, data=data, url=url, 505 patchset = models.PatchSet(issue=issue, data=data, url=url,
502 base=base, owner=request.user, parent=issue) 506 base=base, owner=request.user, parent=issue)
503 patchset.put() 507 patchset.put()
504 508
505 patches = engine.ParsePatchSet(patchset) 509 patches = engine.ParsePatchSet(patchset)
506 if not patches: 510 if not patches:
507 raise EmptyPatchSet # Abort the transaction 511 raise EmptyPatchSet # Abort the transaction
508 db.put(patches) 512 db.put(patches)
509 return issue 513 return issue
510 514
511 try: 515 try:
512 return db.run_in_transaction(txn) 516 return db.run_in_transaction(txn)
513 except EmptyPatchSet: 517 except EmptyPatchSet:
514 errkey = url and 'url' or 'data' 518 errkey = url and 'url' or 'data'
515 form.errors[errkey] = ['Patch set contains no recognizable patches'] 519 form.errors[errkey] = ['Patch set contains no recognizable patches']
516 return None 520 return None
517 521
518 522
519 def _get_data_url(form): 523 def _get_data_url(form):
520 """Helper for _make_new() above and add() below.""" 524 """Helper for _make_new() above and add() below."""
521 cleaned_data = form.cleaned_data 525 cleaned_data = form.cleaned_data
522 526
523 data = cleaned_data['data'] 527 data = cleaned_data['data']
524 url = cleaned_data.get('url') 528 url = cleaned_data.get('url')
525 if not (data or url): 529 if not (data or url):
526 form.errors['data'] = ['You must specify a URL or upload a file'] 530 form.errors['data'] = ['You must specify a URL or upload a file']
527 return None 531 return None
528 if data and url: 532 if data and url:
529 form.errors['data'] = ['You must specify either a URL or upload a file ' 533 form.errors['data'] = ['You must specify either a URL or upload a file '
530 'but not both'] 534 'but not both']
531 return None 535 return None
532 536
533 if data is not None: 537 if data is not None:
534 data = db.Blob(data.content) 538 data = db.Blob(data.content)
535 url = None 539 url = None
536 else: 540 else:
537 assert url 541 assert url
538 try: 542 try:
539 fetch_result = urlfetch.fetch(url) 543 fetch_result = urlfetch.fetch(url)
540 except Exception, err: 544 except Exception, err:
541 form.errors['url'] = [str(err)] 545 form.errors['url'] = [str(err)]
542 return None 546 return None
543 if fetch_result.status_code != 200: 547 if fetch_result.status_code != 200:
(...skipping 678 matching lines...) Show 10 above Show 10 below
1222 return respond(request, 'branch_edit.html', 1226 return respond(request, 'branch_edit.html',
1223 {'branch': branch, 'form': form}) 1227 {'branch': branch, 'form': form})
1224 branch.put() 1228 branch.put()
1225 return HttpResponseRedirect('/repos') 1229 return HttpResponseRedirect('/repos')
1226 1230
1227 1231
1228 @login_required 1232 @login_required
1229 def branch_delete(request, branch_id): 1233 def branch_delete(request, branch_id):
1230 """/branch_delete/<branch> - Delete a Branch record.""" 1234 """/branch_delete/<branch> - Delete a Branch record."""
1231 branch = models.Branch.get_by_id(int(branch_id)) 1235 branch = models.Branch.get_by_id(int(branch_id))
1232 if branch.owner != request.user: 1236 if branch.owner != request.user:
1233 return HttpResponseForbidden('You do not own this branch') 1237 return HttpResponseForbidden('You do not own this branch')
1234 repo = branch.repo 1238 repo = branch.repo
1235 branch.delete() 1239 branch.delete()
1236 num_branches = models.Branch.gql('WHERE repo = :1', repo).count() 1240 num_branches = models.Branch.gql('WHERE repo = :1', repo).count()
1237 if not num_branches: 1241 if not num_branches:
1238 # Even if we don't own the repository? Yes, I think so! Empty 1242 # Even if we don't own the repository? Yes, I think so! Empty
1239 # repositories have no representation on screen. 1243 # repositories have no representation on screen.
1240 repo.delete() 1244 repo.delete()
1241 return HttpResponseRedirect('/repos') 1245 return HttpResponseRedirect('/repos')
1242 1246
1243 1247
1244 ### User Profiles ### 1248 ### User Profiles ###
1245 1249
1246 @login_required 1250 @login_required
1247 def settings(request): 1251 def settings(request):
1248 account = models.Account.get_account_for_user(request.user) 1252 account = models.Account.get_account_for_user(request.user)
1249 if request.method != 'POST': 1253 if request.method != 'POST':
1250 nickname = account.nickname 1254 nickname = account.nickname
1251 form = SettingsForm(initial={'nickname': nickname}) 1255 form = SettingsForm(initial={'nickname': nickname})
1252 return respond(request, 'settings.html', {'form': form}) 1256 return respond(request, 'settings.html', {'form': form})
1253 form = SettingsForm(request.POST) 1257 form = SettingsForm(request.POST)
1254 if form.is_valid(): 1258 if form.is_valid():
1255 nickname = form.cleaned_data['nickname'].strip() 1259 nickname = form.cleaned_data['nickname'].strip()
1256 if not nickname: 1260 if not nickname:
1257 form.errors['nickname'] = ['Your nickname cannot be empty.'] 1261 form.errors['nickname'] = ['Your nickname cannot be empty.']
1258 elif '@' in nickname: 1262 elif '@' in nickname:
1259 form.errors['nickname'] = ['Your nickname cannot contain "@".'] 1263 form.errors['nickname'] = ['Your nickname cannot contain "@".']
1260 elif ',' in nickname: 1264 elif ',' in nickname:
1261 form.errors['nickname'] = ['Your nickname cannot contain ",".'] 1265 form.errors['nickname'] = ['Your nickname cannot contain ",".']
1262 else: 1266 else:
1263 accounts = models.Account.get_accounts_for_nickname(nickname) 1267 accounts = models.Account.get_accounts_for_nickname(nickname)
1264 if nickname != account.nickname and accounts: 1268 if nickname != account.nickname and accounts:
1265 form.errors['nickname'] = ['This nickname is already in use.'] 1269 form.errors['nickname'] = ['This nickname is already in use.']
1266 else: 1270 else:
1267 account.nickname = nickname 1271 account.nickname = nickname
1268 account.put() 1272 account.put()
1269 if not form.is_valid(): 1273 if not form.is_valid():
1270 return respond(request, 'settings.html', {'form': form}) 1274 return respond(request, 'settings.html', {'form': form})
1271 return HttpResponseRedirect('/settings') 1275 return HttpResponseRedirect('/settings')
OLDNEW

Powered by Google App Engine
This is Rietveld r292