Commit ced0b445 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'master' into 'backstage/gb/use-persisted-stages-to-improve-pipelines-table'

# Conflicts:
#   db/schema.rb
parents da246582 1fc6935e
...@@ -349,7 +349,7 @@ on those issues. Please select someone with relevant experience from the ...@@ -349,7 +349,7 @@ on those issues. Please select someone with relevant experience from the
[GitLab team][team]. If there is nobody mentioned with that expertise look in [GitLab team][team]. If there is nobody mentioned with that expertise look in
the commit history for the affected files to find someone. the commit history for the affected files to find someone.
[described in our handbook]: https://about.gitlab.com/handbook/engineering/issues/issue-triage-policies/ [described in our handbook]: https://about.gitlab.com/handbook/engineering/issue-triage/
[issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815 [issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815
### Feature proposals ### Feature proposals
......
...@@ -168,6 +168,7 @@ the stable branch are: ...@@ -168,6 +168,7 @@ the stable branch are:
* Fixes for [regressions](#regressions) * Fixes for [regressions](#regressions)
* Fixes for security issues * Fixes for security issues
* Fixes or improvements to automated QA scenarios
* New or updated translations (as long as they do not touch application code) * New or updated translations (as long as they do not touch application code)
During the feature freeze all merge requests that are meant to go into the During the feature freeze all merge requests that are meant to go into the
......
...@@ -126,5 +126,5 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on ...@@ -126,5 +126,5 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
## Is it awesome? ## Is it awesome?
Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua.
[These people](https://twitter.com/gitlab/likes) seem to like it. [These people](https://twitter.com/gitlab/likes) seem to like it.
...@@ -265,10 +265,10 @@ export default { ...@@ -265,10 +265,10 @@ export default {
/> />
<section <section
v-if="mr.maintainerEditAllowed" v-if="mr.allowCollaboration"
class="mr-info-list mr-links" class="mr-info-list mr-links"
> >
{{ s__("mrWidget|Allows edits from maintainers") }} {{ s__("mrWidget|Allows commits from members who can merge to the target branch") }}
</section> </section>
<mr-widget-related-links <mr-widget-related-links
......
...@@ -83,7 +83,7 @@ export default class MergeRequestStore { ...@@ -83,7 +83,7 @@ export default class MergeRequestStore {
this.canBeMerged = data.can_be_merged || false; this.canBeMerged = data.can_be_merged || false;
this.isMergeAllowed = data.mergeable || false; this.isMergeAllowed = data.mergeable || false;
this.mergeOngoing = data.merge_ongoing; this.mergeOngoing = data.merge_ongoing;
this.maintainerEditAllowed = data.allow_maintainer_to_push; this.allowCollaboration = data.allow_collaboration;
// Cherry-pick and Revert actions related // Cherry-pick and Revert actions related
this.canCherryPickInCurrentMR = currentUser.can_cherry_pick_on_current_merge_request || false; this.canCherryPickInCurrentMR = currentUser.can_cherry_pick_on_current_merge_request || false;
......
...@@ -124,15 +124,18 @@ ...@@ -124,15 +124,18 @@
break; break;
} }
}, },
hideOnSmallScreen(item) {
return !item.first && !item.last && !item.next && !item.prev && !item.active;
},
}, },
}; };
</script> </script>
<template> <template>
<div <div
v-if="showPagination" v-if="showPagination"
class="gl-pagination" class="gl-pagination prepend-top-default"
> >
<ul class="pagination clearfix"> <ul class="pagination justify-content-center">
<li <li
v-for="(item, index) in getItems" v-for="(item, index) in getItems"
:key="index" :key="index"
...@@ -142,12 +145,17 @@ ...@@ -142,12 +145,17 @@
'js-next-button': item.next, 'js-next-button': item.next,
'js-last-button': item.last, 'js-last-button': item.last,
'js-first-button': item.first, 'js-first-button': item.first,
'd-none d-md-block': hideOnSmallScreen(item),
separator: item.separator, separator: item.separator,
active: item.active, 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 }} {{ item.title }}
</a> </a>
</li> </li>
......
...@@ -24,6 +24,11 @@ html { ...@@ -24,6 +24,11 @@ html {
font-size: 14px; font-size: 14px;
} }
legend {
border-bottom: 1px solid $border-color;
margin-bottom: 20px;
}
button, button,
html [type="button"], html [type="button"],
[type="reset"], [type="reset"],
...@@ -183,7 +188,9 @@ table { ...@@ -183,7 +188,9 @@ table {
.nav-tabs { .nav-tabs {
.nav-link { .nav-link {
border: 0; border-top: 0;
border-left: 0;
border-right: 0;
} }
.nav-item { .nav-item {
......
...@@ -115,9 +115,3 @@ body { ...@@ -115,9 +115,3 @@ body {
.with-performance-bar .layout-page { .with-performance-bar .layout-page {
margin-top: $header-height + $performance-bar-height; margin-top: $header-height + $performance-bar-height;
} }
.vertical-center {
min-height: 100vh;
display: flex;
align-items: center;
}
.gl-pagination { .gl-pagination {
text-align: center; a {
border-top: 1px solid $border-color; color: inherit;
margin: 0; text-decoration: none;
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;
}
}
} }
} }
...@@ -485,6 +485,15 @@ ...@@ -485,6 +485,15 @@
.sidebar-collapsed-user { .sidebar-collapsed-user {
padding-bottom: 0; padding-bottom: 0;
margin-bottom: 10px; margin-bottom: 10px;
.author_link {
padding-left: 0;
.avatar {
position: static;
margin: 0;
}
}
} }
.issuable-header-btn { .issuable-header-btn {
......
...@@ -130,12 +130,17 @@ class ApplicationController < ActionController::Base ...@@ -130,12 +130,17 @@ class ApplicationController < ActionController::Base
end end
def access_denied!(message = nil) def access_denied!(message = nil)
# If we display a custom access denied message to the user, we don't want to
# hide existence of the resource, rather tell them they cannot access it using
# the provided message
status = message.present? ? :forbidden : :not_found
respond_to do |format| respond_to do |format|
format.any { head :not_found } format.any { head status }
format.html do format.html do
render "errors/access_denied", render "errors/access_denied",
layout: "errors", layout: "errors",
status: 404, status: status,
locals: { message: message } locals: { message: message }
end end
end end
......
...@@ -15,7 +15,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont ...@@ -15,7 +15,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
def merge_request_params_attributes def merge_request_params_attributes
[ [
:allow_maintainer_to_push, :allow_collaboration,
:assignee_id, :assignee_id,
:description, :description,
:force_remove_source_branch, :force_remove_source_branch,
......
...@@ -13,6 +13,10 @@ module Users ...@@ -13,6 +13,10 @@ module Users
def index def index
@redirect = redirect_path @redirect = redirect_path
if @term.accepted_by_user?(current_user)
flash.now[:notice] = "You have already accepted the Terms of Service as #{current_user.to_reference}"
end
end end
def accept def accept
......
...@@ -126,8 +126,8 @@ module MergeRequestsHelper ...@@ -126,8 +126,8 @@ module MergeRequestsHelper
link_to(url[merge_request.project, merge_request], data: data_attrs, &block) link_to(url[merge_request.project, merge_request], data: data_attrs, &block)
end end
def allow_maintainer_push_unavailable_reason(merge_request) def allow_collaboration_unavailable_reason(merge_request)
return if merge_request.can_allow_maintainer_to_push?(current_user) return if merge_request.can_allow_collaboration?(current_user)
minimum_visibility = [merge_request.target_project.visibility_level, minimum_visibility = [merge_request.target_project.visibility_level,
merge_request.source_project.visibility_level].min merge_request.source_project.visibility_level].min
......
...@@ -412,7 +412,10 @@ module ProjectsHelper ...@@ -412,7 +412,10 @@ module ProjectsHelper
exports_path = File.join(Settings.shared['path'], 'tmp/project_exports') exports_path = File.join(Settings.shared['path'], 'tmp/project_exports')
filtered_message = message.strip.gsub(exports_path, "[REPO EXPORT PATH]") filtered_message = message.strip.gsub(exports_path, "[REPO EXPORT PATH]")
disk_path = Gitlab.config.repositories.storages[project.repository_storage].legacy_disk_path disk_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab.config.repositories.storages[project.repository_storage].legacy_disk_path
end
filtered_message.gsub(disk_path.chomp('/'), "[REPOS PATH]") filtered_message.gsub(disk_path.chomp('/'), "[REPOS PATH]")
end end
......
class ApplicationSetting class ApplicationSetting
class Term < ActiveRecord::Base class Term < ActiveRecord::Base
include CacheMarkdownField include CacheMarkdownField
has_many :term_agreements
validates :terms, presence: true validates :terms, presence: true
...@@ -9,5 +10,10 @@ class ApplicationSetting ...@@ -9,5 +10,10 @@ class ApplicationSetting
def self.latest def self.latest
order(:id).last order(:id).last
end end
def accepted_by_user?(user)
user.accepted_term_id == id ||
term_agreements.accepted.where(user: user).exists?
end
end end
end end
...@@ -219,10 +219,8 @@ module Ci ...@@ -219,10 +219,8 @@ module Ci
cache_attributes(values) cache_attributes(values)
if persist_cached_data? # We save data without validation, it will always change due to `contacted_at`
self.assign_attributes(values) self.update_columns(values) if persist_cached_data?
self.save if self.changed?
end
end end
def pick_build!(build) def pick_build!(build)
......
...@@ -4,11 +4,14 @@ module Avatarable ...@@ -4,11 +4,14 @@ module Avatarable
included do included do
prepend ShadowMethods prepend ShadowMethods
include ObjectStorage::BackgroundMove include ObjectStorage::BackgroundMove
include Gitlab::Utils::StrongMemoize
validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i } validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
mount_uploader :avatar, AvatarUploader mount_uploader :avatar, AvatarUploader
after_initialize :add_avatar_to_batch
end end
module ShadowMethods module ShadowMethods
...@@ -18,6 +21,17 @@ module Avatarable ...@@ -18,6 +21,17 @@ module Avatarable
avatar_path(only_path: args.fetch(:only_path, true)) || super avatar_path(only_path: args.fetch(:only_path, true)) || super
end end
def retrieve_upload(identifier, paths)
upload = retrieve_upload_from_batch(identifier)
# This fallback is needed when deleting an upload, because we may have
# already been removed from the DB. We have to check an explicit `#nil?`
# because it's a BatchLoader instance.
upload = super if upload.nil?
upload
end
end end
def avatar_type def avatar_type
...@@ -52,4 +66,37 @@ module Avatarable ...@@ -52,4 +66,37 @@ module Avatarable
url_base + avatar.local_url url_base + avatar.local_url
end end
# Path that is persisted in the tracking Upload model. Used to fetch the
# upload from the model.
def upload_paths(identifier)
avatar_mounter.blank_uploader.store_dirs.map { |store, path| File.join(path, identifier) }
end
private
def retrieve_upload_from_batch(identifier)
BatchLoader.for(identifier: identifier, model: self).batch(key: self.class) do |upload_params, loader, args|
model_class = args[:key]
paths = upload_params.flat_map do |params|
params[:model].upload_paths(params[:identifier])
end
Upload.where(uploader: AvatarUploader, path: paths).find_each do |upload|
model = model_class.instantiate('id' => upload.model_id)
loader.call({ model: model, identifier: File.basename(upload.path) }, upload)
end
end
end
def add_avatar_to_batch
return unless avatar_mounter
avatar_mounter.read_identifiers.each { |identifier| retrieve_upload_from_batch(identifier) }
end
def avatar_mounter
strong_memoize(:avatar_mounter) { _mounter(:avatar) }
end
end end
...@@ -36,4 +36,8 @@ module WithUploads ...@@ -36,4 +36,8 @@ module WithUploads
upload.destroy upload.destroy
end end
end end
def retrieve_upload(_identifier, paths)
uploads.find_by(path: paths)
end
end end
...@@ -1125,21 +1125,21 @@ class MergeRequest < ActiveRecord::Base ...@@ -1125,21 +1125,21 @@ class MergeRequest < ActiveRecord::Base
project.merge_requests.merged.where(author_id: author_id).empty? project.merge_requests.merged.where(author_id: author_id).empty?
end end
def allow_maintainer_to_push def allow_collaboration
maintainer_push_possible? && super collaborative_push_possible? && super
end end
alias_method :allow_maintainer_to_push?, :allow_maintainer_to_push alias_method :allow_collaboration?, :allow_collaboration
def maintainer_push_possible? def collaborative_push_possible?
source_project.present? && for_fork? && source_project.present? && for_fork? &&
target_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE && target_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE &&
source_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE && source_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE &&
!ProtectedBranch.protected?(source_project, source_branch) !ProtectedBranch.protected?(source_project, source_branch)
end end
def can_allow_maintainer_to_push?(user) def can_allow_collaboration?(user)
maintainer_push_possible? && collaborative_push_possible? &&
Ability.allowed?(user, :push_code, source_project) Ability.allowed?(user, :push_code, source_project)
end end
......
...@@ -435,6 +435,10 @@ class Note < ActiveRecord::Base ...@@ -435,6 +435,10 @@ class Note < ActiveRecord::Base
super.merge(noteable: noteable) super.merge(noteable: noteable)
end end
def retrieve_upload(_identifier, paths)
Upload.find_by(model: self, path: paths)
end
private private
def keep_around_commit def keep_around_commit
......
class PersonalSnippet < Snippet class PersonalSnippet < Snippet
include WithUploads
end end
...@@ -1975,18 +1975,18 @@ class Project < ActiveRecord::Base ...@@ -1975,18 +1975,18 @@ class Project < ActiveRecord::Base
.limit(1) .limit(1)
.select(1) .select(1)
source_of_merge_requests.opened source_of_merge_requests.opened
.where(allow_maintainer_to_push: true) .where(allow_collaboration: true)
.where('EXISTS (?)', developer_access_exists) .where('EXISTS (?)', developer_access_exists)
end end
def branch_allows_maintainer_push?(user, branch_name) def branch_allows_collaboration?(user, branch_name)
return false unless user return false unless user
cache_key = "user:#{user.id}:#{branch_name}:branch_allows_push" cache_key = "user:#{user.id}:#{branch_name}:branch_allows_push"
memoized_results = strong_memoize(:branch_allows_maintainer_push) do memoized_results = strong_memoize(:branch_allows_collaboration) do
Hash.new do |result, cache_key| Hash.new do |result, cache_key|
result[cache_key] = fetch_branch_allows_maintainer_push?(user, branch_name) result[cache_key] = fetch_branch_allows_collaboration?(user, branch_name)
end end
end end
...@@ -2128,18 +2128,18 @@ class Project < ActiveRecord::Base ...@@ -2128,18 +2128,18 @@ class Project < ActiveRecord::Base
raise ex raise ex
end end
def fetch_branch_allows_maintainer_push?(user, branch_name) def fetch_branch_allows_collaboration?(user, branch_name)
check_access = -> do check_access = -> do
next false if empty_repo? next false if empty_repo?
merge_request = source_of_merge_requests.opened merge_request = source_of_merge_requests.opened
.where(allow_maintainer_to_push: true) .where(allow_collaboration: true)
.find_by(source_branch: branch_name) .find_by(source_branch: branch_name)
merge_request&.can_be_merged_by?(user) merge_request&.can_be_merged_by?(user)
end end
if RequestStore.active? if RequestStore.active?
RequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_maintainer_push") do RequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
check_access.call check_access.call
end end
else else
......
...@@ -2,5 +2,7 @@ class TermAgreement < ActiveRecord::Base ...@@ -2,5 +2,7 @@ class TermAgreement < ActiveRecord::Base
belongs_to :term, class_name: 'ApplicationSetting::Term' belongs_to :term, class_name: 'ApplicationSetting::Term'
belongs_to :user belongs_to :user
scope :accepted, -> { where(accepted: true) }
validates :user, :term, presence: true validates :user, :term, presence: true
end end
...@@ -14,8 +14,8 @@ module Ci ...@@ -14,8 +14,8 @@ module Ci
@subject.triggered_by?(@user) @subject.triggered_by?(@user)
end end
condition(:branch_allows_maintainer_push) do condition(:branch_allows_collaboration) do
@subject.project.branch_allows_maintainer_push?(@user, @subject.ref) @subject.project.branch_allows_collaboration?(@user, @subject.ref)
end end
rule { protected_ref }.policy do rule { protected_ref }.policy do
...@@ -25,7 +25,7 @@ module Ci ...@@ -25,7 +25,7 @@ module Ci
rule { can?(:admin_build) | (can?(:update_build) & owner_of_job) }.enable :erase_build rule { can?(:admin_build) | (can?(:update_build) & owner_of_job) }.enable :erase_build
rule { can?(:public_access) & branch_allows_maintainer_push }.policy do rule { can?(:public_access) & branch_allows_collaboration }.policy do
enable :update_build enable :update_build
enable :update_commit_status enable :update_commit_status
end end
......
...@@ -4,13 +4,13 @@ module Ci ...@@ -4,13 +4,13 @@ module Ci
condition(:protected_ref) { ref_protected?(@user, @subject.project, @subject.tag?, @subject.ref) } condition(:protected_ref) { ref_protected?(@user, @subject.project, @subject.tag?, @subject.ref) }
condition(:branch_allows_maintainer_push) do condition(:branch_allows_collaboration) do
@subject.project.branch_allows_maintainer_push?(@user, @subject.ref) @subject.project.branch_allows_collaboration?(@user, @subject.ref)
end end
rule { protected_ref }.prevent :update_pipeline rule { protected_ref }.prevent :update_pipeline
rule { can?(:public_access) & branch_allows_maintainer_push }.policy do rule { can?(:public_access) & branch_allows_collaboration }.policy do
enable :update_pipeline enable :update_pipeline
end end
......
...@@ -13,7 +13,7 @@ class MergeRequestWidgetEntity < IssuableEntity ...@@ -13,7 +13,7 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :squash expose :squash
expose :target_branch expose :target_branch
expose :target_project_id expose :target_project_id
expose :allow_maintainer_to_push expose :allow_collaboration
expose :should_be_rebased?, as: :should_be_rebased expose :should_be_rebased?, as: :should_be_rebased
expose :ff_only_enabled do |merge_request| expose :ff_only_enabled do |merge_request|
......
module ApplicationSettings module ApplicationSettings
class UpdateService < ApplicationSettings::BaseService class UpdateService < ApplicationSettings::BaseService
attr_reader :params, :application_setting
def execute def execute
update_terms(@params.delete(:terms)) update_terms(@params.delete(:terms))
......
...@@ -2,8 +2,7 @@ module Applications ...@@ -2,8 +2,7 @@ module Applications
class CreateService class CreateService
def initialize(current_user, params) def initialize(current_user, params)
@current_user = current_user @current_user = current_user
@params = params @params = params.except(:ip_address)
@ip_address = @params.delete(:ip_address)
end end
def execute(request = nil) def execute(request = nil)
......
...@@ -38,8 +38,8 @@ module MergeRequests ...@@ -38,8 +38,8 @@ module MergeRequests
def filter_params(merge_request) def filter_params(merge_request)
super super
unless merge_request.can_allow_maintainer_to_push?(current_user) unless merge_request.can_allow_collaboration?(current_user)
params.delete(:allow_maintainer_to_push) params.delete(:allow_collaboration)
end end
end end
......
module TestHooks module TestHooks
class ProjectService < TestHooks::BaseService class ProjectService < TestHooks::BaseService
private attr_writer :project
def project def project
@project ||= hook.project @project ||= hook.project
end end
private
def push_events_data def push_events_data
throw(:validation_error, 'Ensure the project has at least one commit.') if project.empty_repo? throw(:validation_error, 'Ensure the project has at least one commit.') if project.empty_repo?
......
...@@ -33,7 +33,7 @@ module ObjectStorage ...@@ -33,7 +33,7 @@ module ObjectStorage
unless current_upload_satisfies?(paths, model) unless current_upload_satisfies?(paths, model)
# the upload we already have isn't right, find the correct one # the upload we already have isn't right, find the correct one
self.upload = uploads.find_by(model: model, path: paths) self.upload = model&.retrieve_upload(identifier, paths)
end end
super super
...@@ -46,7 +46,7 @@ module ObjectStorage ...@@ -46,7 +46,7 @@ module ObjectStorage
end end
def upload=(upload) def upload=(upload)
return unless upload return if upload.nil?
self.object_store = upload.store self.object_store = upload.store
super super
......
%fieldset %fieldset
%legend Access %legend Access
.form-group .form-group.row
= f.label :projects_limit, class: 'col-form-label' = 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' .col-sm-10= f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control'
.form-group .form-group.row
= f.label :can_create_group, class: 'col-form-label' = f.label :can_create_group, class: 'col-form-label col-sm-2'
.col-sm-10= f.check_box :can_create_group .col-sm-10= f.check_box :can_create_group
.form-group .form-group.row
= f.label :access_level, class: 'col-form-label' = f.label :access_level, class: 'col-form-label col-sm-2'
.col-sm-10 .col-sm-10
- editing_current_user = (current_user == @user) - editing_current_user = (current_user == @user)
= f.radio_button :access_level, :regular, disabled: editing_current_user = f.radio_button :access_level, :regular, disabled: editing_current_user
= label_tag :regular do = label_tag :regular, class: 'font-weight-bold' do
Regular Regular
%p.light %p.light
Regular users have access to their groups and projects Regular users have access to their groups and projects
= f.radio_button :access_level, :admin, disabled: editing_current_user = f.radio_button :access_level, :admin, disabled: editing_current_user
= label_tag :admin do = label_tag :admin, class: 'font-weight-bold' do
Admin Admin
%p.light %p.light
Administrators have access to all groups, projects and users and can manage all features in this installation Administrators have access to all groups, projects and users and can manage all features in this installation
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
%p.light %p.light
You cannot remove your own admin rights. You cannot remove your own admin rights.
.form-group .form-group.row
= f.label :external, class: 'col-form-label' = f.label :external, class: 'col-form-label col-sm-2'
.col-sm-10 .col-sm-10
= f.check_box :external do = f.check_box :external do
External External
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
= f.label :linkedin, class: 'col-form-label col-sm-2' = f.label :linkedin, class: 'col-form-label col-sm-2'
.col-sm-10= f.text_field :linkedin, class: 'form-control' .col-sm-10= f.text_field :linkedin, class: 'form-control'
.form-group.row .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' .col-sm-10= f.text_field :twitter, class: 'form-control'
.form-group.row .form-group.row
= f.label :website_url, 'Website', class: 'col-form-label col-sm-2' = f.label :website_url, 'Website', class: 'col-form-label col-sm-2'
......
...@@ -5,5 +5,5 @@ ...@@ -5,5 +5,5 @@
-# total_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# 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' = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link'
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
-# total_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# 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' = link_to raw(t 'views.pagination.truncate'), '#', class: 'page-link'
...@@ -5,5 +5,5 @@ ...@@ -5,5 +5,5 @@
-# total_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# 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'} = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {remote: remote, class: 'page-link'}
...@@ -8,5 +8,5 @@ ...@@ -8,5 +8,5 @@
- page_url = current_page.last? ? '#' : url - 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' = link_to raw(t 'views.pagination.next'), page_url, rel: 'next', remote: remote, class: 'page-link'
...@@ -6,5 +6,5 @@ ...@@ -6,5 +6,5 @@
-# total_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# 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' } = link_to page, url, { remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil, class: 'page-link' }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-# remote: data-remote -# remote: data-remote
-# paginator: the paginator that renders the pagination tags inside -# paginator: the paginator that renders the pagination tags inside
= paginator.render do = paginator.render do
.gl-pagination .gl-pagination.prepend-top-default
%ul.pagination.justify-content-center %ul.pagination.justify-content-center
- unless current_page.first? - unless current_page.first?
= first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages
......
...@@ -8,5 +8,5 @@ ...@@ -8,5 +8,5 @@
- page_url = current_page.first? ? '#' : url - 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' = link_to raw(t 'views.pagination.previous'), page_url, rel: 'prev', remote: remote, class: 'page-link'
.gl-pagination .gl-pagination.prepend-top-default
%ul.pagination.clearfix %ul.pagination.justify-content-center
- if previous_path - if previous_path
%li.page-item.prev %li.page-item.prev
= link_to(t('views.pagination.previous'), previous_path, rel: 'prev', class: 'page-link') = link_to(t('views.pagination.previous'), previous_path, rel: 'prev', class: 'page-link')
......
.file-content.blob_file.blob-no-preview .file-content.blob_file.blob-no-preview
.center.render-error.vertical-center .center.render-error
= link_to blob_raw_path do = link_to blob_raw_path do
%h1.light %h1.light
= sprite_icon('download') = sprite_icon('download')
......
...@@ -29,16 +29,16 @@ ...@@ -29,16 +29,16 @@
.col-lg-9.js-toggle-container .col-lg-9.js-toggle-container
%ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' } %ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' }
%li{ class: active_when(active_tab == 'blank'), role: 'presentation' } %li.nav-item{ role: 'presentation' }
%a{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab' }, role: 'tab' } %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-none.d-sm-block Blank project
%span.d-block.d-sm-none Blank %span.d-block.d-sm-none Blank
%li{ class: active_when(active_tab == 'template'), role: 'presentation' } %li.nav-item{ role: 'presentation' }
%a{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab' }, role: 'tab' } %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-none.d-sm-block Create from template
%span.d-block.d-sm-none Template %span.d-block.d-sm-none Template
%li{ class: active_when(active_tab == 'import'), role: 'presentation' } %li.nav-item{ role: 'presentation' }
%a{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab' }, role: 'tab' } %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-none.d-sm-block Import project
%span.d-block.d-sm-none Import %span.d-block.d-sm-none Import
......
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
= _('Contribution') = _('Contribution')
.col-sm-10 .col-sm-10
.form-check .form-check
= form.check_box :allow_maintainer_to_push, disabled: !issuable.can_allow_maintainer_to_push?(current_user), class: 'form-check-input' = form.check_box :allow_collaboration, disabled: !issuable.can_allow_collaboration?(current_user), class: 'form-check-input'
= form.label :allow_maintainer_to_push, class: 'form-check-label' do = form.label :allow_collaboration, class: 'form-check-label' do
= _('Allow edits from maintainers.') = _('Allow commits from members who can merge to the target branch.')
= link_to 'About this feature', help_page_path('user/project/merge_requests/maintainer_access') = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration')
.form-text.text-muted .form-text.text-muted
= allow_maintainer_push_unavailable_reason(issuable) = allow_collaboration_unavailable_reason(issuable)
- unless can?(current_user, :push_code, @project) - unless can?(current_user, :push_code, @project)
.inline.prepend-left-10 .inline.prepend-left-10
- if @project.branch_allows_maintainer_push?(current_user, selected_branch) - if @project.branch_allows_collaboration?(current_user, selected_branch)
= commit_in_single_accessible_branch = commit_in_single_accessible_branch
- else - else
= commit_in_fork_help = commit_in_fork_help
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
.float-right .float-right
= button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do
= _('Accept terms') = _('Accept terms')
- else
.pull-right
= link_to root_path, class: 'btn btn-success prepend-left-8' do
= _('Continue')
- if can?(current_user, :decline_terms, @term) - if can?(current_user, :decline_terms, @term)
.float-right .float-right
= button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do = button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do
......
---
title: Rephrasing Merge Request's 'allow edits from maintainer' functionality
merge_request: 19061
author:
type: deprecated
---
title: Add flash notice if user has already accepted terms and allow users to continue
to root path
merge_request: 19156
author:
type: changed
---
title: Fix an N+1 when loading user avatars
merge_request:
author:
type: performance
---
title: Update runner cached informations without performing validations
merge_request:
author:
type: performance
---
title: Add migration to disable the usage of DSA keys
merge_request: 19299
author:
type: other
---
title: Eliminate N+1 queries with authors and push_data_payload in Events API
merge_request:
author:
type: performance
class RenameMergeRequestsAllowMaintainerToPush < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
rename_column_concurrently :merge_requests, :allow_maintainer_to_push, :allow_collaboration
end
def down
cleanup_concurrent_column_rename :merge_requests, :allow_collaboration, :allow_maintainer_to_push
end
end
class ChangeDefaultValueForDsaKeyRestriction < ActiveRecord::Migration
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
change_column :application_settings, :dsa_key_restriction, :integer, null: false,
default: -1
execute("UPDATE application_settings SET dsa_key_restriction = -1")
end
def down
change_column :application_settings, :dsa_key_restriction, :integer, null: false,
default: 0
end
end
class CleanupMergeRequestsAllowMaintainerToPushRename < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
cleanup_concurrent_column_rename :merge_requests, :allow_maintainer_to_push, :allow_collaboration
end
def down
rename_column_concurrently :merge_requests, :allow_collaboration, :allow_maintainer_to_push
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180530135500) do ActiveRecord::Schema.define(version: 20180531220618) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -110,7 +110,7 @@ ActiveRecord::Schema.define(version: 20180530135500) do ...@@ -110,7 +110,7 @@ ActiveRecord::Schema.define(version: 20180530135500) do
t.text "shared_runners_text_html" t.text "shared_runners_text_html"
t.text "after_sign_up_text_html" t.text "after_sign_up_text_html"
t.integer "rsa_key_restriction", default: 0, null: false t.integer "rsa_key_restriction", default: 0, null: false
t.integer "dsa_key_restriction", default: 0, null: false t.integer "dsa_key_restriction", default: -1, null: false
t.integer "ecdsa_key_restriction", default: 0, null: false t.integer "ecdsa_key_restriction", default: 0, null: false
t.integer "ed25519_key_restriction", default: 0, null: false t.integer "ed25519_key_restriction", default: 0, null: false
t.boolean "housekeeping_enabled", default: true, null: false t.boolean "housekeeping_enabled", default: true, null: false
...@@ -1230,7 +1230,7 @@ ActiveRecord::Schema.define(version: 20180530135500) do ...@@ -1230,7 +1230,7 @@ ActiveRecord::Schema.define(version: 20180530135500) do
t.boolean "discussion_locked" t.boolean "discussion_locked"
t.integer "latest_merge_request_diff_id" t.integer "latest_merge_request_diff_id"
t.string "rebase_commit_sha" t.string "rebase_commit_sha"
t.boolean "allow_maintainer_to_push" t.boolean "allow_collaboration"
t.boolean "squash", default: false, null: false t.boolean "squash", default: false, null: false
end end
......
...@@ -651,7 +651,8 @@ POST /projects/:id/merge_requests ...@@ -651,7 +651,8 @@ POST /projects/:id/merge_requests
| `labels` | string | no | Labels for MR as a comma-separated list | | `labels` | string | no | Labels for MR as a comma-separated list |
| `milestone_id` | integer | no | The global ID of a milestone | | `milestone_id` | integer | no | The global ID of a milestone |
| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging | | `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
| `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch | | `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch |
| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration |
| `squash` | boolean | no | Squash commits into a single commit when merging | | `squash` | boolean | no | Squash commits into a single commit when merging |
```json ```json
...@@ -709,6 +710,7 @@ POST /projects/:id/merge_requests ...@@ -709,6 +710,7 @@ POST /projects/:id/merge_requests
"squash": false, "squash": false,
"web_url": "http://example.com/example/example/merge_requests/1", "web_url": "http://example.com/example/example/merge_requests/1",
"discussion_locked": false, "discussion_locked": false,
"allow_collaboration": false,
"allow_maintainer_to_push": false, "allow_maintainer_to_push": false,
"time_stats": { "time_stats": {
"time_estimate": 0, "time_estimate": 0,
...@@ -741,7 +743,8 @@ PUT /projects/:id/merge_requests/:merge_request_iid ...@@ -741,7 +743,8 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging | | `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
| `squash` | boolean | no | Squash commits into a single commit when merging | | `squash` | boolean | no | Squash commits into a single commit when merging |
| `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. | | `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. |
| `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch | | `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch |
| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration |
Must include at least one non-required attribute from above. Must include at least one non-required attribute from above.
...@@ -799,6 +802,7 @@ Must include at least one non-required attribute from above. ...@@ -799,6 +802,7 @@ Must include at least one non-required attribute from above.
"squash": false, "squash": false,
"web_url": "http://example.com/example/example/merge_requests/1", "web_url": "http://example.com/example/example/merge_requests/1",
"discussion_locked": false, "discussion_locked": false,
"allow_collaboration": false,
"allow_maintainer_to_push": false, "allow_maintainer_to_push": false,
"time_stats": { "time_stats": {
"time_estimate": 0, "time_estimate": 0,
......
...@@ -16,7 +16,7 @@ are very appreciative of the work done by translators and proofreaders! ...@@ -16,7 +16,7 @@ are very appreciative of the work done by translators and proofreaders!
- Dutch - Dutch
- Esperanto - Esperanto
- French - French
- Rémy Coutable - [GitLab](https://gitlab.com/rymai), [Crowdin](https://crowdin.com/profile/rymai) - Davy Defaud - [GitLab](https://gitlab.com/DevDef), [Crowdin](https://crowdin.com/profile/DevDef)
- German - German
- Indonesian - Indonesian
- Ahmad Naufal Mukhtar - [GitLab](https://gitlab.com/anaufalm), [Crowdin](https://crowdin.com/profile/anaufalm) - Ahmad Naufal Mukhtar - [GitLab](https://gitlab.com/anaufalm), [Crowdin](https://crowdin.com/profile/anaufalm)
......
# Allow collaboration on merge requests across forks
> [Introduced][ce-17395] in GitLab 10.6.
This feature is available for merge requests across forked projects that are
publicly accessible. It makes it easier for members of projects to
collaborate on merge requests across forks.
When enabled for a merge request, members with merge access to the target
branch of the project will be granted write permissions to the source branch
of the merge request.
The feature can only be enabled by users who already have push access to the
source project, and only lasts while the merge request is open.
Enable this functionality while creating or editing a merge request:
![Enable collaboration](./img/allow_collaboration.png)
[ce-17395]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17395
...@@ -28,7 +28,7 @@ With GitLab merge requests, you can: ...@@ -28,7 +28,7 @@ With GitLab merge requests, you can:
- Enable [fast-forward merge requests](#fast-forward-merge-requests) - Enable [fast-forward merge requests](#fast-forward-merge-requests)
- Enable [semi-linear history merge requests](#semi-linear-history-merge-requests) as another security layer to guarantee the pipeline is passing in the target branch - Enable [semi-linear history merge requests](#semi-linear-history-merge-requests) as another security layer to guarantee the pipeline is passing in the target branch
- [Create new merge requests by email](#create-new-merge-requests-by-email) - [Create new merge requests by email](#create-new-merge-requests-by-email)
- Allow maintainers of the target project to push directly to the fork by [allowing edits from maintainers](maintainer_access.md) - [Allow collaboration](allow_collaboration.md) so members of the target project can push directly to the fork
- [Squash and merge](squash_and_merge.md) for a cleaner commit history - [Squash and merge](squash_and_merge.md) for a cleaner commit history
With **[GitLab Enterprise Edition][ee]**, you can also: With **[GitLab Enterprise Edition][ee]**, you can also:
......
# Allow maintainer pushes for merge requests across forks This document was moved to [another location](allow_collaboration.md).
> [Introduced][ce-17395] in GitLab 10.6.
This feature is available for merge requests across forked projects that are
publicly accessible. It makes it easier for maintainers of projects to
collaborate on merge requests across forks.
When enabled for a merge request, members with merge access to the target
branch of the project will be granted write permissions to the source branch
of the merge request.
The feature can only be enabled by users who already have push access to the
source project, and only lasts while the merge request is open.
Enable this functionality while creating a merge request:
![Enable maintainer edits](./img/allow_maintainer_push.png)
[ce-17395]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17395
...@@ -559,7 +559,9 @@ module API ...@@ -559,7 +559,9 @@ module API
expose :discussion_locked expose :discussion_locked
expose :should_remove_source_branch?, as: :should_remove_source_branch expose :should_remove_source_branch?, as: :should_remove_source_branch
expose :force_remove_source_branch?, as: :force_remove_source_branch expose :force_remove_source_branch?, as: :force_remove_source_branch
expose :allow_maintainer_to_push, if: -> (merge_request, _) { merge_request.for_fork? } expose :allow_collaboration, if: -> (merge_request, _) { merge_request.for_fork? }
# Deprecated
expose :allow_collaboration, as: :allow_maintainer_to_push, if: -> (merge_request, _) { merge_request.for_fork? }
expose :web_url do |merge_request, options| expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request) Gitlab::UrlBuilder.build(merge_request)
......
...@@ -17,6 +17,7 @@ module API ...@@ -17,6 +17,7 @@ module API
def present_events(events) def present_events(events)
events = events.reorder(created_at: params[:sort]) events = events.reorder(created_at: params[:sort])
.with_associations
present paginate(events), with: Entities::Event present paginate(events), with: Entities::Event
end end
......
...@@ -162,7 +162,8 @@ module API ...@@ -162,7 +162,8 @@ module API
optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request' optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request'
optional :labels, type: String, desc: 'Comma-separated list of label names' optional :labels, type: String, desc: 'Comma-separated list of label names'
optional :remove_source_branch, type: Boolean, desc: 'Remove source branch when merging' optional :remove_source_branch, type: Boolean, desc: 'Remove source branch when merging'
optional :allow_maintainer_to_push, type: Boolean, desc: 'Whether a maintainer of the target project can push to the source project' optional :allow_collaboration, type: Boolean, desc: 'Allow commits from members who can merge to the target branch'
optional :allow_maintainer_to_push, type: Boolean, as: :allow_collaboration, desc: '[deprecated] See allow_collaboration'
optional :squash, type: Grape::API::Boolean, desc: 'When true, the commits will be squashed into a single commit on merge' optional :squash, type: Grape::API::Boolean, desc: 'When true, the commits will be squashed into a single commit on merge'
use :optional_params_ee use :optional_params_ee
......
module Backup
Error = Class.new(StandardError)
end
...@@ -44,7 +44,7 @@ module Backup ...@@ -44,7 +44,7 @@ module Backup
end end
report_success(success) report_success(success)
abort 'Backup failed' unless success raise Backup::Error, 'Backup failed' unless success
end end
def restore def restore
...@@ -72,7 +72,7 @@ module Backup ...@@ -72,7 +72,7 @@ module Backup
end end
report_success(success) report_success(success)
abort 'Restore failed' unless success abort Backup::Error, 'Restore failed' unless success
end end
protected protected
......
...@@ -26,7 +26,7 @@ module Backup ...@@ -26,7 +26,7 @@ module Backup
unless status.zero? unless status.zero?
puts output puts output
abort 'Backup failed' raise Backup::Error, 'Backup failed'
end end
run_pipeline!([%W(tar --exclude=lost+found -C #{@backup_files_dir} -cf - .), %w(gzip -c -1)], out: [backup_tarball, 'w', 0600]) run_pipeline!([%W(tar --exclude=lost+found -C #{@backup_files_dir} -cf - .), %w(gzip -c -1)], out: [backup_tarball, 'w', 0600])
...@@ -39,7 +39,11 @@ module Backup ...@@ -39,7 +39,11 @@ module Backup
def restore def restore
backup_existing_files_dir backup_existing_files_dir
run_pipeline!([%w(gzip -cd), %W(tar --unlink-first --recursive-unlink -C #{app_files_dir} -xf -)], in: backup_tarball) run_pipeline!([%w(gzip -cd), %W(#{tar} --unlink-first --recursive-unlink -C #{app_files_dir} -xf -)], in: backup_tarball)
end
def tar
system(*%w[gtar --version], out: '/dev/null') ? 'gtar' : 'tar'
end end
def backup_existing_files_dir def backup_existing_files_dir
...@@ -61,7 +65,7 @@ module Backup ...@@ -61,7 +65,7 @@ module Backup
def run_pipeline!(cmd_list, options = {}) def run_pipeline!(cmd_list, options = {})
status_list = Open3.pipeline(*cmd_list, options) status_list = Open3.pipeline(*cmd_list, options)
abort 'Backup failed' unless status_list.compact.all?(&:success?) raise Backup::Error, 'Backup failed' unless status_list.compact.all?(&:success?)
end end
end end
end end
...@@ -27,7 +27,7 @@ module Backup ...@@ -27,7 +27,7 @@ module Backup
progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
puts "creating archive #{tar_file} failed".color(:red) puts "creating archive #{tar_file} failed".color(:red)
abort 'Backup failed' raise Backup::Error, 'Backup failed'
end end
upload upload
...@@ -52,7 +52,7 @@ module Backup ...@@ -52,7 +52,7 @@ module Backup
progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
puts "uploading backup to #{remote_directory} failed".color(:red) puts "uploading backup to #{remote_directory} failed".color(:red)
abort 'Backup failed' raise Backup::Error, 'Backup failed'
end end
end end
...@@ -66,7 +66,7 @@ module Backup ...@@ -66,7 +66,7 @@ module Backup
progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
puts "deleting tmp directory '#{dir}' failed".color(:red) puts "deleting tmp directory '#{dir}' failed".color(:red)
abort 'Backup failed' raise Backup::Error, 'Backup failed'
end end
end end
end end
......
...@@ -17,7 +17,10 @@ module Backup ...@@ -17,7 +17,10 @@ module Backup
Project.find_each(batch_size: 1000) do |project| Project.find_each(batch_size: 1000) do |project|
progress.print " * #{display_repo_path(project)} ... " progress.print " * #{display_repo_path(project)} ... "
path_to_project_repo = path_to_repo(project)
path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
path_to_repo(project)
end
path_to_project_bundle = path_to_bundle(project) path_to_project_bundle = path_to_bundle(project)
# Create namespace dir or hashed path if missing # Create namespace dir or hashed path if missing
...@@ -51,7 +54,9 @@ module Backup ...@@ -51,7 +54,9 @@ module Backup
end end
wiki = ProjectWiki.new(project) wiki = ProjectWiki.new(project)
path_to_wiki_repo = path_to_repo(wiki) path_to_wiki_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
path_to_repo(wiki)
end
path_to_wiki_bundle = path_to_bundle(wiki) path_to_wiki_bundle = path_to_bundle(wiki)
if File.exist?(path_to_wiki_repo) if File.exist?(path_to_wiki_repo)
...@@ -111,7 +116,9 @@ module Backup ...@@ -111,7 +116,9 @@ module Backup
# TODO: Need to find a way to do this for gitaly # TODO: Need to find a way to do this for gitaly
# Gitaly migration issue: https://gitlab.com/gitlab-org/gitaly/issues/1195 # Gitaly migration issue: https://gitlab.com/gitlab-org/gitaly/issues/1195
in_path(path_to_tars(project)) do |dir| in_path(path_to_tars(project)) do |dir|
path_to_project_repo = path_to_repo(project) path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
path_to_repo(project)
end
cmd = %W(tar -xf #{path_to_tars(project, dir)} -C #{path_to_project_repo} #{dir}) cmd = %W(tar -xf #{path_to_tars(project, dir)} -C #{path_to_project_repo} #{dir})
output, status = Gitlab::Popen.popen(cmd) output, status = Gitlab::Popen.popen(cmd)
......
...@@ -109,7 +109,7 @@ module Gitlab ...@@ -109,7 +109,7 @@ module Gitlab
end end
def ==(other) def ==(other)
path == other.path [storage, relative_path] == [other.storage, other.relative_path]
end end
def path def path
......
...@@ -26,10 +26,6 @@ module Gitlab ...@@ -26,10 +26,6 @@ module Gitlab
@shared.error(e) @shared.error(e)
false false
end end
def path_to_repo
@project.repository.path_to_repo
end
end end
end end
end end
...@@ -22,12 +22,8 @@ module Gitlab ...@@ -22,12 +22,8 @@ module Gitlab
"project.wiki.bundle" "project.wiki.bundle"
end end
def path_to_repo
@wiki.repository.path_to_repo
end
def wiki_repository_exists? def wiki_repository_exists?
File.exist?(@wiki.repository.path_to_repo) && !@wiki.repository.empty? @wiki.repository.exists? && !@wiki.repository.empty?
end end
end end
end end
......
...@@ -128,10 +128,12 @@ module Gitlab ...@@ -128,10 +128,12 @@ module Gitlab
end end
def all_repos def all_repos
Gitlab.config.repositories.storages.each_value do |repository_storage| Gitlab::GitalyClient::StorageSettings.allow_disk_access do
IO.popen(%W(find #{repository_storage.legacy_disk_path} -mindepth 2 -type d -name *.git)) do |find| Gitlab.config.repositories.storages.each_value do |repository_storage|
find.each_line do |path| IO.popen(%W(find #{repository_storage.legacy_disk_path} -mindepth 2 -type d -name *.git)) do |find|
yield path.chomp find.each_line do |path|
yield path.chomp
end
end end
end end
end end
......
...@@ -65,7 +65,7 @@ module Gitlab ...@@ -65,7 +65,7 @@ module Gitlab
return false unless can_access_git? return false unless can_access_git?
return false unless project return false unless project
return false if !user.can?(:push_code, project) && !project.branch_allows_maintainer_push?(user, ref) return false if !user.can?(:push_code, project) && !project.branch_allows_collaboration?(user, ref)
if protected?(ProtectedBranch, project, ref) if protected?(ProtectedBranch, project, ref)
protected_branch_accessible_to?(ref, action: :push) protected_branch_accessible_to?(ref, action: :push)
......
...@@ -12,7 +12,7 @@ namespace :gitlab do ...@@ -12,7 +12,7 @@ namespace :gitlab do
namespaces = Namespace.pluck(:path) namespaces = Namespace.pluck(:path)
namespaces << HASHED_REPOSITORY_NAME # add so that it will be ignored namespaces << HASHED_REPOSITORY_NAME # add so that it will be ignored
Gitlab.config.repositories.storages.each do |name, repository_storage| Gitlab.config.repositories.storages.each do |name, repository_storage|
git_base_path = repository_storage.legacy_disk_path git_base_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository_storage.legacy_disk_path }
all_dirs = Dir.glob(git_base_path + '/*') all_dirs = Dir.glob(git_base_path + '/*')
puts git_base_path.color(:yellow) puts git_base_path.color(:yellow)
...@@ -54,7 +54,8 @@ namespace :gitlab do ...@@ -54,7 +54,8 @@ namespace :gitlab do
move_suffix = "+orphaned+#{Time.now.to_i}" move_suffix = "+orphaned+#{Time.now.to_i}"
Gitlab.config.repositories.storages.each do |name, repository_storage| Gitlab.config.repositories.storages.each do |name, repository_storage|
repo_root = repository_storage.legacy_disk_path repo_root = Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository_storage.legacy_disk_path }
# Look for global repos (legacy, depth 1) and normal repos (depth 2) # Look for global repos (legacy, depth 1) and normal repos (depth 2)
IO.popen(%W(find #{repo_root} -mindepth 1 -maxdepth 2 -name *.git)) do |find| IO.popen(%W(find #{repo_root} -mindepth 1 -maxdepth 2 -name *.git)) do |find|
find.each_line do |path| find.each_line do |path|
......
...@@ -331,7 +331,7 @@ msgstr "" ...@@ -331,7 +331,7 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings." msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "" msgstr ""
msgid "Allow edits from maintainers." msgid "Allow commits from members who can merge to the target branch."
msgstr "" msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents." msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
...@@ -4894,7 +4894,7 @@ msgstr "" ...@@ -4894,7 +4894,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB" msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "" msgstr ""
msgid "mrWidget|Allows edits from maintainers" msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "" msgstr ""
msgid "mrWidget|Cancel automatic merge" msgid "mrWidget|Cancel automatic merge"
......
...@@ -477,4 +477,28 @@ describe ApplicationController do ...@@ -477,4 +477,28 @@ describe ApplicationController do
end end
end end
end end
describe '#access_denied' do
controller(described_class) do
def index
access_denied!(params[:message])
end
end
before do
sign_in user
end
it 'renders a 404 without a message' do
get :index
expect(response).to have_gitlab_http_status(404)
end
it 'renders a 403 when a message is passed to access denied' do
get :index, message: 'None shall pass'
expect(response).to have_gitlab_http_status(403)
end
end
end end
...@@ -43,13 +43,13 @@ describe ControllerWithCrossProjectAccessCheck do ...@@ -43,13 +43,13 @@ describe ControllerWithCrossProjectAccessCheck do
end end
end end
it 'renders a 404 with trying to access a cross project page' do it 'renders a 403 with trying to access a cross project page' do
message = "This page is unavailable because you are not allowed to read "\ message = "This page is unavailable because you are not allowed to read "\
"information across multiple projects." "information across multiple projects."
get :index get :index
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(403)
expect(response.body).to match(/#{message}/) expect(response.body).to match(/#{message}/)
end end
...@@ -119,7 +119,7 @@ describe ControllerWithCrossProjectAccessCheck do ...@@ -119,7 +119,7 @@ describe ControllerWithCrossProjectAccessCheck do
get :index get :index
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(403)
end end
it 'is executed when the `unless` condition returns true' do it 'is executed when the `unless` condition returns true' do
...@@ -127,19 +127,19 @@ describe ControllerWithCrossProjectAccessCheck do ...@@ -127,19 +127,19 @@ describe ControllerWithCrossProjectAccessCheck do
get :index get :index
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(403)
end end
it 'does not skip the check on an action that is not skipped' do it 'does not skip the check on an action that is not skipped' do
get :show, id: 'hello' get :show, id: 'hello'
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(403)
end end
it 'does not skip the check on an action that was not defined to skip' do it 'does not skip the check on an action that was not defined to skip' do
get :edit, id: 'hello' get :edit, id: 'hello'
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(403)
end end
end end
end end
......
...@@ -32,7 +32,7 @@ describe SearchController do ...@@ -32,7 +32,7 @@ describe SearchController do
it 'still blocks searches without a project_id' do it 'still blocks searches without a project_id' do
get :show, search: 'hello' get :show, search: 'hello'
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(403)
end end
it 'allows searches with a project_id' do it 'allows searches with a project_id' do
......
require 'spec_helper' require 'spec_helper'
describe Users::TermsController do describe Users::TermsController do
include TermsHelper
let(:user) { create(:user) } let(:user) { create(:user) }
let(:term) { create(:term) } let(:term) { create(:term) }
...@@ -15,10 +16,25 @@ describe Users::TermsController do ...@@ -15,10 +16,25 @@ describe Users::TermsController do
expect(response).to have_gitlab_http_status(:redirect) expect(response).to have_gitlab_http_status(:redirect)
end end
it 'shows terms when they exist' do context 'when terms exist' do
term before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
term
end
it 'shows terms when they exist' do
get :index
expect(response).to have_gitlab_http_status(:success)
end
expect(response).to have_gitlab_http_status(:success) it 'shows a message when the user already accepted the terms' do
accept_terms(user)
get :index
expect(controller).to set_flash.now[:notice].to(/already accepted/)
end
end end
end end
......
...@@ -3,4 +3,12 @@ FactoryBot.define do ...@@ -3,4 +3,12 @@ FactoryBot.define do
term term
user user
end end
trait :declined do
accepted false
end
trait :accepted do
accepted true
end
end end
...@@ -14,7 +14,7 @@ describe 'a maintainer edits files on a source-branch of an MR from a fork', :js ...@@ -14,7 +14,7 @@ describe 'a maintainer edits files on a source-branch of an MR from a fork', :js
source_branch: 'fix', source_branch: 'fix',
target_branch: 'master', target_branch: 'master',
author: author, author: author,
allow_maintainer_to_push: true) allow_collaboration: true)
end end
before do before do
......
require 'spec_helper' require 'spec_helper'
describe 'create a merge request that allows maintainers to push', :js do describe 'create a merge request, allowing commits from members who can merge to the target branch', :js do
include ProjectForksHelper include ProjectForksHelper
let(:user) { create(:user) } let(:user) { create(:user) }
let(:target_project) { create(:project, :public, :repository) } let(:target_project) { create(:project, :public, :repository) }
...@@ -21,16 +21,16 @@ describe 'create a merge request that allows maintainers to push', :js do ...@@ -21,16 +21,16 @@ describe 'create a merge request that allows maintainers to push', :js do
sign_in(user) sign_in(user)
end end
it 'allows setting maintainer push possible' do it 'allows setting possible' do
visit_new_merge_request visit_new_merge_request
check 'Allow edits from maintainers' check 'Allow commits from members who can merge to the target branch'
click_button 'Submit merge request' click_button 'Submit merge request'
wait_for_requests wait_for_requests
expect(page).to have_content('Allows edits from maintainers') expect(page).to have_content('Allows commits from members who can merge to the target branch')
end end
it 'shows a message when one of the projects is private' do it 'shows a message when one of the projects is private' do
...@@ -57,12 +57,12 @@ describe 'create a merge request that allows maintainers to push', :js do ...@@ -57,12 +57,12 @@ describe 'create a merge request that allows maintainers to push', :js do
visit_new_merge_request visit_new_merge_request
expect(page).not_to have_content('Allows edits from maintainers') expect(page).not_to have_content('Allows commits from members who can merge to the target branch')
end end
end end
context 'when a maintainer tries to edit the option' do context 'when a member who can merge tries to edit the option' do
let(:maintainer) { create(:user) } let(:member) { create(:user) }
let(:merge_request) do let(:merge_request) do
create(:merge_request, create(:merge_request,
source_project: source_project, source_project: source_project,
...@@ -71,15 +71,15 @@ describe 'create a merge request that allows maintainers to push', :js do ...@@ -71,15 +71,15 @@ describe 'create a merge request that allows maintainers to push', :js do
end end
before do before do
target_project.add_master(maintainer) target_project.add_master(member)
sign_in(maintainer) sign_in(member)
end end
it 'it hides the option from maintainers' do it 'it hides the option from members' do
visit edit_project_merge_request_path(target_project, merge_request) visit edit_project_merge_request_path(target_project, merge_request)
expect(page).not_to have_content('Allows edits from maintainers') expect(page).not_to have_content('Allows commits from members who can merge to the target branch')
end end
end end
end end
...@@ -87,11 +87,13 @@ feature 'Import/Export - project import integration test', :js do ...@@ -87,11 +87,13 @@ feature 'Import/Export - project import integration test', :js do
def wiki_exists?(project) def wiki_exists?(project)
wiki = ProjectWiki.new(project) wiki = ProjectWiki.new(project)
File.exist?(wiki.repository.path_to_repo) && !wiki.repository.empty? wiki.repository.exists? && !wiki.repository.empty?
end end
def project_hook_exists?(project) def project_hook_exists?(project)
Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository).exists? Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository).exists?
end
end end
def click_import_project_tab def click_import_project_tab
......
...@@ -39,6 +39,22 @@ describe 'Users > Terms' do ...@@ -39,6 +39,22 @@ describe 'Users > Terms' do
end end
end end
context 'when the user has already accepted the terms' do
before do
accept_terms(user)
end
it 'allows the user to continue to the app' do
visit terms_path
expect(page).to have_content "You have already accepted the Terms of Service as #{user.to_reference}"
click_link 'Continue'
expect(current_path).to eq(root_path)
end
end
context 'terms were enforced while session is active', :js do context 'terms were enforced while session is active', :js do
let(:project) { create(:project) } let(:project) { create(:project) }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"assignee_id": { "type": ["integer", "null"] }, "assignee_id": { "type": ["integer", "null"] },
"subscribed": { "type": ["boolean", "null"] }, "subscribed": { "type": ["boolean", "null"] },
"participants": { "type": "array" }, "participants": { "type": "array" },
"allow_collaboration": { "type": "boolean"},
"allow_maintainer_to_push": { "type": "boolean"} "allow_maintainer_to_push": { "type": "boolean"}
}, },
"additionalProperties": false "additionalProperties": false
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
"source_project_id": { "type": "integer" }, "source_project_id": { "type": "integer" },
"target_branch": { "type": "string" }, "target_branch": { "type": "string" },
"target_project_id": { "type": "integer" }, "target_project_id": { "type": "integer" },
"allow_maintainer_to_push": { "type": "boolean"}, "allow_collaboration": { "type": "boolean"},
"metrics": { "metrics": {
"oneOf": [ "oneOf": [
{ "type": "null" }, { "type": "null" },
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
"human_time_estimate": { "type": ["string", "null"] }, "human_time_estimate": { "type": ["string", "null"] },
"human_total_time_spent": { "type": ["string", "null"] } "human_total_time_spent": { "type": ["string", "null"] }
}, },
"allow_collaboration": { "type": ["boolean", "null"] },
"allow_maintainer_to_push": { "type": ["boolean", "null"] } "allow_maintainer_to_push": { "type": ["boolean", "null"] }
}, },
"required": [ "required": [
......
require 'spec_helper' require 'spec_helper'
describe 'Fog::Storage::GoogleXML::File' do describe 'Fog::Storage::GoogleXML::File', :fog_requests do
let(:storage) do let(:storage) do
Fog.mock! Fog.mock!
Fog::Storage.new({ Fog::Storage.new(
google_storage_access_key_id: "asdf", google_storage_access_key_id: "asdf",
google_storage_secret_access_key: "asdf", google_storage_secret_access_key: "asdf",
provider: "Google" provider: "Google"
}) )
end end
let(:file) do let(:file) do
......
...@@ -51,7 +51,7 @@ describe('Pagination component', () => { ...@@ -51,7 +51,7 @@ describe('Pagination component', () => {
expect( expect(
component.$el.querySelector('.js-previous-button').classList.contains('disabled'), component.$el.querySelector('.js-previous-button').classList.contains('disabled'),
).toEqual(true); ).toEqual(true);
component.$el.querySelector('.js-previous-button a').click(); component.$el.querySelector('.js-previous-button a').click();
......
...@@ -46,7 +46,9 @@ describe Backup::Files do ...@@ -46,7 +46,9 @@ describe Backup::Files do
end end
it 'calls tar command with unlink' do it 'calls tar command with unlink' do
expect(subject).to receive(:run_pipeline!).with([%w(gzip -cd), %w(tar --unlink-first --recursive-unlink -C /var/gitlab-registry -xf -)], any_args) expect(subject).to receive(:tar).and_return('blabla-tar')
expect(subject).to receive(:run_pipeline!).with([%w(gzip -cd), %w(blabla-tar --unlink-first --recursive-unlink -C /var/gitlab-registry -xf -)], any_args)
subject.restore subject.restore
end end
end end
......
...@@ -274,16 +274,13 @@ describe Backup::Manager do ...@@ -274,16 +274,13 @@ describe Backup::Manager do
} }
) )
# the Fog mock only knows about directories we create explicitly
Fog.mock! Fog.mock!
# the Fog mock only knows about directories we create explicitly
connection = ::Fog::Storage.new(Gitlab.config.backup.upload.connection.symbolize_keys) connection = ::Fog::Storage.new(Gitlab.config.backup.upload.connection.symbolize_keys)
connection.directories.create(key: Gitlab.config.backup.upload.remote_directory) connection.directories.create(key: Gitlab.config.backup.upload.remote_directory)
end end
after do
Fog.unmock!
end
context 'target path' do context 'target path' do
it 'uses the tar filename by default' do it 'uses the tar filename by default' do
expect_any_instance_of(Fog::Collection).to receive(:create) expect_any_instance_of(Fog::Collection).to receive(:create)
......
...@@ -34,7 +34,9 @@ describe Backup::Repository do ...@@ -34,7 +34,9 @@ describe Backup::Repository do
let(:timestamp) { Time.utc(2017, 3, 22) } let(:timestamp) { Time.utc(2017, 3, 22) }
let(:temp_dirs) do let(:temp_dirs) do
Gitlab.config.repositories.storages.map do |name, storage| Gitlab.config.repositories.storages.map do |name, storage|
File.join(storage.legacy_disk_path, '..', 'repositories.old.' + timestamp.to_i.to_s) Gitlab::GitalyClient::StorageSettings.allow_disk_access do
File.join(storage.legacy_disk_path, '..', 'repositories.old.' + timestamp.to_i.to_s)
end
end end
end end
......
...@@ -20,6 +20,13 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do ...@@ -20,6 +20,13 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do
Rainbow.enabled = @rainbow Rainbow.enabled = @rainbow
end end
around do |example|
# TODO migrate BareRepositoryImport https://gitlab.com/gitlab-org/gitaly/issues/953
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
shared_examples 'importing a repository' do shared_examples 'importing a repository' do
describe '.execute' do describe '.execute' do
it 'creates a project for a repository in storage' do it 'creates a project for a repository in storage' do
......
...@@ -62,8 +62,10 @@ describe ::Gitlab::BareRepositoryImport::Repository do ...@@ -62,8 +62,10 @@ describe ::Gitlab::BareRepositoryImport::Repository do
before do before do
gitlab_shell.create_repository(repository_storage, hashed_path) gitlab_shell.create_repository(repository_storage, hashed_path)
repository = Rugged::Repository.new(repo_path) Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repository.config['gitlab.fullpath'] = 'to/repo' repository = Rugged::Repository.new(repo_path)
repository.config['gitlab.fullpath'] = 'to/repo'
end
end end
after do after do
......
...@@ -159,6 +159,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -159,6 +159,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:feature2) { 'feature2' } let(:feature2) { 'feature2' }
around do |example| around do |example|
# discover_default_branch will be moved to gitaly-ruby
Gitlab::GitalyClient::StorageSettings.allow_disk_access do Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run example.run
end end
...@@ -373,6 +374,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -373,6 +374,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
context '#submodules' do context '#submodules' do
around do |example| around do |example|
# TODO #submodules will be removed, has been migrated to gitaly
Gitlab::GitalyClient::StorageSettings.allow_disk_access do Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run example.run
end end
...@@ -1055,6 +1057,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1055,6 +1057,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#rugged_commits_between" do describe "#rugged_commits_between" do
around do |example| around do |example|
# TODO #rugged_commits_between will be removed, has been migrated to gitaly
Gitlab::GitalyClient::StorageSettings.allow_disk_access do Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run example.run
end end
...@@ -1703,6 +1706,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1703,6 +1706,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:refs) { ['deadbeef', SeedRepo::RubyBlob::ID, '909e6157199'] } let(:refs) { ['deadbeef', SeedRepo::RubyBlob::ID, '909e6157199'] }
around do |example| around do |example|
# TODO #batch_existence isn't used anywhere, can we remove it?
Gitlab::GitalyClient::StorageSettings.allow_disk_access do Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run example.run
end end
......
...@@ -9,9 +9,11 @@ describe Gitlab::Git::RevList do ...@@ -9,9 +9,11 @@ describe Gitlab::Git::RevList do
end end
def stub_popen_rev_list(*additional_args, with_lazy_block: true, output:) def stub_popen_rev_list(*additional_args, with_lazy_block: true, output:)
repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository.path }
params = [ params = [
args_for_popen(additional_args), args_for_popen(additional_args),
repository.path, repo_path,
{}, {},
hash_including(lazy_block: with_lazy_block ? anything : nil) hash_including(lazy_block: with_lazy_block ? anything : nil)
] ]
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment