Example #1
0
def view_diff_fragment(request,
                       diffset_id,
                       filediff_id,
                       interdiffset_id=None,
                       chunkindex=None,
                       collapseall=False,
                       template_name='diffviewer/diff_file_fragment.html'):
    diffset = get_object_or_404(DiffSet, pk=diffset_id)
    filediff = get_object_or_404(FileDiff, pk=filediff_id, diffset=diffset)
    interdiffset = get_object_or_none(DiffSet, pk=interdiffset_id)
    highlighting = get_enable_highlighting(request.user)

    try:
        files = get_diff_files(diffset, filediff, interdiffset, highlighting)

        if files:
            assert len(files) == 1
            file = files[0]

            context = {
                'standalone': True,
            }

            return HttpResponse(
                build_diff_fragment(request, file, chunkindex, highlighting,
                                    collapseall, context, template_name))
        raise UserVisibleError(
            _(u"Internal error. Unable to locate file record for filediff %s") % \
            filediff.id)
    except Exception, e:
        return exception_traceback(request, e, template_name,
                                   {'standalone': True})
Example #2
0
    def _get_requested_diff_file(self, diffset, filediff, interdiffset,
                                 interfilediff):
        """Fetches information on the requested diff.

        This will look up information on the diff that's to be rendered
        and return it, if found. It may also augment it with additional
        data.

        The file will not contain chunk information. That must be specifically
        populated later.
        """
        files = get_diff_files(diffset=diffset,
                               interdiffset=interdiffset,
                               filediff=filediff,
                               interfilediff=interfilediff,
                               request=self.request)

        if files:
            file = files[0]

            if 'index' in self.request.GET:
                try:
                    file['index'] = int(self.request.GET.get('index'))
                except ValueError:
                    pass

            return file

        return None
Example #3
0
    def _get_requested_diff_file(self, diffset, filediff, interdiffset):
        """Fetches information on the requested diff.

        This will look up information on the diff that's to be rendered
        and return it, if found. It may also augment it with additional
        data.

        The file will not contain chunk information. That must be specifically
        populated later.
        """
        files = get_diff_files(diffset, filediff, interdiffset, request=self.request)

        if files:
            assert len(files) == 1
            file = files[0]

            if "index" in self.request.GET:
                try:
                    file["index"] = int(self.request.GET.get("index"))
                except ValueError:
                    pass

            return file

        return None
Example #4
0
    def _get_requested_diff_file(self, get_chunks=True):
        """Fetches information on the requested diff.

        This will look up information on the diff that's to be rendered
        and return it, if found. It may also augment it with additional
        data.

        If get_chunks is True, the diff file information will include chunks
        for rendering. Otherwise, it will just contain generic information
        from the database.
        """
        files = get_diff_files(self.diffset,
                               self.filediff,
                               self.interdiffset,
                               request=self.request)

        if get_chunks:
            populate_diff_chunks(files,
                                 self.highlighting,
                                 request=self.request)

        if files:
            assert len(files) == 1
            file = files[0]

            if 'index' in self.request.GET:
                file['index'] = self.request.GET.get('index')

            return file

        return None
Example #5
0
    def _get_requested_diff_file(self, diffset, filediff, interdiffset,
                                 interfilediff, base_filediff):
        """Fetches information on the requested diff.

        This will look up information on the diff that's to be rendered
        and return it, if found. It may also augment it with additional
        data.

        The file will not contain chunk information. That must be specifically
        populated later.
        """
        files = get_diff_files(diffset=diffset,
                               interdiffset=interdiffset,
                               filediff=filediff,
                               interfilediff=interfilediff,
                               base_filediff=base_filediff,
                               request=self.request)

        if files:
            diff_file = files[0]

            try:
                diff_file['index'] = int(self.request.GET['index'])
            except (KeyError, ValueError):
                pass

            return diff_file

        return None
Example #6
0
    def _get_requested_diff_file(self, get_chunks=True):
        """Fetches information on the requested diff.

        This will look up information on the diff that's to be rendered
        and return it, if found. It may also augment it with additional
        data.

        If get_chunks is True, the diff file information will include chunks
        for rendering. Otherwise, it will just contain generic information
        from the database.
        """
        files = get_diff_files(self.diffset, self.filediff, self.interdiffset,
                               request=self.request)

        if get_chunks:
            populate_diff_chunks(files, self.highlighting,
                                 request=self.request)

        if files:
            assert len(files) == 1
            file = files[0]

            if 'index' in self.request.GET:
                file['index'] = self.request.GET.get('index')

            return file

        return None
Example #7
0
def view_diff_fragment(request, diffset_id, filediff_id, interdiffset_id=None,
                       chunkindex=None, collapseall=False,
                       template_name='diffviewer/diff_file_fragment.html'):
    diffset = get_object_or_404(DiffSet, pk=diffset_id)
    filediff = get_object_or_404(FileDiff, pk=filediff_id, diffset=diffset)
    interdiffset = get_object_or_none(DiffSet, pk=interdiffset_id)
    highlighting = get_enable_highlighting(request.user)

    try:
        files = get_diff_files(diffset, filediff, interdiffset, highlighting)

        if files:
            assert len(files) == 1
            file = files[0]

            context = {
                'standalone': True,
            }

            return HttpResponse(build_diff_fragment(request, file,
                                                    chunkindex,
                                                    highlighting, collapseall,
                                                    context, template_name))
        raise UserVisibleError(
            _(u"Internal error. Unable to locate file record for filediff %s") % \
            filediff.id)
    except Exception, e:
        return exception_traceback(request, e, template_name,
                                   {'standalone': True})
