diff options
60 files changed, 442 insertions, 196 deletions
diff --git a/CHANGELOG b/CHANGELOG index aa8c146a6fa..a8b43dd4608 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.1.0 (unreleased) + - Include full path of source and target branch names in New Merge Request page (Stan Hu) + - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) - Add user preference to view activities as default dashboard (Stan Hu) - Add option to admin area to sign in as a specific user (Pavel Forkert) - Show CI status on all pages where commits list is rendered @@ -18,6 +20,11 @@ v 8.1.0 (unreleased) - Move CI triggers page to project settings area - Move CI project settings page to CE project settings area - Fix bug when removed file was not appearing in merge request diff + - Note the original location of a moved project when notifying users of the move + - Improve error message when merging fails + - Add support of multibyte characters in LDAP UID (Roman Petrov) + - Show additions/deletions stats on merge request diff + - Remove footer text in emails (Zeger-Jan van de Weg) - Ensure code blocks are properly highlighted after a note is updated v 8.0.3 @@ -104,6 +111,8 @@ v 8.0.0 - Webhook for issue now contains repository field (Jungkook Park) - Add ability to add custom text to the help page (Jeroen van Baarsen) - Add pg_schema to backup config + - Fix references to target project issues in Merge Requests markdown preview and textareas (Francesco Levorato) + - Redirect from incorrectly cased group or project path to correct one (Francesco Levorato) - Removed API calls from CE to CI v 7.14.3 @@ -47,7 +47,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.2.15' +gem "gitlab_git", '~> 7.2.17' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index 4386c6b9abb..6472221bc54 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -278,7 +278,7 @@ GEM mime-types (~> 1.19) gitlab_emoji (0.1.1) gemojione (~> 2.0) - gitlab_git (7.2.15) + gitlab_git (7.2.17) activesupport (~> 4.0) charlock_holmes (~> 0.6) gitlab-linguist (~> 3.0) @@ -834,7 +834,7 @@ DEPENDENCIES gitlab-flowdock-git-hook (~> 1.0.1) gitlab-linguist (~> 3.0.1) gitlab_emoji (~> 0.1) - gitlab_git (~> 7.2.15) + gitlab_git (~> 7.2.17) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.0.2) @@ -937,3 +937,6 @@ DEPENDENCIES webmock (~> 1.21.0) whenever (~> 0.8.4) wikicloth (= 0.8.1) + +BUNDLED WITH + 1.10.6 diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index 995a2f24093..3176e5a8965 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -15,11 +15,12 @@ class @MergeRequestWidget type: 'GET' url: $('.merge-request').data('url') success: (data) => - switch data.state - when 'merged' - location.reload() - else - setTimeout(merge_request_widget.mergeInProgress, 2000) + if data.state == "merged" + location.reload() + else if data.merge_error + $('.mr-widget-body').html("<h4>" + data.merge_error + "</h4>") + else + setTimeout(merge_request_widget.mergeInProgress, 2000) dataType: 'json' getMergeStatus: -> diff --git a/app/assets/stylesheets/base/variables.scss b/app/assets/stylesheets/base/variables.scss index f6bdea9a897..befd63832d5 100644 --- a/app/assets/stylesheets/base/variables.scss +++ b/app/assets/stylesheets/base/variables.scss @@ -1,5 +1,8 @@ $hover: #FFFAF1; -$gl-text-color: #54565b; +$gl-text-color: #54565B; +$gl-text-green: #4A2; +$gl-text-red: #D12F19; +$gl-text-orange: #D90; $gl-header-color: #4c4e54; $gl-link-color: #333c48; $md-text-color: #444; diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 96fb791c242..016cc015e9c 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -1,8 +1,8 @@ /** COLORS **/ .cgray { color: $gl-gray; } .clgray { color: #BBB } -.cred { color: #D12F19 } -.cgreen { color: #4a2 } +.cred { color: $gl-text-red; } +.cgreen { color: $gl-text-green; } .cdark { color: #444 } /** COMMON CLASSES **/ diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index 051ca3792c3..741ff9051a2 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -49,30 +49,33 @@ } .file-stats { + ul { + list-style: none; + margin: 0; + padding: 10px 0; + + li { + padding: 3px 0px; + } + } .new-file { a { - color: #090; - } - i { - color: #1BCF00; + color: $gl-text-green; } } .renamed-file { - i { - color: #FE9300; + a { + color: $gl-text-orange; } } .deleted-file { a { - color: #B00; - } - i { - color: #EE0000; + color: $gl-text-red; } } .edit-file{ - i{ - color: #555; + a { + color: $gl-text-color; } } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 31051785676..818aa10aefe 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -1,6 +1,6 @@ .alert_holder { margin: -16px; - + .alert-link { font-weight: normal; } @@ -31,20 +31,20 @@ margin: -$gl-padding; padding: $gl-padding; padding: 44px 0 17px 0; - + .project-identicon-holder { margin-bottom: 16px; - + .avatar, .identicon { margin: 0 auto; float: none; } - + .identicon { @include border-radius(50%); } } - + .project-home-dropdown { margin: 11px 3px 0; } @@ -86,15 +86,15 @@ top: 17px; margin-bottom: 44px; } - + .project-repo-buttons { margin-top: 12px; margin-bottom: 0px; - + .btn { @include bnt-project; @include btn-info; - + .count { display: inline-block; } @@ -105,7 +105,7 @@ .split-one { display: inline-table; margin-right: 12px; - + a { margin: -1px !important; } @@ -129,10 +129,10 @@ &.git-protocols { padding: 0; border: none; - + .input-group-btn:last-child > .btn { @include border-radius-right(0); - + border-left: 1px solid #c6cacf; margin-left: -2px !important; } @@ -141,55 +141,55 @@ } .projects-search-form { - + .input-group .form-control { height: 42px; } } .input-group-btn { - .btn { + .btn { @include bnt-project; @include btn-middle; - + &:hover { outline: none; } - + &:focus { outline: none; } - + &:active { outline: none; } } - + .active { @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12)); - + border: 1px solid #c6cacf !important; background-color: #e4e7ed !important; } - + .btn-green { @include btn-green } - + } .split-repo-buttons { display: inline-table; margin: 0 12px 0 12px; - + .btn{ @include bnt-project; @include btn-info; } - + .dropdown-toggle { margin: -5px; - } + } } #notification-form { @@ -202,7 +202,7 @@ .open > .dropdown-new.btn { @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12)); - + border: 1px solid #c6cacf !important; background-color: #e4e7ed !important; text-transform: uppercase; @@ -214,21 +214,21 @@ .dropdown-menu { @include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px); @include border-radius (0px); - + border: none; padding: 16px 0; font-size: 14px; font-weight: 100; - + li a { color: #5f697a; line-height: 30px; - + &:hover { - background-color: #3084bb !important; + background-color: #3084bb !important; } } - + .fa-fw { margin-right: 8px; } @@ -370,7 +370,7 @@ table.table.protected-branches-list tr.no-border { ul.nav-pills { display:inline-block; } - + .nav-pills li { display:inline; } @@ -378,12 +378,12 @@ table.table.protected-branches-list tr.no-border { .nav > li > a { @include btn-info; @include bnt-project; - + background-color: transparent; border: 1px solid #f7f8fa; margin-left: 12px; } - + li { display:inline; } @@ -418,27 +418,27 @@ pre.light-well { .git-empty { margin: 0 7px 0 7px; - + h5 { color: #5c5d5e; } - + .light-well { @include border-radius (2px); - + color: #5b6169; - font-size: 13px; - line-height: 1.6em; + font-size: 13px; + line-height: 1.6em; } } -.prepend-top-20 { +.project-footer { margin-top: 20px; - + .btn-remove { @include btn-middle; @include btn-remove; - + float: left !important; } } @@ -446,7 +446,7 @@ pre.light-well { /* * Projects list rendered on dashboard and user page */ - + .projects-list { @include basic-list; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9b6472a7b13..527c9da0faa 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -117,9 +117,14 @@ class ApplicationController < ActionController::Base redirect_to request.original_url.gsub(/\.git\Z/, '') and return end - @project = Project.find_with_namespace("#{namespace}/#{id}") + project_path = "#{namespace}/#{id}" + @project = Project.find_with_namespace(project_path) + if @project and can?(current_user, :read_project, @project) + if @project.path_with_namespace != project_path + redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) and return + end @project elsif current_user.nil? @project = nil diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index 8450ba31021..edf43935f3c 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -16,27 +16,6 @@ class PasswordsController < Devise::PasswordsController end end - # After a user resets their password, prompt for 2FA code if enabled instead - # of signing in automatically - # - # See http://git.io/vURrI - def update - super do |resource| - # TODO (rspeicher): In Devise master (> 3.4.1), we can set - # `Devise.sign_in_after_reset_password = false` and avoid this mess. - if resource.errors.empty? && resource.try(:two_factor_enabled?) - resource.unlock_access! if unlockable?(resource) - - # Since we are not signing this user in, we use the :updated_not_active - # message which only contains "Your password was changed successfully." - set_flash_message(:notice, :updated_not_active) if is_flashing_format? - - # Redirect to sign in so they can enter 2FA code - respond_with(resource, location: new_session_path(resource)) and return - end - end - end - def edit super reset_password_token = Devise.token_generator.digest( diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 7574842cd43..7570934e727 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -150,6 +150,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController return access_denied! unless @merge_request.can_be_merged_by?(current_user) if @merge_request.mergeable? + @merge_request.update(merge_error: nil) MergeWorker.perform_async(@merge_request.id, current_user.id, params) @status = true else diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 9d718e13b85..b896fba3704 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -170,7 +170,7 @@ module DiffHelper def commit_for_diff(diff) if diff.deleted_file - @merge_request ? @merge_request.commits.last : @commit.parent_id + @merge_request ? @merge_request.commits.last : @commit.parents.first else @commit end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index f8169b4f288..81773e7afcf 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -71,4 +71,17 @@ module MergeRequestsHelper merge_request.source_branch end end + + def format_mr_branch_names(merge_request) + source_path = merge_request.source_project_path + target_path = merge_request.target_project_path + source_branch = merge_request.source_branch + target_branch = merge_request.target_branch + + if source_path == target_path + [source_branch, target_branch] + else + ["#{source_path}:#{source_branch}", "#{target_path}:#{target_branch}"] + end + end end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index 4a6e18e6a74..caba63006da 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -50,10 +50,11 @@ module Emails subject: subject("Invitation declined")) end - def project_was_moved_email(project_id, user_id) + def project_was_moved_email(project_id, user_id, old_path_with_namespace) @current_user = @user = User.find user_id @project = Project.find project_id @target_url = namespace_project_url(@project.namespace, @project) + @old_path_with_namespace = old_path_with_namespace mail(to: @user.notification_email, subject: subject("Project was moved")) end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index db2f9654e14..50a409c3754 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -140,7 +140,7 @@ class Notify < BaseMailer # * have a 'In-Reply-To' or 'References' header that references the original 'Message-ID' # def mail_answer_thread(model, headers = {}) - headers['Message-ID'] = SecureRandom.hex + headers['Message-ID'] = "<#{SecureRandom.hex}@#{Gitlab.config.gitlab.host}>" headers['In-Reply-To'] = message_id(model) headers['References'] = message_id(model) diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index 07c87a7fe87..89b3116b9f2 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -11,11 +11,11 @@ # class AbuseReport < ActiveRecord::Base - belongs_to :reporter, class_name: "User" + belongs_to :reporter, class_name: 'User' belongs_to :user validates :reporter, presence: true validates :user, presence: true validates :message, presence: true - validates :user_id, uniqueness: { scope: :reporter_id } + validates :user_id, uniqueness: true end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index cda4fdd4982..19f957eb965 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -143,12 +143,6 @@ module Ci html ||= '' end - def trace - if project && read_attribute(:trace).present? - read_attribute(:trace).gsub(project.token, 'xxxxxx') - end - end - def started? !pending? && !canceled? && started_at end @@ -223,7 +217,7 @@ module Ci end end - def trace + def raw_trace if File.exist?(path_to_trace) File.read(path_to_trace) else @@ -232,6 +226,15 @@ module Ci end end + def trace + trace = raw_trace + if project && trace.present? + trace.gsub(project.token, 'xxxxxx') + else + trace + end + end + def trace=(trace) unless Dir.exists? dir_to_trace FileUtils.mkdir_p dir_to_trace diff --git a/app/models/ci/project.rb b/app/models/ci/project.rb index f0a8fc703b5..24f70171094 100644 --- a/app/models/ci/project.rb +++ b/app/models/ci/project.rb @@ -169,8 +169,7 @@ module Ci # using http and basic auth def repo_url_with_auth auth = "gitlab-ci-token:#{token}@" - url = http_url_to_repo + ".git" - url.sub(/^https?:\/\//) do |prefix| + http_url_to_repo.sub(/^https?:\/\//) do |prefix| prefix + auth end end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 161a16ca61c..bc8525df5a5 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -137,7 +137,9 @@ class Namespace < ActiveRecord::Base end def send_update_instructions - projects.each(&:send_move_instructions) + projects.each do |project| + project.send_move_instructions("#{path_was}/#{project.path}") + end end def kind diff --git a/app/models/project.rb b/app/models/project.rb index 953b37e3f7a..8527fa29808 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -238,10 +238,10 @@ class Project < ActiveRecord::Base return nil unless id.include?('/') id = id.split('/') - namespace = Namespace.find_by(path: id.first) + namespace = Namespace.by_path(id.first) return nil unless namespace - where(namespace_id: namespace.id).find_by(path: id.second) + where(namespace_id: namespace.id).where("LOWER(projects.path) = :path", path: id.second.downcase).first end def visibility_levels @@ -481,8 +481,8 @@ class Project < ActiveRecord::Base end end - def send_move_instructions - NotificationService.new.project_was_moved(self) + def send_move_instructions(old_path_with_namespace) + NotificationService.new.project_was_moved(self, old_path_with_namespace) end def owner @@ -624,7 +624,7 @@ class Project < ActiveRecord::Base # So we basically we mute exceptions in next actions begin gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") - send_move_instructions + send_move_instructions(old_path_with_namespace) reset_events_cache rescue # Returning false does not rollback after_* transaction but gives diff --git a/app/models/user.rb b/app/models/user.rb index 3879f3fd381..9ea7cabff15 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -129,6 +129,7 @@ class User < ActiveRecord::Base has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy + has_one :abuse_report, dependent: :destroy # diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 98a67c0bc99..fcc0f2a6a8d 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -38,6 +38,10 @@ module MergeRequests } repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options) + rescue Exception => e + merge_request.update(merge_error: "Something went wrong during merge") + Rails.logger.error(e.message) + return false end def after_merge diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index e294b23bc23..a6b22348650 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -183,12 +183,12 @@ class NotificationService mailer.group_access_granted_email(group_member.id) end - def project_was_moved(project) + def project_was_moved(project, old_path_with_namespace) recipients = project.team.members recipients = reject_muted_users(recipients, project) recipients.each do |recipient| - mailer.project_was_moved_email(project.id, recipient.id) + mailer.project_was_moved_email(project.id, recipient.id, old_path_with_namespace) end end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 550ed6897dd..c327c244f0d 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -38,7 +38,7 @@ module Projects project.save! # Notifications - project.send_move_instructions + project.send_move_instructions(old_path) # Move main repository unless gitlab_shell.mv_repository(old_path, new_path) diff --git a/app/views/ci/projects/show.html.haml b/app/views/ci/projects/show.html.haml index 73e60795ba6..888b1ea41d5 100644 --- a/app/views/ci/projects/show.html.haml +++ b/app/views/ci/projects/show.html.haml @@ -17,7 +17,7 @@ = link_to @ref, ci_project_path(@project, ref: @ref) %li.pull-right - = link_to 'View on GitLab', @project.gitlab_url, no_turbolink.merge( class: 'btn btn-sm' ) + = link_to 'Go to project', project_path(gl_project), class: 'btn btn-sm' - if @ref %p diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml index 3c58f10e759..035fe0056d3 100644 --- a/app/views/layouts/_init_auto_complete.html.haml +++ b/app/views/layouts/_init_auto_complete.html.haml @@ -1,3 +1,4 @@ +- project = @target_project || @project :javascript - GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(@project.namespace, @project, type: @noteable.class, type_id: params[:id])}" + GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}" GitLab.GfmAutoComplete.setup(); diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml index ec209c38eed..2f7d7e86f56 100644 --- a/app/views/layouts/notify.html.haml +++ b/app/views/layouts/notify.html.haml @@ -42,5 +42,3 @@ - else #{link_to "View it on GitLab", @target_url} = email_action @target_url - - if @project && !@disable_footer - You're receiving this notification because you are a member of the #{link_to_unless @target_url, @project.name_with_namespace, namespace_project_url(@project.namespace, @project)} project team. diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 78dafcd8bfa..abf73bcc709 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -3,10 +3,11 @@ - sidebar "project" unless sidebar - content_for :scripts_body_top do + - project = @target_project || @project - if current_user :javascript - window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}"; - window.markdown_preview_path = "#{markdown_preview_namespace_project_path(@project.namespace, @project)}"; + window.project_uploads_path = "#{namespace_project_uploads_path project.namespace,project}"; + window.markdown_preview_path = "#{markdown_preview_namespace_project_path(project.namespace, project)}"; - content_for :scripts_body do = render "layouts/init_auto_complete" if current_user diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml index 9db75bdb19e..34dbc60e19b 100644 --- a/app/views/notify/merged_merge_request_email.text.haml +++ b/app/views/notify/merged_merge_request_email.text.haml @@ -1,6 +1,6 @@ = "Merge Request ##{@merge_request.iid} was merged" -Merge Request Url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)} +Merge Request url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)} = merge_path_description(@merge_request, 'to') diff --git a/app/views/notify/project_was_moved_email.html.haml b/app/views/notify/project_was_moved_email.html.haml index 3cd759f1f57..87b3ff7f0b3 100644 --- a/app/views/notify/project_was_moved_email.html.haml +++ b/app/views/notify/project_was_moved_email.html.haml @@ -1,5 +1,5 @@ %p - Project was moved to another location + Project #{@old_path_with_namespace} was moved to another location %p The project is now located under = link_to namespace_project_url(@project.namespace, @project) do diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb index b3f18b35a4d..d8a23dabf49 100644 --- a/app/views/notify/project_was_moved_email.text.erb +++ b/app/views/notify/project_was_moved_email.text.erb @@ -1,4 +1,4 @@ -Project was moved to another location +Project #{@old_path_with_namespace} was moved to another location The project is now located under <%= namespace_project_url(@project.namespace, @project) %> diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index c5acafa2630..4f1965bfb39 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,14 +1,14 @@ - if params[:view] == 'parallel' - fluid_layout true +- diff_files = safe_diff_files(diffs) + .gray-content-block.second-block .inline-parallel-buttons .btn-group = inline_diff_btn = parallel_diff_btn - = render 'projects/diffs/stats', diffs: diffs - -- diff_files = safe_diff_files(diffs) + = render 'projects/diffs/stats', diff_files: diff_files - if diff_files.count < diffs.size = render 'projects/diffs/warning', diffs: diffs, shown_files_count: diff_files.count diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index c4d7f26430b..ea2a3e01277 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -2,37 +2,35 @@ .commit-stat-summary Showing = link_to '#', class: 'js-toggle-button' do - %strong #{pluralize(diffs.count, "changed file")} - - if current_controller?(:commit) - - unless @commit.has_zero_stats? - with - %strong.cgreen #{@commit.stats.additions} additions - and - %strong.cred #{@commit.stats.deletions} deletions + %strong #{pluralize(diff_files.count, "changed file")} + with + %strong.cgreen #{diff_files.sum(&:added_lines)} additions + and + %strong.cred #{diff_files.sum(&:removed_lines)} deletions .file-stats.js-toggle-content.hide %ul - - diffs.each_with_index do |diff, i| + - diff_files.each_with_index do |diff_file, i| %li - - if diff.deleted_file + - if diff_file.deleted_file %span.deleted-file %a{href: "#diff-#{i}"} %i.fa.fa-minus - = diff.old_path - - elsif diff.renamed_file + = diff_file.old_path + - elsif diff_file.renamed_file %span.renamed-file %a{href: "#diff-#{i}"} %i.fa.fa-minus - = diff.old_path + = diff_file.old_path → - = diff.new_path - - elsif diff.new_file + = diff_file.new_path + - elsif diff_file.new_file %span.new-file %a{href: "#diff-#{i}"} %i.fa.fa-plus - = diff.new_path + = diff_file.new_path - else %span.edit-file %a{href: "#diff-#{i}"} %i.fa.fa-adjust - = diff.new_path + = diff_file.new_path diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 46aeecd8733..6244d3ba0b4 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -1,10 +1,11 @@ %h3.page-title New merge request %p.slead + - source_title, target_title = format_mr_branch_names(@merge_request) From - %strong.label-branch #{@merge_request.source_project_namespace}:#{@merge_request.source_branch} + %strong.label-branch #{source_title} %span into - %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} + %strong.label-branch #{target_title} %span.pull-right = link_to 'Change branches', mr_change_branches_path(@merge_request) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 6a5fc689803..efa119edd5a 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -75,7 +75,7 @@ - if current_user - access = user_max_access_in_project(current_user, @project) - if access - .prepend-top-20 + .prepend-top-20.project-footer .gray-content-block.footer-block.center You have #{access} access to this project. - if @project.project_member_by_id(current_user) diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 37d5dba0330..11beb3e3239 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -19,14 +19,13 @@ = icon('user') Profile settings - elsif current_user - .pull-right - %span.dropdown - %a.light.dropdown-toggle.btn.btn-sm{href: '#', "data-toggle" => "dropdown"} + .report_abuse.pull-right + - if @user.abuse_report + %span#report_abuse_btn.light.btn.btn-sm.btn-close{title: 'Already reported for abuse', data: {toggle: 'tooltip', placement: 'right', container: 'body'}} + = icon('exclamation-circle') + - else + %a.light.btn.btn-sm{href: new_abuse_report_path(user_id: @user.id), title: 'Report abuse', data: {toggle: 'tooltip', placement: 'right', container: 'body'}} = icon('exclamation-circle') - %ul.dropdown-menu.dropdown-menu-right - %li - = link_to new_abuse_report_path(user_id: @user.id) do - Report abuse .username @#{@user.username} diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c7174f86014..4f7f0b6ef19 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -424,7 +424,6 @@ test: user_filter: '' group_base: 'ou=groups,dc=example,dc=com' admin_group: '' - sync_ssh_keys: false staging: <<: *base diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 2ce24592f8b..29506970af2 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -148,6 +148,10 @@ Devise.setup do |config| # When someone else invites you to GitLab this time is also used so it should be pretty long. config.reset_password_within = 2.days + # When set to false, does not sign a user in automatically after their password is + # reset. Defaults to true, so a user is signed in automatically after a reset. + config.sign_in_after_reset_password = false + # ==> Configuration for :encryptable # Allow you to use another encryption algorithm besides bcrypt (default). You can use # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, diff --git a/db/migrate/20150930001110_merge_request_error_field.rb b/db/migrate/20150930001110_merge_request_error_field.rb new file mode 100644 index 00000000000..c2ee498ef3f --- /dev/null +++ b/db/migrate/20150930001110_merge_request_error_field.rb @@ -0,0 +1,5 @@ +class MergeRequestErrorField < ActiveRecord::Migration + def up + add_column :merge_requests, :merge_error, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 4ce6cee86e5..72609da93f1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -453,6 +453,7 @@ ActiveRecord::Schema.define(version: 20150930095736) do t.integer "position", default: 0 t.datetime "locked_at" t.integer "updated_by_id" + t.string "merge_error" end add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md index 56bf7a14182..46ce0fe98c0 100644 --- a/doc/migrate_ci_to_ce/README.md +++ b/doc/migrate_ci_to_ce/README.md @@ -36,6 +36,11 @@ mv /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds.$(date +%s) and run `sudo gitlab-ctl reconfigure`. +#### 0. Updating Omnibus from versions prior to 7.13 + +If you are updating from older versions you should first update to 7.14 and then to 8.0. +Otherwise it's pretty likely that you will encounter problems described in the [Troubleshooting](#troubleshooting). + #### 1. Verify that backups work Make sure that the backup script on both servers can connect to the database. @@ -43,6 +48,7 @@ Make sure that the backup script on both servers can connect to the database. ``` # On your CI server: # Omnibus +sudo chown gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds sudo gitlab-ci-rake backup:create # Source @@ -319,3 +325,102 @@ You should also make sure that you can: If something went wrong and you need to restore a backup, consult the [Backup restoration](../raketasks/backup_restore.md) guide. + +### Troubleshooting + +#### show:secrets problem (Omnibus-only) +If you see errors like this: +``` +Missing `secret_key_base` or `db_key_base` for 'production' environment. The secrets will be generated and stored in `config/secrets.yml` +rake aborted! +Errno::EACCES: Permission denied @ rb_sysopen - config/secrets.yml +``` + +This can happen if you are updating from versions prior to 7.13 straight to 8.0. +The fix for this is to update to Omnibus 7.14 first and then update it to 8.0. + +#### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds +To fix that issue you have to change builds/ folder permission before doing final backup: +``` +chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds +``` + +#### Problems when importing CI database to GitLab +If you were migrating CI database from MySQL to PostgreSQL manually you can see errros during import about missing sequences: +``` +ALTER SEQUENCE +ERROR: relation "ci_builds_id_seq" does not exist +ERROR: relation "ci_commits_id_seq" does not exist +ERROR: relation "ci_events_id_seq" does not exist +ERROR: relation "ci_jobs_id_seq" does not exist +ERROR: relation "ci_projects_id_seq" does not exist +ERROR: relation "ci_runner_projects_id_seq" does not exist +ERROR: relation "ci_runners_id_seq" does not exist +ERROR: relation "ci_services_id_seq" does not exist +ERROR: relation "ci_taggings_id_seq" does not exist +ERROR: relation "ci_tags_id_seq" does not exist +CREATE TABLE +``` + +To fix that you need to apply this SQL statement before doing final backup: +``` +# Omnibus +gitlab-ci-rails dbconsole <<EOF +-- ALTER TABLES - DROP DEFAULTS +ALTER TABLE ONLY ci_application_settings ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_builds ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_commits ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_events ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_jobs ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_projects ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_runners ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_services ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_taggings ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_tags ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_triggers ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_variables ALTER COLUMN id DROP DEFAULT; +ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id DROP DEFAULT; + +-- ALTER SEQUENCES +ALTER SEQUENCE ci_application_settings_id_seq OWNED BY ci_application_settings.id; +ALTER SEQUENCE ci_builds_id_seq OWNED BY ci_builds.id; +ALTER SEQUENCE ci_commits_id_seq OWNED BY ci_commits.id; +ALTER SEQUENCE ci_events_id_seq OWNED BY ci_events.id; +ALTER SEQUENCE ci_jobs_id_seq OWNED BY ci_jobs.id; +ALTER SEQUENCE ci_projects_id_seq OWNED BY ci_projects.id; +ALTER SEQUENCE ci_runner_projects_id_seq OWNED BY ci_runner_projects.id; +ALTER SEQUENCE ci_runners_id_seq OWNED BY ci_runners.id; +ALTER SEQUENCE ci_services_id_seq OWNED BY ci_services.id; +ALTER SEQUENCE ci_taggings_id_seq OWNED BY ci_taggings.id; +ALTER SEQUENCE ci_tags_id_seq OWNED BY ci_tags.id; +ALTER SEQUENCE ci_trigger_requests_id_seq OWNED BY ci_trigger_requests.id; +ALTER SEQUENCE ci_triggers_id_seq OWNED BY ci_triggers.id; +ALTER SEQUENCE ci_variables_id_seq OWNED BY ci_variables.id; +ALTER SEQUENCE ci_web_hooks_id_seq OWNED BY ci_web_hooks.id; + +-- ALTER TABLES - RE-APPLY DEFAULTS +ALTER TABLE ONLY ci_application_settings ALTER COLUMN id SET DEFAULT nextval('ci_application_settings_id_seq'::regclass); +ALTER TABLE ONLY ci_builds ALTER COLUMN id SET DEFAULT nextval('ci_builds_id_seq'::regclass); +ALTER TABLE ONLY ci_commits ALTER COLUMN id SET DEFAULT nextval('ci_commits_id_seq'::regclass); +ALTER TABLE ONLY ci_events ALTER COLUMN id SET DEFAULT nextval('ci_events_id_seq'::regclass); +ALTER TABLE ONLY ci_jobs ALTER COLUMN id SET DEFAULT nextval('ci_jobs_id_seq'::regclass); +ALTER TABLE ONLY ci_projects ALTER COLUMN id SET DEFAULT nextval('ci_projects_id_seq'::regclass); +ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id SET DEFAULT nextval('ci_runner_projects_id_seq'::regclass); +ALTER TABLE ONLY ci_runners ALTER COLUMN id SET DEFAULT nextval('ci_runners_id_seq'::regclass); +ALTER TABLE ONLY ci_services ALTER COLUMN id SET DEFAULT nextval('ci_services_id_seq'::regclass); +ALTER TABLE ONLY ci_taggings ALTER COLUMN id SET DEFAULT nextval('ci_taggings_id_seq'::regclass); +ALTER TABLE ONLY ci_tags ALTER COLUMN id SET DEFAULT nextval('ci_tags_id_seq'::regclass); +ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_trigger_requests_id_seq'::regclass); +ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass); +ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass); +ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id SET DEFAULT nextval('ci_web_hooks_id_seq'::regclass); +EOF + +# Source +cd /home/gitlab_ci/gitlab-ci +sudo -u gitlab_ci -H bundle exec rails dbconsole production <<EOF +... COPY SQL STATEMENTS FROM ABOVE ... +EOF +``` diff --git a/doc/update/7.14-to-8.0.md b/doc/update/7.14-to-8.0.md index 552216be932..0e65c32098c 100644 --- a/doc/update/7.14-to-8.0.md +++ b/doc/update/7.14-to-8.0.md @@ -101,7 +101,7 @@ EOF ``` If your Git repositories are in a directory other than `/home/git/repositories`, -you need to tell `gitlab-git-http-server` about it via `/etc/gitlab/default`. +you need to tell `gitlab-git-http-server` about it via `/etc/default/gitlab`. See `lib/support/init.d/gitlab.default.example` for the options. ### 6. Copy secrets diff --git a/features/abuse_report.feature b/features/abuse_report.feature index 3e1cb455b77..212972a762a 100644 --- a/features/abuse_report.feature +++ b/features/abuse_report.feature @@ -8,3 +8,10 @@ Feature: Abuse reports And I click "Report abuse" button When I fill and submit abuse form Then I should see success message + + Scenario: Report abuse available only once + Given I visit "Mike" user page + And I click "Report abuse" button + When I fill and submit abuse form + And I visit "Mike" user page + Then I should see a red "Report abuse" button diff --git a/features/steps/abuse_reports.rb b/features/steps/abuse_reports.rb index 8f9ddb2899f..56652ff6f05 100644 --- a/features/steps/abuse_reports.rb +++ b/features/steps/abuse_reports.rb @@ -22,6 +22,10 @@ class Spinach::Features::AbuseReports < Spinach::FeatureSteps user_mike end + step 'I should see a red "Report abuse" button' do + expect(find(:css, '.report_abuse')).to have_selector(:css, 'span.btn-close') + end + def user_mike @user_mike ||= create(:user, name: 'Mike') end diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index 4daf65331e8..142058aa69d 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -44,6 +44,14 @@ module Gitlab diff.old_path end end + + def added_lines + diff_lines.select(&:added?).size + end + + def removed_lines + diff_lines.select(&:removed?).size + end end end end diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb index 8ac1b15e88a..0072194606e 100644 --- a/lib/gitlab/diff/line.rb +++ b/lib/gitlab/diff/line.rb @@ -7,6 +7,14 @@ module Gitlab @text, @type, @index = text, type, index @old_pos, @new_pos = old_pos, new_pos end + + def added? + type == 'new' + end + + def removed? + type == 'old' + end end end end diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index cb66fd500fe..1ea7751e27d 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -14,7 +14,7 @@ module Gitlab # LDAP distinguished name is case-insensitive identity = ::Identity. where(provider: provider). - where('lower(extern_uid) = ?', uid.downcase).last + where('lower(extern_uid) = ?', uid.mb_chars.downcase.to_s).last identity && identity.user end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 871b9219ca9..76d56bc989d 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -8,28 +8,34 @@ describe Projects::IssuesController do before do sign_in(user) project.team << [user, :developer] - controller.instance_variable_set(:@project, project) end describe "GET #index" do it "returns index" do - get :index, namespace_id: project.namespace.id, project_id: project.id + get :index, namespace_id: project.namespace.path, project_id: project.path expect(response.status).to eq(200) end + it "return 301 if request path doesn't match project path" do + get :index, namespace_id: project.namespace.path, project_id: project.path.upcase + + expect(response).to redirect_to(namespace_project_issues_path(project.namespace, project)) + end + it "returns 404 when issues are disabled" do project.issues_enabled = false project.save - get :index, namespace_id: project.namespace.id, project_id: project.id + get :index, namespace_id: project.namespace.path, project_id: project.path expect(response.status).to eq(404) end it "returns 404 when external issue tracker is enabled" do + controller.instance_variable_set(:@project, project) allow(project).to receive(:default_issues_tracker?).and_return(false) - get :index, namespace_id: project.namespace.id, project_id: project.id + get :index, namespace_id: project.namespace.path, project_id: project.path expect(response.status).to eq(404) end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 29233e9fae6..21beaf37fce 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -21,6 +21,20 @@ describe ProjectsController do expect(response.body).to include("content='#{content}'") end end + + context "when requested with case sensitive namespace and project path" do + it "redirects to the normalized path for case mismatch" do + get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase + + expect(response).to redirect_to("/#{public_project.path_with_namespace}") + end + + it "loads the page if normalized path matches request path" do + get :show, namespace_id: public_project.namespace.path, id: public_project.path + + expect(response.status).to eq(200) + end + end end describe "POST #toggle_star" do diff --git a/spec/features/password_reset_spec.rb b/spec/features/password_reset_spec.rb index 2b6311e4fd7..abf66f2356d 100644 --- a/spec/features/password_reset_spec.rb +++ b/spec/features/password_reset_spec.rb @@ -1,27 +1,6 @@ require 'spec_helper' feature 'Password reset', feature: true do - def forgot_password - click_on 'Forgot your password?' - fill_in 'Email', with: user.email - click_button 'Reset password' - user.reload - end - - def get_reset_token - mail = ActionMailer::Base.deliveries.last - body = mail.body.encoded - body.scan(/reset_password_token=(.+)\"/).flatten.first - end - - def reset_password(password = 'password') - visit edit_user_password_path(reset_password_token: get_reset_token) - - fill_in 'New password', with: password - fill_in 'Confirm new password', with: password - click_button 'Change your password' - end - describe 'with two-factor authentication' do let(:user) { create(:user, :two_factor) } @@ -40,14 +19,35 @@ feature 'Password reset', feature: true do describe 'without two-factor authentication' do let(:user) { create(:user) } - it 'automatically logs in after password reset' do + it 'requires login after password reset' do visit root_path forgot_password reset_password - expect(current_path).to eq root_path - expect(page).to have_content("Your password was changed successfully. You are now signed in.") + expect(page).to have_content("Your password was changed successfully.") + expect(current_path).to eq new_user_session_path end end + + def forgot_password + click_on 'Forgot your password?' + fill_in 'Email', with: user.email + click_button 'Reset password' + user.reload + end + + def get_reset_token + mail = ActionMailer::Base.deliveries.last + body = mail.body.encoded + body.scan(/reset_password_token=(.+)\"/).flatten.first + end + + def reset_password(password = 'password') + visit edit_user_password_path(reset_password_token: get_reset_token) + + fill_in 'New password', with: password + fill_in 'Confirm new password', with: password + click_button 'Change your password' + end end diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index efcb8a31abe..c1248162031 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' feature 'Users', feature: true do + let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') } + scenario 'GET /users/sign_in creates a new user account' do visit new_user_session_path fill_in 'user_name', with: 'Name Surname' @@ -11,7 +13,6 @@ feature 'Users', feature: true do end scenario 'Successful user signin invalidates password reset token' do - user = create(:user) expect(user.reset_password_token).to be_nil visit new_user_password_path @@ -28,7 +29,6 @@ feature 'Users', feature: true do expect(user.reset_password_token).to be_nil end - let!(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') } scenario 'Should show one error if email is already taken' do visit new_user_session_path fill_in 'user_name', with: 'Another user name' diff --git a/spec/helpers/merge_requests_helper.rb b/spec/helpers/merge_requests_helper.rb deleted file mode 100644 index 5262d644048..00000000000 --- a/spec/helpers/merge_requests_helper.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe MergeRequestsHelper do - describe :issues_sentence do - subject { issues_sentence(issues) } - let(:issues) do - [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)] - end - - it { is_expected.to eq('#1, #2, and #3') } - end -end diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb new file mode 100644 index 00000000000..0ef1efb8bce --- /dev/null +++ b/spec/helpers/merge_requests_helper_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe MergeRequestsHelper do + describe "#issues_sentence" do + subject { issues_sentence(issues) } + let(:issues) do + [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)] + end + + it { is_expected.to eq('#1, #2, and #3') } + end + + describe "#format_mr_branch_names" do + describe "within the same project" do + let(:merge_request) { create(:merge_request) } + subject { format_mr_branch_names(merge_request) } + + it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) } + end + + describe "within different projects" do + let(:project) { create(:project) } + let(:fork_project) { create(:project, forked_from_project: project) } + let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) } + subject { format_mr_branch_names(merge_request) } + let(:source_title) { "#{fork_project.path_with_namespace}:#{merge_request.source_branch}" } + let(:target_title) { "#{project.path_with_namespace}:#{merge_request.target_branch}" } + + it { is_expected.to eq([source_title, target_title]) } + end + end +end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 2c97a521d96..cb67ec95d57 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -52,6 +52,7 @@ describe Notify do end it 'has headers that reference an existing thread' do + is_expected.to have_header 'Message-ID', /<(.*)@#{Gitlab.config.gitlab.host}>/ is_expected.to have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ is_expected.to have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ @@ -399,7 +400,7 @@ describe Notify do describe 'project was moved' do let(:project) { create(:project) } let(:user) { create(:user) } - subject { Notify.project_was_moved_email(project.id, user.id) } + subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") } it_behaves_like 'an email sent from GitLab' diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index 635a6e2518c..d45319b25d4 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -16,4 +16,16 @@ RSpec.describe AbuseReport, type: :model do subject { create(:abuse_report) } it { expect(subject).to be_valid } + + describe 'associations' do + it { is_expected.to belong_to(:reporter).class_name('User') } + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:reporter) } + it { is_expected.to validate_presence_of(:user) } + it { is_expected.to validate_presence_of(:message) } + it { is_expected.to validate_uniqueness_of(:user_id) } + end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 82623bd8190..ca070a14975 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -178,6 +178,17 @@ describe Ci::Build do it { is_expected.to include(text) } it { expect(subject.length).to be >= text.length } end + + context 'if build.trace hides token' do + let(:token) { 'my_secret_token' } + + before do + build.project.update_attributes(token: token) + build.update_attributes(trace: token) + end + + it { is_expected.to_not include(token) } + end end describe :timeout do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index ba8897b95d9..fe7bb2cc13f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -220,6 +220,7 @@ describe Project do end it { expect(Project.find_with_namespace('gitlab/gitlabhq')).to eq(@project) } + it { expect(Project.find_with_namespace('GitLab/GitlabHQ')).to eq(@project) } it { expect(Project.find_with_namespace('gitlab-ci')).to be_nil } end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 480950859a2..b7b525bfca2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -85,6 +85,7 @@ describe User do it { is_expected.to have_many(:merge_requests).dependent(:destroy) } it { is_expected.to have_many(:assigned_merge_requests).dependent(:destroy) } it { is_expected.to have_many(:identities).dependent(:destroy) } + it { is_expected.to have_one(:abuse_report) } end describe 'validations' do diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 7b564d34d7b..7483f51de03 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -35,5 +35,19 @@ describe MergeRequests::MergeService do expect(note.note).to include 'Status changed to merged' end end + + context "error handling" do + let(:service) { MergeRequests::MergeService.new(project, user, {}) } + + it 'saves error if there is an exception' do + allow(service).to receive(:repository).and_raise("error") + + allow(service).to receive(:execute_hooks) + + service.execute(merge_request, 'Awesome message') + + expect(merge_request.merge_error).to eq("Something went wrong during merge") + end + end end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 8865335d0d1..520140917aa 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -427,15 +427,15 @@ describe NotificationService do should_email(@u_watcher.id) should_email(@u_participating.id) should_not_email(@u_disabled.id) - notification.project_was_moved(project) + notification.project_was_moved(project, "gitlab/gitlab") end def should_email(user_id) - expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id) + expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab") end def should_not_email(user_id) - expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id) + expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab") end end end |