def create(self, request, *args, **kwargs): """Creates a new diff by parsing an uploaded diff file. This will implicitly create the new Review Request draft, which can be updated separately and then published. This accepts a unified diff file, validates it, and stores it along with the draft of a review request. The new diff will have a revision of 0. A parent diff can be uploaded along with the main diff. A parent diff is a diff based on an existing commit in the repository, which will be applied before the main diff. The parent diff will not be included in the diff viewer. It's useful when developing a change based on a branch that is not yet committed. In this case, a parent diff of the parent branch would be provided along with the diff of the new commit, and only the new commit will be shown. It is expected that the client will send the data as part of a :mimetype:`multipart/form-data` mimetype. The main diff's name and content would be stored in the ``path`` field. If a parent diff is provided, its name and content would be stored in the ``parent_diff_path`` field. An example of this would be:: -- SoMe BoUnDaRy Content-Disposition: form-data; name=path; filename="foo.diff" <Unified Diff Content Here> -- SoMe BoUnDaRy -- """ try: review_request = \ resources.review_request.get_object(request, *args, **kwargs) except ReviewRequest.DoesNotExist: return DOES_NOT_EXIST if not review_request.is_mutable_by(request.user): return self._no_access_error(request.user) form_data = request.POST.copy() form = UploadDiffForm(review_request, form_data, request.FILES, request=request) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: diffset = form.create(request.FILES['path'], request.FILES.get('parent_diff_path')) except FileNotFoundError, e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': unicode(e.revision) }
def test_clean_with_no_history(self): """Testing UploadDiffForm.clean with a review request created without history support """ review_request = self.create_review_request(create_repository=True) form = UploadDiffForm(review_request=review_request, data={ 'basedir': '', }, files={ 'path': SimpleUploadedFile( 'diff', self.DEFAULT_GIT_FILEDIFF_DATA), }) self.assertTrue(form.is_valid())
def _make_review_request_context(review_request, extra_context): """Returns a dictionary for template contexts used for review requests. The dictionary will contain the common data that is used for all review request-related pages (the review request detail page, the diff viewer, and the screenshot pages). For convenience, extra data can be passed to this dictionary. """ if review_request.repository: upload_diff_form = UploadDiffForm(review_request) scmtool = review_request.repository.get_scmtool() else: upload_diff_form = None scmtool = None return dict( { 'review_request': review_request, 'upload_diff_form': upload_diff_form, 'upload_screenshot_form': UploadScreenshotForm(), 'file_attachment_form': UploadFileForm(), 'comment_file_form': CommentFileForm(), 'scmtool': scmtool, }, **extra_context)
def make_review_request_context(request, review_request, extra_context={}): """Returns a dictionary for template contexts used for review requests. The dictionary will contain the common data that is used for all review request-related pages (the review request detail page, the diff viewer, and the screenshot pages). For convenience, extra data can be passed to this dictionary. """ if review_request.repository: upload_diff_form = UploadDiffForm(review_request, request=request) scmtool = review_request.repository.get_scmtool() else: upload_diff_form = None scmtool = None if 'blocks' not in extra_context: extra_context['blocks'] = list(review_request.blocks.all()) return dict({ 'mutable_by_user': review_request.is_mutable_by(request.user), 'status_mutable_by_user': review_request.is_status_mutable_by(request.user), 'review_request': review_request, 'upload_diff_form': upload_diff_form, 'comment_file_form': CommentFileForm(), 'scmtool': scmtool, }, **extra_context)
def test_clean_with_no_history(self): """Testing UploadDiffForm.clean with a review request created without history support """ review_request = self.create_review_request(create_repository=True) form = UploadDiffForm( review_request=review_request, data={ 'basedir': '', }, files={ 'path': SimpleUploadedFile('diff', self.DEFAULT_GIT_FILEDIFF_DATA_DIFF), }) self.assertTrue(form.is_valid())
def test_clean_with_history(self): """Testing UploadDiffForm.clean with a review request created with history support """ review_request = self.create_review_request(create_repository=True, create_with_history=True) form = UploadDiffForm(review_request=review_request, data={ 'basedir': '', }, files={ 'path': SimpleUploadedFile( 'diff', self.DEFAULT_GIT_FILEDIFF_DATA_DIFF), }) self.assertFalse(form.is_valid()) self.assertNotEqual(form.non_field_errors, [])
def new_diff(request, review_request_id, *args, **kwargs): review_request = get_object_or_404(ReviewRequest, pk=review_request_id) if not review_request.is_mutable_by(request.user): return WebAPIResponseError(request, PERMISSION_DENIED) form_data = request.POST.copy() form = UploadDiffForm(review_request, form_data, request.FILES) if not form.is_valid(): return WebAPIResponseFormError(request, form) try: diffset = form.create(request.FILES['path'], request.FILES.get('parent_diff_path')) except FileNotFoundError, e: return WebAPIResponseError(request, REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': e.revision })
def create(self, request, extra_fields={}, local_site=None, *args, **kwargs): """Creates a new diff by parsing an uploaded diff file. This will implicitly create the new Review Request draft, which can be updated separately and then published. This accepts a unified diff file, validates it, and stores it along with the draft of a review request. The new diff will have a revision of 0. A parent diff can be uploaded along with the main diff. A parent diff is a diff based on an existing commit in the repository, which will be applied before the main diff. The parent diff will not be included in the diff viewer. It's useful when developing a change based on a branch that is not yet committed. In this case, a parent diff of the parent branch would be provided along with the diff of the new commit, and only the new commit will be shown. It is expected that the client will send the data as part of a :mimetype:`multipart/form-data` mimetype. The main diff's name and content would be stored in the ``path`` field. If a parent diff is provided, its name and content would be stored in the ``parent_diff_path`` field. An example of this would be:: -- SoMe BoUnDaRy Content-Disposition: form-data; name=path; filename="foo.diff" <Unified Diff Content Here> -- SoMe BoUnDaRy -- Extra data can be stored later lookup. See :ref:`webapi2.0-extra-data` for more information. """ # Prevent a circular dependency, as ReviewRequestDraftResource # needs DraftDiffResource, which needs DiffResource. from reviewboard.webapi.resources.review_request_draft import \ ReviewRequestDraftResource try: review_request = \ resources.review_request.get_object(request, *args, **kwargs) except ReviewRequest.DoesNotExist: return DOES_NOT_EXIST if not review_request.is_mutable_by(request.user): return self.get_no_access_error(request) if review_request.repository is None: return INVALID_ATTRIBUTE, { 'reason': 'This review request was created as attachments-' 'only, with no repository.', } elif review_request.created_with_history: assert dvcs_feature.is_enabled(request=request) if 'path' in request.FILES: return INVALID_FORM_DATA, { 'reason': ( 'This review request was created with support for ' 'multiple commits.\n' '\n' 'Create an empty diff revision and upload commits to ' 'that instead.' ), } diffset = DiffSet.objects.create_empty( repository=review_request.repository, base_commit_id=request.POST.get('base_commit_id')) diffset.update_revision_from_history( review_request.diffset_history) diffset.save(update_fields=('revision',)) else: form_data = request.POST.copy() form = UploadDiffForm(review_request, data=form_data, files=request.FILES, request=request) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: diffset = form.create() except FileNotFoundError as e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': six.text_type(e.revision) } except EmptyDiffError as e: return DIFF_EMPTY except DiffTooBigError as e: return DIFF_TOO_BIG, { 'reason': six.text_type(e), 'max_size': e.max_diff_size, } except Exception as e: # This could be very wrong, but at least they'll see the error. # We probably want a new error type for this. logging.error("Error uploading new diff: %s", e, exc_info=1, request=request) return INVALID_FORM_DATA, { 'fields': { 'path': [six.text_type(e)] } } discarded_diffset = None try: draft = review_request.draft.get() if draft.diffset and draft.diffset != diffset: discarded_diffset = draft.diffset except ReviewRequestDraft.DoesNotExist: try: draft = ReviewRequestDraftResource.prepare_draft( request, review_request) except PermissionDenied: return self.get_no_access_error(request) draft.diffset = diffset # We only want to add default reviewers the first time. Was bug 318. if review_request.can_add_default_reviewers(): draft.add_default_reviewers() draft.save() if extra_fields: try: self.import_extra_data(diffset, diffset.extra_data, extra_fields) except ImportExtraDataError as e: return e.error_payload diffset.save(update_fields=['extra_data']) if discarded_diffset: discarded_diffset.delete() # E-mail gets sent when the draft is saved. return 201, { self.item_result_key: diffset, }
def make_review_request_context(request, review_request, extra_context={}, is_diff_view=False): """Returns a dictionary for template contexts used for review requests. The dictionary will contain the common data that is used for all review request-related pages (the review request detail page, the diff viewer, and the screenshot pages). For convenience, extra data can be passed to this dictionary. """ if review_request.repository: upload_diff_form = UploadDiffForm(review_request, request=request) scmtool = review_request.repository.get_scmtool() else: upload_diff_form = None scmtool = None if 'blocks' not in extra_context: extra_context['blocks'] = list(review_request.blocks.all()) tabs = [ { 'text': _('Reviews'), 'url': review_request.get_absolute_url(), }, ] draft = review_request.get_draft(request.user) if ((draft and draft.diffset_id) or (hasattr(review_request, '_diffsets') and len(review_request._diffsets) > 0)): has_diffs = True else: # We actually have to do a query has_diffs = DiffSet.objects.filter( history__pk=review_request.diffset_history_id).exists() if has_diffs: tabs.append({ 'active': is_diff_view, 'text': _('Diff'), 'url': ( local_site_reverse( 'view-diff', args=[review_request.display_id], local_site=review_request.local_site) + '#index_header'), }) siteconfig = SiteConfiguration.objects.get_current() review_request_details = extra_context.get('review_request_details', review_request) social_page_description = truncatechars( review_request_details.description.replace('\n', ' '), 300) context = dict({ 'mutable_by_user': review_request.is_mutable_by(request.user), 'status_mutable_by_user': review_request.is_status_mutable_by(request.user), 'review_request': review_request, 'upload_diff_form': upload_diff_form, 'scmtool': scmtool, 'send_email': siteconfig.get('mail_send_review_mail'), 'tabs': tabs, 'social_page_description': social_page_description, 'social_page_url': build_server_url(request.path, request=request), }, **extra_context) if ('review_request_visit' not in context and request.user.is_authenticated()): # The main review request view will already have populated this, but # other related views (like the diffviewer) don't. context['review_request_visit'] = \ ReviewRequestVisit.objects.get_or_create( user=request.user, review_request=review_request)[0] return context
def create(self, request, extra_fields={}, local_site=None, *args, **kwargs): """Creates a new diff by parsing an uploaded diff file. This will implicitly create the new Review Request draft, which can be updated separately and then published. This accepts a unified diff file, validates it, and stores it along with the draft of a review request. The new diff will have a revision of 0. A parent diff can be uploaded along with the main diff. A parent diff is a diff based on an existing commit in the repository, which will be applied before the main diff. The parent diff will not be included in the diff viewer. It's useful when developing a change based on a branch that is not yet committed. In this case, a parent diff of the parent branch would be provided along with the diff of the new commit, and only the new commit will be shown. It is expected that the client will send the data as part of a :mimetype:`multipart/form-data` mimetype. The main diff's name and content would be stored in the ``path`` field. If a parent diff is provided, its name and content would be stored in the ``parent_diff_path`` field. An example of this would be:: -- SoMe BoUnDaRy Content-Disposition: form-data; name=path; filename="foo.diff" <Unified Diff Content Here> -- SoMe BoUnDaRy -- Extra data can be stored later lookup. See :ref:`webapi2.0-extra-data` for more information. """ # Prevent a circular dependency, as ReviewRequestDraftResource # needs DraftDiffResource, which needs DiffResource. from reviewboard.webapi.resources.review_request_draft import \ ReviewRequestDraftResource try: review_request = \ resources.review_request.get_object(request, *args, **kwargs) except ReviewRequest.DoesNotExist: return DOES_NOT_EXIST if not review_request.is_mutable_by(request.user): return self.get_no_access_error(request) if review_request.repository is None: return INVALID_ATTRIBUTE, { 'reason': 'This review request was created as attachments-' 'only, with no repository.', } elif review_request.created_with_history: assert dvcs_feature.is_enabled(request=request) if 'path' in request.FILES: return INVALID_FORM_DATA, { 'reason': ('This review request was created with support for ' 'multiple commits.\n' '\n' 'Create an empty diff revision and upload commits to ' 'that instead.'), } diffset = DiffSet.objects.create_empty( repository=review_request.repository, base_commit_id=request.POST.get('base_commit_id')) diffset.update_revision_from_history( review_request.diffset_history) diffset.save(update_fields=('revision', )) else: form_data = request.POST.copy() form = UploadDiffForm(review_request, data=form_data, files=request.FILES, request=request) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: diffset = form.create() except FileNotFoundError as e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': six.text_type(e.revision) } except EmptyDiffError as e: return DIFF_EMPTY except DiffTooBigError as e: return DIFF_TOO_BIG, { 'reason': six.text_type(e), 'max_size': e.max_diff_size, } except Exception as e: # This could be very wrong, but at least they'll see the error. # We probably want a new error type for this. logger.error("Error uploading new diff: %s", e, exc_info=1, request=request) return INVALID_FORM_DATA, { 'fields': { 'path': [six.text_type(e)] } } discarded_diffset = None try: draft = review_request.draft.get() if draft.diffset and draft.diffset != diffset: discarded_diffset = draft.diffset except ReviewRequestDraft.DoesNotExist: try: draft = ReviewRequestDraftResource.prepare_draft( request, review_request) except PermissionDenied: return self.get_no_access_error(request) draft.diffset = diffset # We only want to add default reviewers the first time. Was bug 318. if review_request.can_add_default_reviewers(): draft.add_default_reviewers() draft.save() if extra_fields: try: self.import_extra_data(diffset, diffset.extra_data, extra_fields) except ImportExtraDataError as e: return e.error_payload diffset.save(update_fields=['extra_data']) if discarded_diffset: discarded_diffset.delete() # E-mail gets sent when the draft is saved. return 201, { self.item_result_key: diffset, }
def handle_noargs(self, users=None, review_requests=None, diffs=None, reviews=None, diff_comments=None, password=None, verbosity=NORMAL, **options): num_of_requests = None num_of_diffs = None num_of_reviews = None num_of_diff_comments = None random.seed() if review_requests: num_of_requests = self.parseCommand("review_requests", review_requests) # Setup repository. repo_dir = os.path.abspath( os.path.join(sys.argv[0], "..", "scmtools", "testdata", "git_repo")) # Throw exception on error so transaction reverts. if not os.path.exists(repo_dir): raise CommandError("No path to the repository") self.repository = Repository.objects.create( name="Test Repository", path=repo_dir, tool=Tool.objects.get(name="Git")) if diffs: num_of_diffs = self.parseCommand("diffs", diffs) # Create the diff directory locations. diff_dir_tmp = os.path.abspath( os.path.join(sys.argv[0], "..", "reviews", "management", "commands", "diffs")) # Throw exception on error so transaction reverts. if not os.path.exists(diff_dir_tmp): raise CommandError("Diff dir does not exist") diff_dir = diff_dir_tmp + '/' # Add trailing slash. # Get a list of the appropriate files. files = [f for f in os.listdir(diff_dir) if f.endswith('.diff')] # Check for any diffs in the files. if len(files) == 0: raise CommandError("No diff files in this directory") if reviews: num_of_reviews = self.parseCommand("reviews", reviews) if diff_comments: num_of_diff_comments = self.parseCommand("diff-comments", diff_comments) # Users is required for any other operation. if not users: raise CommandError("At least one user must be added") # Start adding data to the database. for i in range(1, users + 1): new_user = User.objects.create( username=self.randUsername(), # Avoids having to flush db. first_name=random.choice(NAMES), last_name=random.choice(NAMES), email="*****@*****.**", is_staff=False, is_active=True, is_superuser=False) if password: new_user.set_password(password) new_user.save() else: new_user.set_password("test1") new_user.save() Profile.objects.create( user=new_user, first_time_setup_done=True, collapsed_diffs=True, wordwrapped_diffs=True, syntax_highlighting=True, show_closed=True) # Review Requests. req_val = self.pickRandomValue(num_of_requests) if int(verbosity) > NORMAL: self.stdout.write("For user %s:%s" % (i, new_user.username)) self.stdout.write("=============================") for j in range(0, req_val): if int(verbosity) > NORMAL: self.stdout.write("Request #%s:" % j) review_request = ReviewRequest.objects.create(new_user, None) review_request.public = True review_request.summary = self.lorem_ipsum("summary") review_request.description = self.lorem_ipsum("description") review_request.shipit_count = 0 review_request.repository = self.repository # Set the targeted reviewer to superuser or 1st defined. if j == 0: review_request.target_people.add(User.objects.get(pk=1)) review_request.save() # Add the diffs if any to add. diff_val = self.pickRandomValue(num_of_diffs) # If adding diffs add history. if diff_val > 0: diffset_history = DiffSetHistory.objects.create( name='testDiffFile' + six.text_type(i)) diffset_history.save() # Won't execute if diff_val is 0, ie: no diffs requested. for k in range(0, diff_val): if int(verbosity) > NORMAL: self.stdout.write("%s:\tDiff #%s" % (i, k)) random_number = random.randint(0, len(files) - 1) file_to_open = diff_dir + files[random_number] f = open(file_to_open, 'r') form = UploadDiffForm(review_request=review_request, files={"path": File(f)}) if form.is_valid(): cur_diff = form.create(f, None, diffset_history) review_request.diffset_history = diffset_history review_request.save() review_request.publish(new_user) f.close() # Add the reviews if any. review_val = self.pickRandomValue(num_of_reviews) for l in range(0, review_val): if int(verbosity) > NORMAL: self.stdout.write("%s:%s:\t\tReview #%s:" % (i, j, l)) reviews = Review.objects.create( review_request=review_request, user=new_user) reviews.publish(new_user) # Add comments if any. comment_val = self.pickRandomValue( num_of_diff_comments) for m in range(0, comment_val): if int(verbosity) > NORMAL: self.stdout.write("%s:%s:\t\t\tComments #%s" % (i, j, m)) if m == 0: file_diff = cur_diff.files.order_by('id')[0] # Choose random lines to comment. # Max lines: should be mod'd in future to read # diff. max_lines = 220 first_line = random.randrange(1, max_lines - 1) remain_lines = max_lines - first_line num_lines = random.randrange(1, remain_lines) diff_comment = Comment.objects.create( filediff=file_diff, text="comment number %s" % (m + 1), first_line=first_line, num_lines=num_lines) review_request.publish(new_user) reviews.comments.add(diff_comment) reviews.save() reviews.publish(new_user) db.reset_queries() # No comments, so have previous layer clear queries. if comment_val == 0: db.reset_queries() if review_val == 0: db.reset_queries() if diff_val == 0: db.reset_queries() if req_val == 0: db.reset_queries() # Generate output as users & data is created. if req_val != 0: self.stdout.write("user %s created with %s requests" % (new_user.username, req_val)) else: self.stdout.write("user %s created successfully" % new_user.username)
def create(self, request, *args, **kwargs): """Creates a new diff by parsing an uploaded diff file. This will implicitly create the new Review Request draft, which can be updated separately and then published. This accepts a unified diff file, validates it, and stores it along with the draft of a review request. The new diff will have a revision of 0. A parent diff can be uploaded along with the main diff. A parent diff is a diff based on an existing commit in the repository, which will be applied before the main diff. The parent diff will not be included in the diff viewer. It's useful when developing a change based on a branch that is not yet committed. In this case, a parent diff of the parent branch would be provided along with the diff of the new commit, and only the new commit will be shown. It is expected that the client will send the data as part of a :mimetype:`multipart/form-data` mimetype. The main diff's name and content would be stored in the ``path`` field. If a parent diff is provided, its name and content would be stored in the ``parent_diff_path`` field. An example of this would be:: -- SoMe BoUnDaRy Content-Disposition: form-data; name=path; filename="foo.diff" <Unified Diff Content Here> -- SoMe BoUnDaRy -- """ # Prevent a circular dependency, as ReviewRequestDraftResource # needs DraftDiffResource, which needs DiffResource. from reviewboard.webapi.resources.review_request_draft import \ ReviewRequestDraftResource try: review_request = \ resources.review_request.get_object(request, *args, **kwargs) except ReviewRequest.DoesNotExist: return DOES_NOT_EXIST if not review_request.is_mutable_by(request.user): return self._no_access_error(request.user) form_data = request.POST.copy() form = UploadDiffForm(review_request, form_data, request.FILES, request=request) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: diffset = form.create(request.FILES['path'], request.FILES.get('parent_diff_path')) except FileNotFoundError as e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': six.text_type(e.revision) } except EmptyDiffError as e: return DIFF_EMPTY except DiffTooBigError as e: return DIFF_TOO_BIG, { 'reason': six.text_type(e), 'max_size': e.max_diff_size, } except Exception as e: # This could be very wrong, but at least they'll see the error. # We probably want a new error type for this. logging.error("Error uploading new diff: %s", e, exc_info=1, request=request) return INVALID_FORM_DATA, {'fields': {'path': [six.text_type(e)]}} discarded_diffset = None try: draft = review_request.draft.get() if draft.diffset and draft.diffset != diffset: discarded_diffset = draft.diffset except ReviewRequestDraft.DoesNotExist: try: draft = ReviewRequestDraftResource.prepare_draft( request, review_request) except PermissionDenied: return self._no_access_error(request.user) draft.diffset = diffset # We only want to add default reviewers the first time. Was bug 318. if review_request.diffset_history.diffsets.count() == 0: draft.add_default_reviewers() draft.save() if discarded_diffset: discarded_diffset.delete() # E-mail gets sent when the draft is saved. return 201, { self.item_result_key: diffset, }
def create(self, request, extra_fields={}, *args, **kwargs): """Creates a new diff by parsing an uploaded diff file. This will implicitly create the new Review Request draft, which can be updated separately and then published. This accepts a unified diff file, validates it, and stores it along with the draft of a review request. The new diff will have a revision of 0. A parent diff can be uploaded along with the main diff. A parent diff is a diff based on an existing commit in the repository, which will be applied before the main diff. The parent diff will not be included in the diff viewer. It's useful when developing a change based on a branch that is not yet committed. In this case, a parent diff of the parent branch would be provided along with the diff of the new commit, and only the new commit will be shown. It is expected that the client will send the data as part of a :mimetype:`multipart/form-data` mimetype. The main diff's name and content would be stored in the ``path`` field. If a parent diff is provided, its name and content would be stored in the ``parent_diff_path`` field. An example of this would be:: -- SoMe BoUnDaRy Content-Disposition: form-data; name=path; filename="foo.diff" <Unified Diff Content Here> -- SoMe BoUnDaRy -- Extra data can be stored on the diff for later lookup by passing ``extra_data.key_name=value``. The ``key_name`` and ``value`` can be any valid strings. Passing a blank ``value`` will remove the key. The ``extra_data.`` prefix is required. """ # Prevent a circular dependency, as ReviewRequestDraftResource # needs DraftDiffResource, which needs DiffResource. from reviewboard.webapi.resources.review_request_draft import \ ReviewRequestDraftResource try: review_request = \ resources.review_request.get_object(request, *args, **kwargs) except ReviewRequest.DoesNotExist: return DOES_NOT_EXIST if not review_request.is_mutable_by(request.user): return self._no_access_error(request.user) form_data = request.POST.copy() form = UploadDiffForm(review_request, form_data, request.FILES, request=request) if not form.is_valid(): return INVALID_FORM_DATA, { 'fields': self._get_form_errors(form), } try: diffset = form.create(request.FILES['path'], request.FILES.get('parent_diff_path')) except FileNotFoundError as e: return REPO_FILE_NOT_FOUND, { 'file': e.path, 'revision': six.text_type(e.revision) } except EmptyDiffError as e: return DIFF_EMPTY except DiffTooBigError as e: return DIFF_TOO_BIG, { 'reason': six.text_type(e), 'max_size': e.max_diff_size, } except Exception as e: # This could be very wrong, but at least they'll see the error. # We probably want a new error type for this. logging.error("Error uploading new diff: %s", e, exc_info=1, request=request) return INVALID_FORM_DATA, { 'fields': { 'path': [six.text_type(e)] } } discarded_diffset = None try: draft = review_request.draft.get() if draft.diffset and draft.diffset != diffset: discarded_diffset = draft.diffset except ReviewRequestDraft.DoesNotExist: try: draft = ReviewRequestDraftResource.prepare_draft( request, review_request) except PermissionDenied: return self._no_access_error(request.user) draft.diffset = diffset # We only want to add default reviewers the first time. Was bug 318. if review_request.diffset_history.diffsets.count() == 0: draft.add_default_reviewers() draft.save() if extra_fields: self._import_extra_data(diffset.extra_data, extra_fields) diffset.save(update_fields=['extra_data']) if discarded_diffset: discarded_diffset.delete() # E-mail gets sent when the draft is saved. return 201, { self.item_result_key: diffset, }