コード例 #1
0
    def test_put_finalize_validation_info_extra_commits(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 when
        validation_info contains commits that do not exist
        """
        with override_feature_check(dvcs_feature.feature_id, enabled=True):
            review_request = self.create_review_request(
                create_repository=True,
                create_with_history=True,
                submitter=self.user)
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)
            commit = self.create_diffcommit(diffset=diffset)
            filediff = commit.files.first()

            validation_info = update_validation_info(
                {},
                commit_id=commit.commit_id,
                parent_id=commit.parent_id,
                filediffs=[filediff])

            validation_info = update_validation_info(
                validation_info,
                commit_id='f00',
                parent_id=commit.commit_id,
                filediffs=[])

            cumulative_diff = SimpleUploadedFile('diff',
                                                 filediff.diff,
                                                 content_type='text/x-patch')

            rsp = self.api_put(
                get_draft_diff_item_url(review_request, diffset.revision), {
                    'finalize_commit_series': True,
                    'cumulative_diff': cumulative_diff,
                    'validation_info':
                    serialize_validation_info(validation_info),
                },
                expected_status=400)

        self.assertEqual(
            rsp, {
                'stat': 'fail',
                'err': {
                    'code': INVALID_FORM_DATA.code,
                    'msg': INVALID_FORM_DATA.msg,
                },
                'fields': {
                    'validation_info': [
                        'The following commits are specified in validation_info '
                        'but do not exist: f00'
                    ],
                },
            })
コード例 #2
0
    def test_put_finalized_with_parent(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 and a parent
        diff
        """
        def _get_file_exists(repository,
                             path,
                             revision,
                             base_commit_id=None,
                             request=None):
            self.assertEqual(path, 'README')
            self.assertEqual(revision, 'f00f00')

            return True

        self.spy_on(Repository.get_file_exists, call_fake=_get_file_exists)

        with override_feature_check(dvcs_feature.feature_id, enabled=True):
            review_request = self.create_review_request(
                create_repository=True,
                create_with_history=True,
                submitter=self.user)
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)
            commit = self.create_diffcommit(diffset=diffset)

            filediff = FileDiff.objects.get()
            filediff.parent_diff = (b'diff --git a/README b/README\n'
                                    b'index f00f00..94bdd3e\n'
                                    b'--- a/README\n'
                                    b'+++ b/README\n')
            filediff.extra_data[FileDiff._IS_PARENT_EMPTY_KEY] = True
            filediff.save(update_fields=('extra_data', ))

            cumulative_diff = SimpleUploadedFile('diff',
                                                 filediff.diff,
                                                 content_type='text/x-patch')

            parent_diff = SimpleUploadedFile('parent_diff',
                                             filediff.parent_diff,
                                             content_type='text/x-patch')

            validation_info = update_validation_info(
                {},
                commit_id=commit.commit_id,
                parent_id=commit.parent_id,
                filediffs=[filediff])

            rsp = self.api_put(
                get_draft_diff_item_url(review_request, diffset.revision), {
                    'finalize_commit_series': True,
                    'cumulative_diff': cumulative_diff,
                    'parent_diff': parent_diff,
                    'validation_info':
                    serialize_validation_info(validation_info),
                },
                expected_mimetype=diff_item_mimetype)

        self.assertEqual(rsp['stat'], 'ok')
        self.compare_item(rsp['diff'], diffset)