Example #8
0
    def get_context_data(self,
                         diffset,
                         interdiffset,
                         extra_context={},
                         **kwargs):
        """Calculates and returns data used for rendering the diff viewer.

        This handles all the hard work of generating the data backing the
        side-by-side diff, handling pagination, and more. The data is
        collected into a context dictionary and returned for rendering.
        """
        files = get_diff_files(diffset,
                               None,
                               interdiffset,
                               request=self.request)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files, siteconfig.get('diffviewer_paginate_by'),
                              siteconfig.get('diffviewer_paginate_orphans'))

        page_num = int(self.request.GET.get('page', 1))

        if self.request.GET.get('file', False):
            file_id = int(self.request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].pk == file_id:
                    page_num = i // paginator.per_page + 1

                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages

                    break

        page = paginator.page(page_num)

        return dict(
            {
                'diffset': diffset,
                'interdiffset': interdiffset,
                'diffset_pair': (diffset, interdiffset),
                'files': page.object_list,
                'collapseall': self.collapse_diffs,

                # Add the pagination context
                'is_paginated': page.has_other_pages(),
                'page': page.number,
                'pages': paginator.num_pages,
                'page_numbers': paginator.page_range,
                'has_next': page.has_next(),
                'next_page': page.next_page_number(),
                'has_previous': page.has_previous(),
                'previous_page': page.previous_page_number(),
                'page_start_index': page.start_index(),
            },
            **extra_context)
Example #9
0
    def add_urls_from_datagrid(urls, datagrid, view, group=None):
        datagrid.load_state()

        datagrid_params = "view=%s" % view

        if group:
            datagrid_params += "&group=%s" % group

        datagrid_url = "%s%s?%s" % (url_prefix, reverse("dashboard"), datagrid_params)

        urls.append({"url": datagrid_url, "matchQuery": {"hasAll": datagrid_params}})

        highlighting = get_enable_highlighting(request.user)

        for obj_info in datagrid.rows:
            review_request = obj_info["object"]
            assert isinstance(review_request, ReviewRequest)

            if review_request.id in found_review_requests:
                continue

            found_review_requests[review_request.id] = True

            # Grab the latest activity timestamp.
            # TODO: Make this common between here and review_detail.
            timestamp = get_last_activity_timestamp(review_request)

            if not info["latest_timestamp"] or timestamp > info["latest_timestamp"]:
                info["latest_timestamp"] = timestamp

            urls.append({"url": url_prefix + review_request.get_absolute_url()})

            try:
                diffset = review_request.diffset_history.diffsets.latest()

                view_diff_url = url_prefix + reverse("view_diff", args=[review_request.id])

                urls += [{"url": view_diff_url}, {"url": url_prefix + reverse("raw_diff", args=[review_request.id])}]

                files = get_diff_files(diffset, None, None, highlighting, False)

                # Break the list of files into pages
                siteconfig = SiteConfiguration.objects.get_current()
                paginator = Paginator(
                    files, siteconfig.get("diffviewer_paginate_by"), siteconfig.get("diffviewer_paginate_orphans")
                )

                for pagenum in paginator.page_range:
                    urls.append({"url": "%s?page=%d" % (view_diff_url, pagenum)})
            except DiffSet.DoesNotExist:
                pass

            for screenshot in review_request.screenshots.all():
                urls += [
                    {"url": url_prefix + screenshot.get_absolute_url()},
                    {"url": url_prefix + screenshot.image.url},
                    {"url": url_prefix + screenshot.get_thumbnail_url()},
                ]
Example #10
0
    def get_context_data(self, diffset, interdiffset, extra_context={},
                         **kwargs):
        """Calculates and returns data used for rendering the diff viewer.

        This handles all the hard work of generating the data backing the
        side-by-side diff, handling pagination, and more. The data is
        collected into a context dictionary and returned for rendering.
        """
        files = get_diff_files(diffset, None, interdiffset,
                               request=self.request)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files,
                              siteconfig.get('diffviewer_paginate_by'),
                              siteconfig.get('diffviewer_paginate_orphans'))

        page_num = int(self.request.GET.get('page', 1))

        if self.request.GET.get('file', False):
            file_id = int(self.request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].pk == file_id:
                    page_num = i // paginator.per_page + 1

                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages

                    break

        page = paginator.page(page_num)

        return dict({
            'diffset': diffset,
            'interdiffset': interdiffset,
            'diffset_pair': (diffset, interdiffset),
            'files': page.object_list,
            'collapseall': self.collapse_diffs,

            # Add the pagination context
            'is_paginated': page.has_other_pages(),
            'page': page.number,
            'pages': paginator.num_pages,
            'page_numbers': paginator.page_range,
            'has_next': page.has_next(),
            'next_page': page.next_page_number(),
            'has_previous': page.has_previous(),
            'previous_page': page.previous_page_number(),
            'page_start_index': page.start_index(),
        }, **extra_context)
Example #11
0
    def get_requested_diff_file(get_chunks=True):
        files = get_diff_files(diffset, filediff, interdiffset, highlighting, get_chunks)

        if files:
            assert len(files) == 1
            file = files[0]

            if "index" in request.GET:
                file["index"] = request.GET.get("index")

            return file

        return None
Example #12
0
    def get_requested_diff_file(get_chunks=True):
        files = get_diff_files(diffset, filediff, interdiffset, highlighting,
                               get_chunks)

        if files:
            assert len(files) == 1
            file = files[0]

            if 'index' in request.GET:
                file['index'] = request.GET.get('index')

            return file

        return None
Example #13
0
    def _get_requested_diff_file(self, diffset, filediff, interdiffset,
                                 interfilediff):
        """Fetches information on the requested diff.

        This will look up information on the diff that's to be rendered
        and return it, if found. It may also augment it with additional
        data.

        The file will not contain chunk information. That must be specifically
        populated later.
        """
        base_commit_id = None
        base_commit = None

        if diffset.commit_count > 0 and not interdiffset:
            raw_base_commit_id = self.request.GET.get('base-commit-id')

            if raw_base_commit_id is not None:
                try:
                    base_commit_id = int(raw_base_commit_id)
                except ValueError:
                    pass

            base_commit, tip_commit = get_base_and_tip_commits(
                base_commit_id=base_commit_id,
                tip_commit_id=None,
                diffset=diffset)

        # The tip commit is not required since we are requesting get_diff_files
        # with a FileDiff.
        files = get_diff_files(diffset=diffset,
                               interdiffset=interdiffset,
                               filediff=filediff,
                               interfilediff=interfilediff,
                               request=self.request,
                               base_commit=base_commit)

        if files:
            diff_file = files[0]

            try:
                diff_file['index'] = int(self.request.GET['index'])
            except (KeyError, ValueError):
                pass

            return diff_file

        return None
Example #14
0
    def get_requested_diff_file(get_chunks=True):
        files = get_diff_files(diffset, filediff, interdiffset)

        if get_chunks:
            populate_diff_chunks(files, highlighting)

        if files:
            assert len(files) == 1
            file = files[0]

            if 'index' in request.GET:
                file['index'] = request.GET.get('index')

            return file

        return None
Example #15
0
    def _get_diff_data(self, request, mimetype, *args, **kwargs):
        try:
            resources.review_request.get_object(request, *args, **kwargs)
            filediff = self.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        highlighting = request.GET.get('syntax-highlighting', False)

        files = get_diff_files(diffset=filediff.diffset,
                               filediff=filediff,
                               request=request)
        populate_diff_chunks(files, highlighting, request=request)

        if not files:
            # This may not be the right error here.
            return DOES_NOT_EXIST

        assert len(files) == 1
        f = files[0]

        payload = {
            'diff_data': {
                'binary': f['binary'],
                'chunks': f['chunks'],
                'num_changes': f['num_changes'],
                'changed_chunk_indexes': f['changed_chunk_indexes'],
                'new_file': f['newfile'],
            }
        }

        # XXX: Kind of a hack.
        api_format = mimetype.split('+')[-1]

        resp = WebAPIResponse(request, payload, api_format=api_format)
        set_last_modified(resp, filediff.diffset.timestamp)

        return resp
Example #16
0
    def _get_diff_data(self, request, mimetype, *args, **kwargs):
        try:
            resources.review_request.get_object(request, *args, **kwargs)
            filediff = self.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        highlighting = request.GET.get('syntax-highlighting', False)

        files = get_diff_files(diffset=filediff.diffset,
                               filediff=filediff,
                               request=request)
        populate_diff_chunks(files, highlighting, request=request)

        if not files:
            # This may not be the right error here.
            return DOES_NOT_EXIST

        assert len(files) == 1
        f = files[0]

        payload = {
            'diff_data': {
                'binary': f['binary'],
                'chunks': f['chunks'],
                'num_changes': f['num_changes'],
                'changed_chunk_indexes': f['changed_chunk_indexes'],
                'new_file': f['newfile'],
            }
        }

        # XXX: Kind of a hack.
        api_format = mimetype.split('+')[-1]

        resp = WebAPIResponse(request, payload, api_format=api_format)
        set_last_modified(resp, filediff.diffset.timestamp)

        return resp
Example #17
0
def view_diff(request, diffset_id, interdiffset_id=None, extra_context={},
              template_name='diffviewer/view_diff.html'):

    #import dbgp.client
    #dbgp.client.brk(port=9004)
    
    diffset = get_object_or_404(DiffSet, pk=diffset_id)
    interdiffset = get_object_or_none(DiffSet, pk=interdiffset_id)
    highlighting = get_enable_highlighting(request.user)

    try:
        if interdiffset_id:
            logging.debug("Generating diff viewer page for interdiffset ids "
                          "%s-%s",
                          diffset_id, interdiffset_id)
        else:
            logging.debug("Generating diff viewer page for filediff id %s",
                          diffset_id)

        files = get_diff_files(diffset, None, interdiffset, highlighting)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files,
                              siteconfig.get("diffviewer_paginate_by"),
                              siteconfig.get("diffviewer_paginate_orphans"))

        page_num = int(request.GET.get('page', 1))

        if request.GET.get('file', False):
            file_id = int(request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].id == file_id:
                    page_num = i // paginator.per_page + 1
                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages
                    break

        page = paginator.page(page_num)

        if request.GET.get('expand', False):
            collapseall = False
        elif request.GET.get('collapse', False):
            collapseall = True
        elif request.COOKIES.has_key('collapsediffs'):
            collapseall = (request.COOKIES['collapsediffs'] == "True")
        else:
            collapseall = True

        context = {
            'diffset': diffset,
            'interdiffset': interdiffset,
            'diffset_pair': (diffset, interdiffset),
        }
        context.update(extra_context)

        # XXX We can probably make this even more awesome and completely skip
        #     the get_diff_files call, caching basically the entire context.
        for file in page.object_list:
            file['fragment'] = mark_safe(build_diff_fragment(request,
                                                             file, None,
                                                             highlighting,
                                                             collapseall,
                                                             context))

        context['files'] = page.object_list

        # Add the pagination context
        context['is_paginated'] = page.has_other_pages()
        context['page'] = page.number
        context['pages'] = paginator.num_pages
        context['page_numbers'] = paginator.page_range
        context['has_next'] = page.has_next()
        context['next_page'] = page.next_page_number()
        context['has_previous'] = page.has_previous()
        context['previous_page'] = page.previous_page_number()
        context['page_start_index'] = page.start_index()

        response = render_to_response(template_name,
                                      RequestContext(request, context))
        response.set_cookie('collapsediffs', collapseall)

        if interdiffset_id:
            logging.debug("Done generating diff viewer page for interdiffset "
                          "ids %s-%s",
                          diffset_id, interdiffset_id)
        else:
            logging.debug("Done generating diff viewer page for filediff "
                          "id %s",
                          diffset_id)

        return response

    except Exception, e:
        return exception_traceback(request, e, template_name)
