Ejemplo n.º 1
0
    def test_put_finalize_dvcs_feature_disabled(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 when the
        DVCS feature is disabled
        """
        with override_feature_check(dvcs_feature.feature_id, enabled=False):
            review_request = self.create_review_request(
                create_repository=True,
                submitter=self.user)
            diffset = self.create_diffset(review_request=review_request,
                                          draft=True)

            cumulative_diff = SimpleUploadedFile('diff', b'',
                                                 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({}),
                },
                expected_mimetype=diff_item_mimetype)

        self.assertEqual(rsp['stat'], 'ok')
        self.compare_item(rsp['diff'], diffset)
Ejemplo n.º 2
0
    def test_put_finalize_empty_commit_series(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 for an empty
        commit series
        """
        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)

            cumulative_diff = SimpleUploadedFile('diff',
                                                 b'',
                                                 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({}),
                },
                expected_status=400)

        self.assertEqual(
            rsp, {
                'stat': 'fail',
                'err': {
                    'code': INVALID_ATTRIBUTE.code,
                    'msg': INVALID_ATTRIBUTE.msg,
                },
                'reason': 'Cannot finalize an empty commit series.',
            })
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
    def test_post_subsequent(self):
        """Testing the POST <URL> API with a subsequent commit"""
        repository = self.create_repository(tool_name='Git')
        review_request = self.create_review_request(
            repository=repository,
            submitter=self.user,
            create_with_history=True)
        diffset = self.create_diffset(review_request, draft=True)

        commit = self.create_diffcommit(
            repository,
            diffset,
            diff_contents=self._DEFAULT_DIFF_CONTENTS)

        validation_info = serialize_validation_info({
            commit.commit_id: {
                'parent_id': commit.parent_id,
                'tree': {
                    'added': [],
                    'modified': [{
                        'filename': 'readme',
                        'revision': '5b50866',
                    }],
                    'removed': [],
                },
            },
        })

        diff = SimpleUploadedFile(
            'diff',
            (b'diff --git a/readme b/readme\n'
             b'index 5b50866..f00f00f 100644\n'
             b'--- a/readme\n'
             b'+++ a/readme\n'
             b'@@ -1 +1,4 @@\n'
             b' Hello there\n'
             b' \n'
             b' Oh hi!\n'
             b'+Goodbye!\n'),
            content_type='text/x-patch')

        with override_feature_checks(self.override_features):
            rsp = self.api_post(
                get_draft_diffcommit_list_url(review_request,
                                              diffset.revision),
                dict(self._DEFAULT_POST_DATA, **{
                    'commit_id': 'r2',
                    'parent_id': 'r1',
                    'diff': diff,
                    'validation_info': validation_info,
                }),
                expected_mimetype=draft_diffcommit_item_mimetype)

        self.assertEqual(rsp['stat'], 'ok')
        self.assertIn('draft_commit', rsp)

        item_rsp = rsp['draft_commit']
        self.compare_item(item_rsp, DiffCommit.objects.get(pk=item_rsp['id']))
