Beispiel #1
0
    def get_draft(self, user=None):
        """
        Returns the draft of the review request. If a user is specified,
        than the draft will be returned only if owned by the user. Otherwise,
        None will be returned.
        """
        if not user:
            return get_object_or_none(self.draft)
        elif user.is_authenticated():
            return get_object_or_none(self.draft, review_request__submitter=user)

        return None
Beispiel #2
0
def submitter(request,
              username,
              template_name='reviews/datagrid.html',
              local_site_name=None):
    """
    A list of review requests owned by a particular user.
    """
    local_site = get_object_or_none(LocalSite, name=local_site_name)
    if local_site_name and not local_site:
        raise Http404

    # Make sure the user exists
    if local_site:
        if not local_site.users.filter(username=username).exists():
            raise Http404
    else:
        get_object_or_404(User, username=username)

    datagrid = ReviewRequestDataGrid(request,
        ReviewRequest.objects.from_user(username, status=None,
                                        with_counts=True,
                                        local_site=local_site),
        _("%s's review requests") % username,
        local_site=local_site)

    return datagrid.render_to_response(template_name)
Beispiel #3
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})
Beispiel #4
0
def dashboard(request,
              template_name='reviews/dashboard.html',
              local_site_name=None):
    """
    The dashboard view, showing review requests organized by a variety of
    lists, depending on the 'view' parameter.

    Valid 'view' parameters are:

        * 'outgoing'
        * 'to-me'
        * 'to-group'
        * 'starred'
        * 'watched-groups'
        * 'incoming'
        * 'mine'
    """
    view = request.GET.get('view', None)

    local_site = get_object_or_none(LocalSite, name=local_site_name)

    if view == "watched-groups":
        # This is special. We want to return a list of groups, not
        # review requests.
        grid = WatchedGroupDataGrid(request, local_site=local_site)
    else:
        grid = DashboardDataGrid(request, local_site=local_site)

    user = request.user
    profile = user.get_profile()

    return grid.render_to_response(template_name)
Beispiel #5
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})
Beispiel #6
0
def file_attachment_comments(context, file_attachment):
    """Returns a JSON array of current comments for a file attachment."""
    comments = []
    user = context.get('user', None)

    for comment in file_attachment.comments.all():
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            comments.append({
                'comment_id': comment.id,
                'text': comment.text,
                'user': {
                    'username': review.user.username,
                    'name': review.user.get_full_name() or review.user.username,
                },
                'url': comment.get_review_url(),
                'localdraft': review.user == user and not review.public,
                'review_id': review.id,
                'review_request_id': review.review_request.id,
                'issue_opened': comment.issue_opened,
                'issue_status': BaseComment
                                .issue_status_to_string(comment
                                                        .issue_status),
            })

    return simplejson.dumps(comments)
Beispiel #7
0
def file_attachment_comments(context, file_attachment):
    """Returns a JSON array of current comments for a file attachment."""
    comments = []
    user = context.get('user', None)

    for comment in file_attachment.comments.all():
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            comments.append({
                'comment_id': comment.id,
                'text': escape(comment.text),
                'user': {
                    'username': review.user.username,
                    'name': review.user.get_full_name() or review.user.username,
                },
                'url': comment.get_review_url(),
                'localdraft': review.user == user and not review.public,
                'review_id': review.id,
                'review_request_id': review.review_request.id,
                'issue_opened': comment.issue_opened,
                'issue_status': BaseComment
                                .issue_status_to_string(comment
                                                        .issue_status),
            })

    return simplejson.dumps(comments)
Beispiel #8
0
def render_star(user, obj):
    """
    Does the actual work of rendering the star. The star tag is a wrapper
    around this.
    """
    if user.is_anonymous():
        return ""

    try:
        profile = user.get_profile()
    except Profile.DoesNotExist:
        return ""

    if isinstance(obj, ReviewRequest):
        obj_info = {
            'type': 'reviewrequests',
            'id': obj.id
        }

        starred = bool(get_object_or_none(profile.starred_review_requests,
                                          pk=obj.id))
    elif isinstance(obj, Group):
        obj_info = {
            'type': 'groups',
            'id': obj.name
        }

        starred = bool(get_object_or_none(profile.starred_groups,
                                          pk=obj.id))
    else:
        raise template.TemplateSyntaxError, \
            "star tag received an incompatible object type (%s)" % \
            type(obj)

    if starred:
        image_alt = _("Starred")
    else:
        image_alt = _("Click to star")

    return render_to_string('reviews/star.html', {
        'object': obj_info,
        'starred': int(starred),
        'alt': image_alt,
        'user': user,
        'MEDIA_URL': settings.MEDIA_URL,
    })