Example #18
0
    def get_context_data(self,
                         diffset,
                         interdiffset,
                         extra_context={},
                         **kwargs):
        """Calculates and returns data used for rendering the diff viewer.

        This handles all the hard work of generating the data backing the
        side-by-side diff, handling pagination, and more. The data is
        collected into a context dictionary and returned for rendering.
        """
        try:
            filename_patterns = \
                re.split(',+\s*', self.request.GET['filenames'].strip())
        except KeyError:
            filename_patterns = []

        files = get_diff_files(diffset=diffset,
                               interdiffset=interdiffset,
                               request=self.request,
                               filename_patterns=filename_patterns)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files, siteconfig.get('diffviewer_paginate_by'),
                              siteconfig.get('diffviewer_paginate_orphans'))

        page_num = int(self.request.GET.get('page', 1))

        if self.request.GET.get('file', False):
            file_id = int(self.request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].pk == file_id:
                    page_num = i // paginator.per_page + 1

                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages

                    break

        try:
            page = paginator.page(page_num)
        except InvalidPage:
            page = paginator.page(paginator.num_pages)

        diff_context = {
            'filename_patterns': list(filename_patterns),
            'revision': {
                'revision':
                diffset.revision,
                'is_interdiff':
                interdiffset is not None,
                'interdiff_revision':
                (interdiffset.revision if interdiffset else None),
            },
            'pagination': {
                'is_paginated': page.has_other_pages(),
                'current_page': page.number,
                'pages': paginator.num_pages,
                'page_numbers': paginator.page_range,
                'has_next': page.has_next(),
                'has_previous': page.has_previous(),
            },
        }

        if page.has_next():
            diff_context['pagination']['next_page'] = page.next_page_number()

        if page.has_previous():
            diff_context['pagination']['previous_page'] = \
                page.previous_page_number()

        context = dict(
            {
                'diff_context': diff_context,
                'diffset': diffset,
                'interdiffset': interdiffset,
                'diffset_pair': (diffset, interdiffset),
                'files': page.object_list,
                'collapseall': self.collapse_diffs,
            }, **extra_context)

        return context
Example #19
0
def view_diff(request, diffset_id, interdiffset_id=None, extra_context={}, template_name="diffviewer/view_diff.html"):
    diffset = get_object_or_404(DiffSet, pk=diffset_id)
    interdiffset = get_object_or_none(DiffSet, pk=interdiffset_id)
    highlighting = get_enable_highlighting(request.user)

    try:
        if interdiffset_id:
            logging.debug("Generating diff viewer page for interdiffset ids " "%s-%s", diffset_id, interdiffset_id)
        else:
            logging.debug("Generating diff viewer page for filediff id %s", diffset_id)

        files = get_diff_files(diffset, None, interdiffset, highlighting, False)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(
            files, siteconfig.get("diffviewer_paginate_by"), siteconfig.get("diffviewer_paginate_orphans")
        )

        page_num = int(request.GET.get("page", 1))

        if request.GET.get("file", False):
            file_id = int(request.GET["file"])

            for i, f in enumerate(files):
                if f["filediff"].id == file_id:
                    page_num = i // paginator.per_page + 1
                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages
                    break

        page = paginator.page(page_num)

        collapse_diffs = get_collapse_diff(request)

        context = {
            "diffset": diffset,
            "interdiffset": interdiffset,
            "diffset_pair": (diffset, interdiffset),
            "files": page.object_list,
            "collapseall": collapse_diffs,
            # Add the pagination context
            "is_paginated": page.has_other_pages(),
            "page": page.number,
            "pages": paginator.num_pages,
            "page_numbers": paginator.page_range,
            "has_next": page.has_next(),
            "next_page": page.next_page_number(),
            "has_previous": page.has_previous(),
            "previous_page": page.previous_page_number(),
            "page_start_index": page.start_index(),
        }
        context.update(extra_context)

        # Attempt to preload the first file before rendering any part of
        # the page. This helps to remove the perception that the diff viewer
        # takes longer to load now that we have progressive diffs. Users were
        # seeing the page itself load quickly, but didn't see that first
        # diff immediately and instead saw a spinner, making them feel it was
        # taking longer than it used to to load a page. We just trick the
        # user by providing that first file.
        if page.object_list:
            first_file = page.object_list[0]
        else:
            first_file = None

        if first_file:
            filediff = first_file["filediff"]

            if filediff.diffset == interdiffset:
                temp_files = get_diff_files(interdiffset, filediff, None, highlighting, True)
            else:
                temp_files = get_diff_files(diffset, filediff, interdiffset, highlighting, True)

            if temp_files:
                file_temp = temp_files[0]
                file_temp["index"] = first_file["index"]
                first_file["fragment"] = build_diff_fragment(
                    request,
                    file_temp,
                    None,
                    highlighting,
                    collapse_diffs,
                    context,
                    "diffviewer/diff_file_fragment.html",
                )

        response = render_to_response(template_name, RequestContext(request, context))
        response.set_cookie("collapsediffs", collapse_diffs)

        if interdiffset_id:
            logging.debug("Done generating diff viewer page for interdiffset " "ids %s-%s", diffset_id, interdiffset_id)
        else:
            logging.debug("Done generating diff viewer page for filediff " "id %s", diffset_id)

        return response

    except Exception, e:
        return exception_traceback(request, e, template_name)
