diff options
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 @@ [](https://gitlab.com/gitlab-org/gitlab-ce/commits/master) [](https://gitlab.com/gitlab-org/gitlab-ce/pipelines) +[](https://gemnasium.com/gitlabhq/gitlabhq) [](https://codeclimate.com/github/gitlabhq/gitlabhq) [](https://bestpractices.coreinfrastructure.org/projects/42) [](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 |