Commit Graph
123 Commits
Author SHA1 Message Date
Douwe Maan 84632f0aff Merge branch 'banzai-issue-filter-queries' into 'master'
Reduce SQL query counts in IssueReferenceFilter

## What does this MR do?

This MR adds a preparation phase for reference filters that allows them to prepare/create data structures used while iterating over HTML nodes. In this particular case the preparation phase is used for issue references to greatly cut down the amount of queries executed to get projects/issues for Markdown references.

## Are there points in the code the reviewer needs to double check?

No.

## Why was this MR needed?

Rendering Markdown containing issue references would run at most two queries for every issue reference: one to get the project and one to get the issue from said project. When rendering Markdown with lots of issue references this would result in _a lot_ of queries being executed.

## What are the relevant issue numbers?

#18042

See merge request !4410
2016-06-16 20:49:13 +00:00
Paco Guzman ae6a54f73c Banzai::Filter::ExternalLinkFilter use XPath 2016-06-16 14:13:29 +02:00
Yorick Peterse 19a290e7bf Reduce queries in IssueReferenceFilter
This reduces the number of queries executed in IssueReferenceFilter by
retrieving the various projects/issues that may be referenced in batches
_before_ iterating over all the HTML nodes.

A chunk of the logic resides in AbstractReferenceFilter so it can be
re-used by other filters in the future.
2016-06-16 14:04:45 +02:00
Paco Guzman 46696bde83 Banzai::Filter::UploadLinkFilter use XPath 2016-06-16 11:26:56 +02:00
Yorick Peterse fce675d7fc Eager load project relations in IssueParser
By eager loading these associations we can greatly cut down the number
of SQL queries executed when processing documents with lots of
references, especially in cases where there are references belonging to
the same project.

Since these associations are so specific to the reference parsing
process and the permissions checking process that follows it I opted to
include them directly in IssueParser instead of using something like a
scope. Once we have a need for it we can move this code to a scope or
method.
2016-06-15 15:30:34 +02:00
Sean McGivern 03d2bf141c Fix description and GFM pipelines conflicting
Consider this command:

    bundle exec rails r "include GitlabMarkdownHelper
    puts markdown('<span>this is a span</span>', pipeline: :description)
    puts markdown('<span>this is a span</span>')"

And the same in the opposite order:

    bundle exec rails r "include GitlabMarkdownHelper
    puts markdown('<span>this is a span</span>')
    puts markdown('<span>this is a span</span>', pipeline: :description)"

Before this change, they would both output:

    <p><span>this is a span</span></p>
    <p>this is a span</p>

That's because `span` is added to the list of whitelisted elements in
the `SanitizationFilter`, but this method tries not to make the same
changes multiple times. Unfortunately,
`HTML::Pipeline::SanitizationFilter::LIMITED`, which is used by the
`DescriptionPipeline`, uses the same Ruby objects for all of its hash
values _except_ `:elements`.

That means that whichever of `DescriptionPipeline` and `GfmPipeline` is
called first would have `span` in its whitelisted elements, and the
second wouldn't.

Fix this by creating an entirely separate hash, before either pipeline
is invoked.
2016-06-13 13:06:40 +01:00
Rémy Coutable 3d72cb897e Merge branch '18019-fix-wiki-linking' into 'master'
Fix wiki linking behavior for markdown wiki pages

Related to #18019 

- As per the documentation in !4372 