コード例 #3
0
    def test_put_finalize_adds_default_reviewers(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 adds
        default reviewers
        """
        @self.spy_for(Repository.get_file_exists, owner=Repository)
        def _get_file_exists(repository, path, revision, **kwargs):
            self.assertEqual(path, 'README')
            self.assertEqual(revision, '94bdd3e')

            return True

        with override_feature_check(dvcs_feature.feature_id, enabled=True):
            review_request = self.create_review_request(
                create_repository=True,
                create_with_history=True,
                submitter=self.user)

            # Create the state needed for the default reviewer.
            group = self.create_review_group(name='group1')

            default_reviewer = DefaultReviewer.objects.create(name='default1',
                                                              file_regex='.')
            default_reviewer.groups.add(group)
            default_reviewer.repository.add(review_request.repository)

            # Create the state needed for the diff to post.
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)
            commit = self.create_diffcommit(diffset=diffset)

            filediff = FileDiff.objects.get()

            cumulative_diff = SimpleUploadedFile('diff',
                                                 filediff.diff,
                                                 content_type='text/x-patch')

            validation_info = update_validation_info(
                {},
                commit_id=commit.commit_id,
                parent_id=commit.parent_id,
                filediffs=[filediff])

            # Post the diff.
            rsp = self.api_put(
                get_draft_diff_item_url(review_request, diffset.revision), {
                    'finalize_commit_series': True,
                    'cumulative_diff': cumulative_diff,
                    'validation_info':
                    serialize_validation_info(validation_info),
                },
                expected_mimetype=diff_item_mimetype)

            self.assertEqual(rsp['stat'], 'ok')
            self.compare_item(rsp['diff'], diffset)

            draft = review_request.get_draft()
            self.assertEqual(list(draft.target_groups.all()), [group])
コード例 #4
0
    def test_put_finalize_validation_info_missing_commits(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 when
        validation_info does not contain all commits
        """
        with override_feature_check(dvcs_feature.feature_id, enabled=True):
            review_request = self.create_review_request(
                create_repository=True,
                create_with_history=True,
                submitter=self.user)
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)

            commits = [
                self.create_diffcommit(diffset=diffset, **kwargs)
                for kwargs in (
                    {'commit_id': 'r1', 'parent_id': 'r0'},
                    {'commit_id': 'r2', 'parent_id': 'r1'},
                )
            ]

            filediff = commits[0].files.first()

            validation_info = update_validation_info(
                {},
                commit_id=commits[0].commit_id,
                parent_id=commits[0].parent_id,
                filediffs=[filediff])

            cumulative_diff = SimpleUploadedFile('diff', filediff.diff,
                                                 content_type='text/x-patch')

            rsp = self.api_put(
                get_draft_diff_item_url(review_request, diffset.revision),
                {
                    'finalize_commit_series': True,
                    'cumulative_diff': cumulative_diff,
                    'validation_info': serialize_validation_info(
                        validation_info),
                },
                expected_status=400)

        self.assertEqual(rsp, {
            'stat': 'fail',
            'err': {
                'code': INVALID_FORM_DATA.code,
                'msg': INVALID_FORM_DATA.msg,
            },
            'fields': {
                'validation_info': [
                    'The following commits exist but are not present in '
                    'validation_info: r2',
                ],
            }
        })
コード例 #5
0
    def test_put_finalize(self):
        """Testing the PUT <URL> API with finalize_commit_series=1"""
        def _get_file_exists(repository,
                             path,
                             revision,
                             base_commit_id=None,
                             request=None):
            self.assertEqual(path, 'README')
            self.assertEqual(revision, '94bdd3e')

            return True

        self.spy_on(Repository.get_file_exists,
                    owner=Repository,
                    call_fake=_get_file_exists)

        with override_feature_check(dvcs_feature.feature_id, enabled=True):
            review_request = self.create_review_request(
                create_repository=True,
                create_with_history=True,
                submitter=self.user)
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)
            commit = self.create_diffcommit(diffset=diffset)

            filediff = FileDiff.objects.get()

            cumulative_diff = SimpleUploadedFile('diff',
                                                 filediff.diff,
                                                 content_type='text/x-patch')

            validation_info = update_validation_info(
                {},
                commit_id=commit.commit_id,
                parent_id=commit.parent_id,
                filediffs=[filediff])

            rsp = self.api_put(
                get_draft_diff_item_url(review_request, diffset.revision), {
                    'finalize_commit_series': True,
                    'cumulative_diff': cumulative_diff,
                    'validation_info':
                    serialize_validation_info(validation_info),
                },
                expected_mimetype=diff_item_mimetype)

            self.assertEqual(rsp['stat'], 'ok')
            self.compare_item(rsp['diff'], diffset)
コード例 #6
0
    def create(self,
               request,
               repository,
               commit_id,
               parent_id,
               base_commit_id=None,
               local_site_name=None,
               *args,
               **kwargs):
        """Validate a diff for a commit.

        This API has a similar signature to the :ref:`Draft DiffCommit resource
        <webapi2.0-draft-diff-commit-list-resource>` POST API, but instead of
        actually creating commits, it will return a result representing whether
        or not the included diff file parsed and validated correctly.

        This API must be called before posting to the :ref:`Draft DiffCommit
        resource <webapi2.0-draft-diff-commit-list-resource>` because the
        ``validation_info`` field returned by this resource is required for
        posting to that resource.
        """
        local_site = self._get_local_site(local_site_name)

        try:
            q = Q(pk=int(repository))
        except ValueError:
            q = (Q(path=repository) | Q(mirror_path=repository)
                 | Q(name=repository))

        repository_qs = (Repository.objects.accessible(
            request.user, local_site=local_site).filter(q))
        repository_count = len(repository_qs)

        if repository_count == 0:
            return INVALID_REPOSITORY, {
                'repository': repository,
            }
        elif repository_count > 1:
            msg = ('Too many repositories matched "%s". Try specifying the '
                   'repository by name instead.' % repository)

            return INVALID_REPOSITORY.with_message(msg), {
                'repository': repository,
            }

        repository = repository_qs.first()

        if not repository.scmtool_class.supports_history:
            return INVALID_ATTRIBUTE, {
                'reason':
                ('The "%s" repository does not support review requests '
                 'created with history.' % repository.name),
            }

        form = ValidateCommitForm(repository=repository,
                                  request=request,
                                  data=request.POST,
                                  files=request.FILES)

        if not form.is_valid():
            return INVALID_FORM_DATA, {
                'fields': self._get_form_errors(form),
            }

        try:
            filediffs = form.validate_diff()
        except FileNotFoundError as e:
            return REPO_FILE_NOT_FOUND, {
                'file': e.path,
                'revision': six.text_type(e.revision),
            }
        except EmptyDiffError:
            return DIFF_EMPTY
        except DiffTooBigError as e:
            return DIFF_TOO_BIG, {
                'reason': six.text_type(e),
                'max_size': e.max_diff_size,
            }
        except DiffParserError as e:
            return DIFF_PARSE_ERROR, {
                'reason': six.text_type(e),
                'linenum': e.linenum,
            }
        except ShortSHA1Error as e:
            return REPO_FILE_NOT_FOUND, {
                'reason': six.text_type(e),
                'file': e.path,
                'revision': six.text_type(e.revision),
            }
        except SCMError as e:
            return DIFF_PARSE_ERROR.with_message(six.text_type(e))
        except Exception as e:
            logger.exception(
                'Unexpected exception occurred while validating commit "%s" '
                'in repository "%s" (id %d) with base_commit_id="%s"',
                commit_id,
                repository.name,
                repository.pk,
                base_commit_id,
                request=request)
            return DIFF_PARSE_ERROR.with_message(
                'Unexpected error while validating the diff: %s' % e)

        validation_info = update_validation_info(
            form.cleaned_data.get('validation_info', {}), commit_id, parent_id,
            filediffs)

        return 200, {
            self.item_result_key: {
                'validation_info': serialize_validation_info(validation_info),
            }
        }
コード例 #7
0
    def create(self, request, repository, commit_id, parent_id,
               base_commit_id=None, local_site_name=None, *args, **kwargs):
        """Validate a diff for a commit.

        This API has a similar signature to the :ref:`Draft DiffCommit resource
        <webapi2.0-draft-diff-commit-list-resource>` POST API, but instead of
        actually creating commits, it will return a result representing whether
        or not the included diff file parsed and validated correctly.

        This API must be called before posting to the :ref:`Draft DiffCommit
        resource <webapi2.0-draft-diff-commit-list-resource>` because the
        ``validation_info`` field returned by this resource is required for
        posting to that resource.
        """
        local_site = self._get_local_site(local_site_name)

        try:
            q = Q(pk=int(repository))
        except ValueError:
            q = (Q(path=repository) |
                 Q(mirror_path=repository) |
                 Q(name=repository))

        repository_qs = (
            Repository.objects
            .accessible(request.user, local_site=local_site)
            .filter(q)
        )
        repository_count = len(repository_qs)

        if repository_count == 0:
            return INVALID_REPOSITORY, {
                'repository': repository,
            }
        elif repository_count > 1:
            msg = (
                'Too many repositories matched "%s". Try specifying the '
                'repository by name instead.'
                % repository
            )

            return INVALID_REPOSITORY.with_message(msg), {
                'repository': repository,
            }

        repository = repository_qs.first()

        if not repository.scmtool_class.supports_history:
            return INVALID_ATTRIBUTE, {
                'reason': (
                    'The "%s" repository does not support review requests '
                    'created with history.'
                    % repository.name
                ),
            }

        form = ValidateCommitForm(repository=repository,
                                  request=request,
                                  data=request.POST,
                                  files=request.FILES)

        if not form.is_valid():
            return INVALID_FORM_DATA, {
                'fields': self._get_form_errors(form),
            }

        try:
            filediffs = form.validate_diff()
        except FileNotFoundError as e:
            return REPO_FILE_NOT_FOUND, {
                'file': e.path,
                'revision': six.text_type(e.revision),
            }
        except EmptyDiffError:
            return DIFF_EMPTY
        except DiffTooBigError as e:
            return DIFF_TOO_BIG, {
                'reason': six.text_type(e),
                'max_size': e.max_diff_size,
            }
        except DiffParserError as e:
            return DIFF_PARSE_ERROR, {
                'reason': six.text_type(e),
                'linenum': e.linenum,
            }
        except ShortSHA1Error as e:
            return REPO_FILE_NOT_FOUND, {
                'reason': six.text_type(e),
                'file': e.path,
                'revision': six.text_type(e.revision),
            }
        except SCMError as e:
            return DIFF_PARSE_ERROR.with_message(six.text_type(e))
        except Exception as e:
            logger.exception(
                'Unexpected exception occurred while validating commit "%s" '
                'in repository "%s" (id %d) with base_commit_id="%s"',
                commit_id,
                repository.name,
                repository.pk,
                base_commit_id,
                request=request)
            return DIFF_PARSE_ERROR.with_message(
                'Unexpected error while validating the diff: %s' % e)

        validation_info = update_validation_info(
            form.cleaned_data.get('validation_info', {}),
            commit_id,
            parent_id,
            filediffs)

        return 200, {
            self.item_result_key: {
                'validation_info': serialize_validation_info(
                    validation_info),
            }
        }
コード例 #8
0
    def test_put_finalize_adds_default_reviewers_first_time_only(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 doesn't
        add default reviewers a second time
        """
        def _get_file_exists(repository,
                             path,
                             revision,
                             base_commit_id=None,
                             request=None):
            self.assertEqual(path, 'README')
            self.assertEqual(revision, '94bdd3e')

            return True

        self.spy_on(Repository.get_file_exists, call_fake=_get_file_exists)

        with override_feature_check(dvcs_feature.feature_id, enabled=True):
            review_request = self.create_review_request(
                create_repository=True,
                create_with_history=True,
                submitter=self.user)

            # Create the state needed for the default reviewer.
            group = self.create_review_group(name='group1')

            default_reviewer = DefaultReviewer.objects.create(name='default1',
                                                              file_regex='.')
            default_reviewer.groups.add(group)
            default_reviewer.repository.add(review_request.repository)

            # Create the initial diffset. This should prevent a default
            # reviewer from being applied, since we're not publishing the first
            # diff on a review request.
            self.create_diffset(review_request=review_request)

            # Create the state needed for the diff to post.
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)

            commit = self.create_diffcommit(diffset=diffset)

            filediff = FileDiff.objects.get()

            cumulative_diff = SimpleUploadedFile('diff',
                                                 filediff.diff,
                                                 content_type='text/x-patch')

            validation_info = update_validation_info(
                {},
                commit_id=commit.commit_id,
                parent_id=commit.parent_id,
                filediffs=[filediff])

            # Post the diff.
            rsp = self.api_put(
                get_draft_diff_item_url(review_request, diffset.revision), {
                    'finalize_commit_series': True,
                    'cumulative_diff': cumulative_diff,
                    'validation_info':
                    serialize_validation_info(validation_info),
                },
                expected_mimetype=diff_item_mimetype)

            self.assertEqual(rsp['stat'], 'ok')
            self.compare_item(rsp['diff'], diffset)

            draft = review_request.get_draft()
            self.assertEqual(list(draft.target_groups.all()), [])