diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-14 09:08:19 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-14 09:08:19 +0000 |
commit | 02ab65d49fc94be7c91e511899762236c122977d (patch) | |
tree | 4d4bf4ec54a95a0d73e039fa1410ea841156ffb2 | |
parent | 4411353300cf8219d2b899785bc5103c549ba8cf (diff) | |
download | gitlab-ce-02ab65d49fc94be7c91e511899762236c122977d.tar.gz |
Add latest changes from gitlab-org/gitlab@master
29 files changed, 367 insertions, 255 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 91c7aa53fb7..b65f9e8aff1 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -155,11 +155,10 @@ Rails/ApplicationRecord: # as they need to be as decoupled from application code as possible - db/**/*.rb - lib/gitlab/background_migration/**/*.rb + - ee/lib/ee/gitlab/background_migration/**/*.rb - lib/gitlab/database/**/*.rb - spec/**/*.rb - ee/db/**/*.rb - - ee/lib/gitlab/background_migration/**/*.rb - - ee/lib/ee/gitlab/background_migration/**/*.rb - ee/spec/**/*.rb # GitLab ################################################################### @@ -233,7 +232,8 @@ RSpec/FactoriesInMigrationSpecs: - 'spec/migrations/**/*.rb' - 'ee/spec/migrations/**/*.rb' - 'spec/lib/gitlab/background_migration/**/*.rb' - - 'ee/spec/lib/gitlab/background_migration/**/*.rb' + - 'spec/lib/ee/gitlab/background_migration/**/*.rb' + - 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb' Cop/IncludeActionViewContext: Enabled: true @@ -365,4 +365,4 @@ Style/MultilineWhenThen: Enabled: false Style/FloatDivision: - Enabled: false
\ No newline at end of file + Enabled: false diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js index 66a89582da3..7ffb430296b 100644 --- a/app/assets/javascripts/ide/stores/actions.js +++ b/app/assets/javascripts/ide/stores/actions.js @@ -16,21 +16,7 @@ export const redirectToUrl = (self, url) => visitUrl(url); export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data); export const discardAllChanges = ({ state, commit, dispatch }) => { - state.changedFiles.forEach(file => { - if (file.tempFile || file.prevPath) dispatch('closeFile', file); - - if (file.tempFile) { - dispatch('deleteEntry', file.path); - } else if (file.prevPath) { - dispatch('renameEntry', { - path: file.path, - name: file.prevName, - parentPath: file.prevParentPath, - }); - } else { - commit(types.DISCARD_FILE_CHANGES, file.path); - } - }); + state.changedFiles.forEach(file => dispatch('restoreOriginalFile', file.path)); commit(types.REMOVE_ALL_CHANGES_FILES); }; diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js index 99e13e32ba4..1bfee7b6be4 100644 --- a/app/assets/javascripts/ide/stores/actions/file.js +++ b/app/assets/javascripts/ide/stores/actions/file.js @@ -191,38 +191,47 @@ export const setFileViewMode = ({ commit }, { file, viewMode }) => { commit(types.SET_FILE_VIEWMODE, { file, viewMode }); }; -export const discardFileChanges = ({ dispatch, state, commit, getters }, path) => { +export const restoreOriginalFile = ({ dispatch, state, commit }, path) => { const file = state.entries[path]; + const isDestructiveDiscard = file.tempFile || file.prevPath; if (file.deleted && file.parentPath) { dispatch('restoreTree', file.parentPath); } - if (file.tempFile || file.prevPath) { + if (isDestructiveDiscard) { dispatch('closeFile', file); + } - if (file.tempFile) { - dispatch('deleteEntry', file.path); - } else { - commit(types.DISCARD_FILE_CHANGES, file.path); - dispatch('renameEntry', { - path: file.path, - name: file.prevName, - parentPath: file.prevParentPath, - }); - } + if (file.tempFile) { + dispatch('deleteEntry', file.path); } else { - commit(types.DISCARD_FILE_CHANGES, path); - - if (getters.activeFile && file.path === getters.activeFile.path) { - dispatch('updateDelayViewerUpdated', true) - .then(() => { - router.push(`/project${file.url}`); - }) - .catch(e => { - throw e; - }); - } + commit(types.DISCARD_FILE_CHANGES, file.path); + } + + if (file.prevPath) { + dispatch('renameEntry', { + path: file.path, + name: file.prevName, + parentPath: file.prevParentPath, + }); + } +}; + +export const discardFileChanges = ({ dispatch, state, commit, getters }, path) => { + const file = state.entries[path]; + const isDestructiveDiscard = file.tempFile || file.prevPath; + + dispatch('restoreOriginalFile', path); + + if (!isDestructiveDiscard && file.path === getters.activeFile?.path) { + dispatch('updateDelayViewerUpdated', true) + .then(() => { + router.push(`/project${file.url}`); + }) + .catch(e => { + throw e; + }); } commit(types.REMOVE_FILE_FROM_CHANGED, path); diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml index 50530498f52..c3960ec5026 100644 --- a/app/views/shared/issuable/_search_bar.html.haml +++ b/app/views/shared/issuable/_search_bar.html.haml @@ -1,5 +1,6 @@ - type = local_assigns.fetch(:type) - board = local_assigns.fetch(:board, nil) +- show_sorting_dropdown = local_assigns.fetch(:show_sorting_dropdown, true) - is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics - block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : '' - user_can_admin_list = board && can?(current_user, :admin_list, board.resource_parent) @@ -169,5 +170,5 @@ - if @project #js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project) } } #js-toggle-focus-btn - - elsif is_not_boards_modal_or_productivity_analytics + - elsif is_not_boards_modal_or_productivity_analytics && show_sorting_dropdown = render 'shared/issuable/sort_dropdown' diff --git a/changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml b/changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml new file mode 100644 index 00000000000..8b987c63d96 --- /dev/null +++ b/changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml @@ -0,0 +1,5 @@ +--- +title: 'Fix: undefined background migration classes for EE-CE downgrades' +merge_request: 22160 +author: +type: fixed diff --git a/changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml b/changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml new file mode 100644 index 00000000000..ac02673a8ea --- /dev/null +++ b/changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml @@ -0,0 +1,5 @@ +--- +title: Fix discard all to behave like discard single file in Web IDE +merge_request: 22572 +author: +type: fixed diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md index efb39dd1c55..8c3c17d2ce1 100644 --- a/doc/ci/merge_request_pipelines/index.md +++ b/doc/ci/merge_request_pipelines/index.md @@ -161,7 +161,7 @@ test: only: [merge_requests] except: variables: - $CI_COMMIT_REF_NAME =~ /^docs-/ + - $CI_COMMIT_REF_NAME =~ /^docs-/ ``` ## Important notes about merge requests from forked projects diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index 68e977c1c98..55710145a95 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -17,34 +17,29 @@ NOTE: **Note:** Coming over to GitLab from Jenkins? Check out our [reference](../jenkins/index.md) for converting your pre-existing pipelines over to our format. -GitLab offers a [continuous integration][ci] service. If you -[add a `.gitlab-ci.yml` file][yaml] to the root directory of your repository, -and configure your GitLab project to use a [Runner], then each commit or -push triggers your CI [pipeline]. +GitLab offers a [continuous integration](https://about.gitlab.com/product/continuous-integration/) service. For each commit or push to trigger your CI +[pipeline](../pipelines.md), you must: -The `.gitlab-ci.yml` file tells the GitLab Runner what to do. By default it runs -a pipeline with three [stages]: `build`, `test`, and `deploy`. You don't need to -use all three stages; stages with no jobs are simply ignored. +- Add a [`.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) to your repository's root directory. +- Ensure your project is configured to use a [Runner](#configuring-a-runner). -If everything runs OK (no non-zero return values), you'll get a nice green -checkmark associated with the commit. This makes it -easy to see whether a commit caused any of the tests to fail before -you even look at the code. +The `.gitlab-ci.yml` file tells the GitLab Runner what to do. A simple pipeline commonly has +three [stages](../yaml/README.md#stages): -Most projects use GitLab's CI service to run the test suite so that -developers get immediate feedback if they broke something. +- `build` +- `test` +- `deploy` -There's a growing trend to use continuous delivery and continuous deployment to -automatically deploy tested code to staging and production environments. +You do not need to use all three stages; stages with no jobs are ignored. -So in brief, the steps needed to have a working CI can be summed up to: +The pipeline appears under the project's **CI/CD > Pipelines** page. If everything runs OK (no non-zero +return values), you get a green check mark associated with the commit. This makes it easy to see +whether a commit caused any of the tests to fail before you even look at the job (test) log. Many projects use +GitLab's CI service to run the test suite, so developers get immediate feedback if they broke +something. -1. Add `.gitlab-ci.yml` to the root directory of your repository -1. Configure a Runner - -From there on, on every push to your Git repository, the Runner will -automatically start the pipeline and the pipeline will appear under the -project's **Pipelines** page. +It's also common to use pipelines to automatically deploy +tested code to staging and production environments. --- @@ -237,9 +232,4 @@ CI with various languages. [runner-install]: https://docs.gitlab.com/runner/install/ [blog-ci]: https://about.gitlab.com/blog/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/ [examples]: ../examples/README.md -[ci]: https://about.gitlab.com/product/continuous-integration/ -[yaml]: ../yaml/README.md -[runner]: ../runners/README.md [enabled]: ../enable_or_disable_ci.md -[stages]: ../yaml/README.md#stages -[pipeline]: ../pipelines.md diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 5c5dd12969a..e388fdde58a 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -2719,10 +2719,10 @@ can lead to errors during the deployment. To avoid these errors, the `resource_group` attribute can be used to ensure that the Runner will not run certain jobs simultaneously. -When the `resource_group` key is defined in a job in `.gitlab-ci.yml`, -job runs are mutually exclusive across different pipelines in the same project. +When the `resource_group` key is defined for a job in `.gitlab-ci.yml`, +job executions are mutually exclusive across different pipelines for the same project. If multiple jobs belonging to the same resource group are enqueued simultaneously, -only one of them will be picked by the Runner, and the other jobs will wait until the +only one of the jobs will be picked by the Runner, and the other jobs will wait until the `resource_group` is free. Here is a simple example: diff --git a/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb b/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb new file mode 100644 index 00000000000..83d60d2db19 --- /dev/null +++ b/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class BackfillVersionDataFromGitaly + def perform(issue_id) + end + end + end +end + +Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly.prepend_if_ee('EE::Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly') diff --git a/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb b/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb new file mode 100644 index 00000000000..85bcf8558f2 --- /dev/null +++ b/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class GenerateGitlabSubscriptions + def perform(start_id, stop_id) + end + end + end +end + +Gitlab::BackgroundMigration::GenerateGitlabSubscriptions.prepend_if_ee('EE::Gitlab::BackgroundMigration::GenerateGitlabSubscriptions') diff --git a/lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb b/lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb new file mode 100644 index 00000000000..27b984b4531 --- /dev/null +++ b/lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class MigrateApproverToApprovalRules + # @param target_type [String] class of target, either 'MergeRequest' or 'Project' + # @param target_id [Integer] id of target + def perform(target_type, target_id, sync_code_owner_rule: true) + end + end + end +end + +Gitlab::BackgroundMigration::MigrateApproverToApprovalRules.prepend_if_ee('EE::Gitlab::BackgroundMigration::MigrateApproverToApprovalRules') diff --git a/lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb new file mode 100644 index 00000000000..053b7363286 --- /dev/null +++ b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class MigrateApproverToApprovalRulesCheckProgress + def perform + end + end + end +end + +Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesCheckProgress.prepend_if_ee('EE::Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesCheckProgress') diff --git a/lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb new file mode 100644 index 00000000000..130f97b09d7 --- /dev/null +++ b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class MigrateApproverToApprovalRulesInBatch + def perform(start_id, end_id) + end + end + end +end + +Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesInBatch.prepend_if_ee('EE::Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesInBatch') diff --git a/lib/gitlab/background_migration/move_epic_issues_after_epics.rb b/lib/gitlab/background_migration/move_epic_issues_after_epics.rb new file mode 100644 index 00000000000..dc982e703d1 --- /dev/null +++ b/lib/gitlab/background_migration/move_epic_issues_after_epics.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class MoveEpicIssuesAfterEpics + def perform(start_id, stop_id) + end + end + end +end + +Gitlab::BackgroundMigration::MoveEpicIssuesAfterEpics.prepend_if_ee('EE::Gitlab::BackgroundMigration::MoveEpicIssuesAfterEpics') diff --git a/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb b/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb new file mode 100644 index 00000000000..c3c0db2495c --- /dev/null +++ b/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # This background migration creates any approver rule records according + # to the given merge request IDs range. A _single_ INSERT is issued for the given range. + class PopulateAnyApprovalRuleForMergeRequests + def perform(from_id, to_id) + end + end + end +end + +Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForMergeRequests.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForMergeRequests') diff --git a/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb b/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb new file mode 100644 index 00000000000..2243c7531c0 --- /dev/null +++ b/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # This background migration creates any approver rule records according + # to the given project IDs range. A _single_ INSERT is issued for the given range. + class PopulateAnyApprovalRuleForProjects + def perform(from_id, to_id) + end + end + end +end + +Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForProjects.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForProjects') diff --git a/lib/gitlab/background_migration/prune_orphaned_geo_events.rb b/lib/gitlab/background_migration/prune_orphaned_geo_events.rb new file mode 100644 index 00000000000..8b16db8be35 --- /dev/null +++ b/lib/gitlab/background_migration/prune_orphaned_geo_events.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true +# +# rubocop:disable Style/Documentation + +# This job is added to fix https://gitlab.com/gitlab-org/gitlab/issues/30229 +# It's not used anywhere else. +# Can be removed in GitLab 13.* +module Gitlab + module BackgroundMigration + class PruneOrphanedGeoEvents + def perform(table_name) + end + end + end +end + +Gitlab::BackgroundMigration::PruneOrphanedGeoEvents.prepend_if_ee('EE::Gitlab::BackgroundMigration::PruneOrphanedGeoEvents') diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb new file mode 100644 index 00000000000..dd80d4bab1a --- /dev/null +++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class UpdateAuthorizedKeysFileSince + def perform(cutoff_datetime) + end + end + end +end + +Gitlab::BackgroundMigration::UpdateAuthorizedKeysFileSince.prepend_if_ee('EE::Gitlab::BackgroundMigration::UpdateAuthorizedKeysFileSince') diff --git a/lib/gitlab/background_migration/update_vulnerability_confidence.rb b/lib/gitlab/background_migration/update_vulnerability_confidence.rb new file mode 100644 index 00000000000..6ffaa836f3c --- /dev/null +++ b/lib/gitlab/background_migration/update_vulnerability_confidence.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class UpdateVulnerabilityConfidence + def perform(start_id, stop_id) + end + end + end +end + +Gitlab::BackgroundMigration::UpdateVulnerabilityConfidence.prepend_if_ee('EE::Gitlab::BackgroundMigration::UpdateVulnerabilityConfidence') diff --git a/lib/gitlab/ci/config/entry/includes.rb b/lib/gitlab/ci/config/entry/includes.rb index 43e74dfd628..24d0e27e3a7 100644 --- a/lib/gitlab/ci/config/entry/includes.rb +++ b/lib/gitlab/ci/config/entry/includes.rb @@ -12,6 +12,15 @@ module Gitlab validations do validates :config, array_or_string: true + + validate do + next unless opt(:max_size) + next unless config.is_a?(Array) + + if config.size > opt(:max_size) + errors.add(:config, "is too long (maximum is #{opt(:max_size)})") + end + end end def self.aspects diff --git a/lib/gitlab/email/attachment_uploader.rb b/lib/gitlab/email/attachment_uploader.rb index 3323ce60158..0a14a909e31 100644 --- a/lib/gitlab/email/attachment_uploader.rb +++ b/lib/gitlab/email/attachment_uploader.rb @@ -9,7 +9,7 @@ module Gitlab @message = message end - def execute(project) + def execute(upload_parent:, uploader_class:) attachments = [] message.attachments.each do |attachment| @@ -23,7 +23,7 @@ module Gitlab content_type: attachment.content_type } - uploader = UploadService.new(project, file).execute + uploader = UploadService.new(upload_parent, file, uploader_class).execute attachments << uploader.to_h if uploader ensure tmp.close! diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb index 6b7686cd405..312a9fdfbae 100644 --- a/lib/gitlab/email/handler/reply_processing.rb +++ b/lib/gitlab/email/handler/reply_processing.rb @@ -41,13 +41,20 @@ module Gitlab end def add_attachments(reply) - attachments = Email::AttachmentUploader.new(mail).execute(project) + attachments = Email::AttachmentUploader.new(mail).execute(upload_params) reply + attachments.map do |link| "\n\n#{link[:markdown]}" end.join end + def upload_params + { + upload_parent: project, + uploader_class: FileUploader + } + end + def validate_permission!(permission) raise UserNotFoundError unless author raise UserBlockedError if author.blocked? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 68077245975..f61290b5687 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5639,12 +5639,30 @@ msgstr "" msgid "CycleAnalytics|No stages selected" msgstr "" +msgid "CycleAnalytics|Number of tasks" +msgstr "" + +msgid "CycleAnalytics|Showing %{subject} and %{selectedLabelsCount} labels" +msgstr "" + +msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}" +msgstr "" + +msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{startDate} to %{endDate}" +msgstr "" + msgid "CycleAnalytics|Stages" msgstr "" +msgid "CycleAnalytics|Tasks by type" +msgstr "" + msgid "CycleAnalytics|Total days to completion" msgstr "" +msgid "CycleAnalytics|Type of work" +msgstr "" + msgid "CycleAnalytics|group dropdown filter" msgstr "" @@ -5687,6 +5705,9 @@ msgstr "" msgid "Data is still calculating..." msgstr "" +msgid "Date" +msgstr "" + msgid "Date picker" msgstr "" diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js index 2d72ae770ab..e7b34aa3e7a 100644 --- a/spec/frontend/ide/stores/actions/file_spec.js +++ b/spec/frontend/ide/stores/actions/file_spec.js @@ -619,107 +619,113 @@ describe('IDE store file actions', () => { }); }); - describe('discardFileChanges', () => { + describe('with changed file', () => { let tmpFile; beforeEach(() => { - jest.spyOn(eventHub, '$on').mockImplementation(() => {}); - jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); - tmpFile = file('tempFile'); tmpFile.content = 'testing'; tmpFile.raw = ORIGINAL_CONTENT; store.state.changedFiles.push(tmpFile); store.state.entries[tmpFile.path] = tmpFile; - - jest.spyOn(store, 'dispatch'); }); - it('resets file content', done => { - store - .dispatch('discardFileChanges', tmpFile.path) - .then(() => { + describe('restoreOriginalFile', () => { + it('resets file content', () => + store.dispatch('restoreOriginalFile', tmpFile.path).then(() => { expect(tmpFile.content).toBe(ORIGINAL_CONTENT); + })); - done(); - }) - .catch(done.fail); - }); + it('closes temp file and deletes it', () => { + tmpFile.tempFile = true; + tmpFile.opened = true; + tmpFile.parentPath = 'parentFile'; + store.state.entries.parentFile = file('parentFile'); - it('removes file from changedFiles array', done => { - store - .dispatch('discardFileChanges', tmpFile.path) - .then(() => { - expect(store.state.changedFiles.length).toBe(0); + actions.restoreOriginalFile(store, tmpFile.path); - done(); - }) - .catch(done.fail); - }); + expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile); + expect(store.dispatch).toHaveBeenCalledWith('deleteEntry', tmpFile.path); + }); - it('closes temp file and deletes it', () => { - tmpFile.tempFile = true; - tmpFile.opened = true; - tmpFile.parentPath = 'parentFile'; - store.state.entries.parentFile = file('parentFile'); + describe('with renamed file', () => { + beforeEach(() => { + Object.assign(tmpFile, { + prevPath: 'parentPath/old_name', + prevName: 'old_name', + prevParentPath: 'parentPath', + }); - actions.discardFileChanges(store, tmpFile.path); + store.state.entries.parentPath = file('parentPath'); - expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile); - expect(store.dispatch).toHaveBeenCalledWith('deleteEntry', tmpFile.path); - }); + actions.restoreOriginalFile(store, tmpFile.path); + }); - describe('with renamed file', () => { - beforeEach(() => { - Object.assign(tmpFile, { - prevPath: 'parentPath/old_name', - prevName: 'old_name', - prevParentPath: 'parentPath', + it('renames the file to its original name and closes it if it was open', () => { + expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile); + expect(store.dispatch).toHaveBeenCalledWith('renameEntry', { + path: 'tempFile', + name: 'old_name', + parentPath: 'parentPath', + }); }); - store.state.entries.parentPath = file('parentPath'); + it('resets file content', () => { + expect(tmpFile.content).toBe(ORIGINAL_CONTENT); + }); + }); + }); - actions.discardFileChanges(store, tmpFile.path); + describe('discardFileChanges', () => { + beforeEach(() => { + jest.spyOn(eventHub, '$on').mockImplementation(() => {}); + jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); }); - it('renames the file to its original name and closes it if it was open', () => { - expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile); - expect(store.dispatch).toHaveBeenCalledWith('renameEntry', { - path: 'tempFile', - name: 'old_name', - parentPath: 'parentPath', + describe('with regular file', () => { + beforeEach(() => { + actions.discardFileChanges(store, tmpFile.path); }); - }); - it('resets file content', () => { - expect(tmpFile.content).toBe(ORIGINAL_CONTENT); - }); - }); + it('restores original file', () => { + expect(store.dispatch).toHaveBeenCalledWith('restoreOriginalFile', tmpFile.path); + }); - it('pushes route for active file', done => { - tmpFile.active = true; - store.state.openFiles.push(tmpFile); + it('removes file from changedFiles array', () => { + expect(store.state.changedFiles.length).toBe(0); + }); - store - .dispatch('discardFileChanges', tmpFile.path) - .then(() => { - expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`); + it('does not push a new route', () => { + expect(router.push).not.toHaveBeenCalled(); + }); - done(); - }) - .catch(done.fail); - }); + it('emits eventHub event to dispose cached model', () => { + actions.discardFileChanges(store, tmpFile.path); + + expect(eventHub.$emit).toHaveBeenCalledWith( + `editor.update.model.new.content.${tmpFile.key}`, + ORIGINAL_CONTENT, + ); + expect(eventHub.$emit).toHaveBeenCalledWith( + `editor.update.model.dispose.unstaged-${tmpFile.key}`, + ORIGINAL_CONTENT, + ); + }); + }); - it('emits eventHub event to dispose cached model', done => { - store - .dispatch('discardFileChanges', tmpFile.path) - .then(() => { - expect(eventHub.$emit).toHaveBeenCalled(); + describe('with active file', () => { + beforeEach(() => { + tmpFile.active = true; + store.state.openFiles.push(tmpFile); - done(); - }) - .catch(done.fail); + actions.discardFileChanges(store, tmpFile.path); + }); + + it('pushes route for active file', () => { + expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`); + }); + }); }); }); diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js index a9fc3bf65a6..8abd9c38514 100644 --- a/spec/javascripts/ide/stores/actions_spec.js +++ b/spec/javascripts/ide/stores/actions_spec.js @@ -61,24 +61,25 @@ describe('Multi-file store actions', () => { }); describe('discardAllChanges', () => { - let f; + const paths = ['to_discard', 'another_one_to_discard']; + beforeEach(() => { - f = file('discardAll'); - f.changed = true; + paths.forEach(path => { + const f = file(path); + f.changed = true; - store.state.openFiles.push(f); - store.state.changedFiles.push(f); - store.state.entries[f.path] = f; + store.state.openFiles.push(f); + store.state.changedFiles.push(f); + store.state.entries[f.path] = f; + }); }); - it('discards changes in file', done => { - store - .dispatch('discardAllChanges') - .then(() => { - expect(store.state.openFiles.changed).toBeFalsy(); - }) - .then(done) - .catch(done.fail); + it('discards all changes in file', () => { + const expectedCalls = paths.map(path => ['restoreOriginalFile', path]); + + discardAllChanges(store); + + expect(store.dispatch.calls.allArgs()).toEqual(jasmine.arrayContaining(expectedCalls)); }); it('removes all files from changedFiles state', done => { @@ -86,64 +87,11 @@ describe('Multi-file store actions', () => { .dispatch('discardAllChanges') .then(() => { expect(store.state.changedFiles.length).toBe(0); - expect(store.state.openFiles.length).toBe(1); + expect(store.state.openFiles.length).toBe(2); }) .then(done) .catch(done.fail); }); - - it('closes the temp file and deletes it if it was open', done => { - f.tempFile = true; - - testAction( - discardAllChanges, - undefined, - store.state, - [{ type: types.REMOVE_ALL_CHANGES_FILES }], - [ - { type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) }, - { type: 'deleteEntry', payload: 'discardAll' }, - ], - done, - ); - }); - - it('renames the file to its original name and closes it if it was open', done => { - Object.assign(f, { - prevPath: 'parent/path/old_name', - prevName: 'old_name', - prevParentPath: 'parent/path', - }); - - testAction( - discardAllChanges, - undefined, - store.state, - [{ type: types.REMOVE_ALL_CHANGES_FILES }], - [ - { type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) }, - { - type: 'renameEntry', - payload: { path: 'discardAll', name: 'old_name', parentPath: 'parent/path' }, - }, - ], - done, - ); - }); - - it('discards file changes on all other files', done => { - testAction( - discardAllChanges, - undefined, - store.state, - [ - { type: types.DISCARD_FILE_CHANGES, payload: 'discardAll' }, - { type: types.REMOVE_ALL_CHANGES_FILES }, - ], - [], - done, - ); - }); }); describe('closeAllFiles', () => { diff --git a/spec/lib/gitlab/email/attachment_uploader_spec.rb b/spec/lib/gitlab/email/attachment_uploader_spec.rb index d66a746284d..c69b2f1eabc 100644 --- a/spec/lib/gitlab/email/attachment_uploader_spec.rb +++ b/spec/lib/gitlab/email/attachment_uploader_spec.rb @@ -9,7 +9,7 @@ describe Gitlab::Email::AttachmentUploader do let(:message) { Mail::Message.new(message_raw) } it "uploads all attachments and returns their links" do - links = described_class.new(message).execute(project) + links = described_class.new(message).execute(upload_parent: project, uploader_class: FileUploader) link = links.first expect(link).not_to be_nil diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb index 50e473c459e..909a7618df4 100644 --- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb @@ -181,10 +181,21 @@ describe Gitlab::Email::Handler::CreateNoteHandler do it_behaves_like 'a reply to existing comment' it "adds all attachments" do + expect_next_instance_of(Gitlab::Email::AttachmentUploader) do |uploader| + expect(uploader).to receive(:execute).with(upload_parent: project, uploader_class: FileUploader).and_return( + [ + { + url: "uploads/image.png", + alt: "image", + markdown: markdown + } + ] + ) + end + receiver.execute note = noteable.notes.last - expect(note.note).to include(markdown) end diff --git a/yarn.lock b/yarn.lock index c7e5e2af1f3..5289e563189 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3461,44 +3461,7 @@ d3-zoom@1: d3-selection "1" d3-transition "1" -d3@^5.12.0, d3@^5.7.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/d3/-/d3-5.12.0.tgz#0ddeac879c28c882317cd439b495290acd59ab61" - integrity sha512-flYVMoVuhPFHd9zVCe2BxIszUWqBcd5fvQGMNRmSiBrgdnh6Vlruh60RJQTouAK9xPbOB0plxMvBm4MoyODXNg== - dependencies: - d3-array "1" - d3-axis "1" - d3-brush "1" - d3-chord "1" - d3-collection "1" - d3-color "1" - d3-contour "1" - d3-dispatch "1" - d3-drag "1" - d3-dsv "1" - d3-ease "1" - d3-fetch "1" - d3-force "1" - d3-format "1" - d3-geo "1" - d3-hierarchy "1" - d3-interpolate "1" - d3-path "1" - d3-polygon "1" - d3-quadtree "1" - d3-random "1" - d3-scale "2" - d3-scale-chromatic "1" - d3-selection "1" - d3-shape "1" - d3-time "1" - d3-time-format "2" - d3-timer "1" - d3-transition "1" - d3-voronoi "1" - d3-zoom "1" - -d3@^5.14: +d3@^5.12.0, d3@^5.14, d3@^5.7.0: version "5.15.0" resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a" integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg== |