diff options
author | Mayra Cabrera <mcabrera@gitlab.com> | 2018-06-05 17:42:01 +0000 |
---|---|---|
committer | Mayra Cabrera <mcabrera@gitlab.com> | 2018-06-05 17:42:01 +0000 |
commit | a9d6d022e4b3c6b09465b7667eb69e423db7cb3b (patch) | |
tree | 212d48fc03459954690509daacf9b12613395969 | |
parent | 2e1f2364c864232971e009ab4d58377c46f23375 (diff) | |
parent | 4fd808ed1a061b7d1a8882a8eaccac2ae485f18d (diff) | |
download | gitlab-ce-a9d6d022e4b3c6b09465b7667eb69e423db7cb3b.tar.gz |
Merge branch '11-0-stable-prepare-rc3' into '11-0-stable'
Prepare 11.0 RC3 release
See merge request gitlab-org/gitlab-ce!19414
53 files changed, 433 insertions, 256 deletions
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue index 05dbc1410de..6efcad6adea 100644 --- a/app/assets/javascripts/ide/components/activity_bar.vue +++ b/app/assets/javascripts/ide/components/activity_bar.vue @@ -1,4 +1,5 @@ <script> +import $ from 'jquery'; import { mapActions, mapGetters, mapState } from 'vuex'; import Icon from '~/vue_shared/components/icon.vue'; import tooltip from '~/vue_shared/directives/tooltip'; @@ -20,6 +21,13 @@ export default { }, methods: { ...mapActions(['updateActivityBarView']), + changedActivityView(e, view) { + e.currentTarget.blur(); + + this.updateActivityBarView(view); + + $(e.currentTarget).tooltip('hide'); + }, }, activityBarViews, }; @@ -54,7 +62,7 @@ export default { :class="{ active: currentActivityView === $options.activityBarViews.edit }" - @click.prevent="updateActivityBarView($options.activityBarViews.edit)" + @click.prevent="changedActivityView($event, $options.activityBarViews.edit)" :title="s__('IDE|Edit')" :aria-label="s__('IDE|Edit')" > @@ -73,7 +81,7 @@ export default { :class="{ active: currentActivityView === $options.activityBarViews.review }" - @click.prevent="updateActivityBarView($options.activityBarViews.review)" + @click.prevent="changedActivityView($event, $options.activityBarViews.review)" :title="s__('IDE|Review')" :aria-label="s__('IDE|Review')" > @@ -92,7 +100,7 @@ export default { :class="{ active: currentActivityView === $options.activityBarViews.commit }" - @click.prevent="updateActivityBarView($options.activityBarViews.commit)" + @click.prevent="changedActivityView($event, $options.activityBarViews.commit)" :title="s__('IDE|Commit')" :aria-label="s__('IDE|Commit')" > diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index eafdaf4a672..7d0ff53f366 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -426,7 +426,7 @@ export default class LabelsSelect { const tpl = _.template([ '<% _.each(labels, function(label){ %>', '<a href="<%- issueUpdateURL.slice(0, issueUpdateURL.lastIndexOf("/")) %>?label_name[]=<%- encodeURIComponent(label.title) %>">', - '<span class="label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">', + '<span class="badge label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">', '<%- label.title %>', '</span>', '</a>', diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue index 69d588eb25d..88360b46f24 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue @@ -35,7 +35,12 @@ export default { </script> <template> - <div class="hide-collapsed value issuable-show-labels js-value"> + <div + class="hide-collapsed value issuable-show-labels js-value" + :class="{ + 'has-labels':!isEmpty, + }" + > <span v-if="isEmpty" class="text-secondary" @@ -50,7 +55,7 @@ export default { > <span v-tooltip - class="label color-label" + class="badge color-label" data-placement="bottom" data-container="body" :style="labelStyle(label)" diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.vue b/app/assets/javascripts/vue_shared/components/table_pagination.vue index 22fc5757447..6f231619f26 100644 --- a/app/assets/javascripts/vue_shared/components/table_pagination.vue +++ b/app/assets/javascripts/vue_shared/components/table_pagination.vue @@ -124,15 +124,18 @@ break; } }, + hideOnSmallScreen(item) { + return !item.first && !item.last && !item.next && !item.prev && !item.active; + }, }, }; </script> <template> <div v-if="showPagination" - class="gl-pagination" + class="gl-pagination prepend-top-default" > - <ul class="pagination clearfix"> + <ul class="pagination justify-content-center"> <li v-for="(item, index) in getItems" :key="index" @@ -142,12 +145,17 @@ 'js-next-button': item.next, 'js-last-button': item.last, 'js-first-button': item.first, + 'd-none d-md-block': hideOnSmallScreen(item), separator: item.separator, active: item.active, - disabled: item.disabled + disabled: item.disabled || item.separator }" + class="page-item" > - <a @click.prevent="changePage(item.title, item.disabled)"> + <a + @click.prevent="changePage(item.title, item.disabled)" + class="page-link" + > {{ item.title }} </a> </li> diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss index e24f8b1d4e8..fc4a4250acc 100644 --- a/app/assets/stylesheets/bootstrap_migration.scss +++ b/app/assets/stylesheets/bootstrap_migration.scss @@ -24,6 +24,11 @@ html { font-size: 14px; } +legend { + border-bottom: 1px solid $border-color; + margin-bottom: 20px; +} + button, html [type="button"], [type="reset"], @@ -61,8 +66,23 @@ a { code { padding: 2px 4px; + color: $red-600; background-color: $red-100; border-radius: 3px; + + .code & { + background-color: inherit; + padding: unset; + } + + .build-trace & { + background-color: inherit; + padding: inherit; + } +} + +.code { + padding: 9.5px; } table { @@ -168,7 +188,9 @@ table { .nav-tabs { .nav-link { - border: 0; + border-top: 0; + border-left: 0; + border-right: 0; } .nav-item { diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index b91d579cae6..74475daae14 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -35,6 +35,12 @@ @include media-breakpoint-down(xs) { width: 100%; } + + &.projects-dropdown-menu { + padding: 0; + overflow-y: initial; + max-height: initial; + } } .dropdown-toggle, diff --git a/app/assets/stylesheets/framework/gitlab_theme.scss b/app/assets/stylesheets/framework/gitlab_theme.scss index 11e21edfc1b..14dd3879bdc 100644 --- a/app/assets/stylesheets/framework/gitlab_theme.scss +++ b/app/assets/stylesheets/framework/gitlab_theme.scss @@ -35,7 +35,7 @@ } &.active > a, - &.dropdown.open > a { + &.dropdown.show > a { color: $color-900; background-color: $color-alternate; } @@ -74,7 +74,7 @@ } &.active > a, - &.dropdown.open > a { + &.dropdown.show > a { color: $color-900; background-color: $color-alternate; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 2085e5646ef..094134b63b0 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -297,12 +297,6 @@ display: flex; margin: 0 0 0 6px; - .projects-dropdown-menu { - padding: 0; - overflow-y: initial; - max-height: initial; - } - .dropdown-chevron { position: relative; top: -1px; diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss index d3e013590b6..50a1b1c446d 100644 --- a/app/assets/stylesheets/framework/pagination.scss +++ b/app/assets/stylesheets/framework/pagination.scss @@ -1,91 +1,6 @@ .gl-pagination { - text-align: center; - border-top: 1px solid $border-color; - margin: 0; - margin-top: 0; - - .pagination { - padding: 0; - margin: 20px 0; - - a { - cursor: pointer; - } - - .separator, - .separator:hover { - a { - cursor: default; - background-color: $gray-light; - padding: $gl-vert-padding; - } - } - } - - - .gap, - .gap:hover { - background-color: $gray-light; - padding: $gl-vert-padding; - cursor: default; - } -} - -.card > .gl-pagination { - margin: 0; -} - -/** - * Extra-small screen pagination. - */ -@media (max-width: 320px) { - .gl-pagination { - .first, - .last { - display: none; - } - - .page-item { - display: none; - - &.active { - display: inline; - } - } - } -} - -/** - * Small screen pagination - */ -@include media-breakpoint-down(xs) { - .gl-pagination { - .pagination li a { - padding: 6px 10px; - } - - .page-item { - display: none; - - &.active { - display: inline; - } - } - } -} - -/** - * Medium screen pagination - */ -@media (min-width: map-get($grid-breakpoints, xs)) and (max-width: map-get($grid-breakpoints, sm)) { - .gl-pagination { - .page-item { - display: none; - - &.active, - &.sibling { - display: inline; - } - } + a { + color: inherit; + text-decoration: none; } } diff --git a/app/assets/stylesheets/framework/terms.scss b/app/assets/stylesheets/framework/terms.scss index 744fd0ff796..7cda674e5c8 100644 --- a/app/assets/stylesheets/framework/terms.scss +++ b/app/assets/stylesheets/framework/terms.scss @@ -11,15 +11,15 @@ padding-top: $gl-padding; } - .panel { - .panel-heading { + .card { + .card-header { display: -webkit-flex; display: flex; align-items: center; justify-content: space-between; line-height: $line-height-base; - .title { + .card-title { display: flex; align-items: center; @@ -34,6 +34,8 @@ .navbar-collapse { padding-right: 0; + flex-grow: 0; + flex-basis: auto; .navbar-nav { margin: 0; diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 97b821e0cb9..9e77ea03a24 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -114,26 +114,27 @@ font-size: 0.95em; } + blockquote, .blockquote { color: $gl-grayish-blue; font-size: inherit; padding: 8px 24px; margin: 16px 0; border-left: 3px solid $white-dark; - } - .blockquote:dir(rtl) { - border-left: 0; - border-right: 3px solid $white-dark; - } + &:dir(rtl) { + border-left: 0; + border-right: 3px solid $white-dark; + } - .blockquote p { - color: $gl-grayish-blue !important; - font-size: inherit; - line-height: 1.5; + p { + color: $gl-grayish-blue !important; + font-size: inherit; + line-height: 1.5; - &:last-child { - margin: 0; + &:last-child { + margin: 0; + } } } diff --git a/app/assets/stylesheets/mailers/highlighted_diff_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss index b5eda79e5ed..1835c4364d3 100644 --- a/app/assets/stylesheets/mailers/highlighted_diff_email.scss +++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss @@ -138,6 +138,7 @@ pre { margin: 0; } +blockquote, .blockquote { color: $gl-grayish-blue; padding: 0 0 0 15px; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 4aea9740735..b42c232fd91 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -485,6 +485,15 @@ .sidebar-collapsed-user { padding-bottom: 0; margin-bottom: 10px; + + .author_link { + padding-left: 0; + + .avatar { + position: static; + margin: 0; + } + } } .issuable-header-btn { diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index e178371d21f..25f011a534b 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -196,6 +196,10 @@ .prioritized-labels { margin-bottom: 30px; + h5 { + font-size: $gl-font-size; + } + .add-priority { display: none; color: $gray-light; @@ -210,6 +214,10 @@ } .other-labels { + h5 { + font-size: $gl-font-size; + } + .remove-priority { display: none; } diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss index 6bbcb15329c..2b3cc33c8ae 100644 --- a/app/assets/stylesheets/pages/repo.scss +++ b/app/assets/stylesheets/pages/repo.scss @@ -183,7 +183,7 @@ svg { position: relative; - top: -1px; + top: -2px; } .ide-file-changed-icon { @@ -458,6 +458,10 @@ width: auto; margin-right: 0; + a { + height: 60px; + } + a:hover, a:focus { text-decoration: none; @@ -718,9 +722,17 @@ } .ide-new-btn { + .btn { + padding-top: 3px; + padding-bottom: 3px; + } + + .dropdown { + display: flex; + } + .dropdown-toggle svg { - margin-top: -2px; - margin-bottom: 2px; + top: 0; } .dropdown-menu { @@ -877,6 +889,7 @@ border-top: 1px solid transparent; border-bottom: 1px solid transparent; outline: 0; + cursor: pointer; svg { margin: 0 auto; diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 2b3773eebad..43c39c43bc1 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -174,7 +174,7 @@ .option-description, .option-disabled-reason { - margin-left: 45px; + margin-left: 30px; color: $project-option-descr-color; } diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss index 90ccd4abd90..bb10928a037 100644 --- a/app/assets/stylesheets/print.scss +++ b/app/assets/stylesheets/print.scss @@ -22,9 +22,9 @@ header, nav, -nav.main-nav, nav.navbar-collapse, nav.navbar-collapse.collapse, +.nav-sidebar, .profiler-results, .tree-ref-holder, .tree-holder .breadcrumb, @@ -38,7 +38,8 @@ ul.notes-form, .edit-link, .note-action-button, .right-sidebar, -.flash-container { +.flash-container, +#js-peek { display: none !important; } diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index adc423af9e1..ef1bf283d0c 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -36,7 +36,7 @@ module ApplicationSettingsHelper # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. - def restricted_level_checkboxes(help_block_id, checkbox_name) + def restricted_level_checkboxes(help_block_id, checkbox_name, options = {}) Gitlab::VisibilityLevel.values.map do |level| checked = restricted_visibility_levels(true).include?(level) css_class = checked ? 'active' : '' @@ -46,6 +46,7 @@ module ApplicationSettingsHelper check_box_tag(checkbox_name, level, checked, autocomplete: 'off', 'aria-describedby' => help_block_id, + 'class' => options[:class], id: tag_name) + visibility_level_icon(level) + visibility_level_label(level) end end @@ -53,7 +54,7 @@ module ApplicationSettingsHelper # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. - def import_sources_checkboxes(help_block_id) + def import_sources_checkboxes(help_block_id, options = {}) Gitlab::ImportSources.options.map do |name, source| checked = Gitlab::CurrentSettings.import_sources.include?(source) css_class = checked ? 'active' : '' @@ -63,6 +64,7 @@ module ApplicationSettingsHelper check_box_tag(checkbox_name, source, checked, autocomplete: 'off', 'aria-describedby' => help_block_id, + 'class' => options[:class], id: name.tr(' ', '_')) + name end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 55078e1a2d2..dfca799a53d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -238,6 +238,14 @@ module ProjectsHelper "git push --set-upstream #{repository_url}/$(git rev-parse --show-toplevel | xargs basename).git $(git rev-parse --abbrev-ref HEAD)" end + def show_xcode_link?(project = @project) + browser.platform.mac? && project.repository.xcode_project? + end + + def xcode_uri_to_repo(project = @project) + "xcode://clone?repo=#{CGI.escape(default_url_to_repo(project))}" + end + private def get_project_nav_tabs(project, current_user) diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml index 2b4d3bab54d..05520bd8d2d 100644 --- a/app/views/admin/application_settings/_visibility_and_access.html.haml +++ b/app/views/admin/application_settings/_visibility_and_access.html.haml @@ -23,7 +23,7 @@ .col-sm-10 - checkbox_name = 'application_setting[restricted_visibility_levels][]' = hidden_field_tag(checkbox_name) - - restricted_level_checkboxes('restricted-visibility-help', checkbox_name).each do |level| + - restricted_level_checkboxes('restricted-visibility-help', checkbox_name, class: 'form-check-input').each do |level| .form-check = level %span.form-text.text-muted#restricted-visibility-help @@ -33,7 +33,7 @@ = f.label :import_sources, class: 'col-form-label col-sm-2' .col-sm-10 = hidden_field_tag 'application_setting[import_sources][]' - - import_sources_checkboxes('import-sources-help').each do |source| + - import_sources_checkboxes('import-sources-help', class: 'form-check-input').each do |source| .form-check= source %span.form-text.text-muted#import-sources-help Enabled sources for code import during project creation. OmniAuth must be configured for GitHub diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml index 35a331283ab..04acc5f8423 100644 --- a/app/views/admin/users/_access_levels.html.haml +++ b/app/views/admin/users/_access_levels.html.haml @@ -1,26 +1,26 @@ %fieldset %legend Access - .form-group - = f.label :projects_limit, class: 'col-form-label' + .form-group.row + = f.label :projects_limit, class: 'col-form-label col-sm-2' .col-sm-10= f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control' - .form-group - = f.label :can_create_group, class: 'col-form-label' + .form-group.row + = f.label :can_create_group, class: 'col-form-label col-sm-2' .col-sm-10= f.check_box :can_create_group - .form-group - = f.label :access_level, class: 'col-form-label' + .form-group.row + = f.label :access_level, class: 'col-form-label col-sm-2' .col-sm-10 - editing_current_user = (current_user == @user) = f.radio_button :access_level, :regular, disabled: editing_current_user - = label_tag :regular do + = label_tag :regular, class: 'font-weight-bold' do Regular %p.light Regular users have access to their groups and projects = f.radio_button :access_level, :admin, disabled: editing_current_user - = label_tag :admin do + = label_tag :admin, class: 'font-weight-bold' do Admin %p.light Administrators have access to all groups, projects and users and can manage all features in this installation @@ -28,8 +28,8 @@ %p.light You cannot remove your own admin rights. - .form-group - = f.label :external, class: 'col-form-label' + .form-group.row + = f.label :external, class: 'col-form-label col-sm-2' .col-sm-10 = f.check_box :external do External diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 010cb2ac354..58be07fc83e 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -56,7 +56,7 @@ = f.label :linkedin, class: 'col-form-label col-sm-2' .col-sm-10= f.text_field :linkedin, class: 'form-control' .form-group.row - = f.label :twitter, class: 'col-form-label' + = f.label :twitter, class: 'col-form-label col-sm-2' .col-sm-10= f.text_field :twitter, class: 'form-control' .form-group.row = f.label :website_url, 'Website', class: 'col-form-label col-sm-2' diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml index eb9790c7903..581576a8a3d 100644 --- a/app/views/import/gitea/new.html.haml +++ b/app/views/import/gitea/new.html.haml @@ -12,11 +12,11 @@ = form_tag personal_access_token_import_gitea_path do .form-group.row - = label_tag :gitea_host_url, 'Gitea Host URL', class: 'col-form-label col-sm-8' + = label_tag :gitea_host_url, 'Gitea Host URL', class: 'col-form-label col-sm-2' .col-sm-4 = text_field_tag :gitea_host_url, nil, placeholder: 'https://try.gitea.io', class: 'form-control' .form-group.row - = label_tag :personal_access_token, 'Personal Access Token', class: 'col-form-label col-sm-8' + = label_tag :personal_access_token, 'Personal Access Token', class: 'col-form-label col-sm-2' .col-sm-4 = text_field_tag :personal_access_token, nil, class: 'form-control' .form-actions diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml index c63cf2b31cb..b9ebb1a39d9 100644 --- a/app/views/import/github/new.html.haml +++ b/app/views/import/github/new.html.haml @@ -19,7 +19,7 @@ = form_tag personal_access_token_import_github_path, method: :post, class: 'form-inline' do .form-group - = text_field_tag :personal_access_token, '', class: 'form-control', placeholder: _('Personal Access Token'), size: 40 + = text_field_tag :personal_access_token, '', class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40 = submit_tag _('List your GitHub repositories'), class: 'btn btn-success' - unless github_import_configured? diff --git a/app/views/kaminari/gitlab/_first_page.html.haml b/app/views/kaminari/gitlab/_first_page.html.haml index 369165da02a..3b7d4a1c578 100644 --- a/app/views/kaminari/gitlab/_first_page.html.haml +++ b/app/views/kaminari/gitlab/_first_page.html.haml @@ -5,5 +5,5 @@ -# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%li.first.page-item +%li.page-item.js-first-button = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link' diff --git a/app/views/kaminari/gitlab/_gap.html.haml b/app/views/kaminari/gitlab/_gap.html.haml index 6eec30212d1..849f92fdc95 100644 --- a/app/views/kaminari/gitlab/_gap.html.haml +++ b/app/views/kaminari/gitlab/_gap.html.haml @@ -4,5 +4,5 @@ -# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%li.page-item.disabled +%li.page-item.disabled.d-none.d-md-block = link_to raw(t 'views.pagination.truncate'), '#', class: 'page-link' diff --git a/app/views/kaminari/gitlab/_last_page.html.haml b/app/views/kaminari/gitlab/_last_page.html.haml index 8b49db58281..7836e17f877 100644 --- a/app/views/kaminari/gitlab/_last_page.html.haml +++ b/app/views/kaminari/gitlab/_last_page.html.haml @@ -5,5 +5,5 @@ -# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%li.last.page-item +%li.page-item.js-last-button = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {remote: remote, class: 'page-link'} diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml index 05f151555ad..a7fa1a21a6c 100644 --- a/app/views/kaminari/gitlab/_next_page.html.haml +++ b/app/views/kaminari/gitlab/_next_page.html.haml @@ -8,5 +8,5 @@ - page_url = current_page.last? ? '#' : url -%li.page-item{ class: ('disabled' if current_page.last?) } +%li.page-item.js-next-button{ class: ('disabled' if current_page.last?) } = link_to raw(t 'views.pagination.next'), page_url, rel: 'next', remote: remote, class: 'page-link' diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml index 8a40e13a537..d0dc1784540 100644 --- a/app/views/kaminari/gitlab/_page.html.haml +++ b/app/views/kaminari/gitlab/_page.html.haml @@ -6,5 +6,5 @@ -# total_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%li.page-item.js-pagination-page{ class: [active_when(page.current?), ('sibling' if page.next? || page.prev?)] } +%li.page-item.js-pagination-page{ class: [active_when(page.current?), ('sibling' if page.next? || page.prev?), ('d-none d-md-block' if !page.current?) ] } = link_to page, url, { remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil, class: 'page-link' } diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml index a6435deb4bf..ac9e274dbc7 100644 --- a/app/views/kaminari/gitlab/_paginator.html.haml +++ b/app/views/kaminari/gitlab/_paginator.html.haml @@ -6,7 +6,7 @@ -# remote: data-remote -# paginator: the paginator that renders the pagination tags inside = paginator.render do - .gl-pagination + .gl-pagination.prepend-top-default %ul.pagination.justify-content-center - unless current_page.first? = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml index f4a11a449b7..12b0e106a62 100644 --- a/app/views/kaminari/gitlab/_prev_page.html.haml +++ b/app/views/kaminari/gitlab/_prev_page.html.haml @@ -8,5 +8,5 @@ - page_url = current_page.first? ? '#' : url -%li.page-item{ class: ('disabled' if current_page.first?) } +%li.page-item.js-previous-button{ class: ('disabled' if current_page.first?) } = link_to raw(t 'views.pagination.previous'), page_url, rel: 'prev', remote: remote, class: 'page-link' diff --git a/app/views/kaminari/gitlab/_without_count.html.haml b/app/views/kaminari/gitlab/_without_count.html.haml index 1425a809052..f780400ebcb 100644 --- a/app/views/kaminari/gitlab/_without_count.html.haml +++ b/app/views/kaminari/gitlab/_without_count.html.haml @@ -1,5 +1,5 @@ -.gl-pagination - %ul.pagination.clearfix +.gl-pagination.prepend-top-default + %ul.pagination.justify-content-center - if previous_path %li.page-item.prev = link_to(t('views.pagination.previous'), previous_path, rel: 'prev', class: 'page-link') diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml index a8964b19ba1..977eb350365 100644 --- a/app/views/layouts/terms.html.haml +++ b/app/views/layouts/terms.html.haml @@ -14,9 +14,9 @@ %div{ class: "#{container_class} limit-container-width" } .content{ id: "content-body" } - .panel.panel-default - .panel-heading - .title + .card + .card-header + .card-title = brand_header_logo - logo_text = brand_header_logo_type - if logo_text.present? diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 075badb9e56..89940512bc6 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -42,6 +42,10 @@ .project-clone-holder = render "shared/clone_panel" + - if show_xcode_link?(@project) + .project-action-button.project-xcode.inline + = render "projects/buttons/xcode_link" + - if current_user - if can?(current_user, :download_code, @project) = render 'projects/buttons/download', project: @project, ref: @ref diff --git a/app/views/projects/buttons/_xcode_link.html.haml b/app/views/projects/buttons/_xcode_link.html.haml new file mode 100644 index 00000000000..a8b32fb0ef5 --- /dev/null +++ b/app/views/projects/buttons/_xcode_link.html.haml @@ -0,0 +1,2 @@ +%a.btn.btn-default{ href: xcode_uri_to_repo(@project) } + = _("Open in Xcode") diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 9c78bade254..1f183c274be 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -22,7 +22,7 @@ -# Only show it in the first page - hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1') .prioritized-labels{ class: ('hide' if hide) } - %h5 Prioritized Labels + %h5.prepend-top-10 Prioritized Labels %ul.content-list.manage-labels-list.js-prioritized-labels{ "data-url" => set_priorities_project_labels_path(@project) } #js-priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty?}" } = render 'shared/empty_states/priority_labels' diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 35a09f06bfa..5bb1bfb7059 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -29,16 +29,16 @@ .col-lg-9.js-toggle-container %ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' } - %li{ class: active_when(active_tab == 'blank'), role: 'presentation' } - %a{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab' }, role: 'tab' } + %li.nav-item{ role: 'presentation' } + %a.nav-link.active{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab' }, role: 'tab' } %span.d-none.d-sm-block Blank project %span.d-block.d-sm-none Blank - %li{ class: active_when(active_tab == 'template'), role: 'presentation' } - %a{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab' }, role: 'tab' } + %li.nav-item{ role: 'presentation' } + %a.nav-link{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab' }, role: 'tab' } %span.d-none.d-sm-block Create from template %span.d-block.d-sm-none Template - %li{ class: active_when(active_tab == 'import'), role: 'presentation' } - %a{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab' }, role: 'tab' } + %li.nav-item{ role: 'presentation' } + %a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab' }, role: 'tab' } %span.d-none.d-sm-block Import project %span.d-block.d-sm-none Import diff --git a/app/views/shared/_visibility_level.html.haml b/app/views/shared/_visibility_level.html.haml index d67409ffe14..01ce1225b8d 100644 --- a/app/views/shared/_visibility_level.html.haml +++ b/app/views/shared/_visibility_level.html.haml @@ -1,11 +1,11 @@ - with_label = local_assigns.fetch(:with_label, true) -.form-group.visibility-level-setting +.form-group.row.visibility-level-setting - if with_label = f.label :visibility_level, class: 'col-form-label col-sm-2' do Visibility Level = link_to icon('question-circle'), help_page_path("public_access/public_access") - %div{ :class => ("col-sm-10" if with_label) } + %div{ :class => (with_label ? "col-sm-10" : "col-sm-12") } - if can_change_visibility_level = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: visibility_level, form_model: form_model) - else diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml index 1e27253aaeb..01fbc163a14 100644 --- a/app/views/shared/issuable/form/_metadata.html.haml +++ b/app/views/shared/issuable/form/_metadata.html.haml @@ -15,15 +15,15 @@ - else = render "shared/issuable/form/metadata_merge_request_assignee", issuable: issuable, form: form, has_due_date: has_due_date .form-group.row.issue-milestone - = form.label :milestone_id, "Milestone", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-2"}" - .col-10{ class: ("col-md-8" if has_due_date) } + = form.label :milestone_id, "Milestone", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}" + .col-sm-10{ class: ("col-md-8" if has_due_date) } .issuable-form-select-holder = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone" .form-group.row - has_labels = @labels && @labels.any? - = form.label :label_ids, "Labels", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-2"}" + = form.label :label_ids, "Labels", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}" = form.hidden_field :label_ids, multiple: true, value: '' - .col-10{ class: "#{"col-md-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" } + .col-sm-10{ class: "#{"col-md-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" } .issuable-form-select-holder = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false}, dropdown_title: "Select label" - if has_due_date diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml index e0fe551cf36..b9f25a71170 100644 --- a/app/views/users/terms/index.html.haml +++ b/app/views/users/terms/index.html.haml @@ -1,8 +1,8 @@ - redirect_params = { redirect: @redirect } if @redirect -.panel-content.rendered-terms +.card-body.rendered-terms = markdown_field(@term, :terms) -.row-content-block.footer-block.clearfix +.card-footer.footer-block.clearfix - if can?(current_user, :accept_terms, @term) .float-right = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do diff --git a/changelogs/unreleased/45820-add-xcode-link.yml b/changelogs/unreleased/45820-add-xcode-link.yml new file mode 100644 index 00000000000..9e61703ee10 --- /dev/null +++ b/changelogs/unreleased/45820-add-xcode-link.yml @@ -0,0 +1,5 @@ +--- +title: Add Open in Xcode link for xcode repositories +merge_request: +author: +type: added diff --git a/changelogs/unreleased/gh-importer-transactions.yml b/changelogs/unreleased/gh-importer-transactions.yml new file mode 100644 index 00000000000..1489d60a3fb --- /dev/null +++ b/changelogs/unreleased/gh-importer-transactions.yml @@ -0,0 +1,5 @@ +--- +title: Move PR IO operations out of a transaction +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/osw-ignore-diff-header-when-persisting-diff-hunk.yml b/changelogs/unreleased/osw-ignore-diff-header-when-persisting-diff-hunk.yml new file mode 100644 index 00000000000..ef66deaa0ef --- /dev/null +++ b/changelogs/unreleased/osw-ignore-diff-header-when-persisting-diff-hunk.yml @@ -0,0 +1,5 @@ +--- +title: Adjust insufficient diff hunks being persisted on NoteDiffFile +merge_request: +author: +type: fixed diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index 765fb0289a8..2820293ad5c 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -78,9 +78,12 @@ module Gitlab # Returns the raw diff content up to the given line index def diff_hunk(diff_line) - # Adding 2 because of the @@ diff header and Enum#take should consider - # an extra line, because we're passing an index. - raw_diff.each_line.take(diff_line.index + 2).join + diff_line_index = diff_line.index + # @@ (match) header is not kept if it's found in the top of the file, + # therefore we should keep an extra line on this scenario. + diff_line_index += 1 unless diff_lines.first.match? + + diff_lines.select { |line| line.index <= diff_line_index }.map(&:text).join("\n") end def old_sha diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb index 0603141e441..a1e904cfef4 100644 --- a/lib/gitlab/diff/line.rb +++ b/lib/gitlab/diff/line.rb @@ -53,6 +53,10 @@ module Gitlab %w[match new-nonewline old-nonewline].include?(type) end + def match? + type == :match + end + def discussable? !meta? end diff --git a/lib/gitlab/github_import/importer/pull_request_importer.rb b/lib/gitlab/github_import/importer/pull_request_importer.rb index 49d859f9624..b2f6cb7ad19 100644 --- a/lib/gitlab/github_import/importer/pull_request_importer.rb +++ b/lib/gitlab/github_import/importer/pull_request_importer.rb @@ -22,15 +22,22 @@ module Gitlab end def execute - if (mr_id = create_merge_request) - issuable_finder.cache_database_id(mr_id) + mr, already_exists = create_merge_request + + if mr + insert_git_data(mr, already_exists) + issuable_finder.cache_database_id(mr.id) end end # Creates the merge request and returns its ID. # # This method will return `nil` if the merge request could not be - # created. + # created, otherwise it will return an Array containing the following + # values: + # + # 1. A MergeRequest instance. + # 2. A boolean indicating if the MR already exists. def create_merge_request author_id, author_found = user_finder.author_id_for(pull_request) @@ -69,21 +76,42 @@ module Gitlab merge_request_id = GithubImport .insert_and_return_id(attributes, project.merge_requests) - merge_request = project.merge_requests.find(merge_request_id) - - # These fields are set so we can create the correct merge request - # diffs. - merge_request.source_branch_sha = pull_request.source_branch_sha - merge_request.target_branch_sha = pull_request.target_branch_sha - - merge_request.keep_around_commit - merge_request.merge_request_diffs.create - - merge_request.id + [project.merge_requests.find(merge_request_id), false] end rescue ActiveRecord::InvalidForeignKey # It's possible the project has been deleted since scheduling this # job. In this case we'll just skip creating the merge request. + [] + rescue ActiveRecord::RecordNotUnique + # It's possible we previously created the MR, but failed when updating + # the Git data. In this case we'll just continue working on the + # existing row. + [project.merge_requests.find_by(iid: pull_request.iid), true] + end + + def insert_git_data(merge_request, already_exists = false) + # These fields are set so we can create the correct merge request + # diffs. + merge_request.source_branch_sha = pull_request.source_branch_sha + merge_request.target_branch_sha = pull_request.target_branch_sha + + merge_request.keep_around_commit + + # MR diffs normally use an "after_save" hook to pull data from Git. + # All of this happens in the transaction started by calling + # create/save/etc. This in turn can lead to these transactions being + # held open for much longer than necessary. To work around this we + # first save the diff, then populate it. + diff = + if already_exists + merge_request.merge_request_diffs.take + else + merge_request.merge_request_diffs.build + end + + diff.importing = true + diff.save + diff.save_git_content end end end diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index f8877b6d1aa..4e5391295b6 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -435,4 +435,46 @@ describe ProjectsHelper do expect(helper.send(:git_user_name)).to eq('John \"A\" Doe53') end end + + describe 'show_xcode_link' do + let!(:project) { create(:project) } + let(:mac_ua) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36' } + let(:ios_ua) { 'Mozilla/5.0 (iPad; CPU OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3' } + + context 'when the repository is xcode compatible' do + before do + allow(project.repository).to receive(:xcode_project?).and_return(true) + end + + it 'returns false if the visitor is not using macos' do + allow(helper).to receive(:browser).and_return(Browser.new(ios_ua)) + + expect(helper.show_xcode_link?(project)).to eq(false) + end + + it 'returns true if the visitor is using macos' do + allow(helper).to receive(:browser).and_return(Browser.new(mac_ua)) + + expect(helper.show_xcode_link?(project)).to eq(true) + end + end + + context 'when the repository is not xcode compatible' do + before do + allow(project.repository).to receive(:xcode_project?).and_return(false) + end + + it 'returns false if the visitor is not using macos' do + allow(helper).to receive(:browser).and_return(Browser.new(ios_ua)) + + expect(helper.show_xcode_link?(project)).to eq(false) + end + + it 'returns false if the visitor is using macos' do + allow(helper).to receive(:browser).and_return(Browser.new(mac_ua)) + + expect(helper.show_xcode_link?(project)).to eq(false) + end + end + end end diff --git a/spec/javascripts/labels_select_spec.js b/spec/javascripts/labels_select_spec.js index a2b89c0aef5..386e00bfd0c 100644 --- a/spec/javascripts/labels_select_spec.js +++ b/spec/javascripts/labels_select_spec.js @@ -40,5 +40,9 @@ describe('LabelsSelect', () => { it('generated label item template has correct label styles', () => { expect($labelEl.find('span.label').attr('style')).toBe(`background-color: ${label.color}; color: ${label.text_color};`); }); + + it('generated label item has a badge class', () => { + expect($labelEl.find('span').hasClass('badge')).toEqual(true); + }); }); }); diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js index 4397b00acfa..370a296bd8f 100644 --- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js +++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js @@ -82,7 +82,7 @@ describe('DropdownValueComponent', () => { }); it('renders label element with tooltip and styles based on label details', () => { - const labelEl = vm.$el.querySelector('a span.label.color-label'); + const labelEl = vm.$el.querySelector('a span.badge.color-label'); expect(labelEl).not.toBeNull(); expect(labelEl.dataset.placement).toBe('bottom'); expect(labelEl.dataset.container).toBe('body'); diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js index c63f15e5880..c36b607a34e 100644 --- a/spec/javascripts/vue_shared/components/table_pagination_spec.js +++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js @@ -51,7 +51,7 @@ describe('Pagination component', () => { expect( component.$el.querySelector('.js-previous-button').classList.contains('disabled'), - ).toEqual(true); + ).toEqual(true); component.$el.querySelector('.js-previous-button a').click(); diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index 0588fe935c3..f0e83ccfc7a 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -470,56 +470,69 @@ describe Gitlab::Diff::File do end describe '#diff_hunk' do - let(:raw_diff) do - <<EOS -@@ -6,12 +6,18 @@ module Popen - - def popen(cmd, path=nil) - unless cmd.is_a?(Array) -- raise "System commands must be given as an array of strings" -+ raise RuntimeError, "System commands must be given as an array of strings" - end - - path ||= Dir.pwd -- vars = { "PWD" => path } -- options = { chdir: path } -+ -+ vars = { -+ "PWD" => path -+ } -+ -+ options = { -+ chdir: path -+ } - - unless File.directory?(path) - FileUtils.mkdir_p(path) -@@ -19,6 +25,7 @@ module Popen - - @cmd_output = "" - @cmd_status = 0 -+ - Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| - @cmd_output << stdout.read - @cmd_output << stderr.read -EOS - end - - it 'returns raw diff up to given line index' do - allow(diff_file).to receive(:raw_diff) { raw_diff } - diff_line = instance_double(Gitlab::Diff::Line, index: 5) - - diff_hunk = <<EOS -@@ -6,12 +6,18 @@ module Popen - - def popen(cmd, path=nil) - unless cmd.is_a?(Array) -- raise "System commands must be given as an array of strings" -+ raise RuntimeError, "System commands must be given as an array of strings" - end -EOS - - expect(diff_file.diff_hunk(diff_line)).to eq(diff_hunk) + context 'when first line is a match' do + let(:raw_diff) do + <<~EOS + --- a/files/ruby/popen.rb + +++ b/files/ruby/popen.rb + @@ -6,12 +6,18 @@ module Popen + + def popen(cmd, path=nil) + unless cmd.is_a?(Array) + - raise "System commands must be given as an array of strings" + + raise RuntimeError, "System commands must be given as an array of strings" + end + EOS + end + + it 'returns raw diff up to given line index' do + allow(diff_file).to receive(:raw_diff) { raw_diff } + diff_line = instance_double(Gitlab::Diff::Line, index: 4) + + diff_hunk = <<~EOS + @@ -6,12 +6,18 @@ module Popen + + def popen(cmd, path=nil) + unless cmd.is_a?(Array) + - raise "System commands must be given as an array of strings" + + raise RuntimeError, "System commands must be given as an array of strings" + EOS + + expect(diff_file.diff_hunk(diff_line)).to eq(diff_hunk.strip) + end + end + + context 'when first line is not a match' do + let(:raw_diff) do + <<~EOS + @@ -1,4 +1,4 @@ + -Copyright (c) 2011-2017 GitLab B.V. + +Copyright (c) 2011-2019 GitLab B.V. + + With regard to the GitLab Software: + + @@ -9,17 +9,21 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + EOS + end + + it 'returns raw diff up to given line index' do + allow(diff_file).to receive(:raw_diff) { raw_diff } + diff_line = instance_double(Gitlab::Diff::Line, index: 5) + + diff_hunk = <<~EOS + -Copyright (c) 2011-2017 GitLab B.V. + +Copyright (c) 2011-2019 GitLab B.V. + + With regard to the GitLab Software: + + @@ -9,17 +9,21 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + EOS + + expect(diff_file.diff_hunk(diff_line)).to eq(diff_hunk.strip) + end end end end diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb index d34ca0b76b8..81fe97c1e49 100644 --- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb @@ -180,12 +180,12 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach allow(importer.user_finder) .to receive(:user_id_for) - .ordered.with(issue.assignees[0]) + .with(issue.assignees[0]) .and_return(4) allow(importer.user_finder) .to receive(:user_id_for) - .ordered.with(issue.assignees[1]) + .with(issue.assignees[1]) .and_return(5) expect(Gitlab::Database) diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb index 35f3fdf8304..6686b7ce0b5 100644 --- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb @@ -40,13 +40,19 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi describe '#execute' do it 'imports the pull request' do + mr = double(:merge_request, id: 10) + expect(importer) .to receive(:create_merge_request) - .and_return(10) + .and_return([mr, false]) + + expect(importer) + .to receive(:insert_git_data) + .with(mr, false) expect_any_instance_of(Gitlab::GithubImport::IssuableFinder) .to receive(:cache_database_id) - .with(10) + .with(mr.id) importer.execute end @@ -99,18 +105,11 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi importer.create_merge_request end - it 'returns the ID of the created merge request' do - id = importer.create_merge_request - - expect(id).to be_a_kind_of(Numeric) - end - - it 'creates the merge request diffs' do - importer.create_merge_request - - mr = project.merge_requests.take + it 'returns the created merge request' do + mr, exists = importer.create_merge_request - expect(mr.merge_request_diffs.exists?).to eq(true) + expect(mr).to be_instance_of(MergeRequest) + expect(exists).to eq(false) end end @@ -217,5 +216,65 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi expect { importer.create_merge_request }.not_to raise_error end end + + context 'when the merge request already exists' do + before do + allow(importer.user_finder) + .to receive(:author_id_for) + .with(pull_request) + .and_return([user.id, true]) + + allow(importer.user_finder) + .to receive(:assignee_id_for) + .with(pull_request) + .and_return(user.id) + end + + it 'returns the existing merge request' do + mr1, exists1 = importer.create_merge_request + mr2, exists2 = importer.create_merge_request + + expect(mr2).to eq(mr1) + expect(exists1).to eq(false) + expect(exists2).to eq(true) + end + end + end + + describe '#insert_git_data' do + before do + allow(importer.milestone_finder) + .to receive(:id_for) + .with(pull_request) + .and_return(milestone.id) + + allow(importer.user_finder) + .to receive(:author_id_for) + .with(pull_request) + .and_return([user.id, true]) + + allow(importer.user_finder) + .to receive(:assignee_id_for) + .with(pull_request) + .and_return(user.id) + end + + it 'creates the merge request diffs' do + mr, exists = importer.create_merge_request + + importer.insert_git_data(mr, exists) + + expect(mr.merge_request_diffs.exists?).to eq(true) + end + + it 'creates the merge request diff commits' do + mr, exists = importer.create_merge_request + + importer.insert_git_data(mr, exists) + + diff = mr.merge_request_diffs.take + + expect(diff.merge_request_diff_commits.exists?).to eq(true) + end end end |