def create(self, request, repository, basedir=None, local_site_name=None, base_commit_id=None, *args, **kwargs): """Validate a diff. This API has a similar signature to the ReviewRequest resource POST API, but instead of actually creating a review request, will return either OK or an error, depending on whether the included diff file parsed correctly. """ local_site = self._get_local_site(local_site_name) path = request.FILES.get('path') parent_diff_path = request.FILES.get('parent_diff_path') try: query = Q(pk=int(repository), local_site=local_site) except ValueError: query = (Q(local_site=local_site) & (Q(path=repository) | Q(mirror_path=repository) | Q(name=repository))) try: repository = Repository.objects.get(query) except Repository.DoesNotExist: return INVALID_REPOSITORY, {'repository': repository} except Repository.MultipleObjectsReturned: msg = ('Too many repositories matched "%s". ' 'Try specifying the repository by name instead.' % repository) return INVALID_REPOSITORY.with_message(msg), { 'repository': repository, } if (not repository.get_scmtool().diffs_use_absolute_paths and basedir is None): return INVALID_FORM_DATA, { 'fields': { 'basedir': ['Given repository requires a base directory'], }, } if basedir is None: # If we get here, the repository uses absolute paths. Deeper down # (where we don't necessarily know about the details of the # repository), we do an os.path.join() with the basedir value, # which will choke if it's None. basedir = '' try: DiffSet.objects.create_from_upload(repository, path, parent_diff_path, None, basedir, request, base_commit_id=base_commit_id, save=False) 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: logging.exception('Unexpected error when validating diff.') return DIFF_PARSE_ERROR.with_message( 'Unexpected error when validating the diff: %s' % e) return 200, {}
def create(self, request, repository, basedir=None, local_site_name=None, base_commit_id=None, *args, **kwargs): """Validate a diff. This API has a similar signature to the ReviewRequest resource POST API, but instead of actually creating a review request, will return either OK or an error, depending on whether the included diff file parsed correctly. """ local_site = self._get_local_site(local_site_name) path = request.FILES.get('path') parent_diff_path = request.FILES.get('parent_diff_path') try: query = Q(pk=int(repository), local_site=local_site) except ValueError: query = (Q(local_site=local_site) & (Q(path=repository) | Q(mirror_path=repository) | Q(name=repository))) try: repository = Repository.objects.get(query) except Repository.DoesNotExist: return INVALID_REPOSITORY, { 'repository': repository } except Repository.MultipleObjectsReturned: msg = ('Too many repositories matched "%s". ' 'Try specifying the repository by name instead.' % repository) return INVALID_REPOSITORY.with_message(msg), { 'repository': repository, } if (not repository.get_scmtool().diffs_use_absolute_paths and basedir is None): return INVALID_FORM_DATA, { 'fields': { 'basedir': ['Given repository requires a base directory'], }, } if basedir is None: # If we get here, the repository uses absolute paths. Deeper down # (where we don't necessarily know about the details of the # repository), we do an os.path.join() with the basedir value, # which will choke if it's None. basedir = '' try: DiffSet.objects.create_from_upload( repository=repository, diff_file=path, parent_diff_file=parent_diff_path, basedir=basedir, request=request, base_commit_id=base_commit_id, validate_only=True) 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: logging.exception('Unexpected error when validating diff.') return DIFF_PARSE_ERROR.with_message( 'Unexpected error when validating the diff: %s' % e) return 200, {}
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), } }
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), } }