コード例 #1
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
コード例 #2
0
ファイル: views.py プロジェクト: klpyang/reviewboard
    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
コード例 #3
0
ファイル: views.py プロジェクト: michivious/reviewboard
    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
コード例 #4
0
ファイル: filediff.py プロジェクト: darmhoo/reviewboard
    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
コード例 #5
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
コード例 #6
0
    def render_to_string_uncached(self, request):
        """Renders a diff to a string without caching.

        This is a potentially expensive operation, and so is meant to be called
        only as often as necessary. render_to_string will call this if it's
        not already in the cache.
        """
        if not self.diff_file.get('chunks_loaded', False):
            populate_diff_chunks([self.diff_file],
                                 self.highlighting,
                                 request=request)

        if self.chunk_index is not None:
            assert not self.lines_of_context or self.collapse_all

            self.num_chunks = len(self.diff_file['chunks'])

            if self.chunk_index < 0 or self.chunk_index >= self.num_chunks:
                raise UserVisibleError(
                    _('Invalid chunk index %s specified.') % self.chunk_index)

        return render_to_string(template_name=self.template_name,
                                context=self.make_context())
コード例 #7
0
ファイル: renderers.py プロジェクト: Hackthings/reviewboard
    def render_to_string_uncached(self, request):
        """Renders a diff to a string without caching.

        This is a potentially expensive operation, and so is meant to be called
        only as often as necessary. render_to_string will call this if it's
        not already in the cache.
        """
        if not self.diff_file.get('chunks_loaded', False):
            populate_diff_chunks([self.diff_file], self.highlighting,
                                 request=request)

        if self.chunk_index is not None:
            assert not self.lines_of_context or self.collapse_all

            self.num_chunks = len(self.diff_file['chunks'])

            if self.chunk_index < 0 or self.chunk_index >= self.num_chunks:
                raise UserVisibleError(
                    _('Invalid chunk index %s specified.')
                    % self.chunk_index)

        return render_to_string(self.template_name,
                                Context(self.make_context()))
コード例 #8
0
ファイル: views.py プロジェクト: B-Rich/reviewboard
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
コード例 #9
0
ファイル: diffs.py プロジェクト: thomcc/version-control-tools
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
コード例 #10
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