Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
e4008bc4
Commit
e4008bc4
authored
Oct 20, 2015
by
Jacob Vosmaer
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://gitlab.com/gitlab-org/gitlab-ce
into git-archive-improvements-2
parents
a321404f
befff682
Changes
138
Show whitespace changes
Inline
Side-by-side
Showing
138 changed files
with
1776 additions
and
801 deletions
+1776
-801
CHANGELOG
CHANGELOG
+16
-0
GITLAB_GIT_HTTP_SERVER_VERSION
GITLAB_GIT_HTTP_SERVER_VERSION
+1
-0
app/assets/stylesheets/framework/blocks.scss
app/assets/stylesheets/framework/blocks.scss
+45
-0
app/assets/stylesheets/framework/files.scss
app/assets/stylesheets/framework/files.scss
+4
-0
app/assets/stylesheets/framework/typography.scss
app/assets/stylesheets/framework/typography.scss
+0
-1
app/assets/stylesheets/pages/issues.scss
app/assets/stylesheets/pages/issues.scss
+5
-0
app/assets/stylesheets/pages/notes.scss
app/assets/stylesheets/pages/notes.scss
+4
-1
app/assets/stylesheets/pages/profile.scss
app/assets/stylesheets/pages/profile.scss
+6
-0
app/assets/stylesheets/pages/projects.scss
app/assets/stylesheets/pages/projects.scss
+1
-1
app/assets/stylesheets/pages/tree.scss
app/assets/stylesheets/pages/tree.scss
+0
-8
app/controllers/abuse_reports_controller.rb
app/controllers/abuse_reports_controller.rb
+4
-0
app/controllers/admin/application_settings_controller.rb
app/controllers/admin/application_settings_controller.rb
+1
-0
app/controllers/ci/projects_controller.rb
app/controllers/ci/projects_controller.rb
+8
-3
app/controllers/import/github_controller.rb
app/controllers/import/github_controller.rb
+0
-4
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+7
-0
app/controllers/projects/merge_requests_controller.rb
app/controllers/projects/merge_requests_controller.rb
+1
-1
app/controllers/projects/milestones_controller.rb
app/controllers/projects/milestones_controller.rb
+1
-5
app/controllers/projects_controller.rb
app/controllers/projects_controller.rb
+28
-2
app/finders/issuable_finder.rb
app/finders/issuable_finder.rb
+71
-43
app/helpers/gitlab_markdown_helper.rb
app/helpers/gitlab_markdown_helper.rb
+16
-5
app/helpers/issues_helper.rb
app/helpers/issues_helper.rb
+4
-0
app/helpers/labels_helper.rb
app/helpers/labels_helper.rb
+13
-5
app/helpers/preferences_helper.rb
app/helpers/preferences_helper.rb
+4
-4
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+5
-1
app/mailers/abuse_report_mailer.rb
app/mailers/abuse_report_mailer.rb
+12
-0
app/models/ability.rb
app/models/ability.rb
+2
-1
app/models/application_setting.rb
app/models/application_setting.rb
+4
-0
app/models/commit.rb
app/models/commit.rb
+2
-2
app/models/concerns/issuable.rb
app/models/concerns/issuable.rb
+6
-3
app/models/concerns/mentionable.rb
app/models/concerns/mentionable.rb
+13
-7
app/models/concerns/participable.rb
app/models/concerns/participable.rb
+19
-13
app/models/group_label.rb
app/models/group_label.rb
+9
-0
app/models/group_milestone.rb
app/models/group_milestone.rb
+2
-10
app/models/issue.rb
app/models/issue.rb
+10
-0
app/models/merge_request.rb
app/models/merge_request.rb
+4
-4
app/models/milestone.rb
app/models/milestone.rb
+32
-0
app/models/note.rb
app/models/note.rb
+2
-2
app/models/user.rb
app/models/user.rb
+10
-7
app/services/git_push_service.rb
app/services/git_push_service.rb
+1
-1
app/services/labels/group_service.rb
app/services/labels/group_service.rb
+26
-0
app/services/merge_requests/post_merge_service.rb
app/services/merge_requests/post_merge_service.rb
+10
-0
app/views/abuse_report_mailer/notify.html.haml
app/views/abuse_report_mailer/notify.html.haml
+11
-0
app/views/abuse_report_mailer/notify.text.haml
app/views/abuse_report_mailer/notify.text.haml
+5
-0
app/views/admin/application_settings/_form.html.haml
app/views/admin/application_settings/_form.html.haml
+6
-0
app/views/admin/users/_profile.html.haml
app/views/admin/users/_profile.html.haml
+0
-0
app/views/admin/users/show.html.haml
app/views/admin/users/show.html.haml
+1
-1
app/views/ci/projects/index.html.haml
app/views/ci/projects/index.html.haml
+20
-0
app/views/events/_event_issue.atom.haml
app/views/events/_event_issue.atom.haml
+1
-2
app/views/events/_event_merge_request.atom.haml
app/views/events/_event_merge_request.atom.haml
+1
-2
app/views/events/_event_note.atom.haml
app/views/events/_event_note.atom.haml
+1
-1
app/views/events/_event_push.atom.haml
app/views/events/_event_push.atom.haml
+1
-1
app/views/layouts/notify.html.haml
app/views/layouts/notify.html.haml
+4
-0
app/views/notify/_note_message.html.haml
app/views/notify/_note_message.html.haml
+1
-1
app/views/notify/new_issue_email.html.haml
app/views/notify/new_issue_email.html.haml
+1
-1
app/views/notify/new_merge_request_email.html.haml
app/views/notify/new_merge_request_email.html.haml
+1
-1
app/views/profiles/preferences/show.html.haml
app/views/profiles/preferences/show.html.haml
+2
-2
app/views/projects/_activity.html.haml
app/views/projects/_activity.html.haml
+0
-1
app/views/projects/_files.html.haml
app/views/projects/_files.html.haml
+6
-0
app/views/projects/_readme.html.haml
app/views/projects/_readme.html.haml
+7
-8
app/views/projects/activity.html.haml
app/views/projects/activity.html.haml
+2
-0
app/views/projects/blob/_blob.html.haml
app/views/projects/blob/_blob.html.haml
+17
-14
app/views/projects/blob/show.html.haml
app/views/projects/blob/show.html.haml
+0
-3
app/views/projects/buttons/_notifications.html.haml
app/views/projects/buttons/_notifications.html.haml
+19
-13
app/views/projects/ci_services/index.html.haml
app/views/projects/ci_services/index.html.haml
+1
-1
app/views/projects/edit.html.haml
app/views/projects/edit.html.haml
+17
-1
app/views/projects/imports/new.html.haml
app/views/projects/imports/new.html.haml
+1
-1
app/views/projects/issues/_closed_by_box.html.haml
app/views/projects/issues/_closed_by_box.html.haml
+3
-0
app/views/projects/issues/show.html.haml
app/views/projects/issues/show.html.haml
+2
-1
app/views/projects/merge_requests/widget/_heading.html.haml
app/views/projects/merge_requests/widget/_heading.html.haml
+36
-37
app/views/projects/remove_fork.js.haml
app/views/projects/remove_fork.js.haml
+2
-0
app/views/projects/show.html.haml
app/views/projects/show.html.haml
+4
-11
app/views/projects/tree/_blob_item.html.haml
app/views/projects/tree/_blob_item.html.haml
+1
-1
app/views/projects/tree/_readme.html.haml
app/views/projects/tree/_readme.html.haml
+3
-3
app/views/projects/tree/_tree_content.html.haml
app/views/projects/tree/_tree_content.html.haml
+1
-34
app/views/projects/tree/_tree_header.html.haml
app/views/projects/tree/_tree_header.html.haml
+32
-0
app/views/projects/tree/_tree_item.html.haml
app/views/projects/tree/_tree_item.html.haml
+1
-1
app/views/projects/tree/show.html.haml
app/views/projects/tree/show.html.haml
+4
-4
app/views/shared/_clone_panel.html.haml
app/views/shared/_clone_panel.html.haml
+2
-2
app/views/shared/issuable/_filter.html.haml
app/views/shared/issuable/_filter.html.haml
+4
-5
app/views/users/calendar.html.haml
app/views/users/calendar.html.haml
+2
-4
app/views/users/show.html.haml
app/views/users/show.html.haml
+57
-33
config/routes.rb
config/routes.rb
+1
-0
db/fixtures/development/05_users.rb
db/fixtures/development/05_users.rb
+2
-2
db/fixtures/development/07_milestones.rb
db/fixtures/development/07_milestones.rb
+1
-1
db/fixtures/development/09_issues.rb
db/fixtures/development/09_issues.rb
+1
-1
db/fixtures/development/12_snippets.rb
db/fixtures/development/12_snippets.rb
+1
-1
db/migrate/20151008143519_add_admin_notification_email_setting.rb
...te/20151008143519_add_admin_notification_email_setting.rb
+5
-0
db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb
...rate/20151016195451_add_ci_builds_and_projects_indexes.rb
+9
-0
db/migrate/20151016195706_add_notes_line_code_index.rb
db/migrate/20151016195706_add_notes_line_code_index.rb
+5
-0
db/schema.rb
db/schema.rb
+8
-1
doc/install/installation.md
doc/install/installation.md
+1
-0
doc/update/7.14-to-8.0.md
doc/update/7.14-to-8.0.md
+1
-0
features/steps/abuse_reports.rb
features/steps/abuse_reports.rb
+1
-1
features/steps/project/project.rb
features/steps/project/project.rb
+2
-2
lib/api/projects.rb
lib/api/projects.rb
+2
-2
lib/gitlab/markdown.rb
lib/gitlab/markdown.rb
+77
-41
lib/gitlab/markdown/commit_range_reference_filter.rb
lib/gitlab/markdown/commit_range_reference_filter.rb
+13
-3
lib/gitlab/markdown/commit_reference_filter.rb
lib/gitlab/markdown/commit_reference_filter.rb
+17
-7
lib/gitlab/markdown/cross_project_reference.rb
lib/gitlab/markdown/cross_project_reference.rb
+2
-9
lib/gitlab/markdown/external_issue_reference_filter.rb
lib/gitlab/markdown/external_issue_reference_filter.rb
+2
-1
lib/gitlab/markdown/issue_reference_filter.rb
lib/gitlab/markdown/issue_reference_filter.rb
+5
-3
lib/gitlab/markdown/label_reference_filter.rb
lib/gitlab/markdown/label_reference_filter.rb
+5
-3
lib/gitlab/markdown/merge_request_reference_filter.rb
lib/gitlab/markdown/merge_request_reference_filter.rb
+5
-3
lib/gitlab/markdown/redactor_filter.rb
lib/gitlab/markdown/redactor_filter.rb
+40
-0
lib/gitlab/markdown/reference_filter.rb
lib/gitlab/markdown/reference_filter.rb
+41
-24
lib/gitlab/markdown/reference_gatherer_filter.rb
lib/gitlab/markdown/reference_gatherer_filter.rb
+63
-0
lib/gitlab/markdown/snippet_reference_filter.rb
lib/gitlab/markdown/snippet_reference_filter.rb
+5
-3
lib/gitlab/markdown/user_reference_filter.rb
lib/gitlab/markdown/user_reference_filter.rb
+29
-16
lib/gitlab/reference_extractor.rb
lib/gitlab/reference_extractor.rb
+20
-8
lib/tasks/gitlab/check.rake
lib/tasks/gitlab/check.rake
+1
-1
spec/benchmarks/models/milestone_spec.rb
spec/benchmarks/models/milestone_spec.rb
+17
-0
spec/controllers/abuse_reports_controller_spec.rb
spec/controllers/abuse_reports_controller_spec.rb
+72
-0
spec/controllers/import/github_controller_spec.rb
spec/controllers/import/github_controller_spec.rb
+1
-1
spec/controllers/projects_controller_spec.rb
spec/controllers/projects_controller_spec.rb
+74
-0
spec/features/markdown_spec.rb
spec/features/markdown_spec.rb
+1
-1
spec/features/projects_spec.rb
spec/features/projects_spec.rb
+25
-4
spec/helpers/gitlab_markdown_helper_spec.rb
spec/helpers/gitlab_markdown_helper_spec.rb
+15
-12
spec/helpers/issues_helper_spec.rb
spec/helpers/issues_helper_spec.rb
+10
-0
spec/helpers/labels_helper_spec.rb
spec/helpers/labels_helper_spec.rb
+0
-5
spec/lib/gitlab/closing_issue_extractor_spec.rb
spec/lib/gitlab/closing_issue_extractor_spec.rb
+5
-5
spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
...lib/gitlab/markdown/commit_range_reference_filter_spec.rb
+32
-38
spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
+30
-36
spec/lib/gitlab/markdown/cross_project_reference_spec.rb
spec/lib/gitlab/markdown/cross_project_reference_spec.rb
+8
-28
spec/lib/gitlab/markdown/issue_reference_filter_spec.rb
spec/lib/gitlab/markdown/issue_reference_filter_spec.rb
+35
-41
spec/lib/gitlab/markdown/label_reference_filter_spec.rb
spec/lib/gitlab/markdown/label_reference_filter_spec.rb
+13
-5
spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb
...ib/gitlab/markdown/merge_request_reference_filter_spec.rb
+30
-36
spec/lib/gitlab/markdown/redactor_filter_spec.rb
spec/lib/gitlab/markdown/redactor_filter_spec.rb
+91
-0
spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb
spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb
+89
-0
spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
+29
-35
spec/lib/gitlab/markdown/user_reference_filter_spec.rb
spec/lib/gitlab/markdown/user_reference_filter_spec.rb
+18
-37
spec/lib/gitlab/reference_extractor_spec.rb
spec/lib/gitlab/reference_extractor_spec.rb
+7
-7
spec/models/concerns/issuable_spec.rb
spec/models/concerns/issuable_spec.rb
+0
-1
spec/models/issue_spec.rb
spec/models/issue_spec.rb
+37
-0
spec/models/milestone_spec.rb
spec/models/milestone_spec.rb
+28
-0
spec/requests/api/projects_spec.rb
spec/requests/api/projects_spec.rb
+32
-18
spec/support/filter_spec_helper.rb
spec/support/filter_spec_helper.rb
+8
-15
spec/support/markdown_feature.rb
spec/support/markdown_feature.rb
+13
-19
spec/support/mentionable_shared_examples.rb
spec/support/mentionable_shared_examples.rb
+2
-0
No files found.
CHANGELOG
View file @
e4008bc4
Please view this file on the master branch, on stable branches it's out of date.
v 8.2.0 (unreleased)
- Fix duplicate repositories in GitHub import page (Stan Hu)
- Show last project commit to default branch on project home page
- Highlight comment based on anchor in URL
- Adds ability to remove the forked relationship from project settings screen. (Han Loong Liauw)
- Improved performance of sorting milestone issues
- Allow users to select the Files view as default project view (Cristian Bica)
v 8.1.0 (unreleased)
- Send an email to admin email when a user is reported for spam (Jonathan Rochkind)
- Show notifications button when user is member of group rather than project (Grzegorz Bizon)
- Fix bug preventing mentioned issued from being closed when MR is merged using fast-forward merge.
- Fix nonatomic database update potentially causing project star counts to go negative (Stan Hu)
- Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu)
- Speed up load times of issue detail pages by roughly 1.5x
- If a merge request is to close an issue, show this on the issue page (Zeger-Jan van de Weg)
- Add a system note and update relevant merge requests when a branch is deleted or re-added (Stan Hu)
- Make diff file view easier to use on mobile screens (Stan Hu)
- Improved performance of finding users by username or Email address
...
...
@@ -59,6 +68,7 @@ v 8.1.0 (unreleased)
- Fix position of hamburger in header for smaller screens (Han Loong Liauw)
- Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
- Persist filters when sorting on admin user page (Jerry Lukins)
- Allow dashboard and group issues/MRs to be filtered by label
- Add spellcheck=false to certain input fields
- Invalidate stored service password if the endpoint URL is changed
- Project names are not fully shown if group name is too big, even on group page view
...
...
@@ -68,6 +78,12 @@ v 8.1.0 (unreleased)
- Hide passwords from services API (Alex Lossent)
- Fix: Images cannot show when projects' path was changed
- Let gitlab-git-http-server generate and serve 'git archive' downloads
- Optimize query when filtering on issuables (Zeger-Jan van de Weg)
- Fix padding of outdated discussion item.
v 8.0.5
- Correct lookup-by-email for LDAP logins
- Fix loading spinner sometimes not being hidden on Merge Request tab switches
v 8.0.4
- Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
...
...
GITLAB_GIT_HTTP_SERVER_VERSION
0 → 100644
View file @
e4008bc4
0.3.0
app/assets/stylesheets/framework/blocks.scss
View file @
e4008bc4
...
...
@@ -65,3 +65,48 @@
line-height
:
42px
;
}
}
.cover-block
{
text-align
:
center
;
background
:
#f7f8fa
;
margin
:
-
$gl-padding
;
margin-bottom
:
0
;
padding
:
44px
$gl-padding
;
border-bottom
:
1px
solid
$border-color
;
position
:
relative
;
.avatar-holder
{
margin-bottom
:
16px
;
.avatar
,
.identicon
{
margin
:
0
auto
;
float
:
none
;
}
.identicon
{
@include
border-radius
(
50%
);
}
}
.cover-title
{
color
:
$gl-header-color
;
margin
:
0
;
font-size
:
23px
;
font-weight
:
normal
;
margin
:
16px
0
5px
0
;
color
:
#4c4e54
;
font-size
:
23px
;
line-height
:
1
.1
;
}
.cover-desc
{
padding
:
0
$gl-padding
;
color
:
$gl-text-color
;
}
.cover-controls
{
position
:
absolute
;
top
:
10px
;
right
:
10px
;
}
}
app/assets/stylesheets/framework/files.scss
View file @
e4008bc4
...
...
@@ -10,6 +10,10 @@
border-bottom
:
1px
solid
#E7E9EE
;
margin-bottom
:
1em
;
&
.readme-holder
{
border-bottom
:
0
;
}
table
{
@extend
.table
;
}
...
...
app/assets/stylesheets/framework/typography.scss
View file @
e4008bc4
...
...
@@ -18,7 +18,6 @@
font-family
:
$monospace_font
;
white-space
:
pre
;
word-wrap
:
normal
;
padding
:
1px
2px
;
}
kbd
{
...
...
app/assets/stylesheets/pages/issues.scss
View file @
e4008bc4
...
...
@@ -132,6 +132,11 @@ form.edit-issue {
}
}
.issue-closed-by-widget
{
padding
:
16px
0
;
margin
:
0px
;
}
.issue-form
.select2-container
{
width
:
250px
!
important
;
}
app/assets/stylesheets/pages/notes.scss
View file @
e4008bc4
...
...
@@ -30,7 +30,6 @@ ul.notes {
.discussion-header
,
.note-header
{
@extend
.cgray
;
padding-bottom
:
15px
;
a
:hover
{
text-decoration
:
none
;
...
...
@@ -75,6 +74,10 @@ ul.notes {
}
}
.discussion-body
{
padding-top
:
15px
;
}
.discussion
{
overflow
:
hidden
;
display
:
block
;
...
...
app/assets/stylesheets/pages/profile.scss
View file @
e4008bc4
...
...
@@ -47,3 +47,9 @@
}
}
}
.calendar-hint
{
margin-top
:
-12px
;
float
:
right
;
font-size
:
12px
;
}
app/assets/stylesheets/pages/projects.scss
View file @
e4008bc4
...
...
@@ -544,5 +544,5 @@ pre.light-well {
}
.project-show-readme
.readme-holder
{
padding
:
7px
;
border-top
:
0
;
}
app/assets/stylesheets/pages/tree.scss
View file @
e4008bc4
...
...
@@ -4,14 +4,6 @@
margin-right
:
-
$gl-padding
;
}
.tree_progress
{
display
:
none
;
margin
:
20px
;
&
.loading
{
display
:
block
;
}
}
.tree-table
{
margin-bottom
:
0
;
...
...
app/controllers/abuse_reports_controller.rb
View file @
e4008bc4
...
...
@@ -9,6 +9,10 @@ class AbuseReportsController < ApplicationController
@abuse_report
.
reporter
=
current_user
if
@abuse_report
.
save
if
current_application_settings
.
admin_notification_email
.
present?
AbuseReportMailer
.
delay
.
notify
(
@abuse_report
.
id
)
end
message
=
"Thank you for your report. A GitLab administrator will look into it shortly."
redirect_to
root_path
,
notice:
message
else
...
...
app/controllers/admin/application_settings_controller.rb
View file @
e4008bc4
...
...
@@ -55,6 +55,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:default_snippet_visibility
,
:restricted_signup_domains_raw
,
:version_check_enabled
,
:admin_notification_email
,
:user_oauth_applications
,
restricted_visibility_levels:
[],
import_sources:
[]
...
...
app/controllers/ci/projects_controller.rb
View file @
e4008bc4
module
Ci
class
ProjectsController
<
Ci
::
ApplicationController
before_action
:project
before_action
:authenticate_user!
,
except:
[
:build
,
:badge
]
before_action
:authorize_access_project!
,
except:
[
:badge
]
before_action
:project
,
except:
[
:index
]
before_action
:authenticate_user!
,
except:
[
:
index
,
:
build
,
:badge
]
before_action
:authorize_access_project!
,
except:
[
:
index
,
:
badge
]
before_action
:authorize_manage_project!
,
only:
[
:toggle_shared_runners
,
:dumped_yaml
]
before_action
:no_cache
,
only:
[
:badge
]
protect_from_forgery
def
show
# Temporary compatibility with CI badges pointing to CI project page
redirect_to
namespace_project_path
(
project
.
gl_project
.
namespace
,
project
.
gl_project
)
end
# Project status badge
# Image with build status for sha or ref
def
badge
...
...
app/controllers/import/github_controller.rb
View file @
e4008bc4
...
...
@@ -11,10 +11,6 @@ class Import::GithubController < Import::BaseController
def
status
@repos
=
client
.
repos
client
.
orgs
.
each
do
|
org
|
@repos
+=
client
.
org_repos
(
org
.
login
)
end
@already_added_projects
=
current_user
.
created_projects
.
where
(
import_type:
"github"
)
already_added_projects_names
=
@already_added_projects
.
pluck
(
:import_source
)
...
...
app/controllers/projects/issues_controller.rb
View file @
e4008bc4
...
...
@@ -14,6 +14,9 @@ class Projects::IssuesController < Projects::ApplicationController
# Allow issues bulk update
before_action
:authorize_admin_issues!
,
only:
[
:bulk_update
]
# Cross-reference merge requests
before_action
:closed_by_merge_requests
,
only:
[
:show
]
respond_to
:html
def
index
...
...
@@ -112,6 +115,10 @@ class Projects::IssuesController < Projects::ApplicationController
render
nothing:
true
end
def
closed_by_merge_requests
@closed_by_merge_requests
||=
@issue
.
closed_by_merge_requests
(
current_user
)
end
protected
def
issue
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
e4008bc4
app/controllers/projects/milestones_controller.rb
View file @
e4008bc4
...
...
@@ -75,11 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end
def
sort_issues
@issues
=
@milestone
.
issues
.
where
(
id:
params
[
'sortable_issue'
])
@issues
.
each
do
|
issue
|
issue
.
position
=
params
[
'sortable_issue'
].
index
(
issue
.
id
.
to_s
)
+
1
issue
.
save
end
@milestone
.
sort_issues
(
params
[
'sortable_issue'
].
map
(
&
:to_i
))
render
json:
{
saved:
true
}
end
...
...
app/controllers/projects_controller.rb
View file @
e4008bc4
class
ProjectsController
<
ApplicationController
include
ExtractsPath
prepend_before_filter
:render_go_import
,
only:
[
:show
]
skip_before_action
:authenticate_user!
,
only:
[
:show
,
:activity
]
before_action
:project
,
except:
[
:new
,
:create
]
before_action
:repository
,
except:
[
:new
,
:create
]
before_action
:assign_ref_vars
,
:tree
,
only:
[
:show
],
if: :repo_exists?
# Authorize
before_action
:authorize_admin_project!
,
only:
[
:edit
,
:update
,
:destroy
,
:transfer
,
:archive
,
:unarchive
]
before_action
:authorize_admin_project!
,
only:
[
:edit
,
:update
]
before_action
:event_filter
,
only:
[
:show
,
:activity
]
layout
:determine_layout
...
...
@@ -56,6 +59,8 @@ class ProjectsController < ApplicationController
end
def
transfer
return
access_denied!
unless
can?
(
current_user
,
:change_namespace
,
@project
)
namespace
=
Namespace
.
find_by
(
id:
params
[
:new_namespace_id
])
::
Projects
::
TransferService
.
new
(
project
,
current_user
).
execute
(
namespace
)
...
...
@@ -64,6 +69,15 @@ class ProjectsController < ApplicationController
end
end
def
remove_fork
return
access_denied!
unless
can?
(
current_user
,
:remove_fork_project
,
@project
)
if
@project
.
forked?
@project
.
forked_project_link
.
destroy
flash
[
:notice
]
=
'The fork relationship has been removed.'
end
end
def
activity
respond_to
do
|
format
|
format
.
html
...
...
@@ -87,7 +101,7 @@ class ProjectsController < ApplicationController
render
'projects/empty'
else
if
current_user
@membership
=
@project
.
project_member_by_id
(
current_user
.
id
)
@membership
=
@project
.
team
.
find_member
(
current_user
.
id
)
end
render
:show
...
...
@@ -139,6 +153,7 @@ class ProjectsController < ApplicationController
def
archive
return
access_denied!
unless
can?
(
current_user
,
:archive_project
,
@project
)
@project
.
archive!
respond_to
do
|
format
|
...
...
@@ -148,6 +163,7 @@ class ProjectsController < ApplicationController
def
unarchive
return
access_denied!
unless
can?
(
current_user
,
:archive_project
,
@project
)
@project
.
unarchive!
respond_to
do
|
format
|
...
...
@@ -225,4 +241,14 @@ class ProjectsController < ApplicationController
render
"go_import"
,
layout:
false
end
def
repo_exists?
project
.
repository_exists?
&&
!
project
.
empty_repo?
end
# Override get_id from ExtractsPath, which returns the branch and file path
# for the blob/tree, which in this case is just the root of the default branch.
def
get_id
project
.
repository
.
root_ref
end
end
app/finders/issuable_finder.rb
View file @
e4008bc4
...
...
@@ -53,14 +53,35 @@ class IssuableFinder
end
end
def
project?
params
[
:project_id
].
present?
end
def
project
return
@project
if
defined?
(
@project
)
@project
=
if
params
[
:project_id
].
present?
Project
.
find
(
params
[
:project_id
])
if
project?
@project
=
Project
.
find
(
params
[
:project_id
])
unless
Ability
.
abilities
.
allowed?
(
current_user
,
:read_project
,
@project
)
@project
=
nil
end
else
nil
@project
=
nil
end
@project
end
def
projects
return
@projects
if
defined?
(
@projects
)
if
project?
project
elsif
current_user
&&
params
[
:authorized_only
].
presence
&&
!
current_user_related?
current_user
.
authorized_projects
else
ProjectsFinder
.
new
.
execute
(
current_user
)
end
end
...
...
@@ -72,7 +93,7 @@ class IssuableFinder
params
[
:milestone_title
].
present?
end
def
no_milestones
?
def
filter_by_no_milestone
?
milestones?
&&
params
[
:milestone_title
]
==
Milestone
::
None
.
title
end
...
...
@@ -81,12 +102,22 @@ class IssuableFinder
@milestones
=
if
milestones?
Milestone
.
where
(
title:
params
[
:milestone_title
])
scope
=
Milestone
.
where
(
project_id:
projects
)
scope
.
where
(
title:
params
[
:milestone_title
])
else
nil
end
end
def
labels?
params
[
:label_name
].
present?
end
def
filter_by_no_label?
labels?
&&
params
[
:label_name
]
==
Label
::
None
.
title
end
def
assignee?
params
[
:assignee_id
].
present?
end
...
...
@@ -120,19 +151,7 @@ class IssuableFinder
private
def
init_collection
table_name
=
klass
.
table_name
if
project
if
Ability
.
abilities
.
allowed?
(
current_user
,
:read_project
,
project
)
project
.
send
(
table_name
)
else
[]
end
elsif
current_user
&&
params
[
:authorized_only
].
presence
&&
!
current_user_related?
klass
.
of_projects
(
current_user
.
authorized_projects
).
references
(
:project
)
else
klass
.
of_projects
(
ProjectsFinder
.
new
.
execute
(
current_user
)).
references
(
:project
)
end
klass
.
all
end
def
by_scope
(
items
)
...
...
@@ -170,7 +189,12 @@ class IssuableFinder
end
def
by_project
(
items
)
items
=
items
.
of_projects
(
project
.
id
)
if
project
items
=
if
projects
items
.
of_projects
(
projects
).
references
(
:project
)
else
items
.
none
end
items
end
...
...
@@ -185,18 +209,6 @@ class IssuableFinder
items
.
sort
(
params
[
:sort
])
end
def
by_milestone
(
items
)
if
milestones?
if
no_milestones?
items
=
items
.
where
(
milestone_id:
[
-
1
,
nil
])
else
items
=
items
.
where
(
milestone_id:
milestones
.
try
(
:pluck
,
:id
))
end
end
items
end
def
by_assignee
(
items
)
if
assignee?
items
=
items
.
where
(
assignee_id:
assignee
.
try
(
:id
))
...
...
@@ -213,20 +225,36 @@ class IssuableFinder
items
end
def
by_label
(
items
)
if
params
[
:label_name
].
present?
if
params
[
:label_name
]
==
Label
::
None
.
title
item_ids
=
LabelLink
.
where
(
target_type:
klass
.
name
).
pluck
(
:target_id
)
def
by_milestone
(
items
)
if
milestones?
if
filter_by_no_milestone?
items
=
items
.
where
(
milestone_id:
[
-
1
,
nil
])
else
items
=
items
.
joins
(
:milestone
).
where
(
milestones:
{
title:
params
[
:milestone_title
]
})
if
projects
items
=
items
.
where
(
milestones:
{
project_id:
projects
})
end
end
end
items
end
items
=
items
.
where
(
'id NOT IN (?)'
,
item_ids
)
def
by_label
(
items
)
if
labels?
if
filter_by_no_label?
items
=
items
.
joins
(
"LEFT OUTER JOIN label_links ON label_links.target_type = '
#{
klass
.
name
}
' AND label_links.target_id =
#{
klass
.
table_name
}
.id"
).
where
(
label_links:
{
id:
nil
})
else
label_names
=
params
[
:label_name
].
split
(
","
)
item_ids
=
LabelLink
.
joins
(
:label
).
where
(
'labels.title in (?)'
,
label_names
).
where
(
target_type:
klass
.
name
).
pluck
(
:target_id
)
items
=
items
.
joins
(
:labels
).
where
(
labels:
{
title:
label_names
})
items
=
items
.
where
(
id:
item_ids
)
if
projects
items
=
items
.
where
(
labels:
{
project_id:
projects
})
end
end
end
...
...
app/helpers/gitlab_markdown_helper.rb
View file @
e4008bc4
...
...
@@ -19,7 +19,8 @@ module GitlabMarkdownHelper
escape_once
(
body
)
end
gfm_body
=
Gitlab
::
Markdown
.
gfm
(
escaped_body
,
project:
@project
,
current_user:
current_user
)
user
=
current_user
if
defined?
(
current_user
)
gfm_body
=
Gitlab
::
Markdown
.
gfm
(
escaped_body
,
project:
@project
,
current_user:
user
)
fragment
=
Nokogiri
::
HTML
::
DocumentFragment
.
parse
(
gfm_body
)
if
fragment
.
children
.
size
==
1
&&
fragment
.
children
[
0
].
name
==
'a'
...
...
@@ -45,29 +46,39 @@ module GitlabMarkdownHelper
end
def
markdown
(
text
,
context
=
{})
return
""
unless
text
.
present?
context
.
reverse_merge!
(
current_user:
current_user
,
path:
@path
,
pipeline: :default
,
project:
@project
,
project_wiki:
@project_wiki
,
ref:
@ref
)
Gitlab
::
Markdown
.
render
(
text
,
context
)
user
=
current_user
if
defined?
(
current_user
)
html
=
Gitlab
::
Markdown
.
render
(
text
,
context
)
Gitlab
::
Markdown
.
post_process
(
html
,
pipeline:
context
[
:pipeline
],
project:
@project
,
user:
user
)
end
# TODO (rspeicher): Remove all usages of this helper and just call `markdown`
# with a custom pipeline depending on the content being rendered
def
gfm
(
text
,
options
=
{})
return
""
unless
text
.
present?
options
.
reverse_merge!
(
current_user:
current_user
,
path:
@path
,
pipeline: :default
,
project:
@project
,
project_wiki:
@project_wiki
,
ref:
@ref
)
Gitlab
::
Markdown
.
gfm
(
text
,
options
)
user
=
current_user
if
defined?
(
current_user
)
html
=
Gitlab
::
Markdown
.
gfm
(
text
,
options
)
Gitlab
::
Markdown
.
post_process
(
html
,
pipeline:
options
[
:pipeline
],
project:
@project
,
user:
user
)
end
def
asciidoc
(
text
)
...
...
app/helpers/issues_helper.rb
View file @
e4008bc4
...
...
@@ -83,6 +83,10 @@ module IssuesHelper
end
end
def
merge_requests_sentence
(
merge_requests
)
merge_requests
.
map
(
&
:to_reference
).
to_sentence
(
last_word_connector:
', or '
)
end
# Required for Gitlab::Markdown::IssueReferenceFilter
module_function
:url_for_issue
end
app/helpers/labels_helper.rb
View file @
e4008bc4
...
...
@@ -92,11 +92,19 @@ module LabelsHelper
end
end
def
project_labels_options
(
project
)
labels
=
project
.
labels
.
to_a
labels
.
unshift
(
Label
::
None
)
labels
.
unshift
(
Label
::
Any
)
options_from_collection_for_select
(
labels
,
'name'
,
'title'
,
params
[
:label_name
])
def
projects_labels_options
labels
=
if
@project
@project
.
labels
else
Label
.
where
(
project_id:
@projects
)
end
grouped_labels
=
Labels
::
GroupService
.
new
(
labels
).
execute
grouped_labels
.
unshift
(
Label
::
None
)
grouped_labels
.
unshift
(
Label
::
Any
)
options_from_collection_for_select
(
grouped_labels
,
'name'
,
'title'
,
params
[
:label_name
])
end
# Required for Gitlab::Markdown::LabelReferenceFilter
...
...
app/helpers/preferences_helper.rb
View file @
e4008bc4
...
...
@@ -34,7 +34,8 @@ module PreferencesHelper
def
project_view_choices
[
[
'Readme (default)'
,
:readme
],
[
'Activity view'
,
:activity
]
[
'Activity view'
,
:activity
],
[
'Files view'
,
:files
]
]
end
...
...
@@ -46,8 +47,7 @@ module PreferencesHelper
Gitlab
::
ColorSchemes
.
for_user
(
current_user
).
css_class
end
def
prefer_readme?
!
current_user
||
current_user
.
project_view
==
'readme'
def
default_project_view
current_user
?
current_user
.
project_view
:
'readme'
end
end
app/helpers/projects_helper.rb
View file @
e4008bc4
...
...
@@ -70,6 +70,10 @@ module ProjectsHelper
"You are going to transfer
#{
project
.
name_with_namespace
}
to another owner. Are you ABSOLUTELY sure?"
end
def
remove_fork_project_message
(
project
)
"You are going to remove the fork relationship to source project
#{
@project
.
forked_from_project
.
name_with_namespace
}
. Are you ABSOLUTELY sure?"
end
def
project_nav_tabs
@nav_tabs
||=
get_project_nav_tabs
(
@project
,
current_user
)
end
...
...
@@ -113,7 +117,7 @@ module ProjectsHelper
nav_tabs
<<
:merge_requests
end
if
can?
(
current_user
,
:read_build
,
project
)
if
project
.
gitlab_ci?
&&
can?
(
current_user
,
:read_build
,
project
)
nav_tabs
<<
:builds
end
...
...
app/mailers/abuse_report_mailer.rb
0 → 100644
View file @
e4008bc4
class
AbuseReportMailer
<
BaseMailer
include
Gitlab
::
CurrentSettings
def
notify
(
abuse_report_id
)
@abuse_report
=
AbuseReport
.
find
(
abuse_report_id
)
mail
(
to:
current_application_settings
.
admin_notification_email
,
subject:
"
#{
@abuse_report
.
user
.
name
}
(
#{
@abuse_report
.
user
.
username
}
) was reported for abuse"
)
end
end
app/models/ability.rb
View file @
e4008bc4
...
...
@@ -189,7 +189,8 @@ class Ability
:change_visibility_level
,
:rename_project
,
:remove_project
,
:archive_project
:archive_project
,
:remove_fork_project
]
end
...
...
app/models/application_setting.rb
View file @
e4008bc4
...
...
@@ -44,6 +44,10 @@ class ApplicationSetting < ActiveRecord::Base
allow_blank:
true
,
format:
{
with:
/\A
#{
URI
.
regexp
(
%w(http https)
)
}
\z/
,
message:
"should be a valid url"
}
validates
:admin_notification_email
,
allow_blank:
true
,
email:
true
validates_each
:restricted_visibility_levels
do
|
record
,
attr
,
value
|
unless
value
.
nil?
value
.
each
do
|
level
|
...
...
app/models/commit.rb
View file @
e4008bc4
...
...
@@ -2,13 +2,13 @@ class Commit
extend
ActiveModel
::
Naming
include
ActiveModel
::
Conversion
include
Mentionable
include
Participable
include
Mentionable
include
Referable
include
StaticModel
attr_mentionable
:safe_message
participant
:author
,
:committer
,
:notes
,
:mentioned_users
participant
:author
,
:committer
,
:notes
attr_accessor
:project
...
...
app/models/concerns/issuable.rb
View file @
e4008bc4
...
...
@@ -6,8 +6,8 @@
#
module
Issuable
extend
ActiveSupport
::
Concern
include
Mentionable
include
Participable
include
Mentionable
included
do
belongs_to
:author
,
class_name:
"User"
...
...
@@ -47,8 +47,7 @@ module Issuable
prefix:
true
attr_mentionable
:title
,
:description
participant
:author
,
:assignee
,
:notes_with_associations
,
:mentioned_users
participant
:author
,
:assignee
,
:notes_with_associations
end
module
ClassMethods
...
...
@@ -86,6 +85,10 @@ module Issuable
assignee_id_changed?
end
def
open?
opened?
||
reopened?
end
#
# Votes
#
...
...
app/models/concerns/mentionable.rb
View file @
e4008bc4
...
...
@@ -20,6 +20,12 @@ module Mentionable
end
end
included
do
if
self
<
Participable
participant
->
(
current_user
)
{
mentioned_users
(
current_user
,
load_lazy_references:
false
)
}
end
end
# Returns the text used as the body of a Note when this object is referenced
#
# By default this will be the class name and the result of calling
...
...
@@ -41,22 +47,22 @@ module Mentionable
self
end
def
all_references
(
current_user
=
self
.
author
,
text
=
self
.
mentionable_text
)
ext
=
Gitlab
::
ReferenceExtractor
.
new
(
self
.
project
,
current_user
)
def
all_references
(
current_user
=
self
.
author
,
text
=
self
.
mentionable_text
,
load_lazy_references:
true
)
ext
=
Gitlab
::
ReferenceExtractor
.
new
(
self
.
project
,
current_user
,
load_lazy_references:
load_lazy_references
)
ext
.
analyze
(
text
)
ext
end
def
mentioned_users
(
current_user
=
nil
)
all_references
(
current_user
).
users
.
uniq
def
mentioned_users
(
current_user
=
nil
,
load_lazy_references:
true
)
all_references
(
current_user
,
load_lazy_references:
load_lazy_references
).
users
end
# Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
def
referenced_mentionables
(
current_user
=
self
.
author
,
text
=
self
.
mentionable_text
)
def
referenced_mentionables
(
current_user
=
self
.
author
,
text
=
self
.
mentionable_text
,
load_lazy_references:
true
)
return
[]
if
text
.
blank?
refs
=
all_references
(
current_user
,
text
)
(
refs
.
issues
+
refs
.
merge_requests
+
refs
.
commits
)
.
uniq
-
[
local_reference
]
refs
=
all_references
(
current_user
,
text
,
load_lazy_references:
load_lazy_references
)
(
refs
.
issues
+
refs
.
merge_requests
+
refs
.
commits
)
-
[
local_reference
]
end
# Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+.
...
...
app/models/concerns/participable.rb
View file @
e4008bc4
...
...
@@ -12,7 +12,7 @@
#
# # ...
#
# participant :author, :assignee, :
mentioned_users, :notes
# participant :author, :assignee, :
notes, ->(current_user) { mentioned_users(current_user) }
# end
#
# issue = Issue.last
...
...
@@ -27,7 +27,7 @@ module Participable
module
ClassMethods
def
participant
(
*
attrs
)
participant_attrs
.
concat
(
attrs
.
map
(
&
:to_s
)
)
participant_attrs
.
concat
(
attrs
)
end
def
participant_attrs
...
...
@@ -37,33 +37,39 @@ module Participable
# Be aware that this method makes a lot of sql queries.
# Save result into variable if you are going to reuse it inside same request
def
participants
(
current_user
=
self
.
author
)
self
.
class
.
participant_attrs
.
flat_map
do
|
attr
|
meth
=
method
(
attr
)
def
participants
(
current_user
=
self
.
author
,
load_lazy_references:
true
)
participants
=
self
.
class
.
participant_attrs
.
flat_map
do
|
attr
|
value
=
if
meth
.
arity
==
1
||
meth
.
arity
==
-
1
meth
.
call
(
current_use
r
)
if
attr
.
respond_to?
(
:call
)
instance_exec
(
current_user
,
&
att
r
)
else
meth
.
call
send
(
attr
)
end
participants_for
(
value
,
current_user
)
end
.
compact
.
uniq
.
select
do
|
user
|
user
.
can?
(
:read_project
,
self
.
project
)
end
.
compact
.
uniq
if
load_lazy_references
participants
=
Gitlab
::
Markdown
::
ReferenceFilter
::
LazyReference
.
load
(
participants
).
uniq
participants
.
select!
do
|
user
|
user
.
can?
(
:read_project
,
project
)
end
end
participants
end
private
def
participants_for
(
value
,
current_user
=
nil
)
case
value
when
User
when
User
,
Gitlab
::
Markdown
::
ReferenceFilter
::
LazyReference
[
value
]
when
Enumerable
,
ActiveRecord
::
Relation
value
.
flat_map
{
|
v
|
participants_for
(
v
,
current_user
)
}
when
Participable
value
.
participants
(
current_user
)
value
.
participants
(
current_user
,
load_lazy_references:
false
)
end
end
end
app/models/group_label.rb
0 → 100644
View file @
e4008bc4
class
GroupLabel
attr_accessor
:title
,
:labels
alias_attribute
:name
,
:title
def
initialize
(
title
,
labels
)
@title
=
title
@labels
=
labels
end
end
app/models/group_milestone.rb
View file @
e4008bc4
class
GroupMilestone
attr_accessor
:title
,
:milestones
alias_attribute
:name
,
:title
def
initialize
(
title
,
milestones
)
...
...
@@ -7,18 +7,10 @@ class GroupMilestone
@milestones
=
milestones
end
def
title
@title
end
def
safe_title
@title
.
parameterize
end
def
milestones
@milestones
end
def
projects
milestones
.
map
{
|
milestone
|
milestone
.
project
}
end
...
...
app/models/issue.rb
View file @
e4008bc4
...
...
@@ -95,4 +95,14 @@ class Issue < ActiveRecord::Base
def
source_project
project
end
# From all notes on this issue, we'll select the system notes about linked
# merge requests. Of those, the MRs closing `self` are returned.
def
closed_by_merge_requests
(
current_user
=
nil
)
return
[]
unless
open
?
notes
.
system
.
flat_map
do
|
note
|
note
.
all_references
(
current_user
).
merge_requests
end
.
uniq
.
select
{
|
mr
|
mr
.
open?
&&
mr
.
closes_issue?
(
self
)
}
end
end
app/models/merge_request.rb
View file @
e4008bc4
...
...
@@ -222,10 +222,6 @@ class MergeRequest < ActiveRecord::Base
self
.
target_project
.
events
.
where
(
target_id:
self
.
id
,
target_type:
"MergeRequest"
,
action:
Event
::
CLOSED
).
last
end
def
open?
opened?
||
reopened?
end
def
work_in_progress?
!!
(
title
=~
/\A\[?WIP\]?:? /i
)
end
...
...
@@ -294,6 +290,10 @@ class MergeRequest < ActiveRecord::Base
target_project
end
def
closes_issue?
(
issue
)
closes_issues
.
include?
(
issue
)
end
# Return the set of issues that will be closed if this merge request is accepted.
def
closes_issues
(
current_user
=
self
.
author
)
if
target_branch
==
project
.
default_branch
...
...
app/models/milestone.rb
View file @
e4008bc4
...
...
@@ -105,4 +105,36 @@ class Milestone < ActiveRecord::Base
def
author_id
nil
end
# Sorts the issues for the given IDs.
#
# This method runs a single SQL query using a CASE statement to update the
# position of all issues in the current milestone (scoped to the list of IDs).
#
# Given the ids [10, 20, 30] this method produces a SQL query something like
# the following:
#
# UPDATE issues
# SET position = CASE
# WHEN id = 10 THEN 1
# WHEN id = 20 THEN 2
# WHEN id = 30 THEN 3
# ELSE position
# END
# WHERE id IN (10, 20, 30);
#
# This method expects that the IDs given in `ids` are already Fixnums.
def
sort_issues
(
ids
)
pairs
=
[]
ids
.
each_with_index
do
|
id
,
index
|
pairs
<<
id
pairs
<<
index
+
1
end
conditions
=
'WHEN id = ? THEN ? '
*
ids
.
length
issues
.
where
(
id:
ids
).
update_all
([
"position = CASE
#{
conditions
}
ELSE position END"
,
*
pairs
])
end
end
app/models/note.rb
View file @
e4008bc4
...
...
@@ -22,14 +22,14 @@ require 'carrierwave/orm/activerecord'
require
'file_size_validator'
class
Note
<
ActiveRecord
::
Base
include
Mentionable
include
Gitlab
::
CurrentSettings
include
Participable
include
Mentionable
default_value_for
:system
,
false
attr_mentionable
:note
participant
:author
,
:mentioned_users
participant
:author
belongs_to
:project
belongs_to
:noteable
,
polymorphic:
true
...
...
app/models/user.rb
View file @
e4008bc4
...
...
@@ -183,7 +183,7 @@ class User < ActiveRecord::Base
# User's Project preference
# Note: When adding an option, it MUST go on the end of the array.
enum
project_view:
[
:readme
,
:activity
]
enum
project_view:
[
:readme
,
:activity
,
:files
]
alias_attribute
:private_token
,
:authentication_token
...
...
@@ -706,14 +706,17 @@ class User < ActiveRecord::Base
end
def
toggle_star
(
project
)
UsersStarProject
.
transaction
do
user_star_project
=
users_star_projects
.
where
(
project:
project
,
user:
self
).
take
where
(
project:
project
,
user:
self
).
lock
(
true
).
first
if
user_star_project
user_star_project
.
destroy
else
UsersStarProject
.
create!
(
project:
project
,
user:
self
)
end
end
end
def
manageable_namespaces
@manageable_namespaces
||=
[
namespace
]
+
owned_groups
+
masters_groups
...
...
app/services/git_push_service.rb
View file @
e4008bc4
...
...
@@ -79,7 +79,7 @@ class GitPushService
authors
=
Hash
.
new
do
|
hash
,
commit
|
email
=
commit
.
author_email
return
hash
[
email
]
if
hash
.
has_key?
(
email
)
next
hash
[
email
]
if
hash
.
has_key?
(
email
)
hash
[
email
]
=
commit_user
(
commit
)
end
...
...
app/services/labels/group_service.rb
0 → 100644
View file @
e4008bc4
module
Labels
class
GroupService
<
::
BaseService
def
initialize
(
project_labels
)
@project_labels
=
project_labels
.
group_by
(
&
:title
)
end
def
execute
build
(
@project_labels
)
end
def
label
(
title
)
if
title
group_label
=
@project_labels
[
title
].
group_by
(
&
:title
)
build
(
group_label
).
first
else
nil
end
end
private
def
build
(
label
)
label
.
map
{
|
title
,
labels
|
GroupLabel
.
new
(
title
,
labels
)
}
end
end
end
app/services/merge_requests/post_merge_service.rb
View file @
e4008bc4
...
...
@@ -6,6 +6,7 @@ module MergeRequests
#
class
PostMergeService
<
MergeRequests
::
BaseService
def
execute
(
merge_request
)
close_issues
(
merge_request
)
merge_request
.
mark_as_merged
create_merge_event
(
merge_request
,
current_user
)
create_note
(
merge_request
)
...
...
@@ -15,6 +16,15 @@ module MergeRequests
private
def
close_issues
(
merge_request
)
return
unless
merge_request
.
target_branch
==
project
.
default_branch
closed_issues
=
merge_request
.
closes_issues
(
current_user
)
closed_issues
.
each
do
|
issue
|
Issues
::
CloseService
.
new
(
project
,
current_user
,
{}).
execute
(
issue
,
merge_request
)
end
end
def
create_merge_event
(
merge_request
,
current_user
)
EventCreateService
.
new
.
merge_mr
(
merge_request
,
current_user
)
end
...
...
app/views/abuse_report_mailer/notify.html.haml
0 → 100644
View file @
e4008bc4
%p
#{
link_to
@abuse_report
.
user
.
name
,
user_url
(
@abuse_report
.
user
)
}
(@
#{
@abuse_report
.
user
.
username
}
) was reported for abuse by
#{
link_to
@abuse_report
.
reporter
.
name
,
user_url
(
@abuse_report
.
reporter
)
}
(@
#{
@abuse_report
.
reporter
.
username
}
).
%blockquote
=
@abuse_report
.
message
%p
=
link_to
"View details"
,
abuse_reports_url
app/views/abuse_report_mailer/notify.text.haml
0 → 100644
View file @
e4008bc4
#{
@abuse_report
.
user
.
name
}
(@
#{
@abuse_report
.
user
.
username
}
) was reported for abuse by
#{
@abuse_report
.
reporter
.
name
}
(@
#{
@abuse_report
.
reporter
.
username
}
).
\
>
#{
@abuse_report
.
message
}
\
View details:
#{
admin_abuse_reports_url
}
app/views/admin/application_settings/_form.html.haml
View file @
e4008bc4
...
...
@@ -47,6 +47,12 @@
=
f
.
label
:version_check_enabled
do
=
f
.
check_box
:version_check_enabled
Version check enabled
.form-group
=
f
.
label
:admin_notification_email
,
class:
'control-label col-sm-2'
.col-sm-10
=
f
.
text_field
:admin_notification_email
,
class:
'form-control'
.help-block
Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.
%fieldset
%legend
Account and Limit Settings
...
...
app/views/users/_profile.html.haml
→
app/views/
admin/
users/_profile.html.haml
View file @
e4008bc4
File moved
app/views/admin/users/show.html.haml
View file @
e4008bc4
...
...
@@ -14,7 +14,7 @@
%strong
=
link_to
user_path
(
@user
)
do
=
@user
.
username
=
render
'users/profile'
,
user:
@user
=
render
'
admin/
users/profile'
,
user:
@user
.panel.panel-default
.panel-heading
...
...
app/views/ci/projects/index.html.haml
0 → 100644
View file @
e4008bc4
.wiki
%h1
GitLab CI is now integrated in GitLab UI
%h2
For existing projects
%p
Check the following pages to find the CI status you're looking for:
%ul
%li
Projects page - shows CI status for each project.
%li
Project commits page - show CI status for each commit.
%h2
For new projects
%p
If you want to enable CI for a new project it is easy as adding
=
link_to
".gitlab-ci.yml"
,
"http://doc.gitlab.com/ce/ci/yaml/README.html"
file to your repository
app/views/events/_event_issue.atom.haml
View file @
e4008bc4
%div
{
xmlns:
"http://www.w3.org/1999/xhtml"
}
-
if
issue
.
description
.
present?
=
markdown
(
issue
.
description
,
xhtml:
true
,
reference_only_path:
false
,
project:
issue
.
project
)
=
markdown
(
issue
.
description
,
pipeline: :atom
,
project:
issue
.
project
)
app/views/events/_event_merge_request.atom.haml
View file @
e4008bc4
%div
{
xmlns:
"http://www.w3.org/1999/xhtml"
}
-
if
merge_request
.
description
.
present?
=
markdown
(
merge_request
.
description
,
xhtml:
true
,
reference_only_path:
false
,
project:
merge_request
.
project
)
=
markdown
(
merge_request
.
description
,
pipeline: :atom
,
project:
merge_request
.
project
)
app/views/events/_event_note.atom.haml
View file @
e4008bc4
%div
{
xmlns:
"http://www.w3.org/1999/xhtml"
}
=
markdown
(
note
.
note
,
xhtml:
true
,
reference_only_path:
false
,
project:
note
.
project
)
=
markdown
(
note
.
note
,
pipeline: :atom
,
project:
note
.
project
)
app/views/events/_event_push.atom.haml
View file @
e4008bc4
...
...
@@ -6,7 +6,7 @@
%i
at
=
commit
[
:timestamp
].
to_time
.
to_s
(
:short
)
%blockquote
=
markdown
(
escape_once
(
commit
[
:message
]),
xhtml:
true
,
reference_only_path:
false
,
project:
event
.
project
)
%blockquote
=
markdown
(
escape_once
(
commit
[
:message
]),
pipeline: :atom
,
project:
event
.
project
)
-
if
event
.
commits_count
>
15
%p
%i
...
...
app/views/layouts/notify.html.haml
View file @
e4008bc4
...
...
@@ -41,4 +41,8 @@
#{
link_to
"view it on GitLab"
,
@target_url
}
.
-
else
#{
link_to
"View it on GitLab"
,
@target_url
}
%br
You're receiving this email because of your account on
#{
link_to
Gitlab
.
config
.
gitlab
.
host
,
root_url
}
.
If you'd like to receive fewer emails, you can adjust your notification settings.
=
email_action
@target_url
app/views/notify/_note_message.html.haml
View file @
e4008bc4
%div
=
markdown
(
@note
.
note
,
reference_only_path:
false
)
=
markdown
(
@note
.
note
,
pipeline: :email
)
app/views/notify/new_issue_email.html.haml
View file @
e4008bc4
-
if
@issue
.
description
=
markdown
(
@issue
.
description
,
reference_only_path:
false
)
=
markdown
(
@issue
.
description
,
pipeline: :email
)
-
if
@issue
.
assignee_id
.
present?
%p
...
...
app/views/notify/new_merge_request_email.html.haml
View file @
e4008bc4
...
...
@@ -6,4 +6,4 @@
Assignee:
#{
@merge_request
.
author_name
}
→
#{
@merge_request
.
assignee_name
}
-
if
@merge_request
.
description
=
markdown
(
@merge_request
.
description
,
reference_only_path:
false
)
=
markdown
(
@merge_request
.
description
,
pipeline: :email
)
app/views/profiles/preferences/show.html.haml
View file @
e4008bc4
...
...
@@ -38,7 +38,7 @@
.col-sm-10
=
f
.
select
:layout
,
layout_choices
,
{},
class:
'form-control'
.help-block
Choose between fixed (max. 1200px) and fluid (100%) application layout
Choose between fixed (max. 1200px) and fluid (100%) application layout
.
.form-group
=
f
.
label
:dashboard
,
class:
'control-label'
do
Default Dashboard
...
...
@@ -52,6 +52,6 @@
.col-sm-10
=
f
.
select
:project_view
,
project_view_choices
,
{},
class:
'form-control'
.help-block
Choose what content you want to see
when visit project page
Choose what content you want to see
on a project's home page.
.panel-footer
=
f
.
submit
'Save'
,
class:
'btn btn-save'
app/views/projects/_activity.html.haml
View file @
e4008bc4
=
render
'projects/last_push'
.gray-content-block.activity-filter-block
-
if
current_user
.pull-right
...
...
app/views/projects/_files.html.haml
0 → 100644
View file @
e4008bc4
#tree-holder
.tree-holder.clearfix
.gray-content-block.second-block
=
render
'projects/tree/tree_header'
,
tree:
@tree
=
render
'projects/tree/tree_content'
,
tree:
@tree
app/views/projects/_readme.html.haml
View file @
e4008bc4
-
if
readme
=
@repository
.
readme
%article
.readme-holder
#README
.clearfix
.pull-right
-
if
can?
(
current_user
,
:push_code
,
@project
)
=
link_to
namespace_project_edit_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@repository
.
root_ref
,
readme
.
name
)),
class:
'light'
do
%i
.fa-align.fa.fa-pencil
.wiki
%article
.file-holder.readme-holder
.file-title
=
blob_icon
readme
.
mode
,
readme
.
name
=
link_to
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@repository
.
root_ref
,
readme
.
name
))
do
%strong
=
readme
.
name
.file-content.wiki
=
cache
(
readme_cache_key
)
do
=
render_readme
(
readme
)
-
else
...
...
app/views/projects/activity.html.haml
View file @
e4008bc4
-
page_title
"Activity"
-
header_title
project_title
(
@project
,
"Activity"
,
activity_project_path
(
@project
))
=
render
'projects/last_push'
=
render
'projects/activity'
app/views/projects/blob/_blob.html.haml
View file @
e4008bc4
%ul
.breadcrumb.repo-breadcrumb
.gray-content-block.top-block
.tree-ref-holder
=
render
'shared/ref_switcher'
,
destination:
'blob'
,
path:
@path
%ul
.breadcrumb.repo-breadcrumb
%li
%i
.fa.fa-angle-right
=
link_to
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
@ref
)
do
=
@project
.
path
-
tree_breadcrumbs
(
@tree
,
6
)
do
|
title
,
path
|
...
...
app/views/projects/blob/show.html.haml
View file @
e4008bc4
...
...
@@ -3,9 +3,6 @@
=
render
'projects/last_push'
%div
.tree-ref-holder
=
render
'shared/ref_switcher'
,
destination:
'blob'
,
path:
@path
%div
#tree-holder
.tree-holder
=
render
'blob'
,
blob:
@blob
...
...
app/views/projects/buttons/_notifications.html.haml
View file @
e4008bc4
-
return
unless
@membership
=
form_tag
profile_notifications_path
,
method: :put
,
remote:
true
,
class:
'inline'
,
id:
'notification-form'
do
-
case
@membership
-
when
ProjectMember
=
form_tag
profile_notifications_path
,
method: :put
,
remote:
true
,
class:
'inline'
,
id:
'notification-form'
do
=
hidden_field_tag
:notification_type
,
'project'
=
hidden_field_tag
:notification_id
,
@membership
.
id
=
hidden_field_tag
:notification_level
...
...
@@ -12,3 +12,9 @@
%ul
.dropdown-menu.dropdown-menu-right.project-home-dropdown
-
Notification
.
project_notification_levels
.
each
do
|
level
|
=
notification_list_item
(
level
,
@membership
)
-
when
GroupMember
.btn.btn-new.disabled.has_tooltip
{
title:
"To change the notification level, you need to be a member of the project itself, not only its group."
}
=
icon
(
'bell'
)
=
notification_label
(
@membership
)
=
icon
(
'angle-down'
)
app/views/projects/ci_services/index.html.haml
View file @
e4008bc4
...
...
@@ -6,7 +6,7 @@
%tr
%th
%th
Service
%th
Desription
%th
Des
c
ription
%th
Last edit
-
@services
.
sort_by
(
&
:title
).
each
do
|
service
|
%tr
...
...
app/views/projects/edit.html.haml
View file @
e4008bc4
...
...
@@ -189,6 +189,21 @@
-
else
.nothing-here-block
Only the project owner can transfer a project
-
if
@project
.
forked?
-
if
can?
(
current_user
,
:remove_fork_project
,
@project
)
=
form_for
([
@project
.
namespace
.
becomes
(
Namespace
),
@project
],
url:
remove_fork_namespace_project_path
(
@project
.
namespace
,
@project
),
method: :delete
,
remote:
true
,
html:
{
class:
'transfer-project form-horizontal'
})
do
|
f
|
.panel.panel-default.panel.panel-danger
.panel-heading
Remove fork relationship
.panel-body
%p
This will remove the fork relationship to source project
#{
link_to
@project
.
forked_from_project
.
name_with_namespace
,
project_path
(
@project
.
forked_from_project
)
}
.
%br
%strong
Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
=
button_to
'Remove fork relationship'
,
'#'
,
class:
"btn btn-remove js-confirm-danger"
,
data:
{
"confirm-danger-message"
=>
remove_fork_project_message
(
@project
)
}
-
else
.nothing-here-block
Only the project owner can remove the fork relationship.
-
if
can?
(
current_user
,
:remove_project
,
@project
)
.panel.panel-default.panel.panel-danger
.panel-heading
Remove project
...
...
@@ -201,7 +216,8 @@
=
button_to
'Remove project'
,
'#'
,
class:
"btn btn-remove js-confirm-danger"
,
data:
{
"confirm-danger-message"
=>
remove_project_message
(
@project
)
}
-
else
.nothing-here-block
Only project owner can remove a project
.nothing-here-block
Only the project owner can remove a project.
.save-project-loader.hide
.center
...
...
app/views/projects/imports/new.html.haml
View file @
e4008bc4
...
...
@@ -17,6 +17,6 @@
This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
%br
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
For SVN repositories, check
#{
link_to
"this migrating from SVN doc."
,
"http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"
}
For SVN repositories, check
#{
link_to
"this migrating from SVN doc."
,
"http://doc.gitlab.com/ce/workflow/
importing/
migrating_from_svn.html"
}
.form-actions
=
f
.
submit
'Start import'
,
class:
"btn btn-create"
,
tabindex:
4
app/views/projects/issues/_closed_by_box.html.haml
0 → 100644
View file @
e4008bc4
.issue-closed-by-widget
=
icon
(
'check'
)
This issue will be closed automatically when merge request
#{
gfm
(
merge_requests_sentence
(
@closed_by_merge_requests
.
sort
))
}
is accepted.
app/views/projects/issues/show.html.haml
View file @
e4008bc4
...
...
@@ -46,6 +46,7 @@
=
markdown
(
@issue
.
description
)
%textarea
.hidden.js-task-list-field
=
@issue
.
description
-
if
@closed_by_merge_requests
.
present?
=
render
'projects/issues/closed_by_box'
.issue-discussion
=
render
'projects/issues/discussion'
app/views/projects/merge_requests/widget/_heading.html.haml
View file @
e4008bc4
-
if
@merge_request
.
has_ci?
-
ci_commit
=
@merge_request
.
source_project
.
ci_commit
(
@merge_request
.
source_sha
)
-
if
ci_commit
-
ci_commit
=
@merge_request
.
source_project
.
ci_commit
(
@merge_request
.
source_sha
)
-
if
ci_commit
-
status
=
ci_commit
.
status
.mr-widget-heading
.ci_widget
{
class:
"ci-#{status}"
}
...
...
@@ -10,7 +9,7 @@
%span
.ci-coverage
=
link_to
"View build details"
,
ci_status_path
(
ci_commit
)
-
else
-
elsif
@merge_request
.
has_ci?
-
# Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX
-
# Remove in later versions when services like Jenkins will set CI status via Commit status API
.mr-widget-heading
...
...
app/views/projects/remove_fork.js.haml
0 → 100644
View file @
e4008bc4
:plain
location.href = "
#{
edit_namespace_project_path
(
@project
.
namespace
,
@project
)
}
";
app/views/projects/show.html.haml
View file @
e4008bc4
...
...
@@ -7,8 +7,7 @@
=
render
'shared/no_ssh'
=
render
'shared/no_password'
-
if
prefer_readme?
=
render
'projects/last_push'
=
render
'projects/last_push'
=
render
"home_panel"
...
...
@@ -28,7 +27,7 @@
=
link_to
project_files_path
(
@project
)
do
=
repository_size
-
if
!
prefer_readme?
&&
@repository
.
readme
-
if
default_project_view
!=
'readme'
&&
@repository
.
readme
%li
=
link_to
'Readme'
,
readme_path
(
@project
)
...
...
@@ -68,14 +67,8 @@
.content-block.second-block.white
=
render
'projects/last_commit'
,
commit:
@repository
.
commit
,
project:
@project
%section
-
if
prefer_readme?
.project-show-readme
=
render
'projects/readme'
-
else
.project-show-activity
=
render
'projects/activity'
%div
{
class:
"project-show-#{default_project_view}"
}
=
render
default_project_view
-
if
current_user
-
access
=
user_max_access_in_project
(
current_user
,
@project
)
...
...
app/views/projects/tree/_blob_item.html.haml
View file @
e4008bc4
...
...
@@ -4,5 +4,5 @@
%span
.str-truncated
=
link_to
blob_item
.
name
,
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@id
||
@commit
.
id
,
blob_item
.
name
))
%td
.tree_time_ago.cgray
=
render
'spinner'
=
render
'
projects/tree/
spinner'
%td
.hidden-xs.tree_commit
app/views/projects/tree/_readme.html.haml
View file @
e4008bc4
%article
.file-holder.readme-holder
#README
%article
.file-holder.readme-holder
.file-title
=
link_to
'#README'
do
=
blob_icon
readme
.
mode
,
readme
.
name
=
link_to
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@repository
.
root_ref
,
readme
.
name
))
do
%strong
%i
.fa.fa-file
=
readme
.
name
.file-content.wiki
=
render_readme
(
readme
)
app/views/projects/tree/_tree.html.haml
→
app/views/projects/tree/_tree
_content
.html.haml
View file @
e4008bc4
.gray-content-block
%ul
.breadcrumb.repo-breadcrumb
%li
=
link_to
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
@ref
)
do
=
@project
.
path
-
tree_breadcrumbs
(
tree
,
6
)
do
|
title
,
path
|
%li
-
if
path
=
link_to
truncate
(
title
,
length:
40
),
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
path
)
-
else
=
link_to
title
,
'#'
-
if
allowed_tree_edit?
%li
%span
.dropdown
%a
.dropdown-toggle.btn.add-to-tree
{
href:
'#'
,
"data-toggle"
=>
"dropdown"
}
=
icon
(
'plus'
)
%ul
.dropdown-menu
%li
=
link_to
namespace_project_new_blob_path
(
@project
.
namespace
,
@project
,
@id
),
title:
'Create file'
,
id:
'new-file-link'
do
=
icon
(
'pencil fw'
)
Create file
%li
=
link_to
'#modal-upload-blob'
,
{
'data-target'
=>
'#modal-upload-blob'
,
'data-toggle'
=>
'modal'
}
do
=
icon
(
'file fw'
)
Upload file
%li
.divider
%li
=
link_to
'#modal-create-new-dir'
,
{
'data-target'
=>
'#modal-create-new-dir'
,
'data-toggle'
=>
'modal'
}
do
=
icon
(
'folder fw'
)
New directory
%div
#tree-content-holder
.tree-content-holder
%div
.tree-content-holder
.tree-table-holder
%table
.table
#tree-slider
{
class:
"table_#{@hex_path} tree-table table-striped"
}
%thead
...
...
@@ -60,8 +29,6 @@
-
if
tree
.
readme
=
render
"projects/tree/readme"
,
readme:
tree
.
readme
%div
.tree_progress
-
if
allowed_tree_edit?
=
render
'projects/blob/upload'
,
title:
'Upload'
,
placeholder:
'Upload new file'
,
button_title:
'Upload file'
,
form_path:
namespace_project_create_blob_path
(
@project
.
namespace
,
@project
,
@id
),
method: :post
=
render
'projects/blob/new_dir'
...
...
app/views/projects/tree/_tree_header.html.haml
0 → 100644
View file @
e4008bc4
.tree-ref-holder
=
render
'shared/ref_switcher'
,
destination:
'tree'
,
path:
@path
%ul
.breadcrumb.repo-breadcrumb
%li
=
link_to
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
@ref
)
do
=
@project
.
path
-
tree_breadcrumbs
(
tree
,
6
)
do
|
title
,
path
|
%li
-
if
path
=
link_to
truncate
(
title
,
length:
40
),
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
path
)
-
else
=
link_to
title
,
'#'
-
if
allowed_tree_edit?
%li
%span
.dropdown
%a
.dropdown-toggle.btn.add-to-tree
{
href:
'#'
,
"data-toggle"
=>
"dropdown"
}
=
icon
(
'plus'
)
%ul
.dropdown-menu
%li
=
link_to
namespace_project_new_blob_path
(
@project
.
namespace
,
@project
,
@id
),
title:
'Create file'
,
id:
'new-file-link'
do
=
icon
(
'pencil fw'
)
Create file
%li
=
link_to
'#modal-upload-blob'
,
{
'data-target'
=>
'#modal-upload-blob'
,
'data-toggle'
=>
'modal'
}
do
=
icon
(
'file fw'
)
Upload file
%li
.divider
%li
=
link_to
'#modal-create-new-dir'
,
{
'data-target'
=>
'#modal-create-new-dir'
,
'data-toggle'
=>
'modal'
}
do
=
icon
(
'folder fw'
)
New directory
app/views/projects/tree/_tree_item.html.haml
View file @
e4008bc4
...
...
@@ -5,5 +5,5 @@
-
path
=
flatten_tree
(
tree_item
)
=
link_to
path
,
namespace_project_tree_path
(
@project
.
namespace
,
@project
,
tree_join
(
@id
||
@commit
.
id
,
path
))
%td
.tree_time_ago.cgray
=
render
'spinner'
=
render
'
projects/tree/
spinner'
%td
.hidden-xs.tree_commit
app/views/projects/tree/show.html.haml
View file @
e4008bc4
...
...
@@ -6,12 +6,12 @@
=
render
'projects/last_push'
.tree-ref-holder
=
render
'shared/ref_switcher'
,
destination:
'tree'
,
path:
@path
-
if
can?
current_user
,
:download_code
,
@project
.tree-download-holder
=
render
'projects/repositories/download_archive'
,
ref:
@ref
,
btn_class:
'btn-group pull-right hidden-xs hidden-sm'
,
split_button:
true
#tree-holder
.tree-holder.clearfix
=
render
"tree"
,
tree:
@tree
.gray-content-block.top-block
=
render
'projects/tree/tree_header'
,
tree:
@tree
=
render
'projects/tree/tree_content'
,
tree:
@tree
app/views/shared/_clone_panel.html.haml
View file @
e4008bc4
...
...
@@ -6,7 +6,7 @@
type:
'button'
,
|
class:
"btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }"
,
|
:"data-clone"
=>
project
.
ssh_url_to_repo
,
|
:"data-title"
=>
"Add an SSH key to your profile<br> to pull or push via SSH"
,
:"data-title"
=>
"Add an SSH key to your profile<br> to pull or push via SSH
.
"
,
:"data-html"
=>
"true"
,
:"data-container"
=>
"body"
}
SSH
...
...
@@ -15,7 +15,7 @@
type:
'button'
,
|
class:
"btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }"
,
|
:"data-clone"
=>
project
.
http_url_to_repo
,
|
:"data-title"
=>
"Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}"
,
:"data-title"
=>
"Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}
.
"
,
:"data-html"
=>
"true"
,
:"data-container"
=>
"body"
}
=
gitlab_config
.
protocol
.
upcase
...
...
app/views/shared/issuable/_filter.html.haml
View file @
e4008bc4
...
...
@@ -42,9 +42,8 @@
class:
'select2 trigger-submit'
,
include_blank:
true
,
data:
{
placeholder:
'Milestone'
})
-
if
@project
.filter-item.inline.labels-filter
=
select_tag
(
'label_name'
,
project_labels_options
(
@project
)
,
=
select_tag
(
'label_name'
,
projects_labels_options
,
class:
'select2 trigger-submit'
,
include_blank:
true
,
data:
{
placeholder:
'Label'
})
...
...
app/views/users/calendar.html.haml
View file @
e4008bc4
%h4
Contributions calendar
.pull-right
%small
Issues, merge requests and push events
#cal-heatmap
.calendar
:javascript
new
Calendar
(
...
...
@@ -10,3 +6,5 @@
#{
@starting_month
}
,
'
#{
user_calendar_activities_path
}
'
);
.calendar-hint
Summary of issues, merge requests and push events
app/views/users/show.html.haml
View file @
e4008bc4
...
...
@@ -6,47 +6,72 @@
=
render
'shared/show_aside'
.row
%section
.col-md-7
.header-with-avatar
.cover-block
.avatar-holder
=
link_to
avatar_icon
(
@user
,
400
),
target:
'_blank'
do
=
image_tag
avatar_icon
(
@user
,
90
),
class:
"avatar avatar-tile
s90"
,
alt:
''
%h3
=
image_tag
avatar_icon
(
@user
,
90
),
class:
"avatar
s90"
,
alt:
''
.cover-title
=
@user
.
name
.cover-desc
%span
@
#{
@user
.
username
}
.
-
if
@user
.
bio
.
present?
%span
#{
@user
.
bio
}
.
%span
Member since
#{
@user
.
created_at
.
stamp
(
"Aug 21, 2011"
)
}
.cover-desc
-
unless
@user
.
public_email
.
blank?
=
link_to
@user
.
public_email
,
"mailto:
#{
@user
.
public_email
}
"
-
unless
@user
.
skype
.
blank?
·
=
link_to
"Skype"
,
"skype:
#{
@user
.
skype
}
"
-
unless
@user
.
linkedin
.
blank?
·
=
link_to
"LinkedIn"
,
"http://www.linkedin.com/in/
#{
@user
.
linkedin
}
"
-
unless
@user
.
twitter
.
blank?
·
=
link_to
"Twitter"
,
"http://www.twitter.com/
#{
@user
.
twitter
}
"
-
unless
@user
.
website_url
.
blank?
·
=
link_to
@user
.
short_website_url
,
@user
.
full_website_url
-
unless
@user
.
location
.
blank?
·
=
@user
.
location
.cover-controls
-
if
@user
==
current_user
.pull-right.hidden-xs
=
link_to
profile_path
,
class:
'btn btn-sm'
do
=
icon
(
'user'
)
Profile settings
=
link_to
profile_path
,
class:
'btn btn-gray'
do
=
icon
(
'pencil'
)
-
elsif
current_user
.report_abuse.pull-right
.report-abuse
-
if
@user
.
abuse_report
%span
#report_abuse_btn
.light.btn.btn-sm.btn-close
{
title:
'Already reported for abuse'
,
data:
{
toggle:
'tooltip'
,
placement:
'right'
,
container:
'body'
}}
%button
.btn.btn-danger
{
title:
'Already reported for abuse'
,
data:
{
toggle:
'tooltip'
,
placement:
'left'
,
container:
'body'
}}
=
icon
(
'exclamation-circle'
)
-
else
%a
.light.btn.btn-sm
{
href:
new_abuse_report_path
(
user_id:
@user
.
id
),
title:
'Report abuse'
,
data:
{
toggle:
'tooltip'
,
placement:
'right'
,
container:
'body'
}}
=
link_to
new_abuse_report_path
(
user_id:
@user
.
id
),
class:
'btn btn-gray'
,
title:
'Report abuse'
,
data:
{
toggle:
'tooltip'
,
placement:
'left'
,
container:
'body'
}
do
=
icon
(
'exclamation-circle'
)
.username
@
#{
@user
.
username
}
.description
-
if
@user
.
bio
.
present?
=
@user
.
bio
.gray-content-block.second-block
.user-calendar
%h4
.center.light
%i
.fa.fa-spinner.fa-spin
.user-calendar-activities
.clearfix
.row.prepend-top-20
%section
.col-md-7
-
if
@groups
.
any?
.prepend-top-20
%h4
Groups
=
render
'groups'
,
groups:
@groups
%hr
.hidden-xs
.user-calendar
%h4
.center.light
%i
.fa.fa-spinner.fa-spin
.user-calendar-activities
%hr
%h4
User Activity
...
...
@@ -59,7 +84,6 @@
.content_list
=
spinner
%aside
.col-md-5
=
render
'profile'
,
user:
@user
=
render
'projects'
,
projects:
@projects
,
contributed_projects:
@contributed_projects
:coffeescript
...
...
config/routes.rb
View file @
e4008bc4
...
...
@@ -378,6 +378,7 @@ Gitlab::Application.routes.draw do
[
:new
,
:create
,
:index
],
path:
"/"
)
do
member
do
put
:transfer
delete
:remove_fork
post
:archive
post
:unarchive
post
:toggle_star
...
...
db/fixtures/development/05_users.rb
View file @
e4008bc4
Gitlab
::
Seeder
.
quiet
do
(
2
..
20
).
each
do
|
i
|
20
.
times
do
|
i
|
begin
User
.
create!
(
username:
FFaker
::
Internet
.
user_name
,
...
...
@@ -15,7 +15,7 @@ Gitlab::Seeder.quiet do
end
end
(
1
..
5
).
each
do
|
i
|
5
.
times
do
|
i
|
begin
User
.
create!
(
username:
"user
#{
i
}
"
,
...
...
db/fixtures/development/07_milestones.rb
View file @
e4008bc4
Gitlab
::
Seeder
.
quiet
do
Project
.
all
.
each
do
|
project
|
(
1
..
5
).
each
do
|
i
|
5
.
times
do
|
i
|
milestone_params
=
{
title:
"v
#{
i
}
.0"
,
description:
FFaker
::
Lorem
.
sentence
,
...
...
db/fixtures/development/09_issues.rb
View file @
e4008bc4
Gitlab
::
Seeder
.
quiet
do
Project
.
all
.
each
do
|
project
|
(
1
..
10
).
each
do
|
i
|
10
.
times
do
issue_params
=
{
title:
FFaker
::
Lorem
.
sentence
(
6
),
description:
FFaker
::
Lorem
.
sentence
,
...
...
db/fixtures/development/12_snippets.rb
View file @
e4008bc4
...
...
@@ -22,7 +22,7 @@ class Member < ActiveRecord::Base
end
eos
(
1
..
50
).
each
do
|
i
|
50
.
times
do
|
i
|
user
=
User
.
all
.
sample
PersonalSnippet
.
seed
(
:id
,
[{
...
...
db/migrate/20151008143519_add_admin_notification_email_setting.rb
0 → 100644
View file @
e4008bc4
class
AddAdminNotificationEmailSetting
<
ActiveRecord
::
Migration
def
change
add_column
:application_settings
,
:admin_notification_email
,
:string
end
end
db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb
0 → 100644
View file @
e4008bc4
class
AddCiBuildsAndProjectsIndexes
<
ActiveRecord
::
Migration
def
change
add_index
:ci_projects
,
:gitlab_id
add_index
:ci_projects
,
:shared_runners_enabled
add_index
:ci_builds
,
:type
add_index
:ci_builds
,
:status
end
end
db/migrate/20151016195706_add_notes_line_code_index.rb
0 → 100644
View file @
e4008bc4
class
AddNotesLineCodeIndex
<
ActiveRecord
::
Migration
def
change
add_index
:notes
,
:line_code
end
end
db/schema.rb
View file @
e4008bc4
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201510161
31433
)
do
ActiveRecord
::
Schema
.
define
(
version:
201510161
95706
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -46,6 +46,7 @@ ActiveRecord::Schema.define(version: 20151016131433) do
t
.
integer
"session_expire_delay"
,
default:
10080
,
null:
false
t
.
text
"import_sources"
t
.
text
"help_page_text"
t
.
string
"admin_notification_email"
end
create_table
"audit_events"
,
force:
true
do
|
t
|
...
...
@@ -115,6 +116,8 @@ ActiveRecord::Schema.define(version: 20151016131433) do
add_index
"ci_builds"
,
[
"project_id"
,
"commit_id"
],
name:
"index_ci_builds_on_project_id_and_commit_id"
,
using: :btree
add_index
"ci_builds"
,
[
"project_id"
],
name:
"index_ci_builds_on_project_id"
,
using: :btree
add_index
"ci_builds"
,
[
"runner_id"
],
name:
"index_ci_builds_on_runner_id"
,
using: :btree
add_index
"ci_builds"
,
[
"status"
],
name:
"index_ci_builds_on_status"
,
using: :btree
add_index
"ci_builds"
,
[
"type"
],
name:
"index_ci_builds_on_type"
,
using: :btree
create_table
"ci_commits"
,
force:
true
do
|
t
|
t
.
integer
"project_id"
...
...
@@ -190,6 +193,9 @@ ActiveRecord::Schema.define(version: 20151016131433) do
t
.
text
"generated_yaml_config"
end
add_index
"ci_projects"
,
[
"gitlab_id"
],
name:
"index_ci_projects_on_gitlab_id"
,
using: :btree
add_index
"ci_projects"
,
[
"shared_runners_enabled"
],
name:
"index_ci_projects_on_shared_runners_enabled"
,
using: :btree
create_table
"ci_runner_projects"
,
force:
true
do
|
t
|
t
.
integer
"runner_id"
,
null:
false
t
.
integer
"project_id"
,
null:
false
...
...
@@ -530,6 +536,7 @@ ActiveRecord::Schema.define(version: 20151016131433) do
add_index
"notes"
,
[
"commit_id"
],
name:
"index_notes_on_commit_id"
,
using: :btree
add_index
"notes"
,
[
"created_at"
,
"id"
],
name:
"index_notes_on_created_at_and_id"
,
using: :btree
add_index
"notes"
,
[
"created_at"
],
name:
"index_notes_on_created_at"
,
using: :btree
add_index
"notes"
,
[
"line_code"
],
name:
"index_notes_on_line_code"
,
using: :btree
add_index
"notes"
,
[
"noteable_id"
,
"noteable_type"
],
name:
"index_notes_on_noteable_id_and_noteable_type"
,
using: :btree
add_index
"notes"
,
[
"noteable_type"
],
name:
"index_notes_on_noteable_type"
,
using: :btree
add_index
"notes"
,
[
"project_id"
,
"noteable_type"
],
name:
"index_notes_on_project_id_and_noteable_type"
,
using: :btree
...
...
doc/install/installation.md
View file @
e4008bc4
...
...
@@ -325,6 +325,7 @@ GitLab Shell is an SSH access and repository management software developed speci
cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-git-http-server.git
cd gitlab-git-http-server
sudo -u git -H git checkout 0.3.0
sudo -u git -H make
### Initialize Database and Activate Advanced Features
...
...
doc/update/7.14-to-8.0.md
View file @
e4008bc4
...
...
@@ -84,6 +84,7 @@ Now we download `gitlab-git-http-server` and install it in `/home/git/gitlab-git
cd
/home/git
sudo
-u
git
-H
git clone https://gitlab.com/gitlab-org/gitlab-git-http-server.git
cd
gitlab-git-http-server
sudo
-u
git
-H
git checkout 0.2.14
sudo
-u
git
-H
make
```
...
...
features/steps/abuse_reports.rb
View file @
e4008bc4
...
...
@@ -23,7 +23,7 @@ class Spinach::Features::AbuseReports < Spinach::FeatureSteps
end
step
'I should see a red "Report abuse" button'
do
expect
(
find
(
:css
,
'.report_abuse'
)).
to
have_selector
(
:css
,
'span.btn-close'
)
expect
(
page
).
to
have_button
(
"Already reported for abuse"
)
end
def
user_mike
...
...
features/steps/project/project.rb
View file @
e4008bc4
...
...
@@ -86,13 +86,13 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end
step
'I should see project "Forum" README'
do
page
.
within
(
'
#README
'
)
do
page
.
within
(
'
.readme-holder
'
)
do
expect
(
page
).
to
have_content
'Sample repo for testing gitlab features'
end
end
step
'I should see project "Shop" README'
do
page
.
within
(
'
#README
'
)
do
page
.
within
(
'
.readme-holder
'
)
do
expect
(
page
).
to
have_content
'testme'
end
end
...
...
lib/api/projects.rb
View file @
e4008bc4
...
...
@@ -246,8 +246,8 @@ module API
# Example Request:
# DELETE /projects/:id/fork
delete
":id/fork"
do
auth
enticated_as_admin!
unless
user_project
.
forked_project_link
.
nil
?
auth
orize!
:remove_fork_project
,
user_project
if
user_project
.
forked
?
user_project
.
forked_project_link
.
destroy
end
end
...
...
lib/gitlab/markdown.rb
View file @
e4008bc4
...
...
@@ -7,6 +7,14 @@ module Gitlab
module
Markdown
# Convert a Markdown String into an HTML-safe String of HTML
#
# Note that while the returned HTML will have been sanitized of dangerous
# HTML, it may post a risk of information leakage if it's not also passed
# through `post_process`.
#
# Also note that the returned String is always HTML, not XHTML. Views
# requiring XHTML, such as Atom feeds, need to call `post_process` on the
# result, providing the appropriate `pipeline` option.
#
# markdown - Markdown String
# context - Hash of context options passed to our HTML Pipeline
#
...
...
@@ -31,6 +39,33 @@ module Gitlab
renderer
.
render
(
markdown
)
end
# Perform post-processing on an HTML String
#
# This method is used to perform state-dependent changes to a String of
# HTML, such as removing references that the current user doesn't have
# permission to make (`RedactorFilter`).
#
# html - String to process
# options - Hash of options to customize output
# :pipeline - Symbol pipeline type
# :project - Project
# :user - User object
#
# Returns an HTML-safe String
def
self
.
post_process
(
html
,
options
)
context
=
{
project:
options
[
:project
],
current_user:
options
[
:user
]
}
doc
=
post_processor
.
to_document
(
html
,
context
)
if
options
[
:pipeline
]
==
:atom
doc
.
to_html
(
save_with:
Nokogiri
::
XML
::
Node
::
SaveOptions
::
AS_XHTML
)
else
doc
.
to_html
end
.
html_safe
end
# Provide autoload paths for filters to prevent a circular dependency error
autoload
:AutolinkFilter
,
'gitlab/markdown/autolink_filter'
autoload
:CommitRangeReferenceFilter
,
'gitlab/markdown/commit_range_reference_filter'
...
...
@@ -41,6 +76,7 @@ module Gitlab
autoload
:IssueReferenceFilter
,
'gitlab/markdown/issue_reference_filter'
autoload
:LabelReferenceFilter
,
'gitlab/markdown/label_reference_filter'
autoload
:MergeRequestReferenceFilter
,
'gitlab/markdown/merge_request_reference_filter'
autoload
:RedactorFilter
,
'gitlab/markdown/redactor_filter'
autoload
:RelativeLinkFilter
,
'gitlab/markdown/relative_link_filter'
autoload
:SanitizationFilter
,
'gitlab/markdown/sanitization_filter'
autoload
:SnippetReferenceFilter
,
'gitlab/markdown/snippet_reference_filter'
...
...
@@ -50,26 +86,20 @@ module Gitlab
autoload
:UserReferenceFilter
,
'gitlab/markdown/user_reference_filter'
autoload
:UploadLinkFilter
,
'gitlab/markdown/upload_link_filter'
# Public: Parse the provided
text
with GitLab-Flavored Markdown
# Public: Parse the provided
HTML
with GitLab-Flavored Markdown
#
# text - the source text
# options - A Hash of options used to customize output (default: {}):
# :xhtml - output XHTML instead of HTML
# :reference_only_path - Use relative path for reference links
def
self
.
gfm
(
text
,
options
=
{})
return
text
if
text
.
nil?
# Duplicate the string so we don't alter the original, then call to_str
# to cast it back to a String instead of a SafeBuffer. This is required
# for gsub calls to work as we need them to.
text
=
text
.
dup
.
to_str
options
.
reverse_merge!
(
xhtml:
false
,
reference_only_path:
true
,
project:
options
[
:project
],
current_user:
options
[
:current_user
]
)
# html - HTML String
# options - A Hash of options used to customize output (default: {})
# :no_header_anchors - Disable header anchors in TableOfContentsFilter
# :path - Current path String
# :pipeline - Symbol pipeline type
# :project - Current Project object
# :project_wiki - Current ProjectWiki object
# :ref - Current ref String
#
# Returns an HTML-safe String
def
self
.
gfm
(
html
,
options
=
{})
return
''
unless
html
.
present?
@pipeline
||=
HTML
::
Pipeline
.
new
(
filters
)
...
...
@@ -78,41 +108,36 @@ module Gitlab
pipeline:
options
[
:pipeline
],
# EmojiFilter
asset_root:
Gitlab
.
config
.
gitlab
.
base_url
,
asset_host:
Gitlab
::
Application
.
config
.
asset_host
,
# TableOfContentsFilter
no_header_anchors:
options
[
:no_header_anchors
],
asset_root:
Gitlab
.
config
.
gitlab
.
base_url
,
# ReferenceFilter
current_user:
options
[
:current_user
],
only_path:
options
[
:reference_only_path
],
only_path:
only_path_pipeline?
(
options
[
:pipeline
]),
project:
options
[
:project
],
# RelativeLinkFilter
project_wiki:
options
[
:project_wiki
],
ref:
options
[
:ref
],
requested_path:
options
[
:path
],
project_wiki:
options
[
:project_wiki
]
}
result
=
@pipeline
.
call
(
text
,
context
)
save_options
=
0
if
options
[
:xhtml
]
save_options
|=
Nokogiri
::
XML
::
Node
::
SaveOptions
::
AS_XHTML
end
text
=
result
[
:output
].
to_html
(
save_with:
save_options
)
# TableOfContentsFilter
no_header_anchors:
options
[
:no_header_anchors
]
}
text
.
html_safe
@pipeline
.
to_html
(
html
,
context
)
.
html_safe
end
private
def
self
.
renderer
@markdown
||=
begin
renderer
=
Redcarpet
::
Render
::
HTML
.
new
Redcarpet
::
Markdown
.
new
(
renderer
,
redcarpet_options
)
# Check if a pipeline enables the `only_path` context option
#
# Returns Boolean
def
self
.
only_path_pipeline?
(
pipeline
)
case
pipeline
when
:atom
,
:email
false
else
true
end
end
...
...
@@ -130,6 +155,17 @@ module Gitlab
}.
freeze
end
def
self
.
renderer
@markdown
||=
begin
renderer
=
Redcarpet
::
Render
::
HTML
.
new
Redcarpet
::
Markdown
.
new
(
renderer
,
redcarpet_options
)
end
end
def
self
.
post_processor
@post_processor
||=
HTML
::
Pipeline
.
new
([
Gitlab
::
Markdown
::
RedactorFilter
])
end
# Filters used in our pipeline
#
# SanitizationFilter should come first so that all generated reference HTML
...
...
lib/gitlab/markdown/commit_range_reference_filter.rb
View file @
e4008bc4
...
...
@@ -26,6 +26,18 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
project
=
Project
.
find
(
node
.
attr
(
"data-project"
))
rescue
nil
return
unless
project
id
=
node
.
attr
(
"data-commit-range"
)
range
=
CommitRange
.
new
(
id
,
project
)
return
unless
range
.
valid_commits?
{
commit_range:
range
}
end
def
initialize
(
*
args
)
super
...
...
@@ -53,13 +65,11 @@ module Gitlab
range
=
CommitRange
.
new
(
id
,
project
)
if
range
.
valid_commits?
push_result
(
:commit_range
,
range
)
url
=
url_for_commit_range
(
project
,
range
)
title
=
range
.
reference_title
klass
=
reference_class
(
:commit_range
)
data
=
data_attribute
(
project
.
id
)
data
=
data_attribute
(
project
:
project
.
id
,
commit_range:
id
)
project_ref
+=
'@'
if
project_ref
...
...
lib/gitlab/markdown/commit_reference_filter.rb
View file @
e4008bc4
...
...
@@ -26,6 +26,18 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
project
=
Project
.
find
(
node
.
attr
(
"data-project"
))
rescue
nil
return
unless
project
id
=
node
.
attr
(
"data-commit"
)
commit
=
commit_from_ref
(
project
,
id
)
return
unless
commit
{
commit:
commit
}
end
def
call
replace_text_nodes_matching
(
Commit
.
reference_pattern
)
do
|
content
|
commit_link_filter
(
content
)
...
...
@@ -39,17 +51,15 @@ module Gitlab
# Returns a String with commit references replaced with links. All links
# have `gfm` and `gfm-commit` class names attached for styling.
def
commit_link_filter
(
text
)
self
.
class
.
references_in
(
text
)
do
|
match
,
commit_ref
,
project_ref
|
self
.
class
.
references_in
(
text
)
do
|
match
,
id
,
project_ref
|
project
=
self
.
project_from_ref
(
project_ref
)
if
commit
=
commit_from_ref
(
project
,
commit_ref
)
push_result
(
:commit
,
commit
)
if
commit
=
self
.
class
.
commit_from_ref
(
project
,
id
)
url
=
url_for_commit
(
project
,
commit
)
title
=
escape_once
(
commit
.
link_title
)
klass
=
reference_class
(
:commit
)
data
=
data_attribute
(
project
.
id
)
data
=
data_attribute
(
project
:
project
.
id
,
commit:
id
)
project_ref
+=
'@'
if
project_ref
...
...
@@ -62,9 +72,9 @@ module Gitlab
end
end
def
commit_from_ref
(
project
,
commit_ref
)
def
self
.
commit_from_ref
(
project
,
id
)
if
project
&&
project
.
valid_repo?
project
.
commit
(
commit_ref
)
project
.
commit
(
id
)
end
end
...
...
lib/gitlab/markdown/cross_project_reference.rb
View file @
e4008bc4
...
...
@@ -13,18 +13,11 @@ module Gitlab
#
# ref - String reference.
#
# Returns a Project, or nil if the reference can't be
accesse
d
# Returns a Project, or nil if the reference can't be
foun
d
def
project_from_ref
(
ref
)
return
context
[
:project
]
unless
ref
other
=
Project
.
find_with_namespace
(
ref
)
return
nil
unless
other
&&
user_can_reference_project?
(
other
)
other
end
def
user_can_reference_project?
(
project
,
user
=
context
[
:current_user
])
Ability
.
abilities
.
allowed?
(
user
,
:read_project
,
project
)
Project
.
find_with_namespace
(
ref
)
end
end
end
...
...
lib/gitlab/markdown/external_issue_reference_filter.rb
View file @
e4008bc4
...
...
@@ -47,8 +47,9 @@ module Gitlab
title
=
escape_once
(
"Issue in
#{
project
.
external_issue_tracker
.
title
}
"
)
klass
=
reference_class
(
:issue
)
data
=
data_attribute
(
project:
project
.
id
)
%(<a href="#{url}"
%(<a href="#{url}"
#{data}
title="#{title}"
class="#{klass}">#{match}</a>)
end
...
...
lib/gitlab/markdown/issue_reference_filter.rb
View file @
e4008bc4
...
...
@@ -27,6 +27,10 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
{
issue:
LazyReference
.
new
(
Issue
,
node
.
attr
(
"data-issue"
))
}
end
def
call
replace_text_nodes_matching
(
Issue
.
reference_pattern
)
do
|
content
|
issue_link_filter
(
content
)
...
...
@@ -45,13 +49,11 @@ module Gitlab
project
=
self
.
project_from_ref
(
project_ref
)
if
project
&&
issue
=
project
.
get_issue
(
id
)
push_result
(
:issue
,
issue
)
url
=
url_for_issue
(
id
,
project
,
only_path:
context
[
:only_path
])
title
=
escape_once
(
"Issue:
#{
issue
.
title
}
"
)
klass
=
reference_class
(
:issue
)
data
=
data_attribute
(
project
.
id
)
data
=
data_attribute
(
project
:
project
.
id
,
issue:
issue
.
id
)
%(<a href="#{url}" #{data}
title="#{title}"
...
...
lib/gitlab/markdown/label_reference_filter.rb
View file @
e4008bc4
...
...
@@ -22,6 +22,10 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
{
label:
LazyReference
.
new
(
Label
,
node
.
attr
(
"data-label"
))
}
end
def
call
replace_text_nodes_matching
(
Label
.
reference_pattern
)
do
|
content
|
label_link_filter
(
content
)
...
...
@@ -41,11 +45,9 @@ module Gitlab
params
=
label_params
(
id
,
name
)
if
label
=
project
.
labels
.
find_by
(
params
)
push_result
(
:label
,
label
)
url
=
url_for_label
(
project
,
label
)
klass
=
reference_class
(
:label
)
data
=
data_attribute
(
project
.
id
)
data
=
data_attribute
(
project
:
project
.
id
,
label:
label
.
id
)
%(<a href="#{url}" #{data}
class="#{klass}">#{render_colored_label(label)}</a>)
...
...
lib/gitlab/markdown/merge_request_reference_filter.rb
View file @
e4008bc4
...
...
@@ -27,6 +27,10 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
{
merge_request:
LazyReference
.
new
(
MergeRequest
,
node
.
attr
(
"data-merge-request"
))
}
end
def
call
replace_text_nodes_matching
(
MergeRequest
.
reference_pattern
)
do
|
content
|
merge_request_link_filter
(
content
)
...
...
@@ -45,11 +49,9 @@ module Gitlab
project
=
self
.
project_from_ref
(
project_ref
)
if
project
&&
merge_request
=
project
.
merge_requests
.
find_by
(
iid:
id
)
push_result
(
:merge_request
,
merge_request
)
title
=
escape_once
(
"Merge Request:
#{
merge_request
.
title
}
"
)
klass
=
reference_class
(
:merge_request
)
data
=
data_attribute
(
project
.
id
)
data
=
data_attribute
(
project
:
project
.
id
,
merge_request:
merge_request
.
id
)
url
=
url_for_merge_request
(
merge_request
,
project
)
...
...
lib/gitlab/markdown/redactor_filter.rb
0 → 100644
View file @
e4008bc4
require
'gitlab/markdown'
require
'html/pipeline/filter'
module
Gitlab
module
Markdown
# HTML filter that removes references to records that the current user does
# not have permission to view.
#
# Expected to be run in its own post-processing pipeline.
#
class
RedactorFilter
<
HTML
::
Pipeline
::
Filter
def
call
doc
.
css
(
'a.gfm'
).
each
do
|
node
|
unless
user_can_reference?
(
node
)
node
.
replace
(
node
.
text
)
end
end
doc
end
private
def
user_can_reference?
(
node
)
if
node
.
has_attribute?
(
'data-reference-filter'
)
reference_type
=
node
.
attr
(
'data-reference-filter'
)
reference_filter
=
reference_type
.
constantize
reference_filter
.
user_can_reference?
(
current_user
,
node
,
context
)
else
true
end
end
def
current_user
context
[
:current_user
]
end
end
end
end
lib/gitlab/markdown/reference_filter.rb
View file @
e4008bc4
...
...
@@ -11,30 +11,57 @@ module Gitlab
# Context options:
# :project (required) - Current project, ignored if reference is cross-project.
# :only_path - Generate path-only links.
#
# Results:
# :references - A Hash of references that were found and replaced.
class
ReferenceFilter
<
HTML
::
Pipeline
::
Filter
def
initialize
(
*
args
)
super
LazyReference
=
Struct
.
new
(
:klass
,
:ids
)
do
def
self
.
load
(
refs
)
lazy_references
,
values
=
refs
.
partition
{
|
ref
|
ref
.
is_a?
(
self
)
}
lazy_values
=
lazy_references
.
group_by
(
&
:klass
).
flat_map
do
|
klass
,
refs
|
ids
=
refs
.
flat_map
(
&
:ids
)
klass
.
where
(
id:
ids
)
end
result
[
:references
]
=
Hash
.
new
{
|
hash
,
type
|
hash
[
type
]
=
[]
}
values
+
lazy_values
end
def
load
self
.
klass
.
where
(
id:
self
.
ids
)
end
end
def
self
.
user_can_reference?
(
user
,
node
,
context
)
if
node
.
has_attribute?
(
'data-project'
)
project_id
=
node
.
attr
(
'data-project'
).
to_i
return
true
if
project_id
==
context
[
:project
].
try
(
:id
)
project
=
Project
.
find
(
project_id
)
rescue
nil
Ability
.
abilities
.
allowed?
(
user
,
:read_project
,
project
)
else
true
end
end
def
self
.
referenced_by
(
node
)
raise
NotImplementedError
,
"
#{
self
}
does not implement
#{
__method__
}
"
end
# Returns a data attribute String to attach to a reference link
#
#
id - Object ID
#
type - Object type (default: :project)
#
attributes - Hash, where the key becomes the data attribute name and the
#
value is the data attribute value
#
# Examples:
#
# data_attribute(1) # => "data-project-id=\"1\""
# data_attribute(2, :user) # => "data-user-id=\"2\""
# data_attribute(3, :group) # => "data-group-id=\"3\""
# data_attribute(project: 1, issue: 2)
# # => "data-reference-filter=\"Gitlab::Markdown::SomeReferenceFilter\" data-project=\"1\" data-issue=\"2\""
#
# data_attribute(project: 3, merge_request: 4)
# # => "data-reference-filter=\"Gitlab::Markdown::SomeReferenceFilter\" data-project=\"3\" data-merge-request=\"4\""
#
# Returns a String
def
data_attribute
(
id
,
type
=
:project
)
%Q(data-
#{
type
}
-id="
#{
id
}
")
def
data_attribute
(
attributes
=
{})
attributes
[
:reference_filter
]
=
self
.
class
.
name
attributes
.
map
{
|
key
,
value
|
%Q(data-
#{
key
.
to_s
.
dasherize
}
="
#{
value
}
")
}.
join
(
" "
)
end
def
escape_once
(
html
)
...
...
@@ -59,16 +86,6 @@ module Gitlab
context
[
:project
]
end
# Add a reference to the pipeline's result Hash
#
# type - Singular Symbol reference type (e.g., :issue, :user, etc.)
# values - One or more Objects to add
def
push_result
(
type
,
*
values
)
return
if
values
.
empty?
result
[
:references
][
type
].
push
(
*
values
)
end
def
reference_class
(
type
)
"gfm gfm-
#{
type
}
"
end
...
...
@@ -85,7 +102,7 @@ module Gitlab
# Yields the current node's String contents. The result of the block will
# replace the node's existing content and update the current document.
#
# Returns the updated Nokogiri::
XML::Docu
ment object.
# Returns the updated Nokogiri::
HTML::DocumentFrag
ment object.
def
replace_text_nodes_matching
(
pattern
)
return
doc
if
project
.
nil?
...
...
lib/gitlab/markdown/reference_gatherer_filter.rb
0 → 100644
View file @
e4008bc4
require
'gitlab/markdown'
require
'html/pipeline/filter'
module
Gitlab
module
Markdown
# HTML filter that gathers all referenced records that the current user has
# permission to view.
#
# Expected to be run in its own post-processing pipeline.
#
class
ReferenceGathererFilter
<
HTML
::
Pipeline
::
Filter
def
initialize
(
*
)
super
result
[
:references
]
||=
Hash
.
new
{
|
hash
,
type
|
hash
[
type
]
=
[]
}
end
def
call
doc
.
css
(
'a.gfm'
).
each
do
|
node
|
gather_references
(
node
)
end
load_lazy_references
unless
context
[
:load_lazy_references
]
==
false
doc
end
private
def
gather_references
(
node
)
return
unless
node
.
has_attribute?
(
'data-reference-filter'
)
reference_type
=
node
.
attr
(
'data-reference-filter'
)
reference_filter
=
reference_type
.
constantize
return
if
context
[
:reference_filter
]
&&
reference_filter
!=
context
[
:reference_filter
]
return
unless
reference_filter
.
user_can_reference?
(
current_user
,
node
,
context
)
references
=
reference_filter
.
referenced_by
(
node
)
return
unless
references
references
.
each
do
|
type
,
values
|
Array
.
wrap
(
values
).
each
do
|
value
|
result
[
:references
][
type
]
<<
value
end
end
end
# Will load all references of one type using one query.
def
load_lazy_references
refs
=
result
[
:references
]
refs
.
each
do
|
type
,
values
|
refs
[
type
]
=
ReferenceFilter
::
LazyReference
.
load
(
values
)
end
end
def
current_user
context
[
:current_user
]
end
end
end
end
lib/gitlab/markdown/snippet_reference_filter.rb
View file @
e4008bc4
...
...
@@ -27,6 +27,10 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
{
snippet:
LazyReference
.
new
(
Snippet
,
node
.
attr
(
"data-snippet"
))
}
end
def
call
replace_text_nodes_matching
(
Snippet
.
reference_pattern
)
do
|
content
|
snippet_link_filter
(
content
)
...
...
@@ -45,11 +49,9 @@ module Gitlab
project
=
self
.
project_from_ref
(
project_ref
)
if
project
&&
snippet
=
project
.
snippets
.
find_by
(
id:
id
)
push_result
(
:snippet
,
snippet
)
title
=
escape_once
(
"Snippet:
#{
snippet
.
title
}
"
)
klass
=
reference_class
(
:snippet
)
data
=
data_attribute
(
project
.
id
)
data
=
data_attribute
(
project
:
project
.
id
,
snippet:
snippet
.
id
)
url
=
url_for_snippet
(
snippet
,
project
)
...
...
lib/gitlab/markdown/user_reference_filter.rb
View file @
e4008bc4
...
...
@@ -23,6 +23,31 @@ module Gitlab
end
end
def
self
.
referenced_by
(
node
)
if
node
.
has_attribute?
(
'data-group'
)
group
=
Group
.
find
(
node
.
attr
(
'data-group'
))
rescue
nil
return
unless
group
{
user:
group
.
users
}
elsif
node
.
has_attribute?
(
'data-user'
)
{
user:
LazyReference
.
new
(
User
,
node
.
attr
(
'data-user'
))
}
elsif
node
.
has_attribute?
(
'data-project'
)
project
=
Project
.
find
(
node
.
attr
(
'data-project'
))
rescue
nil
return
unless
project
{
user:
project
.
team
.
members
.
flatten
}
end
end
def
self
.
user_can_reference?
(
user
,
node
,
context
)
if
node
.
has_attribute?
(
'data-group'
)
group
=
Group
.
find
(
node
.
attr
(
'data-group'
))
rescue
nil
Ability
.
abilities
.
allowed?
(
user
,
:read_group
,
group
)
else
super
end
end
def
call
replace_text_nodes_matching
(
User
.
reference_pattern
)
do
|
content
|
user_link_filter
(
content
)
...
...
@@ -61,14 +86,12 @@ module Gitlab
def
link_to_all
project
=
context
[
:project
]
# FIXME (rspeicher): Law of Demeter
push_result
(
:user
,
*
project
.
team
.
members
.
flatten
)
url
=
urls
.
namespace_project_url
(
project
.
namespace
,
project
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
project:
project
.
id
)
text
=
User
.
reference_prefix
+
'all'
%(<a href="#{url}" class="#{link_class}">#{text}</a>)
%(<a href="#{url}"
#{data}
class="#{link_class}">#{text}</a>)
end
def
link_to_namespace
(
namespace
)
...
...
@@ -80,30 +103,20 @@ module Gitlab
end
def
link_to_group
(
group
,
namespace
)
return
unless
user_can_reference_group?
(
namespace
)
push_result
(
:user
,
*
namespace
.
users
)
url
=
urls
.
group_url
(
group
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
namespace
.
id
,
:group
)
data
=
data_attribute
(
group:
namespace
.
id
)
text
=
Group
.
reference_prefix
+
group
%(<a href="#{url}" #{data} class="#{link_class}">#{text}</a>)
end
def
link_to_user
(
user
,
namespace
)
push_result
(
:user
,
namespace
.
owner
)
url
=
urls
.
user_url
(
user
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
namespace
.
owner_id
,
:user
)
data
=
data_attribute
(
user:
namespace
.
owner_id
)
text
=
User
.
reference_prefix
+
user
%(<a href="#{url}" #{data} class="#{link_class}">#{text}</a>)
end
def
user_can_reference_group?
(
group
)
Ability
.
abilities
.
allowed?
(
context
[
:current_user
],
:read_group
,
group
)
end
end
end
end
lib/gitlab/reference_extractor.rb
View file @
e4008bc4
...
...
@@ -3,11 +3,12 @@ require 'gitlab/markdown'
module
Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class
ReferenceExtractor
attr_accessor
:project
,
:current_user
attr_accessor
:project
,
:current_user
,
:load_lazy_references
def
initialize
(
project
,
current_user
=
nil
)
def
initialize
(
project
,
current_user
=
nil
,
load_lazy_references:
true
)
@project
=
project
@current_user
=
current_user
@load_lazy_references
=
load_lazy_references
end
def
analyze
(
text
)
...
...
@@ -26,9 +27,9 @@ module Gitlab
def
references
@references
||=
Hash
.
new
do
|
references
,
type
|
type
=
type
.
to_sym
return
references
[
type
]
if
references
.
has_key?
(
type
)
next
references
[
type
]
if
references
.
has_key?
(
type
)
references
[
type
]
=
pipeline_result
(
type
)
.
uniq
references
[
type
]
=
pipeline_result
(
type
)
end
end
...
...
@@ -41,21 +42,32 @@ module Gitlab
def
pipeline_result
(
filter_type
)
return
[]
if
@text
.
blank?
klass
=
filter_type
.
to_s
.
camelize
+
'ReferenceFilter'
klass
=
"
#{
filter_type
.
to_s
.
camelize
}
ReferenceFilter"
filter
=
Gitlab
::
Markdown
.
const_get
(
klass
)
context
=
{
project:
project
,
current_user:
current_user
,
# We don't actually care about the links generated
only_path:
true
,
ignore_blockquotes:
true
ignore_blockquotes:
true
,
# ReferenceGathererFilter
load_lazy_references:
false
,
reference_filter:
filter
}
pipeline
=
HTML
::
Pipeline
.
new
([
filter
],
context
)
pipeline
=
HTML
::
Pipeline
.
new
([
filter
,
Gitlab
::
Markdown
::
ReferenceGathererFilter
],
context
)
result
=
pipeline
.
call
(
@text
)
result
[
:references
][
filter_type
]
values
=
result
[
:references
][
filter_type
].
uniq
if
@load_lazy_references
values
=
Gitlab
::
Markdown
::
ReferenceFilter
::
LazyReference
.
load
(
values
).
uniq
end
values
end
end
end
lib/tasks/gitlab/check.rake
View file @
e4008bc4
...
...
@@ -335,7 +335,7 @@ namespace :gitlab do
print
"Redis version >=
#{
min_redis_version
}
? ... "
redis_version
=
run
(
%W(redis-cli --version)
)
redis_version
=
redis_version
.
try
(
:match
,
/redis-cli (
.*
)/
)
redis_version
=
redis_version
.
try
(
:match
,
/redis-cli (
\d+\.\d+\.\d+
)/
)
if
redis_version
&&
(
Gem
::
Version
.
new
(
redis_version
[
1
])
>
Gem
::
Version
.
new
(
min_redis_version
))
puts
"yes"
.
green
...
...
spec/benchmarks/models/milestone_spec.rb
0 → 100644
View file @
e4008bc4
require
'spec_helper'
describe
Milestone
,
benchmark:
true
do
describe
'#sort_issues'
do
let
(
:milestone
)
{
create
(
:milestone
)
}
let
(
:issue1
)
{
create
(
:issue
,
milestone:
milestone
)
}
let
(
:issue2
)
{
create
(
:issue
,
milestone:
milestone
)
}
let
(
:issue3
)
{
create
(
:issue
,
milestone:
milestone
)
}
let
(
:issue_ids
)
{
[
issue3
.
id
,
issue2
.
id
,
issue1
.
id
]
}
benchmark_subject
{
milestone
.
sort_issues
(
issue_ids
)
}
it
{
is_expected
.
to
iterate_per_second
(
500
)
}
end
end
spec/controllers/abuse_reports_controller_spec.rb
0 → 100644
View file @
e4008bc4
require
'spec_helper'
describe
AbuseReportsController
do
let
(
:reporter
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:message
)
{
"This user is a spammer"
}
before
do
sign_in
(
reporter
)
end
describe
"POST create"
do
context
"with admin notification email set"
do
let
(
:admin_email
)
{
"admin@example.com"
}
before
(
:each
)
do
stub_application_setting
(
admin_notification_email:
admin_email
)
end
it
"sends a notification email"
do
post
:create
,
abuse_report:
{
user_id:
user
.
id
,
message:
message
}
email
=
ActionMailer
::
Base
.
deliveries
.
last
expect
(
email
.
to
).
to
eq
([
admin_email
])
expect
(
email
.
subject
).
to
include
(
user
.
username
)
expect
(
email
.
text_part
.
body
).
to
include
(
message
)
end
it
"saves the abuse report"
do
expect
do
post
:create
,
abuse_report:
{
user_id:
user
.
id
,
message:
message
}
end
.
to
change
{
AbuseReport
.
count
}.
by
(
1
)
end
end
context
"without admin notification email set"
do
before
(
:each
)
do
stub_application_setting
(
admin_notification_email:
nil
)
end
it
"does not send a notification email"
do
expect
do
post
:create
,
abuse_report:
{
user_id:
user
.
id
,
message:
message
}
end
.
not_to
change
{
ActionMailer
::
Base
.
deliveries
.
count
}
end
it
"saves the abuse report"
do
expect
do
post
:create
,
abuse_report:
{
user_id:
user
.
id
,
message:
message
}
end
.
to
change
{
AbuseReport
.
count
}.
by
(
1
)
end
end
end
end
spec/controllers/import/github_controller_spec.rb
View file @
e4008bc4
...
...
@@ -41,7 +41,7 @@ describe Import::GithubController do
it
"assigns variables"
do
@project
=
create
(
:project
,
import_type:
'github'
,
creator_id:
user
.
id
)
stub_client
(
repos:
[
@repo
],
orgs:
[
@org
],
org_repos:
[
@org_repo
])
stub_client
(
repos:
[
@repo
,
@org_repo
],
orgs:
[
@org
],
org_repos:
[
@org_repo
])
get
:status
...
...
spec/controllers/projects_controller_spec.rb
View file @
e4008bc4
...
...
@@ -22,6 +22,34 @@ describe ProjectsController do
end
end
context
"rendering default project view"
do
render_views
it
"renders the activity view"
do
allow
(
controller
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
user
).
to
receive
(
:project_view
).
and_return
(
'activity'
)
get
:show
,
namespace_id:
public_project
.
namespace
.
path
,
id:
public_project
.
path
expect
(
response
).
to
render_template
(
'_activity'
)
end
it
"renders the readme view"
do
allow
(
controller
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
user
).
to
receive
(
:project_view
).
and_return
(
'readme'
)
get
:show
,
namespace_id:
public_project
.
namespace
.
path
,
id:
public_project
.
path
expect
(
response
).
to
render_template
(
'_readme'
)
end
it
"renders the files view"
do
allow
(
controller
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
user
).
to
receive
(
:project_view
).
and_return
(
'files'
)
get
:show
,
namespace_id:
public_project
.
namespace
.
path
,
id:
public_project
.
path
expect
(
response
).
to
render_template
(
'_files'
)
end
end
context
"when requested with case sensitive namespace and project path"
do
it
"redirects to the normalized path for case mismatch"
do
get
:show
,
namespace_id:
public_project
.
namespace
.
path
,
id:
public_project
.
path
.
upcase
...
...
@@ -62,4 +90,50 @@ describe ProjectsController do
expect
(
user
.
starred?
(
public_project
)).
to
be_falsey
end
end
describe
"DELETE remove_fork"
do
context
'when signed in'
do
before
do
sign_in
(
user
)
end
context
'with forked project'
do
let
(
:project_fork
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
before
do
create
(
:forked_project_link
,
forked_to_project:
project_fork
)
end
it
'should remove fork from project'
do
delete
(
:remove_fork
,
namespace_id:
project_fork
.
namespace
.
to_param
,
id:
project_fork
.
to_param
,
format: :js
)
expect
(
project_fork
.
forked?
).
to
be_falsey
expect
(
flash
[
:notice
]).
to
eq
(
'The fork relationship has been removed.'
)
expect
(
response
).
to
render_template
(
:remove_fork
)
end
end
context
'when project not forked'
do
let
(
:unforked_project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
it
'should do nothing if project was not forked'
do
delete
(
:remove_fork
,
namespace_id:
unforked_project
.
namespace
.
to_param
,
id:
unforked_project
.
to_param
,
format: :js
)
expect
(
flash
[
:notice
]).
to
be_nil
expect
(
response
).
to
render_template
(
:remove_fork
)
end
end
end
it
"does nothing if user is not signed in"
do
delete
(
:remove_fork
,
namespace_id:
project
.
namespace
.
to_param
,
id:
project
.
to_param
,
format: :js
)
expect
(
response
.
status
).
to
eq
(
401
)
end
end
end
spec/features/markdown_spec.rb
View file @
e4008bc4
...
...
@@ -220,7 +220,7 @@ describe 'GitLab Markdown', feature: true do
end
end
#
`markdown` calls these two methods
#
Fake a `current_user` helper
def
current_user
@feat
.
user
end
...
...
spec/features/projects_spec.rb
View file @
e4008bc4
...
...
@@ -34,6 +34,27 @@ feature 'Project', feature: true do
end
end
describe
'remove forked relationship'
,
js:
true
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
before
do
login_with
user
create
(
:forked_project_link
,
forked_to_project:
project
)
visit
edit_namespace_project_path
(
project
.
namespace
,
project
)
end
it
'should remove fork'
do
expect
(
page
).
to
have_content
'Remove fork relationship'
remove_with_confirm
(
'Remove fork relationship'
,
project
.
path
)
expect
(
page
).
to
have_content
'The fork relationship has been removed.'
expect
(
project
.
forked?
).
to
be_falsey
expect
(
page
).
not_to
have_content
'Remove fork relationship'
end
end
describe
'removal'
,
js:
true
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
...
...
@@ -45,13 +66,13 @@ feature 'Project', feature: true do
end
it
'should remove project'
do
expect
{
remove_
project
}.
to
change
{
Project
.
count
}.
by
(
-
1
)
expect
{
remove_
with_confirm
(
'Remove project'
,
project
.
path
)
}.
to
change
{
Project
.
count
}.
by
(
-
1
)
end
end
def
remove_
project
click_button
"Remove project"
fill_in
'confirm_name_input'
,
with:
project
.
pa
th
def
remove_
with_confirm
(
button_text
,
confirm_with
)
click_button
button_text
fill_in
'confirm_name_input'
,
with:
confirm_wi
th
click_button
'Confirm'
end
end
spec/helpers/gitlab_markdown_helper_spec.rb
View file @
e4008bc4
...
...
@@ -11,12 +11,15 @@ describe GitlabMarkdownHelper do
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
,
target_project:
project
)
}
let
(
:snippet
)
{
create
(
:project_snippet
,
project:
project
)
}
# Helper expects a current_user method.
let
(
:current_user
)
{
user
}
before
do
# Ensure the generated reference links aren't redacted
project
.
team
<<
[
user
,
:master
]
# Helper expects a @project instance variable
@project
=
project
helper
.
instance_variable_set
(
:@project
,
project
)
# Stub the `current_user` helper
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
end
describe
"#markdown"
do
...
...
@@ -25,23 +28,23 @@ describe GitlabMarkdownHelper do
it
"should link to the merge request"
do
expected
=
namespace_project_merge_request_path
(
project
.
namespace
,
project
,
merge_request
)
expect
(
markdown
(
actual
)).
to
match
(
expected
)
expect
(
helper
.
markdown
(
actual
)).
to
match
(
expected
)
end
it
"should link to the commit"
do
expected
=
namespace_project_commit_path
(
project
.
namespace
,
project
,
commit
)
expect
(
markdown
(
actual
)).
to
match
(
expected
)
expect
(
helper
.
markdown
(
actual
)).
to
match
(
expected
)
end
it
"should link to the issue"
do
expected
=
namespace_project_issue_path
(
project
.
namespace
,
project
,
issue
)
expect
(
markdown
(
actual
)).
to
match
(
expected
)
expect
(
helper
.
markdown
(
actual
)).
to
match
(
expected
)
end
end
describe
"override default project"
do
let
(
:actual
)
{
issue
.
to_reference
}
let
(
:second_project
)
{
create
(
:project
)
}
let
(
:second_project
)
{
create
(
:project
,
:public
)
}
let
(
:second_issue
)
{
create
(
:issue
,
project:
second_project
)
}
it
'should link to the issue'
do
...
...
@@ -56,7 +59,7 @@ describe GitlabMarkdownHelper do
let
(
:issues
)
{
create_list
(
:issue
,
2
,
project:
project
)
}
it
'should handle references nested in links with all the text'
do
actual
=
link_to_gfm
(
"This should finally fix
#{
issues
[
0
].
to_reference
}
and
#{
issues
[
1
].
to_reference
}
for real"
,
commit_path
)
actual
=
helper
.
link_to_gfm
(
"This should finally fix
#{
issues
[
0
].
to_reference
}
and
#{
issues
[
1
].
to_reference
}
for real"
,
commit_path
)
doc
=
Nokogiri
::
HTML
.
parse
(
actual
)
# Make sure we didn't create invalid markup
...
...
@@ -86,7 +89,7 @@ describe GitlabMarkdownHelper do
end
it
'should forward HTML options'
do
actual
=
link_to_gfm
(
"Fixed in
#{
commit
.
id
}
"
,
commit_path
,
class:
'foo'
)
actual
=
helper
.
link_to_gfm
(
"Fixed in
#{
commit
.
id
}
"
,
commit_path
,
class:
'foo'
)
doc
=
Nokogiri
::
HTML
.
parse
(
actual
)
expect
(
doc
.
css
(
'a'
)).
to
satisfy
do
|
v
|
...
...
@@ -97,13 +100,13 @@ describe GitlabMarkdownHelper do
it
"escapes HTML passed in as the body"
do
actual
=
"This is a <h1>test</h1> - see
#{
issues
[
0
].
to_reference
}
"
expect
(
link_to_gfm
(
actual
,
commit_path
)).
expect
(
helper
.
link_to_gfm
(
actual
,
commit_path
)).
to
match
(
'<h1>test</h1>'
)
end
it
'ignores reference links when they are the entire body'
do
text
=
issues
[
0
].
to_reference
act
=
link_to_gfm
(
text
,
'/foo'
)
act
=
helper
.
link_to_gfm
(
text
,
'/foo'
)
expect
(
act
).
to
eq
%Q(<a href="/foo">
#{
issues
[
0
].
to_reference
}
</a>)
end
...
...
spec/helpers/issues_helper_spec.rb
View file @
e4008bc4
...
...
@@ -117,4 +117,14 @@ describe IssuesHelper do
end
end
describe
"#merge_requests_sentence"
do
subject
{
merge_requests_sentence
(
merge_requests
)}
let
(
:merge_requests
)
do
[
build
(
:merge_request
,
iid:
1
),
build
(
:merge_request
,
iid:
2
),
build
(
:merge_request
,
iid:
3
)]
end
it
{
is_expected
.
to
eq
(
"!1, !2, or !3"
)
}
end
end
spec/helpers/labels_helper_spec.rb
View file @
e4008bc4
...
...
@@ -14,11 +14,6 @@ describe LabelsHelper do
expect
(
label
).
not_to
receive
(
:project
)
link_to_label
(
label
)
end
it
'includes option for "No Label"'
do
result
=
project_labels_options
(
project
)
expect
(
result
).
to
include
(
'No Label'
)
end
end
context
'without @project set'
do
...
...
spec/lib/gitlab/closing_issue_extractor_spec.rb
View file @
e4008bc4
...
...
@@ -140,28 +140,28 @@ describe Gitlab::ClosingIssueExtractor do
message
=
"Closes
#{
reference
}
and fix
#{
reference2
}
"
expect
(
subject
.
closed_by_message
(
message
)).
to
eq
([
issue
,
other_issue
])
to
match_array
([
issue
,
other_issue
])
end
it
'fetches comma-separated issues references in single line message'
do
message
=
"Closes
#{
reference
}
, closes
#{
reference2
}
"
expect
(
subject
.
closed_by_message
(
message
)).
to
eq
([
issue
,
other_issue
])
to
match_array
([
issue
,
other_issue
])
end
it
'fetches comma-separated issues numbers in single line message'
do
message
=
"Closes
#{
reference
}
,
#{
reference2
}
and
#{
reference3
}
"
expect
(
subject
.
closed_by_message
(
message
)).
to
eq
([
issue
,
other_issue
,
third_issue
])
to
match_array
([
issue
,
other_issue
,
third_issue
])
end
it
'fetches issues in multi-line message'
do
message
=
"Awesome commit (closes
#{
reference
}
)
\n
Also fixes
#{
reference2
}
"
expect
(
subject
.
closed_by_message
(
message
)).
to
eq
([
issue
,
other_issue
])
to
match_array
([
issue
,
other_issue
])
end
it
'fetches issues in hybrid message'
do
...
...
@@ -169,7 +169,7 @@ describe Gitlab::ClosingIssueExtractor do
"Also fixing issues
#{
reference2
}
,
#{
reference3
}
and #4"
expect
(
subject
.
closed_by_message
(
message
)).
to
eq
([
issue
,
other_issue
,
third_issue
])
to
match_array
([
issue
,
other_issue
,
third_issue
])
end
end
end
...
...
spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -4,7 +4,7 @@ module Gitlab::Markdown
describe
CommitRangeReferenceFilter
do
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:commit1
)
{
project
.
commit
}
let
(
:commit2
)
{
project
.
commit
(
"HEAD~2"
)
}
...
...
@@ -75,12 +75,20 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'class'
)).
to
eq
'gfm gfm-commit_range'
end
it
'includes a data-project
-id
attribute'
do
it
'includes a data-project attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-project-id'
)
expect
(
link
.
attr
(
'data-project-id'
)).
to
eq
project
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-project'
)
expect
(
link
.
attr
(
'data-project'
)).
to
eq
project
.
id
.
to_s
end
it
'includes a data-commit-range attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-commit-range'
)
expect
(
link
.
attr
(
'data-commit-range'
)).
to
eq
range
.
to_reference
end
it
'supports an :only_path option'
do
...
...
@@ -92,23 +100,20 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"See
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"See
#{
reference
}
"
)
expect
(
result
[
:references
][
:commit_range
]).
not_to
be_empty
end
end
context
'cross-project reference'
do
let
(
:namespace
)
{
create
(
:namespace
,
name:
'cross-reference'
)
}
let
(
:project2
)
{
create
(
:project
,
namespace:
namespace
)
}
let
(
:project2
)
{
create
(
:project
,
:public
,
namespace:
namespace
)
}
let
(
:reference
)
{
range
.
to_reference
(
project
)
}
before
do
range
.
project
=
project2
end
context
'when user can access reference'
do
before
{
allow_cross_reference!
}
it
'links to a valid reference'
do
doc
=
filter
(
"See
#{
reference
}
"
)
...
...
@@ -132,20 +137,9 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"See
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"See
#{
reference
}
"
)
expect
(
result
[
:references
][
:commit_range
]).
not_to
be_empty
end
end
context
'when user cannot access reference'
do
before
{
disallow_cross_reference!
}
it
'ignores valid references'
do
exp
=
act
=
"See
#{
reference
}
"
expect
(
filter
(
act
).
to_html
).
to
eq
exp
end
end
end
end
end
spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -4,7 +4,7 @@ module Gitlab::Markdown
describe
CommitReferenceFilter
do
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:commit
)
{
project
.
commit
}
it
'requires project context'
do
...
...
@@ -71,12 +71,20 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'class'
)).
to
eq
'gfm gfm-commit'
end
it
'includes a data-project
-id
attribute'
do
it
'includes a data-project attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-project-id'
)
expect
(
link
.
attr
(
'data-project-id'
)).
to
eq
project
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-project'
)
expect
(
link
.
attr
(
'data-project'
)).
to
eq
project
.
id
.
to_s
end
it
'includes a data-commit attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-commit'
)
expect
(
link
.
attr
(
'data-commit'
)).
to
eq
commit
.
id
end
it
'supports an :only_path context'
do
...
...
@@ -88,20 +96,17 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"See
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"See
#{
reference
}
"
)
expect
(
result
[
:references
][
:commit
]).
not_to
be_empty
end
end
context
'cross-project reference'
do
let
(
:namespace
)
{
create
(
:namespace
,
name:
'cross-reference'
)
}
let
(
:project2
)
{
create
(
:project
,
namespace:
namespace
)
}
let
(
:project2
)
{
create
(
:project
,
:public
,
namespace:
namespace
)
}
let
(
:commit
)
{
project2
.
commit
}
let
(
:reference
)
{
commit
.
to_reference
(
project
)
}
context
'when user can access reference'
do
before
{
allow_cross_reference!
}
it
'links to a valid reference'
do
doc
=
filter
(
"See
#{
reference
}
"
)
...
...
@@ -122,20 +127,9 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"See
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"See
#{
reference
}
"
)
expect
(
result
[
:references
][
:commit
]).
not_to
be_empty
end
end
context
'when user cannot access reference'
do
before
{
disallow_cross_reference!
}
it
'ignores valid references'
do
exp
=
act
=
"See
#{
reference
}
"
expect
(
filter
(
act
).
to_html
).
to
eq
exp
end
end
end
end
end
spec/lib/gitlab/markdown/cross_project_reference_spec.rb
View file @
e4008bc4
...
...
@@ -2,20 +2,16 @@ require 'spec_helper'
module
Gitlab::Markdown
describe
CrossProjectReference
do
# context in the html-pipeline sense, not in the rspec sense
let
(
:context
)
do
{
current_user:
double
(
'user'
),
project:
double
(
'project'
)
}
end
include
described_class
describe
'#project_from_ref'
do
context
'when no project was referenced'
do
it
'returns the project from context'
do
expect
(
project_from_ref
(
nil
)).
to
eq
context
[
:project
]
project
=
double
allow
(
self
).
to
receive
(
:context
).
and_return
({
project:
project
})
expect
(
project_from_ref
(
nil
)).
to
eq
project
end
end
...
...
@@ -26,31 +22,15 @@ module Gitlab::Markdown
end
context
'when referenced project exists'
do
let
(
:project2
)
{
double
(
'referenced project'
)
}
it
'returns the referenced project'
do
project2
=
double
(
'referenced project'
)
before
do
expect
(
Project
).
to
receive
(
:find_with_namespace
).
with
(
'cross/reference'
).
and_return
(
project2
)
end
context
'and the user has permission to read it'
do
it
'returns the referenced project'
do
expect
(
self
).
to
receive
(
:user_can_reference_project?
).
with
(
project2
).
and_return
(
true
)
expect
(
project_from_ref
(
'cross/reference'
)).
to
eq
project2
end
end
context
'and the user does not have permission to read it'
do
it
'returns nil'
do
expect
(
self
).
to
receive
(
:user_can_reference_project?
).
with
(
project2
).
and_return
(
false
)
expect
(
project_from_ref
(
'cross/reference'
)).
to
be_nil
end
end
end
end
end
end
spec/lib/gitlab/markdown/issue_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -8,7 +8,7 @@ module Gitlab::Markdown
IssuesHelper
end
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
it
'requires project context'
do
...
...
@@ -68,12 +68,20 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'class'
)).
to
eq
'gfm gfm-issue'
end
it
'includes a data-project
-id
attribute'
do
it
'includes a data-project attribute'
do
doc
=
filter
(
"Issue
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-project-id'
)
expect
(
link
.
attr
(
'data-project-id'
)).
to
eq
project
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-project'
)
expect
(
link
.
attr
(
'data-project'
)).
to
eq
project
.
id
.
to_s
end
it
'includes a data-issue attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-issue'
)
expect
(
link
.
attr
(
'data-issue'
)).
to
eq
issue
.
id
.
to_s
end
it
'supports an :only_path context'
do
...
...
@@ -85,20 +93,17 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Fixed
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Fixed
#{
reference
}
"
)
expect
(
result
[
:references
][
:issue
]).
to
eq
[
issue
]
end
end
context
'cross-project reference'
do
let
(
:namespace
)
{
create
(
:namespace
,
name:
'cross-reference'
)
}
let
(
:project2
)
{
create
(
:empty_project
,
namespace:
namespace
)
}
let
(
:project2
)
{
create
(
:empty_project
,
:public
,
namespace:
namespace
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project2
)
}
let
(
:reference
)
{
issue
.
to_reference
(
project
)
}
context
'when user can access reference'
do
before
{
allow_cross_reference!
}
it
'ignores valid references when cross-reference project uses external tracker'
do
expect_any_instance_of
(
Project
).
to
receive
(
:get_issue
).
with
(
issue
.
iid
).
and_return
(
nil
)
...
...
@@ -126,20 +131,9 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Fixed
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Fixed
#{
reference
}
"
)
expect
(
result
[
:references
][
:issue
]).
to
eq
[
issue
]
end
end
context
'when user cannot access reference'
do
before
{
disallow_cross_reference!
}
it
'ignores valid references'
do
exp
=
act
=
"See
#{
reference
}
"
expect
(
filter
(
act
).
to_html
).
to
eq
exp
end
end
end
end
end
spec/lib/gitlab/markdown/label_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -5,7 +5,7 @@ module Gitlab::Markdown
describe
LabelReferenceFilter
do
include
FilterSpecHelper
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let
(
:label
)
{
create
(
:label
,
project:
project
)
}
let
(
:reference
)
{
label
.
to_reference
}
...
...
@@ -25,12 +25,20 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'class'
)).
to
eq
'gfm gfm-label'
end
it
'includes a data-project
-id
attribute'
do
it
'includes a data-project attribute'
do
doc
=
filter
(
"Label
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-project-id'
)
expect
(
link
.
attr
(
'data-project-id'
)).
to
eq
project
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-project'
)
expect
(
link
.
attr
(
'data-project'
)).
to
eq
project
.
id
.
to_s
end
it
'includes a data-label attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-label'
)
expect
(
link
.
attr
(
'data-label'
)).
to
eq
label
.
id
.
to_s
end
it
'supports an :only_path context'
do
...
...
@@ -42,7 +50,7 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Label
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Label
#{
reference
}
"
)
expect
(
result
[
:references
][
:label
]).
to
eq
[
label
]
end
...
...
spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -4,7 +4,7 @@ module Gitlab::Markdown
describe
MergeRequestReferenceFilter
do
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:merge
)
{
create
(
:merge_request
,
source_project:
project
)
}
it
'requires project context'
do
...
...
@@ -56,12 +56,20 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'class'
)).
to
eq
'gfm gfm-merge_request'
end
it
'includes a data-project
-id
attribute'
do
it
'includes a data-project attribute'
do
doc
=
filter
(
"Merge
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-project-id'
)
expect
(
link
.
attr
(
'data-project-id'
)).
to
eq
project
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-project'
)
expect
(
link
.
attr
(
'data-project'
)).
to
eq
project
.
id
.
to_s
end
it
'includes a data-merge-request attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-merge-request'
)
expect
(
link
.
attr
(
'data-merge-request'
)).
to
eq
merge
.
id
.
to_s
end
it
'supports an :only_path context'
do
...
...
@@ -73,20 +81,17 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Merge
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Merge
#{
reference
}
"
)
expect
(
result
[
:references
][
:merge_request
]).
to
eq
[
merge
]
end
end
context
'cross-project reference'
do
let
(
:namespace
)
{
create
(
:namespace
,
name:
'cross-reference'
)
}
let
(
:project2
)
{
create
(
:project
,
namespace:
namespace
)
}
let
(
:project2
)
{
create
(
:project
,
:public
,
namespace:
namespace
)
}
let
(
:merge
)
{
create
(
:merge_request
,
source_project:
project2
)
}
let
(
:reference
)
{
merge
.
to_reference
(
project
)
}
context
'when user can access reference'
do
before
{
allow_cross_reference!
}
it
'links to a valid reference'
do
doc
=
filter
(
"See
#{
reference
}
"
)
...
...
@@ -107,20 +112,9 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Merge
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Merge
#{
reference
}
"
)
expect
(
result
[
:references
][
:merge_request
]).
to
eq
[
merge
]
end
end
context
'when user cannot access reference'
do
before
{
disallow_cross_reference!
}
it
'ignores valid references'
do
exp
=
act
=
"See
#{
reference
}
"
expect
(
filter
(
act
).
to_html
).
to
eq
exp
end
end
end
end
end
spec/lib/gitlab/markdown/redactor_filter_spec.rb
0 → 100644
View file @
e4008bc4
require
'spec_helper'
module
Gitlab::Markdown
describe
RedactorFilter
do
include
ActionView
::
Helpers
::
UrlHelper
include
FilterSpecHelper
it
'ignores non-GFM links'
do
html
=
%(See <a href="https://google.com/">Google</a>)
doc
=
filter
(
html
,
current_user:
double
)
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
1
end
def
reference_link
(
data
)
link_to
(
'text'
,
''
,
class:
'gfm'
,
data:
data
)
end
context
'with data-project'
do
it
'removes unpermitted Project references'
do
user
=
create
(
:user
)
project
=
create
(
:empty_project
)
link
=
reference_link
(
project:
project
.
id
,
reference_filter:
Gitlab
::
Markdown
::
ReferenceFilter
.
name
)
doc
=
filter
(
link
,
current_user:
user
)
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
0
end
it
'allows permitted Project references'
do
user
=
create
(
:user
)
project
=
create
(
:empty_project
)
project
.
team
<<
[
user
,
:master
]
link
=
reference_link
(
project:
project
.
id
,
reference_filter:
Gitlab
::
Markdown
::
ReferenceFilter
.
name
)
doc
=
filter
(
link
,
current_user:
user
)
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
1
end
it
'handles invalid Project references'
do
link
=
reference_link
(
project:
12345
,
reference_filter:
Gitlab
::
Markdown
::
ReferenceFilter
.
name
)
expect
{
filter
(
link
)
}.
not_to
raise_error
end
end
context
"for user references"
do
context
'with data-group'
do
it
'removes unpermitted Group references'
do
user
=
create
(
:user
)
group
=
create
(
:group
)
link
=
reference_link
(
group:
group
.
id
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
doc
=
filter
(
link
,
current_user:
user
)
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
0
end
it
'allows permitted Group references'
do
user
=
create
(
:user
)
group
=
create
(
:group
)
group
.
add_developer
(
user
)
link
=
reference_link
(
group:
group
.
id
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
doc
=
filter
(
link
,
current_user:
user
)
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
1
end
it
'handles invalid Group references'
do
link
=
reference_link
(
group:
12345
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
expect
{
filter
(
link
)
}.
not_to
raise_error
end
end
context
'with data-user'
do
it
'allows any User reference'
do
user
=
create
(
:user
)
link
=
reference_link
(
user:
user
.
id
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
doc
=
filter
(
link
)
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
1
end
end
end
end
end
spec/lib/gitlab/markdown/reference_gatherer_filter_spec.rb
0 → 100644
View file @
e4008bc4
require
'spec_helper'
module
Gitlab::Markdown
describe
ReferenceGathererFilter
do
include
ActionView
::
Helpers
::
UrlHelper
include
FilterSpecHelper
def
reference_link
(
data
)
link_to
(
'text'
,
''
,
class:
'gfm'
,
data:
data
)
end
context
"for issue references"
do
context
'with data-project'
do
it
'removes unpermitted Project references'
do
user
=
create
(
:user
)
project
=
create
(
:empty_project
)
issue
=
create
(
:issue
,
project:
project
)
link
=
reference_link
(
project:
project
.
id
,
issue:
issue
.
id
,
reference_filter:
Gitlab
::
Markdown
::
IssueReferenceFilter
.
name
)
result
=
pipeline_result
(
link
,
current_user:
user
)
expect
(
result
[
:references
][
:issue
]).
to
be_empty
end
it
'allows permitted Project references'
do
user
=
create
(
:user
)
project
=
create
(
:empty_project
)
issue
=
create
(
:issue
,
project:
project
)
project
.
team
<<
[
user
,
:master
]
link
=
reference_link
(
project:
project
.
id
,
issue:
issue
.
id
,
reference_filter:
Gitlab
::
Markdown
::
IssueReferenceFilter
.
name
)
result
=
pipeline_result
(
link
,
current_user:
user
)
expect
(
result
[
:references
][
:issue
]).
to
eq
([
issue
])
end
it
'handles invalid Project references'
do
link
=
reference_link
(
project:
12345
,
issue:
12345
,
reference_filter:
Gitlab
::
Markdown
::
IssueReferenceFilter
.
name
)
expect
{
pipeline_result
(
link
)
}.
not_to
raise_error
end
end
end
context
"for user references"
do
context
'with data-group'
do
it
'removes unpermitted Group references'
do
user
=
create
(
:user
)
group
=
create
(
:group
)
link
=
reference_link
(
group:
group
.
id
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
result
=
pipeline_result
(
link
,
current_user:
user
)
expect
(
result
[
:references
][
:user
]).
to
be_empty
end
it
'allows permitted Group references'
do
user
=
create
(
:user
)
group
=
create
(
:group
)
group
.
add_developer
(
user
)
link
=
reference_link
(
group:
group
.
id
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
result
=
pipeline_result
(
link
,
current_user:
user
)
expect
(
result
[
:references
][
:user
]).
to
eq
([
user
])
end
it
'handles invalid Group references'
do
link
=
reference_link
(
group:
12345
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
expect
{
pipeline_result
(
link
)
}.
not_to
raise_error
end
end
context
'with data-user'
do
it
'allows any User reference'
do
user
=
create
(
:user
)
link
=
reference_link
(
user:
user
.
id
,
reference_filter:
Gitlab
::
Markdown
::
UserReferenceFilter
.
name
)
result
=
pipeline_result
(
link
)
expect
(
result
[
:references
][
:user
]).
to
eq
([
user
])
end
end
end
end
end
spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -4,7 +4,7 @@ module Gitlab::Markdown
describe
SnippetReferenceFilter
do
include
FilterSpecHelper
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let
(
:snippet
)
{
create
(
:project_snippet
,
project:
project
)
}
let
(
:reference
)
{
snippet
.
to_reference
}
...
...
@@ -55,12 +55,20 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'class'
)).
to
eq
'gfm gfm-snippet'
end
it
'includes a data-project
-id
attribute'
do
it
'includes a data-project attribute'
do
doc
=
filter
(
"Snippet
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-project-id'
)
expect
(
link
.
attr
(
'data-project-id'
)).
to
eq
project
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-project'
)
expect
(
link
.
attr
(
'data-project'
)).
to
eq
project
.
id
.
to_s
end
it
'includes a data-snippet attribute'
do
doc
=
filter
(
"See
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-snippet'
)
expect
(
link
.
attr
(
'data-snippet'
)).
to
eq
snippet
.
id
.
to_s
end
it
'supports an :only_path context'
do
...
...
@@ -72,20 +80,17 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Snippet
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Snippet
#{
reference
}
"
)
expect
(
result
[
:references
][
:snippet
]).
to
eq
[
snippet
]
end
end
context
'cross-project reference'
do
let
(
:namespace
)
{
create
(
:namespace
,
name:
'cross-reference'
)
}
let
(
:project2
)
{
create
(
:empty_project
,
namespace:
namespace
)
}
let
(
:project2
)
{
create
(
:empty_project
,
:public
,
namespace:
namespace
)
}
let
(
:snippet
)
{
create
(
:project_snippet
,
project:
project2
)
}
let
(
:reference
)
{
snippet
.
to_reference
(
project
)
}
context
'when user can access reference'
do
before
{
allow_cross_reference!
}
it
'links to a valid reference'
do
doc
=
filter
(
"See
#{
reference
}
"
)
...
...
@@ -105,20 +110,9 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Snippet
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Snippet
#{
reference
}
"
)
expect
(
result
[
:references
][
:snippet
]).
to
eq
[
snippet
]
end
end
context
'when user cannot access reference'
do
before
{
disallow_cross_reference!
}
it
'ignores valid references'
do
exp
=
act
=
"See
#{
reference
}
"
expect
(
filter
(
act
).
to_html
).
to
eq
exp
end
end
end
end
end
spec/lib/gitlab/markdown/user_reference_filter_spec.rb
View file @
e4008bc4
...
...
@@ -4,7 +4,7 @@ module Gitlab::Markdown
describe
UserReferenceFilter
do
include
FilterSpecHelper
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:reference
)
{
user
.
to_reference
}
...
...
@@ -39,7 +39,7 @@ module Gitlab::Markdown
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Hey
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Hey
#{
reference
}
"
)
expect
(
result
[
:references
][
:user
]).
to
eq
[
project
.
creator
]
end
end
...
...
@@ -64,62 +64,43 @@ module Gitlab::Markdown
expect
(
doc
.
css
(
'a'
).
length
).
to
eq
1
end
it
'includes a data-user
-id
attribute'
do
it
'includes a data-user attribute'
do
doc
=
filter
(
"Hey
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-user
-id
'
)
expect
(
link
.
attr
(
'data-user
-id
'
)).
to
eq
user
.
namespace
.
owner_id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-user'
)
expect
(
link
.
attr
(
'data-user'
)).
to
eq
user
.
namespace
.
owner_id
.
to_s
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Hey
#{
reference
}
"
)
result
=
reference_
pipeline_result
(
"Hey
#{
reference
}
"
)
expect
(
result
[
:references
][
:user
]).
to
eq
[
user
]
end
end
context
'mentioning a group'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:reference
)
{
group
.
to_reference
}
context
'that the current user can read'
do
before
do
group
.
add_developer
(
user
)
end
it
'links to the Group'
do
doc
=
filter
(
"Hey
#{
reference
}
"
,
current_user:
user
)
doc
=
filter
(
"Hey
#{
reference
}
"
)
expect
(
doc
.
css
(
'a'
).
first
.
attr
(
'href'
)).
to
eq
urls
.
group_url
(
group
)
end
it
'includes a data-group-id
attribute'
do
doc
=
filter
(
"Hey
#{
reference
}
"
,
current_user:
user
)
it
'includes a data-group
attribute'
do
doc
=
filter
(
"Hey
#{
reference
}
"
)
link
=
doc
.
css
(
'a'
).
first
expect
(
link
).
to
have_attribute
(
'data-group-id
'
)
expect
(
link
.
attr
(
'data-group-id
'
)).
to
eq
group
.
id
.
to_s
expect
(
link
).
to
have_attribute
(
'data-group
'
)
expect
(
link
.
attr
(
'data-group
'
)).
to
eq
group
.
id
.
to_s
end
it
'adds to the results hash'
do
result
=
pipeline_result
(
"Hey
#{
reference
}
"
,
current_user:
user
)
result
=
reference_pipeline_result
(
"Hey
#{
reference
}
"
)
expect
(
result
[
:references
][
:user
]).
to
eq
group
.
users
end
end
context
'that the current user cannot read'
do
it
'ignores references to the Group'
do
doc
=
filter
(
"Hey
#{
reference
}
"
,
current_user:
user
)
expect
(
doc
.
to_html
).
to
eq
"Hey
#{
reference
}
"
end
it
'does not add to the results hash'
do
result
=
pipeline_result
(
"Hey
#{
reference
}
"
,
current_user:
user
)
expect
(
result
[
:references
][
:user
]).
to
eq
[]
end
end
end
it
'links with adjacent text'
do
doc
=
filter
(
"Mention me (
#{
reference
}
.)"
)
expect
(
doc
.
to_html
).
to
match
(
/\(<a.+>
#{
reference
}
<\/a>\.\)/
)
...
...
spec/lib/gitlab/reference_extractor_spec.rb
View file @
e4008bc4
...
...
@@ -13,7 +13,7 @@ describe Gitlab::ReferenceExtractor do
project
.
team
<<
[
@u_bar
,
:guest
]
subject
.
analyze
(
'@foo, @baduser, @bar, and @offteam'
)
expect
(
subject
.
users
).
to
eq
([
@u_foo
,
@u_bar
,
@u_offteam
])
expect
(
subject
.
users
).
to
match_array
([
@u_foo
,
@u_bar
,
@u_offteam
])
end
it
'ignores user mentions inside specific elements'
do
...
...
@@ -37,7 +37,7 @@ describe Gitlab::ReferenceExtractor do
> @offteam
}
)
expect
(
subject
.
users
).
to
eq
([])
expect
(
subject
.
users
).
to
match_array
([])
end
it
'accesses valid issue objects'
do
...
...
@@ -45,7 +45,7 @@ describe Gitlab::ReferenceExtractor do
@i1
=
create
(
:issue
,
project:
project
)
subject
.
analyze
(
"
#{
@i0
.
to_reference
}
,
#{
@i1
.
to_reference
}
, and
#{
Issue
.
reference_prefix
}
999."
)
expect
(
subject
.
issues
).
to
eq
([
@i0
,
@i1
])
expect
(
subject
.
issues
).
to
match_array
([
@i0
,
@i1
])
end
it
'accesses valid merge requests'
do
...
...
@@ -53,7 +53,7 @@ describe Gitlab::ReferenceExtractor do
@m1
=
create
(
:merge_request
,
source_project:
project
,
target_project:
project
,
source_branch:
'feature_conflict'
)
subject
.
analyze
(
"!999, !
#{
@m1
.
iid
}
, and !
#{
@m0
.
iid
}
."
)
expect
(
subject
.
merge_requests
).
to
eq
([
@m1
,
@m0
])
expect
(
subject
.
merge_requests
).
to
match_array
([
@m1
,
@m0
])
end
it
'accesses valid labels'
do
...
...
@@ -62,7 +62,7 @@ describe Gitlab::ReferenceExtractor do
@l2
=
create
(
:label
)
subject
.
analyze
(
"~
#{
@l0
.
id
}
, ~999, ~
#{
@l2
.
id
}
, ~
#{
@l1
.
id
}
"
)
expect
(
subject
.
labels
).
to
eq
([
@l0
,
@l1
])
expect
(
subject
.
labels
).
to
match_array
([
@l0
,
@l1
])
end
it
'accesses valid snippets'
do
...
...
@@ -71,7 +71,7 @@ describe Gitlab::ReferenceExtractor do
@s2
=
create
(
:project_snippet
)
subject
.
analyze
(
"$
#{
@s0
.
id
}
, $999, $
#{
@s2
.
id
}
, $
#{
@s1
.
id
}
"
)
expect
(
subject
.
snippets
).
to
eq
([
@s0
,
@s1
])
expect
(
subject
.
snippets
).
to
match_array
([
@s0
,
@s1
])
end
it
'accesses valid commits'
do
...
...
@@ -109,7 +109,7 @@ describe Gitlab::ReferenceExtractor do
subject
.
analyze
(
"this refers issue
#{
issue
.
to_reference
(
project
)
}
"
)
extracted
=
subject
.
issues
expect
(
extracted
.
size
).
to
eq
(
1
)
expect
(
extracted
).
to
eq
([
issue
])
expect
(
extracted
).
to
match_array
([
issue
])
end
end
end
spec/models/concerns/issuable_spec.rb
View file @
e4008bc4
...
...
@@ -68,7 +68,6 @@ describe Issue, "Issuable" do
end
end
describe
"#to_hook_data"
do
let
(
:hook_data
)
{
issue
.
to_hook_data
(
user
)
}
...
...
spec/models/issue_spec.rb
View file @
e4008bc4
...
...
@@ -68,6 +68,43 @@ describe Issue do
end
end
describe
'#closed_by_merge_requests'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
,
state:
"opened"
)}
let
(
:closed_issue
)
{
build
(
:issue
,
project:
project
,
state:
"closed"
)}
let
(
:mr
)
do
opts
=
{
title:
'Awesome merge_request'
,
description:
"Fixes
#{
issue
.
to_reference
}
"
,
source_branch:
'feature'
,
target_branch:
'master'
}
MergeRequests
::
CreateService
.
new
(
project
,
project
.
owner
,
opts
).
execute
end
let
(
:closed_mr
)
do
opts
=
{
title:
'Awesome merge_request 2'
,
description:
"Fixes
#{
issue
.
to_reference
}
"
,
source_branch:
'feature'
,
target_branch:
'master'
,
state:
'closed'
}
MergeRequests
::
CreateService
.
new
(
project
,
project
.
owner
,
opts
).
execute
end
it
'returns the merge request to close this issue'
do
allow
(
mr
).
to
receive
(
:closes_issue?
).
with
(
issue
).
and_return
(
true
)
expect
(
issue
.
closed_by_merge_requests
).
to
eq
([
mr
])
end
it
"returns an empty array when the current issue is closed already"
do
expect
(
closed_issue
.
closed_by_merge_requests
).
to
eq
([])
end
end
it_behaves_like
'an editable mentionable'
do
subject
{
create
(
:issue
)
}
...
...
spec/models/milestone_spec.rb
View file @
e4008bc4
...
...
@@ -140,4 +140,32 @@ describe Milestone do
end
end
describe
'#sort_issues'
do
let
(
:milestone
)
{
create
(
:milestone
)
}
let
(
:issue1
)
{
create
(
:issue
,
milestone:
milestone
,
position:
1
)
}
let
(
:issue2
)
{
create
(
:issue
,
milestone:
milestone
,
position:
2
)
}
let
(
:issue3
)
{
create
(
:issue
,
milestone:
milestone
,
position:
3
)
}
let
(
:issue4
)
{
create
(
:issue
,
position:
42
)
}
it
'sorts the given issues'
do
milestone
.
sort_issues
([
issue3
.
id
,
issue2
.
id
,
issue1
.
id
])
issue1
.
reload
issue2
.
reload
issue3
.
reload
expect
(
issue1
.
position
).
to
eq
(
3
)
expect
(
issue2
.
position
).
to
eq
(
2
)
expect
(
issue3
.
position
).
to
eq
(
1
)
end
it
'ignores issues not part of the milestone'
do
milestone
.
sort_issues
([
issue3
.
id
,
issue2
.
id
,
issue1
.
id
,
issue4
.
id
])
issue4
.
reload
expect
(
issue4
.
position
).
to
eq
(
42
)
end
end
end
spec/requests/api/projects_spec.rb
View file @
e4008bc4
...
...
@@ -606,8 +606,21 @@ describe API::API, api: true do
describe
'DELETE /projects/:id/fork'
do
it
"shouldn't
available for non admin users
"
do
it
"shouldn't
be visible to users outside group
"
do
delete
api
(
"/projects/
#{
project_fork_target
.
id
}
/fork"
,
user
)
expect
(
response
.
status
).
to
eq
(
404
)
end
context
'when users belong to project group'
do
let
(
:project_fork_target
)
{
create
(
:project
,
group:
create
(
:group
))
}
before
do
project_fork_target
.
group
.
add_owner
user
project_fork_target
.
group
.
add_developer
user2
end
it
'should be forbidden to non-owner users'
do
delete
api
(
"/projects/
#{
project_fork_target
.
id
}
/fork"
,
user2
)
expect
(
response
.
status
).
to
eq
(
403
)
end
...
...
@@ -631,6 +644,7 @@ describe API::API, api: true do
end
end
end
end
describe
'GET /projects/search/:query'
do
let!
(
:query
)
{
'query'
}
...
...
spec/support/filter_spec_helper.rb
View file @
e4008bc4
...
...
@@ -29,12 +29,19 @@ module FilterSpecHelper
#
# Returns the Hash
def
pipeline_result
(
body
,
contexts
=
{})
contexts
.
reverse_merge!
(
project:
project
)
contexts
.
reverse_merge!
(
project:
project
)
if
defined?
(
project
)
pipeline
=
HTML
::
Pipeline
.
new
([
described_class
],
contexts
)
pipeline
.
call
(
body
)
end
def
reference_pipeline_result
(
body
,
contexts
=
{})
contexts
.
reverse_merge!
(
project:
project
)
if
defined?
(
project
)
pipeline
=
HTML
::
Pipeline
.
new
([
described_class
,
Gitlab
::
Markdown
::
ReferenceGathererFilter
],
contexts
)
pipeline
.
call
(
body
)
end
# Modify a String reference to make it invalid
#
# Commit SHAs get reversed, IDs get incremented by 1, all other Strings get
...
...
@@ -55,20 +62,6 @@ module FilterSpecHelper
end
end
# Stub CrossProjectReference#user_can_reference_project? to return true for
# the current test
def
allow_cross_reference!
allow_any_instance_of
(
described_class
).
to
receive
(
:user_can_reference_project?
).
and_return
(
true
)
end
# Stub CrossProjectReference#user_can_reference_project? to return false for
# the current test
def
disallow_cross_reference!
allow_any_instance_of
(
described_class
).
to
receive
(
:user_can_reference_project?
).
and_return
(
false
)
end
# Shortcut to Rails' auto-generated routes helpers, to avoid including the
# module
def
urls
...
...
spec/support/markdown_feature.rb
View file @
e4008bc4
...
...
@@ -15,18 +15,17 @@ class MarkdownFeature
end
def
group
unless
@group
@group
=
create
(
:group
)
@group
.
add_developer
(
user
)
@group
||=
create
(
:group
).
tap
do
|
group
|
group
.
add_developer
(
user
)
end
@group
end
# Direct references ----------------------------------------------------------
def
project
@project
||=
create
(
:project
)
@project
||=
create
(
:project
).
tap
do
|
project
|
project
.
team
<<
[
user
,
:master
]
end
end
def
issue
...
...
@@ -46,12 +45,10 @@ class MarkdownFeature
end
def
commit_range
unless
@commit_range
@commit_range
||=
begin
commit2
=
project
.
commit
(
'HEAD~3'
)
@commit_range
=
CommitRange
.
new
(
"
#{
commit
.
id
}
...
#{
commit2
.
id
}
"
,
project
)
CommitRange
.
new
(
"
#{
commit
.
id
}
...
#{
commit2
.
id
}
"
,
project
)
end
@commit_range
end
def
simple_label
...
...
@@ -65,13 +62,12 @@ class MarkdownFeature
# Cross-references -----------------------------------------------------------
def
xproject
unless
@xproject
@xproject
||=
begin
namespace
=
create
(
:namespace
,
name:
'cross-reference'
)
@xproject
=
create
(
:project
,
namespace:
namespace
)
@xproject
.
team
<<
[
user
,
:developer
]
create
(
:project
,
namespace:
namespace
)
do
|
project
|
project
.
team
<<
[
user
,
:developer
]
end
end
@xproject
end
def
xissue
...
...
@@ -91,12 +87,10 @@ class MarkdownFeature
end
def
xcommit_range
unless
@xcommit_range
@xcommit_range
||=
begin
xcommit2
=
xproject
.
commit
(
'HEAD~2'
)
@xcommit_range
=
CommitRange
.
new
(
"
#{
xcommit
.
id
}
...
#{
xcommit2
.
id
}
"
,
xproject
)
CommitRange
.
new
(
"
#{
xcommit
.
id
}
...
#{
xcommit2
.
id
}
"
,
xproject
)
end
@xcommit_range
end
def
raw_markdown
...
...
spec/support/mentionable_shared_examples.rb
View file @
e4008bc4
...
...
@@ -50,6 +50,8 @@ def common_mentionable_setup
}
extra_commits
.
each
{
|
c
|
commitmap
[
c
.
short_id
]
=
c
}
allow
(
Project
).
to
receive
(
:find
).
and_call_original
allow
(
Project
).
to
receive
(
:find
).
with
(
project
.
id
.
to_s
).
and_return
(
project
)
allow
(
project
.
repository
).
to
receive
(
:commit
)
{
|
sha
|
commitmap
[
sha
]
}
set_mentionable_text
.
call
(
ref_string
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment