@webapi_login_required
    @webapi_check_local_site
    @webapi_response_errors(DOES_NOT_EXIST, NOT_LOGGED_IN, PERMISSION_DENIED,
                            REPO_FILE_NOT_FOUND, INVALID_FORM_DATA,
                            INVALID_ATTRIBUTE, DIFF_EMPTY, DIFF_TOO_BIG)
    @webapi_request_fields(
        required={
            'path': {
                'type': file,
                'description': 'The main diff to upload.',
            },
        },
        optional={
            'basedir': {
                'type': six.text_type,
                'description': 'The base directory that will prepended to '
                               'all paths in the diff. This is needed for '
                               'some types of repositories. The directory '
                               'must be between the root of the repository '
                               'and the top directory referenced in the '
                               'diff paths.',
            },
            'parent_diff_path': {
                'type': file,
                'description': 'The optional parent diff to upload.',
            },
            'base_commit_id': {
                'type': six.text_type,
                'description': 'The ID/revision this change is built upon. '
                               'If using a parent diff, then this is the base '
                               'for that diff. This may not be provided for '
                               'all diffs or repository types, depending on '
                               'how the diff was uploaded.',
                'added_in': '1.7.13',
            },
        },
        allow_unknown=True
    )
    def create(self, request, extra_fields={}, *args, **kwargs):
        # 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.'
            }

        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.get_no_access_error(request)

        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, 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,
        }
Creates a new diff by parsing an uploaded diff file.
dataset/ETHPy150Open reviewboard/reviewboard/reviewboard/webapi/resources/diff.py/DiffResource.create