diff options
36 files changed, 297 insertions, 86 deletions
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md index ad517f0457d..639a236631d 100644 --- a/.gitlab/issue_templates/Feature proposal.md +++ b/.gitlab/issue_templates/Feature proposal.md @@ -4,7 +4,7 @@ ### Target audience -<!--- For whom are we doing this? Include either a persona from https://design.gitlab.com/#/getting-started/personas or define a specific company role. e.a. "Release Manager" or "Security Analyst" --> +<!--- For whom are we doing this? Include either a persona from https://design.gitlab.com/getting-started/personas or define a specific company role. e.a. "Release Manager" or "Security Analyst" --> ### Further details diff --git a/CHANGELOG.md b/CHANGELOG.md index a51ac887aed..4b4f8fea31c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 11.5.5 (2018-12-20) + +### Security (1 change) + +- Fix persistent symlink in project import. + + ## 11.5.3 (2018-12-06) ### Security (1 change) @@ -628,6 +635,13 @@ entry. - Check frozen string in style builds. (gfyoung) +## 11.3.14 (2018-12-20) + +### Security (1 change) + +- Fix persistent symlink in project import. + + ## 11.3.13 (2018-12-13) ### Security (1 change) diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index d9dd08a7a6b..be451401e97 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -178,31 +178,32 @@ export default { commitId = `<span class="commit-sha">${truncateSha(commitId)}</span>`; } - let text = s__('MergeRequests|started a discussion'); + const { + for_commit: isForCommit, + diff_discussion: isDiffDiscussion, + active: isActive, + } = this.discussion; - if (this.discussion.for_commit) { + let text = s__('MergeRequests|started a discussion'); + if (isForCommit) { text = s__( 'MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}', ); - } else if (this.discussion.diff_discussion) { - if (this.discussion.active) { - text = s__('MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}'); - } else { - text = s__( - 'MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}', - ); - } + } else if (isDiffDiscussion && commitId) { + text = isActive + ? s__('MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}') + : s__( + 'MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}', + ); + } else if (isDiffDiscussion) { + text = isActive + ? s__('MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}') + : s__( + 'MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}', + ); } - return sprintf( - text, - { - commitId, - linkStart, - linkEnd, - }, - false, - ); + return sprintf(text, { commitId, linkStart, linkEnd }, false); }, diffLine() { if (this.discussion.diff_discussion && this.discussion.truncated_diff_lines) { @@ -211,6 +212,16 @@ export default { return this.line; }, + commit() { + if (!this.discussion.for_commit) { + return null; + } + + return { + id: this.discussion.commit_id, + url: this.discussion.discussion_path, + }; + }, }, watch: { isReplying() { @@ -376,6 +387,7 @@ Please check your network connection and try again.`; :note="componentData(initialDiscussion)" :line="line" :help-page-path="helpPagePath" + :commit="commit" @handleDeleteNote="deleteNoteHandler" > <note-edited-text diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 4c02588127e..6edc65c856e 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -2,6 +2,8 @@ import $ from 'jquery'; import { mapGetters, mapActions } from 'vuex'; import { escape } from 'underscore'; +import { truncateSha } from '~/lib/utils/text_utility'; +import { s__, sprintf } from '~/locale'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import Flash from '../../flash'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; @@ -37,6 +39,11 @@ export default { required: false, default: '', }, + commit: { + type: Object, + required: false, + default: () => null, + }, }, data() { return { @@ -73,6 +80,24 @@ export default { isTarget() { return this.targetNoteHash === this.noteAnchorId; }, + actionText() { + if (this.commit) { + const { id, url } = this.commit; + const linkStart = `<a class="commit-sha monospace" href="${escape(url)}">`; + const linkEnd = '</a>'; + return sprintf( + s__('MergeRequests|commented on commit %{linkStart}%{commitId}%{linkEnd}'), + { + commitId: truncateSha(id), + linkStart, + linkEnd, + }, + false, + ); + } + + return '<span class="d-none d-sm-inline">·</span>'; + }, }, created() { @@ -200,13 +225,9 @@ export default { </div> <div class="timeline-content"> <div class="note-header"> - <note-header - v-once - :author="author" - :created-at="note.created_at" - :note-id="note.id" - action-text="commented" - /> + <note-header v-once :author="author" :created-at="note.created_at" :note-id="note.id"> + <span v-html="actionText"></span> + </note-header> <note-actions :author-id="author.id" :note-id="note.id" diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss index 73533571a2f..946f575ac13 100644 --- a/app/assets/stylesheets/framework/highlight.scss +++ b/app/assets/stylesheets/framework/highlight.scss @@ -42,7 +42,6 @@ padding: 10px; text-align: right; float: left; - line-height: 1; a { font-family: $monospace-font; @@ -69,3 +68,9 @@ } } } + +// Vertically aligns <table> line numbers (eg. blame view) +// see https://gitlab.com/gitlab-org/gitlab-ce/issues/54048 +td.line-numbers { + line-height: 1; +} diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss index 7e30747963a..95291b4a9ad 100644 --- a/app/assets/stylesheets/framework/modal.scss +++ b/app/assets/stylesheets/framework/modal.scss @@ -25,8 +25,8 @@ &.w-100 { // after upgrading to Bootstrap 4.2 we can use $modal-header-padding-x here // https://github.com/twbs/bootstrap/pull/26976 - margin-right: -2rem; - padding-right: 2rem; + margin-right: -28px; + padding-right: 28px; } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index ce5aaa8963c..343c09b4a3e 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -198,7 +198,7 @@ $well-light-text-color: #5b6169; $gl-font-size: 14px; $gl-font-size-xs: 11px; $gl-font-size-small: 12px; -$gl-font-size-medium: 1.43rem; +$gl-font-size-medium: 20px; $gl-font-size-large: 16px; $gl-font-weight-normal: 400; $gl-font-weight-bold: 600; diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss index 5ca76bb6c5a..069f45bff49 100644 --- a/app/assets/stylesheets/framework/variables_overrides.scss +++ b/app/assets/stylesheets/framework/variables_overrides.scss @@ -28,3 +28,9 @@ $popover-border-width: 1px; $popover-border-color: $border-color; $popover-box-shadow: 0 $border-radius-small $border-radius-default 0 $shadow-color; $popover-arrow-outer-color: $shadow-color; +$h1-font-size: 14px * 2.5; +$h2-font-size: 14px * 2; +$h3-font-size: 14px * 1.75; +$h4-font-size: 14px * 1.5; +$h5-font-size: 14px * 1.25; +$h6-font-size: 14px; diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index c7dde2f0f2a..09235661cea 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -135,6 +135,7 @@ .build-loader-animation { @include build-loader-animation; float: left; + padding-left: $gl-padding-8; } } diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 033686823a2..293dd20ad49 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -85,7 +85,7 @@ module NotesHelper diffs_project_merge_request_path(discussion.project, discussion.noteable, path_params) elsif discussion.for_commit? - anchor = discussion.line_code if discussion.diff_discussion? + anchor = discussion.diff_discussion? ? discussion.line_code : "note_#{discussion.first_note.id}" project_commit_path(discussion.project, discussion.noteable, anchor: anchor) end diff --git a/app/models/concerns/discussion_on_diff.rb b/app/models/concerns/discussion_on_diff.rb index 266c37fa3a1..86b61248534 100644 --- a/app/models/concerns/discussion_on_diff.rb +++ b/app/models/concerns/discussion_on_diff.rb @@ -39,6 +39,7 @@ module DiscussionOnDiff # Returns an array of at most 16 highlighted lines above a diff note def truncated_diff_lines(highlight: true, diff_limit: nil) + return [] unless on_text? return [] if diff_line.nil? && first_note.is_a?(LegacyDiffNote) diff_limit = [diff_limit, NUMBER_OF_TRUNCATED_DIFF_LINES].compact.min diff --git a/app/views/notify/_note_email.html.haml b/app/views/notify/_note_email.html.haml index 1fbae2f64ed..83c7f548975 100644 --- a/app/views/notify/_note_email.html.haml +++ b/app/views/notify/_note_email.html.haml @@ -4,17 +4,13 @@ - note_style = local_assigns.fetch(:note_style, "") - discussion = note.discussion if note.part_of_discussion? -- diff_discussion = discussion&.diff_discussion? -- on_image = discussion.on_image? if diff_discussion - if discussion - - phrase_end_char = on_image ? "." : ":" - %p{ style: "color: #777777;" } - = succeed phrase_end_char do + = succeed ':' do = link_to note.author_name, user_url(note.author) - - if diff_discussion + - if discussion&.diff_discussion? - if discussion.new_discussion? started a new discussion - else @@ -31,7 +27,7 @@ %p.details #{link_to note.author_name, user_url(note.author)} commented: -- if diff_discussion && !on_image +- if discussion&.diff_discussion? && discussion.on_text? = content_for :head do = stylesheet_link_tag 'mailers/highlighted_diff_email' diff --git a/app/views/notify/_note_email.text.erb b/app/views/notify/_note_email.text.erb index 4bf252b6ce1..50209c46ed1 100644 --- a/app/views/notify/_note_email.text.erb +++ b/app/views/notify/_note_email.text.erb @@ -20,7 +20,7 @@ <% end -%> -<% if discussion&.diff_discussion? -%> +<% if discussion&.diff_discussion? && discussion.on_text? -%> <% discussion.truncated_diff_lines(highlight: false, diff_limit: diff_limit).each do |line| -%> <%= "> #{line.text}\n" -%> <% end -%> diff --git a/changelogs/unreleased/51668-fix-line-numbers.yml b/changelogs/unreleased/51668-fix-line-numbers.yml new file mode 100644 index 00000000000..ac6e45e3cc7 --- /dev/null +++ b/changelogs/unreleased/51668-fix-line-numbers.yml @@ -0,0 +1,5 @@ +--- +title: Adjust line-height of blame view line numbers +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/52620-fix-loader-animation-alignment.yml b/changelogs/unreleased/52620-fix-loader-animation-alignment.yml new file mode 100644 index 00000000000..5cfb7fc019f --- /dev/null +++ b/changelogs/unreleased/52620-fix-loader-animation-alignment.yml @@ -0,0 +1,5 @@ +--- +title: Aligns build loader animation with the job log +merge_request: 23959 +author: +type: fixed diff --git a/changelogs/unreleased/dm-note-email-image-diff-discussion.yml b/changelogs/unreleased/dm-note-email-image-diff-discussion.yml new file mode 100644 index 00000000000..6532052e132 --- /dev/null +++ b/changelogs/unreleased/dm-note-email-image-diff-discussion.yml @@ -0,0 +1,5 @@ +--- +title: Fix notification email for image diff notes +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/security-import-symlink.yml b/changelogs/unreleased/security-import-symlink.yml new file mode 100644 index 00000000000..fe1b6eccf9e --- /dev/null +++ b/changelogs/unreleased/security-import-symlink.yml @@ -0,0 +1,5 @@ +--- +title: Fix persistent symlink in project import +merge_request: +author: +type: security diff --git a/changelogs/unreleased/winh-discussion-header-commented.yml b/changelogs/unreleased/winh-discussion-header-commented.yml new file mode 100644 index 00000000000..8d08409b504 --- /dev/null +++ b/changelogs/unreleased/winh-discussion-header-commented.yml @@ -0,0 +1,5 @@ +--- +title: Display "commented" only for commit discussions on merge requests +merge_request: 23622 +author: +type: fixed diff --git a/changelogs/unreleased/winh-merge-request-commit-context.yml b/changelogs/unreleased/winh-merge-request-commit-context.yml new file mode 100644 index 00000000000..9e12a926af4 --- /dev/null +++ b/changelogs/unreleased/winh-merge-request-commit-context.yml @@ -0,0 +1,5 @@ +--- +title: Display commit ID for discussions made on merge request commits +merge_request: 23837 +author: +type: fixed diff --git a/config/initializers/8_metrics.rb b/config/initializers/zz_metrics.rb index 468f80939d7..462e8c811a6 100644 --- a/config/initializers/8_metrics.rb +++ b/config/initializers/zz_metrics.rb @@ -1,3 +1,6 @@ +# This file was prefixed with zz_ because we want to load it the last! +# See: https://gitlab.com/gitlab-org/gitlab-ce/issues/55611 + # Autoload all classes that we want to instrument, and instrument the methods we # need. This takes the Gitlab::Metrics::Instrumentation module as an argument so # that we can stub it for testing, as it is only called when metrics are diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md index bef166f2aec..a36dc6424a7 100644 --- a/doc/development/instrumentation.md +++ b/doc/development/instrumentation.md @@ -35,7 +35,7 @@ Using this method is in general preferred over directly calling the various instrumentation methods. Method instrumentation should be added in the initializer -`config/initializers/8_metrics.rb`. +`config/initializers/zz_metrics.rb`. ### Examples diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md index c1f2e844362..a1e5735670a 100644 --- a/doc/user/project/clusters/serverless/index.md +++ b/doc/user/project/clusters/serverless/index.md @@ -31,7 +31,7 @@ To run Knative on Gitlab, you will need: external IP address for all the applications served by Knative. You will be prompted to enter a wildcard domain where your applications will be served. Configure your DNS server to use the external IP address for that domain. -1. **`gitlab-ci.yml`:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko) +1. **`.gitlab-ci.yml`:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko) to build the application and the [TriggerMesh CLI](https://github.com/triggermesh/tm) to simplify the deployment of knative services and functions. 1. **`serverless.yml`** (for [functions only](#deploying-functions)): When using serverless to deploy functions, the `serverless.yml` file @@ -81,7 +81,7 @@ you to focus on a single task that can be executed/scaled automatically and inde In order to deploy functions to your Knative instance, the following templates must be present: -1. `gitlab-ci.yml`: This template allows to define the stage, environment, and +1. `.gitlab-ci.yml`: This template allows to define the stage, environment, and image to be used for your functions. It must be included at the root of your repository: ```yaml diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index c9e2a6a78d9..bdecff0931c 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -3,7 +3,8 @@ module Gitlab module ImportExport module CommandLineUtil - DEFAULT_MODE = 0700 + UNTAR_MASK = 'u+rwX,go+rX,go-w' + DEFAULT_DIR_MODE = 0700 def tar_czf(archive:, dir:) tar_with_options(archive: archive, dir: dir, options: 'czf') @@ -14,8 +15,8 @@ module Gitlab end def mkdir_p(path) - FileUtils.mkdir_p(path, mode: DEFAULT_MODE) - FileUtils.chmod(DEFAULT_MODE, path) + FileUtils.mkdir_p(path, mode: DEFAULT_DIR_MODE) + FileUtils.chmod(DEFAULT_DIR_MODE, path) end private @@ -41,6 +42,7 @@ module Gitlab def untar_with_options(archive:, dir:, options:) execute(%W(tar -#{options} #{archive} -C #{dir})) + execute(%W(chmod -R #{UNTAR_MASK} #{dir})) end def execute(cmd) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index fed490309cc..776cd9d03d4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4126,6 +4126,9 @@ msgstr "" msgid "MergeRequests|View replaced file @ %{commitId}" msgstr "" +msgid "MergeRequests|commented on commit %{linkStart}%{commitId}%{linkEnd}" +msgstr "" + msgid "MergeRequests|started a discussion" msgstr "" @@ -4135,6 +4138,9 @@ msgstr "" msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}" msgstr "" +msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}" +msgstr "" + msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}" msgstr "" diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 2d1f48bf249..c51f2f958f9 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -64,6 +64,21 @@ FactoryBot.define do resolved_at { Time.now } resolved_by { create(:user) } end + + factory :image_diff_note_on_merge_request do + position do + Gitlab::Diff::Position.new( + old_path: "files/images/any_image.png", + new_path: "files/images/any_image.png", + width: 10, + height: 10, + x: 1, + y: 1, + diff_refs: diff_refs, + position_type: "image" + ) + end + end end factory :diff_note_on_commit, traits: [:on_commit], class: DiffNote do diff --git a/spec/features/merge_request/user_sees_discussions_spec.rb b/spec/features/merge_request/user_sees_discussions_spec.rb index 4ab9a87ad4b..d130ea05654 100644 --- a/spec/features/merge_request/user_sees_discussions_spec.rb +++ b/spec/features/merge_request/user_sees_discussions_spec.rb @@ -88,5 +88,13 @@ describe 'Merge request > User sees discussions', :js do expect(page).to have_content "started a discussion on commit #{note.commit_id[0...7]}" end end + + context 'a commit non-diff discussion' do + let(:note) { create(:discussion_note_on_commit, project: project) } + + it 'displays correct header' do + expect(page).to have_content "commented on commit #{note.commit_id[0...7]}" + end + end end end diff --git a/spec/fixtures/symlink_export.tar.gz b/spec/fixtures/symlink_export.tar.gz Binary files differnew file mode 100644 index 00000000000..f295f69c56c --- /dev/null +++ b/spec/fixtures/symlink_export.tar.gz diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb index 21461e46cf4..0715f34dafe 100644 --- a/spec/helpers/notes_helper_spec.rb +++ b/spec/helpers/notes_helper_spec.rb @@ -185,8 +185,8 @@ describe NotesHelper do context 'for a non-diff discussion' do let(:discussion) { create(:discussion_note_on_commit, project: project).to_discussion } - it 'returns the commit path' do - expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit)) + it 'returns the commit path with the note anchor' do + expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: "note_#{discussion.first_note.id}")) end end end diff --git a/spec/initializers/8_metrics_spec.rb b/spec/initializers/zz_metrics_spec.rb index 80c77057065..3eaccfe8d8b 100644 --- a/spec/initializers/8_metrics_spec.rb +++ b/spec/initializers/zz_metrics_spec.rb @@ -16,7 +16,7 @@ describe 'instrument_classes' do end it 'can autoload and instrument all files' do - require_relative '../../config/initializers/8_metrics' + require_relative '../../config/initializers/zz_metrics' expect { instrument_classes(config) }.not_to raise_error end end diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js index 106a4ac2546..3aff2dd0641 100644 --- a/spec/javascripts/notes/components/noteable_discussion_spec.js +++ b/spec/javascripts/notes/components/noteable_discussion_spec.js @@ -133,8 +133,10 @@ describe('noteable_discussion component', () => { }); }); - describe('commit discussion', () => { + describe('action text', () => { const commitId = 'razupaltuff'; + const truncatedCommitId = commitId.substr(0, 8); + let commitElement; beforeEach(() => { vm.$destroy(); @@ -143,7 +145,6 @@ describe('noteable_discussion component', () => { projectPath: 'something', }; - vm.$destroy(); vm = new Component({ propsData: { discussion: { @@ -159,17 +160,73 @@ describe('noteable_discussion component', () => { }, store, }).$mount(); + + commitElement = vm.$el.querySelector('.commit-sha'); + }); + + describe('for commit discussions', () => { + it('should display a monospace started a discussion on commit', () => { + expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`); + expect(commitElement).not.toBe(null); + expect(commitElement).toHaveText(truncatedCommitId); + }); }); - it('displays a monospace started a discussion on commit', () => { - const truncatedCommitId = commitId.substr(0, 8); + describe('for diff discussion with a commit id', () => { + it('should display started discussion on commit header', done => { + vm.discussion.for_commit = false; - expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`); + vm.$nextTick(() => { + expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`); + expect(commitElement).not.toBe(null); - const commitElement = vm.$el.querySelector('.commit-sha'); + done(); + }); + }); - expect(commitElement).not.toBe(null); - expect(commitElement).toHaveText(truncatedCommitId); + it('should display outdated change on commit header', done => { + vm.discussion.for_commit = false; + vm.discussion.active = false; + + vm.$nextTick(() => { + expect(vm.$el).toContainText( + `started a discussion on an outdated change in commit ${truncatedCommitId}`, + ); + + expect(commitElement).not.toBe(null); + + done(); + }); + }); + }); + + describe('for diff discussions without a commit id', () => { + it('should show started a discussion on the diff text', done => { + Object.assign(vm.discussion, { + for_commit: false, + commit_id: null, + }); + + vm.$nextTick(() => { + expect(vm.$el).toContainText('started a discussion on the diff'); + + done(); + }); + }); + + it('should show discussion on older version text', done => { + Object.assign(vm.discussion, { + for_commit: false, + commit_id: null, + active: false, + }); + + vm.$nextTick(() => { + expect(vm.$el).toContainText('started a discussion on an old version of the diff'); + + done(); + }); + }); }); }); }); diff --git a/spec/lib/gitlab/import_export/command_line_util_spec.rb b/spec/lib/gitlab/import_export/command_line_util_spec.rb new file mode 100644 index 00000000000..8e5e0aefac0 --- /dev/null +++ b/spec/lib/gitlab/import_export/command_line_util_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::ImportExport::CommandLineUtil do + include ExportFileHelper + + let(:path) { "#{Dir.tmpdir}/symlink_test" } + let(:archive) { 'spec/fixtures/symlink_export.tar.gz' } + let(:shared) { Gitlab::ImportExport::Shared.new(nil) } + + subject do + Class.new do + include Gitlab::ImportExport::CommandLineUtil + + def initialize + @shared = Gitlab::ImportExport::Shared.new(nil) + end + end.new + end + + before do + FileUtils.mkdir_p(path) + subject.untar_zxf(archive: archive, dir: path) + end + + after do + FileUtils.rm_rf(path) + end + + it 'has the right mask for project.json' do + expect(file_permissions("#{path}/project.json")).to eq(0755) # originally 777 + end + + it 'has the right mask for uploads' do + expect(file_permissions("#{path}/uploads")).to eq(0755) # originally 555 + end +end diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb index bf34cefe18f..fbc9bcd2df5 100644 --- a/spec/lib/gitlab/import_export/file_importer_spec.rb +++ b/spec/lib/gitlab/import_export/file_importer_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Gitlab::ImportExport::FileImporter do + include ExportFileHelper + let(:shared) { Gitlab::ImportExport::Shared.new(nil) } let(:storage_path) { "#{Dir.tmpdir}/file_importer_spec" } let(:valid_file) { "#{shared.export_path}/valid.json" } @@ -8,6 +10,7 @@ describe Gitlab::ImportExport::FileImporter do let(:hidden_symlink_file) { "#{shared.export_path}/.hidden" } let(:subfolder_symlink_file) { "#{shared.export_path}/subfolder/invalid.json" } let(:evil_symlink_file) { "#{shared.export_path}/.\nevil" } + let(:custom_mode_symlink_file) { "#{shared.export_path}/symlink.mode" } before do stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0) @@ -45,10 +48,18 @@ describe Gitlab::ImportExport::FileImporter do expect(File.exist?(subfolder_symlink_file)).to be false end + it 'removes symlinks without any file permissions' do + expect(File.exist?(custom_mode_symlink_file)).to be false + end + it 'does not remove a valid file' do expect(File.exist?(valid_file)).to be true end + it 'does not change a valid file permissions' do + expect(file_permissions(valid_file)).not_to eq(0000) + end + it 'creates the file in the right subfolder' do expect(shared.export_path).to include('test/abcd') end @@ -84,5 +95,7 @@ describe Gitlab::ImportExport::FileImporter do FileUtils.ln_s(valid_file, subfolder_symlink_file) FileUtils.ln_s(valid_file, hidden_symlink_file) FileUtils.ln_s(valid_file, evil_symlink_file) + FileUtils.ln_s(valid_file, custom_mode_symlink_file) + FileUtils.chmod_R(0000, custom_mode_symlink_file) end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index f6e5c9d33ac..f2d99872401 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -890,22 +890,14 @@ describe Notify do shared_examples 'an email for a note on a diff discussion' do |model| let(:note) { create(model, author: note_author) } - context 'when note is on image' do + context 'when note is not on text' do before do - allow_any_instance_of(DiffDiscussion).to receive(:on_image?).and_return(true) + allow_any_instance_of(DiffDiscussion).to receive(:on_text?).and_return(false) end it 'does not include diffs with character-level highlighting' do is_expected.not_to have_body_text '<span class="p">}</span></span>' end - - it 'ends the intro with a dot' do - is_expected.to have_body_text "#{note.diff_file.file_path}</a>." - end - end - - it 'ends the intro with a colon' do - is_expected.to have_body_text "#{note.diff_file.file_path}</a>:" end it 'includes diffs with character-level highlighting' do diff --git a/spec/models/concerns/discussion_on_diff_spec.rb b/spec/models/concerns/discussion_on_diff_spec.rb index 73eb7a1160d..4b16e6e3902 100644 --- a/spec/models/concerns/discussion_on_diff_spec.rb +++ b/spec/models/concerns/discussion_on_diff_spec.rb @@ -50,11 +50,17 @@ describe DiscussionOnDiff do end context "when the diff line does not exist on a legacy diff note" do + subject { create(:legacy_diff_note_on_merge_request).to_discussion } + it "returns an empty array" do - legacy_note = LegacyDiffNote.new + expect(truncated_lines).to eq([]) + end + end - allow(subject).to receive(:first_note).and_return(legacy_note) + context 'when the discussion is on an image' do + subject { create(:image_diff_note_on_merge_request).to_discussion } + it 'returns an empty array' do expect(truncated_lines).to eq([]) end end diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb index 40ce8ab736a..fda00a693f0 100644 --- a/spec/models/diff_note_spec.rb +++ b/spec/models/diff_note_spec.rb @@ -337,24 +337,9 @@ describe DiffNote do end describe "image diff notes" do - let(:path) { "files/images/any_image.png" } - - let!(:position) do - Gitlab::Diff::Position.new( - old_path: path, - new_path: path, - width: 10, - height: 10, - x: 1, - y: 1, - diff_refs: merge_request.diff_refs, - position_type: "image" - ) - end + subject { build(:image_diff_note_on_merge_request, project: project, noteable: merge_request) } describe "validations" do - subject { build(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) } - it { is_expected.not_to validate_presence_of(:line_code) } it "does not validate diff line" do diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index a49036c3b80..ac320934f5a 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -133,6 +133,6 @@ module ExportFileHelper end def file_permissions(file) - File.stat(file).mode & 0777 + File.lstat(file).mode & 0777 end end |