summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/stylesheets/framework/buttons.scss18
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss4
-rw-r--r--app/assets/stylesheets/pages/issuable.scss3
-rw-r--r--app/assets/stylesheets/pages/issues.scss8
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss14
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss17
-rw-r--r--app/assets/stylesheets/pages/projects.scss16
-rw-r--r--app/assets/stylesheets/pages/status.scss8
-rw-r--r--app/assets/stylesheets/pages/tags.scss7
-rw-r--r--app/helpers/ci_status_helper.rb14
-rw-r--r--app/helpers/external_wiki_helper.rb5
-rw-r--r--app/helpers/time_helper.rb26
-rw-r--r--app/models/project.rb16
-rw-r--r--app/models/repository.rb5
-rw-r--r--app/models/service.rb8
-rw-r--r--app/models/user.rb2
-rw-r--r--app/views/layouts/_init_auto_complete.html.haml10
-rw-r--r--app/views/projects/builds/_sidebar.html.haml2
-rw-r--r--app/views/projects/buttons/_fork.html.haml4
-rw-r--r--app/views/projects/ci/pipelines/_pipeline.html.haml2
-rw-r--r--app/views/projects/forks/index.html.haml4
-rw-r--r--app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml2
-rw-r--r--app/views/projects/tags/show.html.haml67
-rw-r--r--app/views/shared/icons/_icon_fork.svg1
-rw-r--r--app/views/shared/icons/_icon_status_cancel.svg12
-rw-r--r--app/views/shared/icons/_icon_status_failed.svg12
-rw-r--r--app/views/shared/icons/_icon_status_pending.svg13
-rw-r--r--app/views/shared/icons/_icon_status_running.svg12
-rw-r--r--app/views/shared/icons/_icon_status_success.svg15
-rw-r--r--app/views/shared/icons/_icon_status_warning.svg15
-rw-r--r--config/initializers/secure_headers.rb14
-rw-r--r--config/routes.rb9
-rw-r--r--db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb8
-rw-r--r--db/migrate/20160718153603_add_has_external_wiki_to_projects.rb7
-rw-r--r--db/schema.rb3
-rw-r--r--lib/api/commit_statuses.rb2
-rw-r--r--lib/api/helpers.rb6
-rw-r--r--lib/api/merge_requests.rb2
-rw-r--r--lib/api/projects.rb2
-rw-r--r--lib/gitlab/checks/force_push.rb4
-rw-r--r--lib/gitlab/diff/position.rb4
-rw-r--r--lib/gitlab/git_access_status.rb4
-rw-r--r--lib/gitlab/gon_helper.rb2
-rw-r--r--spec/controllers/help_controller_spec.rb9
-rw-r--r--spec/helpers/ci_status_helper_spec.rb10
-rw-r--r--spec/helpers/time_helper_spec.rb25
-rw-r--r--spec/lib/gitlab/diff/position_spec.rb24
-rw-r--r--spec/models/project_spec.rb41
-rw-r--r--spec/models/repository_spec.rb48
-rw-r--r--spec/models/user_spec.rb23
-rw-r--r--spec/routing/routing_spec.rb7
53 files changed, 470 insertions, 132 deletions
diff --git a/CHANGELOG b/CHANGELOG
index a5d26db7626..1abc4afdddd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,9 +1,11 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.11.0 (unreleased)
- Fix of 'Commits being passed to custom hooks are already reachable when using the UI'
+ - Limit git rev-list output count to one in forced push check
v 8.10.0 (unreleased)
- Fix profile activity heatmap to show correct day name (eanplatter)
+ - Speed up ExternalWikiHelper#get_project_wiki_path
- Expose {should,force}_remove_source_branch (Ben Boeckel)
- Add the functionality to be able to rename a file. !5049 (tiagonbotelho)
- Disable PostgreSQL statement timeout during migrations
@@ -34,6 +36,7 @@ v 8.10.0 (unreleased)
- Added day name to contribution calendar tooltips
- Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell)
+ - Fix GFM autocomplete not working on wiki pages
- Fix MR-auto-close text added to description. !4836
- Support U2F devices in Firefox. !5177
- Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
@@ -133,6 +136,7 @@ v 8.10.0 (unreleased)
- Allow bulk (un)subscription from issues in issue index
- Fix MR diff encoding issues exporting GitLab projects
- Export and import avatar as part of project import/export
+ - Fix migration corrupting import data for old version upgrades
v 8.9.6
- Fix importing of events under notes for GitLab projects. !5154
diff --git a/Gemfile.lock b/Gemfile.lock
index 4bb7a8d0604..363904a4baa 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -578,7 +578,7 @@ GEM
railties (>= 4.2.0, < 5.1)
rinku (2.0.0)
rotp (2.1.2)
- rouge (2.0.3)
+ rouge (2.0.5)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 590b8f54363..f87b8a2ad1c 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -49,6 +49,17 @@
border-color: $border-dark;
color: $color;
}
+
+ svg {
+
+ path {
+ fill: $color;
+ }
+
+ use {
+ stroke: $color;
+ }
+ }
}
@mixin btn-green {
@@ -173,6 +184,13 @@
.caret {
margin-left: 5px;
}
+
+ svg {
+ height: 15px;
+ width: auto;
+ position: relative;
+ top: 2px;
+ }
}
.btn-lg {
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index d52e8f00172..3fa4a22258d 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -198,6 +198,10 @@ header.header-pinned-nav {
.sidebar-collapsed-icon {
cursor: pointer;
+
+ .btn {
+ background-color: $gray-light;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 542fa244689..ded437625ee 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -122,7 +122,8 @@
button {
float: right;
- padding: 3px 5px;
+ padding: 1px 5px;
+ background-color: $gray-light;
}
}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 9807c5a808d..ee3b2d2b801 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -78,6 +78,14 @@ form.edit-issue {
}
}
+.merge-request-ci-status {
+ svg {
+ margin-right: 4px;
+ position: relative;
+ top: 1px;
+ }
+}
+
@media (max-width: $screen-xs-max) {
.issue-btn-group {
width: 100%;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index fbff0c97355..5254faf723d 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -60,8 +60,10 @@
.ci_widget {
border-bottom: 1px solid #eef0f2;
- i {
+ svg {
margin-right: 4px;
+ position: relative;
+ top: 1px;
}
&.ci-success {
@@ -196,6 +198,16 @@
.merge-request-title {
margin-bottom: 2px;
+
+ .ci-status-link {
+
+ svg {
+ height: 16px;
+ width: 16px;
+ position: relative;
+ top: 3px;
+ }
+ }
}
}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index a3b72ec9574..a404f108dc4 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -49,6 +49,14 @@
.commit-link {
+ .ci-status {
+
+ svg {
+ top: 1px;
+ margin-right: 0;
+ }
+ }
+
a:hover {
text-decoration: none;
}
@@ -124,6 +132,15 @@
}
}
+ .stage-cell {
+
+ svg {
+ height: 18px;
+ width: 18px;
+ vertical-align: middle;
+ }
+ }
+
.duration,
.finished-at {
color: $table-text-gray;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index ea9f7cf0540..63853335fb6 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -129,6 +129,17 @@
color: $layout-link-gray;
}
+ svg {
+
+ path {
+ fill: $layout-link-gray;
+ }
+
+ use {
+ stroke: $layout-link-gray;
+ }
+ }
+
.fa-caret-down {
margin-left: 3px;
}
@@ -486,6 +497,11 @@ pre.light-well {
> span {
margin-left: 10px;
}
+
+ svg {
+ position: relative;
+ top: 2px;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index c6b053150be..a22d4b6f6be 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -41,6 +41,14 @@
color: $blue-normal;
border-color: $blue-normal;
}
+
+ svg {
+ height: 13px;
+ width: 13px;
+ position: relative;
+ top: 1px;
+ margin: 0 3px;
+ }
}
.ci-status-icon-success {
diff --git a/app/assets/stylesheets/pages/tags.scss b/app/assets/stylesheets/pages/tags.scss
new file mode 100644
index 00000000000..24ebd3e7cfa
--- /dev/null
+++ b/app/assets/stylesheets/pages/tags.scss
@@ -0,0 +1,7 @@
+.tag-buttons {
+ line-height: 40px;
+
+ .btn:not(.dropdown-toggle) {
+ margin-left: 10px;
+ }
+}
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index e6c99c9959e..59a8365d60b 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -26,18 +26,20 @@ module CiStatusHelper
icon_name =
case status
when 'success'
- 'check'
+ 'icon_status_success'
+ when 'success_with_warnings'
+ 'icon_status_warning'
when 'failed'
- 'close'
+ 'icon_status_failed'
when 'pending'
- 'clock-o'
+ 'icon_status_pending'
when 'running'
- 'spinner'
+ 'icon_status_running'
else
- 'circle'
+ 'icon_status_cancel'
end
- icon(icon_name + ' fw')
+ custom_icon(icon_name)
end
def render_commit_status(commit, tooltip_placement: 'auto left', cssclass: '')
diff --git a/app/helpers/external_wiki_helper.rb b/app/helpers/external_wiki_helper.rb
index 1f3401f2906..defd87d6bbe 100644
--- a/app/helpers/external_wiki_helper.rb
+++ b/app/helpers/external_wiki_helper.rb
@@ -1,8 +1,7 @@
module ExternalWikiHelper
def get_project_wiki_path(project)
- external_wiki_service = project.services.
- find { |service| service.to_param == 'external_wiki' }
- if external_wiki_service.present? && external_wiki_service.active?
+ external_wiki_service = project.external_wiki
+ if external_wiki_service
external_wiki_service.properties['external_wiki_url']
else
namespace_project_wiki_path(project.namespace, project, :home)
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index 8cb82c2d5cc..1926f03af07 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -1,14 +1,4 @@
module TimeHelper
- def duration_in_words(finished_at, started_at)
- if finished_at && started_at
- interval_in_seconds = finished_at.to_i - started_at.to_i
- elsif started_at
- interval_in_seconds = Time.now.to_i - started_at.to_i
- end
-
- time_interval_in_words(interval_in_seconds)
- end
-
def time_interval_in_words(interval_in_seconds)
minutes = interval_in_seconds / 60
seconds = interval_in_seconds - minutes * 60
@@ -25,9 +15,19 @@ module TimeHelper
end
def duration_in_numbers(finished_at, started_at)
- diff_in_seconds = finished_at.to_i - started_at.to_i
- time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S"
+ interval = interval_in_seconds(started_at, finished_at)
+ time_format = interval < 1.hour ? "%M:%S" : "%H:%M:%S"
- Time.at(diff_in_seconds).utc.strftime(time_format)
+ Time.at(interval).utc.strftime(time_format)
+ end
+
+ private
+
+ def interval_in_seconds(started_at, finished_at = nil)
+ if started_at && finished_at
+ finished_at.to_i - started_at.to_i
+ elsif started_at
+ Time.now.to_i - started_at.to_i
+ end
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index a805f5d97bc..d08b737e813 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -650,6 +650,22 @@ class Project < ActiveRecord::Base
update_column(:has_external_issue_tracker, services.external_issue_trackers.any?)
end
+ def external_wiki
+ if has_external_wiki.nil?
+ cache_has_external_wiki # Populate
+ end
+
+ if has_external_wiki
+ @external_wiki ||= services.external_wikis.first
+ else
+ nil
+ end
+ end
+
+ def cache_has_external_wiki
+ update_column(:has_external_wiki, services.external_wikis.any?)
+ end
+
def build_missing_services
services_templates = Service.where(template: true)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 1a2ac90da51..511df2d67c6 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -392,6 +392,11 @@ class Repository
expire_cache if exists?
+ # expire cache that don't depend on repository data (when expiring)
+ expire_tags_cache
+ expire_tag_count_cache
+ expire_branches_cache
+ expire_branch_count_cache
expire_root_ref_cache
expire_emptiness_caches
expire_exists_cache
diff --git a/app/models/service.rb b/app/models/service.rb
index 5432f8c7ab4..4821096379c 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -17,6 +17,7 @@ class Service < ActiveRecord::Base
after_commit :reset_updated_properties
after_commit :cache_project_has_external_issue_tracker
+ after_commit :cache_project_has_external_wiki
belongs_to :project, inverse_of: :services
has_one :service_hook
@@ -25,6 +26,7 @@ class Service < ActiveRecord::Base
scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) }
scope :issue_trackers, -> { where(category: 'issue_tracker') }
+ scope :external_wikis, -> { where(type: 'ExternalWikiService') }
scope :active, -> { where(active: true) }
scope :without_defaults, -> { where(default: false) }
@@ -212,4 +214,10 @@ class Service < ActiveRecord::Base
project.cache_has_external_issue_tracker
end
end
+
+ def cache_project_has_external_wiki
+ if project && !project.destroyed?
+ project.cache_has_external_wiki
+ end
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 3d0a033785c..975e935fa20 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -854,7 +854,7 @@ class User < ActiveRecord::Base
groups.joins(:shared_projects).select(:project_id)]
if min_access_level
- scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } }
+ scope = { access_level: Gitlab::Access.all_values.select { |access| access >= min_access_level } }
relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) }
end
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 12e7ed0e792..351100f3523 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -1,7 +1,7 @@
- project = @target_project || @project
+- noteable_class = @noteable.class if @noteable.present?
-- if @noteable
- :javascript
- GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}"
- GitLab.GfmAutoComplete.cachedData = undefined;
- GitLab.GfmAutoComplete.setup();
+:javascript
+ GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_class, type_id: params[:id])}"
+ GitLab.GfmAutoComplete.cachedData = undefined;
+ GitLab.GfmAutoComplete.setup();
diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml
index 396cc4ad925..dc57b49f27a 100644
--- a/app/views/projects/builds/_sidebar.html.haml
+++ b/app/views/projects/builds/_sidebar.html.haml
@@ -49,7 +49,7 @@
- if @build.duration
%p.build-detail-row
%span.build-light-text Duration:
- #{duration_in_words(@build.finished_at, @build.started_at)}
+ = time_interval_in_words(@build.duration)
- if @build.finished_at
%p.build-detail-row
%span.build-light-text Finished:
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index a9eaed4c5f6..a098a082854 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -2,7 +2,7 @@
- if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do
- = icon('code-fork fw')
+ = custom_icon('icon_fork')
Fork
%div.count-with-arrow
%span.arrow
@@ -10,7 +10,7 @@
= @project.forks_count
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do
- = icon('code-fork fw')
+ = custom_icon('icon_fork')
Fork
%div.count-with-arrow
%span.arrow
diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml
index 996c9073770..cb0ca7bc8e3 100644
--- a/app/views/projects/ci/pipelines/_pipeline.html.haml
+++ b/app/views/projects/ci/pipelines/_pipeline.html.haml
@@ -35,7 +35,7 @@
- stages_status = pipeline.statuses.latest.stages_status
- stages.each do |stage|
- %td
+ %td.stage-cell
- status = stages_status[stage]
- tooltip = "#{stage.titleize}: #{status || 'not found'}"
- if status
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index dbe9ddfde2f..a1d79bdabda 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -31,11 +31,11 @@
- if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do
- = icon('code-fork fw')
+ = custom_icon('icon_fork')
Fork
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do
- = icon('code-fork fw')
+ = custom_icon('icon_fork')
Fork
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index 542827b2f15..331dc1fcc29 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -51,7 +51,7 @@
%td.duration
- if generic_commit_status.duration
= icon("clock-o")
- #{duration_in_words(generic_commit_status.finished_at, generic_commit_status.started_at)}
+ = time_interval_in_words(generic_commit_status.duration)
%td.timestamp
- if generic_commit_status.finished_at
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index b7d7d5c5382..395d7af6cbb 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -1,36 +1,39 @@
+- @no_container = true
- page_title @tag.name, "Tags"
= render "projects/commits/head"
-.row-content-block
- .pull-right
- - if can?(current_user, :push_code, @project)
- = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn has-tooltip', title: 'Edit release notes' do
- = icon("pencil")
- = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse files' do
- = icon('files-o')
- = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse commits' do
- = icon('history')
- - if can? current_user, :download_code, @project
- = render 'projects/tags/download', ref: @tag.name, project: @project
- - if can?(current_user, :admin_project, @project)
- .pull-right
- = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
- %i.fa.fa-trash-o
- .title
- %span.item-title= @tag.name
- - if @commit
- = render 'projects/branches/commit', commit: @commit, project: @project
- - else
- Cant find HEAD commit for this tag
- - if @tag.message.present?
- %pre.body
- = strip_gpg_signature(@tag.message)
+%div{ class: container_class }
+ .sub-header-block
+ .pull-right.tag-buttons
+ - if can?(current_user, :push_code, @project)
+ = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Edit release notes' do
+ = icon("pencil")
+ = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse files' do
+ = icon('files-o')
+ = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse commits' do
+ = icon('history')
+ - if can? current_user, :download_code, @project
+ = render 'projects/tags/download', ref: @tag.name, project: @project
+ - if can?(current_user, :admin_project, @project)
+ .pull-right
+ = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
+ %i.fa.fa-trash-o
+ .tag-info.append-bottom-10
+ .title
+ %span.item-title= @tag.name
+ - if @commit
+ = render 'projects/branches/commit', commit: @commit, project: @project
+ - else
+ Cant find HEAD commit for this tag
+ - if @tag.message.present?
+ %pre.body
+ = strip_gpg_signature(@tag.message)
-.append-bottom-default.prepend-top-default
- - if @release.description.present?
- .description
- .wiki
- = preserve do
- = markdown @release.description
- - else
- This tag has no release notes.
+ .append-bottom-default.prepend-top-default
+ - if @release.description.present?
+ .description
+ .wiki
+ = preserve do
+ = markdown @release.description
+ - else
+ This tag has no release notes.
diff --git a/app/views/shared/icons/_icon_fork.svg b/app/views/shared/icons/_icon_fork.svg
new file mode 100644
index 00000000000..420ffe3a55b
--- /dev/null
+++ b/app/views/shared/icons/_icon_fork.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle id="a" cx="4" cy="4" r="4"/><mask id="d" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#a"/></mask><circle id="b" cx="20" cy="4" r="4"/><mask id="e" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#b"/></mask><circle id="c" cx="12" cy="30" r="4"/><mask id="f" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#c"/></mask></defs><g fill="none" fill-rule="evenodd" transform="translate(8 3)"><path fill="#7E7E7E" d="M10 19.667c-4.14-1.29-7.389-5.878-7.389-5.878C2.274 13.353 2 12.545 2 12.01V6h4v5.509c0 .276.166.65.367.831 0 0 1.136 1.028 1.746 1.574C9.617 15.261 11.048 16 12.09 16c1.028 0 2.41-.723 3.858-2.048.588-.54 1.84-1.742 1.84-1.742a.784.784 0 0 0 .211-.502V6h4v6.008c0 .548-.259 1.349-.601 1.795 0 0-3.21 4.707-7.399 5.916V27h-4v-7.333z"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#d)" xlink:href="#a"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#e)" xlink:href="#b"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#f)" xlink:href="#c"/></g></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_icon_status_cancel.svg b/app/views/shared/icons/_icon_status_cancel.svg
new file mode 100644
index 00000000000..6a0bc1490c4
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_cancel.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="a" cx="7" cy="7" r="7"/>
+ <mask id="b" width="14" height="14" x="0" y="0" fill="white">
+ <use xlink:href="#a"/>
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <use stroke="#5C5C5C" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
+ <rect width="10" height="1" x="2" y="6.5" fill="#5C5C5C" transform="rotate(45 7 7)" rx=".3"/>
+ </g>
+</svg>
diff --git a/app/views/shared/icons/_icon_status_failed.svg b/app/views/shared/icons/_icon_status_failed.svg
new file mode 100644
index 00000000000..c41ca18cae7
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_failed.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="a" cx="7" cy="7" r="7"/>
+ <mask id="b" width="14" height="14" x="0" y="0" fill="white">
+ <use xlink:href="#a"/>
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <use stroke="#D22852" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
+ <path fill="#D22852" d="M7.5,6.5 L7.5,4.30578971 C7.5,4.12531853 7.36809219,4 7.20537567,4 L6.79462433,4 C6.63904572,4 6.5,4.13690672 6.5,4.30578971 L6.5,6.5 L4.30578971,6.5 C4.12531853,6.5 4,6.63190781 4,6.79462433 L4,7.20537567 C4,7.36095428 4.13690672,7.5 4.30578971,7.5 L6.5,7.5 L6.5,9.69421029 C6.5,9.87468147 6.63190781,10 6.79462433,10 L7.20537567,10 C7.36095428,10 7.5,9.86309328 7.5,9.69421029 L7.5,7.5 L9.69421029,7.5 C9.87468147,7.5 10,7.36809219 10,7.20537567 L10,6.79462433 C10,6.63904572 9.86309328,6.5 9.69421029,6.5 L7.5,6.5 Z" transform="rotate(45 7 7)"/>
+ </g>
+</svg>
diff --git a/app/views/shared/icons/_icon_status_pending.svg b/app/views/shared/icons/_icon_status_pending.svg
new file mode 100644
index 00000000000..035cd8b4ccc
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_pending.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="a" cx="7" cy="7" r="7"/>
+ <mask id="b" width="14" height="14" x="0" y="0" fill="white">
+ <use xlink:href="#a"/>
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <use stroke="#E75E40" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
+ <rect width="1" height="4" x="5" y="5" fill="#E75E40" rx=".3"/>
+ <rect width="1" height="4" x="8" y="5" fill="#E75E40" rx=".3"/>
+ </g>
+</svg>
diff --git a/app/views/shared/icons/_icon_status_running.svg b/app/views/shared/icons/_icon_status_running.svg
new file mode 100644
index 00000000000..a48b3a25099
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_running.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="a" cx="7" cy="7" r="7"/>
+ <mask id="b" width="14" height="14" x="0" y="0" fill="white">
+ <use xlink:href="#a"/>
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <use stroke="#2D9FD8" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
+ <path fill="#2D9FD8" d="M7,3.00800862 C9.09023405,3.13960661 10.7448145,4.87657932 10.7448145,7 C10.7448145,9.209139 8.95395346,11 6.74481446,11 C5.4560962,11 4.30972054,10.3905589 3.57817301,9.44416214 L7,7 L7,3.00800862 Z"/>
+ </g>
+</svg>
diff --git a/app/views/shared/icons/_icon_status_success.svg b/app/views/shared/icons/_icon_status_success.svg
new file mode 100644
index 00000000000..260eab013a3
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_success.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="a" cx="7" cy="7" r="7"/>
+ <mask id="b" width="14" height="14" x="0" y="0" fill="white">
+ <use xlink:href="#a"/>
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <use stroke="#31AF64" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
+ <g fill="#31AF64" transform="rotate(45 -.13 10.953)">
+ <rect width="1" height="5" x="2" rx=".3"/>
+ <rect width="3" height="1" y="4" rx=".3"/>
+ </g>
+ </g>
+</svg>
diff --git a/app/views/shared/icons/_icon_status_warning.svg b/app/views/shared/icons/_icon_status_warning.svg
new file mode 100644
index 00000000000..d47e7a1c93f
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_warning.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="a" cx="7" cy="7" r="7"/>
+ <mask id="b" width="14" height="14" x="0" y="0" fill="white">
+ <use xlink:href="#a"/>
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <g fill="#FF8A24" transform="translate(6 3)">
+ <rect width="2" height="5" rx=".5"/>
+ <rect width="2" height="2" y="6" rx=".5"/>
+ </g>
+ <use stroke="#FF8A24" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
+ </g>
+</svg>
diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb
index 9fd24a667cc..253e3cf7410 100644
--- a/config/initializers/secure_headers.rb
+++ b/config/initializers/secure_headers.rb
@@ -4,14 +4,7 @@
require 'gitlab/current_settings'
include Gitlab::CurrentSettings
-# If Sentry is enabled and the Rails app is running in production mode,
-# this will construct the Report URI for Sentry.
-if Rails.env.production? && current_application_settings.sentry_enabled
- uri = URI.parse(current_application_settings.sentry_dsn)
- CSP_REPORT_URI = "#{uri.scheme}://#{uri.host}/api#{uri.path}/csp-report/?sentry_key=#{uri.user}"
-else
- CSP_REPORT_URI = ''
-end
+CSP_REPORT_URI = ''
# Content Security Policy Headers
# For more information on CSP see:
@@ -71,10 +64,7 @@ SecureHeaders::Configuration.default do |config|
upgrade_insecure_requests: true
}
- # Reports are sent to Sentry if it's enabled.
- if current_application_settings.sentry_enabled
- config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
- end
+ config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
# Allow Bootstrap Linter in development mode.
if Rails.env.development?
diff --git a/config/routes.rb b/config/routes.rb
index be651d8903f..2a9fe30b0e6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -89,11 +89,10 @@ Rails.application.routes.draw do
mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\/(info\/lfs|gitlab-lfs)/.match(request.path_info) }, via: [:get, :post, :put]
# Help
-
- get 'help' => 'help#index'
- get 'help/*path' => 'help#show', as: :help_page
- get 'help/shortcuts'
- get 'help/ui' => 'help#ui'
+ get 'help' => 'help#index'
+ get 'help/shortcuts' => 'help#shortcuts'
+ get 'help/ui' => 'help#ui'
+ get 'help/*path' => 'help#show', as: :help_page
#
# Global snippets
diff --git a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
index ac7eac0ea7c..611767ac7fe 100644
--- a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
+++ b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
@@ -7,7 +7,13 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration
class ProjectImportDataFake
extend AttrEncrypted
attr_accessor :credentials
- attr_encrypted :credentials, key: Gitlab::Application.secrets.db_key_base, marshal: true, encode: true, :mode => :per_attribute_iv_and_salt
+ attr_encrypted :credentials,
+ key: Gitlab::Application.secrets.db_key_base,
+ marshal: true,
+ encode: true,
+ :mode => :per_attribute_iv_and_salt,
+ insecure_mode: true,
+ algorithm: 'aes-256-cbc'
end
def up
diff --git a/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb b/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb
new file mode 100644
index 00000000000..55a3e954292
--- /dev/null
+++ b/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb
@@ -0,0 +1,7 @@
+class AddHasExternalWikiToProjects < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ def change
+ add_column :projects, :has_external_wiki, :boolean
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 39b02d9ba35..66ab0512efc 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160716115710) do
+ActiveRecord::Schema.define(version: 20160718153603) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -843,6 +843,7 @@ ActiveRecord::Schema.define(version: 20160716115710) do
t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false
t.boolean "has_external_issue_tracker"
t.string "repository_storage", default: "default", null: false
+ t.boolean "has_external_wiki"
end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index acb4812b5cf..4df6ca8333e 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -24,7 +24,7 @@ module API
pipelines = user_project.pipelines.where(sha: params[:sha])
statuses = ::CommitStatus.where(pipeline: pipelines)
- statuses = statuses.latest unless parse_boolean(params[:all])
+ statuses = statuses.latest unless to_boolean(params[:all])
statuses = statuses.where(ref: params[:ref]) if params[:ref].present?
statuses = statuses.where(stage: params[:stage]) if params[:stage].present?
statuses = statuses.where(name: params[:name]) if params[:name].present?
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index d6e4eb2afd7..130509cdad6 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -5,10 +5,6 @@ module API
SUDO_HEADER = "HTTP_SUDO"
SUDO_PARAM = :sudo
- def parse_boolean(value)
- [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value)
- end
-
def to_boolean(value)
return true if value =~ /^(true|t|yes|y|1|on)$/i
return false if value =~ /^(false|f|no|n|0|off)$/i
@@ -297,7 +293,7 @@ module API
def filter_projects(projects)
# If the archived parameter is passed, limit results accordingly
if params[:archived].present?
- projects = projects.where(archived: parse_boolean(params[:archived]))
+ projects = projects.where(archived: to_boolean(params[:archived]))
end
if params[:search].present?
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 4fcdf8968c9..2b685621da9 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -242,7 +242,7 @@ module API
should_remove_source_branch: params[:should_remove_source_branch]
}
- if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.pipeline && merge_request.pipeline.active?
+ if to_boolean(params[:merge_when_build_succeeds]) && merge_request.pipeline && merge_request.pipeline.active?
::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params).
execute(merge_request)
else
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 6d2a6f3946c..8fed7db8803 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -8,7 +8,7 @@ module API
def map_public_to_visibility_level(attrs)
publik = attrs.delete(:public)
if publik.present? && !attrs[:visibility_level].present?
- publik = parse_boolean(publik)
+ publik = to_boolean(publik)
# Since setting the public attribute to private could mean either
# private or internal, use the more conservative option, private.
attrs[:visibility_level] = (publik == true) ? Gitlab::VisibilityLevel::PUBLIC : Gitlab::VisibilityLevel::PRIVATE
diff --git a/lib/gitlab/checks/force_push.rb b/lib/gitlab/checks/force_push.rb
index dfa83a0eab3..5fe86553bd0 100644
--- a/lib/gitlab/checks/force_push.rb
+++ b/lib/gitlab/checks/force_push.rb
@@ -8,8 +8,8 @@ module Gitlab
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
false
else
- missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
- missed_refs.split("\n").size > 0
+ missed_ref, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list --max-count=1 #{oldrev} ^#{newrev}))
+ missed_ref.present?
end
end
end
diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb
index 989fff8918e..2fdcf8d7838 100644
--- a/lib/gitlab/diff/position.rb
+++ b/lib/gitlab/diff/position.rb
@@ -73,8 +73,8 @@ module Gitlab
diff_refs.complete?
end
- def to_json
- JSON.generate(self.to_h)
+ def to_json(opts = nil)
+ JSON.generate(self.to_h, opts)
end
def type
diff --git a/lib/gitlab/git_access_status.rb b/lib/gitlab/git_access_status.rb
index 5a806ff6e0d..09bb01be694 100644
--- a/lib/gitlab/git_access_status.rb
+++ b/lib/gitlab/git_access_status.rb
@@ -8,8 +8,8 @@ module Gitlab
@message = message
end
- def to_json
- { status: @status, message: @message }.to_json
+ def to_json(opts = nil)
+ { status: @status, message: @message }.to_json(opts)
end
end
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index d4f12cb1df9..c5a11148d33 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -5,7 +5,7 @@ module Gitlab
gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
gon.max_file_size = current_application_settings.max_attachment_size
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
- gon.shortcuts_path = help_shortcuts_path
+ gon.shortcuts_path = help_page_path('shortcuts')
gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
gon.award_menu_url = emojis_path
diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb
index 267d511c2db..347bef1e129 100644
--- a/spec/controllers/help_controller_spec.rb
+++ b/spec/controllers/help_controller_spec.rb
@@ -63,4 +63,13 @@ describe HelpController do
end
end
end
+
+ describe 'GET #ui' do
+ context 'for UI Development Kit' do
+ it 'renders found' do
+ get :ui
+ expect(response).to have_http_status(200)
+ end
+ end
+ end
end
diff --git a/spec/helpers/ci_status_helper_spec.rb b/spec/helpers/ci_status_helper_spec.rb
index 45199d0f09d..637b02d9388 100644
--- a/spec/helpers/ci_status_helper_spec.rb
+++ b/spec/helpers/ci_status_helper_spec.rb
@@ -7,7 +7,13 @@ describe CiStatusHelper do
let(:failed_commit) { double("Ci::Pipeline", status: 'failed') }
describe 'ci_icon_for_status' do
- it { expect(helper.ci_icon_for_status(success_commit.status)).to include('fa-check') }
- it { expect(helper.ci_icon_for_status(failed_commit.status)).to include('fa-close') }
+ it 'renders to correct svg on success' do
+ expect(helper).to receive(:render).with('shared/icons/icon_status_success.svg', anything)
+ helper.ci_icon_for_status(success_commit.status)
+ end
+ it 'renders the correct svg on failure' do
+ expect(helper).to receive(:render).with('shared/icons/icon_status_failed.svg', anything)
+ helper.ci_icon_for_status(failed_commit.status)
+ end
end
end
diff --git a/spec/helpers/time_helper_spec.rb b/spec/helpers/time_helper_spec.rb
index 3f62527c5bb..413ead944b9 100644
--- a/spec/helpers/time_helper_spec.rb
+++ b/spec/helpers/time_helper_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe TimeHelper do
- describe "#duration_in_words" do
+ describe "#time_interval_in_words" do
it "returns minutes and seconds" do
intervals_in_words = {
100 => "1 minute 40 seconds",
@@ -11,26 +11,23 @@ describe TimeHelper do
}
intervals_in_words.each do |interval, expectation|
- expect(duration_in_words(Time.now + interval, Time.now)).to eq(expectation)
+ expect(time_interval_in_words(interval)).to eq(expectation)
end
end
-
- it "calculates interval from now if there is no finished_at" do
- expect(duration_in_words(nil, Time.now - 5)).to eq("5 seconds")
- end
end
- describe "#time_interval_in_words" do
+ describe "#duration_in_numbers" do
it "returns minutes and seconds" do
- intervals_in_words = {
- 100 => "1 minute 40 seconds",
- 121 => "2 minutes 1 second",
- 3721 => "62 minutes 1 second",
- 0 => "0 seconds"
+ duration_in_numbers = {
+ [100, 0] => "01:40",
+ [121, 0] => "02:01",
+ [3721, 0] => "01:02:01",
+ [0, 0] => "00:00",
+ [nil, Time.now.to_i - 42] => "00:42"
}
- intervals_in_words.each do |interval, expectation|
- expect(time_interval_in_words(interval)).to eq(expectation)
+ duration_in_numbers.each do |interval, expectation|
+ expect(duration_in_numbers(*interval)).to eq(expectation)
end
end
end
diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb
index cf28628cb96..10537bea008 100644
--- a/spec/lib/gitlab/diff/position_spec.rb
+++ b/spec/lib/gitlab/diff/position_spec.rb
@@ -338,4 +338,28 @@ describe Gitlab::Diff::Position, lib: true do
end
end
end
+
+ describe "#to_json" do
+ let(:hash) do
+ {
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ base_sha: nil,
+ head_sha: nil,
+ start_sha: nil
+ }
+ end
+
+ let(:diff_position) { described_class.new(hash) }
+
+ it "returns the position as JSON" do
+ expect(JSON.parse(diff_position.to_json)).to eq(hash.stringify_keys)
+ end
+
+ it "works when nested under another hash" do
+ expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => hash.stringify_keys)
+ end
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 9dc34276f18..e3e7319beb2 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -458,6 +458,47 @@ describe Project, models: true do
end
end
+ describe "#cache_has_external_wiki" do
+ let(:project) { create(:project) }
+
+ it "stores true if there is an external wiki" do
+ services = double(:service, external_wikis: [ExternalWikiService.new])
+ expect(project).to receive(:services).and_return(services)
+
+ expect do
+ project.cache_has_external_wiki
+ end.to change { project.has_external_wiki }.to(true)
+ end
+
+ it "stores false if there is no external wiki" do
+ services = double(:service, external_wikis: [])
+ expect(project).to receive(:services).and_return(services)
+
+ expect do
+ project.cache_has_external_wiki
+ end.to change { project.has_external_wiki }.to(false)
+ end
+
+ it "changes to true if an external wiki service is created later" do
+ expect do
+ project.cache_has_external_wiki
+ end.to change { project.has_external_wiki }.to(false)
+
+ expect do
+ create(:service, type: "ExternalWikiService", project: project)
+ end.to change { project.has_external_wiki }.to(true)
+ end
+
+ it "changes to false if an external wiki service is destroyed later" do
+ service = create(:service, type: "ExternalWikiService", project: project)
+ expect(project.has_external_wiki).to be_truthy
+
+ expect do
+ service.destroy
+ end.to change { project.has_external_wiki }.to(false)
+ end
+ end
+
describe '#open_branches' do
let(:project) { create(:project) }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 110df6bbd22..59c5732c075 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -749,6 +749,30 @@ describe Repository, models: true do
repository.before_delete
end
+ it 'flushes the tags cache' do
+ expect(repository).to receive(:expire_tags_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the tag count cache' do
+ expect(repository).to receive(:expire_tag_count_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the branches cache' do
+ expect(repository).to receive(:expire_branches_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the branch count cache' do
+ expect(repository).to receive(:expire_branch_count_cache)
+
+ repository.before_delete
+ end
+
it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache)
@@ -779,6 +803,30 @@ describe Repository, models: true do
repository.before_delete
end
+ it 'flushes the tags cache' do
+ expect(repository).to receive(:expire_tags_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the tag count cache' do
+ expect(repository).to receive(:expire_tag_count_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the branches cache' do
+ expect(repository).to receive(:expire_branches_cache)
+
+ repository.before_delete
+ end
+
+ it 'flushes the branch count cache' do
+ expect(repository).to receive(:expire_branch_count_cache)
+
+ repository.before_delete
+ end
+
it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache)
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index fc74488ac0e..3bf82cf2668 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -887,16 +887,25 @@ describe User, models: true do
end
describe '#authorized_projects' do
- let!(:user) { create(:user) }
- let!(:private_project) { create(:project, :private) }
+ context 'with a minimum access level' do
+ it 'includes projects for which the user is an owner' do
+ user = create(:user)
+ project = create(:empty_project, :private, namespace: user.namespace)
- before do
- private_project.team << [user, Gitlab::Access::MASTER]
- end
+ expect(user.authorized_projects(Gitlab::Access::REPORTER))
+ .to contain_exactly(project)
+ end
- subject { user.authorized_projects }
+ it 'includes projects for which the user is a master' do
+ user = create(:user)
+ project = create(:empty_project, :private)
+
+ project.team << [user, Gitlab::Access::MASTER]
- it { is_expected.to eq([private_project]) }
+ expect(user.authorized_projects(Gitlab::Access::REPORTER))
+ .to contain_exactly(project)
+ end
+ end
end
describe '#ci_authorized_runners' do
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 2c755919456..0a52c1ab933 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -116,12 +116,9 @@ describe HelpController, "routing" do
expect(get(path)).to route_to('help#show',
path: 'workflow/protected_branches/protected_branches1',
format: 'png')
- path = '/help/shortcuts'
- expect(get(path)).to route_to('help#show',
- path: 'shortcuts')
+
path = '/help/ui'
- expect(get(path)).to route_to('help#show',
- path: 'ui')
+ expect(get(path)).to route_to('help#ui')
end
end