Beispiel #9
0
    def get_pending_reply(self, user):
        """
        Returns the pending reply to this review owned by the specified
        user, if any.
        """
        if user.is_authenticated():
            return get_object_or_none(Review, user=user, public=False, base_reply_to=self)

        return None
Beispiel #10
0
def group_list(request,
               local_site_name=None,
               template_name='reviews/datagrid.html'):
    """
    Displays a list of all review groups.
    """
    grid = GroupDataGrid(
        request, local_site=get_object_or_none(LocalSite, name=local_site_name))
    return grid.render_to_response(template_name)
Beispiel #11
0
def view_diff_fragment(
        request,
        diffset_id,
        filediff_id,
        base_url,
        interdiffset_id=None,
        chunkindex=None,
        template_name='diffviewer/diff_file_fragment.html',
        error_template_name='diffviewer/diff_fragment_error.html'):
    """View which renders a specific fragment from a diff."""
    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

    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)

    if chunkindex:
        collapseall = False
    else:
        collapseall = get_collapse_diff(request)

    try:
        file = get_requested_diff_file()

        if file:
            context = {
                'standalone': chunkindex is not None,
                'base_url': base_url,
            }

            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,
            error_template_name,
            extra_context={'file': get_requested_diff_file(False)})
Beispiel #12
0
def view_diff_fragment(
    request,
    diffset_id,
    filediff_id,
    base_url,
    interdiffset_id=None,
    chunkindex=None,
    template_name='diffviewer/diff_file_fragment.html',
    error_template_name='diffviewer/diff_fragment_error.html'):
    """View which renders a specific fragment from a diff."""

    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

    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)

    if chunkindex:
        collapseall = False
    else:
        collapseall = get_collapse_diff(request)

    try:
        file = get_requested_diff_file()

        if file:
            context = {
                'standalone': chunkindex is not None,
                'base_url': base_url,
            }

            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, error_template_name,
            extra_context={'file': get_requested_diff_file(False)})
Beispiel #13
0
def screenshotcommentcounts(context, screenshot):
    """
    Returns a JSON array of current comments for a screenshot.

    Each entry in the array has a dictionary containing the following keys:

      ================== ====================================================
      Key                Description
      ================== ====================================================
      text               The text of the comment
      localdraft         True if this is the current user's draft comment
      x                  The X location of the comment's region
      y                  The Y location of the comment's region
      w                  The width of the comment's region
      h                  The height of the comment's region
      review_id          The ID of the review this comment is associated with
      review_request_id  The ID of the review request this comment is
                         associated with
      ================== ====================================================
    """
    comments = {}
    user = context.get('user', None)

    for comment in screenshot.comments.all():
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            position = '%dx%d+%d+%d' % (comment.w, comment.h, \
                                        comment.x, comment.y)

            comments.setdefault(position, []).append({
                'comment_id': comment.id,
                'text': comment.text,
                'user': {
                    'username': review.user.username,
                    'name': review.user.get_full_name() or review.user.username,
                },
                'url': comment.get_review_url(),
                'localdraft' : review.user == user and \
                               not review.public,
                'x' : comment.x,
                'y' : comment.y,
                'w' : comment.w,
                'h' : comment.h,
                'review_id': review.id,
                'review_request_id': review.review_request.id,
                'issue_opened': comment.issue_opened,
                'issue_status': BaseComment
                                .issue_status_to_string(comment
                                                        .issue_status),
            })

    return simplejson.dumps(comments)