Example #20
0
    def get_context_data(self, diffset, interdiffset, extra_context={},
                         **kwargs):
        """Calculates and returns data used for rendering the diff viewer.

        This handles all the hard work of generating the data backing the
        side-by-side diff, handling pagination, and more. The data is
        collected into a context dictionary and returned for rendering.
        """
        try:
            filename_patterns = \
                re.split(',+\s*', self.request.GET['filenames'].strip())
        except KeyError:
            filename_patterns = []

        files = get_diff_files(diffset=diffset,
                               interdiffset=interdiffset,
                               request=self.request,
                               filename_patterns=filename_patterns)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files,
                              siteconfig.get('diffviewer_paginate_by'),
                              siteconfig.get('diffviewer_paginate_orphans'))

        page_num = int(self.request.GET.get('page', 1))

        if self.request.GET.get('file', False):
            file_id = int(self.request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].pk == file_id:
                    page_num = i // paginator.per_page + 1

                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages

                    break

        try:
            page = paginator.page(page_num)
        except InvalidPage:
            page = paginator.page(paginator.num_pages)

        diff_context = {
            'filename_patterns': list(filename_patterns),
            'revision': {
                'revision': diffset.revision,
                'is_interdiff': interdiffset is not None,
                'interdiff_revision': (interdiffset.revision
                                       if interdiffset else None),
            },
            'pagination': {
                'is_paginated': page.has_other_pages(),
                'current_page': page.number,
                'pages': paginator.num_pages,
                'page_numbers': paginator.page_range,
                'has_next': page.has_next(),
                'has_previous': page.has_previous(),
            },
        }

        if page.has_next():
            diff_context['pagination']['next_page'] = page.next_page_number()

        if page.has_previous():
            diff_context['pagination']['previous_page'] = \
                page.previous_page_number()

        context = dict({
            'diff_context': diff_context,
            'diffset': diffset,
            'interdiffset': interdiffset,
            'diffset_pair': (diffset, interdiffset),
            'files': page.object_list,
            'collapseall': self.collapse_diffs,
        }, **extra_context)

        return context
Example #21
0
    def get_context_data(self, diffset, interdiffset, extra_context={},
                         **kwargs):
        """Calculates and returns data used for rendering the diff viewer.

        This handles all the hard work of generating the data backing the
        side-by-side diff, handling pagination, and more. The data is
        collected into a context dictionary and returned for rendering.
        """
        try:
            filename_patterns = \
                re.split(',+\s*', self.request.GET['filenames'].strip())
        except KeyError:
            filename_patterns = []

        base_commit_id = None
        base_commit = None

        tip_commit_id = None
        tip_commit = None

        commits_by_diffset_id = {}

        if diffset.commit_count > 0:
            diffset_pks = [diffset.pk]

            if interdiffset:
                diffset_pks.append(interdiffset.pk)

            commits = DiffCommit.objects.filter(diffset_id__in=diffset_pks)

            for commit in commits:
                commits_by_diffset_id.setdefault(commit.diffset_id, []).append(
                    commit)

            # Base and tip commit selection is not supported in interdiffs.
            if not interdiffset:
                raw_base_commit_id = self.request.GET.get('base-commit-id')
                raw_tip_commit_id = self.request.GET.get('tip-commit-id')

                if raw_base_commit_id is not None:
                    try:
                        base_commit_id = int(raw_base_commit_id)
                    except ValueError:
                        pass

                if raw_tip_commit_id is not None:
                    try:
                        tip_commit_id = int(raw_tip_commit_id)
                    except ValueError:
                        pass

                base_commit, tip_commit = get_base_and_tip_commits(
                    base_commit_id,
                    tip_commit_id,
                    commits=commits_by_diffset_id[diffset.pk])

        files = get_diff_files(diffset=diffset,
                               interdiffset=interdiffset,
                               request=self.request,
                               filename_patterns=filename_patterns,
                               base_commit=base_commit,
                               tip_commit=tip_commit)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files,
                              siteconfig.get('diffviewer_paginate_by'),
                              siteconfig.get('diffviewer_paginate_orphans'))

        page_num = int(self.request.GET.get('page', 1))

        if self.request.GET.get('file', False):
            file_id = int(self.request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].pk == file_id:
                    page_num = i // paginator.per_page + 1

                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages

                    break

        try:
            page = paginator.page(page_num)
        except InvalidPage:
            page = paginator.page(paginator.num_pages)

        diff_context = {
            'commits': None,
            'commit_history_diff': None,
            'filename_patterns': list(filename_patterns),
            'revision': {
                'revision': diffset.revision,
                'is_interdiff': interdiffset is not None,
                'interdiff_revision': (interdiffset.revision
                                       if interdiffset else None),
            },
            'pagination': {
                'is_paginated': page.has_other_pages(),
                'current_page': page.number,
                'pages': paginator.num_pages,
                'page_numbers': paginator.page_range,
                'has_next': page.has_next(),
                'has_previous': page.has_previous(),
            },
        }

        if page.has_next():
            diff_context['pagination']['next_page'] = page.next_page_number()

        if page.has_previous():
            diff_context['pagination']['previous_page'] = \
                page.previous_page_number()

        if diffset.commit_count > 0:
            if interdiffset:
                diff_context['commit_history_diff'] = [
                    entry.serialize()
                    for entry in diff_histories(
                        commits_by_diffset_id[diffset.pk],
                        commits_by_diffset_id[interdiffset.pk])
                ]

            all_commits = [
                commit
                for pk in commits_by_diffset_id
                for commit in commits_by_diffset_id[pk]
            ]

            diff_context['commits'] = [
                commit.serialize()
                for commit in sorted(all_commits,
                                     key=lambda commit: commit.pk)
            ]

            revision_context = diff_context['revision']

            revision_context.update({
                'base_commit_id': base_commit_id,
                'tip_commit_id': tip_commit_id,
            })

        context = dict({
            'diff_context': diff_context,
            'diffset': diffset,
            'interdiffset': interdiffset,
            'diffset_pair': (diffset, interdiffset),
            'files': page.object_list,
            'collapseall': self.collapse_diffs,
        }, **extra_context)

        return context
