Commit c764980f authored by John Jarvis's avatar John Jarvis

Merge branch '11-9-stable-patch-1' into '11-9-stable'

Prepare 11.9.1 release

See merge request gitlab-org/gitlab-ce!26538
parents a47124c7 7a83fbef
......@@ -806,7 +806,7 @@
.merge-request-tabs-holder {
top: $header-height;
z-index: 300;
z-index: 250;
background-color: $white-light;
border-bottom: 1px solid $border-color;
......
......@@ -4,7 +4,7 @@ class BroadcastMessage < ActiveRecord::Base
include CacheMarkdownField
include Sortable
cache_markdown_field :message, pipeline: :broadcast_message
cache_markdown_field :message, pipeline: :broadcast_message, whitelisted: true
validates :message, presence: true
validates :starts_at, presence: true
......
......@@ -7,6 +7,7 @@
# cache_markdown_field :foo
# cache_markdown_field :bar
# cache_markdown_field :baz, pipeline: :single_line
# cache_markdown_field :baz, whitelisted: true
#
# Corresponding foo_html, bar_html and baz_html fields should exist.
module CacheMarkdownField
......@@ -37,7 +38,15 @@ module CacheMarkdownField
end
def html_fields
markdown_fields.map {|field| html_field(field) }
markdown_fields.map { |field| html_field(field) }
end
def html_fields_whitelisted
markdown_fields.each_with_object([]) do |field, fields|
if @data[field].fetch(:whitelisted, false)
fields << html_field(field)
end
end
end
end
......@@ -149,13 +158,18 @@ module CacheMarkdownField
alias_method :attributes_before_markdown_cache, :attributes
def attributes
attrs = attributes_before_markdown_cache
html_fields = cached_markdown_fields.html_fields
whitelisted = cached_markdown_fields.html_fields_whitelisted
exclude_fields = html_fields - whitelisted
attrs.delete('cached_markdown_version')
cached_markdown_fields.html_fields.each do |field|
exclude_fields.each do |field|
attrs.delete(field)
end
if whitelisted.empty?
attrs.delete('cached_markdown_version')
end
attrs
end
......
......@@ -1378,6 +1378,7 @@ class Project < ActiveRecord::Base
repository.raw_repository.write_ref('HEAD', "refs/heads/#{branch}")
repository.copy_gitattributes(branch)
repository.after_change_head
ProjectCacheWorker.perform_async(self.id, [], [:commit_count])
reload_default_branch
else
errors.add(:base, "Could not change HEAD: branch '#{branch}' does not exist")
......
......@@ -57,7 +57,7 @@ class DiffFileEntity < DiffFileBaseEntity
diff_file.diff_lines_for_serializer
end
expose :is_fully_expanded, if: -> (diff_file, _) { Feature.enabled?(:expand_diff_full_file) && diff_file.text? } do |diff_file|
expose :is_fully_expanded, if: -> (diff_file, _) { Feature.enabled?(:expand_diff_full_file, default_enabled: true) && diff_file.text? } do |diff_file|
diff_file.fully_expanded?
end
......
......@@ -12,7 +12,7 @@
%p
By default, protected branches are designed to:
%ul
%li prevent their creation, if not already created, from everybody except users who are allowed to merge
%li prevent their creation, if not already created, from everybody except Maintainers
%li prevent pushes from everybody except Maintainers
%li prevent <strong>anyone</strong> from force pushing to the branch
%li prevent <strong>anyone</strong> from deleting the branch
......
......@@ -27,6 +27,7 @@ class ProjectCacheWorker
# rubocop: enable CodeReuse/ActiveRecord
def update_statistics(project, statistics = [])
return if Gitlab::Database.read_only?
return unless try_obtain_lease_for(project.id, :update_statistics)
Rails.logger.info("Updating statistics for project #{project.id}")
......
---
title: Fix issue that caused the "Show all activity" button to appear on top of the
mini pipeline status dropdown on the merge request page
merge_request: 26274
author:
type: fixed
---
title: Fix duplicated bottom match line on merge request parallel diff view
merge_request: 26402
author:
type: fixed
---
title: Allow users who can push to protected branches to create protected branches
via CLI
merge_request: 26413
author:
type: fixed
---
title: Add missing .gitlab-ci.yml to Android template
merge_request: 26415
author:
type: fixed
---
title: Upgrade to Gitaly v1.27.1
merge_request: 26533
author:
type: changed
---
title: Refresh commit count after repository head changes
merge_request: 26473
author:
type: fixed
---
title: Set proper default-branch for repository on GitHub Import
merge_request: 26476
author:
type: fixed
---
title: 'GitHub importer: Use the project creator to create branches from forks'
merge_request: 26510
author:
type: fixed
......@@ -10,7 +10,7 @@ created protected branches.
By default, a protected branch does four simple things:
- it prevents its creation, if not already created, from everybody except users
who are allowed to merge
with Maintainer permission
- it prevents pushes from everybody except users with Maintainer permission
- it prevents **anyone** from force pushing to the branch
- it prevents **anyone** from deleting the branch
......
......@@ -59,6 +59,8 @@ module Gitlab
def protected_branch_creation_checks
logger.log_timed(LOG_MESSAGES[:protected_branch_creation_checks]) do
break if user_access.can_push_to_branch?(branch_name)
unless user_access.can_merge_to_branch?(branch_name)
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:create_protected_branch]
end
......
......@@ -158,7 +158,10 @@ module Gitlab
new_blob || old_blob
end
attr_writer :highlighted_diff_lines
def highlighted_diff_lines=(value)
clear_memoization(:diff_lines_for_serializer)
@highlighted_diff_lines = value
end
# Array of Gitlab::Diff::Line objects
def diff_lines
......@@ -314,19 +317,21 @@ module Gitlab
# This adds the bottom match line to the array if needed. It contains
# the data to load more context lines.
def diff_lines_for_serializer
lines = highlighted_diff_lines
strong_memoize(:diff_lines_for_serializer) do
lines = highlighted_diff_lines
return if lines.empty?
return if blob.nil?
next if lines.empty?
next if blob.nil?
last_line = lines.last
last_line = lines.last
if last_line.new_pos < total_blob_lines(blob) && !deleted_file?
match_line = Gitlab::Diff::Line.new("", 'match', nil, last_line.old_pos, last_line.new_pos)
lines.push(match_line)
end
if last_line.new_pos < total_blob_lines(blob) && !deleted_file?
match_line = Gitlab::Diff::Line.new("", 'match', nil, last_line.old_pos, last_line.new_pos)
lines.push(match_line)
end
lines
lines
end
end
def fully_expanded?
......
......@@ -89,7 +89,7 @@ module Gitlab
return if project.repository.branch_exists?(source_branch)
project.repository.add_branch(project.owner, source_branch, pull_request.source_branch_sha)
project.repository.add_branch(project.creator, source_branch, pull_request.source_branch_sha)
rescue Gitlab::Git::CommandError => e
Gitlab::Sentry.track_acceptable_exception(e,
extra: {
......
......@@ -5,6 +5,7 @@ module Gitlab
module Importer
class RepositoryImporter
include Gitlab::ShellAdapter
include Gitlab::Utils::StrongMemoize
attr_reader :project, :client, :wiki_formatter
......@@ -17,7 +18,7 @@ module Gitlab
# Returns true if we should import the wiki for the project.
# rubocop: disable CodeReuse/ActiveRecord
def import_wiki?
client.repository(project.import_source)&.has_wiki &&
client_repository&.has_wiki &&
!project.wiki_repository_exists? &&
Gitlab::GitalyClient::RemoteService.exists?(wiki_url)
end
......@@ -52,6 +53,7 @@ module Gitlab
refmap = Gitlab::GithubImport.refmap
project.repository.fetch_as_mirror(project.import_url, refmap: refmap, forced: true, remote_name: 'github')
project.change_head(default_branch) if default_branch
true
rescue Gitlab::Git::Repository::NoRepository, Gitlab::Shell::Error => e
fail_import("Failed to import the repository: #{e.message}")
......@@ -82,6 +84,18 @@ module Gitlab
project.import_state.mark_as_failed(message)
false
end
private
def default_branch
client_repository&.default_branch
end
def client_repository
strong_memoize(:client_repository) do
client.repository(project.import_source)
end
end
end
end
end
......
......@@ -108,64 +108,86 @@ describe Gitlab::Checks::BranchCheck do
end
context 'protected branch creation feature is enabled' do
context 'user is not allowed to create protected branches' do
context 'user can push to branch' do
before do
allow(user_access)
.to receive(:can_merge_to_branch?)
.to receive(:can_push_to_branch?)
.with('feature')
.and_return(false)
.and_return(true)
end
it 'raises an error' do
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to create protected branches on this project.')
it 'does not raise an error' do
expect { subject.validate! }.not_to raise_error
end
end
context 'user is allowed to create protected branches' do
context 'user cannot push to branch' do
before do
allow(user_access)
.to receive(:can_merge_to_branch?)
.to receive(:can_push_to_branch?)
.with('feature')
.and_return(true)
allow(project.repository)
.to receive(:branch_names_contains_sha)
.with(newrev)
.and_return(['branch'])
.and_return(false)
end
context "newrev isn't in any protected branches" do
context 'user cannot merge to branch' do
before do
allow(ProtectedBranch)
.to receive(:any_protected?)
.with(project, ['branch'])
allow(user_access)
.to receive(:can_merge_to_branch?)
.with('feature')
.and_return(false)
end
it 'raises an error' do
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only use an existing protected branch ref as the basis of a new protected branch.')
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to create protected branches on this project.')
end
end
context 'newrev is included in a protected branch' do
context 'user can merge to branch' do
before do
allow(ProtectedBranch)
.to receive(:any_protected?)
.with(project, ['branch'])
allow(user_access)
.to receive(:can_merge_to_branch?)
.with('feature')
.and_return(true)
allow(project.repository)
.to receive(:branch_names_contains_sha)
.with(newrev)
.and_return(['branch'])
end
context 'via web interface' do
let(:protocol) { 'web' }
context "newrev isn't in any protected branches" do
before do
allow(ProtectedBranch)
.to receive(:any_protected?)
.with(project, ['branch'])
.and_return(false)
end
it 'allows branch creation' do
expect { subject.validate! }.not_to raise_error
it 'raises an error' do
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only use an existing protected branch ref as the basis of a new protected branch.')
end
end
context 'via SSH' do
it 'raises an error' do
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only create protected branches using the web interface and API.')
context 'newrev is included in a protected branch' do
before do
allow(ProtectedBranch)
.to receive(:any_protected?)
.with(project, ['branch'])
.and_return(true)
end
context 'via web interface' do
let(:protocol) { 'web' }
it 'allows branch creation' do
expect { subject.validate! }.not_to raise_error
end
end
context 'via SSH' do
it 'raises an error' do
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only create protected branches using the web interface and API.')
end
end
end
end
......
......@@ -72,6 +72,13 @@ describe Gitlab::Diff::File do
expect(diff_file.diff_lines_for_serializer.last.type).to eq('match')
end
context 'when called multiple times' do
it 'only adds bottom match line once' do
expect(diff_file.diff_lines_for_serializer.size).to eq(31)
expect(diff_file.diff_lines_for_serializer.size).to eq(31)
end
end
context 'when deleted' do
let(:commit) { project.commit('d59c60028b053793cecfb4022de34602e1a9218e') }
let(:diff_file) { commit.diffs.diff_file_with_old_path('files/js/commit.js.coffee') }
......
......@@ -273,10 +273,10 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
mr.state = 'opened'
mr.save
# Ensure the project owner is creating the branches because the
# Ensure the project creator is creating the branches because the
# merge request author may not have access to push to this
# repository.
allow(project.repository).to receive(:add_branch).with(project.owner, anything, anything).and_call_original
# repository. The project owner may also be a group.
allow(project.repository).to receive(:add_branch).with(project.creator, anything, anything).and_call_original
importer.insert_git_data(mr, exists)
......
......@@ -179,6 +179,17 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
describe '#import_repository' do
it 'imports the repository' do
repo = double(:repo, default_branch: 'develop')
expect(client)
.to receive(:repository)
.with('foo/bar')
.and_return(repo)
expect(project)
.to receive(:change_head)
.with('develop')
expect(project)
.to receive(:ensure_repository)
......
......@@ -146,6 +146,18 @@ describe Gitlab::JsonCache do
expect(cache.read(key, BroadcastMessage)).to be_nil
end
it 'gracefully handles excluded fields from attributes during serialization' do
allow(backend).to receive(:read)
.with(expanded_key)
.and_return(broadcast_message.attributes.except("message_html").to_json)
result = cache.read(key, BroadcastMessage)
BroadcastMessage.cached_markdown_fields.html_fields.each do |field|
expect(result.public_send(field)).to be_nil
end
end
end
context 'when the cached value is an array' do
......@@ -327,7 +339,9 @@ describe Gitlab::JsonCache do
.with(expanded_key)
.and_return('{')
expect(cache.read(key, BroadcastMessage)).to be_nil
result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
expect(result).to eq 'block result'
end
it 'gracefully handles an empty hash' do
......@@ -335,7 +349,7 @@ describe Gitlab::JsonCache do
.with(expanded_key)
.and_return('{}')
expect(cache.read(key, BroadcastMessage)).to be_a(BroadcastMessage)
expect(cache.fetch(key, as: BroadcastMessage)).to be_a(BroadcastMessage)
end
it 'gracefully handles unknown attributes' do
......@@ -343,17 +357,19 @@ describe Gitlab::JsonCache do
.with(expanded_key)
.and_return(broadcast_message.attributes.merge(unknown_attribute: 1).to_json)
expect(cache.read(key, BroadcastMessage)).to be_nil
result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
expect(result).to eq 'block result'
end
it 'gracefully handles excluded fields from attributes during serialization' do
backend.write(expanded_key, broadcast_message.to_json)
allow(backend).to receive(:read)
.with(expanded_key)
.and_return(broadcast_message.attributes.except("message_html").to_json)
result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
excluded_fields = BroadcastMessage.cached_markdown_fields.html_fields
(excluded_fields + ['cached_markdown_version']).each do |field|
BroadcastMessage.cached_markdown_fields.html_fields.each do |field|
expect(result.public_send(field)).to be_nil
end
end
......
......@@ -95,6 +95,12 @@ describe BroadcastMessage do
end
end
describe '#attributes' do
it 'includes message_html field' do
expect(subject.attributes.keys).to include("cached_markdown_version", "message_html")
end
end
describe '#active?' do
it 'is truthy when started and not ended' do
message = build(:broadcast_message)
......
......@@ -23,6 +23,7 @@ describe CacheMarkdownField do
include CacheMarkdownField
cache_markdown_field :foo
cache_markdown_field :baz, pipeline: :single_line
cache_markdown_field :zoo, whitelisted: true
def self.add_attr(name)
self.attribute_names += [name]
......@@ -35,7 +36,7 @@ describe CacheMarkdownField do
add_attr :cached_markdown_version
[:foo, :foo_html, :bar, :baz, :baz_html].each do |name|
[:foo, :foo_html, :bar, :baz, :baz_html, :zoo, :zoo_html].each do |name|
add_attr(name)
end
......@@ -84,8 +85,8 @@ describe CacheMarkdownField do
end
describe '.attributes' do
it 'excludes cache attributes' do
expect(thing.attributes.keys.sort).to eq(%w[bar baz foo])
it 'excludes cache attributes that is blacklisted by default' do
expect(thing.attributes.keys.sort).to eq(%w[bar baz cached_markdown_version foo zoo zoo_html])
end
end
......@@ -297,7 +298,12 @@ describe CacheMarkdownField do
it 'saves the changes using #update_columns' do
expect(thing).to receive(:persisted?).and_return(true)
expect(thing).to receive(:update_columns)
.with("foo_html" => updated_html, "baz_html" => "", "cached_markdown_version" => cache_version)
.with(
"foo_html" => updated_html,
"baz_html" => "",
"zoo_html" => "",
"cached_markdown_version" => cache_version
)
thing.refresh_markdown_cache!
end
......
......@@ -2388,6 +2388,12 @@ describe Project do
project.change_head(project.default_branch)
end
it 'updates commit count' do
expect(ProjectCacheWorker).to receive(:perform_async).with(project.id, [], [:commit_count])
project.change_head(project.default_branch)
end
it 'copies the gitattributes' do
expect(project.repository).to receive(:copy_gitattributes).with(project.default_branch)
project.change_head(project.default_branch)
......
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