Beispiel #14
0
def screenshotcommentcounts(context, screenshot):
    """
    Returns a JSON array of current comments for a screenshot.

    Each entry in the array has a dictionary containing the following keys:

      ================== ====================================================
      Key                Description
      ================== ====================================================
      text               The text of the comment
      localdraft         True if this is the current user's draft comment
      x                  The X location of the comment's region
      y                  The Y location of the comment's region
      w                  The width of the comment's region
      h                  The height of the comment's region
      review_id          The ID of the review this comment is associated with
      review_request_id  The ID of the review request this comment is
                         associated with
      ================== ====================================================
    """
    comments = {}
    user = context.get('user', None)

    for comment in screenshot.comments.all():
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            position = '%dx%d+%d+%d' % (comment.w, comment.h, \
                                        comment.x, comment.y)

            comments.setdefault(position, []).append({
                'comment_id': comment.id,
                'text': escape(comment.text),
                'user': {
                    'username': review.user.username,
                    'name': review.user.get_full_name() or review.user.username,
                },
                'url': comment.get_review_url(),
                'localdraft': review.user == user and not review.public,
                'x': comment.x,
                'y': comment.y,
                'w': comment.w,
                'h': comment.h,
                'review_id': review.id,
                'review_request_id': review.review_request.id,
                'issue_opened': comment.issue_opened,
                'issue_status': BaseComment
                                .issue_status_to_string(comment
                                                        .issue_status),
            })

    return simplejson.dumps(comments)
Beispiel #15
0
def screenshotcommentcounts(context, screenshot):
    """
    Returns a JSON array of current comments for a screenshot.

    Each entry in the array has a dictionary containing the following keys:

      ================== ====================================================
      Key                Description
      ================== ====================================================
      text               The text of the comment
      localdraft         True if this is the current user's draft comment
      x                  The X location of the comment's region
      y                  The Y location of the comment's region
      w                  The width of the comment's region
      h                  The height of the comment's region
      review_id          The ID of the review this comment is associated with
      review_request_id  The ID of the review request this comment is
                         associated with
      ================== ====================================================
    """
    comments = {}
    user = context.get("user", None)

    for comment in screenshot.comments.all():
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            position = "%dx%d+%d+%d" % (comment.w, comment.h, comment.x, comment.y)

            comments.setdefault(position, []).append(
                {
                    "comment_id": comment.id,
                    "text": comment.text,
                    "user": {
                        "username": review.user.username,
                        "name": review.user.get_full_name() or review.user.username,
                    },
                    "url": comment.get_review_url(),
                    "localdraft": review.user == user and not review.public,
                    "x": comment.x,
                    "y": comment.y,
                    "w": comment.w,
                    "h": comment.h,
                    "review_id": review.id,
                    "review_request_id": review.review_request.id,
                    "issue_opened": comment.issue_opened,
                    "issue_status": BaseComment.issue_status_to_string(comment.issue_status),
                }
            )

    return simplejson.dumps(comments)
Beispiel #16
0
def count_review_requests(request, func, api_format='json',
                          local_site_name=None, *args, **kwargs):
    """
    Returns the number of review requests.

    Optional parameters:

      * status: The status of the returned review requests. This defaults
                to "pending".
    """
    local_site = get_object_or_none(LocalSite, name=local_site_name)
    status = string_to_status(request.GET.get('status', 'pending'))
    return WebAPIResponse(request, {
        'count': func(user=request.user, status=status,
                      local_site=local_site, **kwargs).count()
    })
Beispiel #17
0
def all_review_requests(request,
                        local_site_name=None,
                        template_name='reviews/datagrid.html'):
    """
    Displays a list of all review requests.
    """
    local_site = get_object_or_none(LocalSite, name=local_site_name)
    if local_site_name and not local_site:
        raise Http404
    datagrid = ReviewRequestDataGrid(request,
        ReviewRequest.objects.public(request.user,
                                     status=None,
                                     local_site=local_site,
                                     with_counts=True),
        _("All review requests"),
        local_site=local_site)
    return datagrid.render_to_response(template_name)
Beispiel #18
0
def search(request,
           template_name='reviews/search.html',
           local_site_name=None):
    """
    Searches review requests on Review Board based on a query string.
    """
    query = request.GET.get('q', '')
    siteconfig = SiteConfiguration.objects.get_current()

    if not siteconfig.get("search_enable"):
        # FIXME: show something useful
        raise Http404

    if not query:
        # FIXME: I'm not super thrilled with this
        return HttpResponseRedirect(reverse("root"))

    if query.isdigit():
        query_review_request = get_object_or_none(ReviewRequest, pk=query)
        if query_review_request:
            return HttpResponseRedirect(query_review_request.get_absolute_url())

    import lucene
    lv = [int(x) for x in lucene.VERSION.split('.')]
    lucene_is_2x = lv[0] == 2 and lv[1] < 9
    lucene_is_3x = lv[0] == 3 or (lv[0] == 2 and lv[1] == 9)

    # We may have already initialized lucene
    try:
        lucene.initVM(lucene.CLASSPATH)
    except ValueError:
        pass

    index_file = siteconfig.get("search_index_file")
    if lucene_is_2x:
        store = lucene.FSDirectory.getDirectory(index_file, False)
    elif lucene_is_3x:
        store = lucene.FSDirectory.open(lucene.File(index_file))
    else:
        assert False

    try:
        searcher = lucene.IndexSearcher(store)
    except lucene.JavaError, e:
        # FIXME: show a useful error
        raise e