Example #22
0
def get_file_chunks_in_range_custom(context, filediff, interfilediff,
                                    first_line, num_lines):
    """
    A generator that yields chunks within a range of lines in the specified
    filediff/interfilediff.

    This function was mostly copied from the Review Board source code. The
    main modification is to always set syntax highlighting to False so that
    plain code is returned in the chunks instead of html.

    This is primarily intended for use with templates. It takes a
    RequestContext for looking up the user and for caching file lists,
    in order to improve performance and reduce lookup times for files that have
    already been fetched.

    Each returned chunk is a dictionary with the following fields:

      ============= ========================================================
      Variable      Description
      ============= ========================================================
      ``change``    The change type ("equal", "replace", "insert", "delete")
      ``numlines``  The number of lines in the chunk.
      ``lines``     The list of lines in the chunk.
      ``meta``      A dictionary containing metadata on the chunk
      ============= ========================================================


    Each line in the list of lines is an array with the following data:

      ======== =============================================================
      Index    Description
      ======== =============================================================
      0        Virtual line number (union of the original and patched files)
      1        Real line number in the original file
      2        HTML markup of the original file
      3        Changed regions of the original line (for "replace" chunks)
      4        Real line number in the patched file
      5        HTML markup of the patched file
      6        Changed regions of the patched line (for "replace" chunks)
      7        True if line consists of only whitespace changes
      ======== =============================================================
    """
    def find_header(headers):
        for header in reversed(headers):
            if header[0] < first_line:
                return {
                    'line': header[0],
                    'text': header[1],
                }

    interdiffset = None

    key = "_diff_files_%s_%s" % (filediff.diffset.id, filediff.id)

    if interfilediff:
        key += "_%s" % (interfilediff.id)
        interdiffset = interfilediff.diffset

    if key in context:
        files = context[key]
    else:
        assert 'user' in context

        request = context.get('request', None)
        files = get_diff_files(filediff.diffset, filediff, interdiffset,
                               request=request)
        populate_diff_chunks(files, False,
                             request=request)
        context[key] = files

    if not files:
        raise StopIteration

    assert len(files) == 1
    last_header = [None, None]

    for chunk in files[0]['chunks']:
        if ('headers' in chunk['meta'] and
                (chunk['meta']['headers'][0] or chunk['meta']['headers'][1])):
            last_header = chunk['meta']['headers']

        lines = chunk['lines']

        if lines[-1][0] >= first_line >= lines[0][0]:
            start_index = first_line - lines[0][0]

            if first_line + num_lines <= lines[-1][0]:
                last_index = start_index + num_lines
            else:
                last_index = len(lines)

            new_chunk = {
                'lines': chunk['lines'][start_index:last_index],
                'numlines': last_index - start_index,
                'change': chunk['change'],
                'meta': chunk.get('meta', {}),
            }

            if 'left_headers' in chunk['meta']:
                left_header = find_header(chunk['meta']['left_headers'])
                right_header = find_header(chunk['meta']['right_headers'])
                del new_chunk['meta']['left_headers']
                del new_chunk['meta']['right_headers']

                if left_header or right_header:
                    header = (left_header, right_header)
                else:
                    header = last_header

                new_chunk['meta']['headers'] = header

            yield new_chunk

            first_line += new_chunk['numlines']
            num_lines -= new_chunk['numlines']

            assert num_lines >= 0
            if num_lines == 0:
                break
