diff options
Diffstat (limited to 'app')
33 files changed, 243 insertions, 173 deletions
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js index 32cb42c8b10..81697af189b 100644 --- a/app/assets/javascripts/fly_out_nav.js +++ b/app/assets/javascripts/fly_out_nav.js @@ -1,4 +1,3 @@ -import Cookies from 'js-cookie'; import bp from './breakpoints'; const HIDE_INTERVAL_TIMEOUT = 300; @@ -8,9 +7,11 @@ const IS_SHOWING_FLY_OUT_CLASS = 'is-showing-fly-out'; let currentOpenMenu = null; let menuCornerLocs; let timeoutId; +let sidebar; export const mousePos = []; +export const setSidebar = (el) => { sidebar = el; }; export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; }; export const slope = (a, b) => (b.y - a.y) / (b.x - a.x); @@ -20,10 +21,8 @@ let headerHeight = 50; export const getHeaderHeight = () => headerHeight; export const canShowActiveSubItems = (el) => { - const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md'; - - if (el.classList.contains('active') && !isHiddenByMedia) { - return Cookies.get('sidebar_collapsed') === 'true'; + if (el.classList.contains('active') && (sidebar && !sidebar.classList.contains('sidebar-icons-only'))) { + return false; } return true; @@ -143,13 +142,13 @@ export const documentMouseMove = (e) => { }; export default () => { - const sidebar = document.querySelector('.sidebar-top-level-items'); + sidebar = document.querySelector('.nav-sidebar'); if (!sidebar) return; const items = [...sidebar.querySelectorAll('.sidebar-top-level-items > li')]; - sidebar.addEventListener('mouseleave', () => { + sidebar.querySelector('.sidebar-top-level-items').addEventListener('mouseleave', () => { clearTimeout(timeoutId); timeoutId = setTimeout(() => { diff --git a/app/assets/javascripts/issue_show/components/edited.vue b/app/assets/javascripts/issue_show/components/edited.vue index d59e6d11032..992b7064c13 100644 --- a/app/assets/javascripts/issue_show/components/edited.vue +++ b/app/assets/javascripts/issue_show/components/edited.vue @@ -37,7 +37,7 @@ export default { Edited <time-ago-tooltip v-if="updatedAt" - placement="bottom" + tooltip-placement="bottom" :time="updatedAt" /> <span diff --git a/app/assets/javascripts/monitoring/components/monitoring.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index a6a2d3119e3..74244faa5d9 100644 --- a/app/assets/javascripts/monitoring/components/monitoring.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -3,8 +3,9 @@ import _ from 'underscore'; import statusCodes from '../../lib/utils/http_status'; import MonitoringService from '../services/monitoring_service'; - import monitoringRow from './monitoring_row.vue'; - import monitoringState from './monitoring_state.vue'; + import GraphGroup from './graph_group.vue'; + import GraphRow from './graph_row.vue'; + import EmptyState from './empty_state.vue'; import MonitoringStore from '../stores/monitoring_store'; import eventHub from '../event_hub'; @@ -31,8 +32,9 @@ }, components: { - monitoringRow, - monitoringState, + GraphGroup, + GraphRow, + EmptyState, }, methods: { @@ -94,7 +96,6 @@ this.updatedAspectRatios = 0; } }, - }, created() { @@ -118,40 +119,27 @@ }, }; </script> + <template> - <div - class="prometheus-graphs" - v-if="!showEmptyState"> - <div - class="row" + <div v-if="!showEmptyState" class="prometheus-graphs"> + <graph-group v-for="(groupData, index) in store.groups" - :key="index"> - <div - class="col-md-12"> - <div - class="panel panel-default prometheus-panel"> - <div - class="panel-heading"> - <h4>{{groupData.group}}</h4> - </div> - <div - class="panel-body"> - <monitoring-row - v-for="(row, index) in groupData.metrics" - :key="index" - :row-data="row" - :update-aspect-ratio="updateAspectRatio" - :deployment-data="store.deploymentData" - /> - </div> - </div> - </div> - </div> + :key="index" + :name="groupData.group" + > + <graph-row + v-for="(row, index) in groupData.metrics" + :key="index" + :row-data="row" + :update-aspect-ratio="updateAspectRatio" + :deployment-data="store.deploymentData" + /> + </graph-group> </div> - <monitoring-state + <empty-state + v-else :selected-state="state" :documentation-path="documentationPath" :settings-path="settingsPath" - v-else /> </template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue index 598021aa4df..a8708be76de 100644 --- a/app/assets/javascripts/monitoring/components/monitoring_state.vue +++ b/app/assets/javascripts/monitoring/components/empty_state.vue @@ -62,49 +62,33 @@ }, }; </script> + <template> - <div - class="prometheus-state"> - <div - class="row"> - <div - class="col-md-4 col-md-offset-4 state-svg" - v-html="currentState.svg"> - </div> + <div class="prometheus-state"> + <div class="row"> + <div class="col-md-4 col-md-offset-4 state-svg" v-html="currentState.svg"></div> </div> - <div - class="row"> - <div - class="col-md-6 col-md-offset-3"> - <h4 - class="text-center state-title"> + <div class="row"> + <div class="col-md-6 col-md-offset-3"> + <h4 class="text-center state-title"> {{currentState.title}} </h4> </div> </div> - <div - class="row"> - <div - class="col-md-6 col-md-offset-3"> - <div - class="description-text text-center state-description"> - {{currentState.description}} - <a - :href="settingsPath" - v-if="showButtonDescription"> - Prometheus server - </a> + <div class="row"> + <div class="col-md-6 col-md-offset-3"> + <div class="description-text text-center state-description"> + {{currentState.description}} + <a v-if="showButtonDescription" :href="settingsPath"> + Prometheus server + </a> </div> </div> </div> - <div - class="row state-button-section"> - <div - class="col-md-4 col-md-offset-4 text-center state-button"> - <a - class="btn btn-success" - :href="buttonPath"> - {{currentState.buttonText}} + <div class="row state-button-section"> + <div class="col-md-4 col-md-offset-4 text-center state-button"> + <a class="btn btn-success" :href="buttonPath"> + {{currentState.buttonText}} </a> </div> </div> diff --git a/app/assets/javascripts/monitoring/components/monitoring_column.vue b/app/assets/javascripts/monitoring/components/graph.vue index a31c26fb4fc..6f6da9e1463 100644 --- a/app/assets/javascripts/monitoring/components/monitoring_column.vue +++ b/app/assets/javascripts/monitoring/components/graph.vue @@ -1,8 +1,8 @@ <script> import d3 from 'd3'; - import monitoringLegends from './monitoring_legends.vue'; - import monitoringFlag from './monitoring_flag.vue'; - import monitoringDeployment from './monitoring_deployment.vue'; + import GraphLegend from './graph/legend.vue'; + import GraphFlag from './graph/flag.vue'; + import GraphDeployment from './graph/deployment.vue'; import MonitoringMixin from '../mixins/monitoring_mixins'; import eventHub from '../event_hub'; import measurements from '../utils/measurements'; @@ -14,7 +14,7 @@ export default { props: { - columnData: { + graphData: { type: Object, required: true, }, @@ -66,9 +66,9 @@ }, components: { - monitoringLegends, - monitoringFlag, - monitoringDeployment, + GraphLegend, + GraphFlag, + GraphDeployment, }, computed: { @@ -97,7 +97,7 @@ methods: { draw() { const breakpointSize = bp.getBreakpointSize(); - const query = this.columnData.queries[0]; + const query = this.graphData.queries[0]; this.margin = measurements.large.margin; if (breakpointSize === 'xs' || breakpointSize === 'sm') { this.graphHeight = 300; @@ -106,7 +106,7 @@ } this.data = query.result[0].values; this.unitOfDisplay = query.unit || ''; - this.yAxisLabel = this.columnData.y_label || 'Values'; + this.yAxisLabel = this.graphData.y_label || 'Values'; this.legendTitle = query.label || 'Average'; this.graphWidth = this.$refs.baseSvg.clientWidth - this.margin.left - this.margin.right; @@ -224,7 +224,7 @@ :class="classType"> <h5 class="text-center graph-title"> - {{columnData.title}} + {{graphData.title}} </h5> <div class="prometheus-svg-container" @@ -240,7 +240,7 @@ class="y-axis" transform="translate(70, 20)"> </g> - <monitoring-legends + <graph-legend :graph-width="graphWidth" :graph-height="graphHeight" :margin="margin" @@ -268,13 +268,13 @@ stroke-width="2" transform="translate(-5, 20)"> </path> - <monitoring-deployment + <graph-deployment :show-deploy-info="showDeployInfo" :deployment-data="reducedDeploymentData" :graph-height="graphHeight" :graph-height-offset="graphHeightOffset" /> - <monitoring-flag + <graph-flag v-if="showFlag" :current-x-coordinate="currentXCoordinate" :current-y-coordinate="currentYCoordinate" diff --git a/app/assets/javascripts/monitoring/components/monitoring_deployment.vue b/app/assets/javascripts/monitoring/components/graph/deployment.vue index dadbcd1aaa6..3623d2ed946 100644 --- a/app/assets/javascripts/monitoring/components/monitoring_deployment.vue +++ b/app/assets/javascripts/monitoring/components/graph/deployment.vue @@ -1,5 +1,5 @@ <script> - import { dateFormat, timeFormat } from '../utils/date_time_formatters'; + import { dateFormat, timeFormat } from '../../utils/date_time_formatters'; export default { props: { diff --git a/app/assets/javascripts/monitoring/components/monitoring_flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue index 61cbeeebb17..c4d4647d240 100644 --- a/app/assets/javascripts/monitoring/components/monitoring_flag.vue +++ b/app/assets/javascripts/monitoring/components/graph/flag.vue @@ -1,5 +1,5 @@ <script> - import { dateFormat, timeFormat } from '../utils/date_time_formatters'; + import { dateFormat, timeFormat } from '../../utils/date_time_formatters'; export default { props: { diff --git a/app/assets/javascripts/monitoring/components/monitoring_legends.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue index 922a5e1bf0e..d08f9cbffd4 100644 --- a/app/assets/javascripts/monitoring/components/monitoring_legends.vue +++ b/app/assets/javascripts/monitoring/components/graph/legend.vue @@ -74,7 +74,7 @@ }; </script> <template> - <g + <g class="axis-label-container"> <line class="label-x-axis-line" @@ -100,7 +100,7 @@ :width="yLabelWidth" :height="yLabelHeight"> </rect> - <text + <text class="label-axis-text y-label-text" text-anchor="middle" :transform="textTransform" diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue new file mode 100644 index 00000000000..32c90fda8cc --- /dev/null +++ b/app/assets/javascripts/monitoring/components/graph_group.vue @@ -0,0 +1,21 @@ +<script> +export default { + props: { + name: { + type: String, + required: true, + }, + }, +}; +</script> + +<template> + <div class="panel panel-default prometheus-panel"> + <div class="panel-heading"> + <h4>{{name}}</h4> + </div> + <div class="panel-body"> + <slot /> + </div> + </div> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_row.vue b/app/assets/javascripts/monitoring/components/graph_row.vue index e5528f17880..bdb9149c3b4 100644 --- a/app/assets/javascripts/monitoring/components/monitoring_row.vue +++ b/app/assets/javascripts/monitoring/components/graph_row.vue @@ -1,5 +1,5 @@ <script> - import monitoringColumn from './monitoring_column.vue'; + import Graph from './graph.vue'; export default { props: { @@ -17,7 +17,7 @@ }, }, components: { - monitoringColumn, + Graph, }, computed: { bootstrapClass() { @@ -26,12 +26,12 @@ }, }; </script> + <template> - <div - class="prometheus-row row"> - <monitoring-column - v-for="(column, index) in rowData" - :column-data="column" + <div class="prometheus-row row"> + <graph + v-for="(graphData, index) in rowData" + :graph-data="graphData" :class-type="bootstrapClass" :key="index" :update-aspect-ratio="updateAspectRatio" diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js index 5d5cb56af72..ef280e02092 100644 --- a/app/assets/javascripts/monitoring/monitoring_bundle.js +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -1,10 +1,10 @@ import Vue from 'vue'; -import Monitoring from './components/monitoring.vue'; +import Dashboard from './components/dashboard.vue'; document.addEventListener('DOMContentLoaded', () => new Vue({ el: '#prometheus-graphs', components: { - 'monitoring-dashboard': Monitoring, + Dashboard, }, - render: createElement => createElement('monitoring-dashboard'), + render: createElement => createElement('dashboard'), })); diff --git a/app/assets/javascripts/new_sidebar.js b/app/assets/javascripts/new_sidebar.js index b18d12b48b5..05e3f33f5ed 100644 --- a/app/assets/javascripts/new_sidebar.js +++ b/app/assets/javascripts/new_sidebar.js @@ -15,6 +15,7 @@ export default class NewNavSidebar { this.$openSidebar = $('.toggle-mobile-nav'); this.$closeSidebar = $('.close-nav-button'); this.$sidebarToggle = $('.js-toggle-sidebar'); + this.$topLevelLinks = $('.sidebar-top-level-items > li > a'); } bindEvents() { @@ -50,6 +51,10 @@ export default class NewNavSidebar { this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed); } NewNavSidebar.setCollapsedCookie(collapsed); + + this.$topLevelLinks.attr('title', function updateTopLevelTitle() { + return collapsed ? this.getAttribute('aria-label') : ''; + }); } render() { diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue index 5df317a76bf..010063a0240 100644 --- a/app/assets/javascripts/pipelines/components/pipelines.vue +++ b/app/assets/javascripts/pipelines/components/pipelines.vue @@ -139,7 +139,9 @@ }; </script> <template> - <div :class="cssClass"> + <div + class="pipelines-container" + :class="cssClass"> <div class="top-area scrolling-tabs-container inner-page-scroll-tabs" v-if="!isLoading && !shouldRenderEmptyState"> diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 4cf2f46c6d3..5871383a57b 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -189,7 +189,7 @@ width: auto; top: 100%; left: 0; - z-index: 9; + z-index: 200; min-width: 240px; max-width: 500px; margin-top: 2px; @@ -797,3 +797,5 @@ margin-top: 2px; } } + +@include new-style-dropdown('.js-namespace-select + '); diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 8018eb8ba84..a39927eb0df 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, +body[data-page="projects:new"] #select2-drop, body[data-page="projects:blob:new"] #select2-drop, body[data-page="profiles:show"] #select2-drop, body[data-page="projects:blob:edit"] #select2-drop { diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index b2423bc1a66..3c0b4c82d19 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -25,6 +25,7 @@ min-width: inherit; min-height: inherit; background-color: inherit; + max-width: 100%; } p a:not(.no-attachment-icon) img { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 334bec8dd7e..9d51c0b7a8a 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -612,6 +612,8 @@ } .mr-version-controls { + @include new-style-dropdown; + position: relative; background: $gray-light; color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index a408bde37d6..51656669c98 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -927,3 +927,7 @@ button.mini-pipeline-graph-dropdown-toggle { } } } + +.pipelines-container .top-area .nav-controls > .btn:last-child { + float: none; +} diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index 54f78fc8719..59be955599d 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -55,7 +55,7 @@ class AutocompleteController < ApplicationController .limit(AWARD_EMOJI_MAX) .where(user: current_user) .group(:name) - .order(count: :desc, name: :asc) + .order('count_all DESC, name ASC') .count # Transform from hash to array to guarantee json order diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb index ee701076a14..3308ab0c259 100644 --- a/app/helpers/tab_helper.rb +++ b/app/helpers/tab_helper.rb @@ -119,4 +119,8 @@ module TabHelper 'active' if current_controller?('oauth/applications') end + + def sidebar_link(href, title: nil, css: nil, &block) + link_to capture(&block), href, title: (title if collapsed_sidebar?), class: css, aria: { label: title } + end end diff --git a/app/models/environment.rb b/app/models/environment.rb index e9ebf0637f3..435eeaf0e2e 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -114,7 +114,7 @@ class Environment < ActiveRecord::Base end def ref_path - "refs/environments/#{Shellwords.shellescape(name)}" + "refs/#{Repository::REF_ENVIRONMENTS}/#{Shellwords.shellescape(name)}" end def formatted_external_url diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 7f73de67625..5be2f6d4e82 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -803,7 +803,7 @@ class MergeRequest < ActiveRecord::Base end def ref_path - "refs/merge-requests/#{iid}/head" + "refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/head" end def ref_fetched? diff --git a/app/models/project.rb b/app/models/project.rb index d5324ceac31..9d7bea4eb66 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -372,11 +372,7 @@ class Project < ActiveRecord::Base if Gitlab::ImportSources.importer_names.include?(project.import_type) && project.repo_exists? project.run_after_commit do - begin - Projects::HousekeepingService.new(project).execute - rescue Projects::HousekeepingService::LeaseTaken => e - Rails.logger.info("Could not perform housekeeping for project #{project.full_path} (#{project.id}): #{e}") - end + Projects::AfterImportService.new(project).execute end end end diff --git a/app/models/repository.rb b/app/models/repository.rb index cb7aba89020..d29d2a83708 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,6 +1,18 @@ require 'securerandom' class Repository + REF_MERGE_REQUEST = 'merge-requests'.freeze + REF_KEEP_AROUND = 'keep-around'.freeze + REF_ENVIRONMENTS = 'environments'.freeze + + RESERVED_REFS_NAMES = %W[ + heads + tags + #{REF_ENVIRONMENTS} + #{REF_KEEP_AROUND} + #{REF_ENVIRONMENTS} + ].freeze + include Gitlab::ShellAdapter include RepositoryMirroring @@ -60,6 +72,10 @@ class Repository @project = project end + def ==(other) + @disk_path == other.disk_path + end + def raw_repository return nil unless full_path @@ -75,6 +91,10 @@ class Repository ) end + def inspect + "#<#{self.class.name}:#{@disk_path}>" + end + # # Git repository can contains some hidden refs like: # /refs/notes/* @@ -234,10 +254,10 @@ class Repository begin write_ref(keep_around_ref_name(sha), sha) rescue Rugged::ReferenceError => ex - Rails.logger.error "Unable to create keep-around reference for repository #{path}: #{ex}" + Rails.logger.error "Unable to create #{REF_KEEP_AROUND} reference for repository #{path}: #{ex}" rescue Rugged::OSError => ex raise unless ex.message =~ /Failed to create locked file/ && ex.message =~ /File exists/ - Rails.logger.error "Unable to create keep-around reference for repository #{path}: #{ex}" + Rails.logger.error "Unable to create #{REF_KEEP_AROUND} reference for repository #{path}: #{ex}" end end @@ -992,25 +1012,22 @@ class Repository end def with_repo_branch_commit(start_repository, start_branch_name) - return yield(nil) if start_repository.empty_repo? + return yield nil if start_repository.empty_repo? - branch_name_or_sha = - if start_repository == self - start_branch_name - else - tmp_ref = fetch_ref( - start_repository.path_to_repo, - "#{Gitlab::Git::BRANCH_REF_PREFIX}#{start_branch_name}", - "refs/tmp/#{SecureRandom.hex}/head" - ) + if start_repository == self + yield commit(start_branch_name) + else + sha = start_repository.commit(start_branch_name).sha - start_repository.commit(start_branch_name).sha + if branch_commit = commit(sha) + yield branch_commit + else + with_repo_tmp_commit( + start_repository, start_branch_name, sha) do |tmp_commit| + yield tmp_commit + end end - - yield(commit(branch_name_or_sha)) - - ensure - rugged.references.delete(tmp_ref) if tmp_ref + end end def add_remote(name, url) @@ -1159,7 +1176,7 @@ class Repository end def keep_around_ref_name(sha) - "refs/keep-around/#{sha}" + "refs/#{REF_KEEP_AROUND}/#{sha}" end def repository_event(event, tags = {}) @@ -1219,4 +1236,16 @@ class Repository .commits_by_message(query, revision: ref, path: path, limit: limit, offset: offset) .map { |c| commit(c) } end + + def with_repo_tmp_commit(start_repository, start_branch_name, sha) + tmp_ref = fetch_ref( + start_repository.path_to_repo, + "#{Gitlab::Git::BRANCH_REF_PREFIX}#{start_branch_name}", + "refs/tmp/#{SecureRandom.hex}/head" + ) + + yield commit(sha) + ensure + delete_refs(tmp_ref) if tmp_ref + end end diff --git a/app/models/user.rb b/app/models/user.rb index fbd08bc4d0a..70787de4b40 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,6 +5,7 @@ class User < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::CurrentSettings + include Gitlab::SQL::Pattern include Avatarable include Referable include Sortable @@ -303,7 +304,7 @@ class User < ActiveRecord::Base # Returns an ActiveRecord::Relation. def search(query) table = arel_table - pattern = "%#{query}%" + pattern = User.to_pattern(query) order = <<~SQL CASE diff --git a/app/services/projects/after_import_service.rb b/app/services/projects/after_import_service.rb new file mode 100644 index 00000000000..e6a68d983ef --- /dev/null +++ b/app/services/projects/after_import_service.rb @@ -0,0 +1,29 @@ +module Projects + class AfterImportService + RESERVED_REFS_REGEXP = + %r{\Arefs/(?:#{Regexp.union(*Repository::RESERVED_REFS_NAMES)})/} + + def initialize(project) + @project = project + end + + def execute + Projects::HousekeepingService.new(@project).execute do + repository.delete_refs(*garbage_refs) + end + rescue Projects::HousekeepingService::LeaseTaken => e + Rails.logger.info( + "Could not perform housekeeping for project #{@project.full_path} (#{@project.id}): #{e}") + end + + private + + def garbage_refs + @garbage_refs ||= repository.all_ref_names_except(RESERVED_REFS_REGEXP) + end + + def repository + @repository ||= @project.repository + end + end +end diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb index d66ef676088..dcef8b66215 100644 --- a/app/services/projects/housekeeping_service.rb +++ b/app/services/projects/housekeeping_service.rb @@ -26,6 +26,8 @@ module Projects lease_uuid = try_obtain_lease raise LeaseTaken unless lease_uuid.present? + yield if block_given? + execute_gitlab_shell_gc(lease_uuid) end diff --git a/app/views/layouts/nav/_new_admin_sidebar.html.haml b/app/views/layouts/nav/_new_admin_sidebar.html.haml index 9294529f496..3b53117deb6 100644 --- a/app/views/layouts/nav/_new_admin_sidebar.html.haml +++ b/app/views/layouts/nav/_new_admin_sidebar.html.haml @@ -7,7 +7,7 @@ .sidebar-context-title Admin Area %ul.sidebar-top-level-items = nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts), html_options: {class: 'home'}) do - = link_to admin_root_path, title: 'Overview', class: 'shortcuts-tree' do + = sidebar_link admin_root_path, title: _('Overview'), css: 'shortcuts-tree' do .nav-icon-container = custom_icon('overview') %span.nav-item-name @@ -48,7 +48,7 @@ ConvDev Index = nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles)) do - = link_to admin_conversational_development_index_path, title: 'Monitoring' do + = sidebar_link admin_conversational_development_index_path, title: _('Monitoring') do .nav-icon-container = custom_icon('monitoring') %span.nav-item-name @@ -77,28 +77,28 @@ Requests Profiles = nav_link(controller: :broadcast_messages) do - = link_to admin_broadcast_messages_path, title: 'Messages' do + = sidebar_link admin_broadcast_messages_path, title: _('Messages') do .nav-icon-container = custom_icon('messages') %span.nav-item-name Messages = nav_link(controller: [:hooks, :hook_logs]) do - = link_to admin_hooks_path, title: 'Hooks' do + = sidebar_link admin_hooks_path, title: _('Hooks') do .nav-icon-container = custom_icon('system_hooks') %span.nav-item-name System Hooks = nav_link(controller: :applications) do - = link_to admin_applications_path, title: 'Applications' do + = sidebar_link admin_applications_path, title: _('Applications') do .nav-icon-container = custom_icon('applications') %span.nav-item-name Applications = nav_link(controller: :abuse_reports) do - = link_to admin_abuse_reports_path, title: "Abuse Reports" do + = sidebar_link admin_abuse_reports_path, title: _("Abuse Reports") do .nav-icon-container = custom_icon('abuse_reports') %span.nav-item-name @@ -107,42 +107,42 @@ - if akismet_enabled? = nav_link(controller: :spam_logs) do - = link_to admin_spam_logs_path, title: "Spam Logs" do + = sidebar_link admin_spam_logs_path, title: _("Spam Logs") do .nav-icon-container = custom_icon('spam_logs') %span.nav-item-name Spam Logs = nav_link(controller: :deploy_keys) do - = link_to admin_deploy_keys_path, title: 'Deploy Keys' do + = sidebar_link admin_deploy_keys_path, title: _('Deploy Keys') do .nav-icon-container = custom_icon('key') %span.nav-item-name Deploy Keys = nav_link(controller: :services) do - = link_to admin_application_settings_services_path, title: 'Service Templates' do + = sidebar_link admin_application_settings_services_path, title: _('Service Templates') do .nav-icon-container = custom_icon('service_templates') %span.nav-item-name Service Templates = nav_link(controller: :labels) do - = link_to admin_labels_path, title: 'Labels' do + = sidebar_link admin_labels_path, title: _('Labels') do .nav-icon-container = custom_icon('labels') %span.nav-item-name Labels = nav_link(controller: :appearances) do - = link_to admin_appearances_path, title: 'Appearances' do + = sidebar_link admin_appearances_path, title: _('Appearances') do .nav-icon-container = custom_icon('appearance') %span.nav-item-name Appearance = nav_link(controller: :application_settings) do - = link_to admin_application_settings_path, title: 'Settings' do + = sidebar_link admin_application_settings_path, title: _('Settings') do .nav-icon-container = custom_icon('settings') %span.nav-item-name diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml index d90aea2e361..5a1511b262f 100644 --- a/app/views/layouts/nav/_new_group_sidebar.html.haml +++ b/app/views/layouts/nav/_new_group_sidebar.html.haml @@ -8,7 +8,7 @@ = @group.name %ul.sidebar-top-level-items = nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do - = link_to group_path(@group), title: 'Group overview' do + = sidebar_link group_path(@group), title: _('Group overview') do .nav-icon-container = custom_icon('project') %span.nav-item-name @@ -26,7 +26,7 @@ Activity = nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do - = link_to issues_group_path(@group), title: 'Issues' do + = sidebar_link issues_group_path(@group), title: _('Issues') do .nav-icon-container = custom_icon('issues') %span.nav-item-name @@ -51,7 +51,7 @@ Milestones = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group), title: 'Merge Requests' do + = sidebar_link merge_requests_group_path(@group), title: _('Merge Requests') do .nav-icon-container = custom_icon('mr_bold') %span.nav-item-name @@ -59,14 +59,14 @@ Merge Requests %span.badge.count= number_with_delimiter(merge_requests.count) = nav_link(path: 'group_members#index') do - = link_to group_group_members_path(@group), title: 'Members' do + = sidebar_link group_group_members_path(@group), title: _('Members') do .nav-icon-container = custom_icon('members') %span.nav-item-name Members - if current_user && can?(current_user, :admin_group, @group) = nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do - = link_to edit_group_path(@group), title: 'Settings' do + = sidebar_link edit_group_path(@group), title: _('Settings') do .nav-icon-container = custom_icon('settings') %span.nav-item-name diff --git a/app/views/layouts/nav/_new_profile_sidebar.html.haml b/app/views/layouts/nav/_new_profile_sidebar.html.haml index 85b2c7630c8..ccb6d1492f1 100644 --- a/app/views/layouts/nav/_new_profile_sidebar.html.haml +++ b/app/views/layouts/nav/_new_profile_sidebar.html.haml @@ -7,76 +7,76 @@ .sidebar-context-title User Settings %ul.sidebar-top-level-items = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do - = link_to profile_path, title: 'Profile Settings' do + = sidebar_link profile_path, title: _('Profile Settings') do .nav-icon-container = custom_icon('profile') %span.nav-item-name Profile = nav_link(controller: [:accounts, :two_factor_auths]) do - = link_to profile_account_path, title: 'Account' do + = sidebar_link profile_account_path, title: _('Account') do .nav-icon-container = custom_icon('account') %span.nav-item-name Account - if current_application_settings.user_oauth_applications? = nav_link(controller: 'oauth/applications') do - = link_to applications_profile_path, title: 'Applications' do + = sidebar_link applications_profile_path, title: _('Applications') do .nav-icon-container = custom_icon('applications') %span.nav-item-name Applications = nav_link(controller: :chat_names) do - = link_to profile_chat_names_path, title: 'Chat' do + = sidebar_link profile_chat_names_path, title: _('Chat') do .nav-icon-container = custom_icon('chat') %span.nav-item-name Chat = nav_link(controller: :personal_access_tokens) do - = link_to profile_personal_access_tokens_path, title: 'Access Tokens' do + = sidebar_link profile_personal_access_tokens_path, title: _('Access Tokens') do .nav-icon-container = custom_icon('access_tokens') %span.nav-item-name Access Tokens = nav_link(controller: :emails) do - = link_to profile_emails_path, title: 'Emails' do + = sidebar_link profile_emails_path, title: _('Emails') do .nav-icon-container = custom_icon('emails') %span.nav-item-name Emails - unless current_user.ldap_user? = nav_link(controller: :passwords) do - = link_to edit_profile_password_path, title: 'Password' do + = sidebar_link edit_profile_password_path, title: _('Password') do .nav-icon-container = custom_icon('lock') %span.nav-item-name Password = nav_link(controller: :notifications) do - = link_to profile_notifications_path, title: 'Notifications' do + = sidebar_link profile_notifications_path, title: _('Notifications') do .nav-icon-container = custom_icon('notifications') %span.nav-item-name Notifications = nav_link(controller: :keys) do - = link_to profile_keys_path, title: 'SSH Keys' do + = sidebar_link profile_keys_path, title: _('SSH Keys') do .nav-icon-container = custom_icon('key') %span.nav-item-name SSH Keys = nav_link(controller: :gpg_keys) do - = link_to profile_gpg_keys_path, title: 'GPG Keys' do + = sidebar_link profile_gpg_keys_path, title: _('GPG Keys') do .nav-icon-container = custom_icon('key_2') %span.nav-item-name GPG Keys = nav_link(controller: :preferences) do - = link_to profile_preferences_path, title: 'Preferences' do + = sidebar_link profile_preferences_path, title: _('Preferences') do .nav-icon-container = custom_icon('preferences') %span.nav-item-name Preferences = nav_link(path: 'profiles#audit_log') do - = link_to audit_log_profile_path, title: 'Authentication log' do + = sidebar_link audit_log_profile_path, title: _('Authentication log') do .nav-icon-container = custom_icon('authentication_log') %span.nav-item-name diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml index 341943cf833..53dbf9e2f2b 100644 --- a/app/views/layouts/nav/_new_project_sidebar.html.haml +++ b/app/views/layouts/nav/_new_project_sidebar.html.haml @@ -9,7 +9,7 @@ = @project.name %ul.sidebar-top-level-items = nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do - = link_to project_path(@project), title: 'Project overview', class: 'shortcuts-project' do + = sidebar_link project_path(@project), title: _('Project overview'), css: 'shortcuts-project' do .nav-icon-container = custom_icon('project') %span.nav-item-name @@ -31,7 +31,7 @@ - if project_nav_tab? :files = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do - = link_to project_tree_path(@project), title: 'Repository', class: 'shortcuts-tree' do + = sidebar_link project_tree_path(@project), title: _('Repository'), css: 'shortcuts-tree' do .nav-icon-container = custom_icon('doc_text') %span.nav-item-name @@ -72,7 +72,7 @@ - if project_nav_tab? :container_registry = nav_link(controller: %w[projects/registry/repositories]) do - = link_to project_container_registry_index_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do + = sidebar_link project_container_registry_index_path(@project), title: _('Container Registry'), css: 'shortcuts-container-registry' do .nav-icon-container = custom_icon('container_registry') %span.nav-item-name @@ -80,7 +80,7 @@ - if project_nav_tab? :issues = nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do - = link_to project_issues_path(@project), title: 'Issues', class: 'shortcuts-issues' do + = sidebar_link project_issues_path(@project), title: _('Issues'), css: 'shortcuts-issues' do .nav-icon-container = custom_icon('issues') %span.nav-item-name @@ -112,7 +112,7 @@ - if project_nav_tab? :merge_requests = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do - = link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do + = sidebar_link project_merge_requests_path(@project), title: _('Merge Requests'), css: 'shortcuts-merge_requests' do .nav-icon-container = custom_icon('mr_bold') %span.nav-item-name @@ -122,7 +122,7 @@ - if project_nav_tab? :pipelines = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do - = link_to project_pipelines_path(@project), title: 'CI / CD', class: 'shortcuts-pipelines' do + = sidebar_link project_pipelines_path(@project), title: _('CI / CD'), css: 'shortcuts-pipelines' do .nav-icon-container = custom_icon('pipeline') %span.nav-item-name @@ -161,7 +161,7 @@ - if project_nav_tab? :wiki = nav_link(controller: :wikis) do - = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do + = sidebar_link get_project_wiki_path(@project), title: _('Wiki'), css: 'shortcuts-wiki' do .nav-icon-container = custom_icon('wiki') %span.nav-item-name @@ -169,7 +169,7 @@ - if project_nav_tab? :snippets = nav_link(controller: :snippets) do - = link_to project_snippets_path(@project), title: 'Snippets', class: 'shortcuts-snippets' do + = sidebar_link project_snippets_path(@project), title: _('Snippets'), css: 'shortcuts-snippets' do .nav-icon-container = custom_icon('snippets') %span.nav-item-name @@ -177,7 +177,7 @@ - if project_nav_tab? :settings = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show]) do - = link_to edit_project_path(@project), title: 'Settings', class: 'shortcuts-tree' do + = sidebar_link edit_project_path(@project), title: _('Settings'), css: 'shortcuts-tree' do .nav-icon-container = custom_icon('settings') %span.nav-item-name diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml index 720a97cddb7..8dbb8aef31b 100644 --- a/app/views/profiles/gpg_keys/index.html.haml +++ b/app/views/profiles/gpg_keys/index.html.haml @@ -12,7 +12,7 @@ Add a GPG key %p.profile-settings-content Before you can add a GPG key you need to - = link_to 'generate it.', help_page_path('user/project/gpg_signed_commits/index.md') + = link_to 'generate it.', help_page_path('user/project/repository/gpg_signed_commits/index.md') = render 'form' %hr %h5 diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml index a3783b31b86..d06b29db838 100644 --- a/app/views/projects/commit/_signature_badge.html.haml +++ b/app/views/projects/commit/_signature_badge.html.haml @@ -12,7 +12,7 @@ %span.monospace= signature.gpg_key_primary_keyid - = link_to('Learn more about signing commits', help_page_path('user/project/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link') + = link_to('Learn more about signing commits', help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link') %button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } } = label |