Beispiel #19
0
def search(request,
           template_name='reviews/search.html',
           local_site_name=None):
    """
    Searches review requests on Review Board based on a query string.
    """
    query = request.GET.get('q', '')
    siteconfig = SiteConfiguration.objects.get_current()

    if not siteconfig.get("search_enable"):
        # FIXME: show something useful
        raise Http404

    if not query:
        # FIXME: I'm not super thrilled with this
        return HttpResponseRedirect(reverse("root"))

    if query.isdigit():
        query_review_request = get_object_or_none(ReviewRequest, pk=query)
        if query_review_request:
            return HttpResponseRedirect(query_review_request.get_absolute_url())

    import lucene
    lv = [int(x) for x in lucene.VERSION.split('.')]
    lucene_is_2x = lv[0] == 2 and lv[1] < 9
    lucene_is_3x = lv[0] == 3 or (lv[0] == 2 and lv[1] == 9)

    # We may have already initialized lucene
    try:
        lucene.initVM(lucene.CLASSPATH)
    except ValueError:
        pass

    index_file = siteconfig.get("search_index_file")
    if lucene_is_2x:
        store = lucene.FSDirectory.getDirectory(index_file, False)
    elif lucene_is_3x:
        store = lucene.FSDirectory.open(lucene.File(index_file))
    else:
        assert False

    try:
        searcher = lucene.IndexSearcher(store)
    except lucene.JavaError, e:
        # FIXME: show a useful error
        raise e
Beispiel #20
0
    def publish(self, user):
        """
        Save the current draft attached to this review request. Send out the
        associated email. Returns the review request that was saved.
        """
        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)
        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            changes = draft.publish(self, send_notification=False)
            draft.delete()
        else:
            changes = None

        self.public = True
        self.save()

        review_request_published.send(sender=self.__class__, user=user, review_request=self, changedesc=changes)
Beispiel #21
0
def group(request,
          name,
          template_name='reviews/datagrid.html',
          local_site_name=None):
    """
    A list of review requests belonging to a particular group.
    """
    # Make sure the group exists
    local_site = get_object_or_none(LocalSite, name=local_site_name)
    group = get_object_or_404(Group, name=name, local_site=local_site)

    if not group.is_accessible_by(request.user):
        return _render_permission_denied(
            request, 'reviews/group_permission_denied.html')

    datagrid = ReviewRequestDataGrid(request,
        ReviewRequest.objects.to_group(name, local_site, status=None,
                                       with_counts=True),
        _("Review requests for %s") % name)

    return datagrid.render_to_response(template_name)
Beispiel #22
0
    def publish(self, user):
        """
        Save the current draft attached to this review request. Send out the
        associated email. Returns the review request that was saved.
        """
        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)
        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            changes = draft.publish(self)
            draft.delete()
        else:
            changes = None

        self.public = True
        self.save()

        siteconfig = SiteConfiguration.objects.get_current()
        if siteconfig.get("mail_send_review_mail"):
            mail_review_request(user, self, changes)
Beispiel #23
0
def filecommentcounts(context, files):
    """
    Returns a JSON array of current comments for a screenshot.

    Each entry in the array has a dictionary containing the following keys:

      =========== ==================================================
      Key         Description
      =========== ==================================================
      text        The text of the comment
      localdraft  True if this is the current user's draft comment
      =========== ==================================================
    """
    fileComments = {}
    user = context.get('user', None)
    for upFile in files:
        default = '%s' % (upFile.id)
        upfileDefault = fileComments.setdefault(default, [])
        for comment in upFile.comments.all():
            review = get_object_or_none(comment.review)

            if review and (review.public or review.user == user):
                position = '%s' % (comment.id)

                upfileDefault.append({
                    'file_id': upFile.id,
                    'id': comment.id,
                    'text': comment.text,
                    'user': {
                        'username': review.user.username,
                        'name': review.user.get_full_name() or review.user.username,
                    },
                    'url': comment.get_review_url(),
                    'localdraft' : review.user == user and \
                                   not review.public,
                })

    return simplejson.dumps(fileComments)