Example #23
0
    def get_context_data(self, diffset, interdiffset, extra_context={}, **kwargs):
        """Calculates and returns data used for rendering the diff viewer.

        This handles all the hard work of generating the data backing the
        side-by-side diff, handling pagination, and more. The data is
        collected into a context dictionary and returned for rendering.
        """
        files = get_diff_files(diffset, None, interdiffset, request=self.request)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(
            files, siteconfig.get("diffviewer_paginate_by"), siteconfig.get("diffviewer_paginate_orphans")
        )

        page_num = int(self.request.GET.get("page", 1))

        if self.request.GET.get("file", False):
            file_id = int(self.request.GET["file"])

            for i, f in enumerate(files):
                if f["filediff"].pk == file_id:
                    page_num = i // paginator.per_page + 1

                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages

                    break

        try:
            page = paginator.page(page_num)
        except InvalidPage:
            page = paginator.page(paginator.num_pages)

        diff_context = {
            "revision": {
                "revision": diffset.revision,
                "is_interdiff": interdiffset is not None,
                "interdiff_revision": (interdiffset.revision if interdiffset else None),
            },
            "pagination": {
                "is_paginated": page.has_other_pages(),
                "current_page": page.number,
                "pages": paginator.num_pages,
                "page_numbers": paginator.page_range,
                "has_next": page.has_next(),
                "has_previous": page.has_previous(),
            },
        }

        if page.has_next():
            diff_context["pagination"]["next_page"] = page.next_page_number()

        if page.has_previous():
            diff_context["pagination"]["previous_page"] = page.previous_page_number()

        context = dict(
            {
                "diff_context": diff_context,
                "diffset": diffset,
                "interdiffset": interdiffset,
                "diffset_pair": (diffset, interdiffset),
                "files": page.object_list,
                "collapseall": self.collapse_diffs,
            },
            **extra_context
        )

        return context
Example #24
0
def get_file_chunks_in_range_custom(context, filediff, interfilediff,
                                    first_line, num_lines):
    """
    A generator that yields chunks within a range of lines in the specified
    filediff/interfilediff.

    This function was mostly copied from the Review Board source code. The
    main modification is to always set syntax highlighting to False so that
    plain code is returned in the chunks instead of html.

    This is primarily intended for use with templates. It takes a
    RequestContext for looking up the user and for caching file lists,
    in order to improve performance and reduce lookup times for files that have
    already been fetched.

    Each returned chunk is a dictionary with the following fields:

      ============= ========================================================
      Variable      Description
      ============= ========================================================
      ``change``    The change type ("equal", "replace", "insert", "delete")
      ``numlines``  The number of lines in the chunk.
      ``lines``     The list of lines in the chunk.
      ``meta``      A dictionary containing metadata on the chunk
      ============= ========================================================


    Each line in the list of lines is an array with the following data:

      ======== =============================================================
      Index    Description
      ======== =============================================================
      0        Virtual line number (union of the original and patched files)
      1        Real line number in the original file
      2        HTML markup of the original file
      3        Changed regions of the original line (for "replace" chunks)
      4        Real line number in the patched file
      5        HTML markup of the patched file
      6        Changed regions of the patched line (for "replace" chunks)
      7        True if line consists of only whitespace changes
      ======== =============================================================
    """
    def find_header(headers):
        for header in reversed(headers):
            if header[0] < first_line:
                return {
                    'line': header[0],
                    'text': header[1],
                }

    interdiffset = None

    key = "_diff_files_%s_%s" % (filediff.diffset.id, filediff.id)

    if interfilediff:
        key += "_%s" % (interfilediff.id)
        interdiffset = interfilediff.diffset

    if key in context:
        files = context[key]
    else:
        assert 'user' in context

        request = context.get('request', None)
        files = get_diff_files(filediff.diffset,
                               filediff,
                               interdiffset,
                               request=request)
        populate_diff_chunks(files, False, request=request)
        context[key] = files

    if not files:
        raise StopIteration

    assert len(files) == 1
    last_header = [None, None]

    for chunk in files[0]['chunks']:
        if ('headers' in chunk['meta'] and
            (chunk['meta']['headers'][0] or chunk['meta']['headers'][1])):
            last_header = chunk['meta']['headers']

        lines = chunk['lines']

        if lines[-1][0] >= first_line >= lines[0][0]:
            start_index = first_line - lines[0][0]

            if first_line + num_lines <= lines[-1][0]:
                last_index = start_index + num_lines
            else:
                last_index = len(lines)

            new_chunk = {
                'lines': chunk['lines'][start_index:last_index],
                'numlines': last_index - start_index,
                'change': chunk['change'],
                'meta': chunk.get('meta', {}),
            }

            if 'left_headers' in chunk['meta']:
                left_header = find_header(chunk['meta']['left_headers'])
                right_header = find_header(chunk['meta']['right_headers'])
                del new_chunk['meta']['left_headers']
                del new_chunk['meta']['right_headers']

                if left_header or right_header:
                    header = (left_header, right_header)
                else:
                    header = last_header

                new_chunk['meta']['headers'] = header

            yield new_chunk

            first_line += new_chunk['numlines']
            num_lines -= new_chunk['numlines']

            assert num_lines >= 0
            if num_lines == 0:
                break
