Commit b0314140 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-06-14

# Conflicts:
#	app/assets/stylesheets/framework/markdown_area.scss
#	app/assets/stylesheets/pages/merge_requests.scss
#	doc/user/markdown.md

[ci skip]
parents 636b7cab c4a3587c
...@@ -119,7 +119,7 @@ const gfmRules = { ...@@ -119,7 +119,7 @@ const gfmRules = {
return el.outerHTML; return el.outerHTML;
}, },
'dl'(el, text) { 'dl'(el, text) {
let lines = text.trim().split('\n'); let lines = text.replace(/\n\n/g, '\n').trim().split('\n');
// Add two spaces to the front of subsequent list items lines, // Add two spaces to the front of subsequent list items lines,
// or leave the line entirely blank. // or leave the line entirely blank.
lines = lines.map((l) => { lines = lines.map((l) => {
...@@ -129,9 +129,13 @@ const gfmRules = { ...@@ -129,9 +129,13 @@ const gfmRules = {
return ` ${line}`; return ` ${line}`;
}); });
return `<dl>\n${lines.join('\n')}\n</dl>`; return `<dl>\n${lines.join('\n')}\n</dl>\n`;
}, },
'sub, dt, dd, kbd, q, samp, var, ruby, rt, rp, abbr, summary, details'(el, text) { 'dt, dd, summary, details'(el, text) {
const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>\n`;
},
'sup, sub, kbd, q, samp, var, ruby, rt, rp, abbr'(el, text) {
const tag = el.nodeName.toLowerCase(); const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>`; return `<${tag}>${text}</${tag}>`;
}, },
...@@ -215,22 +219,22 @@ const gfmRules = { ...@@ -215,22 +219,22 @@ const gfmRules = {
return text.replace(/^- /mg, '1. '); return text.replace(/^- /mg, '1. ');
}, },
'h1'(el, text) { 'h1'(el, text) {
return `# ${text.trim()}`; return `# ${text.trim()}\n`;
}, },
'h2'(el, text) { 'h2'(el, text) {
return `## ${text.trim()}`; return `## ${text.trim()}\n`;
}, },
'h3'(el, text) { 'h3'(el, text) {
return `### ${text.trim()}`; return `### ${text.trim()}\n`;
}, },
'h4'(el, text) { 'h4'(el, text) {
return `#### ${text.trim()}`; return `#### ${text.trim()}\n`;
}, },
'h5'(el, text) { 'h5'(el, text) {
return `##### ${text.trim()}`; return `##### ${text.trim()}\n`;
}, },
'h6'(el, text) { 'h6'(el, text) {
return `###### ${text.trim()}`; return `###### ${text.trim()}\n`;
}, },
'strong'(el, text) { 'strong'(el, text) {
return `**${text}**`; return `**${text}**`;
...@@ -241,11 +245,13 @@ const gfmRules = { ...@@ -241,11 +245,13 @@ const gfmRules = {
'del'(el, text) { 'del'(el, text) {
return `~~${text}~~`; return `~~${text}~~`;
}, },
'sup'(el, text) {
return `^${text}`;
},
'hr'(el) { 'hr'(el) {
return '-----'; // extra leading \n is to ensure that there is a blank line between
// a list followed by an hr, otherwise this breaks old redcarpet rendering
return '\n-----\n';
},
'p'(el, text) {
return `${text.trim()}\n`;
}, },
'table'(el) { 'table'(el) {
const theadEl = el.querySelector('thead'); const theadEl = el.querySelector('thead');
...@@ -263,7 +269,9 @@ const gfmRules = { ...@@ -263,7 +269,9 @@ const gfmRules = {
let before = ''; let before = '';
let after = ''; let after = '';
switch (cell.style.textAlign) { const alignment = cell.align || cell.style.textAlign;
switch (alignment) {
case 'center': case 'center':
before = ':'; before = ':';
after = ':'; after = ':';
......
...@@ -66,8 +66,14 @@ export default class CreateMergeRequestDropdown { ...@@ -66,8 +66,14 @@ export default class CreateMergeRequestDropdown {
} }
bindEvents() { bindEvents() {
this.createMergeRequestButton.addEventListener('click', this.onClickCreateMergeRequestButton.bind(this)); this.createMergeRequestButton.addEventListener(
this.createTargetButton.addEventListener('click', this.onClickCreateMergeRequestButton.bind(this)); 'click',
this.onClickCreateMergeRequestButton.bind(this),
);
this.createTargetButton.addEventListener(
'click',
this.onClickCreateMergeRequestButton.bind(this),
);
this.branchInput.addEventListener('keyup', this.onChangeInput.bind(this)); this.branchInput.addEventListener('keyup', this.onChangeInput.bind(this));
this.dropdownToggle.addEventListener('click', this.onClickSetFocusOnBranchNameInput.bind(this)); this.dropdownToggle.addEventListener('click', this.onClickSetFocusOnBranchNameInput.bind(this));
this.refInput.addEventListener('keyup', this.onChangeInput.bind(this)); this.refInput.addEventListener('keyup', this.onChangeInput.bind(this));
...@@ -77,7 +83,8 @@ export default class CreateMergeRequestDropdown { ...@@ -77,7 +83,8 @@ export default class CreateMergeRequestDropdown {
checkAbilityToCreateBranch() { checkAbilityToCreateBranch() {
this.setUnavailableButtonState(); this.setUnavailableButtonState();
axios.get(this.canCreatePath) axios
.get(this.canCreatePath)
.then(({ data }) => { .then(({ data }) => {
this.setUnavailableButtonState(false); this.setUnavailableButtonState(false);
...@@ -105,7 +112,8 @@ export default class CreateMergeRequestDropdown { ...@@ -105,7 +112,8 @@ export default class CreateMergeRequestDropdown {
createBranch() { createBranch() {
this.isCreatingBranch = true; this.isCreatingBranch = true;
return axios.post(this.createBranchPath) return axios
.post(this.createBranchPath)
.then(({ data }) => { .then(({ data }) => {
this.branchCreated = true; this.branchCreated = true;
window.location.href = data.url; window.location.href = data.url;
...@@ -116,7 +124,8 @@ export default class CreateMergeRequestDropdown { ...@@ -116,7 +124,8 @@ export default class CreateMergeRequestDropdown {
createMergeRequest() { createMergeRequest() {
this.isCreatingMergeRequest = true; this.isCreatingMergeRequest = true;
return axios.post(this.createMrPath) return axios
.post(this.createMrPath)
.then(({ data }) => { .then(({ data }) => {
this.mergeRequestCreated = true; this.mergeRequestCreated = true;
window.location.href = data.url; window.location.href = data.url;
...@@ -195,7 +204,8 @@ export default class CreateMergeRequestDropdown { ...@@ -195,7 +204,8 @@ export default class CreateMergeRequestDropdown {
getRef(ref, target = 'all') { getRef(ref, target = 'all') {
if (!ref) return false; if (!ref) return false;
return axios.get(this.refsPath + ref) return axios
.get(`${this.refsPath}${encodeURIComponent(ref)}`)
.then(({ data }) => { .then(({ data }) => {
const branches = data[Object.keys(data)[0]]; const branches = data[Object.keys(data)[0]];
const tags = data[Object.keys(data)[1]]; const tags = data[Object.keys(data)[1]];
...@@ -204,7 +214,8 @@ export default class CreateMergeRequestDropdown { ...@@ -204,7 +214,8 @@ export default class CreateMergeRequestDropdown {
if (target === 'branch') { if (target === 'branch') {
result = CreateMergeRequestDropdown.findByValue(branches, ref); result = CreateMergeRequestDropdown.findByValue(branches, ref);
} else { } else {
result = CreateMergeRequestDropdown.findByValue(branches, ref, true) || result =
CreateMergeRequestDropdown.findByValue(branches, ref, true) ||
CreateMergeRequestDropdown.findByValue(tags, ref, true); CreateMergeRequestDropdown.findByValue(tags, ref, true);
this.suggestedRef = result; this.suggestedRef = result;
} }
...@@ -255,11 +266,13 @@ export default class CreateMergeRequestDropdown { ...@@ -255,11 +266,13 @@ export default class CreateMergeRequestDropdown {
} }
isBusy() { isBusy() {
return this.isCreatingMergeRequest || return (
this.isCreatingMergeRequest ||
this.mergeRequestCreated || this.mergeRequestCreated ||
this.isCreatingBranch || this.isCreatingBranch ||
this.branchCreated || this.branchCreated ||
this.isGettingRef; this.isGettingRef
);
} }
onChangeInput(event) { onChangeInput(event) {
...@@ -271,7 +284,8 @@ export default class CreateMergeRequestDropdown { ...@@ -271,7 +284,8 @@ export default class CreateMergeRequestDropdown {
value = this.branchInput.value; value = this.branchInput.value;
} else if (event.target === this.refInput) { } else if (event.target === this.refInput) {
target = 'ref'; target = 'ref';
value = event.target.value.slice(0, event.target.selectionStart) + value =
event.target.value.slice(0, event.target.selectionStart) +
event.target.value.slice(event.target.selectionEnd); event.target.value.slice(event.target.selectionEnd);
} else { } else {
return false; return false;
...@@ -396,7 +410,8 @@ export default class CreateMergeRequestDropdown { ...@@ -396,7 +410,8 @@ export default class CreateMergeRequestDropdown {
showNotAvailableMessage(target) { showNotAvailableMessage(target) {
const { input, message } = this.getTargetData(target); const { input, message } = this.getTargetData(target);
const text = target === 'branch' ? __('Branch is already taken') : __('Source is not available'); const text =
target === 'branch' ? __('Branch is already taken') : __('Source is not available');
this.removeMessage(target); this.removeMessage(target);
input.classList.add('gl-field-error-outline'); input.classList.add('gl-field-error-outline');
...@@ -459,11 +474,15 @@ export default class CreateMergeRequestDropdown { ...@@ -459,11 +474,15 @@ export default class CreateMergeRequestDropdown {
// target - 'branch' or 'ref' // target - 'branch' or 'ref'
// ref - string - the new value to use as branch or ref // ref - string - the new value to use as branch or ref
updateCreatePaths(target, ref) { updateCreatePaths(target, ref) {
const pathReplacement = `$1${ref}`; const pathReplacement = `$1${encodeURIComponent(ref)}`;
this.createBranchPath = this.createBranchPath.replace(this.regexps[target].createBranchPath, this.createBranchPath = this.createBranchPath.replace(
pathReplacement); this.regexps[target].createBranchPath,
this.createMrPath = this.createMrPath.replace(this.regexps[target].createMrPath, pathReplacement,
pathReplacement); );
this.createMrPath = this.createMrPath.replace(
this.regexps[target].createMrPath,
pathReplacement,
);
} }
} }
...@@ -94,7 +94,7 @@ export default { ...@@ -94,7 +94,7 @@ export default {
<p class="append-bottom-0"> <p class="append-bottom-0">
{{ __('Found errors in your .gitlab-ci.yml:') }} {{ __('Found errors in your .gitlab-ci.yml:') }}
</p> </p>
<p class="append-bottom-0"> <p class="append-bottom-0 break-word">
{{ latestPipeline.yamlError }} {{ latestPipeline.yamlError }}
</p> </p>
<p <p
......
...@@ -362,7 +362,7 @@ export default class MergeRequestTabs { ...@@ -362,7 +362,7 @@ export default class MergeRequestTabs {
// //
// status - Boolean, true to show, false to hide // status - Boolean, true to show, false to hide
toggleLoading(status) { toggleLoading(status) {
$('.mr-loading-status .loading').toggleClass('hidden', !status); $('.mr-loading-status .loading').toggleClass('hide', !status);
} }
diffViewType() { diffViewType() {
......
...@@ -61,10 +61,13 @@ ...@@ -61,10 +61,13 @@
padding-top: 0; padding-top: 0;
line-height: 19px; line-height: 19px;
<<<<<<< HEAD
&.btn.btn-sm { &.btn.btn-sm {
padding: 2px 5px; padding: 2px 5px;
} }
=======
>>>>>>> upstream/master
&:focus { &:focus {
margin-top: -10px; margin-top: -10px;
padding-top: 10px; padding-top: 10px;
......
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
overflow-x: scroll; overflow-x: scroll;
white-space: nowrap; white-space: nowrap;
min-height: 200px; min-height: 200px;
display: flex;
@include media-breakpoint-only(sm) { @include media-breakpoint-only(sm) {
height: calc(100vh - #{$issue-board-list-difference-sm}); height: calc(100vh - #{$issue-board-list-difference-sm});
...@@ -147,17 +148,15 @@ ...@@ -147,17 +148,15 @@
.board { .board {
display: inline-block; display: inline-block;
width: calc(85vw - 15px); flex: 1;
min-width: 300px;
max-width: 400px;
height: 100%; height: 100%;
padding-right: ($gl-padding / 2); padding-right: ($gl-padding / 2);
padding-left: ($gl-padding / 2); padding-left: ($gl-padding / 2);
white-space: normal; white-space: normal;
vertical-align: top; vertical-align: top;
@include media-breakpoint-up(sm) {
width: 400px;
}
&.is-expandable { &.is-expandable {
.board-header { .board-header {
cursor: pointer; cursor: pointer;
...@@ -165,6 +164,8 @@ ...@@ -165,6 +164,8 @@
} }
&.is-collapsed { &.is-collapsed {
flex: none;
min-width: 0;
width: 50px; width: 50px;
.board-header { .board-header {
......
...@@ -51,12 +51,15 @@ ...@@ -51,12 +51,15 @@
opacity: 0.3; opacity: 0.3;
} }
<<<<<<< HEAD
&.btn-sm { &.btn-sm {
line-height: 1; line-height: 1;
padding: 5px 10px; padding: 5px 10px;
margin-top: 1px; margin-top: 1px;
} }
=======
>>>>>>> upstream/master
&.dropdown-toggle { &.dropdown-toggle {
.fa { .fa {
color: inherit; color: inherit;
......
...@@ -54,7 +54,10 @@ class SnippetsFinder < UnionFinder ...@@ -54,7 +54,10 @@ class SnippetsFinder < UnionFinder
end end
def authorized_snippets def authorized_snippets
Snippet.where(feature_available_projects.or(not_project_related)) # This query was intentionally converted to a raw one to get it work in Rails 5.0.
# In Rails 5.0 and 5.1 there's a bug: https://github.com/rails/arel/issues/531
# Please convert it back when on rails 5.2 as it works again as expected since 5.2.
Snippet.where("#{feature_available_projects} OR #{not_project_related}")
.public_or_visible_to_user(current_user) .public_or_visible_to_user(current_user)
end end
...@@ -86,18 +89,20 @@ class SnippetsFinder < UnionFinder ...@@ -86,18 +89,20 @@ class SnippetsFinder < UnionFinder
def feature_available_projects def feature_available_projects
# Don't return any project related snippets if the user cannot read cross project # Don't return any project related snippets if the user cannot read cross project
return table[:id].eq(nil) unless Ability.allowed?(current_user, :read_cross_project) return table[:id].eq(nil).to_sql unless Ability.allowed?(current_user, :read_cross_project)
projects = projects_for_user do |part| projects = projects_for_user do |part|
part.with_feature_available_for_user(:snippets, current_user) part.with_feature_available_for_user(:snippets, current_user)
end.select(:id) end.select(:id)
arel_query = Arel::Nodes::SqlLiteral.new(projects.to_sql) # This query was intentionally converted to a raw one to get it work in Rails 5.0.
table[:project_id].in(arel_query) # In Rails 5.0 and 5.1 there's a bug: https://github.com/rails/arel/issues/531
# Please convert it back when on rails 5.2 as it works again as expected since 5.2.
"snippets.project_id IN (#{projects.to_sql})"
end end
def not_project_related def not_project_related
table[:project_id].eq(nil) table[:project_id].eq(nil).to_sql
end end
def table def table
......
...@@ -173,11 +173,12 @@ module ProjectsHelper ...@@ -173,11 +173,12 @@ module ProjectsHelper
key = [ key = [
project.route.cache_key, project.route.cache_key,
project.cache_key, project.cache_key,
project.last_activity_date,
controller.controller_name, controller.controller_name,
controller.action_name, controller.action_name,
Gitlab::CurrentSettings.cache_key, Gitlab::CurrentSettings.cache_key,
"cross-project:#{can?(current_user, :read_cross_project)}", "cross-project:#{can?(current_user, :read_cross_project)}",
'v2.5' 'v2.6'
] ]
key << pipeline_status_cache_key(project.pipeline_status) if project.pipeline_status.has_status? key << pipeline_status_cache_key(project.pipeline_status) if project.pipeline_status.has_status?
......
...@@ -114,7 +114,7 @@ module CacheMarkdownField ...@@ -114,7 +114,7 @@ module CacheMarkdownField
end end
def latest_cached_markdown_version def latest_cached_markdown_version
return CacheMarkdownField::CACHE_REDCARPET_VERSION unless cached_markdown_version return CacheMarkdownField::CACHE_COMMONMARK_VERSION unless cached_markdown_version
if cached_markdown_version < CacheMarkdownField::CACHE_COMMONMARK_VERSION_START if cached_markdown_version < CacheMarkdownField::CACHE_COMMONMARK_VERSION_START
CacheMarkdownField::CACHE_REDCARPET_VERSION CacheMarkdownField::CACHE_REDCARPET_VERSION
......
...@@ -43,13 +43,18 @@ class GemnasiumService < Service ...@@ -43,13 +43,18 @@ class GemnasiumService < Service
def execute(data) def execute(data)
return unless supported_events.include?(data[:object_kind]) return unless supported_events.include?(data[:object_kind])
# Gitaly: this class will be removed https://gitlab.com/gitlab-org/gitlab-ee/issues/6010
repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.path_to_repo
end
Gemnasium::GitlabService.execute( Gemnasium::GitlabService.execute(
ref: data[:ref], ref: data[:ref],
before: data[:before], before: data[:before],
after: data[:after], after: data[:after],
token: token, token: token,
api_key: api_key, api_key: api_key,
repo: project.repository.path_to_repo # Gitaly: fixed by https://gitlab.com/gitlab-org/security-products/gemnasium-migration/issues/9 repo: repo_path
) )
end end
end end
...@@ -44,14 +44,14 @@ ...@@ -44,14 +44,14 @@
.git-empty .git-empty
%fieldset %fieldset
%h5 Git global setup %h5 Git global setup
%pre.card.bg-light %pre.bg-light
:preserve :preserve
git config --global user.name "#{h git_user_name}" git config --global user.name "#{h git_user_name}"
git config --global user.email "#{h git_user_email}" git config --global user.email "#{h git_user_email}"
%fieldset %fieldset
%h5 Create a new repository %h5 Create a new repository
%pre.card.bg-light %pre.bg-light
:preserve :preserve
git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')} git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
cd #{h @project.path} cd #{h @project.path}
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
%fieldset %fieldset
%h5 Existing folder %h5 Existing folder
%pre.card.bg-light %pre.bg-light
:preserve :preserve
cd existing_folder cd existing_folder
git init git init
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
%fieldset %fieldset
%h5 Existing Git repository %h5 Existing Git repository
%pre.card.bg-light %pre.bg-light
:preserve :preserve
cd existing_repo cd existing_repo
git remote rename origin old-origin git remote rename origin old-origin
......
...@@ -6,12 +6,6 @@ class GitGarbageCollectWorker ...@@ -6,12 +6,6 @@ class GitGarbageCollectWorker
# Timeout set to 24h # Timeout set to 24h
LEASE_TIMEOUT = 86400 LEASE_TIMEOUT = 86400
GITALY_MIGRATED_TASKS = {
gc: :garbage_collect,
full_repack: :repack_full,
incremental_repack: :repack_incremental
}.freeze
def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil) def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil)
project = Project.find(project_id) project = Project.find(project_id)
active_uuid = get_lease_uuid(lease_key) active_uuid = get_lease_uuid(lease_key)
...@@ -27,21 +21,7 @@ class GitGarbageCollectWorker ...@@ -27,21 +21,7 @@ class GitGarbageCollectWorker
end end
task = task.to_sym task = task.to_sym
cmd = command(task)
gitaly_migrate(GITALY_MIGRATED_TASKS[task], status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_call(task, project.repository.raw_repository) gitaly_call(task, project.repository.raw_repository)
else
repo_path = project.repository.path_to_repo
description = "'#{cmd.join(' ')}' in #{repo_path}"
Gitlab::GitLogger.info(description)
output, status = Gitlab::Popen.popen(cmd, repo_path)
Gitlab::GitLogger.error("#{description} failed:\n#{output}") unless status.zero?
end
end
# Refresh the branch cache in case garbage collection caused a ref lookup to fail # Refresh the branch cache in case garbage collection caused a ref lookup to fail
flush_ref_caches(project) if task == :gc flush_ref_caches(project) if task == :gc
...@@ -82,21 +62,12 @@ class GitGarbageCollectWorker ...@@ -82,21 +62,12 @@ class GitGarbageCollectWorker
when :incremental_repack when :incremental_repack
client.repack_incremental client.repack_incremental
end end
end rescue GRPC::NotFound => e
Gitlab::GitLogger.error("#{method} failed:\nRepository not found")
def command(task) raise Gitlab::Git::Repository::NoRepository.new(e)
case task rescue GRPC::BadStatus => e
when :gc Gitlab::GitLogger.error("#{method} failed:\n#{e}")
git(write_bitmaps: bitmaps_enabled?) + %w[gc] raise Gitlab::Git::CommandError.new(e)
when :full_repack
git(write_bitmaps: bitmaps_enabled?) + %w[repack -A -d --pack-kept-objects]
when :incremental_repack
# Normal git repack fails when bitmaps are enabled. It is impossible to
# create a bitmap here anyway.
git(write_bitmaps: false) + %w[repack -d]
else
raise "Invalid gc task: #{task.inspect}"
end
end end
def flush_ref_caches(project) def flush_ref_caches(project)
...@@ -108,19 +79,4 @@ class GitGarbageCollectWorker ...@@ -108,19 +79,4 @@ class GitGarbageCollectWorker
def bitmaps_enabled? def bitmaps_enabled?
Gitlab::CurrentSettings.housekeeping_bitmaps_enabled Gitlab::CurrentSettings.housekeeping_bitmaps_enabled
end end
def git(write_bitmaps:)
config_value = write_bitmaps ? 'true' : 'false'
%W[git -c repack.writeBitmaps=#{config_value}]
end
def gitaly_migrate(method, status: Gitlab::GitalyClient::MigrationStatus::OPT_IN, &block)
Gitlab::GitalyClient.migrate(method, status: status, &block)
rescue GRPC::NotFound => e
Gitlab::GitLogger.error("#{method} failed:\nRepository not found")
raise Gitlab::Git::Repository::NoRepository.new(e)
rescue GRPC::BadStatus => e
Gitlab::GitLogger.error("#{method} failed:\n#{e}")
raise Gitlab::Git::CommandError.new(e)
end
end end
---
title: Fix fields for author & assignee in MR API docs.
merge_request: 19798
author: gfyoung
type: fixed
---
title: "[Rails5] Fix snippets_finder arel queries"
merge_request: 19796
author: "@blackst0ne"
type: fixed
---
title: Use CommonMark syntax and rendering for new Markdown content
merge_request: 19331
author:
type: added
---
title: 'Remove incorrect CI doc re: PowerShell'
merge_request: 19622
author: gfyoung
type: fixed
---
title: Rails5 fix stack level too deep
merge_request: 19762
author: Jasper Maes
type: fixed
---
title: 'Rails5 ActionController::ParameterMissing: param is missing or the value is
empty: application_setting'
merge_request: 19763
author: Jasper Maes
type: fixed
---
title: Rails5 fix no implicit conversion of Hash into String. ActionController::Parameters
no longer returns an hash in Rails 5
merge_request: 19792
author: Jasper Maes
type: fixed
---
title: Invalidate cache with project details when repository is updated
merge_request: 19774
author:
type: fixed
---
title: Flex issue board columns
merge_request: 19250
author: Roman Rosluk
type: changed
---
title: Fix branch name encoding for dropdown on issue page
merge_request: 19634
author:
type: fixed
...@@ -12,8 +12,10 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration ...@@ -12,8 +12,10 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
end end
def repository_storage_path def repository_storage_path
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab.config.repositories.storages[repository_storage].legacy_disk_path Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
end end
end
def repository_path def repository_path
# TODO: review if the change from Legacy storage needs to reflect here as well. # TODO: review if the change from Legacy storage needs to reflect here as well.
......
...@@ -64,8 +64,10 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration ...@@ -64,8 +64,10 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
# we rename suffix instead of removing it # we rename suffix instead of removing it
path = path.sub(/\.git\z/, '_git') path = path.sub(/\.git\z/, '_git')
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
check_routes(path.dup, 0, path) check_routes(path.dup, 0, path)
end end
end
def check_routes(base, counter, path) def check_routes(base, counter, path)
route_exists = route_exists?(path) route_exists = route_exists?(path)
......
...@@ -70,18 +70,18 @@ Parameters: ...@@ -70,18 +70,18 @@ Parameters:
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 2, "source_project_id": 2,
"target_project_id": 3, "target_project_id": 3,
...@@ -190,18 +190,18 @@ Parameters: ...@@ -190,18 +190,18 @@ Parameters:
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 2, "source_project_id": 2,
"target_project_id": 3, "target_project_id": 3,
...@@ -298,18 +298,18 @@ Parameters: ...@@ -298,18 +298,18 @@ Parameters:
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 2, "source_project_id": 2,
"target_project_id": 3, "target_project_id": 3,
...@@ -550,14 +550,16 @@ Parameters: ...@@ -550,14 +550,16 @@ Parameters:
"username": "jarrett", "username": "jarrett",
"id": 5, "id": 5,
"state": "active", "state": "active",
"avatar_url": "http://www.gravatar.com/avatar/b95567800f828948baf5f4160ebb2473?s=40&d=identicon" "avatar_url": "http://www.gravatar.com/avatar/b95567800f828948baf5f4160ebb2473?s=40&d=identicon",
"web_url" : "https://gitlab.example.com/jarrett"
}, },
"assignee": { "assignee": {
"name": "Administrator", "name": "Administrator",
"username": "root", "username": "root",
"id": 1, "id": 1,
"state": "active", "state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon" "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon",
"web_url" : "https://gitlab.example.com/root"
}, },
"source_project_id": 4, "source_project_id": 4,
"target_project_id": 4, "target_project_id": 4,
...@@ -681,18 +683,18 @@ order for it to take effect: ...@@ -681,18 +683,18 @@ order for it to take effect:
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 3, "source_project_id": 3,
"target_project_id": 4, "target_project_id": 4,
...@@ -774,18 +776,18 @@ Must include at least one non-required attribute from above. ...@@ -774,18 +776,18 @@ Must include at least one non-required attribute from above.
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 3, "source_project_id": 3,
"target_project_id": 4, "target_project_id": 4,
...@@ -884,18 +886,18 @@ Parameters: ...@@ -884,18 +886,18 @@ Parameters:
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 4, "source_project_id": 4,
"target_project_id": 4, "target_project_id": 4,
...@@ -964,18 +966,18 @@ Parameters: ...@@ -964,18 +966,18 @@ Parameters:
"author": { "author": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"assignee": { "assignee": {
"id": 1, "id": 1,
"username": "admin", "username": "admin",
"email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"state": "active", "state": "active",
"created_at": "2012-04-29T08:46:00Z" "avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
}, },
"source_project_id": 4, "source_project_id": 4,
"target_project_id": 4, "target_project_id": 4,
......
...@@ -799,16 +799,6 @@ cache: ...@@ -799,16 +799,6 @@ cache:
- binaries/ - binaries/
``` ```
If you use **Windows PowerShell** to run your shell scripts you need to replace
`$` with `$env:`:
```yaml
cache:
key: "$env:CI_COMMIT_REF_SLUG"
paths:
- binaries/
```
### `cache:untracked` ### `cache:untracked`
Set `untracked: true` to cache all files that are untracked in your Git Set `untracked: true` to cache all files that are untracked in your Git
......
...@@ -15,11 +15,11 @@ Would you like to contribute to GitLab University? Then please take a look at ou ...@@ -15,11 +15,11 @@ Would you like to contribute to GitLab University? Then please take a look at ou
The curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections. The curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections.
1. [GitLab Beginner](#beginner) 1. [GitLab Beginner](#1-gitlab-beginner)
1. [GitLab Intermediate](#intermediate) 1. [GitLab Intermediate](#2-gitlab-intermediate)
1. [GitLab Advanced](#advanced) 1. [GitLab Advanced](#3-gitlab-advanced)
1. [External Articles](#external) 1. [External Articles](#4-external-articles)
1. [Resources for GitLab Team Members](#team) 1. [Resources for GitLab Team Members](#5-resources-for-gitlab-team-members)
--- ---
...@@ -126,7 +126,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project ...@@ -126,7 +126,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw) 1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw)
1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc) 1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc)
2. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times) 2. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
1. See **[Integrations](#integrations)** for integrations with other CI services. 1. See **[Integrations](#39-integrations)** for integrations with other CI services.
#### 2.4. Workflow #### 2.4. Workflow
......
...@@ -24,7 +24,10 @@ You can use GFM in the following areas: ...@@ -24,7 +24,10 @@ You can use GFM in the following areas:
- snippets (the snippet must be named with a `.md` extension) - snippets (the snippet must be named with a `.md` extension)
- wiki pages - wiki pages
- markdown documents inside the repository (currently only rendered by Redcarpet) - markdown documents inside the repository (currently only rendered by Redcarpet)
<<<<<<< HEAD
- epics - epics
=======
>>>>>>> upstream/master
You can also use other rich text files in GitLab. You might have to install a You can also use other rich text files in GitLab. You might have to install a
dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
...@@ -581,7 +584,11 @@ Example: ...@@ -581,7 +584,11 @@ Example:
```no-highlight ```no-highlight
1. First ordered list item 1. First ordered list item
<<<<<<< HEAD
Second paragraph of first item. Second paragraph of first item.
=======
Second paragraph of first item.
>>>>>>> upstream/master
2. Another item 2. Another item
``` ```
......
...@@ -285,7 +285,8 @@ module API ...@@ -285,7 +285,8 @@ module API
attrs[key] = params_hash[key] attrs[key] = params_hash[key]
end end
end end
ActionController::Parameters.new(attrs).permit! permitted_attrs = ActionController::Parameters.new(attrs).permit!
Gitlab.rails5? ? permitted_attrs.to_h : permitted_attrs
end end
def filter_by_iid(items, iid) def filter_by_iid(items, iid)
......
...@@ -10,9 +10,7 @@ module API ...@@ -10,9 +10,7 @@ module API
detail "This feature was introduced in GitLab 11.0." detail "This feature was introduced in GitLab 11.0."
end end
post do post do
# Explicitly set CommonMark as markdown engine to use. context = { only_path: false }
# Remove this set when https://gitlab.com/gitlab-org/gitlab-ce/issues/43011 is done.
context = { markdown_engine: :common_mark, only_path: false }
if params[:project] if params[:project]
project = Project.find_by_full_path(params[:project]) project = Project.find_by_full_path(params[:project])
......
...@@ -14,7 +14,7 @@ module Banzai ...@@ -14,7 +14,7 @@ module Banzai
private private
DEFAULT_ENGINE = :redcarpet DEFAULT_ENGINE = :common_mark
def engine(engine_from_context) def engine(engine_from_context)
engine_from_context ||= DEFAULT_ENGINE engine_from_context ||= DEFAULT_ENGINE
......
...@@ -22,24 +22,9 @@ module Gitlab ...@@ -22,24 +22,9 @@ module Gitlab
private private
def load_blame def load_blame
raw_output = @repo.gitaly_migrate(:blame, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| output = encode_utf8(@repo.gitaly_commit_client.raw_blame(@sha, @path))
if is_enabled
load_blame_by_gitaly
else
load_blame_by_shelling_out
end
end
output = encode_utf8(raw_output)
process_raw_blame output
end
def load_blame_by_gitaly
@repo.gitaly_commit_client.raw_blame(@sha, @path)
end
def load_blame_by_shelling_out process_raw_blame(output)
@repo.shell_blame(@sha, @path)
end end
def process_raw_blame(output) def process_raw_blame(output)
......
...@@ -120,13 +120,11 @@ module Gitlab ...@@ -120,13 +120,11 @@ module Gitlab
# Default branch in the repository # Default branch in the repository
def root_ref def root_ref
@root_ref ||= gitaly_migrate(:root_ref, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_client.default_branch_name gitaly_ref_client.default_branch_name
else rescue GRPC::NotFound => e
discover_default_branch raise NoRepository.new(e.message)
end rescue GRPC::Unknown => e
end raise Gitlab::Git::CommandError.new(e.message)
end end
def rugged def rugged
...@@ -152,23 +150,15 @@ module Gitlab ...@@ -152,23 +150,15 @@ module Gitlab
# Returns an Array of branch names # Returns an Array of branch names
# sorted by name ASC # sorted by name ASC
def branch_names def branch_names
gitaly_migrate(:branch_names, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| wrapped_gitaly_errors do
if is_enabled
gitaly_ref_client.branch_names gitaly_ref_client.branch_names
else
branches.map(&:name)
end
end end
end end
# Returns an Array of Branches # Returns an Array of Branches
def branches def branches
gitaly_migrate(:branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| wrapped_gitaly_errors do
if is_enabled
gitaly_ref_client.branches gitaly_ref_client.branches
else
branches_filter
end
end end
end end
...@@ -200,12 +190,8 @@ module Gitlab ...@@ -200,12 +190,8 @@ module Gitlab
end end
def local_branches(sort_by: nil) def local_branches(sort_by: nil)
gitaly_migrate(:local_branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| wrapped_gitaly_errors do
if is_enabled
gitaly_ref_client.local_branches(sort_by: sort_by) gitaly_ref_client.local_branches(sort_by: sort_by)
else
branches_filter(filter: :local, sort_by: sort_by)
end
end end
end end
...@@ -245,18 +231,6 @@ module Gitlab ...@@ -245,18 +231,6 @@ module Gitlab
# This refs by default not visible in project page and not cloned to client side. # This refs by default not visible in project page and not cloned to client side.
alias_method :has_visible_content?, :has_local_branches? alias_method :has_visible_content?, :has_local_branches?
def has_local_branches_rugged?
rugged.branches.each(:local).any? do |ref|
begin
ref.name && ref.target # ensures the branch is valid
true
rescue Rugged::ReferenceError
false
end
end
end
# Returns the number of valid tags # Returns the number of valid tags
def tag_count def tag_count
gitaly_migrate(:tag_names) do |is_enabled| gitaly_migrate(:tag_names) do |is_enabled|
...@@ -270,12 +244,8 @@ module Gitlab ...@@ -270,12 +244,8 @@ module Gitlab
# Returns an Array of tag names # Returns an Array of tag names
def tag_names def tag_names
gitaly_migrate(:tag_names, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| wrapped_gitaly_errors do
if is_enabled
gitaly_ref_client.tag_names gitaly_ref_client.tag_names
else
rugged.tags.map { |t| t.name }
end
end end
end end
...@@ -283,12 +253,8 @@ module Gitlab ...@@ -283,12 +253,8 @@ module Gitlab
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/390 # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/390
def tags def tags
gitaly_migrate(:tags, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| wrapped_gitaly_errors do
if is_enabled gitaly_ref_client.tags
tags_from_gitaly
else
tags_from_rugged
end
end end
end end
...@@ -364,31 +330,6 @@ module Gitlab ...@@ -364,31 +330,6 @@ module Gitlab
end.map(&:name) end.map(&:name)
end end
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
# - If one branch is present, returns its name
# - If two or more branches are present, returns current HEAD or master or first branch
def discover_default_branch
names = branch_names
return if names.empty?
return names[0] if names.length == 1
if rugged_head
extracted_name = Ref.extract_branch_name(rugged_head.name)
return extracted_name if names.include?(extracted_name)
end
if names.include?('master')
'master'
else
names[0]
end
end
def rugged_head def rugged_head
rugged.head rugged.head
rescue Rugged::ReferenceError rescue Rugged::ReferenceError
...@@ -1457,6 +1398,16 @@ module Gitlab ...@@ -1457,6 +1398,16 @@ module Gitlab
raise CommandError.new(e) raise CommandError.new(e)
end end
def wrapped_gitaly_errors(&block)
yield block
rescue GRPC::NotFound => e
raise NoRepository.new(e)
rescue GRPC::InvalidArgument => e
raise ArgumentError.new(e)
rescue GRPC::BadStatus => e
raise CommandError.new(e)
end
def clean_stale_repository_files def clean_stale_repository_files
gitaly_migrate(:repository_cleanup, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| gitaly_migrate(:repository_cleanup, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
gitaly_repository_client.cleanup if is_enabled && exists? gitaly_repository_client.cleanup if is_enabled && exists?
...@@ -1620,12 +1571,8 @@ module Gitlab ...@@ -1620,12 +1571,8 @@ module Gitlab
private private
def uncached_has_local_branches? def uncached_has_local_branches?
gitaly_migrate(:has_local_branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| wrapped_gitaly_errors do
if is_enabled
gitaly_repository_client.has_local_branches? gitaly_repository_client.has_local_branches?
else
has_local_branches_rugged?
end
end end
end end
...@@ -1745,20 +1692,6 @@ module Gitlab ...@@ -1745,20 +1692,6 @@ module Gitlab
} }
end end
# Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'.
def branches_filter(filter: nil, sort_by: nil)
branches = rugged.branches.each(filter).map do |rugged_ref|
begin
target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target, target_commit)
rescue Rugged::ReferenceError
# Omit invalid branch
end
end.compact
sort_branches(branches, sort_by)
end
def git_merged_branch_names(branch_names, root_sha) def git_merged_branch_names(branch_names, root_sha)
git_arguments = git_arguments =
%W[branch --merged #{root_sha} %W[branch --merged #{root_sha}
...@@ -1970,37 +1903,11 @@ module Gitlab ...@@ -1970,37 +1903,11 @@ module Gitlab
end end
end end
def tags_from_rugged
rugged.references.each("refs/tags/*").map do |ref|
message = nil
if ref.target.is_a?(Rugged::Tag::Annotation)
tag_message = ref.target.message
if tag_message.respond_to?(:chomp)
message = tag_message.chomp
end
end
target_commit = Gitlab::Git::Commit.find(self, ref.target)
Gitlab::Git::Tag.new(self, {
name: ref.name,
target: ref.target,
target_commit: target_commit,
message: message
})
end.sort_by(&:name)
end
def last_commit_for_path_by_rugged(sha, path) def last_commit_for_path_by_rugged(sha, path)
sha = last_commit_id_for_path_by_shelling_out(sha, path) sha = last_commit_id_for_path_by_shelling_out(sha, path)
commit(sha) commit(sha)
end end
def tags_from_gitaly
gitaly_ref_client.tags
end
def size_by_shelling_out def size_by_shelling_out
popen(%w(du -sk), path).first.strip.to_i popen(%w(du -sk), path).first.strip.to_i
end end
......
...@@ -35,11 +35,6 @@ module Gitlab ...@@ -35,11 +35,6 @@ module Gitlab
MAXIMUM_GITALY_CALLS = 35 MAXIMUM_GITALY_CALLS = 35
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
# We have a mechanism to let GitLab automatically opt in to all Gitaly
# features. We want to be able to exclude some features from automatic
# opt-in. That is what EXPLICIT_OPT_IN_REQUIRED is for.
EXPLICIT_OPT_IN_REQUIRED = [Gitlab::GitalyClient::StorageSettings::DISK_ACCESS_DENIED_FLAG].freeze
MUTEX = Mutex.new MUTEX = Mutex.new
class << self class << self
...@@ -251,7 +246,7 @@ module Gitlab ...@@ -251,7 +246,7 @@ module Gitlab
when MigrationStatus::OPT_OUT when MigrationStatus::OPT_OUT
true true
when MigrationStatus::OPT_IN when MigrationStatus::OPT_IN
opt_into_all_features? && !EXPLICIT_OPT_IN_REQUIRED.include?(feature_name) opt_into_all_features? && !explicit_opt_in_required.include?(feature_name)
else else
false false
end end
...@@ -261,6 +256,13 @@ module Gitlab ...@@ -261,6 +256,13 @@ module Gitlab
false false
end end
# We have a mechanism to let GitLab automatically opt in to all Gitaly
# features. We want to be able to exclude some features from automatic
# opt-in. This function has an override in EE.
def self.explicit_opt_in_required
[]
end
# opt_into_all_features? returns true when the current environment # opt_into_all_features? returns true when the current environment
# is one in which we opt into features automatically # is one in which we opt into features automatically
def self.opt_into_all_features? def self.opt_into_all_features?
......
...@@ -5,6 +5,7 @@ module SystemCheck ...@@ -5,6 +5,7 @@ module SystemCheck
attr_accessor :orphans attr_accessor :orphans
def multi_check def multi_check
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab.config.repositories.storages.each do |storage_name, repository_storage| Gitlab.config.repositories.storages.each do |storage_name, repository_storage|
storage_path = repository_storage.legacy_disk_path storage_path = repository_storage.legacy_disk_path
...@@ -17,6 +18,7 @@ module SystemCheck ...@@ -17,6 +18,7 @@ module SystemCheck
print_orphans(orphans, storage_name) print_orphans(orphans, storage_name)
end end
end end
end
private private
......
...@@ -73,7 +73,7 @@ describe Admin::ApplicationSettingsController do ...@@ -73,7 +73,7 @@ describe Admin::ApplicationSettingsController do
end end
it 'updates the restricted_visibility_levels when empty array is passed' do it 'updates the restricted_visibility_levels when empty array is passed' do
put :update, application_setting: { restricted_visibility_levels: [] } put :update, application_setting: { restricted_visibility_levels: [""] }
expect(response).to redirect_to(admin_application_settings_path) expect(response).to redirect_to(admin_application_settings_path)
expect(ApplicationSetting.current.restricted_visibility_levels).to be_empty expect(ApplicationSetting.current.restricted_visibility_levels).to be_empty
......
...@@ -512,7 +512,7 @@ describe ApplicationController do ...@@ -512,7 +512,7 @@ describe ApplicationController do
context '422 errors' do context '422 errors' do
it 'logs a response with a string' do it 'logs a response with a string' do
response = spy(ActionDispatch::Response, status: 422, body: 'Hello world', content_type: 'application/json') response = spy(ActionDispatch::Response, status: 422, body: 'Hello world', content_type: 'application/json', cookies: {})
allow(controller).to receive(:response).and_return(response) allow(controller).to receive(:response).and_return(response)
get :index get :index
...@@ -521,7 +521,7 @@ describe ApplicationController do ...@@ -521,7 +521,7 @@ describe ApplicationController do
it 'logs a response with an array' do it 'logs a response with an array' do
body = ['I want', 'my hat back'] body = ['I want', 'my hat back']
response = spy(ActionDispatch::Response, status: 422, body: body, content_type: 'application/json') response = spy(ActionDispatch::Response, status: 422, body: body, content_type: 'application/json', cookies: {})
allow(controller).to receive(:response).and_return(response) allow(controller).to receive(:response).and_return(response)
get :index get :index
...@@ -529,7 +529,7 @@ describe ApplicationController do ...@@ -529,7 +529,7 @@ describe ApplicationController do
end end
it 'does not log a string with an empty body' do it 'does not log a string with an empty body' do
response = spy(ActionDispatch::Response, status: 422, body: nil, content_type: 'application/json') response = spy(ActionDispatch::Response, status: 422, body: nil, content_type: 'application/json', cookies: {})
allow(controller).to receive(:response).and_return(response) allow(controller).to receive(:response).and_return(response)
get :index get :index
...@@ -537,7 +537,7 @@ describe ApplicationController do ...@@ -537,7 +537,7 @@ describe ApplicationController do
end end
it 'does not log an HTML body' do it 'does not log an HTML body' do
response = spy(ActionDispatch::Response, status: 422, body: 'This is a test', content_type: 'application/html') response = spy(ActionDispatch::Response, status: 422, body: 'This is a test', content_type: 'application/html', cookies: {})
allow(controller).to receive(:response).and_return(response) allow(controller).to receive(:response).and_return(response)
get :index get :index
......
...@@ -319,16 +319,22 @@ describe ProjectsController do ...@@ -319,16 +319,22 @@ describe ProjectsController do
shared_examples_for 'updating a project' do shared_examples_for 'updating a project' do
context 'when only renaming a project path' do context 'when only renaming a project path' do
it "sets the repository to the right path after a rename" do it "sets the repository to the right path after a rename" do
original_repository_path = project.repository.path original_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.path
end
expect { update_project path: 'renamed_path' } expect { update_project path: 'renamed_path' }
.to change { project.reload.path } .to change { project.reload.path }
expect(project.path).to include 'renamed_path' expect(project.path).to include 'renamed_path'
assign_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
assigns(:repository).path
end
if project.hashed_storage?(:repository) if project.hashed_storage?(:repository)
expect(assigns(:repository).path).to eq(original_repository_path) expect(assign_repository_path).to eq(original_repository_path)
else else
expect(assigns(:repository).path).to include(project.path) expect(assign_repository_path).to include(project.path)
end end
expect(response).to have_gitlab_http_status(302) expect(response).to have_gitlab_http_status(302)
......
...@@ -502,6 +502,13 @@ describe 'Copy as GFM', :js do ...@@ -502,6 +502,13 @@ describe 'Copy as GFM', :js do
1. Numbered lists 1. Numbered lists
GFM GFM
# list item followed by an HR
<<-GFM.strip_heredoc,
- list item
-----
GFM
'# Heading', '# Heading',
'## Heading', '## Heading',
'### Heading', '### Heading',
...@@ -515,8 +522,6 @@ describe 'Copy as GFM', :js do ...@@ -515,8 +522,6 @@ describe 'Copy as GFM', :js do
'~~Strikethrough~~', '~~Strikethrough~~',
'2^2',
'-----', '-----',
# table # table
......
...@@ -53,7 +53,7 @@ describe 'GitLab Markdown', :aggregate_failures do ...@@ -53,7 +53,7 @@ describe 'GitLab Markdown', :aggregate_failures do
# Shared behavior that all pipelines should exhibit # Shared behavior that all pipelines should exhibit
shared_examples 'all pipelines' do shared_examples 'all pipelines' do
it 'includes Redcarpet extensions' do it 'includes extensions' do
aggregate_failures 'does not parse emphasis inside of words' do aggregate_failures 'does not parse emphasis inside of words' do
expect(doc.to_html).not_to match('foo<em>bar</em>baz') expect(doc.to_html).not_to match('foo<em>bar</em>baz')
end end
...@@ -81,10 +81,6 @@ describe 'GitLab Markdown', :aggregate_failures do ...@@ -81,10 +81,6 @@ describe 'GitLab Markdown', :aggregate_failures do
aggregate_failures 'parses strikethroughs' do aggregate_failures 'parses strikethroughs' do
expect(doc).to have_selector(%{del:contains("and this text doesn't")}) expect(doc).to have_selector(%{del:contains("and this text doesn't")})
end end
aggregate_failures 'parses superscript' do
expect(doc).to have_selector('sup', count: 2)
end
end end
it 'includes SanitizationFilter' do it 'includes SanitizationFilter' do
...@@ -132,16 +128,24 @@ describe 'GitLab Markdown', :aggregate_failures do ...@@ -132,16 +128,24 @@ describe 'GitLab Markdown', :aggregate_failures do
expect(doc).to have_selector('details summary:contains("collapsible")') expect(doc).to have_selector('details summary:contains("collapsible")')
end end
aggregate_failures 'permits style attribute in th elements' do aggregate_failures 'permits align attribute in th elements' do
expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' expect(doc.at_css('th:contains("Header")')['align']).to eq 'center'
expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' expect(doc.at_css('th:contains("Row")')['align']).to eq 'right'
expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' expect(doc.at_css('th:contains("Example")')['align']).to eq 'left'
end end
aggregate_failures 'permits style attribute in td elements' do aggregate_failures 'permits align attribute in td elements' do
expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' expect(doc.at_css('td:contains("Foo")')['align']).to eq 'center'
expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' expect(doc.at_css('td:contains("Bar")')['align']).to eq 'right'
expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' expect(doc.at_css('td:contains("Baz")')['align']).to eq 'left'
end
aggregate_failures 'permits superscript elements' do
expect(doc).to have_selector('sup', count: 2)
end
aggregate_failures 'permits subscript elements' do
expect(doc).to have_selector('sub', count: 3)
end end
aggregate_failures 'removes `rel` attribute from links' do aggregate_failures 'removes `rel` attribute from links' do
...@@ -323,6 +327,31 @@ describe 'GitLab Markdown', :aggregate_failures do ...@@ -323,6 +327,31 @@ describe 'GitLab Markdown', :aggregate_failures do
end end
end end
context 'Redcarpet documents' do
before do
allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
@html = markdown(@feat.raw_markdown)
end
it 'processes certain elements differently' do
aggregate_failures 'parses superscript' do
expect(doc).to have_selector('sup', count: 3)
end
aggregate_failures 'permits style attribute in th elements' do
expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center'
expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right'
expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left'
end
aggregate_failures 'permits style attribute in td elements' do
expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center'
expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right'
expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left'
end
end
end
# Fake a `current_user` helper # Fake a `current_user` helper
def current_user def current_user
@feat.user @feat.user
......
...@@ -31,11 +31,14 @@ describe "User comments on issue", :js do ...@@ -31,11 +31,14 @@ describe "User comments on issue", :js do
end end
it "adds comment with code block" do it "adds comment with code block" do
comment = "```\nCommand [1]: /usr/local/bin/git , see [text](doc/text)\n```" code_block_content = "Command [1]: /usr/local/bin/git , see [text](doc/text)"
comment = "```\n#{code_block_content}\n```"
add_note(comment) add_note(comment)
expect(page).to have_content(comment) wait_for_requests
expect(page.find('pre code').text).to eq code_block_content
end end
end end
......
...@@ -36,6 +36,19 @@ feature 'Task Lists' do ...@@ -36,6 +36,19 @@ feature 'Task Lists' do
MARKDOWN MARKDOWN
end end
let(:nested_tasks_markdown_redcarpet) do
<<-EOT.strip_heredoc
- [ ] Task a
- [x] Task a.1
- [ ] Task a.2
- [ ] Task b
1. [ ] Task 1
1. [ ] Task 1.1
1. [x] Task 1.2
EOT
end
let(:nested_tasks_markdown) do let(:nested_tasks_markdown) do
<<-EOT.strip_heredoc <<-EOT.strip_heredoc
- [ ] Task a - [ ] Task a
...@@ -141,13 +154,11 @@ feature 'Task Lists' do ...@@ -141,13 +154,11 @@ feature 'Task Lists' do
end end
end end
describe 'nested tasks', :js do shared_examples 'shared nested tasks' do
let(:issue) { create(:issue, description: nested_tasks_markdown, author: user, project: project) }
before do before do
allow(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
visit_issue(project, issue) visit_issue(project, issue)
end end
it 'renders' do it 'renders' do
expect(page).to have_selector('ul.task-list', count: 2) expect(page).to have_selector('ul.task-list', count: 2)
expect(page).to have_selector('li.task-list-item', count: 7) expect(page).to have_selector('li.task-list-item', count: 7)
...@@ -171,6 +182,30 @@ feature 'Task Lists' do ...@@ -171,6 +182,30 @@ feature 'Task Lists' do
expect(page).to have_content('marked the task Task 1.1 as complete') expect(page).to have_content('marked the task Task 1.1 as complete')
end end
end end
describe 'nested tasks', :js do
context 'with Redcarpet' do
let(:issue) { create(:issue, description: nested_tasks_markdown_redcarpet, author: user, project: project) }
before do
allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
visit_issue(project, issue)
end
it_behaves_like 'shared nested tasks'
end
context 'with CommonMark' do
let(:issue) { create(:issue, description: nested_tasks_markdown, author: user, project: project) }
before do
allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('CommonMark')
visit_issue(project, issue)
end
it_behaves_like 'shared nested tasks'
end
end
end end
describe 'for Notes' do describe 'for Notes' do
......
...@@ -43,8 +43,14 @@ This text says this, ~~and this text doesn't~~. ...@@ -43,8 +43,14 @@ This text says this, ~~and this text doesn't~~.
### Superscript ### Superscript
This is my 1^(st) time using superscript in Markdown. Now this is my This is my 1<sup>(st)</sup> time using superscript in Markdown. Now this is my
2^(nd). 2<sup>(nd)</sup>.
Redcarpet supports this superscript syntax ( x^2 ).
### Subscript
This (C<sub>6</sub>H<sub>12</sub>O<sub>6</sub>) is an example of subscripts in Markdown.
### Next step ### Next step
......
...@@ -298,7 +298,7 @@ describe MarkupHelper do ...@@ -298,7 +298,7 @@ describe MarkupHelper do
it 'preserves code color scheme' do it 'preserves code color scheme' do
object = create_object("```ruby\ndef test\n 'hello world'\nend\n```") object = create_object("```ruby\ndef test\n 'hello world'\nend\n```")
expected = "\n<pre class=\"code highlight js-syntax-highlight ruby\">" \ expected = "<pre class=\"code highlight js-syntax-highlight ruby\">" \
"<code><span class=\"line\"><span class=\"k\">def</span> <span class=\"nf\">test</span>...</span>\n" \ "<code><span class=\"line\"><span class=\"k\">def</span> <span class=\"nf\">test</span>...</span>\n" \
"</code></pre>" "</code></pre>"
......
...@@ -90,6 +90,10 @@ describe ProjectsHelper do ...@@ -90,6 +90,10 @@ describe ProjectsHelper do
expect(helper.project_list_cache_key(project)).to include(project.cache_key) expect(helper.project_list_cache_key(project)).to include(project.cache_key)
end end
it "includes the last activity date" do
expect(helper.project_list_cache_key(project)).to include(project.last_activity_date)
end
it "includes the controller name" do it "includes the controller name" do
expect(helper.controller).to receive(:controller_name).and_return("testcontroller") expect(helper.controller).to receive(:controller_name).and_return("testcontroller")
...@@ -285,7 +289,11 @@ describe ProjectsHelper do ...@@ -285,7 +289,11 @@ describe ProjectsHelper do
describe '#sanitize_repo_path' do describe '#sanitize_repo_path' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:storage_path) { Gitlab.config.repositories.storages.default.legacy_disk_path } let(:storage_path) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab.config.repositories.storages.default.legacy_disk_path
end
end
before do before do
allow(Settings.shared).to receive(:[]).with('path').and_return('/base/repo/export/path') allow(Settings.shared).to receive(:[]).with('path').and_return('/base/repo/export/path')
......
import axios from '~/lib/utils/axios_utils';
import MockAdapter from 'axios-mock-adapter';
import CreateMergeRequestDropdown from '~/create_merge_request_dropdown';
import { TEST_HOST } from 'spec/test_constants';
describe('CreateMergeRequestDropdown', () => {
let axiosMock;
let dropdown;
beforeEach(() => {
axiosMock = new MockAdapter(axios);
setFixtures(`
<div id="dummy-wrapper-element">
<div class="available"></div>
<div class="unavailable">
<div class="fa"></div>
<div class="text"></div>
</div>
<div class="js-ref"></div>
<div class="js-create-merge-request"></div>
<div class="js-create-target"></div>
<div class="js-dropdown-toggle"></div>
</div>
`);
const dummyElement = document.getElementById('dummy-wrapper-element');
dropdown = new CreateMergeRequestDropdown(dummyElement);
dropdown.refsPath = `${TEST_HOST}/dummy/refs?search=`;
});
afterEach(() => {
axiosMock.restore();
});
describe('getRef', () => {
it('escapes branch names correctly', done => {
const endpoint = `${dropdown.refsPath}contains%23hash`;
spyOn(axios, 'get').and.callThrough();
axiosMock.onGet(endpoint).replyOnce({});
dropdown
.getRef('contains#hash')
.then(() => {
expect(axios.get).toHaveBeenCalledWith(endpoint);
})
.then(done)
.catch(done.fail);
});
});
describe('updateCreatePaths', () => {
it('escapes branch names correctly', () => {
dropdown.createBranchPath = `${TEST_HOST}/branches?branch_name=some-branch&issue=42`;
dropdown.createMrPath = `${TEST_HOST}/create_merge_request?branch_name=some-branch&ref=master`;
dropdown.updateCreatePaths('branch', 'contains#hash');
expect(dropdown.createBranchPath).toBe(
`${TEST_HOST}/branches?branch_name=contains%23hash&issue=42`,
);
expect(dropdown.createMrPath).toBe(
`${TEST_HOST}/create_merge_request?branch_name=contains%23hash&ref=master`,
);
});
});
});
...@@ -66,7 +66,7 @@ describe('ShortcutsIssuable', function () { ...@@ -66,7 +66,7 @@ describe('ShortcutsIssuable', function () {
}); });
describe('with a multi-line selection', () => { describe('with a multi-line selection', () => {
it('quotes the selected lines as a group', () => { it('quotes the selected lines as a group', () => {
stubSelection('<p>Selected line one.</p>\n\n<p>Selected line two.</p>\n\n<p>Selected line three.</p>'); stubSelection('<p>Selected line one.</p>\n<p>Selected line two.</p>\n<p>Selected line three.</p>');
this.shortcut.replyWithSelectedText(true); this.shortcut.replyWithSelectedText(true);
expect($(this.selector).val()).toBe('> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n'); expect($(this.selector).val()).toBe('> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n');
}); });
......
...@@ -7,13 +7,13 @@ describe Banzai::Filter::MarkdownFilter do ...@@ -7,13 +7,13 @@ describe Banzai::Filter::MarkdownFilter do
it 'adds language to lang attribute when specified' do it 'adds language to lang attribute when specified' do
result = filter("```html\nsome code\n```") result = filter("```html\nsome code\n```")
expect(result).to start_with("\n<pre><code lang=\"html\">") expect(result).to start_with("<pre><code lang=\"html\">")
end end
it 'does not add language to lang attribute when not specified' do it 'does not add language to lang attribute when not specified' do
result = filter("```\nsome code\n```") result = filter("```\nsome code\n```")
expect(result).to start_with("\n<pre><code>") expect(result).to start_with("<pre><code>")
end end
end end
end end
...@@ -7,7 +7,7 @@ describe Gitlab::Git::Blame, seed_helper: true do ...@@ -7,7 +7,7 @@ describe Gitlab::Git::Blame, seed_helper: true do
Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md") Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md")
end end
shared_examples 'blaming a file' do describe 'blaming a file' do
context "each count" do context "each count" do
it do it do
data = [] data = []
...@@ -68,12 +68,4 @@ describe Gitlab::Git::Blame, seed_helper: true do ...@@ -68,12 +68,4 @@ describe Gitlab::Git::Blame, seed_helper: true do
end end
end end
end end
context 'when Gitaly blame feature is enabled' do
it_behaves_like 'blaming a file'
end
context 'when Gitaly blame feature is disabled', :skip_gitaly_mock do
it_behaves_like 'blaming a file'
end
end end
...@@ -77,17 +77,6 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -77,17 +77,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
describe '#root_ref' do describe '#root_ref' do
context 'with gitaly disabled' do
before do
allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false)
end
it 'calls #discover_default_branch' do
expect(repository).to receive(:discover_default_branch)
repository.root_ref
end
end
it 'returns UTF-8' do it 'returns UTF-8' do
expect(repository.root_ref).to be_utf8 expect(repository.root_ref).to be_utf8
end end
...@@ -153,46 +142,6 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -153,46 +142,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
describe "#discover_default_branch" do
let(:master) { 'master' }
let(:feature) { 'feature' }
let(:feature2) { 'feature2' }
around do |example|
# discover_default_branch will be moved to gitaly-ruby
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
example.run
end
end
it "returns 'master' when master exists" do
expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, master])
expect(repository.discover_default_branch).to eq('master')
end
it "returns non-master when master exists but default branch is set to something else" do
File.write(File.join(repository_path, 'HEAD'), 'ref: refs/heads/feature')
expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, master])
expect(repository.discover_default_branch).to eq('feature')
File.write(File.join(repository_path, 'HEAD'), 'ref: refs/heads/master')
end
it "returns a non-master branch when only one exists" do
expect(repository).to receive(:branch_names).at_least(:once).and_return([feature])
expect(repository.discover_default_branch).to eq('feature')
end
it "returns a non-master branch when more than one exists and master does not" do
expect(repository).to receive(:branch_names).at_least(:once).and_return([feature, feature2])
expect(repository.discover_default_branch).to eq('feature')
end
it "returns nil when no branch exists" do
expect(repository).to receive(:branch_names).at_least(:once).and_return([])
expect(repository.discover_default_branch).to be_nil
end
end
describe '#branch_names' do describe '#branch_names' do
subject { repository.branch_names } subject { repository.branch_names }
...@@ -476,7 +425,7 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -476,7 +425,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
describe '#has_local_branches?' do describe '#has_local_branches?' do
shared_examples 'check for local branches' do context 'check for local branches' do
it { expect(repository.has_local_branches?).to eq(true) } it { expect(repository.has_local_branches?).to eq(true) }
context 'mutable' do context 'mutable' do
...@@ -510,14 +459,6 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -510,14 +459,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
end end
context 'with gitaly' do
it_behaves_like 'check for local branches'
end
context 'without gitaly', :skip_gitaly_mock do
it_behaves_like 'check for local branches'
end
end end
describe "#delete_branch" do describe "#delete_branch" do
...@@ -1395,24 +1336,6 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -1395,24 +1336,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end end
end end
# With Gitaly enabled, Gitaly just doesn't return deleted branches.
context 'with deleted branch with Gitaly disabled' do
before do
allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false)
end
it 'returns no results' do
ref = double()
allow(ref).to receive(:name) { 'bad-branch' }
allow(ref).to receive(:target) { raise Rugged::ReferenceError }
branches = double()
allow(branches).to receive(:each) { [ref].each }
allow(repository_rugged).to receive(:branches) { branches }
expect(subject).to be_empty
end
end
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :branches it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :branches
end end
......
...@@ -52,7 +52,9 @@ describe Gitlab::GitAccessWiki do ...@@ -52,7 +52,9 @@ describe Gitlab::GitAccessWiki do
context 'when the wiki repository does not exist' do context 'when the wiki repository does not exist' do
it 'returns not found' do it 'returns not found' do
wiki_repo = project.wiki.repository wiki_repo = project.wiki.repository
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
FileUtils.rm_rf(wiki_repo.path) FileUtils.rm_rf(wiki_repo.path)
end
# Sanity check for rm_rf # Sanity check for rm_rf
expect(wiki_repo.exists?).to eq(false) expect(wiki_repo.exists?).to eq(false)
......
...@@ -6,7 +6,11 @@ require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_ ...@@ -6,7 +6,11 @@ require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_
describe MigrateProcessCommitWorkerJobs do describe MigrateProcessCommitWorkerJobs do
let(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs let(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:commit) { project.commit.raw.rugged_commit } let(:commit) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.commit.raw.rugged_commit
end
end
describe 'Project' do describe 'Project' do
describe 'find_including_path' do describe 'find_including_path' do
......
...@@ -49,10 +49,14 @@ describe TurnNestedGroupsIntoRegularGroupsForMysql do ...@@ -49,10 +49,14 @@ describe TurnNestedGroupsIntoRegularGroupsForMysql do
end end
it 'renames the repository of any projects' do it 'renames the repository of any projects' do
expect(updated_project.repository.path) repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
updated_project.repository.path
end
expect(repo_path)
.to end_with("#{parent_group.name}-#{child_group.name}/#{updated_project.path}.git") .to end_with("#{parent_group.name}-#{child_group.name}/#{updated_project.path}.git")
expect(File.directory?(updated_project.repository.path)).to eq(true) expect(File.directory?(repo_path)).to eq(true)
end end
it 'creates a redirect route for renamed projects' do it 'creates a redirect route for renamed projects' do
......
...@@ -156,7 +156,7 @@ describe CacheMarkdownField do ...@@ -156,7 +156,7 @@ describe CacheMarkdownField do
end end
it { expect(thing.foo_html).to eq(updated_html) } it { expect(thing.foo_html).to eq(updated_html) }
it { expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) } it { expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) }
end end
describe '#cached_html_up_to_date?' do describe '#cached_html_up_to_date?' do
...@@ -234,7 +234,7 @@ describe CacheMarkdownField do ...@@ -234,7 +234,7 @@ describe CacheMarkdownField do
it 'returns default version when version is nil' do it 'returns default version when version is nil' do
thing.cached_markdown_version = nil thing.cached_markdown_version = nil
is_expected.to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) is_expected.to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
end end
end end
...@@ -261,7 +261,7 @@ describe CacheMarkdownField do ...@@ -261,7 +261,7 @@ describe CacheMarkdownField do
thing.cached_markdown_version = nil thing.cached_markdown_version = nil
thing.refresh_markdown_cache thing.refresh_markdown_cache
expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
end end
end end
...@@ -346,7 +346,7 @@ describe CacheMarkdownField do ...@@ -346,7 +346,7 @@ describe CacheMarkdownField do
expect(thing.foo_html).to eq(updated_html) expect(thing.foo_html).to eq(updated_html)
expect(thing.baz_html).to eq(updated_html) expect(thing.baz_html).to eq(updated_html)
expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
end end
end end
...@@ -366,7 +366,7 @@ describe CacheMarkdownField do ...@@ -366,7 +366,7 @@ describe CacheMarkdownField do
expect(thing.foo_html).to eq(updated_html) expect(thing.foo_html).to eq(updated_html)
expect(thing.baz_html).to eq(updated_html) expect(thing.baz_html).to eq(updated_html)
expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION)
end end
end end
end end
......
...@@ -3306,7 +3306,7 @@ describe Project do ...@@ -3306,7 +3306,7 @@ describe Project do
project.rename_repo project.rename_repo
expect(project.repository.rugged.config['gitlab.fullpath']).to eq(project.full_path) expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
end end
end end
...@@ -3467,7 +3467,7 @@ describe Project do ...@@ -3467,7 +3467,7 @@ describe Project do
it 'updates project full path in .git/config' do it 'updates project full path in .git/config' do
project.rename_repo project.rename_repo
expect(project.repository.rugged.config['gitlab.fullpath']).to eq(project.full_path) expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
end end
end end
...@@ -3911,13 +3911,13 @@ describe Project do ...@@ -3911,13 +3911,13 @@ describe Project do
it 'writes full path in .git/config when key is missing' do it 'writes full path in .git/config when key is missing' do
project.write_repository_config project.write_repository_config
expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path expect(rugged_config['gitlab.fullpath']).to eq project.full_path
end end
it 'updates full path in .git/config when key is present' do it 'updates full path in .git/config when key is present' do
project.write_repository_config(gl_full_path: 'old/path') project.write_repository_config(gl_full_path: 'old/path')
expect { project.write_repository_config }.to change { project.repository.rugged.config['gitlab.fullpath'] }.from('old/path').to(project.full_path) expect { project.write_repository_config }.to change { rugged_config['gitlab.fullpath'] }.from('old/path').to(project.full_path)
end end
it 'does not raise an error with an empty repository' do it 'does not raise an error with an empty repository' do
...@@ -4203,4 +4203,10 @@ describe Project do ...@@ -4203,4 +4203,10 @@ describe Project do
let(:uploader_class) { AttachmentUploader } let(:uploader_class) { AttachmentUploader }
end end
end end
def rugged_config
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.rugged.config
end
end
end end
...@@ -196,7 +196,11 @@ describe ProjectWiki do ...@@ -196,7 +196,11 @@ describe ProjectWiki do
before do before do
subject.wiki # Make sure the wiki repo exists subject.wiki # Make sure the wiki repo exists
BareRepoOperations.new(subject.repository.path_to_repo).commit_file(image, 'image.png') repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
subject.repository.path_to_repo
end
BareRepoOperations.new(repo_path).commit_file(image, 'image.png')
end end
it 'returns the latest version of the file if it exists' do it 'returns the latest version of the file if it exists' do
......
...@@ -74,7 +74,9 @@ describe RemoteMirror do ...@@ -74,7 +74,9 @@ describe RemoteMirror do
mirror.update_attribute(:url, 'http://foo:baz@test.com') mirror.update_attribute(:url, 'http://foo:baz@test.com')
config = repo.raw_repository.rugged.config config = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repo.raw_repository.rugged.config
end
expect(config["remote.#{mirror.remote_name}.url"]).to eq('http://foo:baz@test.com') expect(config["remote.#{mirror.remote_name}.url"]).to eq('http://foo:baz@test.com')
end end
......
...@@ -522,7 +522,6 @@ describe API::Internal do ...@@ -522,7 +522,6 @@ describe API::Internal do
context 'the project path was changed' do context 'the project path was changed' do
let(:project) { create(:project, :repository, :legacy_storage) } let(:project) { create(:project, :repository, :legacy_storage) }
let!(:old_path_to_repo) { project.repository.path_to_repo }
let!(:repository) { project.repository } let!(:repository) { project.repository }
before do before do
......
...@@ -272,8 +272,11 @@ describe Projects::CreateService, '#execute' do ...@@ -272,8 +272,11 @@ describe Projects::CreateService, '#execute' do
it 'writes project full path to .git/config' do it 'writes project full path to .git/config' do
project = create_project(user, opts) project = create_project(user, opts)
rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.rugged
end
expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path expect(rugged.config['gitlab.fullpath']).to eq project.full_path
end end
def create_project(user, opts) def create_project(user, opts)
......
...@@ -9,7 +9,7 @@ RSpec.configure do |config| ...@@ -9,7 +9,7 @@ RSpec.configure do |config|
# Use 'and_wrap_original' to make sure the arguments are valid # Use 'and_wrap_original' to make sure the arguments are valid
allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original do |m, *args| allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original do |m, *args|
m.call(*args) m.call(*args)
!Gitlab::GitalyClient::EXPLICIT_OPT_IN_REQUIRED.include?(args.first) !Gitlab::GitalyClient.explicit_opt_in_required.include?(args.first)
end end
end end
end end
......
# monkey patch which fixes serialization matcher in Rails 5
# https://github.com/thoughtbot/shoulda-matchers/issues/913
# This can be removed when a new version of shoulda-matchers
# is released
module Shoulda
module Matchers
class RailsShim
def self.serialized_attributes_for(model)
if defined?(::ActiveRecord::Type::Serialized)
# Rails 5+
serialized_columns = model.columns.select do |column|
model.type_for_attribute(column.name).is_a?(
::ActiveRecord::Type::Serialized
)
end
serialized_columns.inject({}) do |hash, column| # rubocop:disable Style/EachWithObject
hash[column.name.to_s] = model.type_for_attribute(column.name).coder
hash
end
else
model.serialized_attributes
end
end
end
end
end
...@@ -11,7 +11,6 @@ describe GitGarbageCollectWorker do ...@@ -11,7 +11,6 @@ describe GitGarbageCollectWorker do
subject { described_class.new } subject { described_class.new }
describe "#perform" do describe "#perform" do
shared_examples 'flushing ref caches' do |gitaly|
context 'with active lease_uuid' do context 'with active lease_uuid' do
before do before do
allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid) allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
...@@ -19,16 +18,8 @@ describe GitGarbageCollectWorker do ...@@ -19,16 +18,8 @@ describe GitGarbageCollectWorker do
it "flushes ref caches when the task if 'gc'" do it "flushes ref caches when the task if 'gc'" do
expect(subject).to receive(:renew_lease).with(lease_key, lease_uuid).and_call_original expect(subject).to receive(:renew_lease).with(lease_key, lease_uuid).and_call_original
expect(subject).to receive(:command).with(:gc).and_return([:the, :command])
if gitaly
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect) expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect)
.and_return(nil) .and_return(nil)
else
expect(Gitlab::Popen).to receive(:popen)
.with([:the, :command], project.repository.path_to_repo).and_return(["", 0])
end
expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original
expect_any_instance_of(Repository).to receive(:branch_names).and_call_original expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
...@@ -44,7 +35,6 @@ describe GitGarbageCollectWorker do ...@@ -44,7 +35,6 @@ describe GitGarbageCollectWorker do
end end
it 'returns silently' do it 'returns silently' do
expect(subject).not_to receive(:command)
expect_any_instance_of(Repository).not_to receive(:after_create_branch).and_call_original expect_any_instance_of(Repository).not_to receive(:after_create_branch).and_call_original
expect_any_instance_of(Repository).not_to receive(:branch_names).and_call_original expect_any_instance_of(Repository).not_to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).not_to receive(:has_visible_content?).and_call_original expect_any_instance_of(Repository).not_to receive(:has_visible_content?).and_call_original
...@@ -64,16 +54,8 @@ describe GitGarbageCollectWorker do ...@@ -64,16 +54,8 @@ describe GitGarbageCollectWorker do
end end
it "flushes ref caches when the task if 'gc'" do it "flushes ref caches when the task if 'gc'" do
expect(subject).to receive(:command).with(:gc).and_return([:the, :command])
if gitaly
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect) expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect)
.and_return(nil) .and_return(nil)
else
expect(Gitlab::Popen).to receive(:popen)
.with([:the, :command], project.repository.path_to_repo).and_return(["", 0])
end
expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original
expect_any_instance_of(Repository).to receive(:branch_names).and_call_original expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
...@@ -98,15 +80,6 @@ describe GitGarbageCollectWorker do ...@@ -98,15 +80,6 @@ describe GitGarbageCollectWorker do
end end
end end
end end
end
context "with Gitaly turned on" do
it_should_behave_like 'flushing ref caches', true
end
context "with Gitaly turned off", :disable_gitaly do
it_should_behave_like 'flushing ref caches', false
end
context "repack_full" do context "repack_full" do
before do before do
......
...@@ -44,7 +44,9 @@ describe RepositoryRemoveRemoteWorker do ...@@ -44,7 +44,9 @@ describe RepositoryRemoveRemoteWorker do
end end
def create_remote_branch(remote_name, branch_name, target) def create_remote_branch(remote_name, branch_name, target)
rugged = project.repository.rugged rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.rugged
end
rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id) rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id)
end end
end end
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