示例#1
0
    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)
            }
示例#2
0
    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)
            }
示例#3
0
    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())
示例#4
0
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)
示例#5
0
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)
示例#6
0
    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())
示例#7
0
    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, [])
示例#8
0
文件: json.py 项目: yang/reviewboard
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
        })
示例#9
0
    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,
        }
示例#10
0
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
示例#11
0
    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,
        }
示例#12
0
    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)
示例#13
0
    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,
        }
示例#14
0
    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,
        }