Beispiel #24
0
def view_diff_fragment(
        request, diffset_id, filediff_id, interdiffset_id=None,
        chunkindex=None,
        template_name='diffviewer/diff_file_fragment.html',
        error_template_name='diffviewer/diff_fragment_error.html'):

    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

    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)

    if chunkindex:
        collapseall = False
    else:
        collapseall = get_collapse_diff(request)

    etag = ""

    if collapseall:
        etag += "collapseall-"

    if highlighting:
        etag += "highlighting-"

    etag += str(settings.AJAX_SERIAL)

    if etag_if_none_match(request, etag):
        return HttpResponseNotModified()

    try:
        file = get_requested_diff_file()

        if file:
            context = {
                'standalone': chunkindex is not None,
            }

            response = HttpResponse(
                build_diff_fragment(request, file, chunkindex,
                                    highlighting, collapseall,
                                    context, template_name))
            set_etag(response, etag)
            return response
        raise UserVisibleError(
            _(u"Internal error. Unable to locate file record for filediff %s") % \
            filediff.id)
    except Exception, e:
        extra_context = {}

        file = get_requested_diff_file(False)
        extra_context['file'] = file

        return exception_traceback(request, e, error_template_name,
                                   extra_context)
Beispiel #25
0
def commentcounts(context, filediff, interfilediff=None):
    """
    Returns a JSON array of current comments for a filediff, sorted by
    line number.

    Each entry in the array has a dictionary containing the following keys:

      =========== ==================================================
      Key                Description
      =========== ==================================================
      comment_id         The ID of the comment
      text               The text of the comment
      line               The first line number
      num_lines          The number of lines this comment spans
      user               A dictionary containing "username" and "name" keys
                         for the user
      url                The URL to the comment
      localdraft         True if this is the current user's draft comment
      review_id          The ID of the review this comment is associated with
      ==============================================================
    """
    comment_dict = {}
    user = context.get('user', None)

    if interfilediff:
        query = Comment.objects.filter(filediff=filediff,
                                       interfilediff=interfilediff)
    else:
        query = Comment.objects.filter(filediff=filediff,
                                       interfilediff__isnull=True)

    for comment in query:
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            key = (comment.first_line, comment.num_lines)

            comment_dict.setdefault(key, []).append({
                'comment_id': comment.id,
                'text': comment.text,
                'line': comment.first_line,
                'num_lines': comment.num_lines,
                'user': {
                    'username': review.user.username,
                    'name': review.user.get_full_name() or review.user.username,
                },
                #'timestamp': comment.timestamp,
                'url': comment.get_review_url(),
                'localdraft': review.user == user and \
                              not review.public,
                'review_id': review.id,
                'review_request_id': review.review_request.id,
                'issue_opened': comment.issue_opened,
                'issue_status': BaseComment
                                .issue_status_to_string(comment.issue_status),
            })

    comments_array = []

    for key, value in comment_dict.iteritems():
        comments_array.append({
            'linenum': key[0],
            'num_lines': key[1],
            'comments': value,
        })

    comments_array.sort(cmp=lambda x, y: cmp(x['linenum'], y['linenum'] or
                                         cmp(x['num_lines'], y['num_lines'])))

    return simplejson.dumps(comments_array)
Beispiel #26
0
 def can_publish(self):
     return not self.public or get_object_or_none(self.draft) is not None
 def check_delete_result(self, user, group_name):
     self.assertIsNone(get_object_or_none(Group, name=group_name))
Beispiel #28
0
 def get_user(self, user_id):
     return get_object_or_none(User, pk=user_id)
Beispiel #29
0
 def get_user(self, user_id):
     return get_object_or_none(User, pk=user_id)
Beispiel #30
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)
Beispiel #31
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)
 def check_delete_result(self, user, review_request_id):
     self.assertIsNone(get_object_or_none(ReviewRequest,
                                          pk=review_request_id))