## TODO
- [ ] !4432 Have wiki linking behave as per the documentation
    - [x] Move `WikiLinkFilter` specs to the pipeline level
    - [x] Verify current behavior on wiki `show` page
    - [x] Fix current behavior on wiki `show` page
    - [x] Verify current behaviour on wiki preview
    - [x] Fix current behaviour on wiki preview
        - [x] Rewrite all links and get preview links working
        - [x] Make sure all links are on-par with the wiki `show` page
        - [x] TDD `WikiLinkFilter` and get it working
        - [x] Hook `WikiLinkFilter` up
    - [x] Fix tests 
        - [x] Fix `markdown_spec`
        - [x] Fix `wiki` spinach feature
        - [x] Wait for [build](https://gitlab.com/gitlab-org/gitlab-ce/commit/4f50dd2/builds) to pass
        - [x] Make sure all wiki-related pages are working as expected (history, all pages, etc.)
    - [x] Test in different ruby versions
    - [x] GitLab instances hosted on a relative URL
    - [x] Non-markdown rendering formats?
        - [x] RDoc
        - [x] ASCIIDoc
        - [x] Create issues to fix things for RDoc and ASCIIDoc
    - [x] Gauge performance impact
    - [x] Refactor
    - [x] Re-organize commits
    - [x] Make sure [build](https://gitlab.com/gitlab-org/gitlab-ce/commit/f860e9a8dcabe7d5f160c32fc549807c98baa4a1/builds) passes
    - [x] Respond to @rymai's comments
        - [x] `class WikiLinkFilter < HTML::Pipeline::Filter`
        - [x] blank line after guard clause
        - [x] keyword arguments for `wiki` and `slug`
        - [x] invert the condition
        - [x] inline `user` in spec
        - [x] Make sure spec names are not out of date
        - [x] Comment for each rewrite rule
    - [x] Add CHANGELOG entry
    - [x] Reorganize commits
    - [x] Make sure [build](https://gitlab.com/gitlab-org/gitlab-ce/commit/19b91e749a6320d12fb299d33f1f6440777e0e26/builds) passes
    - [ ] Wait for merge

See merge request !4432
2016-06-09 08:37:27 +00:00
Timothy Andrew 8e71c19a69 Implement the correct linking behaviour in WikiLinkFilter.
Original Comments
=================

- Linking behaves as per rules documented here:
  https://gitlab.com/gitlab-org/gitlab-ce/blob/16568-document-wiki-linking-behavior/doc/markdown/wiki.md
- All links (to other wiki pages) are rewritten to be at the level of
  the app root. We can't use links relative to the current
  page ('./foo', 'foo', '../foo'), because they won't work in the
  markdown preview, where the current page is suffixed with `/edit`
- Move existing `WikiLinkFilter` specs to `WikiPipeline` spec. It makes
  sense to run these tests on the combined output of the pipeline,
  rather than a single filter, since we can catch issues with
  conflicting filters.
- Add more tests to cover the new linking

@rymai's Review
===============

- Classes nested under `WikiLinkFilter` should declare `WikiLinkFilter`'s
  inherit, so nothing changes if the nested class is loaded first.
- Add a blank line after a guard clause
- Use keyword arguments for the `Rewriter` constructor
- Invert a condition - use `if` instead of `unless`
- Inline a `let` in `WikiPipeline` spec - it was only used in a single place
- Change out of date spec names
- Add a comment for every rewrite rule in `Rewriter`
2016-06-09 10:04:15 +05:30
Alfredo Sumaran 064cff13fd Remove obvious comment and extra line 2016-06-08 13:07:20 -05:00
Alfredo Sumaran 7be19db42f Set target="_blank" for external links 2016-06-08 13:07:20 -05:00
Douwe Maan 4c8d4c620c Merge branch 'banzai-user-filter-queries' 2016-06-03 14:35:49 +02:00
Yorick Peterse 01575e9966 Reduce Namespace queries in UserReferenceFilter
This changes UserReferenceFilter so it operates using the following
steps:

1. Grab all username references from the input document.
2. Query the corresponding Namespace objects using a single query.
3. Iterate over all nodes to build links while re-using the objects
   queried in step 2.

The impact of these changes is that a comment mentioning 5 different
usernames no longer runs 5 different queries (1 for every username),
instead it only runs a single query.
2016-06-02 14:01:42 +02:00
Yorick Peterse 8a6c3f27e9 Added ReferenceFilter#nodes
This method returns an Array of the HTML nodes as yielded by
ReferenceFilter#each_node. The method's return value is memoized to
allow multiple calls without having to re-query the input document.
2016-06-02 12:30:18 +02:00
Yorick Peterse 2fbfb85492 Returning enums in ReferenceFilter#each_node
This changes ReferenceFilter#each_node so that when it's called without
a block an Enumerator is returned.
2016-06-02 12:30:18 +02:00
Stan Hu ad3d0585aa Fix serious performance bug with rendering Markdown with InlineDiffFilter
Nokogiri's `node.replace` was being unnecessarily called for every text node in
the document due to a comparison bug. The code previously was comparing the
HTML representation of the full document against the text node, which would
always fail. Fix the comparison to just compare the modified text.

Closes #18011
2016-06-01 21:56:27 -07:00
Douwe Maan 2d084dd848 Merge branch 'separate-banzai-references' into 'master'
Separate reference gathering from rendering

This is a required step to allow batch processing when gathering references. This in turn would allow grabbing (for example) all mentioned users of an issue/merge request using a single query.

cc @rspeicher @DouweM 

See merge request !3969
2016-06-01 15:51:59 +00:00
Stan Hu f8a3344d12 Fix 404 page when viewing TODOs that contain milestones or labels in different projects
A user viewing the TODOs page will see a 404 if there are mentioned labels
in multiple different projects. This is likely a caching bug and only occurs
when Markdown rendering occurs across multiple projects, which is why it's so
tricky to reproduce. This is what I think is happening:

1. LabelReferenceFilter#references_in encounters label ~X for ProjectA and finds the label in the DB as id = 1.
2. LabelReferenceFilter.references_in yields [1, 'X', nil, ...]
3. Since project_ref is nil, AbstractReferenceFilter#project_from_ref_cache caches nil => ProjectA.
4. LabelReferenceFilter#references_in encounters label ~Y for ProjectB and finds the label in the DB as id = 2.
5. LabelReferenceFilter.references_in yields [2, 'Y', nil, ...]
6. AbstractReferenceFilter#project_from_ref_cache lookups nil and returns ProjectA. It was supposed to be ProjectB.
7. A is the wrong project, so the label lookup fails.

This MR caches Markdown references if the key is present.

Closes #17898
2016-05-31 20:37:53 -07:00
Yorick Peterse 86166d2802 Split Markdown rendering & reference gathering
This splits the Markdown rendering and reference extraction phases into
two distinct code bases. The reference extraction phase no longer relies
on the html-pipeline Gem (and any related code) and allows for
extracting of references from multiple HTML nodes in a single pass. This
means that if you want to extract user references from 200 comments you
no longer need to run 200 times N number of queries, instead only a
handful of queries may be needed.
2016-05-26 17:14:00 +02:00
Douwe Maan fc1910ddc5 Merge branch 'adambutler/gitlab-ce-feature/support-diff-of-issue-title-rename'
# Conflicts:
#	app/services/system_note_service.rb
2016-05-20 16:23:04 -05:00
Rémy Coutable f29d8b64e4 Merge remote-tracking branch 'origin/master' into eReGeBe/gitlab-ce-feature/milestone-md
Signed-off-by: Rémy Coutable <remy@rymai.me>
2016-05-18 23:40:33 -05:00
Adam ButlerandRémy Coutable 8a8b5497c5 Create DiffFilter and change SystemNoteService#change_title to use Gitlab::Diff::InlineDiff 2016-05-18 11:15:10 -05:00
Timothy Andrew a59ad3936a Add a spec for WikiLinkFilter
- And fix behavior for non-file hierarchical links.
2016-05-12 07:17:07 +05:30
Robert Speicher 0cc8cee6cd Merge branch 'fix/using-uploads-in-global-snippets' into 'master'
Fix using link to uploads in global snippets

Closes #17342, closes #17363

See merge request !4085
2016-05-10 17:07:10 +00:00
Grzegorz Bizon 535be93a77 Do not process upload links if no project context 2016-05-10 13:50:56 +02:00
Grzegorz Bizon 4c506c4498 Fix using link to uploads in global snippets
Closes #17342, closes #17363
2016-05-10 13:46:31 +02:00
Dmitriy Zaporozhets 21f942a5ad Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce 2016-05-10 12:51:24 +02:00
Benedikt Huss bf0fd3ea1b Links for redmine issue references are generated correctly again 2016-05-10 00:37:15 +02:00
Stan Hu 849cc380d8 Use a case-insensitive comparison in sanitizing URI schemes
Closes #1625
2016-05-09 12:47:53 -07:00
Douwe Maan 715959e581 Fix cross-project milestone ref with invalid project 2016-04-23 12:34:09 +02:00
Douwe Maan 952e2dc6d9 Merge branch 'master' into eReGeBe/gitlab-ce-feature/milestone-md 2016-04-23 12:27:09 +02:00
Robert Speicher 1ea2408ba3 Merge branch 'dev_issue_15331' into 'master'
Fixes window.opener bug

Adds `noreferrer` value to rel attribute for external links

REF: https://gitlab.com/gitlab-org/gitlab-ce/issues/15331

See merge request !1953
2016-04-21 20:49:41 +00:00
Alfredo Sumaran 72debd840c Fix failing spec 2016-04-21 14:38:44 -05:00
Grzegorz Bizon 35d8bc4485 Refactor banzai code that finds cross-project labels 2016-04-21 09:13:34 +02:00
Grzegorz Bizon f7348cd348 Fix cross-project label ref with invalid project
Closes #15168
2016-04-21 09:13:34 +02:00
Alfredo Sumaran dbe06ac790 Add noreferrer value to rel attribute for external links 2016-04-20 23:55:06 -05:00
Alejandro Rodríguez 30d1d47d1d Using project path_with_namespace in milestone's cross project references link text 2016-04-20 22:12:43 -03:00
Alejandro Rodríguez 1ff896f2bf Escaping the object_link_text on cross project milestone references 2016-04-20 22:12:43 -03:00
Alejandro Rodríguez 6d9794d42a Transforming milestones link references to the short reference form 2016-04-20 22:12:43 -03:00
Alejandro Rodríguez 375e83bb57 Consistently using iid when treating milestones as referrables
Also, addint a suffix to the reference text when the milestone is in another project
2016-04-20 22:12:43 -03:00
Alejandro Rodríguez 077f9a4eee Implementing special GitLab markdown reference for milestones
Using the syntax proposed in #13829 [project_reference]%(milestone_id | milestone_name)
to get a link to the referred milestone.
2016-04-20 22:12:43 -03:00
Yorick Peterse 935f913165 Instrument Banzai code 2016-04-11 17:43:12 +02:00
Robert Speicher 730625f022 Merge branch 'patch/fix-markdown-preview-wikis' into 'master'
Wiki preview URL converting problem [via Markdown]

Current implementation when rendering the preview, thinks relative links are for project repository files.

We are creating a new preview route that will define correct context data to render for wikis instead.

Fixes #2380, #1184

See merge request !3461
2016-04-07 00:17:21 +00:00
Gabriel Mazetto 1575a95b65 little refactor and improvements on specs 2016-04-06 20:09:15 -03:00
Yorick Peterse 507cbca339 Fix header link rendering when containing numbers
This fixes the problem where Markdown such as:

    ### 31st

Would get rendered as a link tag pointing to issue number 31 inside a
header tag.

See gitlab-org/gitlab-ce#14936 for more information.
2016-04-06 14:24:30 +02:00
Gabriel Mazetto 207b7218aa Ensure correct filter order to validate with our markdown spec 2016-04-06 03:30:56 -03:00
Gabriel Mazetto 22055e1058 Fix a few edited references from WikiLinkFilter and specs 2016-04-06 03:13:46 -03:00
Gabriel Mazetto 61fe0a2397 Fixed WikiPipeline and specs 2016-04-06 03:12:39 -03:00
connorshea b9abf938ed Wrap images in discussions and wikis with a link to the image source using ImageLinkFilter.
Resolves #14411.

See merge request !3464
2016-04-04 19:44:07 -06:00
Yorick Peterse 915fd3f910 Cleaned up caching in AbstractReferenceFilter
Cleaning this up any further is a bit tricky as the caches in question
should only be evaluated if RequestStore is actually enabled.
2016-04-04 11:39:11 +02:00
Yorick Peterse 7f0fd73eeb Cache default_issues_tracker? in Banzai
Every object processed by ExternalIssueReferenceFilter can return a
different Project instance when calling "project". For example, every
note processed will have it's own associated Project. If we were to
cache Project#default_issues_tracker? on Project level this would have
no impact on Markdown rendering timings as the cache would have to be
built for every Project instance without it ever being re-used.

To work around this we cache Project#default_issues_tracker? in
Banzai::Filter::ExternalIssueReferenceFilter using the project's _id_
instead of the whole object. This setup allows re-using of the cached
data even when the Project instances used are different, as long as the
actual project IDs are the same.
2016-04-04 10:44:35 +02:00