summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-09-05 16:49:34 +0100
committerPhil Hughes <me@iamphill.com>2017-09-05 16:49:34 +0100
commit68e9372acd2285055df70cdf84665febfb496166 (patch)
tree4308616ddd08eaec2c3a9442a895b570f4db6d1d
parentdf35410a9b908361843dcc9e36bcf73d4a704300 (diff)
parentd0f5b3c287f98e3e4bdab8bf26f33262cce8f4c4 (diff)
downloadgitlab-ce-68e9372acd2285055df70cdf84665febfb496166.tar.gz
Merge branch 'master' into breadcrumbs-improvements
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--README.md1
-rw-r--r--app/assets/javascripts/project.js4
-rw-r--r--app/assets/javascripts/project_select.js42
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js10
-rw-r--r--app/assets/stylesheets/framework/selects.scss1
-rw-r--r--app/controllers/concerns/issuable_collections.rb28
-rw-r--r--app/controllers/projects/issues_controller.rb5
-rw-r--r--app/controllers/projects/merge_requests_controller.rb5
-rw-r--r--app/finders/issuable_finder.rb4
-rw-r--r--app/helpers/issuables_helper.rb3
-rw-r--r--app/views/layouts/nav/_new_dashboard.html.haml4
-rw-r--r--app/views/layouts/project.html.haml8
-rw-r--r--app/views/projects/issues/_issues.html.haml2
-rw-r--r--app/views/projects/merge_requests/_merge_requests.html.haml2
-rw-r--r--changelogs/unreleased/35010-remove-goto-project-from-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/36821-fix-new-nav-wrapping-caret-and-increasing-height.yml5
-rw-r--r--changelogs/unreleased/37331-button-MR-widget.yml5
-rw-r--r--changelogs/unreleased/feature-dependency-status-badge.yml5
-rw-r--r--changelogs/unreleased/mr-index-page-performance.yml5
-rw-r--r--doc/user/permissions.md45
-rw-r--r--lib/gitlab/issuables_count_for_state.rb50
-rw-r--r--lib/tasks/gettext.rake3
-rw-r--r--spec/controllers/concerns/issuable_collections_spec.rb82
-rw-r--r--spec/finders/issues_finder_spec.rb18
-rw-r--r--spec/finders/merge_requests_finder_spec.rb14
-rw-r--r--spec/javascripts/projects_dropdown/service/projects_service_spec.js14
-rw-r--r--spec/lib/gitlab/issuables_count_for_state_spec.rb37
-rw-r--r--vendor/gitignore/Global/JetBrains.gitignore2
-rw-r--r--vendor/gitignore/Haskell.gitignore1
-rw-r--r--vendor/gitignore/Prestashop.gitignore4
-rw-r--r--vendor/gitignore/Smalltalk.gitignore4
-rw-r--r--vendor/gitignore/Symfony.gitignore3
-rw-r--r--vendor/gitignore/VisualStudio.gitignore2
-rw-r--r--vendor/gitlab-ci-yml/Go.gitlab-ci.yml32
-rw-r--r--vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml43
-rw-r--r--vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml4
-rw-r--r--vendor/gitlab-ci-yml/PHP.gitlab-ci.yml3
-rw-r--r--vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml8
39 files changed, 360 insertions, 155 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index aa7659d1b41..b08c441028b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -212,7 +212,6 @@ update-tests-metadata:
flaky-examples-check:
<<: *dedicated-runner
- <<: *except-docs
image: ruby:2.3-alpine
services: []
before_script: []
@@ -227,6 +226,7 @@ flaky-examples-check:
- branches
except:
- master
+ - /(^docs[\/-].*|.*-docs$)/
artifacts:
expire_in: 30d
paths:
diff --git a/README.md b/README.md
index 9309922ae39..9ead6d51c5d 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
[![Build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
[![Overall test coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-ce/pipelines)
+[![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.svg)](https://gemnasium.com/gitlabhq/gitlabhq)
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
[![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/42/badge)](https://bestpractices.coreinfrastructure.org/projects/42)
[![Gitter](https://badges.gitter.im/gitlabhq/gitlabhq.svg)](https://gitter.im/gitlabhq/gitlabhq?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
diff --git a/app/assets/javascripts/project.js b/app/assets/javascripts/project.js
index d7e3ab42f00..fe6602259e2 100644
--- a/app/assets/javascripts/project.js
+++ b/app/assets/javascripts/project.js
@@ -53,10 +53,6 @@ import Cookies from 'js-cookie';
return _this.changeProject($(e.currentTarget).val());
};
})(this));
- return $('.js-projects-dropdown-toggle').on('click', function(e) {
- e.preventDefault();
- return $('.js-projects-dropdown').select2('open');
- });
};
Project.prototype.changeProject = function(url) {
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index 1b4ed6be90a..fb01390f91c 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -5,48 +5,6 @@ import ProjectSelectComboButton from './project_select_combo_button';
(function() {
this.ProjectSelect = (function() {
function ProjectSelect() {
- $('.js-projects-dropdown-toggle').each(function(i, dropdown) {
- var $dropdown;
- $dropdown = $(dropdown);
- return $dropdown.glDropdown({
- filterable: true,
- filterRemote: true,
- search: {
- fields: ['name_with_namespace']
- },
- data: function(term, callback) {
- var finalCallback, projectsCallback;
- var orderBy = $dropdown.data('order-by');
- finalCallback = function(projects) {
- return callback(projects);
- };
- if (this.includeGroups) {
- projectsCallback = function(projects) {
- var groupsCallback;
- groupsCallback = function(groups) {
- var data;
- data = groups.concat(projects);
- return finalCallback(data);
- };
- return Api.groups(term, {}, groupsCallback);
- };
- } else {
- projectsCallback = finalCallback;
- }
- if (this.groupId) {
- return Api.groupProjects(this.groupId, term, projectsCallback);
- } else {
- return Api.projects(term, { order_by: orderBy }, projectsCallback);
- }
- },
- url: function(project) {
- return project.web_url;
- },
- text: function(project) {
- return project.name_with_namespace;
- }
- });
- });
$('.ajax-project-select').each(function(i, select) {
var placeholder;
this.groupId = $(select).data('group-id');
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
index c05a76a3b4a..aaca42e3ebc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
@@ -75,18 +75,20 @@ export default {
class="btn btn-small inline">
Check out branch
</a>
- <span class="dropdown inline prepend-left-10">
+ <span class="dropdown prepend-left-10">
<a
- class="btn btn-xs dropdown-toggle"
+ class="btn btn-small inline dropdown-toggle"
data-toggle="dropdown"
aria-label="Download as"
role="button">
<i
class="fa fa-download"
- aria-hidden="true" />
+ aria-hidden="true">
+ </i>
<i
class="fa fa-caret-down"
- aria-hidden="true" />
+ aria-hidden="true">
+ </i>
</a>
<ul class="dropdown-menu dropdown-menu-align-right">
<li>
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 9acdf8730af..6c14e8b97e0 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -267,6 +267,7 @@
// TODO: change global style
.ajax-project-dropdown,
+.ajax-users-dropdown,
body[data-page="projects:edit"] #select2-drop,
body[data-page="projects:new"] #select2-drop,
body[data-page="projects:merge_requests:edit"] #select2-drop,
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index a34a82b7ba6..23909bd2d39 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -36,6 +36,34 @@ module IssuableCollections
@merge_requests_finder ||= issuable_finder_for(MergeRequestsFinder)
end
+ def redirect_out_of_range(relation, total_pages)
+ return false if total_pages.zero?
+
+ out_of_range = relation.current_page > total_pages
+
+ if out_of_range
+ redirect_to(url_for(params.merge(page: total_pages, only_path: true)))
+ end
+
+ out_of_range
+ end
+
+ def issues_page_count(relation)
+ page_count_for_relation(relation, issues_finder.row_count)
+ end
+
+ def merge_requests_page_count(relation)
+ page_count_for_relation(relation, merge_requests_finder.row_count)
+ end
+
+ def page_count_for_relation(relation, row_count)
+ limit = relation.limit_value.to_f
+
+ return 1 if limit.zero?
+
+ (row_count.to_f / limit).ceil
+ end
+
def issuable_finder_for(finder_class)
finder_class.new(current_user, filter_params)
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 0d4266f0899..dc9e6f71152 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -27,10 +27,9 @@ class Projects::IssuesController < Projects::ApplicationController
@issues = issues_collection
@issues = @issues.page(params[:page])
@issuable_meta_data = issuable_meta_data(@issues, @collection_type)
+ @total_pages = issues_page_count(@issues)
- if @issues.out_of_range? && @issues.total_pages != 0
- return redirect_to url_for(params.merge(page: @issues.total_pages, only_path: true))
- end
+ return if redirect_out_of_range(@issues, @total_pages)
if params[:label_name].present?
@labels = LabelsFinder.new(current_user, project_id: @project.id, title: params[:label_name]).execute
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index e3fa3736808..5095d7fd445 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -18,10 +18,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@merge_requests = @merge_requests.page(params[:page])
@merge_requests = @merge_requests.preload(merge_request_diff: :merge_request)
@issuable_meta_data = issuable_meta_data(@merge_requests, @collection_type)
+ @total_pages = merge_requests_page_count(@merge_requests)
- if @merge_requests.out_of_range? && @merge_requests.total_pages != 0
- return redirect_to url_for(params.merge(page: @merge_requests.total_pages, only_path: true))
- end
+ return if redirect_out_of_range(@merge_requests, @total_pages)
if params[:label_name].present?
labels_params = { project_id: @project.id, title: params[:label_name] }
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index c8dd2275730..9848497f258 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -61,6 +61,10 @@ class IssuableFinder
execute.find_by(*params)
end
+ def row_count
+ Gitlab::IssuablesCountForState.new(self).for_state_or_opened(params[:state])
+ end
+
# We often get counts for each state by running a query per state, and
# counting those results. This is typically slower than running one query
# (even if that query is slower than any of the individual state queries) and
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index ef9cdd058a9..e39d62ecf63 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -249,7 +249,8 @@ module IssuablesHelper
def issuables_count_for_state(issuable_type, state)
finder = public_send("#{issuable_type}_finder") # rubocop:disable GitlabSecurity/PublicSend
- finder.count_by_state[state]
+
+ Gitlab::IssuablesCountForState.new(finder)[state]
end
def close_issuable_url(issuable)
diff --git a/app/views/layouts/nav/_new_dashboard.html.haml b/app/views/layouts/nav/_new_dashboard.html.haml
index 88d164cac32..e670e04928c 100644
--- a/app/views/layouts/nav/_new_dashboard.html.haml
+++ b/app/views/layouts/nav/_new_dashboard.html.haml
@@ -10,7 +10,7 @@
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups
- = nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm" }) do
+ = nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm hidden-md" }) do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
Activity
@@ -20,7 +20,7 @@
= icon("chevron-down", class: "dropdown-chevron")
.dropdown-menu
%ul
- = nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm" }) do
+ = nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm visible-md" }) do
= link_to activity_dashboard_path, title: 'Activity' do
Activity
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 54d56e9b873..d6db85ee87a 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -14,12 +14,4 @@
:javascript
window.uploads_path = "#{project_uploads_path(project)}";
-- content_for :header_content do
- .js-dropdown-menu-projects
- .dropdown-menu.dropdown-select.dropdown-menu-projects
- = dropdown_title("Go to a project")
- = dropdown_filter("Search your projects")
- = dropdown_content
- = dropdown_loading
-
= render template: "layouts/application"
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index 34d5a3e1831..6fb5aa45166 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -4,4 +4,4 @@
= render 'shared/empty_states/issues'
- if @issues.present?
- = paginate @issues, theme: "gitlab"
+ = paginate @issues, theme: "gitlab", total_pages: @total_pages
diff --git a/app/views/projects/merge_requests/_merge_requests.html.haml b/app/views/projects/merge_requests/_merge_requests.html.haml
index 4e97f74dd6a..bd6f1c05949 100644
--- a/app/views/projects/merge_requests/_merge_requests.html.haml
+++ b/app/views/projects/merge_requests/_merge_requests.html.haml
@@ -5,4 +5,4 @@
= render 'shared/empty_states/merge_requests'
- if @merge_requests.present?
- = paginate @merge_requests, theme: "gitlab"
+ = paginate @merge_requests, theme: "gitlab", total_pages: @total_pages
diff --git a/changelogs/unreleased/35010-remove-goto-project-from-breadcrumb.yml b/changelogs/unreleased/35010-remove-goto-project-from-breadcrumb.yml
new file mode 100644
index 00000000000..6cd7f4e9cc6
--- /dev/null
+++ b/changelogs/unreleased/35010-remove-goto-project-from-breadcrumb.yml
@@ -0,0 +1,5 @@
+---
+title: Remove project select dropdown from breadcrumb
+merge_request: 14010
+author:
+type: changed
diff --git a/changelogs/unreleased/36821-fix-new-nav-wrapping-caret-and-increasing-height.yml b/changelogs/unreleased/36821-fix-new-nav-wrapping-caret-and-increasing-height.yml
new file mode 100644
index 00000000000..54c7a8c8788
--- /dev/null
+++ b/changelogs/unreleased/36821-fix-new-nav-wrapping-caret-and-increasing-height.yml
@@ -0,0 +1,5 @@
+---
+title: Fix new navigation wrapping and causing height to grow
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/37331-button-MR-widget.yml b/changelogs/unreleased/37331-button-MR-widget.yml
new file mode 100644
index 00000000000..59bc1bd201e
--- /dev/null
+++ b/changelogs/unreleased/37331-button-MR-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Fix buttons with different height in merge request widget
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/feature-dependency-status-badge.yml b/changelogs/unreleased/feature-dependency-status-badge.yml
new file mode 100644
index 00000000000..1becff3585a
--- /dev/null
+++ b/changelogs/unreleased/feature-dependency-status-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Add badge for dependency status
+merge_request: 13588
+author: Markus Koller
+type: other
diff --git a/changelogs/unreleased/mr-index-page-performance.yml b/changelogs/unreleased/mr-index-page-performance.yml
new file mode 100644
index 00000000000..df5f44c04fa
--- /dev/null
+++ b/changelogs/unreleased/mr-index-page-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Re-use issue/MR counts for the pagination system
+merge_request:
+author:
+type: other
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index dcf210e1085..bd0a58c4cca 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -21,16 +21,16 @@ The following table depicts the various user permission levels in a project.
| Action | Guest | Reporter | Developer | Master | Owner |
|---------------------------------------|---------|------------|-------------|----------|--------|
-| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View confidential issues | (✓) [^1] | ✓ | ✓ | ✓ | ✓ |
-| Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ |
-| See a list of jobs | ✓ [^2] | ✓ | ✓ | ✓ | ✓ |
-| See a job log | ✓ [^2] | ✓ | ✓ | ✓ | ✓ |
-| Download and browse job artifacts | ✓ [^2] | ✓ | ✓ | ✓ | ✓ |
-| View wiki pages | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Pull project code | | ✓ | ✓ | ✓ | ✓ |
-| Download project | | ✓ | ✓ | ✓ | ✓ |
+| Create new issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| Create confidential issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| View confidential issues | (✓) [^2] | ✓ | ✓ | ✓ | ✓ |
+| Leave comments | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| See a list of jobs | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
+| See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
+| Download and browse job artifacts | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
+| View wiki pages | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| Pull project code | [^1] | ✓ | ✓ | ✓ | ✓ |
+| Download project | [^1] | ✓ | ✓ | ✓ | ✓ |
| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ |
@@ -71,8 +71,8 @@ The following table depicts the various user permission levels in a project.
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
| Remove project | | | | | ✓ |
-| Force push to protected branches [^3] | | | | | |
-| Remove protected branches [^3] | | | | | |
+| Force push to protected branches [^4] | | | | | |
+| Remove protected branches [^4] | | | | | |
| Remove pages | | | | | ✓ |
## Project features permissions
@@ -215,13 +215,13 @@ users:
| Run CI job | | ✓ | ✓ | ✓ |
| Clone source and LFS from current project | | ✓ | ✓ | ✓ |
| Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
-| Clone source and LFS from internal projects | | ✓ [^4] | ✓ [^4] | ✓ |
-| Clone source and LFS from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] |
+| Clone source and LFS from internal projects | | ✓ [^5] | ✓ [^5] | ✓ |
+| Clone source and LFS from private projects | | ✓ [^6] | ✓ [^6] | ✓ [^6] |
| Push source and LFS | | | | |
| Pull container images from current project | | ✓ | ✓ | ✓ |
| Pull container images from public projects | | ✓ | ✓ | ✓ |
-| Pull container images from internal projects| | ✓ [^4] | ✓ [^4] | ✓ |
-| Pull container images from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] |
+| Pull container images from internal projects| | ✓ [^5] | ✓ [^5] | ✓ |
+| Pull container images from private projects | | ✓ [^6] | ✓ [^6] | ✓ [^6] |
| Push container images to current project | | ✓ | ✓ | ✓ |
| Push container images to other projects | | | | |
@@ -243,12 +243,11 @@ with the permissions described on the documentation on [auditor users permission
Auditor users are available in [GitLab Enterprise Edition Premium](https://about.gitlab.com/gitlab-ee/)
only.
-----
-
-[^1]: Guest users can only view the confidential issues they created themselves
-[^2]: If **Public pipelines** is enabled in **Project Settings > Pipelines**
-[^3]: Not allowed for Guest, Reporter, Developer, Master, or Owner
-[^4]: Only if user is not external one.
-[^5]: Only if user is a member of the project.
+[^1]: On public and internal projects, all users are able to perform this action.
+[^2]: Guest users can only view the confidential issues they created themselves
+[^3]: If **Public pipelines** is enabled in **Project Settings > Pipelines**
+[^4]: Not allowed for Guest, Reporter, Developer, Master, or Owner
+[^5]: Only if user is not external one.
+[^6]: Only if user is a member of the project.
[ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994
[new-mod]: project/new_ci_build_permissions_model.md
diff --git a/lib/gitlab/issuables_count_for_state.rb b/lib/gitlab/issuables_count_for_state.rb
new file mode 100644
index 00000000000..505810964bc
--- /dev/null
+++ b/lib/gitlab/issuables_count_for_state.rb
@@ -0,0 +1,50 @@
+module Gitlab
+ # Class for counting and caching the number of issuables per state.
+ class IssuablesCountForState
+ # The name of the RequestStore cache key.
+ CACHE_KEY = :issuables_count_for_state
+
+ # The state values that can be safely casted to a Symbol.
+ STATES = %w[opened closed merged all].freeze
+
+ # finder - The finder class to use for retrieving the issuables.
+ def initialize(finder)
+ @finder = finder
+ @cache =
+ if RequestStore.active?
+ RequestStore[CACHE_KEY] ||= initialize_cache
+ else
+ initialize_cache
+ end
+ end
+
+ def for_state_or_opened(state = nil)
+ self[state || :opened]
+ end
+
+ # Returns the count for the given state.
+ #
+ # state - The name of the state as either a String or a Symbol.
+ #
+ # Returns an Integer.
+ def [](state)
+ state = state.to_sym if cast_state_to_symbol?(state)
+
+ cache_for_finder[state] || 0
+ end
+
+ private
+
+ def cache_for_finder
+ @cache[@finder]
+ end
+
+ def cast_state_to_symbol?(state)
+ state.is_a?(String) && STATES.include?(state)
+ end
+
+ def initialize_cache
+ Hash.new { |hash, finder| hash[finder] = finder.count_by_state }
+ end
+ end
+end
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index f7f2fa2f14c..35ba729c156 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -1,5 +1,4 @@
require "gettext_i18n_rails/tasks"
-require 'simple_po_parser'
namespace :gettext do
# Customize list of translatable files
@@ -23,6 +22,8 @@ namespace :gettext do
desc 'Lint all po files in `locale/'
task lint: :environment do
+ require 'simple_po_parser'
+
FastGettext.silence_errors
files = Dir.glob(Rails.root.join('locale/*/gitlab.po'))
diff --git a/spec/controllers/concerns/issuable_collections_spec.rb b/spec/controllers/concerns/issuable_collections_spec.rb
new file mode 100644
index 00000000000..c9687af4dd2
--- /dev/null
+++ b/spec/controllers/concerns/issuable_collections_spec.rb
@@ -0,0 +1,82 @@
+require 'spec_helper'
+
+describe IssuableCollections do
+ let(:user) { create(:user) }
+
+ let(:controller) do
+ klass = Class.new do
+ def self.helper_method(name); end
+
+ include IssuableCollections
+ end
+
+ controller = klass.new
+
+ allow(controller).to receive(:params).and_return(state: 'opened')
+
+ controller
+ end
+
+ describe '#redirect_out_of_range' do
+ before do
+ allow(controller).to receive(:url_for)
+ end
+
+ it 'returns true and redirects if the offset is out of range' do
+ relation = double(:relation, current_page: 10)
+
+ expect(controller).to receive(:redirect_to)
+ expect(controller.send(:redirect_out_of_range, relation, 2)).to eq(true)
+ end
+
+ it 'returns false if the offset is not out of range' do
+ relation = double(:relation, current_page: 1)
+
+ expect(controller).not_to receive(:redirect_to)
+ expect(controller.send(:redirect_out_of_range, relation, 2)).to eq(false)
+ end
+ end
+
+ describe '#issues_page_count' do
+ it 'returns the number of issue pages' do
+ project = create(:project, :public)
+
+ create(:issue, project: project)
+
+ finder = IssuesFinder.new(user)
+ issues = finder.execute
+
+ allow(controller).to receive(:issues_finder)
+ .and_return(finder)
+
+ expect(controller.send(:issues_page_count, issues)).to eq(1)
+ end
+ end
+
+ describe '#merge_requests_page_count' do
+ it 'returns the number of merge request pages' do
+ project = create(:project, :public)
+
+ create(:merge_request, source_project: project, target_project: project)
+
+ finder = MergeRequestsFinder.new(user)
+ merge_requests = finder.execute
+
+ allow(controller).to receive(:merge_requests_finder)
+ .and_return(finder)
+
+ pages = controller.send(:merge_requests_page_count, merge_requests)
+
+ expect(pages).to eq(1)
+ end
+ end
+
+ describe '#page_count_for_relation' do
+ it 'returns the number of pages' do
+ relation = double(:relation, limit_value: 20)
+ pages = controller.send(:page_count_for_relation, relation, 28)
+
+ expect(pages).to eq(2)
+ end
+ end
+end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 0e80df94e18..47b173dea0a 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -15,8 +15,8 @@ describe IssuesFinder do
set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) }
describe '#execute' do
- set(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') }
- set(:label_link) { create(:label_link, label: label, target: issue2) }
+ let!(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') }
+ let!(:label_link) { create(:label_link, label: label, target: issue2) }
let(:search_user) { user }
let(:params) { {} }
let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute }
@@ -347,6 +347,20 @@ describe IssuesFinder do
end
end
+ describe '#row_count', :request_store do
+ it 'returns the number of rows for the default state' do
+ finder = described_class.new(user)
+
+ expect(finder.row_count).to eq(3)
+ end
+
+ it 'returns the number of rows for a given state' do
+ finder = described_class.new(user, state: 'closed')
+
+ expect(finder.row_count).to be_zero
+ end
+ end
+
describe '#with_confidentiality_access_check' do
let(:guest) { create(:user) }
set(:authorized_user) { create(:user) }
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index b54155a6704..95f445e7905 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -108,4 +108,18 @@ describe MergeRequestsFinder do
end
end
end
+
+ describe '#row_count', :request_store do
+ it 'returns the number of rows for the default state' do
+ finder = described_class.new(user)
+
+ expect(finder.row_count).to eq(3)
+ end
+
+ it 'returns the number of rows for a given state' do
+ finder = described_class.new(user, state: 'closed')
+
+ expect(finder.row_count).to eq(1)
+ end
+ end
end
diff --git a/spec/javascripts/projects_dropdown/service/projects_service_spec.js b/spec/javascripts/projects_dropdown/service/projects_service_spec.js
index 7abfa463582..d5dd8b3449a 100644
--- a/spec/javascripts/projects_dropdown/service/projects_service_spec.js
+++ b/spec/javascripts/projects_dropdown/service/projects_service_spec.js
@@ -12,21 +12,13 @@ FREQUENT_PROJECTS.MAX_COUNT = 3;
describe('ProjectsService', () => {
let service;
- let originalGon;
beforeEach(() => {
- originalGon = window.gon;
-
- window.gon = Object.assign({}, {
- api_version: currentSession.apiVersion,
- });
+ gon.api_version = currentSession.apiVersion;
+ gon.current_user_id = 1;
service = new ProjectsService(currentSession.username);
});
- afterEach(() => {
- window.gon = originalGon;
- });
-
describe('contructor', () => {
it('should initialize default properties of class', () => {
expect(service.isLocalStorageAvailable).toBeTruthy();
@@ -44,7 +36,7 @@ describe('ProjectsService', () => {
const queryParams = {
simple: false,
per_page: 20,
- membership: false,
+ membership: true,
order_by: 'last_activity_at',
search: searchQuery,
};
diff --git a/spec/lib/gitlab/issuables_count_for_state_spec.rb b/spec/lib/gitlab/issuables_count_for_state_spec.rb
new file mode 100644
index 00000000000..c262fdfcb61
--- /dev/null
+++ b/spec/lib/gitlab/issuables_count_for_state_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Gitlab::IssuablesCountForState do
+ let(:finder) do
+ double(:finder, count_by_state: { opened: 2, closed: 1 })
+ end
+
+ let(:counter) { described_class.new(finder) }
+
+ describe '#for_state_or_opened' do
+ it 'returns the number of issuables for the given state' do
+ expect(counter.for_state_or_opened(:closed)).to eq(1)
+ end
+
+ it 'returns the number of open issuables when no state is given' do
+ expect(counter.for_state_or_opened).to eq(2)
+ end
+
+ it 'returns the number of open issuables when a nil value is given' do
+ expect(counter.for_state_or_opened(nil)).to eq(2)
+ end
+ end
+
+ describe '#[]' do
+ it 'returns the number of issuables for the given state' do
+ expect(counter[:closed]).to eq(1)
+ end
+
+ it 'casts valid states from Strings to Symbols' do
+ expect(counter['closed']).to eq(1)
+ end
+
+ it 'returns 0 when using an invalid state name as a String' do
+ expect(counter['kittens']).to be_zero
+ end
+ end
+end
diff --git a/vendor/gitignore/Global/JetBrains.gitignore b/vendor/gitignore/Global/JetBrains.gitignore
index ff23445e2b0..345e61ae3f2 100644
--- a/vendor/gitignore/Global/JetBrains.gitignore
+++ b/vendor/gitignore/Global/JetBrains.gitignore
@@ -31,7 +31,7 @@ cmake-build-debug/
## Plugin-specific files:
# IntelliJ
-/out/
+out/
# mpeltonen/sbt-idea plugin
.idea_modules/
diff --git a/vendor/gitignore/Haskell.gitignore b/vendor/gitignore/Haskell.gitignore
index 450f32ec40c..eee88b2f0f7 100644
--- a/vendor/gitignore/Haskell.gitignore
+++ b/vendor/gitignore/Haskell.gitignore
@@ -18,3 +18,4 @@ cabal.sandbox.config
.stack-work/
cabal.project.local
.HTF/
+.ghc.environment.*
diff --git a/vendor/gitignore/Prestashop.gitignore b/vendor/gitignore/Prestashop.gitignore
index 7c6ae1e31cc..81f45e19eba 100644
--- a/vendor/gitignore/Prestashop.gitignore
+++ b/vendor/gitignore/Prestashop.gitignore
@@ -7,8 +7,10 @@ config/settings.*.php
# The following files are generated by PrestaShop.
admin-dev/autoupgrade/
-/cache/
+/cache/*
!/cache/index.php
+!/cache/*/
+/cache/*/*
!/cache/cachefs/index.php
!/cache/purifier/index.php
!/cache/push/index.php
diff --git a/vendor/gitignore/Smalltalk.gitignore b/vendor/gitignore/Smalltalk.gitignore
index 75272b23472..943995e1172 100644
--- a/vendor/gitignore/Smalltalk.gitignore
+++ b/vendor/gitignore/Smalltalk.gitignore
@@ -13,6 +13,10 @@ SqueakDebug.log
# Monticello package cache
/package-cache
+# playground cache
+/play-cache
+/play-stash
+
# Metacello-github cache
/github-cache
github-*.zip
diff --git a/vendor/gitignore/Symfony.gitignore b/vendor/gitignore/Symfony.gitignore
index 6c224e024e9..85fd714a965 100644
--- a/vendor/gitignore/Symfony.gitignore
+++ b/vendor/gitignore/Symfony.gitignore
@@ -39,3 +39,6 @@
# Backup entities generated with doctrine:generate:entities command
**/Entity/*~
+
+# Embedded web-server pid file
+/.web-server-pid
diff --git a/vendor/gitignore/VisualStudio.gitignore b/vendor/gitignore/VisualStudio.gitignore
index 22fd88a55a3..89c66054885 100644
--- a/vendor/gitignore/VisualStudio.gitignore
+++ b/vendor/gitignore/VisualStudio.gitignore
@@ -151,7 +151,7 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
+# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
diff --git a/vendor/gitlab-ci-yml/Go.gitlab-ci.yml b/vendor/gitlab-ci-yml/Go.gitlab-ci.yml
index e23b6e212f0..8a214352d2a 100644
--- a/vendor/gitlab-ci-yml/Go.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Go.gitlab-ci.yml
@@ -1,14 +1,19 @@
image: golang:latest
+variables:
+ # Please edit to your GitLab project
+ REPO_NAME: gitlab.com/namespace/project
+
# The problem is that to be able to use go get, one needs to put
# the repository in the $GOPATH. So for example if your gitlab domain
-# is mydomainperso.com, and that your repository is repos/projectname, and
+# is gitlab.com, and that your repository is namespace/project, and
# the default GOPATH being /go, then you'd need to have your
-# repository in /go/src/mydomainperso.com/repos/projectname
+# repository in /go/src/gitlab.com/namespace/project
# Thus, making a symbolic link corrects this.
before_script:
- - ln -s /builds /go/src/mydomainperso.com
- - cd /go/src/mydomainperso.com/repos/projectname
+ - mkdir -p $GOPATH/src/$REPO_NAME
+ - ln -svf $CI_PROJECT_DIR/* $GOPATH/src/$REPO_NAME
+ - cd $GOPATH/src/$REPO_NAME
stages:
- test
@@ -17,21 +22,14 @@ stages:
format:
stage: test
script:
- # Add here all the dependencies, or use glide/govendor to get
- # them automatically.
- # - curl https://glide.sh/get | sh
- - go get github.com/alecthomas/kingpin
- - go tool vet -composites=false -shadow=true *.go
- - go test -race $(go list ./... | grep -v /vendor/)
+ - go fmt $(go list ./... | grep -v /vendor/)
+ - go vet $(go list ./... | grep -v /vendor/)
+ - go test -race $(go list ./... | grep -v /vendor/)
compile:
stage: build
script:
- # Add here all the dependencies, or use glide/govendor/...
- # to get them automatically.
- - go get github.com/alecthomas/kingpin
- # Better put this in a Makefile
- - go build -race -ldflags "-extldflags '-static'" -o mybinary
+ - go build -race -ldflags "-extldflags '-static'" -o mybinary
artifacts:
- paths:
- - mybinary
+ paths:
+ - mybinary
diff --git a/vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml b/vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml
index a65e48a3389..48d98dddfad 100644
--- a/vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml
@@ -1,41 +1,36 @@
-# This template uses the java:8 docker image because there isn't any
-# official Gradle image at this moment
-#
# This is the Gradle build system for JVM applications
# https://gradle.org/
# https://github.com/gradle/gradle
-image: java:8
+image: gradle:alpine
# Disable the Gradle daemon for Continuous Integration servers as correctness
# is usually a priority over speed in CI environments. Using a fresh
# runtime for each build is more reliable since the runtime is completely
# isolated from any previous builds.
variables:
- GRADLE_OPTS: "-Dorg.gradle.daemon=false"
+ GRADLE_OPTS: "-Dorg.gradle.daemon=false"
-# Make the gradle wrapper executable. This essentially downloads a copy of
-# Gradle to build the project with.
-# https://docs.gradle.org/current/userguide/gradle_wrapper.html
-# It is expected that any modern gradle project has a wrapper
before_script:
- - chmod +x gradlew
+ - export GRADLE_USER_HOME=`pwd`/.gradle
-# We redirect the gradle user home using -g so that it caches the
-# wrapper and dependencies.
-# https://docs.gradle.org/current/userguide/gradle_command_line.html
-#
-# Unfortunately it also caches the build output so
-# cleaning removes reminants of any cached builds.
-# The assemble task actually builds the project.
-# If it fails here, the tests can't run.
build:
stage: build
- script:
- - ./gradlew -g /cache/.gradle clean assemble
- allow_failure: false
+ script: gradle --build-cache assemble
+ cache:
+ key: "$CI_COMMIT_REF_NAME"
+ policy: push
+ paths:
+ - build
+ - .gradle
+
-# Use the generated build output to run the tests.
test:
stage: test
- script:
- - ./gradlew -g /cache/.gradle check
+ script: gradle check
+ cache:
+ key: "$CI_COMMIT_REF_NAME"
+ policy: pull
+ paths:
+ - build
+ - .gradle
+
diff --git a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
index 434de4f055a..0ad662cf704 100644
--- a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
@@ -34,6 +34,10 @@ before_script:
# Install php extensions
- docker-php-ext-install mbstring mcrypt pdo_mysql curl json intl gd xml zip bz2 opcache
+ # Install & enable Xdebug for code coverage reports
+ - pecl install xdebug
+ - docker-php-ext-enable xdebug
+
# Install Composer and project dependencies.
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install
diff --git a/vendor/gitlab-ci-yml/PHP.gitlab-ci.yml b/vendor/gitlab-ci-yml/PHP.gitlab-ci.yml
index bb8caa49d6b..33f44ee9222 100644
--- a/vendor/gitlab-ci-yml/PHP.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/PHP.gitlab-ci.yml
@@ -11,6 +11,9 @@ before_script:
- apt-get install -yqq git libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev
# Install PHP extensions
- docker-php-ext-install mbstring mcrypt pdo_pgsql curl json intl gd xml zip bz2 opcache
+# Install & enable Xdebug for code coverage reports
+- pecl install xdebug
+- docker-php-ext-enable xdebug
# Install and run Composer
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install
diff --git a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
index 4e181e85451..ff7bdd32239 100644
--- a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
@@ -1,6 +1,6 @@
# Official language image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/ruby/tags/
-image: "ruby:2.3"
+image: "ruby:2.4"
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
@@ -40,9 +40,9 @@ rails:
variables:
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
script:
- - bundle exec rake db:migrate
- - bundle exec rake db:seed
- - bundle exec rake test
+ - rails db:migrate
+ - rails db:seed
+ - rails test
# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk
# are supported too: https://github.com/travis-ci/dpl