Beispiel #33
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)
Beispiel #34
0
def diff_line_comments(request, review_request_id, line, diff_revision,
                       filediff_id, interdiff_revision=None,
                       interfilediff_id=None):
    review_request = get_object_or_404(ReviewRequest, pk=review_request_id)
    filediff = get_object_or_404(FileDiff,
        pk=filediff_id, diffset__history=review_request.diffset_history,
        diffset__revision=diff_revision)

    if interdiff_revision is not None and interfilediff_id is not None:
        interfilediff = get_object_or_none(FileDiff,
            pk=interfilediff_id,
            diffset__history=review_request.diffset_history,
            diffset__revision=interdiff_revision)
    else:
        interfilediff = None

    if request.POST:
        if request.user.is_anonymous():
            return WebAPIResponseError(request, NOT_LOGGED_IN)

        num_lines = request.POST['num_lines']
        action = request.POST['action']

        # TODO: Sanity check the fields

        if action == "set":
            text = request.POST['text']

            review, review_is_new = Review.objects.get_or_create(
                review_request=review_request,
                user=request.user,
                public=False,
                base_reply_to__isnull=True)

            if interfilediff:
                comment, comment_is_new = review.comments.get_or_create(
                    filediff=filediff,
                    interfilediff=interfilediff,
                    first_line=line)
            else:
                comment, comment_is_new = review.comments.get_or_create(
                    filediff=filediff,
                    interfilediff__isnull=True,
                    first_line=line)

            comment.text = text
            comment.num_lines = num_lines
            comment.timestamp = datetime.now()
            comment.save()

            if comment_is_new:
                review.comments.add(comment)
                review.save()
        elif action == "delete":
            review = review_request.get_pending_review(request.user)

            if not review:
                raise Http404()

            q = Q(filediff=filediff, first_line=line)

            if interfilediff:
                q = q & Q(interfilediff=interfilediff)
            else:
                q = q & Q(interfilediff__isnull=True)

            try:
                comment = review.comments.get(q)
                comment.delete()
            except Comment.DoesNotExist:
                pass

            if review.body_top.strip() == "" and \
               review.body_bottom.strip() == "" and \
               review.comments.count() == 0 and \
               review.screenshot_comments.count() == 0:
                review.delete()
        else:
            return WebAPIResponseError(request, INVALID_ACTION,
                                     {'action': action})

    comments_query = filediff.comments.filter(
        Q(review__public=True) | Q(review__user=request.user),
        first_line=line)

    if interfilediff:
        comments_query = comments_query.filter(interfilediff=interfilediff)
    else:
        comments_query = comments_query.filter(interfilediff__isnull=True)

    return WebAPIResponse(request, {
        'comments': comments_query
    })
def commentcounts(context, filediff, interfilediff=None):
    """
    Returns a JSON array of current comments for a filediff, sorted by
    line number.

    Each entry in the array has a dictionary containing the following keys:

      =========== ==================================================
      Key         Description
      =========== ==================================================
      comment_id  The ID of the comment
      text        The text of the comment
      line        The first line number
      num_lines   The number of lines this comment spans
      user        A dictionary containing "username" and "name" keys
                  for the user
      url         The URL to the comment
      localdraft  True if this is the current user's draft comment
      =========== ==================================================
    """
    comment_dict = {}
    user = context.get('user', None)

    if interfilediff:
        query = Comment.objects.filter(filediff=filediff,
                                       interfilediff=interfilediff)
    else:
        query = Comment.objects.filter(filediff=filediff,
                                       interfilediff__isnull=True)

    for comment in query:
        review = get_object_or_none(comment.review)

        if review and (review.public or review.user == user):
            key = (comment.first_line, comment.num_lines)

            comment_dict.setdefault(key, []).append({
                'comment_id': comment.id,
                'text': comment.text,
                'line': comment.first_line,
                'num_lines': comment.num_lines,
                'user': {
                    'username': review.user.username,
                    'name': review.user.get_full_name() or review.user.username,
                },
                #'timestamp': comment.timestamp,
                'url': comment.get_review_url(),
                'localdraft': review.user == user and \
                              not review.public,
            })

    comments_array = []

    for key, value in comment_dict.iteritems():
        comments_array.append({
            'linenum': key[0],
            'num_lines': key[1],
            'comments': value,
        })

    comments_array.sort(cmp=lambda x, y: cmp(
        x['linenum'], y['linenum'] or cmp(x['num_lines'], y['num_lines'])))

    return simplejson.dumps(comments_array)