Example #25
0
def view_diff(request, diffset, interdiffset=None, extra_context={},
              template_name='diffviewer/view_diff.html'):
    highlighting = get_enable_highlighting(request.user)

    try:
        if interdiffset:
            logging.debug("Generating diff viewer page for interdiffset ids "
                          "%s-%s",
                          diffset.id, interdiffset.id, request=request)
        else:
            logging.debug("Generating diff viewer page for filediff id %s",
                          diffset.id, request=request)

        files = get_diff_files(diffset, None, interdiffset, request=request)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files,
                              siteconfig.get("diffviewer_paginate_by"),
                              siteconfig.get("diffviewer_paginate_orphans"))

        page_num = int(request.GET.get('page', 1))

        if request.GET.get('file', False):
            file_id = int(request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].id == file_id:
                    page_num = i // paginator.per_page + 1
                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages
                    break

        page = paginator.page(page_num)

        collapse_diffs = get_collapse_diff(request)

        context = {
            'diffset': diffset,
            'interdiffset': interdiffset,
            'diffset_pair': (diffset, interdiffset),
            'files': page.object_list,
            'collapseall': collapse_diffs,

            # Add the pagination context
            'is_paginated': page.has_other_pages(),
            'page': page.number,
            'pages': paginator.num_pages,
            'page_numbers': paginator.page_range,
            'has_next': page.has_next(),
            'next_page': page.next_page_number(),
            'has_previous': page.has_previous(),
            'previous_page': page.previous_page_number(),
            'page_start_index': page.start_index(),
        }
        context.update(extra_context)

        # Attempt to preload the first file before rendering any part of
        # the page. This helps to remove the perception that the diff viewer
        # takes longer to load now that we have progressive diffs. Users were
        # seeing the page itself load quickly, but didn't see that first
        # diff immediately and instead saw a spinner, making them feel it was
        # taking longer than it used to to load a page. We just trick the
        # user by providing that first file.
        if page.object_list:
            first_file = page.object_list[0]
        else:
            first_file = None

        if first_file:
            filediff = first_file['filediff']

            if filediff.diffset == interdiffset:
                temp_files = get_diff_files(interdiffset, filediff, None,
                                            request=request)
            else:
                temp_files = get_diff_files(diffset, filediff, interdiffset,
                                            request=request)

            if temp_files:
                try:
                    populate_diff_chunks(temp_files, highlighting,
                                         request=request)
                except Exception, e:
                    file_temp = temp_files[0]
                    file_temp['index'] = first_file['index']
                    first_file['fragment'] = \
                        exception_traceback(request, e,
                                            'diffviewer/diff_fragment_error.html',
                                            extra_context={'file': file_temp})
                else:
                    file_temp = temp_files[0]
                    file_temp['index'] = first_file['index']
                    first_file['fragment'] = build_diff_fragment(
                        request, file_temp, None, highlighting,
                        collapse_diffs, None,
                        context=context,
                        template_name='diffviewer/diff_file_fragment.html')

        response = render_to_response(template_name,
                                      RequestContext(request, context))
        response.set_cookie('collapsediffs', collapse_diffs)

        if interdiffset:
            logging.debug("Done generating diff viewer page for interdiffset "
                          "ids %s-%s",
                          diffset.id, interdiffset.id, request=request)
        else:
            logging.debug("Done generating diff viewer page for filediff "
                          "id %s",
                          diffset.id, request=request)

        return response
Example #26
0
def view_diff(request,
              diffset_id,
              interdiffset_id=None,
              extra_context={},
              template_name='diffviewer/view_diff.html'):

    #import dbgp.client
    #dbgp.client.brk(port=9004)

    diffset = get_object_or_404(DiffSet, pk=diffset_id)
    interdiffset = get_object_or_none(DiffSet, pk=interdiffset_id)
    highlighting = get_enable_highlighting(request.user)

    try:
        if interdiffset_id:
            logging.debug(
                "Generating diff viewer page for interdiffset ids "
                "%s-%s", diffset_id, interdiffset_id)
        else:
            logging.debug("Generating diff viewer page for filediff id %s",
                          diffset_id)

        files = get_diff_files(diffset, None, interdiffset, highlighting)

        # Break the list of files into pages
        siteconfig = SiteConfiguration.objects.get_current()

        paginator = Paginator(files, siteconfig.get("diffviewer_paginate_by"),
                              siteconfig.get("diffviewer_paginate_orphans"))

        page_num = int(request.GET.get('page', 1))

        if request.GET.get('file', False):
            file_id = int(request.GET['file'])

            for i, f in enumerate(files):
                if f['filediff'].id == file_id:
                    page_num = i // paginator.per_page + 1
                    if page_num > paginator.num_pages:
                        page_num = paginator.num_pages
                    break

        page = paginator.page(page_num)

        if request.GET.get('expand', False):
            collapseall = False
        elif request.GET.get('collapse', False):
            collapseall = True
        elif request.COOKIES.has_key('collapsediffs'):
            collapseall = (request.COOKIES['collapsediffs'] == "True")
        else:
            collapseall = True

        context = {
            'diffset': diffset,
            'interdiffset': interdiffset,
            'diffset_pair': (diffset, interdiffset),
        }
        context.update(extra_context)

        # XXX We can probably make this even more awesome and completely skip
        #     the get_diff_files call, caching basically the entire context.
        for file in page.object_list:
            file['fragment'] = mark_safe(
                build_diff_fragment(request, file, None, highlighting,
                                    collapseall, context))

        context['files'] = page.object_list

        # Add the pagination context
        context['is_paginated'] = page.has_other_pages()
        context['page'] = page.number
        context['pages'] = paginator.num_pages
        context['page_numbers'] = paginator.page_range
        context['has_next'] = page.has_next()
        context['next_page'] = page.next_page_number()
        context['has_previous'] = page.has_previous()
        context['previous_page'] = page.previous_page_number()
        context['page_start_index'] = page.start_index()

        response = render_to_response(template_name,
                                      RequestContext(request, context))
        response.set_cookie('collapsediffs', collapseall)

        if interdiffset_id:
            logging.debug(
                "Done generating diff viewer page for interdiffset "
                "ids %s-%s", diffset_id, interdiffset_id)
        else:
            logging.debug(
                "Done generating diff viewer page for filediff "
                "id %s", diffset_id)

        return response

    except Exception, e:
        return exception_traceback(request, e, template_name)