diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-10 21:08:12 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-10 21:08:12 +0000 |
commit | ddfa6a1f19f1c6847d30314858f1d0ad21de13f9 (patch) | |
tree | 715fd181e594d7c6339d90eb8daaa45c962f2565 /app | |
parent | f27a1b0faf16a83ba9c3f71f660262e368f4509a (diff) | |
download | gitlab-ce-ddfa6a1f19f1c6847d30314858f1d0ad21de13f9.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
11 files changed, 189 insertions, 102 deletions
diff --git a/app/assets/javascripts/ci/runner/components/runner_bulk_delete.vue b/app/assets/javascripts/ci/runner/components/runner_bulk_delete.vue index 1ec3f8da7c3..8dde3ac4e19 100644 --- a/app/assets/javascripts/ci/runner/components/runner_bulk_delete.vue +++ b/app/assets/javascripts/ci/runner/components/runner_bulk_delete.vue @@ -162,22 +162,28 @@ export default { </script> <template> - <div v-if="checkedCount" class="gl-my-4 gl-p-4 gl-border-1 gl-border-solid gl-border-gray-100"> - <div class="gl-display-flex gl-align-items-center"> - <div> - <gl-sprintf :message="bannerMessage"> - <template #strong="{ content }"> - <strong>{{ content }}</strong> - </template> - </gl-sprintf> - </div> - <div class="gl-ml-auto"> - <gl-button variant="default" @click="onClearChecked">{{ - s__('Runners|Clear selection') - }}</gl-button> - <gl-button v-gl-modal="$options.BULK_DELETE_MODAL_ID" variant="danger">{{ - s__('Runners|Delete selected') - }}</gl-button> + <div> + <div + v-if="checkedCount" + data-testid="runner-bulk-delete-banner" + class="gl-my-4 gl-p-4 gl-border-1 gl-border-solid gl-border-gray-100" + > + <div class="gl-display-flex gl-align-items-center"> + <div> + <gl-sprintf :message="bannerMessage"> + <template #strong="{ content }"> + <strong>{{ content }}</strong> + </template> + </gl-sprintf> + </div> + <div class="gl-ml-auto"> + <gl-button variant="default" @click="onClearChecked">{{ + s__('Runners|Clear selection') + }}</gl-button> + <gl-button v-gl-modal="$options.BULK_DELETE_MODAL_ID" variant="danger">{{ + s__('Runners|Delete selected') + }}</gl-button> + </div> </div> </div> <gl-modal diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 457a519d70e..9bf382c41e7 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -4,7 +4,7 @@ import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils'; import $ from 'jquery'; -import { isFunction, defer, escape } from 'lodash'; +import { isFunction, defer, escape, partial, toLower } from 'lodash'; import Cookies from '~/lib/utils/cookies'; import { SCOPED_LABEL_DELIMITER } from '~/sidebar/components/labels/labels_select_widget/constants'; import { convertToCamelCase, convertToSnakeCase } from './text_utility'; @@ -552,6 +552,22 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => convertObjectProps(convertToCamelCase, obj, options); /** + * This method returns a new object with lowerCase property names + * + * Reasoning for this method is to ensure consistent access for some + * sort of objects + * + * This method also supports additional params in `options` object + * + * @param {Object} obj - Object to be converted. + * @param {Object} options - Object containing additional options. + * @param {boolean} options.deep - FLag to allow deep object converting + * @param {Array[]} options.dropKeys - List of properties to discard while building new object + * @param {Array[]} options.ignoreKeyNames - List of properties to leave intact while building new object + */ +export const convertObjectPropsToLowerCase = partial(convertObjectProps, toLower); + +/** * Converts all the object keys to snake case * * This method also supports additional params in `options` object diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js index 7d81ef30f2c..82035008459 100644 --- a/app/assets/javascripts/pages/projects/edit/index.js +++ b/app/assets/javascripts/pages/projects/edit/index.js @@ -11,6 +11,7 @@ import initSettingsPanels from '~/settings_panels'; import UserCallout from '~/user_callout'; import initTopicsTokenSelector from '~/projects/settings/topics'; import { initProjectSelects } from '~/vue_shared/components/entity_select/init_project_selects'; +import initPruneObjectsButton from '~/projects/prune_objects_button'; import initProjectPermissionsSettings from '../shared/permissions'; import initProjectLoadingSpinner from '../shared/save_project_loader'; @@ -18,6 +19,7 @@ initFilePickers(); initConfirmDanger(); initSettingsPanels(); initProjectDeleteButton(); +initPruneObjectsButton(); mountBadgeSettings(PROJECT_BADGE); new UserCallout({ className: 'js-service-desk-callout' }); // eslint-disable-line no-new diff --git a/app/assets/javascripts/projects/commit/components/branches_dropdown.vue b/app/assets/javascripts/projects/commit/components/branches_dropdown.vue index a037e721677..0ed154c47dd 100644 --- a/app/assets/javascripts/projects/commit/components/branches_dropdown.vue +++ b/app/assets/javascripts/projects/commit/components/branches_dropdown.vue @@ -1,12 +1,7 @@ <script> -import { - GlDropdown, - GlSearchBoxByType, - GlDropdownItem, - GlDropdownText, - GlLoadingIcon, -} from '@gitlab/ui'; +import { GlCollapsibleListbox } from '@gitlab/ui'; import { mapActions, mapGetters, mapState } from 'vuex'; +import { debounce } from 'lodash'; import { I18N_NO_RESULTS_MESSAGE, I18N_BRANCH_HEADER, @@ -16,11 +11,7 @@ import { export default { name: 'BranchesDropdown', components: { - GlDropdown, - GlSearchBoxByType, - GlDropdownItem, - GlDropdownText, - GlLoadingIcon, + GlCollapsibleListbox, }, props: { value: { @@ -46,19 +37,17 @@ export default { }, computed: { ...mapGetters(['joinedBranches']), - ...mapState(['isFetching', 'branch', 'branches']), - filteredResults() { - const lowerCasedSearchTerm = this.searchTerm.toLowerCase(); - return this.joinedBranches.filter((resultString) => - resultString.toLowerCase().includes(lowerCasedSearchTerm), - ); + ...mapState(['isFetching']), + listboxItems() { + return this.joinedBranches.map((value) => ({ value, text: value })); }, }, watch: { // Parent component can set the branch value (e.g. when the user selects a different project) // and we need to keep the search term in sync with the selected value value(val) { - this.searchTermChanged(val); + this.searchTerm = val; + this.fetchBranches(this.searchTerm); }, }, mounted() { @@ -67,50 +56,29 @@ export default { methods: { ...mapActions(['fetchBranches']), selectBranch(branch) { - this.$emit('selectBranch', branch); - this.searchTerm = branch; // enables isSelected to work as expected - }, - isSelected(selectedBranch) { - return selectedBranch === this.branch; + this.$emit('input', branch); }, + debouncedSearch: debounce(function debouncedSearch() { + this.fetchBranches(this.searchTerm); + }, 250), searchTermChanged(value) { - this.searchTerm = value; - this.fetchBranches(value); + this.searchTerm = value.trim(); + this.debouncedSearch(value); }, }, }; </script> <template> - <gl-dropdown :text="value" :header-text="$options.i18n.branchHeaderTitle"> - <gl-search-box-by-type - :value="searchTerm" - trim - autocomplete="off" - :debounce="250" - :placeholder="$options.i18n.branchSearchPlaceholder" - data-testid="dropdown-search-box" - @input="searchTermChanged" - /> - <gl-dropdown-item - v-for="branch in filteredResults" - v-show="!isFetching" - :key="branch" - :name="branch" - :is-checked="isSelected(branch)" - is-check-item - data-testid="dropdown-item" - @click="selectBranch(branch)" - > - {{ branch }} - </gl-dropdown-item> - <gl-dropdown-text v-show="isFetching" data-testid="dropdown-text-loading-icon"> - <gl-loading-icon size="sm" class="gl-mx-auto" /> - </gl-dropdown-text> - <gl-dropdown-text - v-if="!filteredResults.length && !isFetching" - data-testid="empty-result-message" - > - <span class="gl-text-gray-500">{{ $options.i18n.noResultsMessage }}</span> - </gl-dropdown-text> - </gl-dropdown> + <gl-collapsible-listbox + :header-text="$options.i18n.branchHeaderTitle" + :toggle-text="value" + :items="listboxItems" + searchable + :search-placeholder="$options.i18n.branchSearchPlaceholder" + :searching="isFetching" + :selected="value" + :no-results-text="$options.i18n.noResultsMessage" + @search="searchTermChanged" + @select="selectBranch" + /> </template> diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue index 921c66587c9..f78afef1c17 100644 --- a/app/assets/javascripts/projects/commit/components/form_modal.vue +++ b/app/assets/javascripts/projects/commit/components/form_modal.vue @@ -151,12 +151,7 @@ export default { > <input id="start_branch" type="hidden" name="start_branch" :value="branch" /> - <branches-dropdown - class="gl-w-half" - :value="branch" - :blanked="isRevert" - @selectBranch="setBranch" - /> + <branches-dropdown :value="branch" :blanked="isRevert" @input="setBranch" /> </gl-form-group> <gl-form-checkbox diff --git a/app/assets/javascripts/projects/prune_objects_button.js b/app/assets/javascripts/projects/prune_objects_button.js new file mode 100644 index 00000000000..dba73f6a19d --- /dev/null +++ b/app/assets/javascripts/projects/prune_objects_button.js @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import PruneUnreachableObjectsButton from './prune_unreachable_objects_button.vue'; + +export default (selector = '#js-project-prune-unreachable-objects-button') => { + const el = document.querySelector(selector); + + if (!el) return; + + const { pruneObjectsPath, pruneObjectsDocPath } = el.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el, + render(createElement) { + return createElement(PruneUnreachableObjectsButton, { + props: { + pruneObjectsPath, + pruneObjectsDocPath, + }, + }); + }, + }); +}; diff --git a/app/assets/javascripts/projects/prune_unreachable_objects_button.vue b/app/assets/javascripts/projects/prune_unreachable_objects_button.vue new file mode 100644 index 00000000000..1387fbb78c0 --- /dev/null +++ b/app/assets/javascripts/projects/prune_unreachable_objects_button.vue @@ -0,0 +1,75 @@ +<script> +import { GlButton, GlLink, GlModal, GlModalDirective } from '@gitlab/ui'; +import csrf from '~/lib/utils/csrf'; +import { s__ } from '~/locale'; + +export default { + components: { + GlButton, + GlLink, + GlModal, + }, + PRUNE_UNREACHABLE_OBJECTS_MODAL_ID: 'prune-objects-modal', + MODAL_ACTION_PRIMARY: { + text: s__('UpdateProject|Prune'), + attributes: [{ variant: 'danger' }], + }, + MODAL_ACTION_CANCEL: { + text: s__('UpdateProject|Cancel'), + }, + directives: { + GlModal: GlModalDirective, + }, + props: { + pruneObjectsPath: { + type: String, + required: true, + }, + pruneObjectsDocPath: { + type: String, + required: true, + }, + }, + computed: { + csrfToken() { + return csrf.token; + }, + }, + methods: { + submitForm() { + this.$refs.form.submit(); + }, + }, +}; +</script> + +<template> + <form ref="form" :action="pruneObjectsPath" method="post"> + <input :value="csrfToken" type="hidden" name="authenticity_token" /> + <input value="true" type="hidden" name="prune" /> + <gl-modal + :modal-id="$options.PRUNE_UNREACHABLE_OBJECTS_MODAL_ID" + :title="s__('UpdateProject|Are you sure you want to prune unreachable objects?')" + :action-primary="$options.MODAL_ACTION_PRIMARY" + :action-cancel="$options.MODAL_ACTION_CANCEL" + size="sm" + :no-focus-on-show="true" + @ok="submitForm" + > + <p> + {{ s__('UpdateProject|Pruning unreachable objects can lead to repository corruption.') }} + <gl-link :href="pruneObjectsDocPath" target="_blank"> + {{ s__('UpdateProject|Learn more.') }} + </gl-link> + {{ s__('UpdateProject|Are you sure you want to prune?') }} + </p> + </gl-modal> + <gl-button + v-gl-modal="$options.PRUNE_UNREACHABLE_OBJECTS_MODAL_ID" + category="primary" + variant="danger" + > + {{ s__('UpdateProject|Prune unreachable objects') }} + </gl-button> + </form> +</template> diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c5306d16bc7..0338c912b53 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -222,7 +222,13 @@ class ProjectsController < Projects::ApplicationController end def housekeeping - ::Repositories::HousekeepingService.new(@project, :eager).execute + task = if params[:prune].present? + :prune + else + :eager + end + + ::Repositories::HousekeepingService.new(@project, task).execute redirect_to( project_path(@project), diff --git a/app/services/packages/create_event_service.rb b/app/services/packages/create_event_service.rb index 8fed6e2def8..82c4292fca8 100644 --- a/app/services/packages/create_event_service.rb +++ b/app/services/packages/create_event_service.rb @@ -21,6 +21,17 @@ module Packages end end + def originator_type + case current_user + when User + :user + when DeployToken + :deploy_token + else + :guest + end + end + private def event_scope @@ -34,20 +45,5 @@ module Packages def event_name params[:event_name] end - - def originator_type - case current_user - when User - :user - when DeployToken - :deploy_token - else - :guest - end - end - - def guest? - originator_type == :guest - end end end diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index e9335762577..e87005434e4 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -74,6 +74,9 @@ = link_to _('Run housekeeping'), housekeeping_project_path(@project), method: :post, class: "btn gl-button btn-default" + .gl-display-inline-flex + #js-project-prune-unreachable-objects-button{ data: { prune_objects_path: housekeeping_project_path(@project, prune: true), prune_objects_doc_path: help_page_path('administration/housekeeping', anchor: 'prune-unreachable-objects') } } + = render 'export', project: @project = render_if_exists 'projects/settings/archive' diff --git a/app/workers/concerns/git_garbage_collect_methods.rb b/app/workers/concerns/git_garbage_collect_methods.rb index de3796f7e43..718031ec33e 100644 --- a/app/workers/concerns/git_garbage_collect_methods.rb +++ b/app/workers/concerns/git_garbage_collect_methods.rb @@ -84,13 +84,10 @@ module GitGarbageCollectMethods repository = resource.repository.raw_repository client = repository.gitaly_repository_client - case task - when :prune + if task == :prune client.prune_unreachable_objects - when :eager - client.optimize_repository(eager: true) else - client.optimize_repository + client.optimize_repository(eager: task == :eager) end rescue GRPC::NotFound => e Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found") |