Ejemplo n.º 5
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])
Ejemplo n.º 6
0
    def test_post_subsequent(self):
        """Testing the POST <URL> API with a subsequent commit"""
        repository = self.create_repository(tool_name='Git')
        review_request = self.create_review_request(repository=repository,
                                                    submitter=self.user,
                                                    create_with_history=True)
        diffset = self.create_diffset(review_request, draft=True)

        commit = self.create_diffcommit(
            repository, diffset, diff_contents=self._DEFAULT_DIFF_CONTENTS)

        validation_info = serialize_validation_info({
            commit.commit_id: {
                'parent_id': commit.parent_id,
                'tree': {
                    'added': [],
                    'modified': [{
                        'filename': 'readme',
                        'revision': '5b50866',
                    }],
                    'removed': [],
                },
            },
        })

        diff = SimpleUploadedFile('diff', (b'diff --git a/readme b/readme\n'
                                           b'index 5b50866..f00f00f 100644\n'
                                           b'--- a/readme\n'
                                           b'+++ a/readme\n'
                                           b'@@ -1 +1,4 @@\n'
                                           b' Hello there\n'
                                           b' \n'
                                           b' Oh hi!\n'
                                           b'+Goodbye!\n'),
                                  content_type='text/x-patch')

        with override_feature_checks(self.override_features):
            rsp = self.api_post(
                get_draft_diffcommit_list_url(review_request,
                                              diffset.revision),
                dict(
                    self._DEFAULT_POST_DATA, **{
                        'commit_id': 'r2',
                        'parent_id': 'r1',
                        'diff': diff,
                        'validation_info': validation_info,
                    }),
                expected_mimetype=draft_diffcommit_item_mimetype)

        self.assertEqual(rsp['stat'], 'ok')
        self.assertIn('draft_commit', rsp)

        item_rsp = rsp['draft_commit']
        self.compare_item(item_rsp, DiffCommit.objects.get(pk=item_rsp['id']))
Ejemplo n.º 7
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',
                ],
            }
        })
Ejemplo n.º 8
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'
                    ],
                },
            })
Ejemplo n.º 9
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)
Ejemplo n.º 10
0
    def test_post_added_in_parent(self):
        """Testing the POST <URL> API with a subsequent commit that contains a
        file added in the parent diff
        """
        def _exists(repository, filename, revision, *args, **kwargs):
            return filename == 'README' and revision == '94bdd3e'

        initial_validation_info = {
            'r1': {
                'parent_id': 'r0',
                'tree': {
                    'added': [],
                    'modified': [],
                    'removed': [],
                },
            },
        }

        repo = self.create_repository(name='repo')

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

        diff = SimpleUploadedFile('diff',
                                  self.DEFAULT_GIT_FILEDIFF_DATA_DIFF,
                                  content_type='text/x-patch')

        with override_feature_checks(self.override_features):
            rsp = self.api_post(get_validate_diffcommit_url(), {
                'commit_id':
                'r2',
                'parent_id':
                'r1',
                'diff':
                diff,
                'repository':
                repo.name,
                'validation_info':
                serialize_validation_info(initial_validation_info),
            },
                                expected_mimetype=validate_diffcommit_mimetype,
                                expected_status=200)

        self.assertEqual(rsp['stat'], 'ok')
Ejemplo n.º 11
0
    def test_post_finalized(self):
        """Testing the POST <URL> API after the parent DiffSet has been
        finalized
        """
        with override_feature_checks(self.override_features):
            review_request = self.create_review_request(
                create_repository=True,
                submitter=self.user,
                create_with_history=True)

            diffset = self.create_diffset(review_request, draft=True)
            diffset.finalize_commit_series(
                cumulative_diff=self.DEFAULT_GIT_FILEDIFF_DATA_DIFF,
                validation_info=None,
                validate=False,
                save=True)

            diff = SimpleUploadedFile('diff',
                                      self._DEFAULT_DIFF_CONTENTS,
                                      content_type='text/x-patch')

            rsp = self.api_post(get_draft_diffcommit_list_url(
                review_request, diffset.revision),
                                dict(
                                    self._DEFAULT_POST_DATA, **{
                                        'validation_info':
                                        serialize_validation_info({}),
                                        'diff':
                                        diff,
                                    }),
                                expected_status=400)

            self.assertEqual(
                rsp, {
                    'stat': 'fail',
                    'err': {
                        'code': INVALID_ATTRIBUTE.code,
                        'msg': INVALID_ATTRIBUTE.msg,
                    },
                    'reason': 'The diff has already been finalized.',
                })
Ejemplo n.º 12
0
    def setup_basic_post_test(self, user, with_local_site, local_site_name,
                              post_valid_data):
        repository = self.create_repository(tool_name='Git',
                                            with_local_site=with_local_site)

        post_data = {}

        if post_valid_data:
            self.spy_on(Repository.get_file_exists,
                        owner=Repository,
                        call_fake=lambda *args, **kwargs: True)

            validation_info = serialize_validation_info({
                'r1': {
                    'parent_id': 'r0',
                    'tree': {
                        'added': [{
                            'filename': 'README',
                            'revision': '94bdd3e',
                        }],
                        'modified': [],
                        'removed': [],
                    },
                },
            })
            diff = SimpleUploadedFile('diff',
                                      self.DEFAULT_GIT_FILEDIFF_DATA_DIFF,
                                      content_type='text/x-patch')
            post_data = {
                'commit_id': 'r2',
                'parent_id': 'r1',
                'diff': diff,
                'validation_info': validation_info,
                'repository': repository.pk,
            }

        return (get_validate_diffcommit_url(local_site_name=local_site_name),
                validate_diffcommit_mimetype,
                post_data,
                [])
Ejemplo n.º 13
0
    def test_put_finalize_again(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 when the
        diff is already finalized
        """
        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)
            self.create_diffcommit(diffset=diffset)

            diffset.finalize_commit_series(
                cumulative_diff=self.DEFAULT_GIT_FILEDIFF_DATA_DIFF,
                validation_info=None,
                validate=False,
                save=True)

            cumulative_diff = SimpleUploadedFile('diff',
                                                 b'',
                                                 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({}),
                },
                expected_status=400)

        self.assertEqual(
            rsp, {
                'stat': 'fail',
                'err': {
                    'code': INVALID_ATTRIBUTE.code,
                    'msg': INVALID_ATTRIBUTE.msg,
                },
                'reason': 'This diff is already finalized.',
            })
Ejemplo n.º 14
0
    def test_post_finalized(self):
        """Testing the POST <URL> API after the parent DiffSet has been
        finalized
        """
        with override_feature_checks(self.override_features):
            review_request = self.create_review_request(
                create_repository=True,
                submitter=self.user,
                create_with_history=True)

            diffset = self.create_diffset(review_request, draft=True)
            diffset.finalize_commit_series(
                cumulative_diff=self.DEFAULT_GIT_FILEDIFF_DATA_DIFF,
                validation_info=None,
                validate=False,
                save=True)

            diff = SimpleUploadedFile(
                'diff',
                self._DEFAULT_DIFF_CONTENTS,
                content_type='text/x-patch')

            rsp = self.api_post(
                get_draft_diffcommit_list_url(review_request,
                                              diffset.revision),
                dict(self._DEFAULT_POST_DATA, **{
                    'validation_info': serialize_validation_info({}),
                    'diff': diff,
                }),
                expected_status=400)

            self.assertEqual(rsp, {
                'stat': 'fail',
                'err': {
                    'code': INVALID_ATTRIBUTE.code,
                    'msg': INVALID_ATTRIBUTE.msg,
                },
                'reason': 'The diff has already been finalized.',
            })
Ejemplo n.º 15
0
    def test_put_finalize_invalid_validation_info_json_format(self):
        """Testing the PUT <URL> API with finalize_commit_series=1 when
        validation_info is invalid json
        """
        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)
            self.create_diffcommit(diffset=diffset)

            cumulative_diff = SimpleUploadedFile('diff',
                                                 b'',
                                                 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('foo'),
                },
                expected_status=400)

        self.assertEqual(
            rsp, {
                'stat': 'fail',
                'err': {
                    'code': INVALID_FORM_DATA.code,
                    'msg': INVALID_FORM_DATA.msg,
                },
                'fields': {
                    'validation_info': [
                        'Could not parse field: Invalid format.',
                    ],
                },
            })
Ejemplo n.º 16
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),
            }
        }
Ejemplo n.º 17
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),
            }
        }
Ejemplo n.º 18
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()), [])